From d2efb6faba994d53068568eafaee042f49425a66 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 24 Feb 2025 16:44:28 +0100 Subject: [PATCH] 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 --- .../itemviews/qabstractitemdelegate.cpp | 45 ++++++++++++++++++- src/widgets/itemviews/qabstractitemdelegate.h | 3 ++ .../itemviews/qabstractitemdelegate_p.h | 2 +- src/widgets/itemviews/qitemdelegate.cpp | 29 ++---------- src/widgets/itemviews/qstyleditemdelegate.cpp | 34 ++------------ 5 files changed, 54 insertions(+), 59 deletions(-) diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp index 975a912f937..ae2fa7629f5 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.cpp +++ b/src/widgets/itemviews/qabstractitemdelegate.cpp @@ -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) { #if QT_CONFIG(textedit) @@ -408,7 +451,7 @@ static bool editorHandlesKeyEvent(QWidget *editor, const QKeyEvent *event) return false; } -bool QAbstractItemDelegatePrivate::editorEventFilter(QObject *object, QEvent *event) +bool QAbstractItemDelegatePrivate::handleEditorEvent(QObject *object, QEvent *event) { Q_Q(QAbstractItemDelegate); diff --git a/src/widgets/itemviews/qabstractitemdelegate.h b/src/widgets/itemviews/qabstractitemdelegate.h index b28a1c4f807..3705024c46f 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.h +++ b/src/widgets/itemviews/qabstractitemdelegate.h @@ -66,6 +66,8 @@ public: QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); + // for widget editors + bool handleEditorEvent(QObject *object, QEvent *event); virtual bool helpEvent(QHelpEvent *event, QAbstractItemView *view, @@ -81,6 +83,7 @@ Q_SIGNALS: protected: QAbstractItemDelegate(QObjectPrivate &, QObject *parent = nullptr); + private: Q_DECLARE_PRIVATE(QAbstractItemDelegate) Q_DISABLE_COPY(QAbstractItemDelegate) diff --git a/src/widgets/itemviews/qabstractitemdelegate_p.h b/src/widgets/itemviews/qabstractitemdelegate_p.h index e720f4d1057..82f0fe9d5f6 100644 --- a/src/widgets/itemviews/qabstractitemdelegate_p.h +++ b/src/widgets/itemviews/qabstractitemdelegate_p.h @@ -32,7 +32,7 @@ class Q_AUTOTEST_EXPORT QAbstractItemDelegatePrivate : public QObjectPrivate public: explicit QAbstractItemDelegatePrivate(); - bool editorEventFilter(QObject *object, QEvent *event); + bool handleEditorEvent(QObject *object, QEvent *event); bool tryFixup(QWidget *editor); QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision = 6) const; void _q_commitDataAndCloseEditor(QWidget *editor); diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp index be17dcc8c74..ae530497c70 100644 --- a/src/widgets/itemviews/qitemdelegate.cpp +++ b/src/widgets/itemviews/qitemdelegate.cpp @@ -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 - 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() + See details in QAbstractItemDelegate::handleEditorEvent(). */ bool QItemDelegate::eventFilter(QObject *object, QEvent *event) { - Q_D(QItemDelegate); - return d->editorEventFilter(object, event); + return handleEditorEvent(object, event); } /*! diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp index 19a367ca35b..c91b73c98a3 100644 --- a/src/widgets/itemviews/qstyleditemdelegate.cpp +++ b/src/widgets/itemviews/qstyleditemdelegate.cpp @@ -511,42 +511,14 @@ void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *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 - 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() + See details in QAbstractItemDelegate::handleEditorEvent(). */ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event) { - Q_D(QStyledItemDelegate); - return d->editorEventFilter(object, event); + return handleEditorEvent(object, event); } /*!