diff options
Diffstat (limited to 'src/widgets')
69 files changed, 611 insertions, 205 deletions
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/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/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/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 1fedad80aa..9aa14db368 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(); diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index ec25ccdb12..f1ef92bdf8 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -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(); @@ -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..a7f39a0538 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; 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..4b1c4c3e90 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); @@ -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 0d434c7097..39540cf898 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1022,17 +1022,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); } } @@ -1142,11 +1142,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; @@ -1196,8 +1196,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) { @@ -3274,6 +3274,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; @@ -3310,6 +3311,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); 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 baf717d715..a53b87bd39 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) @@ -383,7 +393,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. @@ -396,7 +406,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 @@ -499,7 +509,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); } @@ -513,10 +523,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..8e3263ad92 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) { @@ -2657,7 +2658,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 +2723,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 +2736,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 +2765,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 +2777,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 +2788,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 +2798,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 +2816,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 +4665,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 +4762,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 +8452,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..c39333161b 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 ); 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/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 7ca47e9f0f..c5ccfac109 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -639,7 +639,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); } @@ -828,6 +836,9 @@ void QAbstractSpinBox::changeEvent(QEvent *event) d->reset(); d->updateEditFieldGeometry(); break; + case QEvent::LocaleChange: + d->updateEdit(); + break; case QEvent::EnabledChange: if (!isEnabled()) { d->reset(); @@ -1895,6 +1906,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/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/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/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 258e018151..9df1a4823a 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -2682,7 +2682,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..b1cb556505 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -163,6 +163,9 @@ QString QTextBrowserPrivate::findFile(const QUrl &name) const fileName = name.toLocalFile(); } + if (fileName.isEmpty()) + return fileName; + if (QFileInfo(fileName).isAbsolute()) return 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; |