diff options
Diffstat (limited to 'src/widgets')
77 files changed, 899 insertions, 732 deletions
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index a806cb7af6..a2805a2458 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -470,21 +470,15 @@ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const { QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match); - if (match & QAccessible::Labelled) { - QVarLengthArray<QObject *, 4> relatedObjects; - #ifndef QT_NO_SHORTCUT + if (match & QAccessible::Labelled) { if (QLabel *label = qobject_cast<QLabel*>(object())) { - relatedObjects.append(label->buddy()); - } -#endif - for (int i = 0; i < relatedObjects.count(); ++i) { const QAccessible::Relation rel = QAccessible::Labelled; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i)); - if (iface) + if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy())) rels.append(qMakePair(iface, rel)); } } +#endif return rels; } diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 39eacae596..ab3099dfe8 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -355,7 +355,7 @@ void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect) paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw)); } -/*! +/* Reimplement this function to change the contents of the well array. */ void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r) @@ -441,16 +441,12 @@ void QWellArray::focusInEvent(QFocusEvent*) emit currentChanged(curRow, curCol); } -/*!\reimp -*/ void QWellArray::focusOutEvent(QFocusEvent*) { updateCell(curRow, curCol); } -/*\reimp -*/ void QWellArray::keyPressEvent(QKeyEvent* e) { switch(e->key()) { // Look at the key code diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 5892ec6a75..5c07279821 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -860,7 +860,7 @@ void QFileDialog::setVisible(bool visible) } } - if (d->usingWidgets()) + if (visible && d->usingWidgets()) d->qFileDialogUi->fileNameEdit->setFocus(); QDialog::setVisible(visible); @@ -1461,6 +1461,19 @@ void QFileDialog::selectNameFilter(const QString &filter) } /*! + * \since 5.9 + * \return The mimetype of the file that the user selected in the file dialog. + */ +QString QFileDialog::selectedMimeTypeFilter() const +{ + Q_D(const QFileDialog); + if (!d->usingWidgets()) + return d->selectedMimeTypeFilter_sys(); + + return d->options->initiallySelectedMimeTypeFilter(); +} + +/*! \since 4.4 Returns the filter that the user selected in the file dialog. @@ -1579,9 +1592,19 @@ QStringList QFileDialog::mimeTypeFilters() const */ void QFileDialog::selectMimeTypeFilter(const QString &filter) { - const QString text = nameFilterForMime(filter); - if (!text.isEmpty()) - selectNameFilter(text); + Q_D(QFileDialog); + d->options->setInitiallySelectedMimeTypeFilter(filter); + + const QString filterForMime = nameFilterForMime(filter); + + if (!d->usingWidgets()) { + d->selectMimeTypeFilter_sys(filter); + if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) { + selectNameFilter(filterForMime); + } + } else if (!filterForMime.isEmpty()) { + selectNameFilter(filterForMime); + } } #endif // QT_NO_MIMETYPE diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 4ade50793d..7959eebd7b 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -62,7 +62,6 @@ class QAbstractProxyModel; class Q_WIDGETS_EXPORT QFileDialog : public QDialog { Q_OBJECT - Q_FLAGS(Options) Q_PROPERTY(ViewMode viewMode READ viewMode WRITE setViewMode) Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode) Q_PROPERTY(AcceptMode acceptMode READ acceptMode WRITE setAcceptMode) @@ -97,6 +96,7 @@ public: }; Q_ENUM(Option) Q_DECLARE_FLAGS(Options, Option) + Q_FLAG(Options) QFileDialog(QWidget *parent, Qt::WindowFlags f); explicit QFileDialog(QWidget *parent = Q_NULLPTR, @@ -125,6 +125,7 @@ public: void setNameFilters(const QStringList &filters); QStringList nameFilters() const; void selectNameFilter(const QString &filter); + QString selectedMimeTypeFilter() const; QString selectedNameFilter() const; #ifndef QT_NO_MIMETYPE diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index afebad4457..b665b54a9b 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -258,6 +258,8 @@ public: void selectFile_sys(const QUrl &filename); QList<QUrl> selectedFiles_sys() const; void setFilter_sys(); + void selectMimeTypeFilter_sys(const QString &filter); + QString selectedMimeTypeFilter_sys() const; void selectNameFilter_sys(const QString &filter); QString selectedNameFilter_sys() const; ////////////////////////////////////////////// @@ -400,6 +402,20 @@ inline void QFileDialogPrivate::setFilter_sys() helper->setFilter(); } +inline void QFileDialogPrivate::selectMimeTypeFilter_sys(const QString &filter) +{ + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) + helper->selectMimeTypeFilter(filter); +} + +QString QFileDialogPrivate::selectedMimeTypeFilter_sys() const +{ + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) + return helper->selectedMimeTypeFilter(); + + return QString(); +} + inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) { if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 6df020dd58..08c5a40c7c 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -65,6 +65,18 @@ Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot() } #endif +static QString translateDriveName(const QFileInfo &drive) +{ + QString driveName = drive.absoluteFilePath(); +#ifdef Q_OS_WIN + if (driveName.startsWith(QLatin1Char('/'))) // UNC host + return drive.fileName(); + if (driveName.endsWith(QLatin1Char('/'))) + driveName.chop(1); +#endif // Q_OS_WIN + return driveName; +} + /*! Creates thread */ @@ -82,6 +94,16 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) watcher = new QFileSystemWatcher(this); connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString))); connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString))); + +# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + const QVariant listener = watcher->property("_q_driveListener"); + if (listener.canConvert<QObject *>()) { + if (QObject *driveListener = listener.value<QObject *>()) { + connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded())); + connect(driveListener, SIGNAL(driveRemoved(QString)), this, SLOT(driveRemoved())); + } + } +# endif // Q_OS_WIN && !Q_OS_WINRT #endif start(LowPriority); } @@ -106,6 +128,20 @@ void QFileInfoGatherer::setResolveSymlinks(bool enable) #endif } +void QFileInfoGatherer::driveAdded() +{ + fetchExtendedInformation(QString(), QStringList()); +} + +void QFileInfoGatherer::driveRemoved() +{ + QStringList drives; + const QFileInfoList driveInfoList = QDir::drives(); + for (const QFileInfo &fi : driveInfoList) + drives.append(translateDriveName(fi)); + newListOfFiles(QString(), drives); +} + bool QFileInfoGatherer::resolveSymlinks() const { #ifdef Q_OS_WIN @@ -260,18 +296,6 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const return info; } -static QString translateDriveName(const QFileInfo &drive) -{ - QString driveName = drive.absoluteFilePath(); -#if defined(Q_OS_WIN) - if (driveName.startsWith(QLatin1Char('/'))) // UNC host - return drive.fileName(); - if (driveName.endsWith(QLatin1Char('/'))) - driveName.chop(1); -#endif - return driveName; -} - /* Get specific file info's, batch the files so update when we have 100 items and every 200ms after that diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 3186e9d015..0018b6c387 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -180,6 +180,10 @@ public Q_SLOTS: void setResolveSymlinks(bool enable); void setIconProvider(QFileIconProvider *provider); +private Q_SLOTS: + void driveAdded(); + void driveRemoved(); + private: void run() Q_DECL_OVERRIDE; // called by run(): diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index 955e93a26f..b20a1449eb 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -867,8 +867,7 @@ QFont QFontDialog::selectedFont() const \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".) \value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's - native font panel. (Currently, the native dialog is never used, - but this is likely to change in future Qt releases.) + native font panel. \value ScalableFonts Show scalable fonts \value NonScalableFonts Show non scalable fonts \value MonospacedFonts Show monospaced fonts diff --git a/src/widgets/dialogs/qmessagebox.h b/src/widgets/dialogs/qmessagebox.h index c6a55964fe..3e561a5161 100644 --- a/src/widgets/dialogs/qmessagebox.h +++ b/src/widgets/dialogs/qmessagebox.h @@ -56,7 +56,6 @@ class QCheckBox; class Q_WIDGETS_EXPORT QMessageBox : public QDialog { Q_OBJECT - Q_FLAGS(StandardButtons) Q_PROPERTY(QString text READ text WRITE setText) Q_PROPERTY(Icon icon READ icon WRITE setIcon) Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap) @@ -131,6 +130,7 @@ public: typedef StandardButton Button; // obsolete Q_DECLARE_FLAGS(StandardButtons, StandardButton) + Q_FLAG(StandardButtons) explicit QMessageBox(QWidget *parent = Q_NULLPTR); QMessageBox(Icon icon, const QString &title, const QString &text, diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 9153d7ea41..532ee4700f 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -3255,7 +3255,7 @@ void QWizard::paintEvent(QPaintEvent * event) #endif } -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) /*! \reimp */ diff --git a/src/widgets/dialogs/qwizard.h b/src/widgets/dialogs/qwizard.h index 9ce68b6566..7915c9e7f8 100644 --- a/src/widgets/dialogs/qwizard.h +++ b/src/widgets/dialogs/qwizard.h @@ -55,7 +55,6 @@ class QWizardPrivate; class Q_WIDGETS_EXPORT QWizard : public QDialog { Q_OBJECT - Q_FLAGS(WizardOptions) Q_PROPERTY(WizardStyle wizardStyle READ wizardStyle WRITE setWizardStyle) Q_PROPERTY(WizardOptions options READ options WRITE setOptions) Q_PROPERTY(Qt::TextFormat titleFormat READ titleFormat WRITE setTitleFormat) @@ -120,6 +119,7 @@ public: Q_ENUM(WizardOption) Q_DECLARE_FLAGS(WizardOptions, WizardOption) + Q_FLAG(WizardOptions) explicit QWizard(QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); ~QWizard(); @@ -188,7 +188,7 @@ protected: bool event(QEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; #endif void done(int result) Q_DECL_OVERRIDE; diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index 80e37dab25..4ab01aca66 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -49,6 +49,7 @@ #include "qwizard.h" #include "qpaintengine.h" #include "qapplication.h" +#include <QtCore/QOperatingSystemVersion> #include <QtCore/QVariant> #include <QtCore/QDebug> #include <QtGui/QMouseEvent> @@ -214,8 +215,7 @@ void QVistaHelper::disconnectBackButton() QColor QVistaHelper::basicWindowFrameColor() { DWORD rgb; - HWND handle = QApplicationPrivate::getHWNDForWidget(QApplication::desktop()); - const HANDLE hTheme = OpenThemeData(handle, L"WINDOW"); + const HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW"); GetThemeColor(hTheme, WP_CAPTION, CS_ACTIVE, wizard->isActiveWindow() ? TMT_FILLCOLORHINT : TMT_BORDERCOLORHINT, &rgb); BYTE r = GetRValue(rgb); @@ -257,8 +257,7 @@ static LOGFONT getCaptionLogFont(HANDLE hTheme) static bool getCaptionQFont(int dpi, QFont *result) { - const HANDLE hTheme = - OpenThemeData(QApplicationPrivate::getHWNDForWidget(QApplication::desktop()), L"WINDOW"); + const HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW"); if (!hTheme) return false; // Call into QWindowsNativeInterface to convert the LOGFONT into a QFont. @@ -589,8 +588,7 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q if (vistaState() == VistaAero) { const QRect rectDp = QRect(rect.topLeft() * QVistaHelper::m_devicePixelRatio, rect.size() * QVistaHelper::m_devicePixelRatio); - HWND handle = QApplicationPrivate::getHWNDForWidget(QApplication::desktop()); - const HANDLE hTheme = OpenThemeData(handle, L"WINDOW"); + const HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW"); if (!hTheme) return false; // Set up a memory DC and bitmap that we'll draw into HDC dcMem; @@ -718,7 +716,7 @@ int QVistaHelper::topOffset() if (vistaState() != VistaAero) return titleBarSize() + 3; static const int aeroOffset = - QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7 ? + QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ? QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); return aeroOffset + titleBarSize(); } diff --git a/src/widgets/effects/qgraphicseffect.h b/src/widgets/effects/qgraphicseffect.h index 06ee78f2a0..8e07e51dca 100644 --- a/src/widgets/effects/qgraphicseffect.h +++ b/src/widgets/effects/qgraphicseffect.h @@ -62,7 +62,6 @@ class QGraphicsEffectPrivate; class Q_WIDGETS_EXPORT QGraphicsEffect : public QObject { Q_OBJECT - Q_FLAGS(ChangeFlags) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) public: enum ChangeFlag { @@ -72,6 +71,7 @@ public: SourceInvalidated = 0x8 }; Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag) + Q_FLAG(ChangeFlags) enum PixmapPadMode { NoPad, @@ -155,7 +155,6 @@ class QGraphicsBlurEffectPrivate; class Q_WIDGETS_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT - Q_FLAGS(BlurHint BlurHints) Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(BlurHints blurHints READ blurHints WRITE setBlurHints NOTIFY blurHintsChanged) public: @@ -164,7 +163,9 @@ public: QualityHint = 0x01, AnimationHint = 0x02 }; + Q_FLAG(BlurHint) Q_DECLARE_FLAGS(BlurHints, BlurHint) + Q_FLAG(BlurHints) QGraphicsBlurEffect(QObject *parent = Q_NULLPTR); ~QGraphicsBlurEffect(); diff --git a/src/widgets/graphicsview/qgraph_p.h b/src/widgets/graphicsview/qgraph_p.h index b0bf3c91c9..b42d4cf2e3 100644 --- a/src/widgets/graphicsview/qgraph_p.h +++ b/src/widgets/graphicsview/qgraph_p.h @@ -250,7 +250,7 @@ public: } strVertices += QString::fromLatin1("\"%1\" [label=\"%2\"]\n").arg(v->toString()).arg(v->toString()); } - return QString::fromLatin1("%1\n%2\n").arg(strVertices).arg(edges); + return QString::fromLatin1("%1\n%2\n").arg(strVertices, edges); } #endif diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index 6e10d18e11..60e9039b4a 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -892,7 +892,7 @@ bool QGraphicsAnchorLayoutPrivate::replaceVertex(Orientation orientation, Anchor AnchorVertex *otherV = replaceVertex_helper(ad, oldV, newV); #if defined(QT_DEBUG) - ad->name = QString::fromLatin1("%1 --to--> %2").arg(ad->from->toString()).arg(ad->to->toString()); + ad->name = QString::fromLatin1("%1 --to--> %2").arg(ad->from->toString(), ad->to->toString()); #endif bool newFeasible; @@ -1755,7 +1755,7 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt data->from = v1; data->to = v2; #ifdef QT_DEBUG - data->name = QString::fromLatin1("%1 --to--> %2").arg(v1->toString()).arg(v2->toString()); + data->name = QString::fromLatin1("%1 --to--> %2").arg(v1->toString(), v2->toString()); #endif // ### bit to track internal anchors, since inside AnchorData methods // we don't have access to the 'q' pointer. @@ -2575,10 +2575,12 @@ void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> & for (const AnchorData *ad : visited) identifyNonFloatItems_helper(ad, &nonFloating); - QSet<QGraphicsLayoutItem *> allItems; - foreach (QGraphicsLayoutItem *item, items) - allItems.insert(item); - m_floatItems[orientation] = allItems - nonFloating; + QSet<QGraphicsLayoutItem *> floatItems; + for (QGraphicsLayoutItem *item : qAsConst(items)) { + if (!nonFloating.contains(item)) + floatItems.insert(item); + } + m_floatItems[orientation] = std::move(floatItems); } diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h index b6d8a12658..8da338dff7 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h @@ -260,7 +260,7 @@ inline QString AnchorVertex::toString() const { if (m_type == Pair) { const AnchorVertexPair *vp = static_cast<const AnchorVertexPair *>(this); - return QString::fromLatin1("(%1, %2)").arg(vp->m_first->toString()).arg(vp->m_second->toString()); + return QString::fromLatin1("(%1, %2)").arg(vp->m_first->toString(), vp->m_second->toString()); } else if (!m_item) { return QString::fromLatin1("NULL_%1").arg(quintptr(this)); } diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index c9eea6928a..bd5bf08bb8 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -7191,9 +7191,6 @@ void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) } } -/*! - obsolete -*/ bool _qt_movableAncestorIsSelected(const QGraphicsItem *item) { const QGraphicsItem *parent = item->parentItem(); diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h index d6c5d58934..309b8c4d59 100644 --- a/src/widgets/itemviews/qabstractitemview.h +++ b/src/widgets/itemviews/qabstractitemview.h @@ -62,7 +62,6 @@ class QAbstractItemViewPrivate; class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea { Q_OBJECT - Q_FLAGS(EditTriggers) Q_PROPERTY(bool autoScroll READ hasAutoScroll WRITE setAutoScroll) Q_PROPERTY(int autoScrollMargin READ autoScrollMargin WRITE setAutoScrollMargin) Q_PROPERTY(EditTriggers editTriggers READ editTriggers WRITE setEditTriggers) @@ -118,6 +117,7 @@ public: }; Q_DECLARE_FLAGS(EditTriggers, EditTrigger) + Q_FLAG(EditTriggers) enum ScrollMode { ScrollPerItem, diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h index d21ae573cd..5e3858f491 100644 --- a/src/widgets/itemviews/qabstractitemview_p.h +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -89,18 +89,6 @@ class QTypeInfo<QItemViewPaintPair> : public QTypeInfoMerger<QItemViewPaintPair, typedef QVector<QItemViewPaintPair> QItemViewPaintPairs; -class QEmptyModel : public QAbstractItemModel -{ -public: - explicit QEmptyModel(QObject *parent = 0) : QAbstractItemModel(parent) {} - QModelIndex index(int, int, const QModelIndex &) const override { return QModelIndex(); } - QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); } - int rowCount(const QModelIndex &) const override { return 0; } - int columnCount(const QModelIndex &) const override { return 0; } - bool hasChildren(const QModelIndex &) const override { return false; } - QVariant data(const QModelIndex &, int) const override { return QVariant(); } -}; - class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate { Q_DECLARE_PUBLIC(QAbstractItemView) diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 65421bfb67..45c547d313 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1625,6 +1625,33 @@ bool QListView::isSelectionRectVisible() const } /*! + \property QListView::expandingListItems + \brief if items occupy the entire width of the column + \since 5.9 + + If this property is \c true then all items in the column + will have the width of the column; otherwise the width of + each item will be determined by it's size hint. + + By default, this property is \c true. +*/ +void QListView::setExpandingListItems(bool enable) +{ + Q_D(QListView); + if (d->expandingListItems == enable) + return; + d->expandingListItems = enable; + if (viewMode() == ListMode && flow() == QListView::TopToBottom && isWrapping()) + d->doDelayedItemsLayout(); +} + +bool QListView::isExpandingListItems() const +{ + Q_D(const QListView); + return d->expandingListItems; +} + +/*! \reimp */ bool QListView::event(QEvent *e) @@ -1650,7 +1677,8 @@ QListViewPrivate::QListViewPrivate() column(0), uniformItemSizes(false), batchSize(100), - showElasticBand(false) + showElasticBand(false), + expandingListItems(true) { } @@ -2335,13 +2363,7 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) bool QListModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max) { doStaticLayout(info); - if (batchStartRow > max) { // stop items layout - flowPositions.resize(flowPositions.count()); - segmentPositions.resize(segmentPositions.count()); - segmentStartRows.resize(segmentStartRows.count()); - return true; // done - } - return false; // not done + return batchStartRow > max; // returning true stops items layout } QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) const @@ -2371,7 +2393,8 @@ QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) c int right = (segment + 1 >= segmentPositions.count() ? contentsSize.width() : segmentPositions.at(segment + 1)); - size.setWidth(right - pos.x()); + size.setWidth(dd->expandingListItems ? right - pos.x() + : qMin(size.width(), right - pos.x())); } else { // make the items as wide as the viewport size.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing())); } @@ -2475,9 +2498,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) if (info.wrap && (flowPosition + deltaFlowPosition >= segEndPosition)) { segmentExtents.append(flowPosition); flowPosition = info.spacing + segStartPosition; - segPosition += deltaSegPosition; - if (info.wrap) - segPosition += info.spacing; + segPosition += info.spacing + deltaSegPosition; segmentPositions.append(segPosition); segmentStartRows.append(row); deltaSegPosition = 0; @@ -2557,8 +2578,15 @@ QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const if (isHidden(row)) continue; QModelIndex index = modelIndex(row); - if (index.isValid()) - ret += index; + if (index.isValid()) { + if (flow() == QListView::LeftToRight || dd->expandingListItems) { + ret += index; + } else { + const int iw = indexToListViewItem(index).width(); // item width + if (iw > 0 && segStartPosition - segmentPositions.at(seg) < iw) + ret += index; + } + } #if 0 // for debugging else qWarning("intersectingSet: row %d was invalid", row); diff --git a/src/widgets/itemviews/qlistview.h b/src/widgets/itemviews/qlistview.h index e918e66d38..4cf53f9bab 100644 --- a/src/widgets/itemviews/qlistview.h +++ b/src/widgets/itemviews/qlistview.h @@ -66,6 +66,7 @@ class Q_WIDGETS_EXPORT QListView : public QAbstractItemView Q_PROPERTY(int batchSize READ batchSize WRITE setBatchSize) Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap) Q_PROPERTY(bool selectionRectVisible READ isSelectionRectVisible WRITE setSelectionRectVisible) + Q_PROPERTY(bool expandingListItems READ isExpandingListItems WRITE setExpandingListItems) public: enum Movement { Static, Free, Snap }; @@ -126,6 +127,9 @@ public: void setSelectionRectVisible(bool show); bool isSelectionRectVisible() const; + void setExpandingListItems(bool enable); + bool isExpandingListItems() const; + QRect visualRect(const QModelIndex &index) const Q_DECL_OVERRIDE; void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) Q_DECL_OVERRIDE; QModelIndex indexAt(const QPoint &p) const Q_DECL_OVERRIDE; diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h index 47effcdfd9..a66e007195 100644 --- a/src/widgets/itemviews/qlistview_p.h +++ b/src/widgets/itemviews/qlistview_p.h @@ -431,6 +431,8 @@ public: QRect elasticBand; bool showElasticBand; + + bool expandingListItems; }; // inline implementations diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index e0700d877e..4582a55394 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -625,7 +625,7 @@ QActionGroup *QAction::actionGroup() const it is displayed to the left of the menu text. There is no default icon. - If a null icon (QIcon::isNull() is passed into this function, + If a null icon (QIcon::isNull()) is passed into this function, the icon of the action is cleared. */ void QAction::setIcon(const QIcon &icon) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 5908d3036b..2c85ed3c0b 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -408,7 +408,6 @@ QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input foc QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show() QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus #ifndef QT_NO_WHEELEVENT -int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll QPointer<QWidget> QApplicationPrivate::wheel_widget; #endif bool qt_in_tab_key_event = false; @@ -642,19 +641,12 @@ void QApplicationPrivate::initialize() if (qEnvironmentVariableIntValue("QT_USE_NATIVE_WINDOWS") > 0) QCoreApplication::setAttribute(Qt::AA_NativeWindows); -#ifndef QT_NO_WHEELEVENT - QApplicationPrivate::wheel_scroll_lines = 3; -#endif - if (qt_is_gui_used) initializeMultitouch(); if (QApplication::desktopSettingsAware()) if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { QApplicationPrivate::enabledAnimations = theme->themeHint(QPlatformTheme::UiEffects).toInt(); -#ifndef QT_NO_WHEELEVENT - QApplicationPrivate::wheel_scroll_lines = theme->themeHint(QPlatformTheme::WheelScrollLines).toInt(); -#endif } is_app_running = true; // no longer starting up @@ -2169,11 +2161,14 @@ QWidget *qt_tlw_for_window(QWindow *wnd) // QTBUG-32177, wnd might be a QQuickView embedded via window container. while (wnd && !wnd->isTopLevel()) { QWindow *parent = wnd->parent(); + if (!parent) + break; + // Don't end up in windows not belonging to this application - if (parent && parent->type() != Qt::ForeignWindow) - wnd = wnd->parent(); - else + if (parent->handle() && parent->handle()->isForeignWindow()) break; + + wnd = wnd->parent(); } if (wnd) { const auto tlws = qApp->topLevelWidgets(); @@ -2455,26 +2450,11 @@ bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWin for (int i = 0; i < modalWindowList.count(); ++i) { QWindow *modalWindow = modalWindowList.at(i); - { - // check if the modal window is our window or a (transient) parent of our window - QWindow *w = window; - while (w) { - if (w == modalWindow) { - *blockingWindow = 0; - return false; - } - QWindow *p = w->parent(); - if (!p) - p = w->transientParent(); - w = p; - } - - // Embedded in-process windows are not visible in normal parent-child chain, - // so check the native parent chain, too. - const QPlatformWindow *platWin = window->handle(); - const QPlatformWindow *modalPlatWin = modalWindow->handle(); - if (platWin && modalPlatWin && platWin->isEmbedded(modalPlatWin)) - return false; + // A window is not blocked by another modal window if the two are + // the same, or if the window is a child of the modal window. + if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) { + *blockingWindow = 0; + return false; } Qt::WindowModality windowModality = modalWindow->modality(); @@ -3558,9 +3538,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) touchEvent->setTarget(widget); for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) { QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i]; - QRectF rect = pt.rect(); - rect.translate(offset); - pt.d->rect = rect; + pt.d->pos = pt.pos() + offset; pt.d->startPos = pt.startPos() + offset; pt.d->lastPos = pt.lastPos() + offset; } @@ -4066,16 +4044,18 @@ int QApplication::keyboardInputInterval() or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}. By default, this property has a value of 3. + + \sa QStyleHints::wheelScrollLines() */ #ifndef QT_NO_WHEELEVENT int QApplication::wheelScrollLines() { - return QApplicationPrivate::wheel_scroll_lines; + return styleHints()->wheelScrollLines(); } void QApplication::setWheelScrollLines(int lines) { - QApplicationPrivate::wheel_scroll_lines = lines; + styleHints()->setWheelScrollLines(lines); } #endif @@ -4257,12 +4237,10 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i]; // preserve the sub-pixel resolution - QRectF rect = touchPoint.screenRect(); - const QPointF screenPos = rect.center(); + const QPointF screenPos = touchPoint.screenRect().center(); const QPointF delta = screenPos - screenPos.toPoint(); - rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta); - touchPoint.d->rect = rect; + touchPoint.d->pos = widget->mapFromGlobal(screenPos.toPoint()) + delta; touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 73c75bbc14..271844a23e 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -91,12 +91,6 @@ extern Q_GUI_EXPORT bool qt_is_gui_used; extern QClipboard *qt_clipboard; #endif -#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) -extern QSysInfo::WinVersion qt_winver; -#elif defined (Q_OS_MAC) -extern QSysInfo::MacVersion qt_macver; -#endif - typedef QHash<QByteArray, QFont> FontHash; FontHash *qt_app_fonts_hash(); diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index 4846a868aa..dade4fe45e 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -56,6 +56,7 @@ #include "private/qwidget_p.h" #include <QtCore/qalgorithms.h> +#include <QtGui/qscreen.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index 6b134379c6..c66a6d5673 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -1167,12 +1167,12 @@ QLayoutItem* QFormLayoutPrivate::replaceAt(int index, QLayoutItem *newitem) */ /*! - \since 5.8 - \struct QFormLayout::TakeRowResult + \class QFormLayout::TakeRowResult \brief Contains the result of a QFormLayout::takeRow() call. - + \inmodule QtWidgets + \since 5.8 \sa QFormLayout::takeRow() */ diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp index 2f33066389..3962cbe6c5 100644 --- a/src/widgets/kernel/qgesture.cpp +++ b/src/widgets/kernel/qgesture.cpp @@ -819,7 +819,6 @@ void QTapAndHoldGesture::setPosition(const QPointF &value) later the touch is still down, it will trigger the QTapAndHoldGesture. The default value is 700 milliseconds. */ -// static void QTapAndHoldGesture::setTimeout(int msecs) { QTapAndHoldGesturePrivate::Timeout = msecs; @@ -832,7 +831,6 @@ void QTapAndHoldGesture::setTimeout(int msecs) later the touch is still down, it will trigger the QTapAndHoldGesture. The default value is 700 milliseconds. */ -// static int QTapAndHoldGesture::timeout() { return QTapAndHoldGesturePrivate::Timeout; diff --git a/src/widgets/kernel/qgesture.h b/src/widgets/kernel/qgesture.h index 034d1d88c1..4dd6e82fd1 100644 --- a/src/widgets/kernel/qgesture.h +++ b/src/widgets/kernel/qgesture.h @@ -135,7 +135,6 @@ class Q_WIDGETS_EXPORT QPinchGesture : public QGesture { Q_OBJECT Q_DECLARE_PRIVATE(QPinchGesture) - Q_FLAGS(ChangeFlags ChangeFlag) public: enum ChangeFlag { @@ -143,7 +142,9 @@ public: RotationAngleChanged = 0x2, CenterPointChanged = 0x4 }; + Q_FLAG(ChangeFlag) Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag) + Q_FLAG(ChangeFlags) Q_PROPERTY(ChangeFlags totalChangeFlags READ totalChangeFlags WRITE setTotalChangeFlags) Q_PROPERTY(ChangeFlags changeFlags READ changeFlags WRITE setChangeFlags) diff --git a/src/widgets/kernel/qsizepolicy.cpp b/src/widgets/kernel/qsizepolicy.cpp index e902bb522c..a03523d2af 100644 --- a/src/widgets/kernel/qsizepolicy.cpp +++ b/src/widgets/kernel/qsizepolicy.cpp @@ -395,6 +395,18 @@ void QSizePolicy::setControlType(ControlType type) \fn void QSizePolicy::transpose() Swaps the horizontal and vertical policies and stretches. + + \sa transposed() +*/ + +/*! + \fn QSizePolicy QSizePolicy::transposed() const + \since 5.9 + + Returns a size policy object with the horizontal and vertical + policies and stretches swapped. + + \sa transpose() */ /*! diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h index 63b578fbf3..3ab672a8e8 100644 --- a/src/widgets/kernel/qsizepolicy.h +++ b/src/widgets/kernel/qsizepolicy.h @@ -45,6 +45,29 @@ QT_BEGIN_NAMESPACE +// gcc < 4.8.0 has problems with init'ing variant members in constexpr ctors +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54922 +#if !defined(Q_CC_GNU) || defined(Q_CC_INTEL) || defined(Q_CC_CLANG) || Q_CC_GNU >= 408 +# define QT_SIZEPOLICY_CONSTEXPR Q_DECL_CONSTEXPR +# if defined(Q_COMPILER_UNIFORM_INIT) +# define QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT Q_DECL_CONSTEXPR +# if defined(Q_COMPILER_CONSTEXPR) +# define QT_SIZEPOLICY_RETURN_BITS(E1, E2, E3, E4, E5, E6, E7, E8) \ + return Bits{ E1, E2, E3, E4, E5, E6, E7, E8 } +# endif // constexpr && uniform-init +# endif // uniform-init +#endif + +#ifndef QT_SIZEPOLICY_CONSTEXPR +# define QT_SIZEPOLICY_CONSTEXPR +#endif +#ifndef QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT +# define QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT +#endif +#ifndef QT_SIZEPOLICY_RETURN_BITS +# define QT_SIZEPOLICY_RETURN_BITS(E1, E2, E3, E4, E5, E6, E7, E8) \ + const Bits result = { E1, E2, E3, E4, E5, E6, E7, E8 }; return result +#endif class QVariant; class QSizePolicy; @@ -54,7 +77,6 @@ Q_DECL_CONST_FUNCTION inline uint qHash(QSizePolicy key, uint seed = 0) Q_DECL_N class Q_WIDGETS_EXPORT QSizePolicy { Q_GADGET - Q_FLAGS(ControlTypes) public: enum PolicyFlag { @@ -93,8 +115,9 @@ public: ToolButton = 0x00004000 }; Q_DECLARE_FLAGS(ControlTypes, ControlType) + Q_FLAG(ControlTypes) - QSizePolicy() : data(0) { } + QT_SIZEPOLICY_CONSTEXPR QSizePolicy() : data(0) { } QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) : data(0) { @@ -102,48 +125,56 @@ public: bits.verPolicy = vertical; setControlType(type); } - Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); } - Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); } + QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); } + QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); } ControlType controlType() const; void setHorizontalPolicy(Policy d) { bits.horPolicy = d; } void setVerticalPolicy(Policy d) { bits.verPolicy = d; } void setControlType(ControlType type); - Qt::Orientations expandingDirections() const { + QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const { return ( (verticalPolicy() & ExpandFlag) ? Qt::Vertical : Qt::Orientations() ) | ( (horizontalPolicy() & ExpandFlag) ? Qt::Horizontal : Qt::Orientations() ) ; } - void setHeightForWidth(bool b) { bits.hfw = b; } - bool hasHeightForWidth() const { return bits.hfw; } + void setHeightForWidth(bool b) { bits.hfw = b; } + QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const { return bits.hfw; } void setWidthForHeight(bool b) { bits.wfh = b; } - bool hasWidthForHeight() const { return bits.wfh; } + QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const { return bits.wfh; } - bool operator==(const QSizePolicy& s) const { return data == s.data; } - bool operator!=(const QSizePolicy& s) const { return data != s.data; } + QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const { return data == s.data; } + QT_SIZEPOLICY_CONSTEXPR bool operator!=(const QSizePolicy& s) const { return data != s.data; } friend Q_DECL_CONST_FUNCTION uint qHash(QSizePolicy key, uint seed) Q_DECL_NOTHROW { return qHash(key.data, seed); } operator QVariant() const; - int horizontalStretch() const { return static_cast<int>(bits.horStretch); } - int verticalStretch() const { return static_cast<int>(bits.verStretch); } + QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const { return static_cast<int>(bits.horStretch); } + QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const { return static_cast<int>(bits.verStretch); } void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } - bool retainSizeWhenHidden() const { return bits.retainSizeWhenHidden; } + QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const { return bits.retainSizeWhenHidden; } void setRetainSizeWhenHidden(bool retainSize) { bits.retainSizeWhenHidden = retainSize; } - void transpose(); - + void transpose() { *this = transposed(); } +#ifndef Q_QDOC + QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT +#endif + QSizePolicy transposed() const Q_DECL_NOTHROW Q_REQUIRED_RESULT + { + return QSizePolicy(bits.transposed()); + } private: #ifndef QT_NO_DATASTREAM friend Q_WIDGETS_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &); friend Q_WIDGETS_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &); #endif - QSizePolicy(int i) : data(i) { } + QT_SIZEPOLICY_CONSTEXPR QSizePolicy(int i) : data(i) { } + struct Bits; + QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) Q_DECL_NOTHROW : bits(b) { } struct Bits { quint32 horStretch : 8; @@ -154,6 +185,19 @@ private: quint32 hfw : 1; quint32 wfh : 1; quint32 retainSizeWhenHidden : 1; + + QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT + Bits transposed() const Q_DECL_NOTHROW + { + QT_SIZEPOLICY_RETURN_BITS(verStretch, // \ swap + horStretch, // / + verPolicy, // \ swap + horPolicy, // / + ctype, + hfw, // \ don't swap (historic behavior) + wfh, // / + retainSizeWhenHidden); + } }; union { Bits bits; @@ -176,16 +220,10 @@ Q_WIDGETS_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &); Q_WIDGETS_EXPORT QDebug operator<<(QDebug dbg, const QSizePolicy &); #endif -inline void QSizePolicy::transpose() { - Policy hData = horizontalPolicy(); - Policy vData = verticalPolicy(); - int hStretch = horizontalStretch(); - int vStretch = verticalStretch(); - setHorizontalPolicy(vData); - setVerticalPolicy(hData); - setHorizontalStretch(vStretch); - setVerticalStretch(hStretch); -} + +#undef QT_SIZEPOLICY_CONSTEXPR +#undef QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT +#undef QT_SIZEPOLICY_RETURN_BITS QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index cf90df6b9b..dc55c2d5d9 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1477,12 +1477,16 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ? QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive; - win->create(); - // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing. - if ((flags & Qt::Desktop) == Qt::Window) + + if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) { + win->create(); + // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing. win->handle()->setFrameStrutEventsEnabled(true); + } data.window_flags = win->flags(); + if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level + data.window_flags &= ~Qt::ForeignWindow; if (!topData()->role.isNull()) QXcbWindowFunctions::setWmWindowRole(win, topData()->role.toLatin1()); @@ -1499,10 +1503,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } setWindowModified_helper(); - WId id = win->winId(); - // See the QPlatformWindow::winId() documentation - Q_ASSERT(id != WId(0)); - setWinId(id); + + if (win->handle()) { + WId id = win->winId(); + // See the QPlatformWindow::winId() documentation + Q_ASSERT(id != WId(0)); + setWinId(id); + } // Check children and create windows for them if necessary q_createNativeChildrenAndSetParent(q); @@ -5246,8 +5253,6 @@ static void sendResizeEvents(QWidget *target) \sa render(), QPixmap */ - -/* INVOKABLE since used by QPixmap::grabWidget(). */ QPixmap QWidget::grab(const QRect &rectangle) { Q_D(QWidget); @@ -6593,11 +6598,6 @@ void QWidget::setFocus(Qt::FocusReason reason) } else { f->d_func()->updateFocusChild(); } - - if (QTLWExtra *extra = f->window()->d_func()->maybeTopData()) { - if (extra->window) - emit extra->window->focusObjectChanged(f); - } } void QWidgetPrivate::setFocus_sys() @@ -6632,6 +6632,11 @@ void QWidgetPrivate::updateFocusChild() w = w->isWindow() ? 0 : w->parentWidget(); } } + + if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) { + if (extra->window) + emit extra->window->focusObjectChanged(q); + } } /*! @@ -6673,9 +6678,15 @@ void QWidget::clearFocus() w->d_func()->focus_child = 0; w = w->parentWidget(); } - // Since focus_child is the basis for the top level QWidgetWindow's focusObject() - // we need to report this change to the rest of Qt, but we match setFocus() and - // do it at the end of the function. + + // Since we've unconditionally cleared the focus_child of our parents, we need + // to report this to the rest of Qt. Note that the focus_child is not the same + // thing as the application's focusWidget, which is why this piece of code is + // not inside the hasFocus() block below. + if (QTLWExtra *extra = window()->d_func()->maybeTopData()) { + if (extra->window) + emit extra->window->focusObjectChanged(extra->window->focusObject()); + } #ifndef QT_NO_GRAPHICSVIEW QWExtra *topData = d_func()->extra; @@ -6698,15 +6709,6 @@ void QWidget::clearFocus() #endif } } - - // Since we've unconditionally cleared the focus_child of our parents, we need - // to report this to the rest of Qt. Note that the focus_child is not the same - // thing as the application's focusWidget, which is why this piece of code is - // not inside the hasFocus() block above. - if (QTLWExtra *extra = window()->d_func()->maybeTopData()) { - if (extra->window) - emit extra->window->focusObjectChanged(extra->window->focusObject()); - } } @@ -10353,7 +10355,7 @@ void QWidget::updateGeometry() a window, causing the widget to be hidden. You must call show() to make the widget visible again.. - \sa windowType(), {Window Flags Example} + \sa windowType(), setWindowFlag(), {Window Flags Example} */ void QWidget::setWindowFlags(Qt::WindowFlags flags) { @@ -10361,6 +10363,23 @@ void QWidget::setWindowFlags(Qt::WindowFlags flags) d->setWindowFlags(flags); } +/*! + \since 5.9 + + Sets the window flag \a flag on this widget if \a on is true; + otherwise clears the flag. + + \sa setWindowFlags(), windowFlags(), windowType() +*/ +void QWidget::setWindowFlag(Qt::WindowType flag, bool on) +{ + Q_D(QWidget); + if (on) + d->setWindowFlags(data->window_flags | flag); + else + d->setWindowFlags(data->window_flags & ~flag); +} + /*! \internal Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it. @@ -12710,7 +12729,6 @@ void QWidget::activateWindow() } /*! - \fn int QWidget::metric(PaintDeviceMetric m) const Internal implementation of the virtual QPaintDevice::metric() function. @@ -12934,6 +12952,9 @@ void QWidget::setMask(const QBitmap &bitmap) */ void QWidget::clearMask() { + Q_D(QWidget); + if (!d->extra || !d->extra->hasMask) + return; setMask(QRegion()); } diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index 58413c6bd3..4c80038a4f 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -562,6 +562,7 @@ public: void setWindowFlags(Qt::WindowFlags type); inline Qt::WindowFlags windowFlags() const; + void setWindowFlag(Qt::WindowType, bool on = true); void overrideWindowFlags(Qt::WindowFlags type); inline Qt::WindowType windowType() const; diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 910704498c..781ad9600d 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -164,23 +164,11 @@ static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec return; const HDC hdc = reinterpret_cast<HDC>(hdcV); - HBRUSH brush; - static int i = 0; - switch (i) { - case 0: - brush = CreateSolidBrush(RGB(255, 255, 0)); - break; - case 1: - brush = CreateSolidBrush(RGB(255, 200, 55)); - break; - case 2: - brush = CreateSolidBrush(RGB(200, 255, 55)); - break; - case 3: - brush = CreateSolidBrush(RGB(200, 200, 0)); - break; - } - i = (i + 1) & 3; + static const COLORREF colors[] = {RGB(255, 255, 0), RGB(255, 200, 55), RGB(200, 255, 55), RGB(200, 200, 0)}; + + static size_t i = 0; + const HBRUSH brush = CreateSolidBrush(colors[i]); + i = (i + 1) % (sizeof(colors) / sizeof(colors[0])); for (const QRect &rect : region) { RECT winRect; diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 3e15b6977a..7295cc36f6 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -957,8 +957,8 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event // Sent event if the state changed (that is, it is not triggered by // QWidget::setWindowState(), which also sends an event to the widget). - if (widgetState != int(m_widget->data->window_state)) { - m_widget->data->window_state = widgetState; + if (widgetState != Qt::WindowStates::Int(m_widget->data->window_state)) { + m_widget->data->window_state = uint(widgetState); QWindowStateChangeEvent widgetEvent(eventState); QGuiApplication::sendSpontaneousEvent(m_widget, &widgetEvent); } diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index edf2383596..a81355160e 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -56,6 +56,7 @@ #include <QtCore/private/qobject_p.h> #include <QtGui/private/qevent_p.h> +#include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 7971bd0b8b..18a0c4fb64 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -1099,7 +1099,7 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *w || opt->shape == QTabBar::TriangularEast || opt->shape == QTabBar::TriangularWest; if (verticalTabs) - tr.setRect(0, 0, tr.height(), tr.width()); //0, 0 as we will have a translate transform + tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); @@ -1122,7 +1122,7 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *w // right widget if (!opt->rightButtonSize.isEmpty()) { tr.setRight(tr.right() - 4 - - (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width())); + (verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width())); } // icon @@ -1134,12 +1134,12 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *w } QSize tabIconSize = opt->icon.actualSize(iconSize, (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, - (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off ); - // High-dpi icons do not need adjustmet; make sure tabIconSize is not larger than iconSize + (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); + // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, - tabIconSize.width(), tabIconSize .height()); + tabIconSize.width(), tabIconSize.height()); if (!verticalTabs) *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); tr.setLeft(tr.left() + tabIconSize.width() + 4); @@ -4872,6 +4872,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, QRect decorationRect, displayRect, checkRect; d->viewItemLayout(vopt, &checkRect, &decorationRect, &displayRect, true); sz = (decorationRect|displayRect|checkRect).size(); + if (decorationRect.isValid() && sz.height() == decorationRect.height()) + sz.rheight() += 2; // Prevent icons from overlapping. } break; #endif // QT_NO_ITEMVIEWS diff --git a/src/widgets/styles/qdrawutil.cpp b/src/widgets/styles/qdrawutil.cpp index fa80a7a6ca..0b0583ea94 100644 --- a/src/widgets/styles/qdrawutil.cpp +++ b/src/widgets/styles/qdrawutil.cpp @@ -797,7 +797,11 @@ typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray; void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, - const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) + const QTileRules &rules +#ifndef Q_CLANG_QDOC + , QDrawBorderPixmap::DrawingHints hints +#endif + ) { QPainter::PixmapFragment d; d.opacity = 1.0; diff --git a/src/widgets/styles/qdrawutil.h b/src/widgets/styles/qdrawutil.h index 121221dfc9..d5582f2c90 100644 --- a/src/widgets/styles/qdrawutil.h +++ b/src/widgets/styles/qdrawutil.h @@ -119,7 +119,7 @@ struct QTileRules Qt::TileRule vertical; }; -#ifndef Q_QDOC +#ifndef Q_CLANG_QDOC // For internal use only. namespace QDrawBorderPixmap { @@ -151,7 +151,7 @@ Q_WIDGETS_EXPORT void qDrawBorderPixmap(QPainter *painter, const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules = QTileRules() -#ifndef Q_QDOC +#ifndef Q_CLANG_QDOC , QDrawBorderPixmap::DrawingHints hints = QDrawBorderPixmap::DrawingHints() #endif ); diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index e08cd3ac70..75c50bb146 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -2437,7 +2437,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption int oldMin = styleObject->property("_q_stylemin").toInt(); int oldMax = styleObject->property("_q_stylemax").toInt(); QRect oldRect = styleObject->property("_q_stylerect").toRect(); - int oldState = styleObject->property("_q_stylestate").toInt(); + QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>()); uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); // a scrollbar is transient when the the scrollbar itself and @@ -2460,7 +2460,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption styleObject->setProperty("_q_stylemin", scrollBar->minimum); styleObject->setProperty("_q_stylemax", scrollBar->maximum); styleObject->setProperty("_q_stylerect", scrollBar->rect); - styleObject->setProperty("_q_stylestate", static_cast<int>(scrollBar->state)); + styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(scrollBar->state)); styleObject->setProperty("_q_stylecontrols", static_cast<uint>(scrollBar->activeSubControls)); #ifndef QT_NO_ANIMATION diff --git a/src/widgets/styles/qmacstyle.qdoc b/src/widgets/styles/qmacstyle.qdoc index f8bd1f57a9..a77843a4dd 100644 --- a/src/widgets/styles/qmacstyle.qdoc +++ b/src/widgets/styles/qmacstyle.qdoc @@ -143,45 +143,6 @@ \reimp */ -/*! - \enum QMacStyle::FocusRectPolicy - - This type is used to signify a widget's focus rectangle policy. - - \value FocusEnabled show a focus rectangle when the widget has focus. - \value FocusDisabled never show a focus rectangle for the widget. - \value FocusDefault show a focus rectangle when the widget has - focus and the widget is a QSpinWidget, QDateTimeEdit, QLineEdit, - QListBox, QListView, editable QTextEdit, or one of their - subclasses. -*/ - -/*! \fn void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) - \obsolete - Sets the focus rectangle policy of \a w. The \a policy can be one of - \l{QMacStyle::FocusRectPolicy}. - - This is now simply an interface to the Qt::WA_MacShowFocusRect attribute and the - FocusDefault value does nothing anymore. If you want to set a widget back - to its default value, you must save the old value of the attribute before - you change it. - - \sa focusRectPolicy(), QWidget::setAttribute() -*/ - -/*! \fn QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) - \obsolete - Returns the focus rectangle policy for the widget \a w. - - The focus rectangle policy can be one of \l{QMacStyle::FocusRectPolicy}. - - In 4.3 and up this function will simply test for the - Qt::WA_MacShowFocusRect attribute and will never return - QMacStyle::FocusDefault. - - \sa setFocusRectPolicy(), QWidget::testAttribute() -*/ - /*! \fn void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) \obsolete diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 007ce20175..cc895e2c33 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -84,6 +84,7 @@ #include <qtoolbutton.h> #include <qtreeview.h> #include <qtableview.h> +#include <qoperatingsystemversion.h> #include <qwizard.h> #include <qdebug.h> #include <qlibrary.h> @@ -1016,7 +1017,7 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const { - qreal pixelRatio = p->device()->devicePixelRatioF(); + const qreal pixelRatio = p->device()->devicePixelRatioF(); static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4"); const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio); QPixmap focusRingPixmap; @@ -1027,20 +1028,38 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h focusRingPixmap.fill(Qt::transparent); focusRingPixmap.setDevicePixelRatio(pixelRatio); { + const CGFloat focusRingWidth = radius > 0 ? 3.5 : 6; QMacAutoReleasePool pool; + QMacCGContext ctx(&focusRingPixmap); + CGContextBeginTransparencyLayer(ctx, NULL); + CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx + flipped:NO]]; + CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size); NSBezierPath *focusRingPath; - if (radius > 0) - focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(hMargin, vMargin, size, size) + if (radius > 0) { + const CGFloat roundedRectInset = -1.5; + focusRingPath = [NSBezierPath bezierPathWithRoundedRect:CGRectInset(focusRingRect, roundedRectInset, roundedRectInset) xRadius:radius yRadius:radius]; - else - focusRingPath = [NSBezierPath bezierPathWithRect:NSMakeRect(hMargin, vMargin, size, size)]; - [NSGraphicsContext saveGraphicsState]; - QMacCGContext gc(&focusRingPixmap); - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(CGContextRef)gc - flipped:NO]]; - NSSetFocusRingStyle(NSFocusRingOnly); - [focusRingPath fill]; + } else { + const CGFloat outerClipInset = -focusRingWidth / 2; + NSBezierPath *focusRingClipPath = [NSBezierPath bezierPathWithRect:CGRectInset(focusRingRect, outerClipInset, outerClipInset)]; + const CGFloat innerClipInset = 1; + NSBezierPath *focusRingInnerClipPath = [NSBezierPath bezierPathWithRect:CGRectInset(focusRingRect, innerClipInset, innerClipInset)]; + [focusRingClipPath appendBezierPath:focusRingInnerClipPath.bezierPathByReversingPath]; + [focusRingClipPath setClip]; + focusRingPath = [NSBezierPath bezierPathWithRect:focusRingRect]; + focusRingPath.lineJoinStyle = NSRoundLineJoinStyle; + } + + focusRingPath.lineWidth = focusRingWidth; + [[NSColor keyboardFocusIndicatorColor] setStroke]; + [focusRingPath stroke]; + + CGContextEndTransparencyLayer(ctx); [NSGraphicsContext restoreGraphicsState]; } QPixmapCache::insert(key, focusRingPixmap); @@ -1312,8 +1331,6 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem bdi->adornment = kThemeAdornmentFocus; if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) bdi->state = kThemeStatePressed; - else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) - bdi->state = kThemeStateActive; else bdi->state = tds; @@ -1634,7 +1651,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti || slider->tickPosition == QSlider::TicksBothSides; tdi->bounds = qt_hirectForQRect(slider->rect); - if (isScrollbar || QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) { + if (isScrollbar) { tdi->min = slider->minimum; tdi->max = slider->maximum; tdi->value = slider->sliderPosition; @@ -1946,7 +1963,6 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD const bool button = opt->type == QStyleOption::SO_Button; const bool viewItem = opt->type == QStyleOption::SO_ViewItem; const bool pressed = bdi->state == kThemeStatePressed; - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; if (button && pressed) { if (bdi->kind == kThemePushButton) { @@ -1985,7 +2001,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); if (button && pressed) bdi->state = kThemeStateActive; - else if (usingYosemiteOrLater && viewItem) + else if (viewItem) bdi->state = kThemeStateInactive; HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); } @@ -1993,34 +2009,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD if (!combo && !button && bdi->value == kThemeButtonOff) { pm = activePixmap; - } else if (!usingYosemiteOrLater && (combo || button)) { - 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 darkest = qRed(pixel); - int mid = qGreen(pixel); - int lightest = qBlue(pixel); - - if (darkest > mid) - qSwap(darkest, mid); - if (mid > lightest) - qSwap(mid, lightest); - if (darkest > mid) - qSwap(darkest, mid); - - int gray = (mid + 2 * lightest) / 3; - if (pressed) - gray *= 0.88; - pixel = qRgba(gray, gray, gray, qAlpha(pixel)); - } - } - pm = QPixmap::fromImage(image); - } else if ((usingYosemiteOrLater && combo && !editableCombo) || button) { + } else if ((combo && !editableCombo) || button) { QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi->kind); NSButton *bc = (NSButton *)cocoaControl(cw); [bc highlight:pressed]; @@ -2034,7 +2023,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD rect.adjust(0, 0, -5, 0); drawNSViewInRect(cw, bc, rect, p); return; - } else if (usingYosemiteOrLater && (editableCombo || viewItem)) { + } else if (editableCombo || viewItem) { QImage image = activePixmap.toImage(); for (int y = 0; y < height; ++y) { @@ -3100,23 +3089,6 @@ QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOpt return icon.pixmap(qt_getWindow(widget), QSize(size, size)); } -void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) -{ - switch (policy) { - case FocusDefault: - break; - case FocusEnabled: - case FocusDisabled: - w->setAttribute(Qt::WA_MacShowFocusRect, policy == FocusEnabled); - break; - } -} - -QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) -{ - return w->testAttribute(Qt::WA_MacShowFocusRect) ? FocusEnabled : FocusDisabled; -} - void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) { QWidget *wadget = const_cast<QWidget *>(widget); @@ -3317,32 +3289,60 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai } break; case PE_IndicatorMenuCheckMark: { - const int checkw = 8; - const int checkh = 8; - const int xoff = qMax(0, (opt->rect.width() - checkw) / 2); - const int yoff = qMax(0, (opt->rect.width() - checkh) / 2); - const int x1 = xoff + opt->rect.x(); - const int y1 = yoff + opt->rect.y() + checkw/2; - const int x2 = xoff + opt->rect.x() + checkw/4; - const int y2 = yoff + opt->rect.y() + checkh; - const int x3 = xoff + opt->rect.x() + checkw; - const int y3 = yoff + opt->rect.y(); - - QVector<QLineF> a(2); - a << QLineF(x1, y1, x2, y2); - a << QLineF(x2, y2, x3, y3); - if (opt->palette.currentColorGroup() == QPalette::Active) { - if (opt->state & State_On) - p->setPen(QPen(opt->palette.highlightedText().color(), 3)); - else - p->setPen(QPen(opt->palette.text().color(), 3)); - } else { - p->setPen(QPen(QColor(100, 100, 100), 3)); - } - p->save(); - p->setRenderHint(QPainter::Antialiasing); - p->drawLines(a); - p->restore(); + if (!(opt->state & State_On)) + break; + QColor pc; + if (opt->state & State_Selected) + pc = opt->palette.highlightedText().color(); + else + pc = opt->palette.text().color(); + QCFType<CGColorRef> checkmarkColor = CGColorCreateGenericRGB(static_cast<CGFloat>(pc.redF()), + static_cast<CGFloat>(pc.greenF()), + static_cast<CGFloat>(pc.blueF()), + static_cast<CGFloat>(pc.alphaF())); + // kCTFontUIFontSystem and others give the same result + // as kCTFontUIFontMenuItemMark. However, the latter is + // more reminiscent to HITheme's kThemeMenuItemMarkFont. + // See also the font for small- and mini-sized widgets, + // where we end up using the generic system font type. + const CTFontUIFontType fontType = (opt->state & State_Mini) ? kCTFontUIFontMiniSystem : + (opt->state & State_Small) ? kCTFontUIFontSmallSystem : + kCTFontUIFontMenuItemMark; + // Similarly for the font size, where there is a small difference + // between regular combobox and item view items, and and menu items. + // However, we ignore any difference for small- and mini-sized widgets. + const CGFloat fontSize = fontType == kCTFontUIFontMenuItemMark ? opt->fontMetrics.height() : 0.0; + QCFType<CTFontRef> checkmarkFont = CTFontCreateUIFontForLanguage(fontType, fontSize, NULL); + + CGContextSaveGState(cg); + CGContextSetShouldSmoothFonts(cg, NO); // Same as HITheme and Cocoa menu checkmarks + + // Baseline alignment tweaks for QComboBox and QMenu + const CGFloat vOffset = (opt->state & State_Mini) ? 0.0 : + (opt->state & State_Small) ? 1.0 : + 0.75; + + CGContextTranslateCTM(cg, 0, opt->rect.bottom()); + CGContextScaleCTM(cg, 1, -1); + // Translate back to the original position and add rect origin and offset + CGContextTranslateCTM(cg, opt->rect.x(), vOffset); + + // CTFont has severe difficulties finding the checkmark character among its + // glyphs. Fortunately, CTLine knows its ways inside the Cocoa labyrinth. + static const CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; + static const int numValues = sizeof(keys) / sizeof(keys[0]); + const CFTypeRef values[] = { (CFTypeRef)checkmarkFont, (CFTypeRef)checkmarkColor }; + Q_STATIC_ASSERT((sizeof(values) / sizeof(values[0])) == numValues); + QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, + numValues, NULL, NULL); + // U+2713: CHECK MARK + QCFType<CFAttributedStringRef> checkmarkString = CFAttributedStringCreate(kCFAllocatorDefault, (CFStringRef)@"\u2713", attributes); + QCFType<CTLineRef> line = CTLineCreateWithAttributedString(checkmarkString); + + CTLineDraw((CTLineRef)line, cg); + CGContextFlush(cg); // CTLineDraw's documentation says it doesn't flush + + CGContextRestoreGState(cg); break; } case PE_IndicatorViewItemCheck: case PE_IndicatorRadioButton: @@ -3581,7 +3581,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { @@ -3802,10 +3801,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // takes precedence over a normal default button if (btn->features & QStyleOptionButton::AutoDefaultButton && opt->state & State_Active && opt->state & State_HasFocus) { - if (usingYosemiteOrLater) - d->autoDefaultButton = opt->styleObject; - else - d->setAutoDefaultButton(opt->styleObject); + d->autoDefaultButton = opt->styleObject; } else if (d->autoDefaultButton == opt->styleObject) { d->setAutoDefaultButton(0); } @@ -3813,8 +3809,6 @@ 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 (!usingYosemiteOrLater && !d->animation(opt->styleObject)) - d->startAnimation(new QStyleAnimation(opt->styleObject)); } else if (d->defaultButton == opt->styleObject) { if (QStyleAnimation *animation = d->animation(opt->styleObject)) { animation->updateTarget(); @@ -3835,42 +3829,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIThemeButtonDrawInfo bdi; d->initHIThemePushButton(btn, w, tds, &bdi); - if (usingYosemiteOrLater) { - if (!hasMenu) { - // 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; - } - } 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(); - } - } + if (!hasMenu) { + // 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; } // Unlike Carbon, we want the button to always be drawn inside its bounds. @@ -3888,7 +3858,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; } - if (hasMenu && usingYosemiteOrLater && bdi.kind != kThemeBevelButton) { + if (hasMenu && bdi.kind != kThemeBevelButton) { QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); cw.first = QCocoaPullDownButton; NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); @@ -3902,7 +3872,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); - if (usingYosemiteOrLater && btn->state & State_HasFocus) { + if (btn->state & State_HasFocus) { CGRect focusRect = newRect; if (bdi.kind == kThemePushButton) focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. @@ -3932,7 +3902,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); } - if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) { + if (hasMenu && bdi.kind == kThemeBevelButton) { int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); QRect ir = btn->rect; int arrowXOffset = bdi.kind == kThemePushButton ? 6 : @@ -3973,7 +3943,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter bool hasIcon = !btn.icon.isNull(); bool hasText = !btn.text.isEmpty(); - if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { + if (!hasMenu) { if (tds == kThemeStatePressed || (tds == kThemeStateActive && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) @@ -4077,10 +4047,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { QStyleOptionComboBox comboCopy = *cb; comboCopy.direction = Qt::LeftToRight; - if (opt->state & QStyle::State_Small) - comboCopy.rect.translate(0, w ? 0 : (QSysInfo::macVersion() >= QSysInfo::MV_10_10 ? 0 : -2)); // Supports Qt Quick Controls - else if (QSysInfo::macVersion() == QSysInfo::MV_10_9) - comboCopy.rect.translate(0, 1); QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); } break; @@ -4143,12 +4109,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.adornment = kHIThemeTabAdornmentNone; tdi.kind = kHIThemeTabKindNormal; - 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) { @@ -4212,15 +4172,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QStyleOptionTab myTab = *tab; ThemeTabDirection ttd = getTabDirection(myTab.shape); bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; - bool selected = (myTab.state & QStyle::State_Selected); // 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"); - bool isSelectedAndNeedsShadow = selected && !usingYosemiteOrLater; - if (isSelectedAndNeedsShadow || verticalTabs || nonDefaultFont || !tab->icon.isNull() + if (verticalTabs || nonDefaultFont || !tab->icon.isNull() || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) { int heightOffset = 0; if (verticalTabs) { @@ -4231,7 +4189,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } myTab.rect.setHeight(myTab.rect.height() + heightOffset); - if (myTab.documentMode || isSelectedAndNeedsShadow) { + if (myTab.documentMode) { p->save(); rotateTabPainter(p, myTab.shape, myTab.rect); @@ -4427,61 +4385,27 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter p->setPen(mi->palette.buttonText().color()); if (mi->checked) { - // Use the HIThemeTextInfo foo to draw the check mark correctly, if we do it, - // we somehow need to use a special encoding as it doesn't look right with our - // drawText(). - p->save(); - CGContextSetShouldAntialias(cg, true); - CGContextSetShouldSmoothFonts(cg, true); - QColor textColor = p->pen().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()); - CGContextSetFillColor(cg, colorComp); - HIThemeTextInfo tti; - tti.version = qt_mac_hitheme_version; - tti.state = tds; - if (active && enabled) - tti.state = kThemeStatePressed; - switch (widgetSize) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - tti.fontID = kThemeMenuItemMarkFont; - break; - case QAquaSizeSmall: - tti.fontID = kThemeSmallSystemFont; - break; - case QAquaSizeMini: - tti.fontID = kThemeMiniSystemFont; - break; - } - tti.horizontalFlushness = kHIThemeTextHorizontalFlushLeft; - tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; - tti.options = kHIThemeTextBoxOptionNone; - tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1; - QCFString checkmark; -#if 0 - if (mi->checkType == QStyleOptionMenuItem::Exclusive) - checkmark = QString(QChar(kDiamondUnicode)); - else -#endif - checkmark = QString(QChar(kCheckUnicode)); - int mw = checkcol + macItemFrame; - int mh = contentRect.height() - 2 * macItemFrame; - int xp = contentRect.x(); - xp += macItemFrame; - CGFloat outWidth, outHeight, outBaseline; - HIThemeGetTextDimensions(checkmark, 0, &tti, &outWidth, &outHeight, - &outBaseline); + QStyleOption checkmarkOpt; + checkmarkOpt.initFrom(w); + + const int mw = checkcol + macItemFrame; + const int mh = contentRect.height() + macItemFrame; + const int xp = contentRect.x() + macItemFrame; + checkmarkOpt.rect = QRect(xp, contentRect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh); + + checkmarkOpt.state |= State_On; // Always on. Never rendered when off. + checkmarkOpt.state.setFlag(State_Selected, active); + checkmarkOpt.state.setFlag(State_Enabled, enabled); if (widgetSize == QAquaSizeMini) - outBaseline += 1; - QRect r(xp, contentRect.y(), mw, mh); - r.translate(0, p->fontMetrics().ascent() - int(outBaseline) + 1); - HIRect bounds = qt_hirectForQRect(r); - HIThemeDrawTextBox(checkmark, &bounds, &tti, - cg, kHIThemeOrientationNormal); - p->restore(); + checkmarkOpt.state |= State_Mini; + else if (widgetSize == QAquaSizeSmall) + checkmarkOpt.state |= State_Small; + + // We let drawPrimitive(PE_IndicatorMenuCheckMark) pick the right color + checkmarkOpt.palette.setColor(QPalette::HighlightedText, p->pen().color()); + checkmarkOpt.palette.setColor(QPalette::Text, p->pen().color()); + + proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &checkmarkOpt, p, w); } if (!mi->icon.isNull()) { QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal @@ -4654,7 +4578,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.value = pb->progress; tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) { + if (isIndeterminate) { if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) tdi.trackInfo.progress.phase = animation->animationStep(); else if (opt->styleObject) @@ -4736,8 +4660,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIThemeSplitterDrawInfo sdi; sdi.version = qt_mac_hitheme_version; sdi.state = tds; - sdi.adornment = qt_mac_is_metal(w) || usingYosemiteOrLater ? - kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone; + sdi.adornment = kHIThemeSplitterAdornmentMetal; HIRect hirect = qt_hirectForQRect(opt->rect); HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); } else { @@ -5287,7 +5210,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; switch (cc) { case CC_Slider: case CC_ScrollBar: @@ -5380,7 +5302,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex int oldMin = styleObject->property("_q_stylemin").toInt(); int oldMax = styleObject->property("_q_stylemax").toInt(); QRect oldRect = styleObject->property("_q_stylerect").toRect(); - int oldState = styleObject->property("_q_stylestate").toInt(); + QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>()); uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); // a scrollbar is transient when the scrollbar itself and @@ -5403,7 +5325,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex styleObject->setProperty("_q_stylemin", slider->minimum); styleObject->setProperty("_q_stylemax", slider->maximum); styleObject->setProperty("_q_stylerect", slider->rect); - styleObject->setProperty("_q_stylestate", static_cast<int>(slider->state)); + styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(slider->state)); styleObject->setProperty("_q_stylecontrols", static_cast<uint>(slider->activeSubControls)); QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject)); @@ -5532,7 +5454,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } else { d->stopAnimation(opt->styleObject); - if (usingYosemiteOrLater && cc == CC_Slider) { + if (cc == CC_Slider) { // Fix min and max positions. (See also getSliderInfo() // for the slider values adjustments.) // HITheme seems to have forgotten how to render @@ -5595,22 +5517,20 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { HIRect bounds; - if (usingYosemiteOrLater) { - // As part of fixing the min and max positions, - // we need to adjust the tickmarks as well - bounds = tdi.bounds; - if (slider->orientation == Qt::Horizontal) { - tdi.bounds.size.width += 2; - tdi.bounds.origin.x -= 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) - tdi.bounds.origin.y -= 2; - } else { - tdi.bounds.size.height += 3; - tdi.bounds.origin.y -= 3; - tdi.bounds.origin.y += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left - tdi.bounds.origin.x -= 2; - } + // As part of fixing the min and max positions, + // we need to adjust the tickmarks as well + bounds = tdi.bounds; + if (slider->orientation == Qt::Horizontal) { + tdi.bounds.size.width += 2; + tdi.bounds.origin.x -= 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) + tdi.bounds.origin.y -= 2; + } else { + tdi.bounds.size.height += 3; + tdi.bounds.origin.y -= 3; + tdi.bounds.origin.y += 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left + tdi.bounds.origin.x -= 2; } if (qt_mac_is_metal(widget)) { @@ -5634,10 +5554,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex cg, kHIThemeOrientationNormal); tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; - if (usingYosemiteOrLater) { - if (slider->orientation == Qt::Vertical) - tdi.bounds.origin.x -= 2; - } + // 10.10 and above need a slight shift + if (slider->orientation == Qt::Vertical) + tdi.bounds.origin.x -= 2; HIThemeDrawTrackTickMarks(&tdi, numMarks, cg, kHIThemeOrientationNormal); @@ -5649,11 +5568,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex kHIThemeOrientationNormal); } - if (usingYosemiteOrLater) - tdi.bounds = bounds; + tdi.bounds = bounds; } - if (usingYosemiteOrLater && cc == CC_Slider) { + if (cc == CC_Slider) { // Still as part of fixing the min and max positions, // we also adjust the knob position. We can do this // because it's rendered separately from the track. @@ -5745,11 +5663,11 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex HIThemeButtonDrawInfo bdi; d->initComboboxBdi(combo, &bdi, widget, tds); HIRect rect = qt_hirectForQRect(combo->rect); - if (combo->editable && usingYosemiteOrLater) + if (combo->editable) rect.origin.y += tds == kThemeStateInactive ? 1 : 2; if (tds != kThemeStateInactive) QMacStylePrivate::drawCombobox(rect, bdi, p); - else if (!widget && combo->editable && usingYosemiteOrLater) { + else if (!widget && combo->editable) { QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); NSView *cb = d->cocoaControl(cw); QRect r = combo->rect.adjusted(3, 0, 0, 0); @@ -5931,31 +5849,23 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex drawToolbarButtonArrow(tb->rect, tds, cg); } if (tb->state & State_On) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { - QWindow *window = 0; - if (widget && widget->window()) - window = widget->window()->windowHandle(); - else if (opt->styleObject) - window = opt->styleObject->property("_q_styleObjectWindow").value<QWindow *>(); - - NSView *view = window ? (NSView *)window->winId() : nil; - bool isKey = false; - if (view) - isKey = [view.window isKeyWindow]; - - QBrush brush(isKey ? QColor(0, 0, 0, 28) - : QColor(0, 0, 0, 21)); - QPainterPath path; - path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); - p->setRenderHint(QPainter::Antialiasing); - p->fillPath(path, brush); - } else { - static QPixmap pm(QLatin1String(":/qt-project.org/mac/style/images/leopard-unified-toolbar-on.png")); - p->save(); - p->setRenderHint(QPainter::SmoothPixmapTransform); - QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2); - p->restore(); - } + QWindow *window = 0; + if (widget && widget->window()) + window = widget->window()->windowHandle(); + else if (opt->styleObject) + window = opt->styleObject->property("_q_styleObjectWindow").value<QWindow *>(); + + NSView *view = window ? (NSView *)window->winId() : nil; + bool isKey = false; + if (view) + isKey = [view.window isKeyWindow]; + + QBrush brush(isKey ? QColor(0, 0, 0, 28) + : QColor(0, 0, 0, 21)); + QPainterPath path; + path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); + p->setRenderHint(QPainter::Antialiasing); + p->fillPath(path, brush); } proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); } else { @@ -6295,8 +6205,8 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op switch (sc) { case SC_ComboBoxEditField:{ ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) - ret.setHeight(ret.height() - 1); + // 10.10 and above need a slight shift + ret.setHeight(ret.height() - 1); break; } case SC_ComboBoxArrow:{ ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); @@ -6754,7 +6664,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_ComboBox: { sz.rwidth() += 50; const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable)) + if (cb && !cb->editable) sz.rheight() += 2; break; } diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h index 3642424a14..98a9063bf0 100644 --- a/src/widgets/styles/qmacstyle_mac_p.h +++ b/src/widgets/styles/qmacstyle_mac_p.h @@ -100,10 +100,6 @@ public: virtual int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, QStyleHintReturn *shret = 0) const; - enum FocusRectPolicy { FocusEnabled, FocusDisabled, FocusDefault }; - static void setFocusRectPolicy(QWidget *w, FocusRectPolicy policy); - static FocusRectPolicy focusRectPolicy(const QWidget *w); - enum WidgetSizePolicy { SizeSmall, SizeLarge, SizeMini, SizeDefault }; diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 7f52d3d2f3..972deef150 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -39,6 +39,7 @@ #include "qwindowsvistastyle_p.h" #include "qwindowsvistastyle_p_p.h" +#include <qoperatingsystemversion.h> #include <qscreen.h> #include <qwindow.h> #include <private/qstyleanimation_p.h> @@ -1752,7 +1753,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle theme.stateId = stateId; d->drawBackground(theme); - if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) { const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index f999d823e0..f50c143a4a 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -397,13 +397,7 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) return topLevelHwnd; } - if (QDesktopWidget *desktop = qApp->desktop()) - if (const HWND desktopHwnd = QApplicationPrivate::getHWNDForWidget(desktop)) - return desktopHwnd; - - Q_ASSERT(false); - - return 0; + return GetDesktopWindow(); } /*! \internal diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index f7464d50ec..83c1764f38 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -59,6 +59,25 @@ QT_BEGIN_NAMESPACE +static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon) +{ + QStyle::StandardPixmap stdIcon = QStyle::SP_CustomBase; // silence gcc 4.9.0 about uninited variable + switch (icon) { + case QSystemTrayIcon::Information: + stdIcon = QStyle::SP_MessageBoxInformation; + break; + case QSystemTrayIcon::Warning: + stdIcon = QStyle::SP_MessageBoxWarning; + break; + case QSystemTrayIcon::Critical: + stdIcon = QStyle::SP_MessageBoxCritical; + break; + case QSystemTrayIcon::NoIcon: + return QIcon(); + } + return QApplication::style()->standardIcon(stdIcon); +} + /*! \class QSystemTrayIcon \brief The QSystemTrayIcon class provides an icon for an application in the system tray. @@ -382,11 +401,29 @@ bool QSystemTrayIcon::supportsMessages() \sa show(), supportsMessages() */ void QSystemTrayIcon::showMessage(const QString& title, const QString& msg, - QSystemTrayIcon::MessageIcon icon, int msecs) + QSystemTrayIcon::MessageIcon msgIcon, int msecs) +{ + Q_D(QSystemTrayIcon); + if (d->visible) + d->showMessage_sys(title, msg, messageIcon2qIcon(msgIcon), msgIcon, msecs); +} + +/*! + \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon &icon, int millisecondsTimeoutHint) + + \overload showMessage() + + Shows a balloon message for the entry with the given \a title, \a message, + and custom icon \a icon for the time specified in \a millisecondsTimeoutHint. + + \since 5.9 +*/ +void QSystemTrayIcon::showMessage(const QString &title, const QString &msg, + const QIcon &icon, int msecs) { Q_D(QSystemTrayIcon); if (d->visible) - d->showMessage_sys(title, msg, icon, msecs); + d->showMessage_sys(title, msg, icon, QSystemTrayIcon::NoIcon, msecs); } void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason) @@ -398,9 +435,9 @@ void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::Activatio ////////////////////////////////////////////////////////////////////// static QBalloonTip *theSolitaryBalloonTip = 0; -void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow) +void QBalloonTip::showBalloon(const QIcon &icon, const QString &title, + const QString &message, QSystemTrayIcon *trayIcon, + const QPoint &pos, int timeout, bool showArrow) { hideBalloon(); if (message.isEmpty() && title.isEmpty()) @@ -434,8 +471,8 @@ bool QBalloonTip::isBalloonVisible() return theSolitaryBalloonTip; } -QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *ti) +QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title, + const QString &message, QSystemTrayIcon *ti) : QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1), @@ -485,26 +522,10 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit)); } - QIcon si; - switch (icon) { - case QSystemTrayIcon::Warning: - si = style()->standardIcon(QStyle::SP_MessageBoxWarning); - break; - case QSystemTrayIcon::Critical: - si = style()->standardIcon(QStyle::SP_MessageBoxCritical); - break; - case QSystemTrayIcon::Information: - si = style()->standardIcon(QStyle::SP_MessageBoxInformation); - break; - case QSystemTrayIcon::NoIcon: - default: - break; - } - QGridLayout *layout = new QGridLayout; - if (!si.isNull()) { + if (!icon.isNull()) { QLabel *iconLabel = new QLabel; - iconLabel->setPixmap(si.pixmap(iconSize, iconSize)); + iconLabel->setPixmap(icon.pixmap(iconSize, iconSize)); iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); iconLabel->setMargin(2); layout->addWidget(iconLabel, 0, 0); @@ -681,54 +702,6 @@ void QSystemTrayIconPrivate::remove_sys_qpa() qpa_sys->cleanup(); } -QRect QSystemTrayIconPrivate::geometry_sys_qpa() const -{ - return qpa_sys->geometry(); -} - -void QSystemTrayIconPrivate::updateIcon_sys_qpa() -{ - qpa_sys->updateIcon(icon); -} - -void QSystemTrayIconPrivate::updateMenu_sys_qpa() -{ -#if QT_CONFIG(menu) - if (menu) { - addPlatformMenu(menu); - qpa_sys->updateMenu(menu->platformMenu()); - } -#endif -} - -void QSystemTrayIconPrivate::updateToolTip_sys_qpa() -{ - qpa_sys->updateToolTip(toolTip); -} - -void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &title, - const QString &message, - QSystemTrayIcon::MessageIcon icon, - int msecs) -{ - QIcon notificationIcon; - switch (icon) { - case QSystemTrayIcon::Information: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - break; - case QSystemTrayIcon::Warning: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); - break; - case QSystemTrayIcon::Critical: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); - break; - default: - break; - } - qpa_sys->showMessage(title, message, notificationIcon, - static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs); -} - void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const { #if QT_CONFIG(menu) diff --git a/src/widgets/util/qsystemtrayicon.h b/src/widgets/util/qsystemtrayicon.h index fb238c92b0..918dd0478e 100644 --- a/src/widgets/util/qsystemtrayicon.h +++ b/src/widgets/util/qsystemtrayicon.h @@ -101,6 +101,7 @@ public Q_SLOTS: void setVisible(bool visible); inline void show() { setVisible(true); } inline void hide() { setVisible(false); } + void showMessage(const QString &title, const QString &msg, const QIcon &icon, int msecs = 10000); void showMessage(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int msecs = 10000); diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h index 79e824f4b7..3f5cab40be 100644 --- a/src/widgets/util/qsystemtrayicon_p.h +++ b/src/widgets/util/qsystemtrayicon_p.h @@ -84,7 +84,8 @@ public: void updateToolTip_sys(); void updateMenu_sys(); QRect geometry_sys() const; - void showMessage_sys(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs); + void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon, + QSystemTrayIcon::MessageIcon msgIcon, int msecs); static bool isSystemTrayAvailable_sys(); static bool supportsMessages_sys(); @@ -101,11 +102,7 @@ public: private: void install_sys_qpa(); void remove_sys_qpa(); - void updateIcon_sys_qpa(); - void updateToolTip_sys_qpa(); - void updateMenu_sys_qpa(); - QRect geometry_sys_qpa() const; - void showMessage_sys_qpa(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs); + void addPlatformMenu(QMenu *menu) const; }; @@ -113,16 +110,16 @@ class QBalloonTip : public QWidget { Q_OBJECT public: - static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow = true); + static void showBalloon(const QIcon &icon, const QString &title, + const QString &msg, QSystemTrayIcon *trayIcon, + const QPoint &pos, int timeout, bool showArrow = true); static void hideBalloon(); static bool isBalloonVisible(); static void updateBalloonPosition(const QPoint& pos); private: - QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon); + QBalloonTip(const QIcon &icon, const QString &title, + const QString &msg, QSystemTrayIcon *trayIcon); ~QBalloonTip(); void balloon(const QPoint&, int, bool); diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp index 643f17a5fe..c0bf058681 100644 --- a/src/widgets/util/qsystemtrayicon_qpa.cpp +++ b/src/widgets/util/qsystemtrayicon_qpa.cpp @@ -76,7 +76,7 @@ void QSystemTrayIconPrivate::remove_sys() QRect QSystemTrayIconPrivate::geometry_sys() const { if (qpa_sys) - return geometry_sys_qpa(); + return qpa_sys->geometry(); else return QRect(); } @@ -84,19 +84,23 @@ QRect QSystemTrayIconPrivate::geometry_sys() const void QSystemTrayIconPrivate::updateIcon_sys() { if (qpa_sys) - updateIcon_sys_qpa(); + qpa_sys->updateIcon(icon); } void QSystemTrayIconPrivate::updateMenu_sys() { - if (qpa_sys) - updateMenu_sys_qpa(); +#if QT_CONFIG(menu) + if (qpa_sys && menu) { + addPlatformMenu(menu); + qpa_sys->updateMenu(menu->platformMenu()); + } +#endif } void QSystemTrayIconPrivate::updateToolTip_sys() { if (qpa_sys) - updateToolTip_sys_qpa(); + qpa_sys->updateToolTip(toolTip); } bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() @@ -118,10 +122,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys() } void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, - QSystemTrayIcon::MessageIcon icon, int msecs) + const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs) { if (qpa_sys) - showMessage_sys_qpa(title, message, icon, msecs); + qpa_sys->showMessage(title, message, icon, + static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs); } QT_END_NAMESPACE diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp index 2da24e482b..d110cb8be4 100644 --- a/src/widgets/util/qsystemtrayicon_win.cpp +++ b/src/widgets/util/qsystemtrayicon_win.cpp @@ -81,11 +81,14 @@ struct Q_NOTIFYICONIDENTIFIER { # define NIN_BALLOONTIMEOUT (WM_USER + 4) # define NIN_BALLOONUSERCLICK (WM_USER + 5) # define NIF_SHOWTIP 0x00000080 +# define NIIF_LARGE_ICON 0x00000020 # define NOTIFYICON_VERSION_4 4 #endif #define Q_MSGFLT_ALLOW 1 +Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &); + typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation); typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag); typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct); @@ -107,7 +110,7 @@ public: ~QSystemTrayIconSys(); bool trayMessage(DWORD msg); void setIconContents(NOTIFYICONDATA &data); - bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); + bool showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs); QRect findIconGeometry(UINT iconId); HICON createIcon(); bool winEvent(MSG *m, long *result); @@ -184,7 +187,7 @@ static inline HWND createTrayIconMessageWindow() QSystemTrayIconSys::QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object) : m_hwnd(hwnd), hIcon(0), q(object) - , notifyIconSize(NOTIFYICONDATA_V2_SIZE), version(NOTIFYICON_VERSION) + , notifyIconSize(sizeof(NOTIFYICONDATA)), version(NOTIFYICON_VERSION_4) , ignoreNextMouseRelease(false) { @@ -237,11 +240,7 @@ void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t)); } -#ifndef NIIF_LARGE_ICON -# define NIIF_LARGE_ICON 0x00000020 -#endif - -bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) +bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs) { NOTIFYICONDATA tnd; memset(&tnd, 0, notifyIconSize); @@ -249,23 +248,32 @@ bool QSystemTrayIconSys::showMessage(const QString &title, const QString &messag qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64); tnd.uID = q_uNOTIFYICONID; - switch (type) { - case QSystemTrayIcon::Information: + tnd.dwInfoFlags = NIIF_USER; + + HICON *phIcon = &tnd.hIcon; + QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + if (version == NOTIFYICON_VERSION_4) { + const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); + QSize more = icon.actualSize(largeIcon); + if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) { + tnd.dwInfoFlags |= NIIF_LARGE_ICON; + size = largeIcon; + } + phIcon = &tnd.hBalloonIcon; + } + QPixmap pm = icon.pixmap(size); + if (pm.isNull()) { tnd.dwInfoFlags = NIIF_INFO; - break; - case QSystemTrayIcon::Warning: - tnd.dwInfoFlags = NIIF_WARNING; - break; - case QSystemTrayIcon::Critical: - tnd.dwInfoFlags = NIIF_ERROR; - break; - case QSystemTrayIcon::NoIcon: - tnd.dwInfoFlags = hIcon ? NIIF_USER : NIIF_NONE; - break; + } else { + if (pm.size() != size) { + qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d", + pm.size().width(), pm.size().height(), size.width(), size.height()); + pm = pm.scaled(size, Qt::IgnoreAspectRatio); + } + *phIcon = qt_pixmapToWinHICON(pm); } - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - tnd.dwInfoFlags |= NIIF_LARGE_ICON; tnd.cbSize = notifyIconSize; + tnd.uVersion = version; tnd.hWnd = m_hwnd; tnd.uTimeout = uSecs; tnd.uFlags = NIF_INFO | NIF_SHOWTIP; @@ -296,8 +304,6 @@ bool QSystemTrayIconSys::trayMessage(DWORD msg) return success; } -Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &); - HICON QSystemTrayIconSys::createIcon() { const HICON oldIcon = hIcon; @@ -509,7 +515,8 @@ QRect QSystemTrayIconSys::findIconGeometry(UINT iconId) void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &messageIn, - QSystemTrayIcon::MessageIcon type, + const QIcon &icon, + QSystemTrayIcon::MessageIcon, int timeOut) { if (!sys || !allowsMessages()) @@ -522,7 +529,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, if (message.isEmpty() && !title.isEmpty()) message.append(QLatin1Char(' ')); - sys->showMessage(title, message, type, uSecs); + sys->showMessage(title, message, icon, uSecs); } QRect QSystemTrayIconPrivate::geometry_sys() const @@ -557,7 +564,8 @@ void QSystemTrayIconPrivate::updateIcon_sys() void QSystemTrayIconPrivate::updateMenu_sys() { - +#if QT_CONFIG(menu) +#endif } void QSystemTrayIconPrivate::updateToolTip_sys() diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index 0bde31fd61..ac6c14dc63 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -286,7 +286,7 @@ void QSystemTrayIconPrivate::install_sys() QRect QSystemTrayIconPrivate::geometry_sys() const { if (qpa_sys) - return geometry_sys_qpa(); + return qpa_sys->geometry(); if (!sys) return QRect(); return sys->globalGeometry(); @@ -309,7 +309,7 @@ void QSystemTrayIconPrivate::remove_sys() void QSystemTrayIconPrivate::updateIcon_sys() { if (qpa_sys) { - updateIcon_sys_qpa(); + qpa_sys->updateIcon(icon); return; } if (sys) @@ -318,14 +318,18 @@ void QSystemTrayIconPrivate::updateIcon_sys() void QSystemTrayIconPrivate::updateMenu_sys() { - if (qpa_sys) - updateMenu_sys_qpa(); +#if QT_CONFIG(menu) + if (qpa_sys && menu) { + addPlatformMenu(menu); + qpa_sys->updateMenu(menu->platformMenu()); + } +#endif } void QSystemTrayIconPrivate::updateToolTip_sys() { if (qpa_sys) { - updateToolTip_sys_qpa(); + qpa_sys->updateToolTip(toolTip); return; } if (!sys) @@ -359,10 +363,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys() } void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, - QSystemTrayIcon::MessageIcon icon, int msecs) + const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs) { if (qpa_sys) { - showMessage_sys_qpa(title, message, icon, msecs); + qpa_sys->showMessage(title, message, icon, + static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs); return; } if (!sys) diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 033d4e9e05..dc0b6855ac 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -145,6 +145,36 @@ QUndoCommand::~QUndoCommand() } /*! + \since 5.9 + + Returns whether the command is obsolete. + + The boolean is used for the automatic removal of commands that are not necessary in the + stack anymore. The isObsolete function is checked in the functions QUndoStack::push(), + QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex(). + + \sa setObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() +*/ + +bool QUndoCommand::isObsolete() const +{ + return d->obsolete; +} + +/*! + \since 5.9 + + Sets whether the command is obsolete to \a obsolete. + + \sa isObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() +*/ + +void QUndoCommand::setObsolete(bool obsolete) +{ + d->obsolete = obsolete; +} + +/*! Returns the ID of this command. A command ID is used in command compression. It must be an integer unique to @@ -390,6 +420,28 @@ const QUndoCommand *QUndoCommand::child(int index) const and to update the document's title to reflect that it contains unsaved changes. + \section1 Obsolete Commands + + QUndoStack is able to delete commands from the stack if the command is no + longer needed. One example may be to delete a command when two commands are + merged together in such a way that the merged command has no function. This + can be seen with move commands where the user moves their mouse to one part + of the screen and then moves it to the original position. The merged command + results in a mouse movement of 0. This command can be deleted since it serves + no purpose. Another example is with networking commands that fail due to connection + issues. In this case, the command is to be removed from the stack because the redo() + and undo() functions have no function since there was connection issues. + + A command can be marked obsolete with the QUndoCommand::setObsolete() function. + The QUndoCommand::isObsolete() flag is checked in QUndoStack::push(), + QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex() after calling + QUndoCommand::undo(), QUndoCommand::redo() and QUndoCommand:mergeWith() where + applicable. + + If a command is set obsolete and the clean index is greater than or equal to the + current command index, then the clean index will be reset when the command is + deleted from the stack. + \sa QUndoCommand, QUndoView */ @@ -563,6 +615,11 @@ void QUndoStack::clear() commands by calling QUndoCommand::mergeWith() on the most recently executed command. If QUndoCommand::mergeWith() returns \c true, \a cmd is deleted. + After calling QUndoCommand::redo() and, if applicable, QUndoCommand::mergeWith(), + QUndoCommand::isObsolete() will be called for \a cmd or the merged command. + If QUndoCommand::isObsolete() returns \c true, then \a cmd or the merged command + will be deleted from the stack. + In all other cases \a cmd is simply pushed on the stack. If commands were undone before \a cmd was pushed, the current command and @@ -580,7 +637,8 @@ void QUndoStack::clear() void QUndoStack::push(QUndoCommand *cmd) { Q_D(QUndoStack); - cmd->redo(); + if (!cmd->isObsolete()) + cmd->redo(); bool macro = !d->macro_stack.isEmpty(); @@ -605,13 +663,25 @@ void QUndoStack::push(QUndoCommand *cmd) if (try_merge && cur->mergeWith(cmd)) { delete cmd; - if (!macro) { - emit indexChanged(d->index); - emit canUndoChanged(canUndo()); - emit undoTextChanged(undoText()); - emit canRedoChanged(canRedo()); - emit redoTextChanged(redoText()); + + if (macro) { + if (cur->isObsolete()) + delete d->macro_stack.constLast()->d->child_list.takeLast(); + } else { + if (cur->isObsolete()) { + delete d->command_list.takeLast(); + + d->setIndex(d->index - 1, false); + } else { + emit indexChanged(d->index); + emit canUndoChanged(canUndo()); + emit undoTextChanged(undoText()); + emit canRedoChanged(canRedo()); + emit redoTextChanged(redoText()); + } } + } else if (cmd->isObsolete()) { + delete cmd; // command should be deleted and NOT added to the stack } else { if (macro) { d->macro_stack.constLast()->d->child_list.append(cmd); @@ -712,6 +782,11 @@ int QUndoStack::cleanIndex() const If the stack is empty, or if the bottom command on the stack has already been undone, this function does nothing. + After the command is undone, if QUndoCommand::isObsolete() returns \c true, + then the command will be deleted from the stack. Additionally, if the clean + index is greater than or equal to the current command index, then the clean + index is reset. + \sa redo(), index() */ @@ -727,7 +802,18 @@ void QUndoStack::undo() } int idx = d->index - 1; - d->command_list.at(idx)->undo(); + QUndoCommand *cmd = d->command_list.at(idx); + + if (!cmd->isObsolete()) + cmd->undo(); + + if (cmd->isObsolete()) { // A separate check is done b/c the undo command may set obsolete flag + delete d->command_list.takeAt(idx); + + if (d->clean_index > idx) + resetClean(); + } + d->setIndex(idx, false); } @@ -738,6 +824,11 @@ void QUndoStack::undo() If the stack is empty, or if the top command on the stack has already been redone, this function does nothing. + If QUndoCommand::isObsolete() returns true for the current command, then + the command will be deleted from the stack. Additionally, if the clean + index is greater than or equal to the current command index, then the clean + index is reset. + \sa undo(), index() */ @@ -752,8 +843,20 @@ void QUndoStack::redo() return; } - d->command_list.at(d->index)->redo(); - d->setIndex(d->index + 1, false); + int idx = d->index; + QUndoCommand *cmd = d->command_list.at(idx); + + if (!cmd->isObsolete()) + cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag + + if (cmd->isObsolete()) { + delete d->command_list.takeAt(idx); + + if (d->clean_index > idx) + resetClean(); + } else { + d->setIndex(d->index + 1, false); + } } /*! @@ -805,10 +908,35 @@ void QUndoStack::setIndex(int idx) idx = d->command_list.size(); int i = d->index; - while (i < idx) - d->command_list.at(i++)->redo(); - while (i > idx) - d->command_list.at(--i)->undo(); + while (i < idx) { + QUndoCommand *cmd = d->command_list.at(i); + + if (!cmd->isObsolete()) + cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag + + if (cmd->isObsolete()) { + delete d->command_list.takeAt(i); + + if (d->clean_index > i) + resetClean(); + + idx--; // Subtract from idx because we removed a command + } else { + i++; + } + } + + while (i > idx) { + QUndoCommand *cmd = d->command_list.at(--i); + + cmd->undo(); + if (cmd->isObsolete()) { + delete d->command_list.takeAt(i); + + if (d->clean_index > i) + resetClean(); + } + } d->setIndex(idx, false); } diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h index ca918b0618..2a8f4decb6 100644 --- a/src/widgets/util/qundostack.h +++ b/src/widgets/util/qundostack.h @@ -69,6 +69,9 @@ public: QString actionText() const; void setText(const QString &text); + bool isObsolete() const; + void setObsolete(bool obsolete); + virtual int id() const; virtual bool mergeWith(const QUndoCommand *other); diff --git a/src/widgets/util/qundostack_p.h b/src/widgets/util/qundostack_p.h index 1bfe992426..e92a1fe620 100644 --- a/src/widgets/util/qundostack_p.h +++ b/src/widgets/util/qundostack_p.h @@ -66,11 +66,12 @@ class QUndoGroup; class QUndoCommandPrivate { public: - QUndoCommandPrivate() : id(-1) {} + QUndoCommandPrivate() : id(-1), obsolete(false) {} QList<QUndoCommand*> child_list; QString text; QString actionText; int id; + bool obsolete; }; #ifndef QT_NO_UNDOSTACK diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 35b9851cad..d091d1e970 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -638,7 +638,6 @@ QWidget *QAbstractScrollArea::viewport() const Returns the size of the viewport as if the scroll bars had no valid scrolling range. */ -// ### still thinking about the name QSize QAbstractScrollArea::maximumViewportSize() const { Q_D(const QAbstractScrollArea); diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index cc6a407bf8..0ea9250695 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -303,9 +303,7 @@ void QAbstractSlider::setOrientation(Qt::Orientation orientation) d->orientation = orientation; if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy(sp); + setSizePolicy(sizePolicy().transposed()); setAttribute(Qt::WA_WState_OwnSizePolicy, false); } update(); diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 8ccad5c35d..6bcdc372ef 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -2114,8 +2114,8 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant default: Q_ASSERT_X(0, "QAbstractSpinBoxPrivate::variantCompare", qPrintable(QString::fromLatin1("Internal error 3 (%1 %2)"). - arg(QString::fromLatin1(arg1.typeName())). - arg(QString::fromLatin1(arg2.typeName())))); + arg(QString::fromLatin1(arg1.typeName()), + QString::fromLatin1(arg2.typeName())))); } return -2; } diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index b0ded70c4a..da4850a816 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -765,7 +765,7 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e) if (m_widget) { if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { QKeyEvent* ke = (QKeyEvent*)e; - if ((ke->text().length() > 0 && ke->text()[0].isPrint()) || m_dateFrame) { + if ((ke->text().length() > 0 && ke->text().at(0).isPrint()) || m_dateFrame) { if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Select) { applyDate(); emit editingFinished(); diff --git a/src/widgets/widgets/qdatetimeedit.h b/src/widgets/widgets/qdatetimeedit.h index 5c9f4e0f9d..b54b0e7cf0 100644 --- a/src/widgets/widgets/qdatetimeedit.h +++ b/src/widgets/widgets/qdatetimeedit.h @@ -58,7 +58,6 @@ class Q_WIDGETS_EXPORT QDateTimeEdit : public QAbstractSpinBox { Q_OBJECT - Q_FLAGS(Sections) Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged USER true) Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged) Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged) @@ -92,6 +91,7 @@ public: Q_ENUM(Section) Q_DECLARE_FLAGS(Sections, Section) + Q_FLAG(Sections) explicit QDateTimeEdit(QWidget *parent = Q_NULLPTR); explicit QDateTimeEdit(const QDateTime &dt, QWidget *parent = Q_NULLPTR); diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index 23158cf82f..61ef8e8c93 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -411,12 +411,7 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut else addButton(button, static_cast<QDialogButtonBox::ButtonRole>(role), doLayout); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Since mnemonics is off by default on Mac, we add a Cmd-D - // shortcut here to e.g. make the "Don't Save" button work nativly: - if (sbutton == QDialogButtonBox::Discard) - button->setShortcut(QKeySequence(QLatin1String("Ctrl+D"))); -#endif + button->setShortcut(QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton)); return button; } diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h index 699547c32f..00ec315555 100644 --- a/src/widgets/widgets/qdialogbuttonbox.h +++ b/src/widgets/widgets/qdialogbuttonbox.h @@ -53,7 +53,6 @@ class QDialogButtonBoxPrivate; class Q_WIDGETS_EXPORT QDialogButtonBox : public QWidget { Q_OBJECT - Q_FLAGS(StandardButtons) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) Q_PROPERTY(StandardButtons standardButtons READ standardButtons WRITE setStandardButtons) Q_PROPERTY(bool centerButtons READ centerButtons WRITE setCenterButtons) @@ -104,6 +103,7 @@ public: }; Q_DECLARE_FLAGS(StandardButtons, StandardButton) + Q_FLAG(StandardButtons) enum ButtonLayout { // keep this in sync with QMessageBox::ButtonLayout and QPlatformDialogHelper::ButtonLayout diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 53cb21186f..aa5d809431 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -930,7 +930,9 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event) } if (state->dragging && !state->nca) { - QPoint pos = event->globalPos() - state->pressPos; + QMargins windowMargins = q->window()->windowHandle()->frameMargins(); + QPoint windowMarginOffset = QPoint(windowMargins.left(), windowMargins.top()); + QPoint pos = event->globalPos() - state->pressPos - windowMarginOffset; QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent); if (floatingTab && !q->isFloating()) diff --git a/src/widgets/widgets/qdockwidget.h b/src/widgets/widgets/qdockwidget.h index 7b3f8d0ddb..80df009007 100644 --- a/src/widgets/widgets/qdockwidget.h +++ b/src/widgets/widgets/qdockwidget.h @@ -57,7 +57,6 @@ class Q_WIDGETS_EXPORT QDockWidget : public QWidget { Q_OBJECT - Q_FLAGS(DockWidgetFeatures) Q_PROPERTY(bool floating READ isFloating WRITE setFloating) Q_PROPERTY(DockWidgetFeatures features READ features WRITE setFeatures NOTIFY featuresChanged) Q_PROPERTY(Qt::DockWidgetAreas allowedAreas READ allowedAreas @@ -86,6 +85,7 @@ public: Reserved = 0xff }; Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) + Q_FLAG(DockWidgetFeatures) void setFeatures(DockWidgetFeatures features); DockWidgetFeatures features() const; diff --git a/src/widgets/widgets/qfontcombobox.h b/src/widgets/widgets/qfontcombobox.h index c409d33fef..983d5224dd 100644 --- a/src/widgets/widgets/qfontcombobox.h +++ b/src/widgets/widgets/qfontcombobox.h @@ -54,7 +54,6 @@ class QFontComboBoxPrivate; class Q_WIDGETS_EXPORT QFontComboBox : public QComboBox { Q_OBJECT - Q_FLAGS(FontFilters) Q_PROPERTY(QFontDatabase::WritingSystem writingSystem READ writingSystem WRITE setWritingSystem) Q_PROPERTY(FontFilters fontFilters READ fontFilters WRITE setFontFilters) Q_PROPERTY(QFont currentFont READ currentFont WRITE setCurrentFont NOTIFY currentFontChanged) @@ -74,6 +73,7 @@ public: ProportionalFonts = 0x8 }; Q_DECLARE_FLAGS(FontFilters, FontFilter) + Q_FLAG(FontFilters) void setFontFilters(FontFilters filters); FontFilters fontFilters() const; diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index e5e832ab98..fb0ffd6083 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -737,10 +737,10 @@ void QLineEdit::setCursorPosition(int pos) d->control->setCursorPosition(pos); } +// ### What should this do if the point is outside of contentsRect? Currently returns 0. /*! Returns the cursor position under the point \a pos. */ -// ### What should this do if the point is outside of contentsRect? Currently returns 0. int QLineEdit::cursorPositionAt(const QPoint &pos) { Q_D(QLineEdit); diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h index 9bd7eb1cd8..bab1176d8a 100644 --- a/src/widgets/widgets/qmainwindow.h +++ b/src/widgets/widgets/qmainwindow.h @@ -60,7 +60,6 @@ class Q_WIDGETS_EXPORT QMainWindow : public QWidget { Q_OBJECT - Q_FLAGS(DockOptions) Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) Q_PROPERTY(Qt::ToolButtonStyle toolButtonStyle READ toolButtonStyle WRITE setToolButtonStyle) #ifndef QT_NO_DOCKWIDGET @@ -89,6 +88,7 @@ public: }; Q_ENUM(DockOption) Q_DECLARE_FLAGS(DockOptions, DockOption) + Q_FLAG(DockOptions) explicit QMainWindow(QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); ~QMainWindow(); diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 5d218ac1ba..e9a5db1112 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -98,8 +98,8 @@ public: #else // addAction(QString): Connect to a QObject slot / functor or function pointer (with context) template<class Obj, typename Func1> - inline typename QtPrivate::QEnableIf<!std::is_same<const char*, Func1>::value - && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::Type + inline typename std::enable_if<!std::is_same<const char*, Func1>::value + && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type addAction(const QString &text, const Obj *object, Func1 slot, const QKeySequence &shortcut = 0) { QAction *result = addAction(text); @@ -126,8 +126,8 @@ public: } // addAction(QIcon, QString): Connect to a QObject slot / functor or function pointer (with context) template<class Obj, typename Func1> - inline typename QtPrivate::QEnableIf<!std::is_same<const char*, Func1>::value - && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::Type + inline typename std::enable_if<!std::is_same<const char*, Func1>::value + && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot, const QKeySequence &shortcut = 0) { QAction *result = addAction(actionIcon, text); diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 2588f41468..77ed7a4f78 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1119,7 +1119,7 @@ void QMenuBar::keyPressEvent(QKeyEvent *e) int clashCount = 0; QAction *first = 0, *currentSelected = 0, *firstAfterCurrent = 0; { - QChar c = e->text()[0].toUpper(); + const QChar c = e->text().at(0).toUpper(); for(int i = 0; i < d->actions.size(); ++i) { if (d->actionRects.at(i).isNull()) continue; @@ -1192,10 +1192,6 @@ QPlatformMenu *QMenuBarPrivate::getPlatformMenu(QAction *action) QPlatformMenu *platformMenu = action->menu()->platformMenu(); if (!platformMenu && platformMenuBar) { platformMenu = platformMenuBar->createMenu(); - // QPlatformMenuBar::createMenu() was introduced in Qt 5.7. Not all third party - // platform themes are using it, so fallback to QPlatformTheme::createPlatformMenu(). - if (!platformMenu) - platformMenu = QGuiApplicationPrivate::platformTheme()->createPlatformMenu(); if (platformMenu) action->menu()->setPlatformMenu(platformMenu); } @@ -1494,6 +1490,7 @@ bool QMenuBar::eventFilter(QObject *object, QEvent *event) case QEvent::FocusIn: case QEvent::FocusOut: case QEvent::ActivationChange: + case QEvent::Shortcut: d->altPressed = false; qApp->removeEventFilter(this); break; diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index 64f19047b6..2b228cdb2c 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -508,9 +508,7 @@ void QProgressBar::setOrientation(Qt::Orientation orientation) return; d->orientation = orientation; if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy(sp); + setSizePolicy(sizePolicy().transposed()); setAttribute(Qt::WA_WState_OwnSizePolicy, false); } d->resetLayoutItemMargins(); diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index 3b1440edb6..d8eae724ee 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -607,19 +607,21 @@ QPoint QPushButtonPrivate::adjustedMenuPosition() QPoint globalPos = q->mapToGlobal(rect.topLeft()); int x = globalPos.x(); int y = globalPos.y(); + const QRect availableGeometry = QApplication::desktop()->availableGeometry(q); if (horizontal) { - if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->availableGeometry(q).height()) { + if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) { y += rect.height(); - } else { + } else if (globalPos.y() - menuSize.height() >= availableGeometry.y()) { y -= menuSize.height(); } if (q->layoutDirection() == Qt::RightToLeft) x += rect.width() - menuSize.width(); } else { - if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->availableGeometry(q).width()) + if (globalPos.x() + rect.width() + menu->sizeHint().width() <= availableGeometry.right()) { x += rect.width(); - else + } else if (globalPos.x() - menuSize.width() >= availableGeometry.x()) { x -= menuSize.width(); + } } return QPoint(x,y); @@ -676,7 +678,7 @@ bool QPushButton::event(QEvent *e) } #if 0 // Used to be included in Qt4 for Q_WS_MAC -/*! \reimp */ +/* \reimp */ bool QPushButton::hitButton(const QPoint &pos) const { QStyleOptionButton opt; diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 910904e96e..e6332293e4 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -241,21 +241,24 @@ void QSplitterHandle::resizeEvent(QResizeEvent *event) { Q_D(const QSplitterHandle); - // When splitters are only 1 or 0 pixel large we increase the - // actual grab area to five pixels + // Ensure the actual grab area is at least 4 or 5 pixels + const int handleMargin = (5 - d->s->handleWidth()) / 2; // Note that QSplitter uses contentsRect for layouting // and ensures that handles are drawn on top of widgets // We simply use the contents margins for draggin and only // paint the mask area - bool useTinyMode = (d->s->handleWidth() <= 1); + const bool useTinyMode = handleMargin > 0; setAttribute(Qt::WA_MouseNoMask, useTinyMode); if (useTinyMode) { if (orientation() == Qt::Horizontal) - setContentsMargins(2, 0, 2, 0); + setContentsMargins(handleMargin, 0, handleMargin, 0); else - setContentsMargins(0, 2, 0, 2); + setContentsMargins(0, handleMargin, 0, handleMargin); setMask(QRegion(contentsRect())); + } else { + setContentsMargins(0, 0, 0, 0); + clearMask(); } QWidget::resizeEvent(event); @@ -731,6 +734,12 @@ void QSplitterPrivate::setSizes_helper(const QList<int> &sizes, bool clampNegati doResize(); } +bool QSplitterPrivate::shouldShowWidget(const QWidget *w) const +{ + Q_Q(const QSplitter); + return q->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide)); +} + void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool allowCollapse) { Q_Q(QSplitter); @@ -827,8 +836,7 @@ void QSplitterPrivate::insertWidget_helper(int index, QWidget *widget, bool show { Q_Q(QSplitter); QBoolBlocker b(blockChildAdd); - bool needShow = show && q->isVisible() && - !(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide)); + const bool needShow = show && shouldShowWidget(widget); if (widget->parentWidget() != q) widget->setParent(q); if (needShow) @@ -1000,9 +1008,7 @@ void QSplitter::setOrientation(Qt::Orientation orientation) return; if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) { - QSizePolicy sp = sizePolicy(); - sp.transpose(); - setSizePolicy(sp); + setSizePolicy(sizePolicy().transposed()); setAttribute(Qt::WA_WState_OwnSizePolicy, false); } @@ -1125,6 +1131,66 @@ void QSplitter::insertWidget(int index, QWidget *widget) } /*! + \since 5.9 + + Replaces the widget in the splitter's layout at the given \a index by \a widget. + + Returns the widget that has just been replaced if \a index is valid and \a widget + is not already a child of the splitter. Otherwise, it returns null and no replacement + or addition is made. + + The geometry of the newly inserted widget will be the same as the widget it replaces. + Its visible and collapsed states are also inherited. + + \note The splitter takes ownership of \a widget and sets the parent of the + replaced widget to null. + + \sa insertWidget(), indexOf() +*/ +QWidget *QSplitter::replaceWidget(int index, QWidget *widget) +{ + Q_D(QSplitter); + if (!widget) { + qWarning("QSplitter::replaceWidget: Widget can't be null"); + return nullptr; + } + + if (index < 0 || index >= d->list.count()) { + qWarning("QSplitter::replaceWidget: Index %d out of range", index); + return nullptr; + } + + QSplitterLayoutStruct *s = d->list.at(index); + QWidget *current = s->widget; + if (current == widget) { + qWarning("QSplitter::replaceWidget: Trying to replace a widget with itself"); + return nullptr; + } + + if (widget->parentWidget() == this) { + qWarning("QSplitter::replaceWidget: Trying to replace a widget with one of its siblings"); + return nullptr; + } + + QBoolBlocker b(d->blockChildAdd); + + const QRect geom = current->geometry(); + const bool shouldShow = d->shouldShowWidget(current); + + s->widget = widget; + current->setParent(nullptr); + widget->setParent(this); + + // The splitter layout struct's geometry is already set and + // should not change. Only set the geometry on the new widget + widget->setGeometry(geom); + widget->lower(); + widget->setVisible(shouldShow); + + return current; +} + +/*! \fn int QSplitter::indexOf(QWidget *widget) const Returns the index in the splitter's layout of the specified \a widget. This @@ -1232,7 +1298,7 @@ void QSplitter::childEvent(QChildEvent *c) if (c->added() && !d->blockChildAdd && !d->findWidget(w)) { d->insertWidget_helper(d->list.count(), w, false); } else if (c->polished() && !d->blockChildAdd) { - if (isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide))) + if (d->shouldShowWidget(w)) w->show(); } else if (c->type() == QEvent::ChildRemoved) { for (int i = 0; i < d->list.size(); ++i) { diff --git a/src/widgets/widgets/qsplitter.h b/src/widgets/widgets/qsplitter.h index 9cfde9fed3..e9ef3c3f2d 100644 --- a/src/widgets/widgets/qsplitter.h +++ b/src/widgets/widgets/qsplitter.h @@ -71,6 +71,7 @@ public: void addWidget(QWidget *widget); void insertWidget(int index, QWidget *widget); + QWidget *replaceWidget(int index, QWidget *widget); void setOrientation(Qt::Orientation); Qt::Orientation orientation() const; diff --git a/src/widgets/widgets/qsplitter_p.h b/src/widgets/widgets/qsplitter_p.h index 4422d9a8a4..07b43e56b8 100644 --- a/src/widgets/widgets/qsplitter_p.h +++ b/src/widgets/widgets/qsplitter_p.h @@ -125,6 +125,7 @@ public: int findWidgetJustBeforeOrJustAfter(int index, int delta, int &collapsibleSize) const; void updateHandles(); void setSizes_helper(const QList<int> &sizes, bool clampNegativeSize = false); + bool shouldShowWidget(const QWidget *w) const; }; diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 35d9498413..9bf062b407 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -177,8 +177,7 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex) if (tab.textColor.isValid()) option->palette.setColor(q->foregroundRole(), tab.textColor); #ifdef Q_OS_MACOS - else if (isCurrent && !documentMode - && (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || q->isActiveWindow())) { + else if (isCurrent && !documentMode && q->isActiveWindow()) { option->palette.setColor(QPalette::WindowText, Qt::white); } #endif @@ -1757,7 +1756,10 @@ void QTabBar::paintEvent(QPaintEvent *) p.drawControl(QStyle::CE_TabBarTab, tab); else { int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0, this); - d->movingTab->setGeometry(tab.rect.adjusted(-taboverlap, 0, taboverlap, 0)); + if (verticalTabs(d->shape)) + d->movingTab->setGeometry(tab.rect.adjusted(0, -taboverlap, 0, taboverlap)); + else + d->movingTab->setGeometry(tab.rect.adjusted(-taboverlap, 0, taboverlap, 0)); } } @@ -2036,7 +2038,10 @@ void QTabBarPrivate::setupMovableTab() int taboverlap = q->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0 ,q); QRect grabRect = q->tabRect(pressedIndex); - grabRect.adjust(-taboverlap, 0, taboverlap, 0); + if (verticalTabs(shape)) + grabRect.adjust(0, -taboverlap, 0, taboverlap); + else + grabRect.adjust(-taboverlap, 0, taboverlap, 0); QPixmap grabImage(grabRect.size() * q->devicePixelRatioF()); grabImage.setDevicePixelRatio(q->devicePixelRatioF()); @@ -2046,7 +2051,11 @@ void QTabBarPrivate::setupMovableTab() QStyleOptionTab tab; q->initStyleOption(&tab, pressedIndex); - tab.rect.moveTopLeft(QPoint(taboverlap, 0)); + tab.position = QStyleOptionTab::OnlyOneTab; + if (verticalTabs(shape)) + tab.rect.moveTopLeft(QPoint(0, taboverlap)); + else + tab.rect.moveTopLeft(QPoint(taboverlap, 0)); p.drawControl(QStyle::CE_TabBarTab, tab); p.end(); diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index 5dce76056c..1394c6b44c 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -732,7 +732,7 @@ QTabBar* QTabWidget::tabBar() const return d->tabs; } -/*! +/* Ensures that the selected tab's page is visible and appropriately sized. */ diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index 3b523e3ed0..b0e19193a9 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -64,7 +64,6 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea { Q_OBJECT Q_DECLARE_PRIVATE(QTextEdit) - Q_FLAGS(AutoFormatting) Q_PROPERTY(AutoFormatting autoFormatting READ autoFormatting WRITE setAutoFormatting) Q_PROPERTY(bool tabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus) Q_PROPERTY(QString documentTitle READ documentTitle WRITE setDocumentTitle) @@ -100,6 +99,7 @@ public: }; Q_DECLARE_FLAGS(AutoFormatting, AutoFormattingFlag) + Q_FLAG(AutoFormatting) explicit QTextEdit(QWidget *parent = Q_NULLPTR); explicit QTextEdit(const QString &text, QWidget *parent = Q_NULLPTR); diff --git a/src/widgets/widgets/qtoolbar.h b/src/widgets/widgets/qtoolbar.h index 0ea4d4afeb..e0f2d9b073 100644 --- a/src/widgets/widgets/qtoolbar.h +++ b/src/widgets/widgets/qtoolbar.h @@ -116,8 +116,8 @@ public: #else // addAction(QString): Connect to a QObject slot / functor or function pointer (with context) template<class Obj, typename Func1> - inline typename QtPrivate::QEnableIf<!std::is_same<const char*, Func1>::value - && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::Type + inline typename std::enable_if<!std::is_same<const char*, Func1>::value + && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type addAction(const QString &text, const Obj *object, Func1 slot) { QAction *result = addAction(text); @@ -134,8 +134,8 @@ public: } // addAction(QString): Connect to a QObject slot / functor or function pointer (with context) template<class Obj, typename Func1> - inline typename QtPrivate::QEnableIf<!std::is_same<const char*, Func1>::value - && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::Type + inline typename std::enable_if<!std::is_same<const char*, Func1>::value + && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot) { QAction *result = addAction(actionIcon, text); |