diff options
Diffstat (limited to 'src/widgets')
90 files changed, 846 insertions, 309 deletions
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp index 6cdc06d702..1499ab827c 100644 --- a/src/widgets/accessible/complexwidgets.cpp +++ b/src/widgets/accessible/complexwidgets.cpp @@ -199,7 +199,7 @@ QAccessibleTabBar::QAccessibleTabBar(QWidget *w) QAccessibleTabBar::~QAccessibleTabBar() { - foreach (QAccessible::Id id, m_childInterfaces) + for (QAccessible::Id id : qAsConst(m_childInterfaces)) QAccessible::deleteAccessibleInterface(id); } diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp index 4d37400dc9..04a5dcc878 100644 --- a/src/widgets/accessible/itemviews.cpp +++ b/src/widgets/accessible/itemviews.cpp @@ -115,7 +115,7 @@ bool QAccessibleTable::isValid() const QAccessibleTable::~QAccessibleTable() { - Q_FOREACH (QAccessible::Id id, childToId) + for (QAccessible::Id id : qAsConst(childToId)) QAccessible::deleteAccessibleInterface(id); } @@ -221,7 +221,7 @@ QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const return cells; const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes(); cells.reserve(selectedIndexes.size()); - Q_FOREACH (const QModelIndex &index, selectedIndexes) + for (const QModelIndex &index : selectedIndexes) cells.append(child(logicalIndex(index))); return cells; } @@ -233,7 +233,7 @@ QList<int> QAccessibleTable::selectedColumns() const QList<int> columns; const QModelIndexList selectedColumns = view()->selectionModel()->selectedColumns(); columns.reserve(selectedColumns.size()); - Q_FOREACH (const QModelIndex &index, selectedColumns) + for (const QModelIndex &index : selectedColumns) columns.append(index.column()); return columns; @@ -246,7 +246,7 @@ QList<int> QAccessibleTable::selectedRows() const QList<int> rows; const QModelIndexList selectedRows = view()->selectionModel()->selectedRows(); rows.reserve(selectedRows.size()); - Q_FOREACH (const QModelIndex &index, selectedRows) + for (const QModelIndex &index : selectedRows) rows.append(index.row()); return rows; @@ -553,7 +553,7 @@ void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event) switch (event->modelChangeType()) { case QAccessibleTableModelChangeEvent::ModelReset: - Q_FOREACH (QAccessible::Id id, childToId) + for (QAccessible::Id id : qAsConst(childToId)) QAccessible::deleteAccessibleInterface(id); childToId.clear(); break; diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index 8b3353f625..507584eb02 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -117,10 +117,9 @@ QAccessibleInterface *QAccessibleMenu::child(int index) const QAccessibleInterface *QAccessibleMenu::parent() const { if (QAction *menuAction = menu()->menuAction()) { - QList<QWidget *> parentCandidates; - parentCandidates << menu()->parentWidget(); - parentCandidates << menuAction->associatedWidgets(); - foreach (QWidget *w, parentCandidates) { + const QList<QWidget*> parentCandidates = + QList<QWidget*>() << menu()->parentWidget() << menuAction->associatedWidgets(); + for (QWidget *w : parentCandidates) { if (qobject_cast<QMenu*>(w) #if QT_CONFIG(menubar) || qobject_cast<QMenuBar*>(w) diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index 872ddcded5..0d87cc486d 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -569,7 +569,7 @@ QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const QAbstractItemView *QAccessibleCalendarWidget::calendarView() const { - foreach (QObject *child, calendarWidget()->children()) { + for (QObject *child : calendarWidget()->children()) { if (child->objectName() == QLatin1String("qt_calendar_calendarview")) return static_cast<QAbstractItemView *>(child); } @@ -578,7 +578,7 @@ QAbstractItemView *QAccessibleCalendarWidget::calendarView() const QWidget *QAccessibleCalendarWidget::navigationBar() const { - foreach (QObject *child, calendarWidget()->children()) { + for (QObject *child : calendarWidget()->children()) { if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) return static_cast<QWidget *>(child); } diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 3d91bdef34..ef369349b2 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -517,7 +517,7 @@ void QFileDialog::changeEvent(QEvent *e) QFileDialogPrivate::QFileDialogPrivate() : -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) proxyModel(0), #endif model(0), @@ -663,7 +663,7 @@ void QFileDialogPrivate::retranslateStrings() QList<QAction*> actions = qFileDialogUi->treeView->header()->actions(); QAbstractItemModel *abstractModel = model; -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) if (proxyModel) abstractModel = proxyModel; #endif @@ -2796,7 +2796,7 @@ bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPo QList<QAction*> actions = headerView->actions(); QAbstractItemModel *abstractModel = model; -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) if (proxyModel) abstractModel = proxyModel; #endif @@ -2965,7 +2965,7 @@ void QFileDialogPrivate::createWidgets() q, SLOT(_q_showHeader(QAction*)));; QAbstractItemModel *abstractModel = model; -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) if (proxyModel) abstractModel = proxyModel; #endif @@ -3046,7 +3046,7 @@ void QFileDialogPrivate::_q_showHeader(QAction *action) qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked()); } -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) /*! \since 4.3 @@ -3124,7 +3124,7 @@ QAbstractProxyModel *QFileDialog::proxyModel() const Q_D(const QFileDialog); return d->proxyModel; } -#endif // QT_NO_PROXYMODEL +#endif // QT_CONFIG(proxymodel) /*! \internal diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 1cbd690f24..8646894750 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -178,7 +178,7 @@ public: void setSupportedSchemes(const QStringList &schemes); QStringList supportedSchemes() const; -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) void setProxyModel(QAbstractProxyModel *model); QAbstractProxyModel *proxyModel() const; #endif diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index 17290381d3..3a93a53911 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -227,7 +227,7 @@ public: void _q_fileRenamed(const QString &path, const QString &oldName, const QString &newName); // layout -#ifndef QT_NO_PROXYMODEL +#if QT_CONFIG(proxymodel) QAbstractProxyModel *proxyModel; #endif @@ -346,17 +346,17 @@ private: }; QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const { -#ifdef QT_NO_PROXYMODEL - return index; -#else +#if QT_CONFIG(proxymodel) return proxyModel ? proxyModel->mapToSource(index) : index; +#else + return index; #endif } QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) const { -#ifdef QT_NO_PROXYMODEL - return index; -#else +#if QT_CONFIG(proxymodel) return proxyModel ? proxyModel->mapFromSource(index) : index; +#else + return index; #endif } diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index 71027f00a2..86c1fa243c 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -2526,7 +2526,7 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) // Check if this constraint have some overlap with current // trunk variables... - foreach (QSimplexVariable *ad, trunkVariables) { + for (QSimplexVariable *ad : qAsConst(trunkVariables)) { if (c->variables.contains(ad)) { match = true; break; diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index cef1d1b6da..38df9e72bd 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -7308,7 +7308,7 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) selectedItems = d_ptr->scene->selectedItems(); initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions; if (initialPositions.isEmpty()) { - foreach (QGraphicsItem *item, selectedItems) + for (QGraphicsItem *item : qAsConst(selectedItems)) initialPositions[item] = item->pos(); initialPositions[this] = pos(); } diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 37c631483a..c207bb359f 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -6391,7 +6391,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) ev.setWidget(event->widget()); sendEvent(receiver.data(), &ev); QSet<QGesture *> ignoredGestures; - foreach (QGesture *g, gestures) { + for (QGesture *g : qAsConst(gestures)) { if (!ev.isAccepted() && !ev.isAccepted(g)) { // if the gesture was ignored by its target, we will update the // targetItems list with a possible target items (items that diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp index f7f09486e9..398ef1aaf5 100644 --- a/src/widgets/graphicsview/qgraphicssceneevent.cpp +++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp @@ -259,8 +259,9 @@ #include "qgraphicssceneevent.h" -#ifndef QT_NO_DEBUG +#ifndef QT_NO_DEBUG_STREAM #include <QtCore/qdebug.h> +#include <private/qdebug_p.h> #endif #include <QtCore/qmap.h> #include <QtCore/qpoint.h> @@ -1730,4 +1731,99 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) d->newPos = pos; } +#ifndef QT_NO_DEBUG_STREAM +template <class Event> +static inline void formatPositions(QDebug &debug, const Event *event) +{ + debug << ", pos="; + QtDebugUtils::formatQPoint(debug, event->pos()); + debug << ", scenePos="; + QtDebugUtils::formatQPoint(debug, event->scenePos()); + debug << ", screenPos="; + QtDebugUtils::formatQPoint(debug, event->screenPos()); +} + +QDebug operator<<(QDebug debug, const QGraphicsSceneEvent *event) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + if (!event) { + debug << "QGraphicsSceneEvent(0)"; + return debug; + } + + const QEvent::Type type = event->type(); + switch (type) { + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMouseDoubleClick: { + const QGraphicsSceneMouseEvent *me = static_cast<const QGraphicsSceneMouseEvent *>(event); + const Qt::MouseButton button = me->button(); + const Qt::MouseButtons buttons = me->buttons(); + debug << "QGraphicsSceneMouseEvent("; + QtDebugUtils::formatQEnum(debug, type); + if (type != QEvent::GraphicsSceneMouseMove) { + debug << ", "; + QtDebugUtils::formatQEnum(debug, button); + } + if (buttons && button != buttons) { + debug << ", buttons="; + QtDebugUtils::formatQFlags(debug, buttons); + } + QtDebugUtils::formatNonNullQFlags(debug, ", ", me->modifiers()); + formatPositions(debug, me); + QtDebugUtils::formatNonNullQEnum(debug, ", ", me->source()); + QtDebugUtils::formatNonNullQFlags(debug, ", flags=", me->flags()); + debug << ')'; + } + break; + case QEvent::GraphicsSceneContextMenu: { + const QGraphicsSceneContextMenuEvent *ce = static_cast<const QGraphicsSceneContextMenuEvent *>(event); + debug << "QGraphicsSceneContextMenuEvent(reason=" << ce->reason(); + QtDebugUtils::formatNonNullQFlags(debug, ", ", ce->modifiers()); + formatPositions(debug, ce); + debug << ')'; + } + break; + case QEvent::GraphicsSceneHoverEnter: + case QEvent::GraphicsSceneHoverMove: + case QEvent::GraphicsSceneHoverLeave: + debug << "QGraphicsSceneHoverEvent("; + formatPositions(debug, static_cast<const QGraphicsSceneHoverEvent *>(event)); + debug << ')'; + break; + case QEvent::GraphicsSceneHelp: + break; + case QEvent::GraphicsSceneDragEnter: + case QEvent::GraphicsSceneDragMove: + case QEvent::GraphicsSceneDragLeave: + case QEvent::GraphicsSceneDrop: { + const QGraphicsSceneDragDropEvent *de = static_cast<const QGraphicsSceneDragDropEvent *>(event); + debug << "QGraphicsSceneDragDropEvent(proposedAction="; + QtDebugUtils::formatQEnum(debug, de->proposedAction()); + debug << ", possibleActions="; + QtDebugUtils::formatQFlags(debug, de->possibleActions()); + debug << ", source=" << de->source(); + QtDebugUtils::formatNonNullQFlags(debug, ", buttons=", de->buttons()); + QtDebugUtils::formatNonNullQFlags(debug, ", ", de->modifiers()); + formatPositions(debug, de); + } + break; + case QEvent::GraphicsSceneWheel: { + const QGraphicsSceneWheelEvent *we = static_cast<const QGraphicsSceneWheelEvent *>(event); + debug << "QGraphicsSceneWheelEvent("; + QtDebugUtils::formatNonNullQFlags(debug, ", buttons=", we->buttons()); + QtDebugUtils::formatNonNullQFlags(debug, ", ", we->modifiers()); + formatPositions(debug, we); + debug << ')'; + } + break; + default: + break; + } + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h index 77b53e401d..9d940be2c0 100644 --- a/src/widgets/graphicsview/qgraphicssceneevent.h +++ b/src/widgets/graphicsview/qgraphicssceneevent.h @@ -320,6 +320,10 @@ public: void setNewPos(const QPointF &pos); }; +#ifndef QT_NO_DEBUG_STREAM +Q_WIDGETS_EXPORT QDebug operator<<(QDebug, const QGraphicsSceneEvent *); +#endif + QT_END_NAMESPACE #endif diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 0c847b899e..705d5a0f4d 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -2703,7 +2703,7 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects) dirtyViewportRects << xrect; } - foreach (const QRect &rect, dirtyViewportRects) { + for (const QRect &rect : qAsConst(dirtyViewportRects)) { // Add the exposed rect to the update region. In rect update // mode, we only count the bounding rect of items. if (!boundingRectUpdate) { diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 00e9ff7400..21245d38ce 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -4086,7 +4086,7 @@ bool QHeaderViewPrivate::read(QDataStream &in) } int sectionItemsLengthTotal = 0; - foreach (const SectionItem §ion, newSectionItems) + for (const SectionItem §ion : qAsConst(newSectionItems)) sectionItemsLengthTotal += section.size; if (sectionItemsLengthTotal != lengthIn) return false; diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp index 91122283a4..dff4cc4593 100644 --- a/src/widgets/itemviews/qitemdelegate.cpp +++ b/src/widgets/itemviews/qitemdelegate.cpp @@ -103,7 +103,10 @@ public: QItemEditorFactory *f; bool clipPainting; - QRect textLayoutBounds(const QStyleOptionViewItem &options) const; + QRect displayRect(const QModelIndex &index, const QStyleOptionViewItem &option, + const QRect &decorationRect, const QRect &checkRect) const; + QRect textLayoutBounds(const QStyleOptionViewItem &option, + const QRect &decorationRect, const QRect &checkRect) const; QSizeF doTextLayout(int lineWidth) const; mutable QTextLayout textLayout; mutable QTextOption textOption; @@ -121,21 +124,53 @@ public: } tmp; }; -QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option) const +QRect QItemDelegatePrivate::displayRect(const QModelIndex &index, const QStyleOptionViewItem &option, + const QRect &decorationRect, const QRect &checkRect) const +{ + Q_Q(const QItemDelegate); + const QVariant value = index.data(Qt::DisplayRole); + if (!value.isValid() || value.isNull()) + return QRect(); + + const QString text = valueToText(value, option); + const QVariant fontVal = index.data(Qt::FontRole); + const QFont fnt = qvariant_cast<QFont>(fontVal).resolve(option.font); + return q->textRectangle(nullptr, + textLayoutBounds(option, decorationRect, checkRect), + fnt, text); +} + +// similar to QCommonStylePrivate::viewItemSize(Qt::DisplayRole) +QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option, + const QRect &decorationRect, const QRect &checkRect) const { QRect rect = option.rect; + const QWidget *w = widget(option); + QStyle *style = w ? w->style() : QApplication::style(); const bool wrapText = option.features & QStyleOptionViewItem::WrapText; + // see QItemDelegate::drawDisplay + const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, w) + 1; switch (option.decorationPosition) { case QStyleOptionViewItem::Left: case QStyleOptionViewItem::Right: - rect.setWidth(wrapText && rect.isValid() ? rect.width() : (QFIXED_MAX)); + rect.setWidth(wrapText && rect.isValid() ? rect.width() - 2 * textMargin : (QFIXED_MAX)); break; case QStyleOptionViewItem::Top: case QStyleOptionViewItem::Bottom: - rect.setWidth(wrapText ? option.decorationSize.width() : (QFIXED_MAX)); + rect.setWidth(wrapText ? option.decorationSize.width() - 2 * textMargin : (QFIXED_MAX)); break; } + if (wrapText) { + if (!decorationRect.isNull()) + rect.setWidth(rect.width() - decorationRect.width() - 2 * textMargin); + if (!checkRect.isNull()) + rect.setWidth(rect.width() - checkRect.width() - 2 * textMargin); + // adjust height to be sure that the text fits + const QSizeF size = doTextLayout(rect.width()); + rect.setHeight(qCeil(size.height())); + } + return rect; } @@ -395,14 +430,6 @@ void QItemDelegate::paint(QPainter *painter, decorationRect = QRect(); } - QString text; - QRect displayRect; - value = index.data(Qt::DisplayRole); - if (value.isValid() && !value.isNull()) { - text = d->valueToText(value, opt); - displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text); - } - QRect checkRect; Qt::CheckState checkState = Qt::Unchecked; value = index.data(Qt::CheckStateRole); @@ -411,6 +438,14 @@ void QItemDelegate::paint(QPainter *painter, checkRect = doCheck(opt, opt.rect, value); } + QString text; + QRect displayRect; + value = index.data(Qt::DisplayRole); + if (value.isValid() && !value.isNull()) { + text = d->valueToText(value, opt); + displayRect = d->displayRect(index, opt, decorationRect, checkRect); + } + // do the layout doLayout(opt, &checkRect, &decorationRect, &displayRect, false); @@ -440,12 +475,13 @@ void QItemDelegate::paint(QPainter *painter, QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + Q_D(const QItemDelegate); QVariant value = index.data(Qt::SizeHintRole); if (value.isValid()) return qvariant_cast<QSize>(value); QRect decorationRect = rect(option, index, Qt::DecorationRole); - QRect displayRect = rect(option, index, Qt::DisplayRole); QRect checkRect = rect(option, index, Qt::CheckStateRole); + QRect displayRect = d->displayRect(index, option, decorationRect, checkRect); doLayout(option, &checkRect, &decorationRect, &displayRect, true); @@ -1000,8 +1036,8 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, /*! \internal + Only used (and usable) for Qt::DecorationRole and Qt::CheckStateRole */ - QRect QItemDelegate::rect(const QStyleOptionViewItem &option, const QModelIndex &index, int role) const { @@ -1032,7 +1068,9 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option, const QString text = d->valueToText(value, option); value = index.data(Qt::FontRole); QFont fnt = qvariant_cast<QFont>(value).resolve(option.font); - return textRectangle(0, d->textLayoutBounds(option), fnt, text); } + return textRectangle(nullptr, + d->textLayoutBounds(option, QRect(), QRect()), + fnt, text); } } } return QRect(); diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 6777b09043..504e45c2fd 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -2601,7 +2601,7 @@ int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wr positions = segmentPositions; else if (!flowPositions.isEmpty()) { positions.reserve(scrollValueMap.size()); - foreach (int itemShown, scrollValueMap) + for (int itemShown : scrollValueMap) positions.append(flowPositions.at(itemShown)); } if (positions.isEmpty() || bounds <= length) @@ -2782,7 +2782,7 @@ bool QIconModeViewBase::filterDropEvent(QDropEvent *e) if (qq->acceptDrops()) { const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled; const QVector<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1))); - foreach (const QModelIndex &index, dropIndices) + for (const QModelIndex &index : dropIndices) if ((index.flags() & dropableFlags) == dropableFlags) return false; } diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 1fedad80aa..0faed6df47 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -48,9 +48,6 @@ QT_BEGIN_NAMESPACE -// workaround for VC++ 6.0 linker bug (?) -typedef bool(*LessThan)(const QPair<QListWidgetItem*,int>&,const QPair<QListWidgetItem*,int>&); - class QListWidgetMimeData : public QMimeData { Q_OBJECT @@ -301,7 +298,7 @@ void QListModel::sort(int column, Qt::SortOrder order) sorting[i].second = i; } - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::sort(sorting.begin(), sorting.end(), compare); QModelIndexList fromIndexes; QModelIndexList toIndexes; @@ -338,7 +335,7 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en sorting[i].second = start + i; } - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::sort(sorting.begin(), sorting.end(), compare); QModelIndexList oldPersistentIndexes = persistentIndexList(); @@ -1847,7 +1844,7 @@ QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*> items) const // if non empty, it's called from the model's own mimeData if (cachedIndexes.isEmpty()) { cachedIndexes.reserve(items.count()); - foreach (QListWidgetItem *item, items) + for (QListWidgetItem *item : items) cachedIndexes << indexFromItem(item); QMimeData *result = d->listModel()->internalMimeData(); diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index ec25ccdb12..313ef424a3 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -74,7 +74,7 @@ void QSpanCollection::addSpan(QSpanCollection::Span *span) //the previouslist is the list of spans that sarts _before_ the row of the span. // and which may intersect this row. const SubIndex previousList = it_y.value(); - foreach(Span *s, previousList) { + for (Span *s : previousList) { //If a subspans intersect the row, we need to split it into subspans if(s->bottom() >= span->top()) sub_index.insert(-s->left(), s); @@ -798,6 +798,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, const QStyleOptionViewItem &option, QBitArray *drawn, int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn) { + Q_Q(const QTableView); bool alternateBase = false; QRegion region = viewport->rect(); @@ -816,7 +817,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, visibleSpans = set.toList(); } - foreach (QSpanCollection::Span *span, visibleSpans) { + for (QSpanCollection::Span *span : qAsConst(visibleSpans)) { int row = span->top(); int col = span->left(); QModelIndex index = model->index(row, col, root); @@ -831,6 +832,18 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, alternateBase = alternatingColors && (span->top() & 1); opt.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase); drawCell(painter, opt, index); + if (showGrid) { + // adjust the clip rect to be able to paint the top & left grid lines + // if the headers are not visible, see paintEvent() + if (horizontalHeader->visualIndex(row) == 0) + rect.setTop(rect.top() + 1); + if (verticalHeader->visualIndex(row) == 0) { + if (q->isLeftToRight()) + rect.setLeft(rect.left() + 1); + else + rect.setRight(rect.right() - 1); + } + } region -= rect; for (int r = span->top(); r <= span->bottom(); ++r) { const int vr = visualRow(r); @@ -1321,10 +1334,10 @@ void QTableView::scrollContentsBy(int dx, int dy) //we need to update the first line of the previous top item in the view //because it has the grid drawn if the header is invisible. //It is strictly related to what's done at then end of the paintEvent - if (dy > 0 && d->horizontalHeader->isHidden() && d->verticalScrollMode == ScrollPerItem) { + if (dy > 0 && d->horizontalHeader->isHidden()) { d->viewport->update(0, dy, d->viewport->width(), dy); } - if (dx > 0 && d->verticalHeader->isHidden() && d->horizontalScrollMode == ScrollPerItem) { + if (dx > 0 && d->verticalHeader->isHidden()) { d->viewport->update(dx, 0, dx, d->viewport->height()); } } @@ -1504,10 +1517,26 @@ void QTableView::paintEvent(QPaintEvent *event) //draw the top & left grid lines if the headers are not visible. //We do update this line when subsequent scroll happen (see scrollContentsBy) - if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem) - painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0); - if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem) - painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom()); + if (horizontalHeader->isHidden() && top == 0) { + const int row = verticalHeader->logicalIndex(top); + if (!verticalHeader->isSectionHidden(row)) { + const int rowY = rowViewportPosition(row) + offset.y(); + if (rowY == dirtyArea.top()) + painter.drawLine(dirtyArea.left(), rowY, dirtyArea.right(), rowY); + } + } + if (verticalHeader->isHidden() && left == 0) { + const int col = horizontalHeader->logicalIndex(left); + if (!horizontalHeader->isSectionHidden(col)) { + int colX = columnViewportPosition(col) + offset.x(); + if (!isLeftToRight()) + colX += columnWidth(left) - 1; + if (isLeftToRight() && colX == dirtyArea.left()) + painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom()); + if (!isLeftToRight() && colX == dirtyArea.right()) + painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom()); + } + } painter.setPen(old); } } diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 301d5dbe4d..1006b11219 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -506,7 +506,7 @@ void QTableModel::sort(int column, Qt::SortOrder order) unsortable.append(row); } - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sortable.begin(), sortable.end(), compare); QVector<QTableWidgetItem*> sorted_table(tableItems.count()); @@ -558,7 +558,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order, sorting.append(QPair<QTableWidgetItem*,int>(itm, row)); } - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sorting.begin(), sorting.end(), compare); QModelIndexList oldPersistentIndexes, newPersistentIndexes; QVector<QTableWidgetItem*> newTable = tableItems; @@ -2595,7 +2595,7 @@ QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const // if non empty, it's called from the model's own mimeData if (cachedIndexes.isEmpty()) { cachedIndexes.reserve(items.count()); - foreach (QTableWidgetItem *item, items) + for (QTableWidgetItem *item : items) cachedIndexes << indexFromItem(item); QMimeData *result = d->tableModel()->internalMimeData(); diff --git a/src/widgets/itemviews/qtablewidget_p.h b/src/widgets/itemviews/qtablewidget_p.h index 6412477be0..74b1f226c1 100644 --- a/src/widgets/itemviews/qtablewidget_p.h +++ b/src/widgets/itemviews/qtablewidget_p.h @@ -62,9 +62,6 @@ QT_REQUIRE_CONFIG(tablewidget); QT_BEGIN_NAMESPACE -// workaround for VC++ 6.0 linker bug -typedef bool(*LessThan)(const QPair<QTableWidgetItem*,int>&,const QPair<QTableWidgetItem*,int>&); - class QTableWidgetMimeData : public QMimeData { Q_OBJECT diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index ebeefad682..8f7061f9d9 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -632,11 +632,8 @@ bool QTreeView::isFirstColumnSpanned(int row, const QModelIndex &parent) const Q_D(const QTreeView); if (d->spanningIndexes.isEmpty() || !d->model) return false; - QModelIndex index = d->model->index(row, 0, parent); - for (int i = 0; i < d->spanningIndexes.count(); ++i) - if (d->spanningIndexes.at(i) == index) - return true; - return false; + const QModelIndex index = d->model->index(row, 0, parent); + return d->spanningIndexes.contains(index); } /*! @@ -653,20 +650,14 @@ void QTreeView::setFirstColumnSpanned(int row, const QModelIndex &parent, bool s Q_D(QTreeView); if (!d->model) return; - QModelIndex index = d->model->index(row, 0, parent); + const QModelIndex index = d->model->index(row, 0, parent); if (!index.isValid()) return; - if (span) { - QPersistentModelIndex persistent(index); - if (!d->spanningIndexes.contains(persistent)) - d->spanningIndexes.append(persistent); - } else { - QPersistentModelIndex persistent(index); - int i = d->spanningIndexes.indexOf(persistent); - if (i >= 0) - d->spanningIndexes.remove(i); - } + if (span) + d->spanningIndexes.insert(index); + else + d->spanningIndexes.remove(index); d->executePostedLayout(); int i = d->viewIndex(index); @@ -1420,7 +1411,7 @@ QItemViewPaintPairs QTreeViewPrivate::draggablePaintPairs(const QModelIndexList if (spanningIndexes.isEmpty()) return QAbstractItemViewPrivate::draggablePaintPairs(indexes, r); QModelIndexList list; - foreach (const QModelIndex &idx, indexes) { + for (const QModelIndex &idx : indexes) { if (idx.column() > 0 && q->isFirstColumnSpanned(idx.row(), idx.parent())) continue; list << idx; @@ -2495,7 +2486,6 @@ void QTreeView::scrollContentsBy(int dx, int dy) int previousScrollbarValue = currentScrollbarValue + dy; // -(-dy) int currentViewIndex = currentScrollbarValue; // the first visible item int previousViewIndex = previousScrollbarValue; - const QVector<QTreeViewItem> viewItems = d->viewItems; dy = 0; if (previousViewIndex < currentViewIndex) { // scrolling down for (int i = previousViewIndex; i < currentViewIndex; ++i) { diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h index 9a391ee88a..8b217036a2 100644 --- a/src/widgets/itemviews/qtreeview_p.h +++ b/src/widgets/itemviews/qtreeview_p.h @@ -247,7 +247,7 @@ public: void updateIndentationFromStyle(); // used for spanning rows - QVector<QPersistentModelIndex> spanningIndexes; + QSet<QPersistentModelIndex> spanningIndexes; // used for updating resized columns int columnResizeTimerID; diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index de7f7c0b77..07907711d7 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -52,9 +52,6 @@ QT_BEGIN_NAMESPACE -// workaround for VC++ 6.0 linker bug (?) -typedef bool(*LessThan)(const QPair<QTreeWidgetItem*,int>&,const QPair<QTreeWidgetItem*,int>&); - class QTreeModelLessThan { public: @@ -610,7 +607,7 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order, sorting[i].second = start + i; } - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sorting.begin(), sorting.end(), compare); QModelIndexList oldPersistentIndexes; @@ -777,7 +774,7 @@ bool QTreeModel::isChanging() const if column is -1 then all columns have changed */ -void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column) +void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column, const QVector<int> &roles) { if (signalsBlocked()) return; @@ -800,7 +797,7 @@ void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column) topLeft = index(item, column); bottomRight = topLeft; } - emit dataChanged(topLeft, bottomRight); + emit dataChanged(topLeft, bottomRight, roles); } void QTreeModel::beginInsertItems(QTreeWidgetItem *parent, int row, int count) @@ -850,7 +847,7 @@ void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortO } // do the sorting - LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); + const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sorting.begin(), sorting.end(), compare); QModelIndexList fromList; @@ -1766,11 +1763,14 @@ void QTreeWidgetItem::setData(int column, int role, const QVariant &value) } if (model) { - model->emitDataChanged(this, column); + const QVector<int> roles((role == Qt::DisplayRole || role == Qt::EditRole) ? + QVector<int>({Qt::DisplayRole, Qt::EditRole}) : + QVector<int>({role})); + model->emitDataChanged(this, column, roles); if (role == Qt::CheckStateRole) { QTreeWidgetItem *p; for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par) - model->emitDataChanged(p, column); + model->emitDataChanged(p, column, roles); } } } diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h index a31af0428a..24919c411d 100644 --- a/src/widgets/itemviews/qtreewidget.h +++ b/src/widgets/itemviews/qtreewidget.h @@ -339,6 +339,7 @@ Q_SIGNALS: void itemDoubleClicked(QTreeWidgetItem *item, int column); void itemActivated(QTreeWidgetItem *item, int column); void itemEntered(QTreeWidgetItem *item, int column); + // ### Qt 6: add changed roles void itemChanged(QTreeWidgetItem *item, int column); void itemExpanded(QTreeWidgetItem *item); void itemCollapsed(QTreeWidgetItem *item); diff --git a/src/widgets/itemviews/qtreewidget_p.h b/src/widgets/itemviews/qtreewidget_p.h index f4625842ef..7bc8af8fbd 100644 --- a/src/widgets/itemviews/qtreewidget_p.h +++ b/src/widgets/itemviews/qtreewidget_p.h @@ -139,7 +139,7 @@ public: protected: QTreeModel(QTreeModelPrivate &, QTreeWidget *parent = 0); - void emitDataChanged(QTreeWidgetItem *item, int column); + void emitDataChanged(QTreeWidgetItem *item, int column, const QVector<int> &roles); void beginInsertItems(QTreeWidgetItem *parent, int row, int count); void endInsertItems(); void beginRemoveItems(QTreeWidgetItem *parent, int row, int count); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 404bebd40c..122d94d152 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1023,17 +1023,17 @@ QString QApplication::styleSheet() const void QApplication::setStyleSheet(const QString& styleSheet) { QApplicationPrivate::styleSheet = styleSheet; - QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style); + QStyleSheetStyle *styleSheetStyle = qt_styleSheet(QApplicationPrivate::app_style); if (styleSheet.isEmpty()) { // application style sheet removed - if (!proxy) + if (!styleSheetStyle) return; // there was no stylesheet before - setStyle(proxy->base); - } else if (proxy) { // style sheet update, just repolish - proxy->repolish(qApp); + setStyle(styleSheetStyle->base); + } else if (styleSheetStyle) { // style sheet update, just repolish + styleSheetStyle->repolish(qApp); } else { // stylesheet set the first time - QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style); - QApplicationPrivate::app_style->setParent(newProxy); - setStyle(newProxy); + QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(QApplicationPrivate::app_style); + QApplicationPrivate::app_style->setParent(newStyleSheetStyle); + setStyle(newStyleSheetStyle); } } @@ -1143,11 +1143,11 @@ void QApplication::setStyle(QStyle *style) QStyle *old = QApplicationPrivate::app_style; // save #ifndef QT_NO_STYLE_STYLESHEET - if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) { + if (!QApplicationPrivate::styleSheet.isEmpty() && !qt_styleSheet(style)) { // we have a stylesheet already and a new style is being set - QStyleSheetStyle *newProxy = new QStyleSheetStyle(style); - style->setParent(newProxy); - QApplicationPrivate::app_style = newProxy; + QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(style); + style->setParent(newStyleSheetStyle); + QApplicationPrivate::app_style = newStyleSheetStyle; } else #endif // QT_NO_STYLE_STYLESHEET QApplicationPrivate::app_style = style; @@ -1197,8 +1197,8 @@ void QApplication::setStyle(QStyle *style) } #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) { - oldProxy->deref(); + if (QStyleSheetStyle *oldStyleSheetStyle = qt_styleSheet(old)) { + oldStyleSheetStyle->deref(); } else #endif if (old && old->parent() == qApp) { @@ -2625,7 +2625,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *nativeWidget, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, - bool spontaneous) + bool spontaneous, bool onlyDispatchEnterLeave) { Q_ASSERT(receiver); Q_ASSERT(event); @@ -2686,11 +2686,17 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. const bool wasLeaveAfterRelease = leaveAfterRelease != 0; - bool result; - if (spontaneous) - result = QApplication::sendSpontaneousEvent(receiver, event); - else - result = QApplication::sendEvent(receiver, event); + bool result = true; + // This code is used for sending the synthetic enter/leave events for cases where it is needed + // due to other events causing the widget under the mouse to change. However in those cases + // we do not want to send the mouse event associated with this call, so this enables us to + // not send the unneeded mouse event + if (!onlyDispatchEnterLeave) { + if (spontaneous) + result = QApplication::sendSpontaneousEvent(receiver, event); + else + result = QApplication::sendEvent(receiver, event); + } if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) { @@ -2765,9 +2771,10 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) if (widget->data->in_destructor && qt_button_down == widget) qt_button_down = 0; - // Send enter/leave events followed by a mouse move on the entered widget. + // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the + // enter/leave events as appropriate QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver); + sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver, true, true); #else // !QT_NO_CURSOR Q_UNUSED(widget); #endif // QT_NO_CURSOR @@ -3286,6 +3293,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), phase, wheel->source(), wheel->inverted()); + we.setTimestamp(wheel->timestamp()); bool eventAccepted; do { we.spont = spontaneous && w == receiver; @@ -3322,6 +3330,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->source()); + we.setTimestamp(wheel->timestamp()); we.spont = true; we.ignore(); d->notify_helper(QApplicationPrivate::wheel_widget, &we); @@ -3647,7 +3656,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; w = w->parentWidget(); } - foreach (QGesture *g, allGestures) + for (QGesture *g : qAsConst(allGestures)) gestureEvent->setAccepted(g, false); gestureEvent->m_accept = false; // to make sure we check individual gestures } else { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 019fad3fc3..21ba47caa3 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -226,7 +226,7 @@ public: QWidget *buttonDown, QWidget *alienWidget); static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, - bool spontaneous = true); + bool spontaneous = true, bool onlyDispatchEnterLeave = false); void sendSyntheticEnterLeave(QWidget *widget); static QWindow *windowForWidget(const QWidget *widget) diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp index 7f8bf18e90..fc715687c6 100644 --- a/src/widgets/kernel/qgesture.cpp +++ b/src/widgets/kernel/qgesture.cpp @@ -916,7 +916,7 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const QList<QGesture *> QGestureEvent::activeGestures() const { QList<QGesture *> gestures; - foreach (QGesture *gesture, m_gestures) { + for (QGesture *gesture : m_gestures) { if (gesture->state() != Qt::GestureCanceled) gestures.append(gesture); } @@ -929,7 +929,7 @@ QList<QGesture *> QGestureEvent::activeGestures() const QList<QGesture *> QGestureEvent::canceledGestures() const { QList<QGesture *> gestures; - foreach (QGesture *gesture, m_gestures) { + for (QGesture *gesture : m_gestures) { if (gesture->state() == Qt::GestureCanceled) gestures.append(gesture); } diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index f3db4f4e2d..64acd8d229 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -1244,6 +1244,26 @@ int QLayout::indexOf(QWidget *widget) const } /*! + \since 5.12 + Searches for layout item \a layoutItem in this layout (not including child + layouts). + + Returns the index of \a layoutItem, or -1 if \a layoutItem is not found. +*/ +int QLayout::indexOf(QLayoutItem *layoutItem) const +{ + int i = 0; + QLayoutItem *item = itemAt(i); + while (item) { + if (item == layoutItem) + return i; + ++i; + item = itemAt(i); + } + return -1; +} + +/*! \enum QLayout::SizeConstraint The possible values are: diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h index bcc33a0811..616f4e7164 100644 --- a/src/widgets/kernel/qlayout.h +++ b/src/widgets/kernel/qlayout.h @@ -122,6 +122,7 @@ public: virtual QLayoutItem *itemAt(int index) const = 0; virtual QLayoutItem *takeAt(int index) = 0; virtual int indexOf(QWidget *) const; + QT6_VIRTUAL int indexOf(QLayoutItem *) const; virtual int count() const = 0; bool isEmpty() const override; QSizePolicy::ControlTypes controlTypes() const override; diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index ed7184302a..e9a682fabf 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -123,11 +123,11 @@ class QTipLabel : public QLabel { Q_OBJECT public: - QTipLabel(const QString &text, QWidget *w, int msecDisplayTime); + QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime); ~QTipLabel(); static QTipLabel *instance; - void updateSize(); + void updateSize(const QPoint &pos); bool eventFilter(QObject *, QEvent *) override; @@ -135,7 +135,7 @@ public: bool fadingOut; - void reuseTip(const QString &text, int msecDisplayTime); + void reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos); void hideTip(); void hideTipImmediately(); void setTipRect(QWidget *w, const QRect &r); @@ -171,7 +171,7 @@ private: QTipLabel *QTipLabel::instance = 0; -QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime) +QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime) #ifndef QT_NO_STYLE_STYLESHEET : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0) #else @@ -192,7 +192,7 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime) setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0); setMouseTracking(true); fadingOut = false; - reuseTip(text, msecDisplayTime); + reuseTip(text, msecDisplayTime, pos); } void QTipLabel::restartExpireTimer(int msecDisplayTime) @@ -204,7 +204,7 @@ void QTipLabel::restartExpireTimer(int msecDisplayTime) hideTimer.stop(); } -void QTipLabel::reuseTip(const QString &text, int msecDisplayTime) +void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos) { #ifndef QT_NO_STYLE_STYLESHEET if (styleSheetParent){ @@ -214,20 +214,30 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime) } #endif - setWordWrap(Qt::mightBeRichText(text)); + setWordWrap(true); setText(text); - updateSize(); + updateSize(pos); restartExpireTimer(msecDisplayTime); } -void QTipLabel::updateSize() +void QTipLabel::updateSize(const QPoint &pos) { QFontMetrics fm(font()); QSize extra(1, 0); // Make it look good with the default ToolTip font on Mac, which has a small descent. if (fm.descent() == 2 && fm.ascent() >= 11) ++extra.rheight(); - resize(sizeHint() + extra); + QSize sh = sizeHint(); + if (wordWrap()) { + const QRect screenRect = QApplication::desktop()->screenGeometry(pos); + if (sh.width() > screenRect.width()) { + // Try to use widely accepted 75chars max length or 80% of the screen width else. + // See https://en.wikipedia.org/wiki/Line_length + sh.setWidth(qMin(fm.averageCharWidth() * 75, static_cast<int>(screenRect.width() * .8))); + sh.setHeight(heightForWidth(sh.width())); + } + } + resize(sh + extra); } void QTipLabel::paintEvent(QPaintEvent *ev) @@ -381,7 +391,7 @@ int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w) void QTipLabel::placeTip(const QPoint &pos, QWidget *w) { #ifndef QT_NO_STYLE_STYLESHEET - if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) { + if (testAttribute(Qt::WA_StyleSheet) || (w && qt_styleSheet(w->style()))) { //the stylesheet need to know the real parent QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w)); //we force the style to be the QStyleSheetStyle, and force to clear the cache as well. @@ -394,7 +404,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) QTipLabel::instance, SLOT(styleSheetParentDestroyed())); // QTBUG-64550: A font inherited by the style sheet might change the size, // particular on Windows, where the tip is not parented on a window. - QTipLabel::instance->updateSize(); + QTipLabel::instance->updateSize(pos); } } #endif //QT_NO_STYLE_STYLESHEET @@ -497,7 +507,7 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons if (w) localPos = w->mapFromGlobal(pos); if (QTipLabel::instance->tipChanged(localPos, text, w)){ - QTipLabel::instance->reuseTip(text, msecDisplayTime); + QTipLabel::instance->reuseTip(text, msecDisplayTime, pos); QTipLabel::instance->setTipRect(w, rect); QTipLabel::instance->placeTip(pos, w); } @@ -511,10 +521,10 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons // raised when the tooltip will be shown QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime); + new QTipLabel(text, pos, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime); QT_WARNING_POP #else - new QTipLabel(text, w, msecDisplayTime); // sets QTipLabel::instance to itself + new QTipLabel(text, pos, w, msecDisplayTime); // sets QTipLabel::instance to itself #endif QTipLabel::instance->setTipRect(w, rect); QTipLabel::instance->placeTip(pos, w); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index c347ca0b59..6b3fad6b5f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1677,6 +1677,7 @@ QWidget::~QWidget() } } + d->wasDeleted = true; if (d->declarativeData) { if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) { if (QAbstractDeclarativeData::destroyed_qml1) @@ -1847,7 +1848,7 @@ void QWidgetPrivate::deleteExtra() deleteSysExtra(); #ifndef QT_NO_STYLE_STYLESHEET // dereference the stylesheet style - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style)) + if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style)) proxy->deref(); #endif if (extra->topextra) { @@ -1903,19 +1904,21 @@ void QWidgetPrivate::deleteTLSysExtra() } /* - Returns \c true if there are widgets above this which overlap with + Returns \c region of widgets above this which overlap with \a rect, which is in parent's coordinate system (same as crect). */ -bool QWidgetPrivate::isOverlapped(const QRect &rect) const +QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const { Q_Q(const QWidget); const QWidget *w = q; QRect r = rect; + QPoint p; + QRegion region; while (w) { if (w->isWindow()) - return false; + break; QWidgetPrivate *pd = w->parentWidget()->d_func(); bool above = false; for (int i = 0; i < pd->children.size(); ++i) { @@ -1927,19 +1930,23 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const continue; } - if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) { + const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect); + if (qRectIntersects(siblingRect, r)) { const QWExtra *siblingExtra = sibling->d_func()->extra; if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; } - return true; + region += siblingRect.translated(-p); + if (breakAfterFirst) + break; } } w = w->parentWidget(); r.translate(pd->data.crect.topLeft()); + p += pd->data.crect.topLeft(); } - return false; + return region; } void QWidgetPrivate::syncBackingStore() @@ -2657,7 +2664,7 @@ void QWidget::setStyleSheet(const QString& styleSheet) return; d->createExtra(); - QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style); + QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style); d->extra->styleSheet = styleSheet; if (styleSheet.isEmpty()) { // stylesheet removed if (!proxy) @@ -2722,12 +2729,12 @@ void QWidget::setStyle(QStyle *style) setAttribute(Qt::WA_SetStyle, style != 0); d->createExtra(); #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) { + if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) { //if for some reason someone try to set a QStyleSheetStyle, ref it //(this may happen for exemple in QButtonDialogBox which propagates its style) - proxy->ref(); + styleSheetStyle->ref(); d->setStyle_helper(style, false); - } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) { + } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) { // if we have an application stylesheet or have a proxy already, propagate d->setStyle_helper(new QStyleSheetStyle(style), true); } else @@ -2735,48 +2742,22 @@ void QWidget::setStyle(QStyle *style) d->setStyle_helper(style, false); } -void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool -#if 0 // Used to be included in Qt4 for Q_WS_MAC - metalHack -#endif - ) +void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate) { Q_Q(QWidget); - QStyle *oldStyle = q->style(); -#ifndef QT_NO_STYLE_STYLESHEET - QPointer<QStyle> origStyle; -#endif + QStyle *oldStyle = q->style(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // the metalhack boolean allows Qt/Mac to do a proper re-polish depending - // on how the Qt::WA_MacBrushedMetal attribute is set. It is only ever - // set when changing that attribute and passes the widget's CURRENT style. - // therefore no need to do a reassignment. - if (!metalHack) -#endif - { - createExtra(); + createExtra(); #ifndef QT_NO_STYLE_STYLESHEET - origStyle = extra->style.data(); + QPointer<QStyle> origStyle = extra->style; #endif - extra->style = newStyle; - } + extra->style = newStyle; // repolish - if (q->windowType() != Qt::Desktop) { - if (polished) { - oldStyle->unpolish(q); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (metalHack) - macUpdateMetalAttribute(); -#endif - q->style()->polish(q); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - } else if (metalHack) { - macUpdateMetalAttribute(); -#endif - } + if (polished && q->windowType() != Qt::Desktop) { + oldStyle->unpolish(q); + q->style()->polish(q); } if (propagate) { @@ -2790,8 +2771,8 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool } #ifndef QT_NO_STYLE_STYLESHEET - if (!qobject_cast<QStyleSheetStyle*>(newStyle)) { - if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) { + if (!qt_styleSheet(newStyle)) { + if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) { cssStyle->clearWidgetFont(q); } } @@ -2802,7 +2783,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool #ifndef QT_NO_STYLE_STYLESHEET // dereference the old stylesheet style - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data())) + if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle)) proxy->deref(); #endif } @@ -2813,7 +2794,9 @@ void QWidgetPrivate::inheritStyle() #ifndef QT_NO_STYLE_STYLESHEET Q_Q(QWidget); - QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0; + QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr; + + QStyleSheetStyle *proxy = qt_styleSheet(extraStyle); if (!q->styleSheet().isEmpty()) { Q_ASSERT(proxy); @@ -2821,16 +2804,16 @@ void QWidgetPrivate::inheritStyle() return; } - QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0); + QStyle *origStyle = proxy ? proxy->base : extraStyle; QWidget *parent = q->parentWidget(); QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0; // If we have stylesheet on app or parent has stylesheet style, we need // to be running a proxy - if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) { + if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) { QStyle *newStyle = parentStyle; if (q->testAttribute(Qt::WA_SetStyle)) newStyle = new QStyleSheetStyle(origStyle); - else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle)) + else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle)) newProxy->ref(); setStyle_helper(newStyle, true); @@ -2839,7 +2822,7 @@ void QWidgetPrivate::inheritStyle() // So, we have no stylesheet on parent/app and we have an empty stylesheet // we just need our original style back - if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different? + if (origStyle == extraStyle) // is it any different? return; // We could have inherited the proxy from our parent (which has a custom style) @@ -4688,9 +4671,8 @@ void QWidget::setFont(const QFont &font) #ifndef QT_NO_STYLE_STYLESHEET const QStyleSheetStyle* style; - if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) { + if (d->extra && (style = qt_styleSheet(d->extra->style))) style->saveWidgetFont(this, font); - } #endif setAttribute(Qt::WA_SetFont, font.resolve() != 0); @@ -4786,7 +4768,7 @@ void QWidgetPrivate::updateFont(const QFont &font) Q_Q(QWidget); #ifndef QT_NO_STYLE_STYLESHEET const QStyleSheetStyle* cssStyle; - cssStyle = extra ? qobject_cast<const QStyleSheetStyle*>(extra->style) : 0; + cssStyle = extra ? qt_styleSheet(extra->style) : 0; const bool useStyleSheetPropagationInWidgetStyles = QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles); #endif @@ -8476,7 +8458,7 @@ bool QWidgetPrivate::close_helper(CloseMode mode) data.is_closing = 1; QPointer<QWidget> that = q; - QPointer<QWidget> parentWidget = q->parentWidget(); + QPointer<QWidget> parentWidget = (q->parentWidget() && !QObjectPrivate::get(q->parentWidget())->wasDeleted) ? q->parentWidget() : nullptr; bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose); if (mode != CloseNoEvent) { diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a9c73c6a26..fae9e5ff4e 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -395,7 +395,7 @@ public: void setLocale_helper(const QLocale &l, bool forceUpdate = false); void resolveLocale(); - void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false); + void setStyle_helper(QStyle *newStyle, bool propagate); void inheritStyle(); void setUpdatesEnabled_helper(bool ); @@ -453,7 +453,7 @@ public: // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). void invalidateBuffer(const QRegion &); void invalidateBuffer(const QRect &); - bool isOverlapped(const QRect&) const; + QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const; void syncBackingStore(); void syncBackingStore(const QRegion ®ion); diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 3b093283cd..768406f361 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -59,6 +59,7 @@ #include <private/qgraphicseffect_p.h> #endif #include <QtGui/private/qwindow_p.h> +#include <QtGui/private/qhighdpiscaling_p.h> #include <qpa/qplatformbackingstore.h> @@ -793,6 +794,24 @@ QWidgetBackingStore::~QWidgetBackingStore() delete dirtyOnScreenWidgets; } +static QVector<QRect> getSortedRectsToScroll(const QRegion ®ion, int dx, int dy) +{ + QVector<QRect> rects = region.rects(); + if (rects.count() > 1) { + std::sort(rects.begin(), rects.end(), [=](const QRect &r1, const QRect &r2) { + if (r1.y() == r2.y()) { + if (dx > 0) + return r1.x() > r2.x(); + return r1.x() < r2.x(); + } + if (dy > 0) + return r1.y() > r2.y(); + return r1.y() < r2.y(); + }); + } + return rects; +} + //parent's coordinates; move whole rect; update parent and widget //assume the screen blt has already been done, so we don't need to refresh that part void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) @@ -820,12 +839,12 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) const QRect parentRect(rect & clipR); const bool nativeWithTextureChild = textureChildSeen && q->internalWinId(); - bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild + const bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild #if QT_CONFIG(graphicsview) // No accelerate move for proxy widgets. && !tlw->d_func()->extra->proxyWidget #endif - && !isOverlapped(sourceRect) && !isOverlapped(destRect); + ; if (!accelerateMove) { QRegion parentR(effectiveRectFor(parentRect)); @@ -841,18 +860,39 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) QWidgetBackingStore *wbs = x->backingStoreTracker.data(); QRegion childExpose(newRect & clipR); + QRegion overlappedExpose; - if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw)) - childExpose -= destRect; + if (sourceRect.isValid()) { + overlappedExpose = (overlappedRegion(sourceRect) | overlappedRegion(destRect)) & clipR; + + const qreal factor = QHighDpiScaling::factor(q->windowHandle()); + if (overlappedExpose.isEmpty() || qFloor(factor) == factor) { + const QVector<QRect> rectsToScroll + = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); + for (QRect rect : rectsToScroll) { + if (wbs->bltRect(rect, dx, dy, pw)) { + childExpose -= rect.translated(dx, dy); + } + } + } + + childExpose -= overlappedExpose; + } if (!pw->updatesEnabled()) return; const bool childUpdatesEnabled = q->updatesEnabled(); - if (childUpdatesEnabled && !childExpose.isEmpty()) { - childExpose.translate(-data.crect.topLeft()); - wbs->markDirty(childExpose, q); - isMoved = true; + if (childUpdatesEnabled) { + if (!overlappedExpose.isEmpty()) { + overlappedExpose.translate(-data.crect.topLeft()); + invalidateBuffer(overlappedExpose); + } + if (!childExpose.isEmpty()) { + childExpose.translate(-data.crect.topLeft()); + wbs->markDirty(childExpose, q); + isMoved = true; + } } QRegion parentExpose(parentRect); @@ -888,13 +928,12 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0; - QRect scrollRect = rect & clipRect(); - bool overlapped = false; - bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent) - && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft()))); + const QRect clipR = clipRect(); + const QRect scrollRect = rect & clipR; + const bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent); if (!accelerateScroll) { - if (overlapped) { + if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) { QRegion region(scrollRect); subtractOpaqueSiblings(region); invalidateBuffer(region); @@ -906,12 +945,23 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) const QRect destRect = scrollRect.translated(dx, dy) & scrollRect; const QRect sourceRect = destRect.translated(-dx, -dy); + const QRegion overlappedExpose = (overlappedRegion(scrollRect.translated(data.crect.topLeft()))) + .translated(-data.crect.topLeft()) & clipR; QRegion childExpose(scrollRect); - if (sourceRect.isValid()) { - if (wbs->bltRect(sourceRect, dx, dy, q)) - childExpose -= destRect; + + const qreal factor = QHighDpiScaling::factor(q->windowHandle()); + if (overlappedExpose.isEmpty() || qFloor(factor) == factor) { + const QVector<QRect> rectsToScroll + = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); + for (const QRect &rect : rectsToScroll) { + if (wbs->bltRect(rect, dx, dy, q)) { + childExpose -= rect.translated(dx, dy); + } + } } + childExpose -= overlappedExpose; + if (inDirtyList) { if (rect == q->rect()) { dirty.translate(dx, dy); @@ -928,6 +978,8 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (!q->updatesEnabled()) return; + if (!overlappedExpose.isEmpty()) + invalidateBuffer(overlappedExpose); if (!childExpose.isEmpty()) { wbs->markDirty(childExpose, q); isScrolled = true; diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 1078652234..e33a891d74 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -840,6 +840,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QPoint mapped = widget->mapFrom(rootWidget, pos); QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); + translated.setTimestamp(event->timestamp()); QGuiApplication::forwardEvent(widget, &translated, event); } diff --git a/src/widgets/styles/images/titlebar-contexthelp-16.png b/src/widgets/styles/images/titlebar-contexthelp-16.png Binary files differnew file mode 100644 index 0000000000..2cead19910 --- /dev/null +++ b/src/widgets/styles/images/titlebar-contexthelp-16.png diff --git a/src/widgets/styles/images/titlebar-contexthelp-32.png b/src/widgets/styles/images/titlebar-contexthelp-32.png Binary files differnew file mode 100644 index 0000000000..1cd4843d5e --- /dev/null +++ b/src/widgets/styles/images/titlebar-contexthelp-32.png diff --git a/src/widgets/styles/images/titlebar-contexthelp-48.png b/src/widgets/styles/images/titlebar-contexthelp-48.png Binary files differnew file mode 100644 index 0000000000..9b170687be --- /dev/null +++ b/src/widgets/styles/images/titlebar-contexthelp-48.png diff --git a/src/widgets/styles/images/titlebar-max-16.png b/src/widgets/styles/images/titlebar-max-16.png Binary files differnew file mode 100644 index 0000000000..101a7eac2b --- /dev/null +++ b/src/widgets/styles/images/titlebar-max-16.png diff --git a/src/widgets/styles/images/titlebar-max-32.png b/src/widgets/styles/images/titlebar-max-32.png Binary files differnew file mode 100644 index 0000000000..529c54f61d --- /dev/null +++ b/src/widgets/styles/images/titlebar-max-32.png diff --git a/src/widgets/styles/images/titlebar-max-48.png b/src/widgets/styles/images/titlebar-max-48.png Binary files differnew file mode 100644 index 0000000000..cfa0b67edf --- /dev/null +++ b/src/widgets/styles/images/titlebar-max-48.png diff --git a/src/widgets/styles/images/titlebar-min-16.png b/src/widgets/styles/images/titlebar-min-16.png Binary files differnew file mode 100644 index 0000000000..95e714b522 --- /dev/null +++ b/src/widgets/styles/images/titlebar-min-16.png diff --git a/src/widgets/styles/images/titlebar-min-32.png b/src/widgets/styles/images/titlebar-min-32.png Binary files differnew file mode 100644 index 0000000000..0b9afedecf --- /dev/null +++ b/src/widgets/styles/images/titlebar-min-32.png diff --git a/src/widgets/styles/images/titlebar-min-48.png b/src/widgets/styles/images/titlebar-min-48.png Binary files differnew file mode 100644 index 0000000000..b59a336d36 --- /dev/null +++ b/src/widgets/styles/images/titlebar-min-48.png diff --git a/src/widgets/styles/images/titlebar-shade-16.png b/src/widgets/styles/images/titlebar-shade-16.png Binary files differnew file mode 100644 index 0000000000..cc870a1e5c --- /dev/null +++ b/src/widgets/styles/images/titlebar-shade-16.png diff --git a/src/widgets/styles/images/titlebar-shade-32.png b/src/widgets/styles/images/titlebar-shade-32.png Binary files differnew file mode 100644 index 0000000000..b785b8e216 --- /dev/null +++ b/src/widgets/styles/images/titlebar-shade-32.png diff --git a/src/widgets/styles/images/titlebar-shade-48.png b/src/widgets/styles/images/titlebar-shade-48.png Binary files differnew file mode 100644 index 0000000000..42b75b4a0c --- /dev/null +++ b/src/widgets/styles/images/titlebar-shade-48.png diff --git a/src/widgets/styles/images/titlebar-unshade-16.png b/src/widgets/styles/images/titlebar-unshade-16.png Binary files differnew file mode 100644 index 0000000000..ef19de6c2f --- /dev/null +++ b/src/widgets/styles/images/titlebar-unshade-16.png diff --git a/src/widgets/styles/images/titlebar-unshade-32.png b/src/widgets/styles/images/titlebar-unshade-32.png Binary files differnew file mode 100644 index 0000000000..9f74bb0ac7 --- /dev/null +++ b/src/widgets/styles/images/titlebar-unshade-32.png diff --git a/src/widgets/styles/images/titlebar-unshade-48.png b/src/widgets/styles/images/titlebar-unshade-48.png Binary files differnew file mode 100644 index 0000000000..bd17c3cf48 --- /dev/null +++ b/src/widgets/styles/images/titlebar-unshade-48.png diff --git a/src/widgets/styles/images/toolbar-ext-h-16.png b/src/widgets/styles/images/toolbar-ext-h-16.png Binary files differnew file mode 100644 index 0000000000..c6bd1b1784 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-16.png diff --git a/src/widgets/styles/images/toolbar-ext-h-32.png b/src/widgets/styles/images/toolbar-ext-h-32.png Binary files differnew file mode 100644 index 0000000000..99c62698f2 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-32.png diff --git a/src/widgets/styles/images/toolbar-ext-h-8.png b/src/widgets/styles/images/toolbar-ext-h-8.png Binary files differnew file mode 100644 index 0000000000..340a374bce --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-8.png diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-16.png b/src/widgets/styles/images/toolbar-ext-h-rtl-16.png Binary files differnew file mode 100644 index 0000000000..31c72892b4 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-rtl-16.png diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-32.png b/src/widgets/styles/images/toolbar-ext-h-rtl-32.png Binary files differnew file mode 100644 index 0000000000..bfc333daac --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-rtl-32.png diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-8.png b/src/widgets/styles/images/toolbar-ext-h-rtl-8.png Binary files differnew file mode 100644 index 0000000000..538e408310 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-h-rtl-8.png diff --git a/src/widgets/styles/images/toolbar-ext.png b/src/widgets/styles/images/toolbar-ext-macstyle.png Binary files differindex 37bd403ff8..37bd403ff8 100644 --- a/src/widgets/styles/images/toolbar-ext.png +++ b/src/widgets/styles/images/toolbar-ext-macstyle.png diff --git a/src/widgets/styles/images/toolbar-ext@2x.png b/src/widgets/styles/images/toolbar-ext-macstyle@2x.png Binary files differindex 6fc729efb0..6fc729efb0 100644 --- a/src/widgets/styles/images/toolbar-ext@2x.png +++ b/src/widgets/styles/images/toolbar-ext-macstyle@2x.png diff --git a/src/widgets/styles/images/toolbar-ext-v-10.png b/src/widgets/styles/images/toolbar-ext-v-10.png Binary files differnew file mode 100644 index 0000000000..2a6d0e4c70 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-v-10.png diff --git a/src/widgets/styles/images/toolbar-ext-v-20.png b/src/widgets/styles/images/toolbar-ext-v-20.png Binary files differnew file mode 100644 index 0000000000..adc27f52b5 --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-v-20.png diff --git a/src/widgets/styles/images/toolbar-ext-v-5.png b/src/widgets/styles/images/toolbar-ext-v-5.png Binary files differnew file mode 100644 index 0000000000..21c670446c --- /dev/null +++ b/src/widgets/styles/images/toolbar-ext-v-5.png diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 557277b9e0..c2f96ba68b 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -931,11 +931,10 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt viewItemTextLayout(textLayout, textRect.width()); - QString elidedText; qreal height = 0; qreal width = 0; - int elidedIndex = -1; const int lineCount = textLayout.lineCount(); + QHash<int, QString> elidedTexts; for (int j = 0; j < lineCount; ++j) { const QTextLine line = textLayout.lineAt(j); if (j + 1 <= lineCount - 1) { @@ -944,22 +943,20 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt int start = line.textStart(); int length = line.textLength() + nextLine.textLength(); const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); - elidedText = engine.elidedText(option->textElideMode, textRect.width()); + elidedTexts.insert(j, engine.elidedText(option->textElideMode, textRect.width())); height += line.height(); width = textRect.width(); - elidedIndex = j; - break; + continue; } } if (line.naturalTextWidth() > textRect.width()) { int start = line.textStart(); int length = line.textLength(); const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); - elidedText = engine.elidedText(option->textElideMode, textRect.width()); + elidedTexts.insert(j, engine.elidedText(option->textElideMode, textRect.width())); height += line.height(); width = textRect.width(); - elidedIndex = j; - break; + continue; } width = qMax<qreal>(width, line.width()); height += line.height(); @@ -970,14 +967,16 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt const QPointF position = layoutRect.topLeft(); for (int i = 0; i < lineCount; ++i) { const QTextLine line = textLayout.lineAt(i); - if (i == elidedIndex) { + auto it = elidedTexts.constFind(i); + if (it != elidedTexts.constEnd()) { + const QString &elidedText = it.value(); qreal x = position.x() + line.x(); qreal y = position.y() + line.y() + line.ascent(); p->save(); p->setFont(option->font); p->drawText(QPointF(x, y), elidedText); p->restore(); - break; + continue; } line.draw(p, position); } @@ -2856,8 +2855,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, case SE_TabBarScrollLeftButton: { const bool vertical = opt->rect.width() < opt->rect.height(); const Qt::LayoutDirection ld = widget->layoutDirection(); - const int buttonWidth = qMax(pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width()); - const int buttonOverlap = pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, 0, widget); + const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width()); + const int buttonOverlap = proxy()->pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, 0, widget); r = vertical ? QRect(0, opt->rect.height() - (buttonWidth * 2) + buttonOverlap, opt->rect.width(), buttonWidth) : QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - (buttonWidth * 2) + buttonOverlap, 0, buttonWidth, opt->rect.height())); @@ -2865,7 +2864,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, case SE_TabBarScrollRightButton: { const bool vertical = opt->rect.width() < opt->rect.height(); const Qt::LayoutDirection ld = widget->layoutDirection(); - const int buttonWidth = qMax(pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width()); + const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width()); r = vertical ? QRect(0, opt->rect.height() - buttonWidth, opt->rect.width(), buttonWidth) : QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - buttonWidth, 0, buttonWidth, opt->rect.height())); @@ -3080,7 +3079,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, //have all the information we need (ie. the layout's margin) const QToolBar *tb = qobject_cast<const QToolBar*>(widget); const int margin = tb && tb->layout() ? tb->layout()->margin() : 2; - const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb); + const int handleExtent = proxy()->pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb); if (tbopt->state & QStyle::State_Horizontal) { r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin); r = QStyle::visualRect(tbopt->direction, tbopt->rect, r); @@ -4935,8 +4934,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_SpinBox: if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { // Add button + frame widths - int buttonWidth = 20; - int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0; + const int buttonWidth = (vopt->subControls & (QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown)) != 0 ? 20 : 0; + const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0; sz += QSize(buttonWidth + 2*fw, 2*fw); } break; @@ -5717,14 +5716,14 @@ static inline QString iconPngSuffix() { return QStringLiteral(".png"); } static void addIconFiles(const QString &prefix, const int sizes[], size_t count, QIcon &icon) { - for (size_t i = 0; i < count; ++i) { - const int size = sizes[i]; - icon.addFile(prefix + QString::number(size) + iconPngSuffix(), QSize(size, size)); - } + for (size_t i = 0; i < count; ++i) + icon.addFile(prefix + QString::number(sizes[i]) + iconPngSuffix()); } static const int dockTitleIconSizes[] = {10, 16, 20, 32, 48, 64}; - +static const int titleBarSizes[] = {16, 32, 48}; +static const int toolBarExtHSizes[] = {8, 16, 32}; +static const int toolBarExtVSizes[] = {5, 10, 20}; #endif // imageformat_png /*! @@ -6039,6 +6038,27 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption switch (standardIcon) { #ifndef QT_NO_IMAGEFORMAT_PNG + case SP_TitleBarMinButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-min-"), + titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon); + break; + case SP_TitleBarMaxButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-max-"), + titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon); + break; + case SP_TitleBarShadeButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-shade-"), + titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon); + + break; + case SP_TitleBarUnshadeButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-unshade-"), + titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon); + break; + case SP_TitleBarContextHelpButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-contexthelp-"), + titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon); + break; case SP_FileDialogNewFolder: icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16)); icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32)); @@ -6247,6 +6267,17 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption addIconFiles(iconResourcePrefix() + QStringLiteral("normalizedockup-"), dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon); break; + case SP_ToolBarHorizontalExtensionButton: { + QString prefix = iconResourcePrefix() + QStringLiteral("toolbar-ext-h-"); + if (rtl) + prefix += QStringLiteral("rtl-"); + addIconFiles(prefix, toolBarExtHSizes, sizeof(toolBarExtHSizes)/sizeof(toolBarExtHSizes[0]), icon); + } + break; + case SP_ToolBarVerticalExtensionButton: + addIconFiles(iconResourcePrefix() + QStringLiteral("toolbar-ext-v-"), + toolBarExtVSizes, sizeof(toolBarExtVSizes)/sizeof(toolBarExtVSizes[0]), icon); + break; #endif // QT_NO_IMAGEFORMAT_PNG default: icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget)); diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc index 2dc3207e6d..d3511ee754 100644 --- a/src/widgets/styles/qstyle.qrc +++ b/src/widgets/styles/qstyle.qrc @@ -140,13 +140,37 @@ <file>images/normalizedockup-32.png</file> <file>images/normalizedockup-48.png</file> <file>images/normalizedockup-64.png</file> + <file>images/toolbar-ext-h-8.png</file> + <file>images/toolbar-ext-h-16.png</file> + <file>images/toolbar-ext-h-32.png</file> + <file>images/toolbar-ext-h-rtl-8.png</file> + <file>images/toolbar-ext-h-rtl-16.png</file> + <file>images/toolbar-ext-h-rtl-32.png</file> + <file>images/toolbar-ext-v-5.png</file> + <file>images/toolbar-ext-v-10.png</file> + <file>images/toolbar-ext-v-20.png</file> + <file>images/titlebar-contexthelp-16.png</file> + <file>images/titlebar-contexthelp-32.png</file> + <file>images/titlebar-contexthelp-48.png</file> + <file>images/titlebar-max-16.png</file> + <file>images/titlebar-max-32.png</file> + <file>images/titlebar-max-48.png</file> + <file>images/titlebar-min-16.png</file> + <file>images/titlebar-min-32.png</file> + <file>images/titlebar-min-48.png</file> + <file>images/titlebar-shade-16.png</file> + <file>images/titlebar-shade-32.png</file> + <file>images/titlebar-shade-48.png</file> + <file>images/titlebar-unshade-16.png</file> + <file>images/titlebar-unshade-32.png</file> + <file>images/titlebar-unshade-48.png</file> </qresource> <qresource prefix="/qt-project.org/styles/macstyle"> <file alias="images/closedock-16.png">images/closedock-macstyle-16.png</file> <file alias="images/closedock-down-16.png">images/closedock-down-macstyle-16.png</file> <file alias="images/dockdock-16.png">images/dockdock-macstyle-16.png</file> <file alias="images/dockdock-down-16.png">images/dockdock-down-macstyle-16.png</file> - <file>images/toolbar-ext.png</file> - <file>images/toolbar-ext@2x.png</file> + <file alias="images/toolbar-ext.png">images/toolbar-ext-macstyle.png</file> + <file alias="images/toolbar-ext@2x.png">images/toolbar-ext-macstyle@2x.png</file> </qresource> </RCC> diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index 3666bce205..774c039ecc 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -1842,10 +1842,12 @@ QStyleOptionMenuItem::QStyleOptionMenuItem(int version) /*! \variable QStyleOptionMenuItem::tabWidth - \brief the tab width for the menu item + \brief the reserved width for the menu item's shortcut - The tab width is the distance between the text of the menu item - and the shortcut. The default value is 0. + QMenu sets it to the width occupied by the widest shortcut among + all visible items within the menu. + + The default value is 0. */ diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 2880917510..241399543b 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -366,7 +366,7 @@ public: QString text; QIcon icon; int maxIconWidth; - int tabWidth; + int tabWidth; // ### Qt 6: rename to reservedShortcutWidth QFont font; QStyleOptionMenuItem(); diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index e12aeb900b..36e5b03c0d 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -1039,7 +1039,7 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject if (const QWidget *widget = qobject_cast<const QWidget *>(object)) { QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle); if (!style) - style = qobject_cast<QStyleSheetStyle *>(widget->style()); + style = qt_styleSheet(widget->style()); if (style) fixupBorder(style->nativeFrameWidth(widget)); } @@ -1500,7 +1500,7 @@ public: return className; } else if (name == QLatin1String("style")) { QWidget *w = qobject_cast<QWidget *>(obj); - QStyleSheetStyle *proxy = w ? qobject_cast<QStyleSheetStyle *>(w->style()) : 0; + QStyleSheetStyle *proxy = w ? qt_styleSheet(w->style()) : 0; if (proxy) { QString styleName = QString::fromLatin1(proxy->baseStyle()->metaObject()->className()); cache[name] = styleName; @@ -2732,7 +2732,7 @@ QStyle *QStyleSheetStyle::baseStyle() const { if (base) return base; - if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(QApplication::style())) + if (QStyleSheetStyle *me = qt_styleSheet(QApplication::style())) return me->base; return QApplication::style(); } @@ -3671,6 +3671,17 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q bool dis = !(opt->state & QStyle::State_Enabled), act = opt->state & QStyle::State_Selected; + int checkableOffset = 0; + if (checkable) { + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); + QStyleOptionMenuItem newMi = mi; + newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction); + checkableOffset = newMi.rect.width(); + if (subSubRule.hasDrawable() || checked) + drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w); + } + + int iconOffset = 0; if (!mi.icon.isNull()) { QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; if (act && !dis) @@ -3690,20 +3701,22 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q iconRule.geo->height = pixh; } QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction); + if (opt->direction == Qt::LeftToRight) + iconRect.moveLeft(iconRect.left() + checkableOffset); + else + iconRect.moveRight(iconRect.right() - checkableOffset); iconRule.drawRule(p, iconRect); QRect pmr(0, 0, pixw, pixh); pmr.moveCenter(iconRect.center()); p->drawPixmap(pmr.topLeft(), pixmap); - } else if (checkable) { - QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); - if (subSubRule.hasDrawable() || checked) { - QStyleOptionMenuItem newMi = mi; - newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction); - drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w); - } + iconOffset = iconRule.geo->width; } QRect textRect = subRule.contentsRect(opt->rect); + if (opt->direction == Qt::LeftToRight) + textRect.setLeft(textRect.left() + checkableOffset + iconOffset); + else + textRect.setRight(textRect.right() - checkableOffset - iconOffset); textRect.setWidth(textRect.width() - mi.tabWidth); QStringRef s(&mi.text); p->setPen(mi.palette.buttonText().color()); @@ -5045,6 +5058,16 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op int width = csz.width(); if (mi->text.contains(QLatin1Char('\t'))) width += 12; //as in QCommonStyle + bool checkable = mi->checkType != QStyleOptionMenuItem::NotCheckable; + if (checkable) { + QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark); + QRect checkmarkRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction); + width += checkmarkRect.width(); + } + if (!mi->icon.isNull()) { + QPixmap pixmap = mi->icon.pixmap(pixelMetric(PM_SmallIconSize)); + width += pixmap.width(); + } return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height()))); } } diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h index 042abf5c22..d1647fb107 100644 --- a/src/widgets/styles/qstylesheetstyle_p.h +++ b/src/widgets/styles/qstylesheetstyle_p.h @@ -215,6 +215,13 @@ template <typename T> class QTypeInfo<QStyleSheetStyleCaches::Tampered<T>> : QTypeInfoMerger<QStyleSheetStyleCaches::Tampered<T>, T> {}; + +// Returns a QStyleSheet from the given style. +inline QStyleSheetStyle* qt_styleSheet(QStyle *style) +{ + return qobject_cast<QStyleSheetStyle *>(style); +} + QT_END_NAMESPACE #endif // QT_NO_STYLE_STYLESHEET #endif // QSTYLESHEETSTYLE_P_H diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index d444fe6053..60421a56b7 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -999,7 +999,7 @@ QCompleter::QCompleter(QAbstractItemModel *model, QObject *parent) d->init(model); } -#ifndef QT_NO_STRINGLISTMODEL +#if QT_CONFIG(stringlistmodel) /*! Constructs a QCompleter object with the given \a parent that uses the specified \a list as a source of possible completions. @@ -1010,7 +1010,7 @@ QCompleter::QCompleter(const QStringList& list, QObject *parent) Q_D(QCompleter); d->init(new QStringListModel(list, this)); } -#endif // QT_NO_STRINGLISTMODEL +#endif // QT_CONFIG(stringlistmodel) /*! Destroys the completer object. diff --git a/src/widgets/util/qcompleter.h b/src/widgets/util/qcompleter.h index de79302e15..fd1191d123 100644 --- a/src/widgets/util/qcompleter.h +++ b/src/widgets/util/qcompleter.h @@ -84,7 +84,7 @@ public: QCompleter(QObject *parent = nullptr); QCompleter(QAbstractItemModel *model, QObject *parent = nullptr); -#ifndef QT_NO_STRINGLISTMODEL +#if QT_CONFIG(stringlistmodel) QCompleter(const QStringList& completions, QObject *parent = nullptr); #endif ~QCompleter(); diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 903a141e49..28504f5631 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -1894,7 +1894,7 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio if (orientation == Qt::Horizontal) { // the snap points in the list - foreach (qreal snapPos, snapPositionsX) { + for (qreal snapPos : snapPositionsX) { qreal snapPosDist = snapPos - p; if ((dir > 0 && snapPosDist < 0) || (dir < 0 && snapPosDist > 0)) @@ -1941,7 +1941,7 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio } else { // (orientation == Qt::Vertical) // the snap points in the list - foreach (qreal snapPos, snapPositionsY) { + for (qreal snapPos : snapPositionsY) { qreal snapPosDist = snapPos - p; if ((dir > 0 && snapPosDist < 0) || (dir < 0 && snapPosDist > 0)) diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index b371e903a6..e928b9fe37 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -742,6 +742,17 @@ void QUndoStack::resetClean() } /*! + \since 5.12 + \property QUndoStack::clean + \brief the clean status of this stack. + + This property indicates whether or not the stack is clean. For example, a + stack is clean when a document has been saved. + + \sa isClean(), setClean(), resetClean(), cleanIndex() +*/ + +/*! If the stack is in the clean state, returns \c true; otherwise returns \c false. \sa setClean(), cleanIndex() @@ -940,6 +951,17 @@ void QUndoStack::setIndex(int idx) } /*! + \since 5.12 + \property QUndoStack::canUndo + \brief whether this stack can undo. + + This property indicates whether or not there is a command that can be + undone. + + \sa canUndo(), index(), canRedo() +*/ + +/*! Returns \c true if there is a command available for undo; otherwise returns \c false. This function returns \c false if the stack is empty, or if the bottom command @@ -959,6 +981,17 @@ bool QUndoStack::canUndo() const } /*! + \since 5.12 + \property QUndoStack::canRedo + \brief whether this stack can redo. + + This property indicates whether or not there is a command that can be + redone. + + \sa canRedo(), index(), canUndo() +*/ + +/*! Returns \c true if there is a command available for redo; otherwise returns \c false. This function returns \c false if the stack is empty or if the top command @@ -978,6 +1011,17 @@ bool QUndoStack::canRedo() const } /*! + \since 5.12 + \property QUndoStack::undoText + \brief the undo text of the next command that is undone. + + This property holds the text of the command which will be undone in the + next call to undo(). + + \sa undoText(), QUndoCommand::actionText(), redoText() +*/ + +/*! Returns the text of the command which will be undone in the next call to undo(). \sa QUndoCommand::actionText(), redoText() @@ -994,6 +1038,17 @@ QString QUndoStack::undoText() const } /*! + \since 5.12 + \property QUndoStack::redoText + \brief the redo text of the next command that is redone. + + This property holds the text of the command which will be redone in the + next call to redo(). + + \sa redoText(), QUndoCommand::actionText(), undoText() +*/ + +/*! Returns the text of the command which will be redone in the next call to redo(). \sa QUndoCommand::actionText(), undoText() diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h index 4be24eadab..b5716b2e9b 100644 --- a/src/widgets/util/qundostack.h +++ b/src/widgets/util/qundostack.h @@ -90,6 +90,11 @@ class Q_WIDGETS_EXPORT QUndoStack : public QObject Q_DECLARE_PRIVATE(QUndoStack) Q_PROPERTY(bool active READ isActive WRITE setActive) Q_PROPERTY(int undoLimit READ undoLimit WRITE setUndoLimit) + Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged) + Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged) + Q_PROPERTY(QString undoText READ undoText NOTIFY undoTextChanged) + Q_PROPERTY(QString redoText READ redoText NOTIFY redoTextChanged) + Q_PROPERTY(bool clean READ isClean NOTIFY cleanChanged) public: explicit QUndoStack(QObject *parent = nullptr); diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index e059f2d52f..d2cbd9d456 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -638,7 +638,15 @@ void QAbstractSpinBox::stepBy(int steps) e = AlwaysEmit; } if (!dontstep) { - d->setValue(d->bound(d->value + (d->singleStep * steps), old, steps), e); + QVariant singleStep; + switch (d->stepType) { + case QAbstractSpinBox::StepType::AdaptiveDecimalStepType: + singleStep = d->calculateAdaptiveDecimalStep(steps); + break; + default: + singleStep = d->singleStep; + } + d->setValue(d->bound(d->value + (singleStep * steps), old, steps), e); } else if (e == AlwaysEmit) { d->emitSignals(e, old); } @@ -827,6 +835,9 @@ void QAbstractSpinBox::changeEvent(QEvent *event) d->reset(); d->updateEditFieldGeometry(); break; + case QEvent::LocaleChange: + d->updateEdit(); + break; case QEvent::EnabledChange: if (!isEnabled()) { d->reset(); @@ -1894,6 +1905,11 @@ void QAbstractSpinBoxPrivate::clearCache() const cachedState = QValidator::Acceptable; } +QVariant QAbstractSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const +{ + Q_UNUSED(steps) + return singleStep; +} // --- QSpinBoxValidator --- diff --git a/src/widgets/widgets/qabstractspinbox.h b/src/widgets/widgets/qabstractspinbox.h index 83bf83d779..87d46c7326 100644 --- a/src/widgets/widgets/qabstractspinbox.h +++ b/src/widgets/widgets/qabstractspinbox.h @@ -127,6 +127,13 @@ public: virtual void fixup(QString &input) const; virtual void stepBy(int steps); + + enum StepType { + DefaultStepType, + AdaptiveDecimalStepType + }; + Q_ENUM(StepType) + public Q_SLOTS: void stepUp(); void stepDown(); diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h index 8f312fa900..b8bc088160 100644 --- a/src/widgets/widgets/qabstractspinbox_p.h +++ b/src/widgets/widgets/qabstractspinbox_p.h @@ -122,6 +122,8 @@ public: static int variantCompare(const QVariant &arg1, const QVariant &arg2); static QVariant variantBound(const QVariant &min, const QVariant &value, const QVariant &max); + virtual QVariant calculateAdaptiveDecimalStep(int steps) const; + QLineEdit *edit; QString prefix, suffix, specialValueText; QVariant value, minimum, maximum, singleStep; @@ -143,6 +145,7 @@ public: uint cleared : 1; uint ignoreUpdateEdit : 1; QAbstractSpinBox::CorrectionMode correctionMode; + QAbstractSpinBox::StepType stepType = QAbstractSpinBox::StepType::DefaultStepType; int acceleration; QStyle::SubControl hoverControl; QRect hoverRect; diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 71726eaeee..9c216738c0 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -2628,8 +2628,9 @@ void QDockAreaLayout::removePlaceHolder(const QString &name) QList<int> index = indexOfPlaceHolder(name); if (!index.isEmpty()) remove(index); - foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>( - QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) { index = dwgw->layoutInfo()->indexOfPlaceHolder(name); if (!index.isEmpty()) { dwgw->layoutInfo()->remove(index); @@ -3064,8 +3065,9 @@ QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget) bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget) { QDockAreaLayoutItem *item = 0; - foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>( - QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) { QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName()); if (!index.isEmpty()) { dockWidget->setParent(dwgw); @@ -3174,7 +3176,7 @@ void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks, if (!info->tabbed && info->o == o) { info->item_list[path.constLast()].size = size; int totalSize = 0; - foreach (const QDockAreaLayoutItem &item, info->item_list) { + for (const QDockAreaLayoutItem &item : qAsConst(info->item_list)) { if (!item.skip()) { if (totalSize != 0) totalSize += sep; diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index 947da273dd..c624187190 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -1021,9 +1021,8 @@ void QLabel::paintEvent(QPaintEvent *) QStyleOption opt; opt.initFrom(this); #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) { + if (QStyleSheetStyle* cssStyle = qt_styleSheet(style)) cssStyle->styleSheetPalette(this, &opt, &opt.palette); - } #endif if (d->control) { #ifndef QT_NO_SHORTCUT diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index bdeef7cdf7..d7c9d7a44c 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -2000,7 +2000,7 @@ void QLineEdit::paintEvent(QPaintEvent *) // draw text, selections and cursors #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) { + if (QStyleSheetStyle* cssStyle = qt_styleSheet(style())) { cssStyle->styleSheetPalette(this, &panel, &pal); } #endif diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 6a8af53c97..acf49cda72 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -347,11 +347,9 @@ void QLineEditIconButton::paintEvent(QPaintEvent *) QWindow *window = nullptr; if (const QWidget *nativeParent = nativeParentWidget()) window = nativeParent->windowHandle(); - // Note isDown should really use the active state but in most styles - // this has no proper feedback QIcon::Mode state = QIcon::Disabled; if (isEnabled()) - state = isDown() ? QIcon::Selected : QIcon::Normal; + state = isDown() ? QIcon::Active : QIcon::Normal; const QLineEditPrivate *lep = lineEditPrivate(); const int iconWidth = lep ? lep->sideWidgetParameters().iconSize : 16; const QSize iconSize(iconWidth, iconWidth); diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index d4ce0ffa4c..0297172100 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -423,7 +423,8 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty() } // Make sure to reparent the possibly floating or hidden QDockWidgets to the parent - foreach (QDockWidget *dw, findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) { + const auto dockWidgets = findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidget *dw : dockWidgets) { bool wasFloating = dw->isFloating(); bool wasHidden = dw->isHidden(); dw->setParent(parentWidget()); @@ -442,7 +443,8 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty() dw->show(); } #if QT_CONFIG(tabbar) - foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly)) + const auto tabBars = findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly); + for (QTabBar *tb : tabBars) tb->setParent(parentWidget()); #endif deleteLater(); @@ -1034,10 +1036,10 @@ void QMainWindowLayoutState::saveState(QDataStream &stream) const #if QT_CONFIG(dockwidget) dockAreaLayout.saveState(stream); #if QT_CONFIG(tabbar) - QList<QDockWidgetGroupWindow *> floatingTabs = + const QList<QDockWidgetGroupWindow *> floatingTabs = mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly); - foreach (QDockWidgetGroupWindow *floating, floatingTabs) { + for (QDockWidgetGroupWindow *floating : floatingTabs) { if (floating->layoutInfo()->isEmpty()) continue; stream << uchar(QDockAreaLayout::FloatingDockWidgetTabMarker) << floating->geometry(); @@ -1525,9 +1527,9 @@ void QMainWindowLayout::setDocumentMode(bool enabled) _documentMode = enabled; // Update the document mode for all tab bars - foreach (QTabBar *bar, usedTabBars) + for (QTabBar *bar : qAsConst(usedTabBars)) bar->setDocumentMode(_documentMode); - foreach (QTabBar *bar, unusedTabBars) + for (QTabBar *bar : qAsConst(unusedTabBars)) bar->setDocumentMode(_documentMode); } #endif // QT_CONFIG(tabbar) @@ -1806,8 +1808,9 @@ QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget) QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget); if (info) return info; - foreach (QDockWidgetGroupWindow *dwgw, - parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) { info = dwgw->layoutInfo()->info(widget); if (info) return info; @@ -2074,8 +2077,9 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem) layoutState.remove(previousPath); previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget); // Let's remove the widget from any possible group window - foreach (QDockWidgetGroupWindow *dwgw, - parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) { if (dwgw == currentHoveredFloat) continue; QList<int> path = dwgw->layoutInfo()->indexOf(widget); @@ -2103,8 +2107,9 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem) #if QT_CONFIG(dockwidget) // Let's remove the widget from any possible group window - foreach (QDockWidgetGroupWindow *dwgw, - parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) { QList<int> path = dwgw->layoutInfo()->indexOf(widget); if (!path.isEmpty()) dwgw->layoutInfo()->remove(path); @@ -2246,7 +2251,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget) #if QT_CONFIG(dockwidget) parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); #if QT_CONFIG(tabbar) - foreach (QTabBar *tab_bar, usedTabBars) + for (QTabBar *tab_bar : qAsConst(usedTabBars)) tab_bar->show(); #endif // QT_CONFIG(tabbar) #endif // QT_CONFIG(dockwidget) @@ -2530,7 +2535,8 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) // Check if we are over another floating dock widget QVarLengthArray<QWidget *, 10> candidates; - foreach (QObject *c, parentWidget()->children()) { + const auto siblings = parentWidget()->children(); + for (QObject *c : siblings) { QWidget *w = qobject_cast<QWidget*>(c); if (!w) continue; @@ -2540,7 +2546,8 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) candidates << w; if (QDockWidgetGroupWindow *group = qobject_cast<QDockWidgetGroupWindow *>(w)) { // Sometimes, there are floating QDockWidget that have a QDockWidgetGroupWindow as a parent. - foreach (QObject *c, group->children()) { + const auto groupChildren = group->children(); + for (QObject *c : groupChildren) { if (QDockWidget *dw = qobject_cast<QDockWidget*>(c)) { if (dw != widget && dw->isFloating() && dw->isVisible() && !dw->isMinimized()) candidates << dw; @@ -2668,14 +2675,14 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat { #if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars(); - foreach (QDockWidgetGroupWindow *dwgw, - parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) { + const auto groups = + parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly); + for (QDockWidgetGroupWindow *dwgw : groups) used += dwgw->layoutInfo()->usedTabBars(); - } - QSet<QTabBar*> retired = usedTabBars - used; + const QSet<QTabBar*> retired = usedTabBars - used; usedTabBars = used; - foreach (QTabBar *tab_bar, retired) { + for (QTabBar *tab_bar : retired) { tab_bar->hide(); while (tab_bar->count() > 0) tab_bar->removeTab(0); @@ -2683,10 +2690,10 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat } if (sep == 1) { - QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets(); - QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps; + const QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets(); + const QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps; usedSeparatorWidgets = usedSeps; - foreach (QWidget *sepWidget, retiredSeps) { + for (QWidget *sepWidget : retiredSeps) { unusedSeparatorWidgets.append(sepWidget); } } @@ -2728,7 +2735,7 @@ bool QMainWindowLayout::restoreState(QDataStream &stream) #if QT_CONFIG(dockwidget) if (parentWidget()->isVisible()) { #if QT_CONFIG(tabbar) - foreach (QTabBar *tab_bar, usedTabBars) + for (QTabBar *tab_bar : qAsConst(usedTabBars)) tab_bar->show(); #endif diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 45c01dec80..8639f57ea1 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -471,8 +471,8 @@ QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end()); result.reserve(ylist.size() * xlist.size()); - foreach (int y, ylist) - foreach (int x, xlist) + for (int y : qAsConst(ylist)) + for (int x : qAsConst(xlist)) result << QRect(QPoint(x, y), size); return result; } diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 363647aee0..96635ae505 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2433,7 +2433,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) atAction = d->defaultAction; // TODO: This works for first level menus, not yet sub menus } else { - foreach (QAction *action, d->actions) + for (QAction *action : qAsConst(d->actions)) if (action->isEnabled()) { atAction = action; break; diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 561215ec85..7f29c0c52c 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -45,6 +45,8 @@ #include <qvalidator.h> #include <qdebug.h> +#include <algorithm> +#include <cmath> #include <float.h> QT_BEGIN_NAMESPACE @@ -75,6 +77,8 @@ public: } int displayIntegerBase; + + QVariant calculateAdaptiveDecimalStep(int steps) const override; }; class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate @@ -100,6 +104,8 @@ public: // When fiddling with the decimals property, we may lose precision in these properties. double actualMin; double actualMax; + + QVariant calculateAdaptiveDecimalStep(int steps) const override; }; @@ -415,6 +421,41 @@ void QSpinBox::setRange(int minimum, int maximum) } /*! + Sets the step type for the spin box: single step or adaptive + decimal step. + + Adaptive decimal step means that the step size will continuously be + adjusted to one power of ten below the current \l value. So when + the value is 1100, the step is set to 100, so stepping up once + increases it to 1200. For 1200 stepping up takes it to 1300. For + negative values, stepping down from -1100 goes to -1200. + + Step direction is taken into account to handle edges cases, so + that stepping down from 100 takes the value to 99 instead of 90. + Thus a step up followed by a step down -- or vice versa -- always + lands on the starting value; 99 -> 100 -> 99. + + Setting this will cause the spin box to disregard the value of + \l singleStep, although it is preserved so that \l singleStep + comes into effect if adaptive decimal step is later turned off. + + \sa QAbstractSpinBox::groupSeparator() + \since 5.12 +*/ + +void QSpinBox::setStepType(QAbstractSpinBox::StepType stepType) +{ + Q_D(QSpinBox); + d->stepType = stepType; +} + +QAbstractSpinBox::StepType QSpinBox::stepType() const +{ + Q_D(const QSpinBox); + return d->stepType; +} + +/*! \property QSpinBox::displayIntegerBase \brief the base used to display the value of the spin box @@ -847,6 +888,44 @@ void QDoubleSpinBox::setRange(double minimum, double maximum) } /*! + Sets the step type for the spin box: single step or adaptive + decimal step. + + Adaptive decimal step means that the step size will continuously be + adjusted to one power of ten below the current \l value. So when + the value is 1100, the step is set to 100, so stepping up once + increases it to 1200. For 1200 stepping up takes it to 1300. For + negative values, stepping down from -1100 goes to -1200. + + It also works for any decimal values, 0.041 is increased to 0.042 + by stepping once. + + Step direction is taken into account to handle edges cases, so + that stepping down from 100 takes the value to 99 instead of 90. + Thus a step up followed by a step down -- or vice versa -- always + lands on the starting value; 99 -> 100 -> 99. + + Setting this will cause the spin box to disregard the value of + \l singleStep, although it is preserved so that \l singleStep + comes into effect if adaptive decimal step is later turned off. + + \sa QAbstractSpinBox::groupSeparator() + \since 5.12 +*/ + +void QDoubleSpinBox::setStepType(StepType stepType) +{ + Q_D(QDoubleSpinBox); + d->stepType = stepType; +} + +QAbstractSpinBox::StepType QDoubleSpinBox::stepType() const +{ + Q_D(const QDoubleSpinBox); + return d->stepType; +} + +/*! \property QDoubleSpinBox::decimals \brief the precision of the spin box, in decimals @@ -1078,6 +1157,22 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, return cachedValue; } +QVariant QSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const +{ + const int intValue = value.toInt(); + const int absValue = qAbs(intValue); + + if (absValue < 100) + return 1; + + const bool valueNegative = intValue < 0; + const bool stepsNegative = steps < 0; + const int signCompensation = (valueNegative == stepsNegative) ? 0 : 1; + + const int log = static_cast<int>(std::log10(absValue - signCompensation)) - 1; + return static_cast<int>(std::pow(10, log)); +} + // --- QDoubleSpinBoxPrivate --- /*! @@ -1303,6 +1398,27 @@ QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const return q->textFromValue(f.toDouble()); } +QVariant QDoubleSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const +{ + const double doubleValue = value.toDouble(); + const double minStep = std::pow(10, -decimals); + double absValue = qAbs(doubleValue); + + if (absValue < minStep) + return minStep; + + const bool valueNegative = doubleValue < 0; + const bool stepsNegative = steps < 0; + if (valueNegative != stepsNegative) + absValue /= 1.01; + + const double shift = std::pow(10, 1 - std::floor(std::log10(absValue))); + const double absRounded = round(absValue * shift) / shift; + const double log = floorf(std::log10(absRounded)) - 1; + + return std::max(minStep, std::pow(10, log)); +} + /*! \reimp */ bool QSpinBox::event(QEvent *event) { diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h index 73489c9a68..d2eac903fb 100644 --- a/src/widgets/widgets/qspinbox.h +++ b/src/widgets/widgets/qspinbox.h @@ -58,6 +58,7 @@ class Q_WIDGETS_EXPORT QSpinBox : public QAbstractSpinBox Q_PROPERTY(int minimum READ minimum WRITE setMinimum) Q_PROPERTY(int maximum READ maximum WRITE setMaximum) Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep) + Q_PROPERTY(StepType stepType READ stepType WRITE setStepType) Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true) Q_PROPERTY(int displayIntegerBase READ displayIntegerBase WRITE setDisplayIntegerBase) @@ -86,6 +87,9 @@ public: void setRange(int min, int max); + StepType stepType() const; + void setStepType(StepType stepType); + int displayIntegerBase() const; void setDisplayIntegerBase(int base); @@ -121,6 +125,7 @@ class Q_WIDGETS_EXPORT QDoubleSpinBox : public QAbstractSpinBox Q_PROPERTY(double minimum READ minimum WRITE setMinimum) Q_PROPERTY(double maximum READ maximum WRITE setMaximum) Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep) + Q_PROPERTY(StepType stepType READ stepType WRITE setStepType) Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged USER true) public: explicit QDoubleSpinBox(QWidget *parent = nullptr); @@ -147,6 +152,9 @@ public: void setRange(double min, double max); + StepType stepType() const; + void setStepType(StepType stepType); + int decimals() const; void setDecimals(int prec); diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp index 468fc272b5..3dc396395f 100644 --- a/src/widgets/widgets/qsplashscreen.cpp +++ b/src/widgets/widgets/qsplashscreen.cpp @@ -327,7 +327,13 @@ void QSplashScreen::drawContents(QPainter *painter) cursor.select(QTextCursor::Document); QTextBlockFormat fmt; fmt.setAlignment(Qt::Alignment(d->currAlign)); + fmt.setLayoutDirection(layoutDirection()); cursor.mergeBlockFormat(fmt); + const QSizeF txtSize = doc.size(); + if (d->currAlign & Qt::AlignBottom) + r.setTop(r.height() - txtSize.height()); + else if (d->currAlign & Qt::AlignVCenter) + r.setTop(r.height() / 2 - txtSize.height() / 2); painter->save(); painter->translate(r.topLeft()); doc.drawContents(painter); diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 6ee49aa9f0..9e38c8f18a 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -826,7 +826,7 @@ QSplitterLayoutStruct *QSplitterPrivate::findWidget(QWidget *w) const if (list.at(i)->widget == w) return list.at(i); } - return 0; + return nullptr; } @@ -855,7 +855,7 @@ void QSplitterPrivate::insertWidget_helper(int index, QWidget *widget, bool show QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w) { Q_Q(QSplitter); - QSplitterLayoutStruct *sls = 0; + QSplitterLayoutStruct *sls = nullptr; int i; int last = list.count(); for (i = 0; i < list.size(); ++i) { @@ -872,12 +872,9 @@ QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w) if (sls) { list.move(i,index); } else { - QSplitterHandle *newHandle = 0; sls = new QSplitterLayoutStruct; - QString tmp = QLatin1String("qt_splithandle_"); - tmp += w->objectName(); - newHandle = q->createHandle(); - newHandle->setObjectName(tmp); + QSplitterHandle *newHandle = q->createHandle(); + newHandle->setObjectName(QLatin1String("qt_splithandle_") + w->objectName()); sls->handle = newHandle; sls->widget = w; w->lower(); @@ -1248,7 +1245,7 @@ QSplitterHandle *QSplitter::handle(int index) const { Q_D(const QSplitter); if (index < 0 || index >= d->list.size()) - return 0; + return nullptr; return d->list.at(index)->handle; } @@ -1262,7 +1259,7 @@ QWidget *QSplitter::widget(int index) const { Q_D(const QSplitter); if (index < 0 || index >= d->list.size()) - return 0; + return nullptr; return d->list.at(index)->widget; } @@ -1463,7 +1460,7 @@ void QSplitter::moveSplitter(int pos, int index) void QSplitter::getRange(int index, int *min, int *max) const { Q_D(const QSplitter); - d->getRange(index, min, 0, 0, max); + d->getRange(index, min, nullptr, nullptr, max); } diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 2f2d1bceee..3e26b04327 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -2686,7 +2686,7 @@ void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(const QVariant &cu priv->moveTab(priv->tabList.indexOf(*tab), current.toInt()); } -void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State, QAbstractAnimation::State newState) +void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State) { if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab)); } diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index 1092878f2c..f303ed54d1 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -144,7 +144,7 @@ public: void updateCurrentValue(const QVariant ¤t) override; - void updateState(State, State newState) override; + void updateState(State newState, State) override; private: //these are needed for the callbacks Tab *tab; diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index fa4dd14c92..46b973bae7 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -163,10 +163,13 @@ QString QTextBrowserPrivate::findFile(const QUrl &name) const fileName = name.toLocalFile(); } + if (fileName.isEmpty()) + return fileName; + if (QFileInfo(fileName).isAbsolute()) return fileName; - foreach (QString path, searchPaths) { + for (QString path : qAsConst(searchPaths)) { if (!path.endsWith(QLatin1Char('/'))) path.append(QLatin1Char('/')); path.append(fileName); @@ -1089,6 +1092,8 @@ QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name) QByteArray data; QString fileName = d->findFile(d->resolveUrl(name)); + if (fileName.isEmpty()) + return QVariant(); QFile f(fileName); if (f.open(QFile::ReadOnly)) { data = f.readAll(); diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 623ca5b0a1..ff00e26683 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -711,7 +711,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); if (m_validInput) { if (m_text != textCopy) { - internalSetText(textCopy, cursorCopy, false); + internalSetText(textCopy, cursorCopy, edited); return true; } m_cursor = cursorCopy; |