diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-09-24 09:49:07 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-09-24 12:04:52 +0200 |
commit | c96426f19f8c244c0f5748f0009016f576db9616 (patch) | |
tree | f6365344e8a24415e7a67694af2f0c043bb0dae6 /src/widgets | |
parent | 2137cb7dc5c902ce71855901c83c4c9d87b1ce2d (diff) | |
parent | c5a3e5edd9e63b18abf1838c86a27a662224b02c (diff) |
Merge "Merge remote-tracking branch 'origin/5.3' into 5.4" into refs/staging/5.4
Diffstat (limited to 'src/widgets')
38 files changed, 586 insertions, 120 deletions
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 77b94c02a4..0ead8a6797 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -456,15 +456,15 @@ QByteArray QFileDialog::saveState() const stream << d->qFileDialogUi->splitter->saveState(); stream << d->qFileDialogUi->sidebar->urls(); } else { - stream << QByteArray(); - stream << QList<QUrl>(); + stream << d->splitterState; + stream << d->sidebarUrls; } stream << history(); stream << *lastVisitedDir(); if (d->usingWidgets()) stream << d->qFileDialogUi->treeView->header()->saveState(); else - stream << QByteArray(); + stream << d->headerData; stream << qint32(viewMode()); return data; } @@ -485,9 +485,6 @@ bool QFileDialog::restoreState(const QByteArray &state) QDataStream stream(&sd, QIODevice::ReadOnly); if (stream.atEnd()) return false; - QByteArray splitterState; - QByteArray headerData; - QList<QUrl> bookmarks; QStringList history; QUrl currentDirectory; qint32 marker; @@ -499,8 +496,8 @@ bool QFileDialog::restoreState(const QByteArray &state) if (marker != QFileDialogMagic || (v != 3 && v != 4)) return false; - stream >> splitterState - >> bookmarks + stream >> d->splitterState + >> d->sidebarUrls >> history; if (v == 3) { QString currentDirectoryString; @@ -509,7 +506,7 @@ bool QFileDialog::restoreState(const QByteArray &state) } else { stream >> currentDirectory; } - stream >> headerData + stream >> d->headerData >> viewMode; setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir()); @@ -518,7 +515,7 @@ bool QFileDialog::restoreState(const QByteArray &state) if (!d->usingWidgets()) return true; - if (!d->qFileDialogUi->splitter->restoreState(splitterState)) + if (!d->qFileDialogUi->splitter->restoreState(d->splitterState)) return false; QList<int> list = d->qFileDialogUi->splitter->sizes(); if (list.count() >= 2 && list.at(0) == 0 && list.at(1) == 0) { @@ -527,12 +524,12 @@ bool QFileDialog::restoreState(const QByteArray &state) d->qFileDialogUi->splitter->setSizes(list); } - d->qFileDialogUi->sidebar->setUrls(bookmarks); + d->qFileDialogUi->sidebar->setUrls(d->sidebarUrls); while (history.count() > 5) history.pop_front(); setHistory(history); QHeaderView *headerView = d->qFileDialogUi->treeView->header(); - if (!headerView->restoreState(headerData)) + if (!headerView->restoreState(d->headerData)) return false; QList<QAction*> actions = headerView->actions(); diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index eccc0779f2..15bbd43446 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -273,6 +273,11 @@ public: QSharedPointer<QFileDialogOptions> options; + // Memory of what was read from QSettings in restoreState() in case widgets are not used + QByteArray splitterState; + QByteArray headerData; + QList<QUrl> sidebarUrls; + ~QFileDialogPrivate(); private: diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h index 1338114d96..1c12f15744 100644 --- a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h +++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h @@ -42,6 +42,17 @@ #ifndef QGRAPHICSGRIDLAYOUTENGINE_P_H #define QGRAPHICSGRIDLAYOUTENGINE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtGui/private/qgridlayoutengine_p.h> #ifndef QT_NO_GRAPHICSVIEW diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h index 275ebab6a1..8770e96136 100644 --- a/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h +++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h @@ -41,6 +41,17 @@ #ifndef QGRAPHICSLAYOUTSTYLEINFO_P_H #define QGRAPHICSLAYOUTSTYLEINFO_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtGui/private/qabstractlayoutstyleinfo_p.h> #include <QtWidgets/qstyleoption.h> diff --git a/src/widgets/itemviews/qfileiconprovider_p.h b/src/widgets/itemviews/qfileiconprovider_p.h index 9b2d536258..1c50a7e772 100644 --- a/src/widgets/itemviews/qfileiconprovider_p.h +++ b/src/widgets/itemviews/qfileiconprovider_p.h @@ -42,6 +42,17 @@ #ifndef QFILEICONPROVIDER_P_H #define QFILEICONPROVIDER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qfileiconprovider.h" #include <QtCore/qstring.h> diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp index da5aeb3290..b5fc8d7d63 100644 --- a/src/widgets/itemviews/qstyleditemdelegate.cpp +++ b/src/widgets/itemviews/qstyleditemdelegate.cpp @@ -627,6 +627,9 @@ void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *factory) \li \uicontrol Esc \endlist + If the \a editor's type is QTextEdit or QPlainTextEdit then \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 comitted to the model and the editor is closed. If the \a event is a \uicontrol Tab key press diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp index 157fa55d2e..a186326551 100644 --- a/src/widgets/kernel/qboxlayout.cpp +++ b/src/widgets/kernel/qboxlayout.cpp @@ -51,20 +51,6 @@ QT_BEGIN_NAMESPACE -/* - Returns \c true if the \a widget can be added to the \a layout; - otherwise returns \c false. -*/ -static bool checkWidget(QLayout *layout, QWidget *widget) -{ - if (!widget) { - qWarning("QLayout: Cannot add null widget to %s/%s", layout->metaObject()->className(), - layout->objectName().toLocal8Bit().data()); - return false; - } - return true; -} - struct QBoxLayoutItem { QBoxLayoutItem(QLayoutItem *it, int stretch_ = 0) @@ -958,6 +944,8 @@ void QBoxLayout::insertSpacerItem(int index, QSpacerItem *spacerItem) void QBoxLayout::insertLayout(int index, QLayout *layout, int stretch) { Q_D(QBoxLayout); + if (!d->checkLayout(layout)) + return; if (!adoptLayout(layout)) return; if (index < 0) // append @@ -991,7 +979,7 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch, Qt::Alignment alignment) { Q_D(QBoxLayout); - if (!checkWidget(this, widget)) + if (!d->checkWidget(widget)) return; addChildWidget(widget); if (index < 0) // append diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index 239e1ce1e2..9f545b858a 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -1280,6 +1280,8 @@ void QFormLayout::addRow(QLayout *layout) void QFormLayout::insertRow(int row, QWidget *label, QWidget *field) { Q_D(QFormLayout); + if ((label && !d->checkWidget(label)) || (field && !d->checkWidget(field))) + return; row = d->insertRow(row); if (label) @@ -1295,6 +1297,8 @@ void QFormLayout::insertRow(int row, QWidget *label, QWidget *field) void QFormLayout::insertRow(int row, QWidget *label, QLayout *field) { Q_D(QFormLayout); + if ((label && !d->checkWidget(label)) || (field && !d->checkLayout(field))) + return; row = d->insertRow(row); if (label) @@ -1313,6 +1317,10 @@ void QFormLayout::insertRow(int row, QWidget *label, QLayout *field) */ void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field) { + Q_D(QFormLayout); + if (field && !d->checkWidget(field)) + return; + QLabel *label = 0; if (!labelText.isEmpty()) { label = new QLabel(labelText); @@ -1331,6 +1339,10 @@ void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field) */ void QFormLayout::insertRow(int row, const QString &labelText, QLayout *field) { + Q_D(QFormLayout); + if (field && !d->checkLayout(field)) + return; + insertRow(row, labelText.isEmpty() ? 0 : new QLabel(labelText), field); } @@ -1344,11 +1356,8 @@ void QFormLayout::insertRow(int row, const QString &labelText, QLayout *field) void QFormLayout::insertRow(int row, QWidget *widget) { Q_D(QFormLayout); - - if (!widget) { - qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName())); + if (!d->checkWidget(widget)) return; - } row = d->insertRow(row); d->setWidget(row, SpanningRole, widget); @@ -1365,11 +1374,8 @@ void QFormLayout::insertRow(int row, QWidget *widget) void QFormLayout::insertRow(int row, QLayout *layout) { Q_D(QFormLayout); - - if (!layout) { - qWarning("QFormLayout: Cannot add null field to %s", qPrintable(objectName())); + if (!d->checkLayout(layout)) return; - } row = d->insertRow(row); d->setLayout(row, SpanningRole, layout); diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp index 5434c40f97..6782e4a9f8 100644 --- a/src/widgets/kernel/qgridlayout.cpp +++ b/src/widgets/kernel/qgridlayout.cpp @@ -1430,20 +1430,6 @@ void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, i invalidate(); } -/* - Returns \c true if the widget \a w can be added to the layout \a l; - otherwise returns \c false. -*/ -static bool checkWidget(QLayout *l, QWidget *w) -{ - if (!w) { - qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(), - l->objectName().toLocal8Bit().data()); - return false; - } - return true; -} - /*! Adds the given \a widget to the cell grid at \a row, \a column. The top-left position is (0, 0) by default. @@ -1454,7 +1440,8 @@ static bool checkWidget(QLayout *l, QWidget *w) */ void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment) { - if (!checkWidget(this, widget)) + Q_D(QGridLayout); + if (!d->checkWidget(widget)) return; if (row < 0 || column < 0) { qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d", @@ -1483,7 +1470,7 @@ void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment) { Q_D(QGridLayout); - if (!checkWidget(this, widget)) + if (!d->checkWidget(widget)) return; int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1; int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1; @@ -1518,6 +1505,8 @@ void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment) { Q_D(QGridLayout); + if (!d->checkLayout(layout)) + return; if (!adoptLayout(layout)) return; QGridBox *b = new QGridBox(layout); @@ -1538,6 +1527,8 @@ void QGridLayout::addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment) { Q_D(QGridLayout); + if (!d->checkLayout(layout)) + return; if (!adoptLayout(layout)) return; QGridBox *b = new QGridBox(layout); diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index eb21a580b1..778514f47a 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -858,6 +858,47 @@ void QLayoutPrivate::reparentChildWidgets(QWidget *mw) } /*! + Returns \c true if the \a widget can be added to the \a layout; + otherwise returns \c false. +*/ +bool QLayoutPrivate::checkWidget(QWidget *widget) const +{ + Q_Q(const QLayout); + if (!widget) { + qWarning("QLayout: Cannot add a null widget to %s/%s", q->metaObject()->className(), + qPrintable(q->objectName())); + return false; + } + if (widget == q->parentWidget()) { + qWarning("QLayout: Cannot add parent widget %s/%s to its child layout %s/%s", + widget->metaObject()->className(), qPrintable(widget->objectName()), + q->metaObject()->className(), qPrintable(q->objectName())); + return false; + } + return true; +} + +/*! + Returns \c true if the \a otherLayout can be added to the \a layout; + otherwise returns \c false. +*/ +bool QLayoutPrivate::checkLayout(QLayout *otherLayout) const +{ + Q_Q(const QLayout); + if (!otherLayout) { + qWarning("QLayout: Cannot add a null layout to %s/%s", q->metaObject()->className(), + qPrintable(q->objectName())); + return false; + } + if (otherLayout == q) { + qWarning("QLayout: Cannot add layout %s/%s to itself", q->metaObject()->className(), + qPrintable(q->objectName())); + return false; + } + return true; +} + +/*! This function is called from \c addWidget() functions in subclasses to add \a w as a managed widget of a layout. diff --git a/src/widgets/kernel/qlayout_p.h b/src/widgets/kernel/qlayout_p.h index 2100d86aba..71e0f9bcd3 100644 --- a/src/widgets/kernel/qlayout_p.h +++ b/src/widgets/kernel/qlayout_p.h @@ -76,6 +76,8 @@ public: void getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const; void doResize(const QSize &); void reparentChildWidgets(QWidget *mw); + bool checkWidget(QWidget *widget) const; + bool checkLayout(QLayout *otherLayout) const; static QWidgetItem *createWidgetItem(const QLayout *layout, QWidget *widget); static QSpacerItem *createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum); diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index 87ad7a4bd4..1db1a4b600 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -42,6 +42,17 @@ #ifndef QWIDGETWINDOW_P_H #define QWIDGETWINDOW_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtGui/qwindow.h> #include <QtCore/private/qobject_p.h> diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index fa906a5aa2..065f6c86cf 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -92,8 +92,11 @@ public: Q_Q(QWindowContainer); QWidget *p = q->parentWidget(); while (p) { - if (qobject_cast<QMdiSubWindow *>(p) != 0 - || qobject_cast<QAbstractScrollArea *>(p) != 0) { + if ( +#ifndef QT_NO_MDIAREA + qobject_cast<QMdiSubWindow *>(p) != 0 || +#endif + qobject_cast<QAbstractScrollArea *>(p) != 0) { q->winId(); usesNativeWidgets = true; break; @@ -203,6 +206,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: d->window = embeddedWindow; d->window->setParent(&d->fakeParent); + setAcceptDrops(true); connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)), this, SLOT(focusWindowChanged(QWindow*))); } @@ -295,6 +299,7 @@ bool QWindowContainer::event(QEvent *e) } } break; +#ifndef QT_NO_DRAGANDDROP case QEvent::Drop: case QEvent::DragMove: case QEvent::DragLeave: @@ -306,6 +311,7 @@ bool QWindowContainer::event(QEvent *e) QCoreApplication::sendEvent(d->window, e); e->accept(); return true; +#endif default: break; } diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index 014b163f97..45b3cc021f 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWCONTAINER_H #define QWINDOWCONTAINER_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index bc455dd5c0..110682a7b6 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -1138,6 +1138,7 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget } #endif //QT_NO_TABBAR +#ifndef QT_NO_ANIMATION /*! \internal */ QList<const QObject*> QCommonStylePrivate::animationTargets() const { @@ -1178,6 +1179,7 @@ void QCommonStylePrivate::_q_removeAnimation() if (animation) animations.remove(animation->parent()); } +#endif /*! \reimp diff --git a/src/widgets/styles/qcommonstyle.h b/src/widgets/styles/qcommonstyle.h index 942721a6a3..ef5634a94d 100644 --- a/src/widgets/styles/qcommonstyle.h +++ b/src/widgets/styles/qcommonstyle.h @@ -98,7 +98,9 @@ protected: private: Q_DECLARE_PRIVATE(QCommonStyle) Q_DISABLE_COPY(QCommonStyle) +#ifndef QT_NO_ANIMATION Q_PRIVATE_SLOT(d_func(), void _q_removeAnimation()) +#endif }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h index 8f8a97a2dc..1f5d8b8a81 100644 --- a/src/widgets/styles/qcommonstyle_p.h +++ b/src/widgets/styles/qcommonstyle_p.h @@ -77,7 +77,9 @@ public: ~QCommonStylePrivate() { +#ifndef QT_NO_ANIMATION qDeleteAll(animations); +#endif #ifndef QT_NO_ITEMVIEWS delete cachedOption; #endif @@ -114,6 +116,7 @@ public: #endif int animationFps; +#ifndef QT_NO_ANIMATION void _q_removeAnimation(); QList<const QObject*> animationTargets() const; @@ -123,6 +126,7 @@ public: private: mutable QHash<const QObject*, QStyleAnimation*> animations; +#endif // QT_NO_ANIMATION }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 001a032f9b..989f277c58 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2894,7 +2894,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top()); } painter->save(); - painter->setClipRect(clipRect.adjusted(0, 0, 1, 1)); + painter->setClipRect(clipRect.adjusted(0, 0, 1, 1), Qt::IntersectClip); painter->drawPixmap(groove.topLeft(), cache); painter->restore(); } diff --git a/src/widgets/styles/qfusionstyle_p.h b/src/widgets/styles/qfusionstyle_p.h index 9e5a55918d..ceee6f8b03 100644 --- a/src/widgets/styles/qfusionstyle_p.h +++ b/src/widgets/styles/qfusionstyle_p.h @@ -42,6 +42,17 @@ #ifndef QFUSIONSTYLE_P_H #define QFUSIONSTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtWidgets/qcommonstyle.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h index 525d7f840a..93bb0d309b 100644 --- a/src/widgets/styles/qgtkstyle_p.h +++ b/src/widgets/styles/qgtkstyle_p.h @@ -42,6 +42,17 @@ #ifndef QGTKSTYLE_P_H #define QGTKSTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <private/qwindowsstyle_p.h> #include <QtGui/QPalette> #include <QtGui/QFont> diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index a1838ef1d3..f0a45548f6 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1109,6 +1109,19 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz } #endif +static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath) +{ + CGContextSaveGState(cg); + [NSGraphicsContext setCurrentContext:[NSGraphicsContext + graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; + [NSGraphicsContext saveGraphicsState]; + NSSetFocusRingStyle(NSFocusRingOnly); + [focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos + [focusRingPath fill]; + [NSGraphicsContext restoreGraphicsState]; + CGContextRestoreGState(cg); +} + QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, QStyle::ContentsType ct, QSize szHint, QSize *insz) const { @@ -1333,7 +1346,7 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem bdi->adornment = kThemeAdornmentFocus; if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) bdi->state = kThemeStatePressed; - else if (tds == kThemeStateInactive) + else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion <= QSysInfo::MV_10_9) bdi->state = kThemeStateActive; else bdi->state = tds; @@ -1700,7 +1713,7 @@ void QMacStylePrivate::setAutoDefaultButton(QObject *button) const } QMacStylePrivate::QMacStylePrivate() - : mouseDown(false) + : mouseDown(false), backingStoreNSView(nil) { defaultButtonStart = CFAbsoluteTimeGetCurrent(); memset(&buttonState, 0, sizeof(ButtonState)); @@ -1713,6 +1726,12 @@ QMacStylePrivate::QMacStylePrivate() } +QMacStylePrivate::~QMacStylePrivate() +{ + Q_FOREACH (NSView *b, buttons) + [b release]; +} + ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) { ThemeDrawState tds = kThemeStateActive; @@ -1730,6 +1749,97 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) return tds; } +NSView *QMacStylePrivate::buttonOfKind(ThemeButtonKind kind) const +{ + NSView *bv = buttons[kind]; + if (!bv) { + if (kind == kThemePopupButton) + bv = [[NSPopUpButton alloc] init]; + else if (kind == kThemeComboBox) + bv = [[NSComboBox alloc] init]; + else + bv = [[NSButton alloc] init]; + + switch (kind) { + case kThemeArrowButton: { + NSButton *bc = (NSButton *)bv; + bc.buttonType = NSOnOffButton; + bc.bezelStyle = NSDisclosureBezelStyle; + break; + } + case kThemeCheckBox: + case kThemeCheckBoxSmall: + case kThemeCheckBoxMini: { + NSButton *bc = (NSButton *)bv; + bc.buttonType = NSSwitchButton; + break; + } + case kThemeRadioButton: + case kThemeRadioButtonSmall: + case kThemeRadioButtonMini: { + NSButton *bc = (NSButton *)bv; + bc.buttonType = NSRadioButton; + break; + } + case kThemePushButton: + case kThemePushButtonSmall: + case kThemePushButtonMini: { + NSButton *bc = (NSButton *)bv; + bc.buttonType = NSMomentaryPushButton; + bc.bezelStyle = NSRoundedBezelStyle; + break; + } + default: + break; + } + +// if (kind == kThemePushButtonSmall +// || kind == kThemePopupButtonSmall +// || kind == kThemeCheckBoxSmall +// || kind == kThemeRadioButtonSmall) +// bc.controlSize = NSSmallControlSize; +// else if (kind == kThemePushButtonMini +// || kind == kThemePopupButtonMini +// || kind == kThemeCheckBoxMini +// || kind == kThemeRadioButtonMini) +// bc.controlSize = NSMiniControlSize; + + if ([bv isKindOfClass:[NSButton class]]) { + NSButton *bc = (NSButton *)bv; + bc.title = nil; + } + + const_cast<QMacStylePrivate *>(this)->buttons.insert(kind, bv); + } + + return bv; +} + +void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p) const +{ + QMacCGContext ctx(p); + CGContextSaveGState(ctx); + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext + graphicsContextWithGraphicsPort:ctx flipped:YES]]; + + CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); + + [backingStoreNSView addSubview:view]; + view.frame = rect; + [view drawRect:rect]; + [view removeFromSuperviewWithoutNeedingDisplay]; + + [NSGraphicsContext restoreGraphicsState]; + CGContextRestoreGState(ctx); +} + +void QMacStylePrivate::resolveCurrentNSView(QWindow *window) +{ + backingStoreNSView = window ? (NSView *)window->winId() : nil; +} + void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, QPainter *p, const QStyleOption *opt) const { @@ -1740,8 +1850,12 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD finalyoff = 0; const bool combo = opt->type == QStyleOption::SO_ComboBox; + const bool editableCombo = bdi->kind == kThemeComboBox + || bdi->kind == kThemeComboBoxSmall + || bdi->kind == kThemeComboBoxMini; const bool button = opt->type == QStyleOption::SO_Button; const bool pressed = bdi->state == kThemeStatePressed; + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; if (button && pressed) { if (bdi->kind == kThemePushButton) { @@ -1786,7 +1900,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD if (!combo && !button && bdi->value == kThemeButtonOff) { pm = activePixmap; - } else if (combo || button) { + } else if (!usingYosemiteOrLater && (combo || button)) { QImage image = activePixmap.toImage(); for (int y = 0; y < height; ++y) { @@ -1813,6 +1927,40 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD } } pm = QPixmap::fromImage(image); + } else if ((usingYosemiteOrLater && combo && !editableCombo) || button) { + NSButton *bc = (NSButton *)buttonOfKind(bdi->kind); + [bc highlight:pressed]; + bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; + bc.state = bdi->value == kThemeButtonOn ? NSOnState : + bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState; + p->translate(0, 1); + drawNSViewInRect(bc, opt->rect, p); + p->translate(0, -1); + return; + } else if (usingYosemiteOrLater && editableCombo) { + QImage image = activePixmap.toImage(); + + for (int y = 0; y < height; ++y) { + QRgb *scanLine = reinterpret_cast<QRgb *>(image.scanLine(y)); + + for (int x = 0; x < width; ++x) { + QRgb &pixel = scanLine[x]; + int gray = qRed(pixel); // We know the image is grayscale + int alpha = qAlpha(pixel); + + if (gray == 128 && alpha == 128) { + pixel = qRgba(255, 255, 255, 255); + } else if (alpha == 0) { + pixel = 0; + } else { + bool belowThreshold = (alpha * gray) / 255 + 255 - alpha < 128; + gray = belowThreshold ? 0 : 2 * gray - 255; + alpha = belowThreshold ? 0 : 2 * alpha - 255; + pixel = qRgba(gray, gray, gray, alpha); + } + } + } + pm = QPixmap::fromImage(image); } else { QImage activeImage = activePixmap.toImage(); QImage colorlessImage; @@ -2917,6 +3065,9 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai Q_D(const QMacStyle); ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); + QWindow *window = w && w->window() ? w->window()->windowHandle() : + QStyleHelper::styleObjectWindow(opt->styleObject); + const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); switch (pe) { case PE_IndicatorArrowUp: case PE_IndicatorArrowDown: @@ -3333,6 +3484,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter Q_D(const QMacStyle); ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); + QWindow *window = w && w->window() ? w->window()->windowHandle() : + QStyleHelper::styleObjectWindow(opt->styleObject); + const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { @@ -3545,11 +3699,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; } + // No default button pulsating animation on Yosemite, + // so we have to do few things differently. + const bool yosemiteOrLater = QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + // a focused auto-default button within an active window // takes precedence over a normal default button if (btn->features & QStyleOptionButton::AutoDefaultButton && opt->state & State_Active && opt->state & State_HasFocus) { - d->setAutoDefaultButton(opt->styleObject); + if (yosemiteOrLater) + d->autoDefaultButton = opt->styleObject; + else + d->setAutoDefaultButton(opt->styleObject); } else if (d->autoDefaultButton == opt->styleObject) { d->setAutoDefaultButton(0); } @@ -3557,7 +3718,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (!d->autoDefaultButton) { if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) { d->defaultButton = opt->styleObject; - if (!d->animation(opt->styleObject)) + if (!yosemiteOrLater && !d->animation(opt->styleObject)) d->startAnimation(new QStyleAnimation(opt->styleObject)); } else if (d->defaultButton == opt->styleObject) { if (QStyleAnimation *animation = d->animation(opt->styleObject)) { @@ -3575,29 +3736,45 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else if (d->pressedButton == opt->styleObject) d->pressedButton = 0; - // the default button animation is paused meanwhile any button - // is pressed or an auto-default button is animated instead - if (QStyleAnimation *defaultAnimation = d->animation(d->defaultButton)) { - if (d->pressedButton || d->autoDefaultButton) { - if (defaultAnimation->state() == QStyleAnimation::Running) { - defaultAnimation->pause(); - defaultAnimation->updateTarget(); - } - } else if (defaultAnimation->state() == QStyleAnimation::Paused) { - defaultAnimation->resume(); - } - } - HIThemeButtonDrawInfo bdi; d->initHIThemePushButton(btn, w, tds, &bdi); - if (!d->pressedButton) { - QStyleAnimation* animation = d->animation(opt->styleObject); - if (animation && animation->state() == QStyleAnimation::Running) { + + if (yosemiteOrLater) { + // HITheme is not drawing a nice focus frame around buttons. + // We'll do it ourselves further down. + bdi.adornment &= ~kThemeAdornmentFocus; + + // We can't rely on an animation existing to test for the default look. That means a bit + // more logic (notice that the logic is slightly different for the bevel and the label). + if (tds == kThemeStateActive + && (btn->features & QStyleOptionButton::DefaultButton + || (btn->features & QStyleOptionButton::AutoDefaultButton + && d->autoDefaultButton == btn->styleObject))) bdi.adornment |= kThemeAdornmentDefault; - bdi.animation.time.start = d->defaultButtonStart; - bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); + } else { + // the default button animation is paused meanwhile any button + // is pressed or an auto-default button is animated instead + if (QStyleAnimation *defaultAnimation = d->animation(d->defaultButton)) { + if (d->pressedButton || d->autoDefaultButton) { + if (defaultAnimation->state() == QStyleAnimation::Running) { + defaultAnimation->pause(); + defaultAnimation->updateTarget(); + } + } else if (defaultAnimation->state() == QStyleAnimation::Paused) { + defaultAnimation->resume(); + } + } + + if (!d->pressedButton) { + QStyleAnimation* animation = d->animation(opt->styleObject); + if (animation && animation->state() == QStyleAnimation::Running) { + bdi.adornment |= kThemeAdornmentDefault; + bdi.animation.time.start = d->defaultButtonStart; + bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); + } } } + // Unlike Carbon, we want the button to always be drawn inside its bounds. // Therefore, make the button a bit smaller, so that even if it got focus, // the focus 'shadow' will be inside. @@ -3619,6 +3796,37 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); + if (yosemiteOrLater && btn->state & State_HasFocus) { + CGRect focusRect = newRect; + if (bdi.kind == kThemePushButton) + focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. + else if (bdi.kind == kThemePushButtonMini) + focusRect.size.height = 15; // Our QPushButton sizes are really weird + + if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) { + if (bdi.kind == kThemePushButtonSmall) { + focusRect = CGRectInset(focusRect, -1, 0); + } else if (bdi.kind == kThemePushButtonMini) { + focusRect = CGRectInset(focusRect, 1, 0); + } + } else { + if (bdi.kind == kThemePushButton) { + focusRect = CGRectInset(focusRect, 1, 1); + } else if (bdi.kind == kThemePushButtonSmall) { + focusRect = CGRectInset(focusRect, 0, 2); + } else if (bdi.kind == kThemePushButtonMini) { + focusRect = CGRectInset(focusRect, 2, 1); + } + } + + NSBezierPath *pushButtonFocusRingPath; + if (bdi.kind == kThemeBevelButton) + pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:focusRect]; + else + pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:focusRect xRadius:4 yRadius:4]; + qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath); + } + if (hasMenu) { int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); QRect ir = btn->rect; @@ -3663,14 +3871,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } break; case CE_PushButtonLabel: - if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + if (const QStyleOptionButton *b = qstyleoption_cast<const QStyleOptionButton *>(opt)) { + QStyleOptionButton btn(*b); // We really don't want the label to be drawn the same as on // windows style if it has an icon and text, then it should be more like a // tab. So, cheat a little here. However, if it *is* only an icon // the windows style works great, so just use that implementation. - bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - bool hasIcon = !btn->icon.isNull(); - bool hasText = !btn->text.isEmpty(); + bool hasMenu = btn.features & QStyleOptionButton::HasMenu; + bool hasIcon = !btn.icon.isNull(); + bool hasText = !btn.text.isEmpty(); + + if (QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) { + if (tds == kThemeStatePressed + || (tds == kThemeStateActive + && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) + || d->autoDefaultButton == btn.styleObject))) + btn.palette.setColor(QPalette::ButtonText, Qt::white); + } + if (!hasIcon && !hasMenu) { // ### this is really overly difficult, simplify. // It basically tries to get the right font for "small" and "mini" icons. @@ -3689,8 +3907,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; } } + if (themeId == kThemePushButtonFont) { - QCommonStyle::drawControl(ce, btn, p, w); + QCommonStyle::drawControl(ce, &btn, p, w); } else { p->save(); CGContextSetShouldAntialias(cg, true); @@ -3698,7 +3917,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIThemeTextInfo tti; tti.version = qt_mac_hitheme_version; tti.state = tds; - QColor textColor = btn->palette.buttonText().color(); + QColor textColor; + textColor = btn.palette.buttonText().color(); CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); @@ -3708,9 +3928,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; tti.options = kHIThemeTextBoxOptionNone; tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1 + btn->text.count(QLatin1Char('\n')); - QCFString buttonText = qt_mac_removeMnemonics(btn->text); - QRect r = btn->rect; + tti.truncationMaxLines = 1 + btn.text.count(QLatin1Char('\n')); + QCFString buttonText = qt_mac_removeMnemonics(btn.text); + QRect r = btn.rect; HIRect bounds = qt_hirectForQRect(r); HIThemeDrawTextBox(buttonText, &bounds, &tti, cg, kHIThemeOrientationNormal); @@ -3718,11 +3938,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } } else { if (hasIcon && !hasText) { - QCommonStyle::drawControl(ce, btn, p, w); + QCommonStyle::drawControl(ce, &btn, p, w); } else { - QRect freeContentRect = btn->rect; + QRect freeContentRect = btn.rect; QRect textRect = itemTextRect( - btn->fontMetrics, freeContentRect, Qt::AlignCenter, btn->state & State_Enabled, btn->text); + btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); if (hasMenu) { if (QSysInfo::macVersion() > QSysInfo::MV_10_6) textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls @@ -3734,21 +3954,21 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter int contentW = textRect.width(); if (hasMenu) contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; - QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; - if (mode == QIcon::Normal && btn->state & State_HasFocus) + QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + if (mode == QIcon::Normal && btn.state & State_HasFocus) mode = QIcon::Active; // Decide if the icon is should be on or off: QIcon::State state = QIcon::Off; - if (btn->state & State_On) + if (btn.state & State_On) state = QIcon::On; - QPixmap pixmap = btn->icon.pixmap(btn->iconSize, mode, state); + QPixmap pixmap = btn.icon.pixmap(btn.iconSize, mode, state); int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding; int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2; QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight); - QRect visualIconDestRect = visualRect(btn->direction, freeContentRect, iconDestRect); + QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect); proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); int newOffset = iconDestRect.x() + iconDestRect.width() + QMacStylePrivate::PushButtonContentPadding - textRect.x(); @@ -3756,9 +3976,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } // Draw the text: if (hasText) { - textRect = visualRect(btn->direction, freeContentRect, textRect); - proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette, - (btn->state & State_Enabled), btn->text, QPalette::ButtonText); + textRect = visualRect(btn.direction, freeContentRect, textRect); + proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, + (btn.state & State_Enabled), btn.text, QPalette::ButtonText); } } } @@ -3793,6 +4013,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter return; } } + + bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + HIThemeTabDrawInfo tdi; tdi.version = 1; tdi.style = kThemeTabNonFront; @@ -3833,10 +4056,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else tdi.adornment = kHIThemeTabAdornmentNone; tdi.kind = kHIThemeTabKindNormal; - if (!verticalTabs) - tabRect.setY(tabRect.y() - 1); - else - tabRect.setX(tabRect.x() - 1); + + if (!usingYosemiteOrLater) { + if (!verticalTabs) + tabRect.setY(tabRect.y() - 1); + else + tabRect.setX(tabRect.x() - 1); + } QStyleOptionTab::TabPosition tp = tabOpt->position; QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { @@ -3901,18 +4127,21 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter ThemeTabDirection ttd = getTabDirection(myTab.shape); bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; bool selected = (myTab.state & QStyle::State_Selected); - bool usingModernOSX = QSysInfo::MacintoshVersion > QSysInfo::MV_10_6; + bool usingLionOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_6; + bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; - if (usingModernOSX && selected && !myTab.documentMode) - myTab.palette.setColor(QPalette::WindowText, QColor(Qt::white)); + if (usingLionOrLater && selected && !myTab.documentMode + && (!usingYosemiteOrLater || myTab.state & State_Active)) + myTab.palette.setColor(QPalette::WindowText, Qt::white); // Check to see if we use have the same as the system font // (QComboMenuItem is internal and should never be seen by the // outside world, unless they read the source, in which case, it's // their own fault). bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); - if ((usingModernOSX && selected) || verticalTabs || nonDefaultFont || !tab->icon.isNull() - || !myTab.leftButtonSize.isNull() || !myTab.rightButtonSize.isNull()) { + bool isSelectedAndNeedsShadow = selected && usingLionOrLater && !usingYosemiteOrLater; + if (isSelectedAndNeedsShadow || verticalTabs || nonDefaultFont || !tab->icon.isNull() + || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) { int heightOffset = 0; if (verticalTabs) { heightOffset = -1; @@ -3922,7 +4151,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } myTab.rect.setHeight(myTab.rect.height() + heightOffset); - if (myTab.documentMode || (usingModernOSX && selected)) { + if (myTab.documentMode || isSelectedAndNeedsShadow) { p->save(); rotateTabPainter(p, myTab.shape, myTab.rect); @@ -4062,16 +4291,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w); NSRect rect = NSMakeRect(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff, opt->rect.height() - 2 * yOff); - CGContextSaveGState(cg); - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; - [NSGraphicsContext saveGraphicsState]; - NSSetFocusRingStyle(NSFocusRingOnly); NSBezierPath *focusFramePath = [NSBezierPath bezierPathWithRect:rect]; - [focusFramePath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos - [focusFramePath fill]; - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(cg); + qt_drawFocusRingOnPath(cg, focusFramePath); break; } case CE_MenuItem: case CE_MenuEmptyArea: @@ -4983,6 +5204,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex Q_D(const QMacStyle); ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); + QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : + QStyleHelper::styleObjectWindow(opt->styleObject); + const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); switch (cc) { case CC_Slider: case CC_ScrollBar: diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h index 305bcf871c..b0fb9e06be 100644 --- a/src/widgets/styles/qmacstyle_mac_p.h +++ b/src/widgets/styles/qmacstyle_mac_p.h @@ -42,6 +42,17 @@ #ifndef QMACSTYLE_MAC_P_H #define QMACSTYLE_MAC_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtWidgets/qcommonstyle.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h index 6f42f0ea79..3bbff61340 100644 --- a/src/widgets/styles/qmacstyle_mac_p_p.h +++ b/src/widgets/styles/qmacstyle_mac_p_p.h @@ -145,6 +145,7 @@ class QMacStylePrivate : public QCommonStylePrivate Q_DECLARE_PUBLIC(QMacStyle) public: QMacStylePrivate(); + ~QMacStylePrivate(); // Ideally these wouldn't exist, but since they already exist we need some accessors. static const int PushButtonLeftOffset; @@ -194,6 +195,11 @@ public: void setAutoDefaultButton(QObject *button) const; + NSView *buttonOfKind(ThemeButtonKind kind) const; + + void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p) const; + void resolveCurrentNSView(QWindow *window); + public: mutable QPointer<QObject> pressedButton; mutable QPointer<QObject> defaultButton; @@ -212,6 +218,8 @@ public: void *nsscroller; #endif void *indicatorBranchButtonCell; + NSView *backingStoreNSView; + QHash<ThemeButtonKind , NSView *> buttons; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp index e6e47a98e9..65d011f01f 100644 --- a/src/widgets/styles/qstyleanimation.cpp +++ b/src/widgets/styles/qstyleanimation.cpp @@ -40,6 +40,9 @@ ****************************************************************************/ #include "qstyleanimation_p.h" + +#ifndef QT_NO_ANIMATION + #include <qcoreapplication.h> #include <qwidget.h> #include <qevent.h> @@ -363,3 +366,5 @@ void QScrollbarStyleAnimation::updateCurrentTime(int time) } QT_END_NAMESPACE + +#endif //QT_NO_ANIMATION diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h index 19e629cb25..526722d09a 100644 --- a/src/widgets/styles/qstyleanimation_p.h +++ b/src/widgets/styles/qstyleanimation_p.h @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_ANIMATION + // // W A R N I N G // ------------- @@ -199,6 +201,8 @@ private: bool _active; }; +#endif // QT_NO_ANIMATION + QT_END_NAMESPACE #endif // QSTYLEANIMATION_P_H diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 6be07a3f45..49e406a8b7 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -47,6 +47,7 @@ #include <qmath.h> #include <qscrollbar.h> #include <qabstractscrollarea.h> +#include <qwindow.h> #include "qstylehelper_p.h" #include <qstringbuilder.h> @@ -397,5 +398,14 @@ QColor backgroundColor(const QPalette &pal, const QWidget* widget) return widget->parentWidget()->parentWidget()->palette().color(QPalette::Base); return pal.color(QPalette::Base); } + +QWindow *styleObjectWindow(QObject *so) +{ + if (so) + return so->property("_q_styleObjectWindow").value<QWindow *>(); + + return 0; +} + } QT_END_NAMESPACE diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h index 73e5c94dcd..1229af7497 100644 --- a/src/widgets/styles/qstylehelper_p.h +++ b/src/widgets/styles/qstylehelper_p.h @@ -68,6 +68,7 @@ class QPainter; class QPixmap; class QStyleOptionSlider; class QStyleOption; +class QWindow; namespace QStyleHelper { @@ -87,6 +88,7 @@ namespace QStyleHelper bool hasAncestor(QObject *obj, QAccessible::Role role); #endif QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0); + QWindow *styleObjectWindow(QObject *so); } diff --git a/src/widgets/styles/qwindowscestyle_p.h b/src/widgets/styles/qwindowscestyle_p.h index 73fb2b7ab7..d5e2ee84ed 100644 --- a/src/widgets/styles/qwindowscestyle_p.h +++ b/src/widgets/styles/qwindowscestyle_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWSCESTYLE_P_H #define QWINDOWSCESTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <private/qwindowsstyle_p.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qwindowsmobilestyle_p.h b/src/widgets/styles/qwindowsmobilestyle_p.h index 4262bf5c73..75a4e45ea9 100644 --- a/src/widgets/styles/qwindowsmobilestyle_p.h +++ b/src/widgets/styles/qwindowsmobilestyle_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWSMOBILESTYLE_P_H #define QWINDOWSMOBILESTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <private/qwindowsstyle_p.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h index 1107e70061..39b85ec148 100644 --- a/src/widgets/styles/qwindowsstyle_p.h +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWSSTYLE_P_H #define QWINDOWSSTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtWidgets/qcommonstyle.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle_p.h b/src/widgets/styles/qwindowsvistastyle_p.h index f7914f1645..1b3201c026 100644 --- a/src/widgets/styles/qwindowsvistastyle_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWSVISTASTYLE_P_H #define QWINDOWSVISTASTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <private/qwindowsxpstyle_p.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h index d61132295c..4bb7c73660 100644 --- a/src/widgets/styles/qwindowsxpstyle_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p.h @@ -42,6 +42,17 @@ #ifndef QWINDOWSXPSTYLE_P_H #define QWINDOWSXPSTYLE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <private/qwindowsstyle_p.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qkeysequenceedit_p.h b/src/widgets/widgets/qkeysequenceedit_p.h index f74433bb71..adb3dc7a55 100644 --- a/src/widgets/widgets/qkeysequenceedit_p.h +++ b/src/widgets/widgets/qkeysequenceedit_p.h @@ -43,6 +43,17 @@ #ifndef QKEYSEQUENCEEDIT_P_H #define QKEYSEQUENCEEDIT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qkeysequenceedit.h" #include <private/qwidget_p.h> diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 58ec068bb2..76830c57a1 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -310,7 +310,6 @@ QLineEditIconButton::QLineEditIconButton(QWidget *parent) : QToolButton(parent) , m_opacity(0) { - updateCursor(); setFocusPolicy(Qt::NoFocus); } @@ -334,18 +333,20 @@ void QLineEditIconButton::setOpacity(qreal value) { if (!qFuzzyCompare(m_opacity, value)) { m_opacity = value; + updateCursor(); update(); } } +#ifndef QT_NO_ANIMATION void QLineEditIconButton::startOpacityAnimation(qreal endValue) { QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity")); - connect(animation, &QAbstractAnimation::finished, this, &QLineEditIconButton::updateCursor); animation->setDuration(160); animation->setEndValue(endValue); animation->start(QAbstractAnimation::DeleteWhenStopped); } +#endif void QLineEditIconButton::updateCursor() { @@ -360,6 +361,7 @@ void QLineEditPrivate::_q_textChanged(const QString &text) const int newTextSize = text.size(); if (!newTextSize || !lastTextSize) { lastTextSize = newTextSize; +#ifndef QT_NO_ANIMATION const bool fadeIn = newTextSize > 0; foreach (const SideWidgetEntry &e, leadingSideWidgets) { if (e.flags & SideWidgetFadeInWithText) @@ -369,6 +371,7 @@ void QLineEditPrivate::_q_textChanged(const QString &text) if (e.flags & SideWidgetFadeInWithText) static_cast<QLineEditIconButton *>(e.widget)->animateShow(fadeIn); } +#endif } } } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 08365521d5..b45fde8a1a 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -84,7 +84,9 @@ public: qreal opacity() const { return m_opacity; } void setOpacity(qreal value); +#ifndef QT_NO_ANIMATION void animateShow(bool visible) { startOpacityAnimation(visible ? 1.0 : 0.0); } +#endif protected: void paintEvent(QPaintEvent *event); @@ -93,7 +95,9 @@ private slots: void updateCursor(); private: +#ifndef QT_NO_ANIMATION void startOpacityAnimation(qreal endValue); +#endif qreal m_opacity; }; diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 3959cb6c3f..f1471cc6e4 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -997,7 +997,8 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() } else { vmax = qMax(0, doc->lineCount() - 1); - vSliderLength = viewport->height() / q->fontMetrics().lineSpacing(); + int lineSpacing = q->fontMetrics().lineSpacing(); + vSliderLength = lineSpacing != 0 ? viewport->height() / lineSpacing : 0; } diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp index e46de3958f..5994071bfc 100644 --- a/src/widgets/widgets/qsizegrip.cpp +++ b/src/widgets/widgets/qsizegrip.cpp @@ -83,7 +83,7 @@ public: int dyMax; Qt::Corner m_corner; bool gotMousePress; - QWidget *tlw; + QPointer<QWidget> tlw; #ifdef Q_WS_MAC void updateMacSizer(bool hide) const; #endif diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 1b5ba8cd58..a3845c96f2 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -653,6 +653,10 @@ void QToolButton::setMenu(QMenu* menu) } else { d->menuAction = 0; } + + // changing the menu set may change the size hint, so reset it + d->sizeHint = QSize(); + updateGeometry(); update(); } |