QComboBox - only react on a mouse-release if we had a mousepress
In delegates we get into trouble with calling showPopup in setEditorData (edit by double click) - and that is not reasonable. The user has requested edit - and therefore it is natural to save a click for the user and show the popup at once. However that fails since we have the mouse down and as soon as we release the mouse we will call hidePopup. This patch ensures that the mouseReleaseEvent, that caused the problem is only considered if we have had a mousePressEvent. Change-Id: Ibe031fcb9ad2158f6969e41127bbb5f651b9cae6 Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
This commit is contained in:
parent
943ae90744
commit
7523bbb0c0
@ -407,7 +407,7 @@ void QComboBoxPrivateContainer::leaveEvent(QEvent *)
|
||||
}
|
||||
|
||||
QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent)
|
||||
: QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0)
|
||||
: QFrame(parent, Qt::Popup), combo(parent), view(0), top(0), bottom(0), maybeIgnoreMouseButtonRelease(false)
|
||||
{
|
||||
// we need the combobox and itemview
|
||||
Q_ASSERT(parent);
|
||||
@ -667,10 +667,15 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
maybeIgnoreMouseButtonRelease = false;
|
||||
break;
|
||||
case QEvent::MouseButtonRelease: {
|
||||
bool ignoreEvent = maybeIgnoreMouseButtonRelease && popupTimer.elapsed() < QApplication::doubleClickInterval();
|
||||
|
||||
QMouseEvent *m = static_cast<QMouseEvent *>(e);
|
||||
if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid()
|
||||
&& !blockMouseReleaseTimer.isActive()
|
||||
&& !blockMouseReleaseTimer.isActive() && !ignoreEvent
|
||||
&& (view->currentIndex().flags() & Qt::ItemIsEnabled)
|
||||
&& (view->currentIndex().flags() & Qt::ItemIsSelectable)) {
|
||||
combo->hidePopup();
|
||||
@ -2562,6 +2567,7 @@ void QComboBox::showPopup()
|
||||
container->setUpdatesEnabled(false);
|
||||
#endif
|
||||
|
||||
bool startTimer = !container->isVisible();
|
||||
container->raise();
|
||||
container->show();
|
||||
container->updateScrollers();
|
||||
@ -2581,6 +2587,10 @@ void QComboBox::showPopup()
|
||||
if (QApplication::keypadNavigationEnabled())
|
||||
view()->setEditFocus(true);
|
||||
#endif
|
||||
if (startTimer) {
|
||||
container->popupTimer.start();
|
||||
container->maybeIgnoreMouseButtonRelease = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2876,6 +2886,11 @@ void QComboBox::mousePressEvent(QMouseEvent *e)
|
||||
}
|
||||
#endif
|
||||
showPopup();
|
||||
// The code below ensures that regular mousepress and pick item still works
|
||||
// If it was not called the viewContainer would ignore event since it didn't have
|
||||
// a mousePressEvent first.
|
||||
if (d->viewContainer())
|
||||
d->viewContainer()->maybeIgnoreMouseButtonRelease = false;
|
||||
} else {
|
||||
#ifdef QT_KEYPAD_NAVIGATION
|
||||
if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && d->lineEdit) {
|
||||
|
@ -254,6 +254,10 @@ private:
|
||||
QAbstractItemView *view;
|
||||
QComboBoxPrivateScroller *top;
|
||||
QComboBoxPrivateScroller *bottom;
|
||||
bool maybeIgnoreMouseButtonRelease;
|
||||
QElapsedTimer popupTimer;
|
||||
|
||||
friend class QComboBox;
|
||||
};
|
||||
|
||||
class QComboMenuDelegate : public QAbstractItemDelegate
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QItemDelegate>
|
||||
#include <QDebug>
|
||||
#include <QComboBox>
|
||||
|
||||
class ExampleEditor : public QLineEdit
|
||||
{
|
||||
@ -56,13 +57,26 @@ public:
|
||||
class ExampleDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
ExampleDelegate():QItemDelegate() { m_editor = new ExampleEditor(0); }
|
||||
protected:
|
||||
QWidget* createEditor(QWidget *p, const QStyleOptionViewItem &o, const QModelIndex &) const
|
||||
ExampleDelegate() : QItemDelegate()
|
||||
{
|
||||
m_editor->setParent(p);
|
||||
m_editor->setGeometry(o.rect);
|
||||
return m_editor;
|
||||
m_editor = new ExampleEditor(0);
|
||||
m_combobox = new QComboBox(0);
|
||||
m_combobox->addItem(QString::fromUtf8("item1"));
|
||||
m_combobox->addItem(QString::fromUtf8("item2"));
|
||||
}
|
||||
protected:
|
||||
QWidget* createEditor(QWidget *p, const QStyleOptionViewItem &o, const QModelIndex &i) const
|
||||
{
|
||||
// doubleclick rownumber 3 (last row) to see the difference.
|
||||
if (i.row() == 3) {
|
||||
m_combobox->setParent(p);
|
||||
m_combobox->setGeometry(o.rect);
|
||||
return m_combobox;
|
||||
} else {
|
||||
m_editor->setParent(p);
|
||||
m_editor->setGeometry(o.rect);
|
||||
return m_editor;
|
||||
}
|
||||
}
|
||||
void destroyEditor(QWidget *editor, const QModelIndex &) const
|
||||
{
|
||||
@ -71,10 +85,25 @@ protected:
|
||||
}
|
||||
|
||||
// Avoid setting data - and therefore show that the editor keeps its state.
|
||||
void setEditorData(QWidget*, const QModelIndex &) const { }
|
||||
void setEditorData(QWidget* w, const QModelIndex &) const
|
||||
{
|
||||
QComboBox *combobox = qobject_cast<QComboBox*>(w);
|
||||
if (combobox) {
|
||||
qDebug() << "Try to show popup at once";
|
||||
// Now we could try to make a call to
|
||||
// QCoreApplication::processEvents();
|
||||
// But it does not matter. The fix:
|
||||
// https://codereview.qt-project.org/40608
|
||||
// is blocking QComboBox from reacting to this doubleclick edit event
|
||||
// and we need to do that since the mouseReleaseEvent has not yet happened,
|
||||
// and therefore cannot be processed.
|
||||
combobox->showPopup();
|
||||
}
|
||||
}
|
||||
|
||||
~ExampleDelegate() { delete m_editor; }
|
||||
mutable ExampleEditor *m_editor;
|
||||
mutable QComboBox *m_combobox;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
Loading…
x
Reference in New Issue
Block a user