[PyQt] QDateEdit, QStandardItemModel and empty date fields

Maurizio Berti maurizio.berti at gmail.com
Tue Mar 5 18:37:16 GMT 2019


Il giorno mar 5 mar 2019 alle ore 16:31 Sibylle Koczian <
nulla.epistola at web.de> ha scritto:
> Am 05.03.2019 um 09:43 schrieb J Barchan:
> > I had to deal with this.  I did not take @Maurizio's approach.  I do not
> > know what his solution does about QDateEdit.setData/data() for an empty
> > date, and other things.  Until now I didn't know you could get at its
> > QLineEdit.  For my part I chose to have a QLineEdit plus an associated
> > ... button to its right which leads to a modal dialog.  I paste extracts
> > below, feel free to cannibalise it if you want my approach. If @Maurizio
> > wishes to criticize mine, that's fine, I will read and consider!

Well, Jonathan, your implementation seems fine, and, as long as it works,
who am I to judge? ;-)
The only issue in this case might be that you wouldn't be able to take
advantage of the "automatic" systems used to fill/read the editor of a
delegate, since the lineEdit is not publicly exposed, thus its methods
won't be too.
By using parenting, you'll be able to keep all original methods of the
QLineEdit and still have that extra button for "advanced" editing. This is
useful even in non-delegate scenarios, as it will make coding easier by
directly using the QLineEdit subclass.
Here's what I'd do (this is just a simple QLineEdit, obviously without the
date implementation):

class LineEditWithDotButton(QtWidgets.QLineEdit):
    advancedEditRequested = QtCore.Signal(str)

    def __init__(self, *args, **kwargs):
        QtWidgets.QLineEdit.__init__(self, *args, **kwargs)
        self.editBtn = QtWidgets.QToolButton(self)
        self.editBtn.setText('...')
        self.editBtn.setCursor(QtCore.Qt.ArrowCursor)
        self.editBtn.setFocusPolicy(QtCore.Qt.NoFocus)
        self.margin = 4
        l, t, r, b = self.getContentsMargins()
        self.setContentsMargins(l, t, r + self.editBtn.sizeHint().width() +
self.margin, b)
        self.editBtn.clicked.connect(lambda:
self.advancedEditRequested.emit(self.text())

    def showEvent(self, event):
        self.moveEditButton()

    def resizeEvent(self, event):
        self.moveEditButton()

    def moveEditButton(self):
        self.editBtn.setFixedHeight(self.height())
        self.editBtn.move(self.width() - self.getContentsMargins()[2] +
self.margin, 0)

I've used a QToolButton as standard QPushButtons with text have the issue
of fixed minimum size which could obviously be worked around, but since a
QToolButton is fine enough for this case, there's no need to add more
headaches. ;-)
The cursor is overridden, since the button is child of the line edit it
would use the IBeamCursor and that's not very good for UX. There will be
some space where the IBeamCursor is still active (the margin between the
edit and the button), if you're not happy with it you can
setMouseTracking(True) and use setCursor() in the mouseMoveEvent()
implementation. I also used existing content margins, as the current style
or (inherited) stylesheet might set them.

> I think in Maurizios approach much depends on the delegate that's used.

Yes, it is necessary to apply some "magic" to the delegate by letting it
"talk" with the editor.
The basic idea is that if the setEditorData() argument contains an invalid
date, it sets an internal bool property, which can be reset whenever the
user types/select a valid date. That property can later be checked back in
the setModelData, to avoid invalid submissions to the model.

Well, good luck ;-)

Maurizio

--
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190305/581a72d6/attachment-0001.html>


More information about the PyQt mailing list