From c88305b68d228a60fa302afb627b6887ece7a110 Mon Sep 17 00:00:00 2001 From: Olga Radko Date: Thu, 9 Aug 2018 16:50:03 +0300 Subject: [PATCH 01/12] QSortFilterProxyModel: add test for inserting via a QComboBox This new test double-checks the bugfix for QSortFilterProxyModel::insertRows in commit 70ba75519d. Previously, when using QComboBox on top of QSortFilterProxyModel and calling QComboBox::addItem with row==rowCount(), an empty item was inserted in one place, and then another item was modified (instead of the inserted empty one). This test checks that the above bugfix indeed fixes the behavior of QComboBox::addItem when used in this manner. Task-number: QTBUG-69158 Change-Id: Id01345e0525694a57250c656222d626e2267aa8e Reviewed-by: Luca Beldi Reviewed-by: David Faure --- .../tst_qsortfilterproxymodel.cpp | 53 +++++++++++++++++++ .../tst_qsortfilterproxymodel.h | 2 + 2 files changed, 55 insertions(+) diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp index 646f96c3a16..82cd26971b7 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -506,6 +507,58 @@ void tst_QSortFilterProxyModel::prependRow() QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there } +void tst_QSortFilterProxyModel::appendRowFromCombobox_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("newitem"); + QTest::addColumn("expected"); + + QTest::newRow("filter_out_second_last_item") + << "^[0-9]*$" + << (QStringList() << "a" << "1") + << "2" + << (QStringList() << "a" << "1" << "2"); + + QTest::newRow("filter_out_everything") + << "^c*$" + << (QStringList() << "a" << "b") + << "c" + << (QStringList() << "a" << "b" << "c"); + + QTest::newRow("no_filter") + << "" + << (QStringList() << "0" << "1") + << "2" + << (QStringList() << "0" << "1" << "2"); + + QTest::newRow("filter_out_last_item") + << "^[a-z]*$" + << (QStringList() << "a" << "1") + << "b" + << (QStringList() << "a" << "1" << "b"); +} + +void tst_QSortFilterProxyModel::appendRowFromCombobox() +{ + QFETCH(QString, pattern); + QFETCH(QStringList, initial); + QFETCH(QString, newitem); + QFETCH(QStringList, expected); + + QStringListModel model(initial); + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setFilterRegExp(pattern); + + QComboBox comboBox; + comboBox.setModel(&proxy); + comboBox.addItem(newitem); + + QCOMPARE(model.stringList(), expected); +} + void tst_QSortFilterProxyModel::removeRows_data() { QTest::addColumn("initial"); diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h index 4ea5e8fb6a6..82d4b7344e6 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h @@ -72,6 +72,8 @@ private slots: void insertRows_data(); void insertRows(); void prependRow(); + void appendRowFromCombobox_data(); + void appendRowFromCombobox(); void removeRows_data(); void removeRows(); void removeColumns_data(); From dc73a691bff1a2aabb2b035802f591b527eda12f Mon Sep 17 00:00:00 2001 From: Luca Beldi Date: Tue, 4 Sep 2018 17:15:03 +0100 Subject: [PATCH 02/12] Fix QSIM::itemData returning role 255 Before this fix, QStandardItemModel::itemData returns a map containing role 255 which is used internally to store the flags. This role is an undocumented implementation detail so it should not be returned to the user. [ChangeLog][QtGui][QStandardItemModel] itemData does not return role 255 Change-Id: Ibead3cba84cfe92b3c664bc8ce87508cbcbdc9bd Reviewed-by: David Faure --- src/gui/itemmodels/qstandarditemmodel.cpp | 13 +++++++++---- .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 6 +++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index a771bffa2f4..8ec88ebc609 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -306,8 +306,11 @@ const QMap QStandardItemPrivate::itemData() const { QMap result; QVector::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) - result.insert((*it).role, (*it).value); + for (it = values.cbegin(); it != values.cend(); ++it){ + // Qt::UserRole - 1 is used internally to store the flags + if (it->role != Qt::UserRole - 1) + result.insert(it->role, it->value); + } return result; } @@ -2939,8 +2942,10 @@ bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &paren QMap QStandardItemModel::itemData(const QModelIndex &index) const { Q_D(const QStandardItemModel); - QStandardItem *item = d->itemFromIndex(index); - return item ? item->d_func()->itemData() : QMap(); + const QStandardItem *const item = d->itemFromIndex(index); + if (!item || item == d->root.data()) + return QMap(); + return item->d_func()->itemData(); } /*! diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp index f6ed3e142d3..e2d7a41bd19 100644 --- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -750,7 +750,11 @@ void tst_QStandardItemModel::data() QCOMPARE(m_model->data(m_model->index(0, 0), Qt::DisplayRole).toString(), QLatin1String("initialitem")); QCOMPARE(m_model->data(m_model->index(0, 0), Qt::ToolTipRole).toString(), QLatin1String("tooltip")); - + const QMap itmData = m_model->itemData(m_model->index(0, 0)); + QCOMPARE(itmData.value(Qt::DisplayRole), QLatin1String("initialitem")); + QCOMPARE(itmData.value(Qt::ToolTipRole), QLatin1String("tooltip")); + QVERIFY(!itmData.contains(Qt::UserRole - 1)); + QVERIFY(m_model->itemData(QModelIndex()).isEmpty()); } void tst_QStandardItemModel::clearItemData() From 550d2a0a15c9403894448ab83863e71bbac2d349 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Aug 2018 14:24:58 +0200 Subject: [PATCH 03/12] uic: Fix pixmap functions for QIcon Task-number: QTBUG-8563 Change-Id: I69b16ac2327fee6dd6f26845bdda60ad4dde56fa Reviewed-by: Jarek Kobus --- src/tools/uic/cpp/cppwriteinitialization.cpp | 57 +++++++++++++- src/tools/uic/cpp/cppwriteinitialization.h | 2 + .../auto/tools/uic/baseline/pixmapfunction.ui | 47 ++++++++++++ .../tools/uic/baseline/pixmapfunction.ui.h | 74 +++++++++++++++++++ 4 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 tests/auto/tools/uic/baseline/pixmapfunction.ui create mode 100644 tests/auto/tools/uic/baseline/pixmapfunction.ui.h diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index e6d90540b3d..6a0e2f03389 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1645,6 +1645,53 @@ static void writeResourceIcon(QTextStream &output, } } +void WriteInitialization::writePixmapFunctionIcon(QTextStream &output, + const QString &iconName, + const QString &indent, + const DomResourceIcon *i) const +{ + if (i->hasElementNormalOff()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text()) + << ", QIcon::Normal, QIcon::Off);\n"; + } + if (i->hasElementNormalOn()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text()) + << ", QIcon::Normal, QIcon::On);\n"; + } + if (i->hasElementDisabledOff()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text()) + << ", QIcon::Disabled, QIcon::Off);\n"; + } + if (i->hasElementDisabledOn()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text()) + << ", QIcon::Disabled, QIcon::On);\n"; + } + if (i->hasElementActiveOff()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text()) + << ", QIcon::Active, QIcon::Off);\n"; + } + if (i->hasElementActiveOn()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text()) + << ", QIcon::Active, QIcon::On);\n"; + } + if (i->hasElementSelectedOff()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text()) + << ", QIcon::Selected, QIcon::Off);\n"; + } + if (i->hasElementSelectedOn()) { + output << indent << iconName << ".addPixmap(" + << pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text()) + << ", QIcon::Selected, QIcon::On);\n"; + } +} + QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) { // check cache @@ -1661,7 +1708,10 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) if (i->attributeTheme().isEmpty()) { // No theme: Write resource icon as is m_output << m_indent << "QIcon " << iconName << ";\n"; - writeResourceIcon(m_output, iconName, m_indent, i); + if (m_uic->pixmapFunction().isEmpty()) + writeResourceIcon(m_output, iconName, m_indent, i); + else + writePixmapFunctionIcon(m_output, iconName, m_indent, i); } else { // Theme: Generate code to check the theme and default to resource const QString themeIconName = fixString(i->attributeTheme(), QString()); @@ -1683,7 +1733,10 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) << ")) {\n" << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n" << m_indent << "} else {\n"; - writeResourceIcon(m_output, iconName, m_dindent, i); + if (m_uic->pixmapFunction().isEmpty()) + writeResourceIcon(m_output, iconName, m_dindent, i); + else + writePixmapFunctionIcon(m_output, iconName, m_dindent, i); m_output << m_indent << "}\n"; } else { // Theme, but no state pixmaps: Construct from theme directly. diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h index e6950a00ea3..cce83bd677d 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.h +++ b/src/tools/uic/cpp/cppwriteinitialization.h @@ -230,6 +230,8 @@ private: private: QString writeFontProperties(const DomFont *f); QString writeIconProperties(const DomResourceIcon *i); + void writePixmapFunctionIcon(QTextStream &output, const QString &iconName, + const QString &indent, const DomResourceIcon *i) const; QString writeSizePolicy(const DomSizePolicy *sp); QString writeBrushInitialization(const DomBrush *brush); void addButtonGroup(const DomWidget *node, const QString &varName); diff --git a/tests/auto/tools/uic/baseline/pixmapfunction.ui b/tests/auto/tools/uic/baseline/pixmapfunction.ui new file mode 100644 index 00000000000..8edafc72482 --- /dev/null +++ b/tests/auto/tools/uic/baseline/pixmapfunction.ui @@ -0,0 +1,47 @@ + + + Form + + + + 0 + 0 + 149 + 112 + + + + Form + + + + + + + + + labelPixmap + + + + + + + PushButton + + + + buttonIconNormalOff + buttonIconNormalOn + buttonIconDisabledOff + buttonIconDisabledOn + + + + + + + pixmapFunction + + + diff --git a/tests/auto/tools/uic/baseline/pixmapfunction.ui.h b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h new file mode 100644 index 00000000000..1644380c158 --- /dev/null +++ b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h @@ -0,0 +1,74 @@ +/******************************************************************************** +** Form generated from reading UI file 'pixmapfunction.ui' +** +** Created by: Qt User Interface Compiler version 5.12.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef PIXMAPFUNCTION_H +#define PIXMAPFUNCTION_H + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Form +{ +public: + QVBoxLayout *verticalLayout; + QLabel *label; + QPushButton *pushButton; + + void setupUi(QWidget *Form) + { + if (Form->objectName().isEmpty()) + Form->setObjectName(QString::fromUtf8("Form")); + Form->resize(149, 112); + verticalLayout = new QVBoxLayout(Form); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + label = new QLabel(Form); + label->setObjectName(QString::fromUtf8("label")); + label->setPixmap(QPixmap(pixmapFunction("labelPixmap"))); + + verticalLayout->addWidget(label); + + pushButton = new QPushButton(Form); + pushButton->setObjectName(QString::fromUtf8("pushButton")); + QIcon icon; + icon.addPixmap(QPixmap(pixmapFunction("buttonIconNormalOff")), QIcon::Normal, QIcon::Off); + icon.addPixmap(QPixmap(pixmapFunction("buttonIconNormalOn")), QIcon::Normal, QIcon::On); + icon.addPixmap(QPixmap(pixmapFunction("buttonIconDisabledOff")), QIcon::Disabled, QIcon::Off); + icon.addPixmap(QPixmap(pixmapFunction("buttonIconDisabledOn")), QIcon::Disabled, QIcon::On); + pushButton->setIcon(icon); + + verticalLayout->addWidget(pushButton); + + + retranslateUi(Form); + + QMetaObject::connectSlotsByName(Form); + } // setupUi + + void retranslateUi(QWidget *Form) + { + Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr)); + label->setText(QString()); + pushButton->setText(QApplication::translate("Form", "PushButton", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Form: public Ui_Form {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // PIXMAPFUNCTION_H From fbd21e1024d503b4b8b5e38b629a3b17392dbb05 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 31 Aug 2018 21:46:35 +0200 Subject: [PATCH 04/12] QHeaderView: Take padding/margin into account when eliding text When QHeaderView has an elide mode set, the available width passed to QFontMetrics::elidedText() was not adjusted when padding or margin was set. This lead to a too long text displayed in the header. Now QStyle::subElementRect(SE_HeaderLabel) is used to get the correct rect. Task-number: QTBUG-23203 Change-Id: I12fc646092470272bb91b3ffb7c7a51e239c7a35 Reviewed-by: David Faure --- src/widgets/itemviews/qheaderview.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 6857ccd8bb1..3396a91dc50 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2968,8 +2968,10 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical margin += style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this) + style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this); - if (d->textElideMode != Qt::ElideNone) - opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - margin); + if (d->textElideMode != Qt::ElideNone) { + const QRect textRect = style()->subElementRect(QStyle::SE_HeaderLabel, &opt, this); + opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode, textRect.width() - margin); + } QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::ForegroundRole); From 20be62da8c4dc547baaee2e949d1126500988a68 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 31 Aug 2018 23:56:06 +0200 Subject: [PATCH 05/12] QHeaderView: remove dead code The special handling when a font for a headerview is set became useless after a4e6117c53c3984585b3bbb74c00d6d863c98fcd since it is now included in branch four lines above. Change-Id: I73bec48913ebca5f278128a124b58d1b6172e334 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qstylesheetstyle.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 3e55bdaabcb..5ba45d51d39 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3874,13 +3874,6 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q ParentStyle::drawControl(ce, opt, p, w); return; } - if (subRule.hasFont) { - const QFont oldFont = p->font(); - p->setFont(subRule.font.resolve(p->font())); - baseStyle()->drawControl(ce, opt, p, w); - p->setFont(oldFont); - return; - } } break; case CE_HeaderSection: From 6c088af0f9677e19447fb42b8a1e0e633664dd2e Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 31 Aug 2018 23:44:15 +0200 Subject: [PATCH 06/12] QHeaderView: honor qss padding attribute QStyleSheetStyle did not check if a border (which includes the padding) is given and therefore the padding attribute given by css was ignored. Only when another attribute was additionally set, the padding was used. Task-number: QTBUG-59501 Change-Id: If3e691a23266ef6d0fb942a43053b29d65e40047 Reviewed-by: Richard Moe Gustavsen --- src/widgets/styles/qstylesheetstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 5ba45d51d39..c2ffcc82b19 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -3870,7 +3870,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q if(hasStyleRule(w, PseudoElement_HeaderViewSection)) { QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection); if (!subRule.hasNativeBorder() || !subRule.baseStyleCanDraw() - || subRule.hasBackground() || subRule.hasPalette() || subRule.hasFont) { + || subRule.hasBackground() || subRule.hasPalette() || subRule.hasFont || subRule.hasBorder()) { ParentStyle::drawControl(ce, opt, p, w); return; } From 367adc10de1d6c1f02546a543ddfd50471a1b03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Sep 2018 11:45:46 +0200 Subject: [PATCH 07/12] macOS: Rename QCocoaGLContext::setActiveWindow to setDrawable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0be5125b434418c005f45f05c54b22f0418b46e4 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaglcontext.h | 2 +- .../platforms/cocoa/qcocoaglcontext.mm | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 0e5934bc23f..9d827289f77 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -74,7 +74,7 @@ public: private: static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format); - bool setActiveWindow(QWindow *window); + bool setDrawable(QPlatformSurface *surface); void updateSurfaceFormat(); NSOpenGLContext *m_context = nil; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index c23636a1a0a..2c8885e4191 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -336,11 +336,8 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) return true; } - QWindow *window = static_cast(surface)->window(); - if (!setActiveWindow(window)) { - qCDebug(lcQpaOpenGLContext) << "Failed to activate window, skipping makeCurrent"; + if (!setDrawable(surface)) return false; - } [m_context makeCurrentContext]; @@ -365,8 +362,15 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) return true; } -bool QCocoaGLContext::setActiveWindow(QWindow *window) +/*! + Sets the drawable object of the NSOpenGLContext, which is the + frame buffer that is the target of OpenGL drawing operations. +*/ +bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) { + Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); + QWindow *window = static_cast(surface)->window(); + if (window == m_currentWindow.data()) return true; @@ -375,11 +379,11 @@ bool QCocoaGLContext::setActiveWindow(QWindow *window) NSView *view = cocoaWindow->view(); if ((m_context.view = view) != view) { - qCDebug(lcQpaOpenGLContext) << "Associating" << view << "with" << m_context << "failed"; + qCInfo(lcQpaOpenGLContext) << "Failed to set" << view << "as drawable for" << m_context; return false; } - qCDebug(lcQpaOpenGLContext) << m_context << "now associated with" << m_context.view; + qCInfo(lcQpaOpenGLContext) << "Set drawable for" << m_context << "to" << m_context.view; if (m_currentWindow && m_currentWindow.data()->handle()) static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); @@ -408,9 +412,9 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - QWindow *window = static_cast(surface)->window(); - if (!setActiveWindow(window)) { - qCWarning(lcQpaOpenGLContext) << "Failed to activate window, skipping swapBuffers"; + if (!setDrawable(surface)) { + qCWarning(lcQpaOpenGLContext) << "Can't flush" << m_context + << "without" << surface << "as drawable"; return; } @@ -435,7 +439,7 @@ void QCocoaGLContext::windowWasHidden() { // If the window is hidden, we need to unset the m_currentWindow // variable so that succeeding makeCurrent's will not abort prematurely - // because of the optimization in setActiveWindow. + // because of the optimization in setDrawable. // Doing a full doneCurrent here is not preferable, because the GL context // might be rendering in a different thread at this time. m_currentWindow.clear(); From 5ed48895b6974814fb7ac7ec42a6fc8ee935be44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Sep 2018 14:38:28 +0200 Subject: [PATCH 08/12] tst_qglthreads::swapInThread(): Acquire context before resizing widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the QGLWidget's context may be owned by and used by the swap thread when the resize happens on the main thread. Change-Id: Id415747572e6b988924618b1df0efdee5fcb1805 Reviewed-by: Morten Johan Sørvig --- tests/auto/opengl/qglthreads/tst_qglthreads.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp index 76186f55753..09bea20d263 100644 --- a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp +++ b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp @@ -131,6 +131,13 @@ public: setAutoBufferSwap(false); } + void resizeEvent(QResizeEvent *e) + { + m_thread->lock(); + QGLWidget::resizeEvent(e); + m_thread->unlock(); + } + void paintEvent(QPaintEvent *) { m_thread->lock(); From d115196010efb4ac55be998ffe7ed00db0cbffaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Sep 2018 17:21:24 +0200 Subject: [PATCH 09/12] macOS: Use single call site for timer processing in event dispatcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes it easier to add shared logic later on. The call to maybeCancelWaitForMoreEvents() has been left out as it was not called from all call sites. Change-Id: Ibcb10ab4d788de80850b0e5a4286b4d49091cddb Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qcocoaeventdispatcher.h | 1 + .../platforms/cocoa/qcocoaeventdispatcher.mm | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 6d62447f333..ebf33cf4e29 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -153,6 +153,7 @@ public: void maybeStopCFRunLoopTimer(); static void runLoopTimerCallback(CFRunLoopTimerRef, void *info); static void activateTimersSourceCallback(void *info); + bool processTimers(); // Set 'blockSendPostedEvents' to true if you _really_ need // to make sure that qt events are not posted while calling diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 2a414985648..b0f2b6d940f 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -120,11 +120,17 @@ void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void void QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void *info) { QCocoaEventDispatcherPrivate *d = static_cast(info); - (void) d->timerInfoList.activateTimers(); - d->maybeStartCFRunLoopTimer(); + d->processTimers(); d->maybeCancelWaitForMoreEvents(); } +bool QCocoaEventDispatcherPrivate::processTimers() +{ + int activated = timerInfoList.activateTimers(); + maybeStartCFRunLoopTimer(); + return activated > 0; +} + void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer() { if (timerInfoList.isEmpty()) { @@ -500,10 +506,9 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) } while (!d->interrupt && event); if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) { - // when called "manually", always send posted events and timers + // When called "manually", always process posted events and timers d->processPostedEvents(); - retVal = d->timerInfoList.activateTimers() > 0 || retVal; - d->maybeStartCFRunLoopTimer(); + retVal = d->processTimers() || retVal; } // be sure to return true if the posted event source fired From deab54f84f5771755c714e52b4587f152de09446 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 27 Aug 2018 14:11:14 +0200 Subject: [PATCH 10/12] Fix crash when setting Qt::WA_StaticContents on a transient child MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bail out of QWidgetBackingStore::updateLists() when a top level transient child is encountered, preventing from adding children of other top level windows to its list. Task-number: QTBUG-70085 Change-Id: Ibd748ab959af9bfe7fe0622494936b0c109ab25a Reviewed-by: Tor Arne Vestbø --- src/widgets/kernel/qwidgetbackingstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index cbf949be923..53769ef9ed0 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -760,7 +760,7 @@ void QWidgetBackingStore::updateLists(QWidget *cur) QList children = cur->children(); for (int i = 0; i < children.size(); ++i) { QWidget *child = qobject_cast(children.at(i)); - if (!child) + if (!child || child->isWindow()) continue; updateLists(child); From 2105f801696759a365c4f928712de02e0e38e591 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 2 Sep 2018 15:53:12 +0200 Subject: [PATCH 11/12] cocoa: Fix build with MoltenVK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If92afa2d30d55e1dd2968f582350ba2cf16fe27b Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoavulkaninstance.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h index 018488a0a18..5fe6a612afe 100644 --- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h +++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h @@ -40,13 +40,17 @@ #ifndef QCOCOAVULKANINSTANCE_H #define QCOCOAVULKANINSTANCE_H +// Include mvk_vulkan.h first. The order is important since +// mvk_vulkan.h just defines VK_USE_PLATFORM_MACOS_MVK (or the IOS +// variant) and includes vulkan.h. If something else included vulkan.h +// before this then we wouldn't get the MVK specifics... +#include + #include #include #include -#include - QT_BEGIN_NAMESPACE class QCocoaVulkanInstance : public QBasicPlatformVulkanInstance From 35ebdeb83eb4057f5e50042747b13d0772051459 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 16 Oct 2014 13:38:11 +0200 Subject: [PATCH 12/12] QTreeView: Fix expanding of spanning items When using HeaderView::ResizeToContents and QTreeWidgetItem::setFirstColumnSpanned(), it happens that the position of the branch icon is no longer in the first column and thus trying to expand the item results in a selection change. Check for spanning when determining the position. Task-number: QTBUG-41793 Change-Id: I14353127436fb0ebaafb0d50a31b920b8da67333 Reviewed-by: Christian Ehrlicher Reviewed-by: David Faure --- src/widgets/itemviews/qtreeview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index b339fe0f3b1..b534de5c6af 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -3724,9 +3724,14 @@ void QTreeViewPrivate::updateScrollBars() int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const { + Q_Q(const QTreeView); executePostedLayout(); - int x = pos.x(); - int column = header->logicalIndexAt(x); + bool spanned = false; + if (!spanningIndexes.isEmpty()) { + const QModelIndex index = q->indexAt(pos); + spanned = q->isFirstColumnSpanned(index.row(), index.parent()); + } + const int column = spanned ? 0 : header->logicalIndexAt(pos.x()); if (!isTreePosition(column)) return -1; // no logical index at x