diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/configure.json | 2 | ||||
-rw-r--r-- | src/widgets/doc/qtwidgets.qdocconf | 2 | ||||
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 18 | ||||
-rw-r--r-- | src/widgets/kernel/qgesturemanager.cpp | 37 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 127 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 8 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 6 | ||||
-rw-r--r-- | src/widgets/util/qcompleter_p.h | 3 | ||||
-rw-r--r-- | src/widgets/widgets/qabstractspinbox.cpp | 13 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox.cpp | 52 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox_p.h | 1 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu_mac.mm | 5 | ||||
-rw-r--r-- | src/widgets/widgets/qmenubar.cpp | 3 | ||||
-rw-r--r-- | src/widgets/widgets/qtabwidget.cpp | 83 | ||||
-rw-r--r-- | src/widgets/widgets/qwidgetlinecontrol.cpp | 17 |
16 files changed, 236 insertions, 147 deletions
diff --git a/src/widgets/configure.json b/src/widgets/configure.json index 4c596c09a5..b3a5227d26 100644 --- a/src/widgets/configure.json +++ b/src/widgets/configure.json @@ -129,7 +129,7 @@ "label": "QDateTimeEdit", "purpose": "Supports editing dates and times.", "section": "Widgets", - "condition": "features.calendarwidget && features.datestring && features.textdate", + "condition": "features.calendarwidget && features.datestring && features.textdate && features.datetimeparser", "output": [ "publicFeature", "feature" ] }, "stackedwidget": { diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index d0cf9671b1..a49eb439af 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -47,3 +47,5 @@ imagedirs += images \ navigation.landingpage = "Qt Widgets" navigation.cppclassespage = "Qt Widgets C++ Classes" +manifestmeta.highlighted.names = "QtWidgets/Calendar Widget Example" \ + "QtWidgets/Simple Tree Model Example" diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index fe27be8522..15e6b0eb99 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -2230,7 +2230,7 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event) QAbstractScrollArea::focusInEvent(event); const QItemSelectionModel* model = selectionModel(); - const bool currentIndexValid = currentIndex().isValid(); + bool currentIndexValid = currentIndex().isValid(); if (model && !d->currentIndexSet @@ -2238,19 +2238,16 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event) bool autoScroll = d->autoScroll; d->autoScroll = false; QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index - if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason) + if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason) { selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); + currentIndexValid = true; + } d->autoScroll = autoScroll; } - if (model && currentIndexValid) { - if (currentIndex().flags() != Qt::ItemIsEditable) - setAttribute(Qt::WA_InputMethodEnabled, false); - else - setAttribute(Qt::WA_InputMethodEnabled); - } - - if (!currentIndexValid) + if (model && currentIndexValid) + setAttribute(Qt::WA_InputMethodEnabled, (currentIndex().flags() & Qt::ItemIsEditable)); + else if (!currentIndexValid) setAttribute(Qt::WA_InputMethodEnabled, false); d->viewport->update(); @@ -3665,6 +3662,7 @@ void QAbstractItemView::currentChanged(const QModelIndex ¤t, const QModelI d->shouldScrollToCurrentOnShow = d->autoScroll; } } + setAttribute(Qt::WA_InputMethodEnabled, (current.isValid() && (current.flags() & Qt::ItemIsEditable))); } #ifndef QT_NO_DRAGANDDROP diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index fca36c7472..5bf66d68e3 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -244,6 +244,36 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni return state; } +static bool logIgnoredEvent(QEvent::Type t) +{ + bool result = false; + switch (t) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchCancel: + case QEvent::TouchEnd: + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + case QEvent::TabletMove: + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::GraphicsSceneMouseDoubleClick: + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMouseMove: + result = true; + break; + default: + break; + + } + return result; +} + bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts, QEvent *event) @@ -289,10 +319,13 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, qCDebug(lcGestureManager) << "QGestureManager:Recognizer: not gesture: " << state << event; notGestures << state; } else if (recognizerState == QGestureRecognizer::Ignore) { - qCDebug(lcGestureManager) << "QGestureManager:Recognizer: ignored the event: " << state << event; + if (logIgnoredEvent(event->type())) + qCDebug(lcGestureManager) << "QGestureManager:Recognizer: ignored the event: " << state << event; } else { - qCDebug(lcGestureManager) << "QGestureManager:Recognizer: hm, lets assume the recognizer" + if (logIgnoredEvent(event->type())) { + qCDebug(lcGestureManager) << "QGestureManager:Recognizer: hm, lets assume the recognizer" << "ignored the event: " << state << event; + } } if (resultHint & QGestureRecognizer::ConsumeEventHint) { qCDebug(lcGestureManager) << "QGestureManager: we were asked to consume the event: " diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0aa5f57e98..6a633fb575 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1876,39 +1876,15 @@ static void deleteBackingStore(QWidgetPrivate *d) { QTLWExtra *topData = d->topData(); - // The context must be current when destroying the backing store as it may attempt to - // release resources like textures and shader programs. The window may not be suitable - // anymore as there will often not be a platform window underneath at this stage. Fall - // back to a QOffscreenSurface in this case. - QScopedPointer<QOffscreenSurface> tempSurface; -#ifndef QT_NO_OPENGL - if (d->textureChildSeen && topData->shareContext) { - if (topData->window->handle()) { - topData->shareContext->makeCurrent(topData->window); - } else { - tempSurface.reset(new QOffscreenSurface); - tempSurface->setFormat(topData->shareContext->format()); - tempSurface->create(); - topData->shareContext->makeCurrent(tempSurface.data()); - } - } -#endif - delete topData->backingStore; topData->backingStore = 0; - -#ifndef QT_NO_OPENGL - if (d->textureChildSeen && topData->shareContext) - topData->shareContext->doneCurrent(); -#endif } void QWidgetPrivate::deleteTLSysExtra() { if (extra && extra->topextra) { //the qplatformbackingstore may hold a reference to the window, so the backingstore - //needs to be deleted first. If the backingstore holds GL resources, we need to - // make the context current here. This is taken care of by deleteBackingStore(). + //needs to be deleted first. extra->topextra->backingStoreTracker.destroy(); deleteBackingStore(this); @@ -5912,7 +5888,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset -= effectRect.topLeft(); - const qreal dpr = context->painter->device()->devicePixelRatio(); + const qreal dpr = context->painter->device()->devicePixelRatioF(); QPixmap pixmap(effectRect.size() * dpr); pixmap.setDevicePixelRatio(dpr); @@ -6945,6 +6921,9 @@ bool QWidget::isActiveWindow() const /*! Puts the \a second widget after the \a first widget in the focus order. + It effectively removes the \a second widget from its focus chain and + inserts it after the \a first widget. + Note that since the tab order of the \a second widget is changed, you should order a chain like this: @@ -6957,11 +6936,19 @@ bool QWidget::isActiveWindow() const If \a first or \a second has a focus proxy, setTabOrder() correctly substitutes the proxy. + \note Since Qt 5.10: A widget that has a child as focus proxy is understood as + a compound widget. When setting a tab order between one or two compound widgets, the + local tab order inside each will be preserved. This means that if both widgets are + compound widgets, the resulting tab order will be from the last child inside + \a first, to the first child inside \a second. + \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets} */ void QWidget::setTabOrder(QWidget* first, QWidget *second) { - if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus) + if (!first || !second || first == second + || first->focusPolicy() == Qt::NoFocus + || second->focusPolicy() == Qt::NoFocus) return; if (Q_UNLIKELY(first->window() != second->window())) { @@ -6969,54 +6956,56 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) return; } - QWidget *fp = first->focusProxy(); - if (fp) { - // If first is redirected, set first to the last child of first - // that can take keyboard focus so that second is inserted after - // that last child, and the focus order within first is (more - // likely to be) preserved. - QList<QWidget *> l = first->findChildren<QWidget *>(); - for (int i = l.size()-1; i >= 0; --i) { - QWidget * next = l.at(i); - if (next->window() == fp->window()) { - fp = next; - if (fp->focusPolicy() != Qt::NoFocus) - break; - } - } - first = fp; - } + auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild) + { + // Since we need to repeat the same logic for both 'first' and 'second', we add a function that + // determines the last focus child for a widget, taking proxies and compound widgets into account. + // If the target is not a compound widget (it doesn't have a focus proxy that points to a child), + // 'lastFocusChild' will be set to the target itself. + lastFocusChild = target; + + QWidget *focusProxy = target->d_func()->deepestFocusProxy(); + if (!focusProxy || !target->isAncestorOf(focusProxy)) + return; - if (fp == second) - return; + lastFocusChild = focusProxy; - if (QWidget *sp = second->focusProxy()) - second = sp; + for (QWidget *focusNext = lastFocusChild->d_func()->focus_next; + focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window(); + focusNext = focusNext->d_func()->focus_next) { + if (focusNext->focusPolicy() != Qt::NoFocus) + lastFocusChild = focusNext; + } + }; -// QWidget *fp = first->d_func()->focus_prev; - QWidget *fn = first->d_func()->focus_next; + QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond; + determineLastFocusChild(first, lastFocusChildOfFirst); + determineLastFocusChild(second, lastFocusChildOfSecond); - if (fn == second || first == second) + // If the tab order is already correct, exit early + if (lastFocusChildOfFirst->d_func()->focus_next == second) return; - QWidget *sp = second->d_func()->focus_prev; - QWidget *sn = second->d_func()->focus_next; - - fn->d_func()->focus_prev = second; - first->d_func()->focus_next = second; - - second->d_func()->focus_next = fn; - second->d_func()->focus_prev = first; - - sp->d_func()->focus_next = sn; - sn->d_func()->focus_prev = sp; - - - Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first); - Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first); - - Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second); - Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second); + // Note that we need to handle two different sections in the tab chain; The section + // that 'first' belongs to (firstSection), where we are about to insert 'second', and + // the section that 'second' used be a part of (secondSection). When we pull 'second' + // out of the second section and insert it into the first, we also need to ensure + // that we leave the second section in a connected state. + QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next; + QWidget *secondChainNewFirst = second->d_func()->focus_prev; + QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next; + + // Insert 'second' after 'first' + lastFocusChildOfFirst->d_func()->focus_next = second; + second->d_func()->focus_prev = lastFocusChildOfFirst; + + // The widget that used to be 'second' in the first section, should now become 'third' + lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond; + firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond; + + // Repair the second section after we pulled 'second' out of it + secondChainNewFirst->d_func()->focus_next = secondChainNewSecond; + secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst; } /*!\internal diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index b851a5c0af..3b093283cd 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -143,10 +143,8 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBack // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends // to rely on translucency, in order to decide if it should clear to transparent or opaque. const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); - // Use the tlw's context, not widget's. The difference is important with native child - // widgets where tlw != widget. - backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, widgetTextures, - tlw->d_func()->shareContext(), translucentBackground); + backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, + widgetTextures, translucentBackground); widget->window()->d_func()->sendComposeStatus(widget->window(), true); } else #endif diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index e5027e35df..80ed39bf76 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -96,6 +96,7 @@ public: } QRectF closestAcceptableGeometry(const QRectF &rect) const override; + QOpenGLContext *shareContext() const override; }; QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const @@ -127,6 +128,13 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const return result; } +QOpenGLContext *QWidgetWindowPrivate::shareContext() const +{ + Q_Q(const QWidgetWindow); + const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget()); + return widgetPrivate->shareContext(); +} + QWidgetWindow::QWidgetWindow(QWidget *widget) : QWindow(*new QWidgetWindowPrivate(), 0) , m_widget(widget) diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index d2ad7a466e..d388327687 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -89,7 +89,7 @@ public: void updateUsesNativeWidgets() { - if (usesNativeWidgets || window->parent() == 0) + if (window->parent() == 0) return; Q_Q(QWindowContainer); if (q->internalWinId()) { @@ -97,6 +97,7 @@ public: usesNativeWidgets = true; return; } + bool nativeWidgetSet = false; QWidget *p = q->parentWidget(); while (p) { if (false @@ -108,11 +109,12 @@ public: #endif ) { q->winId(); - usesNativeWidgets = true; + nativeWidgetSet = true; break; } p = p->parentWidget(); } + usesNativeWidgets = nativeWidgetSet; } void markParentChain() { diff --git a/src/widgets/util/qcompleter_p.h b/src/widgets/util/qcompleter_p.h index a1112cb9c7..765363744b 100644 --- a/src/widgets/util/qcompleter_p.h +++ b/src/widgets/util/qcompleter_p.h @@ -101,6 +101,9 @@ public: void _q_autoResizePopup(); void _q_fileSystemModelDirectoryLoaded(const QString &path); void setCurrentIndex(QModelIndex, bool = true); + + static QCompleterPrivate *get(QCompleter *o) { return o->d_func(); } + static const QCompleterPrivate *get(const QCompleter *o) { return o->d_func(); } }; class QIndexMapper diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index c72c060f9a..3427579d1f 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -39,7 +39,9 @@ #include <qplatformdefs.h> #include <private/qabstractspinbox_p.h> +#if QT_CONFIG(datetimeparser) #include <private/qdatetimeparser_p.h> +#endif #include <private/qlineedit_p.h> #include <qabstractspinbox.h> @@ -47,9 +49,6 @@ #include <qstylehints.h> #include <qclipboard.h> #include <qdatetime.h> -#if QT_CONFIG(datetimeedit) -#include <qdatetimeedit.h> -#endif #include <qevent.h> #if QT_CONFIG(menu) #include <qmenu.h> @@ -1962,12 +1961,15 @@ QVariant operator+(const QVariant &arg1, const QVariant &arg2) break; } case QVariant::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble()); break; +#if QT_CONFIG(datetimeparser) case QVariant::DateTime: { QDateTime a2 = arg2.toDateTime(); QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATETIME_MIN.daysTo(a2)); a1.setTime(a1.time().addMSecs(QTime().msecsTo(a2.time()))); ret = QVariant(a1); + break; } +#endif // datetimeparser default: break; } return ret; @@ -2022,6 +2024,7 @@ QVariant operator*(const QVariant &arg1, double multiplier) ret = static_cast<int>(qBound<double>(INT_MIN, arg1.toInt() * multiplier, INT_MAX)); break; case QVariant::Double: ret = QVariant(arg1.toDouble() * multiplier); break; +#if QT_CONFIG(datetimeparser) case QVariant::DateTime: { double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier; int daysInt = (int)days; @@ -2031,6 +2034,7 @@ QVariant operator*(const QVariant &arg1, double multiplier) ret = QDateTime(QDate().addDays(int(days)), QTime().addMSecs(msecs)); break; } +#endif // datetimeparser default: ret = arg1; break; } @@ -2053,11 +2057,14 @@ double operator/(const QVariant &arg1, const QVariant &arg2) a1 = arg1.toDouble(); a2 = arg2.toDouble(); break; +#if QT_CONFIG(datetimeparser) case QVariant::DateTime: a1 = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDate()); a2 = QDATETIMEEDIT_DATE_MIN.daysTo(arg2.toDate()); a1 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg1.toDateTime().time()) / (long)(3600 * 24 * 1000); a2 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg2.toDateTime().time()) / (long)(3600 * 24 * 1000); + break; +#endif // datetimeparser default: break; } diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index cd2e20694e..9afb4b3ae6 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -72,6 +72,7 @@ #include <private/qabstractitemmodel_p.h> #include <private/qabstractscrollarea_p.h> #include <private/qlineedit_p.h> +#include <private/qcompleter_p.h> #include <qdebug.h> #if QT_CONFIG(effects) # include <private/qeffects_p.h> @@ -427,6 +428,20 @@ void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e) QFrame::resizeEvent(e); } +void QComboBoxPrivateContainer::paintEvent(QPaintEvent *e) +{ + QStyleOptionComboBox cbOpt = comboStyleOption(); + if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &cbOpt, combo) + && mask().isEmpty()) { + QStyleOption opt; + opt.initFrom(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_PanelMenu, &opt, &p, this); + } + + QFrame::paintEvent(e); +} + void QComboBoxPrivateContainer::leaveEvent(QEvent *) { // On Mac using the Mac style we want to clear the selection @@ -1227,8 +1242,27 @@ Qt::MatchFlags QComboBoxPrivate::matchFlags() const void QComboBoxPrivate::_q_editingFinished() { Q_Q(QComboBox); - if (lineEdit && !lineEdit->text().isEmpty() && itemText(currentIndex) != lineEdit->text()) { - const int index = q_func()->findText(lineEdit->text(), matchFlags()); + if (!lineEdit) + return; + const auto leText = lineEdit->text(); + if (!leText.isEmpty() && itemText(currentIndex) != leText) { +#if QT_CONFIG(completer) + const auto *leCompleter = lineEdit->completer(); + const auto *popup = leCompleter ? QCompleterPrivate::get(leCompleter)->popup : nullptr; + if (popup && popup->isVisible()) { + // QLineEdit::editingFinished() will be emitted before the code flow returns + // to QCompleter::eventFilter(), where QCompleter::activated() may be emitted. + // We know that the completer popup will still be visible at this point, and + // that any selection should be valid. + const QItemSelectionModel *selModel = popup->selectionModel(); + const QModelIndex curIndex = popup->currentIndex(); + const bool completerIsActive = selModel && selModel->selectedIndexes().contains(curIndex); + + if (completerIsActive) + return; + } +#endif + const int index = q_func()->findText(leText, matchFlags()); if (index != -1) { q->setCurrentIndex(index); emitActivated(currentIndex); @@ -3163,13 +3197,13 @@ void QComboBox::keyPressEvent(QKeyEvent *e) Q_D(QComboBox); #if QT_CONFIG(completer) - if (d->lineEdit - && d->lineEdit->completer() - && d->lineEdit->completer()->popup() - && d->lineEdit->completer()->popup()->isVisible()) { - // provide same autocompletion support as line edit - d->lineEdit->event(e); - return; + if (const auto *cmpltr = completer()) { + const auto *popup = QCompleterPrivate::get(cmpltr)->popup; + if (popup && popup->isVisible()) { + // provide same autocompletion support as line edit + d->lineEdit->event(e); + return; + } } #endif diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 835bbf866e..3f75a357e4 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -248,6 +248,7 @@ protected: void timerEvent(QTimerEvent *timerEvent) override; void leaveEvent(QEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; QStyleOptionComboBox comboStyleOption() const; Q_SIGNALS: diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm index 7d932c670f..0d680fb4dc 100644 --- a/src/widgets/widgets/qmenu_mac.mm +++ b/src/widgets/widgets/qmenu_mac.mm @@ -135,6 +135,11 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* containerWindow->setFlags(wf | Qt::SubWindow); [(NSView *)widget->winId() setAutoresizingMask:NSViewWidthSizable]; + if (QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("setEmbeddedInForeignView")) { + typedef void (*SetEmbeddedInForeignViewFunction)(QPlatformWindow *window, bool embedded); + reinterpret_cast<SetEmbeddedInForeignViewFunction>(function)(containerWindow->handle(), true); + } + item->setNativeContents((WId)containerView); container->show(); } diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 137d38e558..c469c0b793 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -289,7 +289,7 @@ void QMenuBarPrivate::setKeyboardMode(bool b) keyboardState = b; if(b) { QWidget *fw = QApplication::focusWidget(); - if (fw != q) + if (fw && fw != q && fw->window() != QApplication::activePopupWidget()) keyboardFocusWidget = fw; focusFirstAction(); q->setFocus(Qt::MenuBarFocusReason); @@ -1707,6 +1707,7 @@ void QMenuBarPrivate::_q_internalShortcutActivated(int id) } } + keyboardFocusWidget = QApplication::focusWidget(); setCurrentAction(act, true, true); if (act && !act->menu()) { activateAction(act, QAction::Trigger); diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index fd783da49a..60a924510a 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -196,6 +196,8 @@ public: void _q_tabMoved(int from, int to); void init(); + void initBasicStyleOption(QStyleOptionTabWidgetFrame *option) const; + QTabBar *tabs; QStackedWidget *stack; QRect panelRect; @@ -258,6 +260,43 @@ bool QTabWidget::hasHeightForWidth() const return has; } +/*! + \internal + + Initialize only time inexpensive parts of the style option + for QTabWidget::setUpLayout()'s non-visible code path. +*/ +void QTabWidgetPrivate::initBasicStyleOption(QStyleOptionTabWidgetFrame *option) const +{ + Q_Q(const QTabWidget); + option->initFrom(q); + + if (q->documentMode()) + option->lineWidth = 0; + else + option->lineWidth = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q); + + switch (pos) { + case QTabWidget::North: + option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedNorth + : QTabBar::TriangularNorth; + break; + case QTabWidget::South: + option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedSouth + : QTabBar::TriangularSouth; + break; + case QTabWidget::West: + option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedWest + : QTabBar::TriangularWest; + break; + case QTabWidget::East: + option->shape = shape == QTabWidget::Rounded ? QTabBar::RoundedEast + : QTabBar::TriangularEast; + break; + } + + option->tabBarRect = q->tabBar()->geometry(); +} /*! Initialize \a option with the values from this QTabWidget. This method is useful @@ -272,12 +311,7 @@ void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const return; Q_D(const QTabWidget); - option->initFrom(this); - - if (documentMode()) - option->lineWidth = 0; - else - option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this); + d->initBasicStyleOption(option); int exth = style()->pixelMetric(QStyle::PM_TabBarBaseHeight, 0, this); QSize t(0, d->stack->frameWidth()); @@ -308,31 +342,10 @@ void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const option->leftCornerWidgetSize = QSize(0, 0); } - switch (d->pos) { - case QTabWidget::North: - option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedNorth - : QTabBar::TriangularNorth; - break; - case QTabWidget::South: - option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedSouth - : QTabBar::TriangularSouth; - break; - case QTabWidget::West: - option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedWest - : QTabBar::TriangularWest; - break; - case QTabWidget::East: - option->shape = d->shape == QTabWidget::Rounded ? QTabBar::RoundedEast - : QTabBar::TriangularEast; - break; - } - option->tabBarSize = t; - QRect tbRect = tabBar()->geometry(); QRect selectedTabRect = tabBar()->tabRect(tabBar()->currentIndex()); - option->tabBarRect = tbRect; - selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + tbRect.topLeft()); + selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + option->tabBarRect.topLeft()); option->selectedTabRect = selectedTabRect; } @@ -764,17 +777,19 @@ void QTabWidget::setUpLayout(bool onlyCheck) if (onlyCheck && !d->dirty) return; // nothing to do - QStyleOptionTabWidgetFrame option; - initStyleOption(&option); - - // this must be done immediately, because QWidgetItem relies on it (even if !isVisible()) - d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option); - if (!isVisible()) { + // this must be done immediately, because QWidgetItem relies on it (even if !isVisible()) + QStyleOptionTabWidgetFrame basicOption; + d->initBasicStyleOption(&basicOption); + d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &basicOption); d->dirty = true; return; // we'll do it later } + QStyleOptionTabWidgetFrame option; + initStyleOption(&option); + d->setLayoutItemMargins(QStyle::SE_TabWidgetLayoutItem, &option); + QRect tabRect = style()->subElementRect(QStyle::SE_TabWidgetTabBar, &option, this); d->panelRect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option, this); QRect contentsRect = style()->subElementRect(QStyle::SE_TabWidgetTabContents, &option, this); diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 1b7a41d547..4f4a6f70b5 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -44,6 +44,7 @@ #endif #include "qclipboard.h" #include <private/qguiapplication_p.h> +#include <private/qcompleter_p.h> #include <qpa/qplatformtheme.h> #include <qstylehints.h> #ifndef QT_NO_ACCESSIBILITY @@ -1484,7 +1485,8 @@ void QWidgetLineControl::complete(int key) } else { #ifndef QT_KEYPAD_NAVIGATION if (text.isEmpty()) { - m_completer->popup()->hide(); + if (auto *popup = QCompleterPrivate::get(m_completer)->popup) + popup->hide(); return; } #endif @@ -1630,25 +1632,16 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event) #if QT_CONFIG(completer) if (m_completer) { QCompleter::CompletionMode completionMode = m_completer->completionMode(); + auto *popup = QCompleterPrivate::get(m_completer)->popup; if ((completionMode == QCompleter::PopupCompletion || completionMode == QCompleter::UnfilteredPopupCompletion) - && m_completer->popup() - && m_completer->popup()->isVisible()) { + && popup && popup->isVisible()) { // The following keys are forwarded by the completer to the widget // Ignoring the events lets the completer provide suitable default behavior switch (event->key()) { case Qt::Key_Escape: event->ignore(); return; - case Qt::Key_Enter: - case Qt::Key_Return: - case Qt::Key_F4: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - m_completer->popup()->hide(); // just hide. will end up propagating to parent default: break; // normal key processing } |