QAbstractItemDelegate: add handleEditorEvent()

QItemDelegate and QStyledItemDelegate had this exact implementation
already, the actual code being in QAbstractItemDelegatePrivate.

If someone writes their own delegate by deriving from
QAbstractItemDelegate, they had no way to call the default
event filter code (to get Enter to commit, Esc to abort editing etc.).

[ChangeLog][QtWidgets][QAbstractItemDelegate] The base class now
provides a handleEditorEvent() method, which provides the same event
handling as in QItemDelegate and QStyledItemDelegate, including Tab,
Enter, Esc keys and focus out handling.

Change-Id: I1b560d8a1b348e3b3bb5cfc3162f9b265b706684
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
David Faure 2025-02-24 16:44:28 +01:00
parent 9245d0a0f0
commit d2efb6faba
5 changed files with 54 additions and 59 deletions

View File

@ -385,6 +385,49 @@ QAbstractItemDelegatePrivate::QAbstractItemDelegatePrivate()
{ {
} }
/*!
\fn bool QAbstractItemDelegate::handleEditorEvent(QObject *editor, QEvent *event)
Implements standard handling of events on behalf of the currently active \a editor.
Call this function from an override of eventFilter() in a QAbstractItemModel subclass,
and return its result. To avoid duplicate event processing, do not call
the parent class implementation of eventFilter() after calling this function.
Returns \c true if the given \a editor is a valid QWidget and the
given \a event is handled; otherwise returns \c false. The following
key press events are handled by default:
\list
\li \uicontrol Tab
\li \uicontrol Backtab
\li \uicontrol Enter
\li \uicontrol Return
\li \uicontrol Esc
\endlist
If the \a editor's type is QTextEdit or QPlainTextEdit then \uicontrol Tab,
\uicontrol Backtab, \uicontrol Enter and \uicontrol Return keys are \e not
handled.
In the case of \uicontrol Tab, \uicontrol Backtab, \uicontrol Enter and \uicontrol Return
key press events, the \a editor's data is committed to the model
and the editor is closed. If the \a event is a \uicontrol Tab key press
the view will open an editor on the next item in the
view. Likewise, if the \a event is a \uicontrol Backtab key press the
view will open an editor on the \e previous item in the view.
If the event is a \uicontrol Esc key press event, the \a editor is
closed \e without committing its data.
\sa commitData(), closeEditor()
\since 6.10
*/
bool QAbstractItemDelegate::handleEditorEvent(QObject *object, QEvent *event)
{
Q_D(QAbstractItemDelegate);
return d->handleEditorEvent(object, event);
}
static bool editorHandlesKeyEvent(QWidget *editor, const QKeyEvent *event) static bool editorHandlesKeyEvent(QWidget *editor, const QKeyEvent *event)
{ {
#if QT_CONFIG(textedit) #if QT_CONFIG(textedit)
@ -408,7 +451,7 @@ static bool editorHandlesKeyEvent(QWidget *editor, const QKeyEvent *event)
return false; return false;
} }
bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *event) bool QAbstractItemDelegatePrivate::handleEditorEvent(QObject *object, QEvent *event)
{ {
Q_Q(QAbstractItemDelegate); Q_Q(QAbstractItemDelegate);

View File

@ -66,6 +66,8 @@ public:
QAbstractItemModel *model, QAbstractItemModel *model,
const QStyleOptionViewItem &option, const QStyleOptionViewItem &option,
const QModelIndex &index); const QModelIndex &index);
// for widget editors
bool handleEditorEvent(QObject *object, QEvent *event);
virtual bool helpEvent(QHelpEvent *event, virtual bool helpEvent(QHelpEvent *event,
QAbstractItemView *view, QAbstractItemView *view,
@ -81,6 +83,7 @@ Q_SIGNALS:
protected: protected:
QAbstractItemDelegate(QObjectPrivate &, QObject *parent = nullptr); QAbstractItemDelegate(QObjectPrivate &, QObject *parent = nullptr);
private: private:
Q_DECLARE_PRIVATE(QAbstractItemDelegate) Q_DECLARE_PRIVATE(QAbstractItemDelegate)
Q_DISABLE_COPY(QAbstractItemDelegate) Q_DISABLE_COPY(QAbstractItemDelegate)

View File

@ -32,7 +32,7 @@ class Q_AUTOTEST_EXPORT QAbstractItemDelegatePrivate : public QObjectPrivate
public: public:
explicit QAbstractItemDelegatePrivate(); explicit QAbstractItemDelegatePrivate();
bool editorEventFilter(QObject *object, QEvent *event); bool handleEditorEvent(QObject *object, QEvent *event);
bool tryFixup(QWidget *editor); bool tryFixup(QWidget *editor);
QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision = 6) const; QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision = 6) const;
void _q_commitDataAndCloseEditor(QWidget *editor); void _q_commitDataAndCloseEditor(QWidget *editor);

View File

@ -1076,37 +1076,14 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
} }
/*! /*!
\fn bool QItemDelegate::eventFilter(QObject *editor, QEvent *event) \reimp
Returns \c true if the given \a editor is a valid QWidget and the See details in QAbstractItemDelegate::handleEditorEvent().
given \a event is handled; otherwise returns \c false. The following
key press events are handled by default:
\list
\li \uicontrol Tab
\li \uicontrol Backtab
\li \uicontrol Enter
\li \uicontrol Return
\li \uicontrol Esc
\endlist
In the case of \uicontrol Tab, \uicontrol Backtab, \uicontrol Enter and \uicontrol Return
key press events, the \a editor's data is committed to the model
and the editor is closed. If the \a event is a \uicontrol Tab key press
the view will open an editor on the next item in the
view. Likewise, if the \a event is a \uicontrol Backtab key press the
view will open an editor on the \e previous item in the view.
If the event is a \uicontrol Esc key press event, the \a editor is
closed \e without committing its data.
\sa commitData(), closeEditor()
*/ */
bool QItemDelegate::eventFilter(QObject *object, QEvent *event) bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
{ {
Q_D(QItemDelegate); return handleEditorEvent(object, event);
return d->editorEventFilter(object, event);
} }
/*! /*!

View File

@ -511,42 +511,14 @@ void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
d->factory = factory; d->factory = factory;
} }
/*! /*!
\fn bool QStyledItemDelegate::eventFilter(QObject *editor, QEvent *event) \reimp
Returns \c true if the given \a editor is a valid QWidget and the See details in QAbstractItemDelegate::handleEditorEvent().
given \a event is handled; otherwise returns \c false. The following
key press events are handled by default:
\list
\li \uicontrol Tab
\li \uicontrol Backtab
\li \uicontrol Enter
\li \uicontrol Return
\li \uicontrol Esc
\endlist
If the \a editor's type is QTextEdit or QPlainTextEdit then \uicontrol Tab,
\uicontrol Backtab, \uicontrol Enter and \uicontrol Return keys are \e not
handled.
In the case of \uicontrol Tab, \uicontrol Backtab, \uicontrol Enter and \uicontrol Return
key press events, the \a editor's data is committed to the model
and the editor is closed. If the \a event is a \uicontrol Tab key press
the view will open an editor on the next item in the
view. Likewise, if the \a event is a \uicontrol Backtab key press the
view will open an editor on the \e previous item in the view.
If the event is a \uicontrol Esc key press event, the \a editor is
closed \e without committing its data.
\sa commitData(), closeEditor()
*/ */
bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event) bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
{ {
Q_D(QStyledItemDelegate); return handleEditorEvent(object, event);
return d->editorEventFilter(object, event);
} }
/*! /*!