From 558c5c849cfd594c9e1cfb6edaffa0b524c852e9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 May 2016 11:20:49 +0200 Subject: QAccessibleWidget: Retrieve window from native parent widget. Query the native parent widget if the widget does not have a window handle. The window is required to be able to determine the correct scale factor for the screen when High DPI scaling is active. Change-Id: Ibaf5e8e7b07327ea635d2f726acea76c2c95bda3 Task-number: QTBUG-52943 Reviewed-by: Frederik Gladhorn --- src/widgets/accessible/qaccessiblewidget.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 3a9422cc26..beff27ad64 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -206,8 +206,14 @@ bool QAccessibleWidget::isValid() const /*! \reimp */ QWindow *QAccessibleWidget::window() const { - Q_ASSERT(widget()); - return widget()->windowHandle(); + const QWidget *w = widget(); + Q_ASSERT(w); + QWindow *result = w->windowHandle(); + if (!result) { + if (const QWidget *nativeParent = w->nativeParentWidget()) + result = nativeParent->windowHandle(); + } + return result; } /*! -- cgit v1.2.3 From 2c90973ebfd1ce61b4815bcef8a9ffc19f309f1a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 May 2016 11:23:25 +0200 Subject: QAccessibleMenuItem: Implement QAccessibleInterface::window(). The window is required to be able to determine the correct scale factor for the screen when High DPI scaling is active. Change-Id: I8f776684396d055754093f62e0d33bd7e23cb52b Task-number: QTBUG-52943 Reviewed-by: Frederik Gladhorn --- src/widgets/accessible/qaccessiblemenu.cpp | 14 ++++++++++++++ src/widgets/accessible/qaccessiblemenu_p.h | 2 ++ 2 files changed, 16 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index a0a7852851..106f724464 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -225,6 +225,20 @@ QObject *QAccessibleMenuItem::object() const return m_action; } +/*! \reimp */ +QWindow *QAccessibleMenuItem::window() const +{ + QWindow *result = Q_NULLPTR; + if (!m_owner.isNull()) { + result = m_owner->windowHandle(); + if (!result) { + if (const QWidget *nativeParent = m_owner->nativeParentWidget()) + result = nativeParent->windowHandle(); + } + } + return result; +} + QRect QAccessibleMenuItem::rect() const { QRect rect; diff --git a/src/widgets/accessible/qaccessiblemenu_p.h b/src/widgets/accessible/qaccessiblemenu_p.h index b42c852ff1..c51597bf1f 100644 --- a/src/widgets/accessible/qaccessiblemenu_p.h +++ b/src/widgets/accessible/qaccessiblemenu_p.h @@ -108,6 +108,8 @@ public: QAccessibleInterface *parent() const Q_DECL_OVERRIDE; QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE; QObject * object() const Q_DECL_OVERRIDE; + QWindow *window() const Q_DECL_OVERRIDE; + QRect rect() const Q_DECL_OVERRIDE; QAccessible::Role role() const Q_DECL_OVERRIDE; void setText(QAccessible::Text t, const QString & text) Q_DECL_OVERRIDE; -- cgit v1.2.3 From 558718ff4406638410364db7c1310cb38963d6df Mon Sep 17 00:00:00 2001 From: Vyacheslav Grigoryev Date: Fri, 6 May 2016 01:29:27 +0300 Subject: QTableView: Fix selection for reordered or hidden rows/columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code sometimes made incorrect selections when rows or columns were hidden or moved. It used logical top left and bottom right indexes to create a selection rectangle. However on moved or hidden cells a wrong rectangle was made. This fix calculates a simple rectangle without hidden cells and makes use of the row/column select functionality provided by the selection model, to make the right selection. [ChangeLog][QtWidgets][QTableView] Fixed a selection bug when rows or columns were hidden (QTBUG-50171) Task-number: QTBUG-50171 Change-Id: Id186012af26da7b2051ff5eb1c13e6b7494cca77 Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qtableview.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index ee0d41ce15..b68c105aba 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -3249,13 +3249,12 @@ void QTableViewPrivate::selectRow(int row, bool anchor) command |= QItemSelectionModel::Current; } - QModelIndex tl = model->index(qMin(rowSectionAnchor, row), logicalColumn(0), root); - QModelIndex br = model->index(qMax(rowSectionAnchor, row), logicalColumn(model->columnCount(root) - 1), root); - if ((verticalHeader->sectionsMoved() && tl.row() != br.row()) - || horizontalHeader->sectionsMoved()) { - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); + QModelIndex upper = model->index(qMin(rowSectionAnchor, row), column, root); + QModelIndex lower = model->index(qMax(rowSectionAnchor, row), column, root); + if ((verticalHeader->sectionsMoved() && upper.row() != lower.row())) { + q->setSelection(q->visualRect(upper) | q->visualRect(lower), command | QItemSelectionModel::Rows); } else { - selectionModel->select(QItemSelection(tl, br), command); + selectionModel->select(QItemSelection(upper, lower), command | QItemSelectionModel::Rows); } } } @@ -3289,14 +3288,12 @@ void QTableViewPrivate::selectColumn(int column, bool anchor) command |= QItemSelectionModel::Current; } - QModelIndex tl = model->index(logicalRow(0), qMin(columnSectionAnchor, column), root); - QModelIndex br = model->index(logicalRow(model->rowCount(root) - 1), - qMax(columnSectionAnchor, column), root); - if ((horizontalHeader->sectionsMoved() && tl.column() != br.column()) - || verticalHeader->sectionsMoved()) { - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); + QModelIndex left = model->index(row, qMin(columnSectionAnchor, column), root); + QModelIndex right = model->index(row, qMax(columnSectionAnchor, column), root); + if ((horizontalHeader->sectionsMoved() && left.column() != right.column())) { + q->setSelection(q->visualRect(left) | q->visualRect(right), command | QItemSelectionModel::Columns); } else { - selectionModel->select(QItemSelection(tl, br), command); + selectionModel->select(QItemSelection(left, right), command | QItemSelectionModel::Columns); } } } -- cgit v1.2.3 From 6a84a51611f69f3641ae47bbd7b6bd5266ae88ef Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 6 Apr 2016 10:51:55 -0700 Subject: QWidgetWindow: Guard reference to own widget ~QWidgetPrivate() may end up calling QWidgetPrivate:: deleteTLSysExtra() which, in turn, calls QWindow::destroy(). This sends an event to the window itself. This reaches QWidgetWindow::event() which will forward the event to the widget. However, the widget has just been deleted since the sequence was initiated by ~QObject(). Task-number: QTBUG-53103 Change-Id: Ib511714a76bbc1e734d6f2800a983eb1459bbf0b Reviewed-by: Marc Mutz Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidgetwindow.cpp | 7 +++++-- src/widgets/kernel/qwidgetwindow_p.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index b638c6c377..ec2618e501 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -123,7 +123,7 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { setSurfaceType(QSurface::RasterGLSurface); } - connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); + connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange())); } @@ -174,6 +174,9 @@ static inline bool shouldBePropagatedToWidget(QEvent *event) bool QWidgetWindow::event(QEvent *event) { + if (!m_widget) + return QWindow::event(event); + if (m_widget->testAttribute(Qt::WA_DontShowOnScreen)) { // \a event is uninteresting for QWidgetWindow, the event was probably // generated before WA_DontShowOnScreen was set @@ -375,7 +378,7 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) } else { const QEnterEvent *ee = static_cast(event); QWidget *child = m_widget->childAt(ee->pos()); - QWidget *receiver = child ? child : m_widget; + QWidget *receiver = child ? child : m_widget.data(); QApplicationPrivate::dispatchEnterLeave(receiver, 0, ee->screenPos()); qt_last_mouse_receiver = receiver; } diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index ca4bac8d86..7fafb01b3d 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -119,7 +119,7 @@ private: }; QWidget *getFocusWidget(FocusWidgets fw); - QWidget *m_widget; + QPointer m_widget; QPointer m_implicit_mouse_grabber; #ifndef QT_NO_DRAGANDDROP QPointer m_dragTarget; -- cgit v1.2.3 From ce37467acf34edf1380f896a0942b616dc4cbead Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 29 Apr 2016 16:32:42 -0700 Subject: Acknowledge QWidgetWindow::widget() may be null We guard QWidgetWindow's widget with a QPointer to avoid sending it events during destruction (which may result in undefined behavior, since this originates from ~QObject and we expect the object to behave as a QWidget). Therefore, we need to harden all access to that widget since it can now be null, specially during destruction. As an example, QGestureManager may crash when we delete a top-level widget. The crash stack trace is: 1 QScopedPointer>::data() const 2 QScopedPointer>::pointer qGetPtrHelper>>(QScopedPointer> const&) 3 QWidget::d_func() 4 QGestureManager::filterEvent(QWidget *, QEvent *) <-- the widget ptr is null 5 QGestureManager::filterEvent(QObject *, QEvent *) 6 QApplication::notify(QObject *, QEvent *) 7 QCoreApplication::notifyInternal2(QObject *, QEvent *) 8 QCoreApplication::sendEvent(QObject *, QEvent *) 9 QWindow::destroy() 10 QWidgetPrivate::deleteTLSysExtra() 11 QWidgetPrivate::deleteExtra() 12 QWidgetPrivate::~QWidgetPrivate() 13 QWidgetPrivate::~QWidgetPrivate() 14 QWidgetPrivate::~QWidgetPrivate() 15 QScopedPointerDeleter::cleanup(QObjectData *) 16 QScopedPointer>::~QScopedPointer() 17 QScopedPointer>::~QScopedPointer() 18 QObject::~QObject() 19 QWidget::~QWidget() Task-number: QTBUG-53103 Change-Id: I1bb32648270c4f7791f668b8f0b639ddb4235703 Reviewed-by: Shawn Rutledge Reviewed-by: Marc Mutz --- src/widgets/kernel/qapplication.cpp | 8 ++++---- src/widgets/kernel/qgesturemanager.cpp | 2 +- src/widgets/kernel/qwidgetwindow.cpp | 20 +++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index a459a57482..fcc195f601 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2249,10 +2249,10 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous) QApplication::setActiveWindow(tlw); // QTBUG-37126, Active X controls may set the focus on native child widgets. if (wnd && tlw && wnd != tlw->windowHandle()) { - if (QWidgetWindow *widgetWindow = qobject_cast(wnd)) { - if (widgetWindow->widget()->inherits("QAxHostWidget")) - widgetWindow->widget()->setFocus(Qt::ActiveWindowFocusReason); - } + if (QWidgetWindow *widgetWindow = qobject_cast(wnd)) + if (QWidget *widget = widgetWindow->widget()) + if (widget->inherits("QAxHostWidget")) + widget->setFocus(Qt::ActiveWindowFocusReason); } } diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 967ef6b40c..89ed6922b5 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -545,7 +545,7 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) // filter method. QWidgetWindow *widgetWindow = qobject_cast(receiver); - if (widgetWindow) + if (widgetWindow && widgetWindow->widget()) return filterEvent(widgetWindow->widget(), event); QGesture *state = qobject_cast(receiver); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index ec2618e501..5290d79d9e 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -87,7 +87,7 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const { Q_Q(const QWidgetWindow); const QWidget *widget = q->widget(); - if (!widget->isWindow() || !widget->hasHeightForWidth()) + if (!widget || !widget->isWindow() || !widget->hasHeightForWidth()) return QRect(); const QSize oldSize = rect.size().toSize(); const QSize newSize = QLayout::closestAcceptableSize(widget, oldSize); @@ -142,16 +142,18 @@ QAccessibleInterface *QWidgetWindow::accessibleRoot() const QObject *QWidgetWindow::focusObject() const { - QWidget *widget = m_widget->focusWidget(); + QWidget *windowWidget = m_widget; + if (!windowWidget) + return Q_NULLPTR; + + QWidget *widget = windowWidget->focusWidget(); if (!widget) - widget = m_widget; + widget = windowWidget; - if (widget) { - QObject *focusObj = QWidgetPrivate::get(widget)->focusObject(); - if (focusObj) - return focusObj; - } + QObject *focusObj = QWidgetPrivate::get(widget)->focusObject(); + if (focusObj) + return focusObj; return widget; } @@ -204,7 +206,7 @@ bool QWidgetWindow::event(QEvent *event) #ifndef QT_NO_ACCESSIBILITY QAccessible::State state; state.active = true; - QAccessibleStateChangeEvent ev(widget(), state); + QAccessibleStateChangeEvent ev(m_widget, state); QAccessible::updateAccessibility(&ev); #endif return false; } -- cgit v1.2.3 From acf43c17b647cdbfc3186bb8bf7e183df67a090b Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 1 Mar 2016 15:44:06 +0300 Subject: QFileSystemModel: create nodes with correct QFileInfos Create parent nodes with the corresponding paths, not with the absolute path of the child node. Otherwise we will get incorrect QFileInfo at least in the following case: QFileSystemModel model; model.setRootPath("/usr/bin"); QModelIndex idx = model.setRootPath("/usr"); qDebug() << model.fileInfo(idx).absoluteFilePath(); Without the fix it prints "/usr/bin". It's a regression triggered by 61cefb2f7a7cb16dfa2732e26d2319017039ef62 (De-inline QFileSystemModel::fileInfo() and implement it efficiently). Change-Id: I3b4e5f5b256711e27ad50824eaa8492dbc096808 Task-number: QTBUG-51586 Reviewed-by: Lars Knoll --- src/widgets/dialogs/qfilesystemmodel.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 9bf5a502c3..0e2eee3b47 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -351,6 +351,9 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS ) return const_cast(&root); QModelIndex index = QModelIndex(); // start with "My Computer" + QString elementPath; + QChar separator = QLatin1Char('/'); + QString trailingSeparator; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path QString host = QLatin1String("\\\\") + pathElements.first(); @@ -358,6 +361,8 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS absolutePath.append(QLatin1Char('/')); if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/'))) absolutePath.append(QLatin1Char('/')); + if (absolutePath.endsWith(QLatin1Char('/'))) + trailingSeparator = QLatin1String("\\"); int r = 0; QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast(&root); if (!root.children.contains(host.toLower())) { @@ -374,11 +379,10 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS r = translateVisibleLocation(rootNode, r); index = q->index(r, 0, QModelIndex()); pathElements.pop_front(); - } else -#endif - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - { + separator = QLatin1Char('\\'); + elementPath = host; + elementPath.append(separator); + } else { if (!pathElements.at(0).contains(QLatin1Char(':'))) { QString rootPath = QDir(longPath).rootPath(); pathElements.prepend(rootPath); @@ -396,6 +400,11 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS for (int i = 0; i < pathElements.count(); ++i) { QString element = pathElements.at(i); + if (i != 0) + elementPath.append(separator); + elementPath.append(element); + if (i == pathElements.count() - 1) + elementPath.append(trailingSeparator); #ifdef Q_OS_WIN // On Windows, "filename " and "filename" are equivalent and // "filename . " and "filename" are equivalent @@ -427,7 +436,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS if (!alreadyExisted) { // Someone might call ::index("file://cookie/monster/doesn't/like/veggies"), // a path that doesn't exists, I.E. don't blindly create directories. - QFileInfo info(absolutePath); + QFileInfo info(elementPath); if (!info.exists()) return const_cast(&root); QFileSystemModelPrivate *p = const_cast(this); -- cgit v1.2.3 From 6bcd27b957a5ffcfe7665b0979679510e3b2ae3d Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 10 May 2016 14:35:20 +0200 Subject: Document how to save an application using QUndoStack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic61374d5b6ce395dfe8d0b30813ea437b5e16e9d Task-number: QTBUG-52497 Reviewed-by: Topi Reiniö --- src/widgets/util/qundostack.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 5bcfa57b37..bd41fb60c1 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -623,6 +623,8 @@ void QUndoStack::push(QUndoCommand *cmd) Marks the stack as clean and emits cleanChanged() if the stack was not already clean. + This is typically called when a document is saved, for example. + Whenever the stack returns to this state through the use of undo/redo commands, it emits the signal cleanChanged(). This signal is also emitted when the stack leaves the clean state. -- cgit v1.2.3 From 72e3fcce387d72043dd0b9fbe06d6b720861c1e7 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 10 May 2016 14:54:24 +0200 Subject: Doc: Remove repository name from examplesinstallpath Examples in binary packages now directly match the install path. Change-Id: Ic1487bc766cfd3b0a0a340cc4ae4ba49d953eaa6 Task-number: QTBUG-52953 Reviewed-by: Oswald Buddenhagen --- src/widgets/doc/qtwidgets.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 8160396ca2..f307e9d3e4 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -4,7 +4,7 @@ project = QtWidgets description = Qt Widgets Reference Documentation version = $QT_VERSION -examplesinstallpath = qtbase/widgets +examplesinstallpath = widgets qhp.projects = QtWidgets -- cgit v1.2.3 From 07dd6dbaee5bdcbeebc54f04dccc45ad4778eab4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 30 Mar 2016 13:57:22 +0200 Subject: QLineEdit: Fix icons being too small on a High DPI screen without scaling. Remove the hardcoded size 16 from QLineEditIconButton. Replace QLineEditPrivate::iconSize() by QLineEditPrivate::sideWidgetParameters() returning a struct SideWidgetParameters containing icon size, widget size and margins. The 32x32 icon will then be used on a High DPI screen without scaling. Task-number: QTBUG-49374 Change-Id: I23c4a0cd078a58581c940aacfa65a3ad493c12dc Reviewed-by: Alessandro Portale --- src/widgets/widgets/qlineedit.cpp | 1 - src/widgets/widgets/qlineedit_p.cpp | 35 +++++++++++++++++++++++----------- src/widgets/widgets/qlineedit_p.h | 38 +++++++++++++++++++++++++++---------- 3 files changed, 52 insertions(+), 22 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 6b32665065..2cad5d325c 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -2176,7 +2176,6 @@ void QLineEdit::changeEvent(QEvent *ev) d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)); d->control->setPasswordMaskDelay(style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, this)); } - d->m_iconSize = QSize(); update(); break; case QEvent::LayoutDirectionChange: diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index ff80c45c9a..b90ddacb7e 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -314,6 +314,12 @@ QLineEditIconButton::QLineEditIconButton(QWidget *parent) setFocusPolicy(Qt::NoFocus); } +QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const +{ + QLineEdit *le = qobject_cast(parentWidget()); + return le ? static_cast(qt_widget_private(le)) : Q_NULLPTR; +} + void QLineEditIconButton::paintEvent(QPaintEvent *) { QPainter painter(this); @@ -325,7 +331,9 @@ void QLineEditIconButton::paintEvent(QPaintEvent *) QIcon::Mode state = QIcon::Disabled; if (isEnabled()) state = isDown() ? QIcon::Selected : QIcon::Normal; - const QSize iconSize(IconButtonSize, IconButtonSize); + const QLineEditPrivate *lep = lineEditPrivate(); + const int iconWidth = lep ? lep->sideWidgetParameters().iconSize : 16; + const QSize iconSize(iconWidth, iconWidth); const QPixmap iconPixmap = icon().pixmap(window, iconSize, state, QIcon::Off); QRect pixmapRect = QRect(QPoint(0, 0), iconSize); pixmapRect.moveCenter(rect().center()); @@ -340,8 +348,8 @@ void QLineEditIconButton::actionEvent(QActionEvent *e) const QAction *action = e->action(); if (isVisibleTo(parentWidget()) != action->isVisible()) { setVisible(action->isVisible()); - if (QLineEdit *le = qobject_cast(parentWidget())) - static_cast(qt_widget_private(le))->positionSideWidgets(); + if (QLineEditPrivate *lep = lineEditPrivate()) + lep->positionSideWidgets(); } } break; @@ -407,11 +415,15 @@ void QLineEditPrivate::_q_clearButtonClicked() } } -QSize QLineEditPrivate::iconSize() const +QLineEditPrivate::SideWidgetParameters QLineEditPrivate::sideWidgetParameters() const { - if (!m_iconSize.isValid()) // This might require style-specific handling (pixel metric). - m_iconSize = QSize(QLineEditIconButton::IconButtonSize + 6, QLineEditIconButton::IconButtonSize + 2); - return m_iconSize; + Q_Q(const QLineEdit); + SideWidgetParameters result; + result.iconSize = q->height() < 34 ? 16 : 32; + result.margin = result.iconSize / 4; + result.widgetWidth = result.iconSize + 6; + result.widgetHeight = result.iconSize + 2; + return result; } QIcon QLineEditPrivate::clearButtonIcon() const @@ -437,15 +449,16 @@ void QLineEditPrivate::positionSideWidgets() Q_Q(QLineEdit); if (hasSideWidgets()) { const QRect contentRect = q->rect(); - const QSize iconSize = QLineEditPrivate::iconSize(); - const int delta = QLineEditIconButton::IconMargin + iconSize.width(); - QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize); + const SideWidgetParameters p = sideWidgetParameters(); + const int delta = p.margin + p.widgetWidth; + QRect widgetGeometry(QPoint(p.margin, (contentRect.height() - p.widgetHeight) / 2), + QSize(p.widgetWidth, p.widgetHeight)); foreach (const SideWidgetEntry &e, leftSideWidgetList()) { e.widget->setGeometry(widgetGeometry); if (e.action->isVisible()) widgetGeometry.moveLeft(widgetGeometry.left() + delta); } - widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin); + widgetGeometry.moveLeft(contentRect.width() - p.widgetWidth - p.margin); foreach (const SideWidgetEntry &e, rightSideWidgetList()) { e.widget->setGeometry(widgetGeometry); if (e.action->isVisible()) diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 60372ab393..1d81090b0f 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE +class QLineEditPrivate; + // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text class Q_AUTOTEST_EXPORT QLineEditIconButton : public QToolButton @@ -72,8 +74,6 @@ class Q_AUTOTEST_EXPORT QLineEditIconButton : public QToolButton Q_OBJECT Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) public: - enum { IconMargin = 4, IconButtonSize = 16 }; - explicit QLineEditIconButton(QWidget *parent = 0); qreal opacity() const { return m_opacity; } @@ -93,6 +93,7 @@ private: #ifndef QT_NO_ANIMATION void startOpacityAnimation(qreal endValue); #endif + QLineEditPrivate *lineEditPrivate() const; qreal m_opacity; }; @@ -116,6 +117,13 @@ public: }; typedef QVector SideWidgetEntryList; + struct SideWidgetParameters { + int iconSize; + int widgetWidth; + int widgetHeight; + int margin; + }; + QLineEditPrivate() : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0), dragEnabled(0), clickCausedFocus(0), hscroll(0), vscroll(0), @@ -206,7 +214,7 @@ public: QWidget *addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition, int flags = 0); void removeAction(QAction *action); - QSize iconSize() const; + SideWidgetParameters sideWidgetParameters() const; QIcon clearButtonIcon() const; void setClearButtonEnabled(bool enabled); void positionSideWidgets(); @@ -227,7 +235,6 @@ private: SideWidgetEntryList leadingSideWidgets; SideWidgetEntryList trailingSideWidgets; int lastTextSize; - mutable QSize m_iconSize; }; Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetEntry, Q_PRIMITIVE_TYPE); @@ -238,18 +245,29 @@ static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e) inline int QLineEditPrivate::effectiveLeftTextMargin() const { - return leftTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) - * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(), - isSideWidgetVisible)); + int result = leftTextMargin; + if (!leftSideWidgetList().isEmpty()) { + const SideWidgetParameters p = sideWidgetParameters(); + result += (p.margin + p.widgetWidth) + * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(), + isSideWidgetVisible)); + } + return result; } inline int QLineEditPrivate::effectiveRightTextMargin() const { - return rightTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) - * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(), - isSideWidgetVisible)); + int result = rightTextMargin; + if (!rightSideWidgetList().isEmpty()) { + const SideWidgetParameters p = sideWidgetParameters(); + result += (p.margin + p.widgetWidth) + * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(), + isSideWidgetVisible)); + } + return result; } + #endif // QT_NO_LINEEDIT QT_END_NAMESPACE -- cgit v1.2.3 From 56b5706ce05895d2acab8de55abf5b7d3f69e80f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 3 Jan 2016 12:41:09 -0200 Subject: Remove dead code from QColorDialog Detected by GCC 6. Change-Id: I24a735698d3c4a719fc9ffff1425f193511406f9 Reviewed-by: Lars Knoll --- src/widgets/dialogs/qcolordialog.cpp | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 9a8bfc552d..6a1135920d 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -168,8 +168,6 @@ private: namespace { -struct QWellArrayData; - class QWellArray : public QWidget { Q_OBJECT @@ -189,8 +187,6 @@ public: QSize sizeHint() const Q_DECL_OVERRIDE; - virtual void setCellBrush(int row, int col, const QBrush &); - inline int cellWidth() const { return cellw; } @@ -257,7 +253,6 @@ private: int curCol; int selRow; int selCol; - QWellArrayData *d; }; void QWellArray::paintEvent(QPaintEvent *e) @@ -307,15 +302,10 @@ void QWellArray::paintEvent(QPaintEvent *e) } } -struct QWellArrayData { - QBrush *brush; -}; - QWellArray::QWellArray(int rows, int cols, QWidget *parent) : QWidget(parent) ,nrows(rows), ncols(cols) { - d = 0; setFocusPolicy(Qt::StrongFocus); cellw = 28; cellh = 24; @@ -364,14 +354,12 @@ void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect) */ void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r) { - if (d) { - p->fillRect(r, d->brush[row*numCols()+col]); - } else { - p->fillRect(r, Qt::white); - p->setPen(Qt::black); - p->drawLine(r.topLeft(), r.bottomRight()); - p->drawLine(r.topRight(), r.bottomLeft()); - } + Q_UNUSED(row); + Q_UNUSED(col); + p->fillRect(r, Qt::white); + p->setPen(Qt::black); + p->drawLine(r.topLeft(), r.bottomRight()); + p->drawLine(r.topRight(), r.bottomLeft()); } void QWellArray::mousePressEvent(QMouseEvent *e) @@ -447,17 +435,6 @@ void QWellArray::focusInEvent(QFocusEvent*) emit currentChanged(curRow, curCol); } -void QWellArray::setCellBrush(int row, int col, const QBrush &b) -{ - if (!d) { - d = new QWellArrayData; - int i = numRows()*numCols(); - d->brush = new QBrush[i]; - } - if (row >= 0 && row < numRows() && col >= 0 && col < numCols()) - d->brush[row*numCols()+col] = b; -} - /*!\reimp */ -- cgit v1.2.3 From 474af0a61d6154006966a775d186687aa8881708 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 21 Jan 2016 08:15:18 +0100 Subject: QWidget::mapTo/FromGlobal(): Rewrite using a QTransform. Introduce a function going up the widget hierarchy determining a QTransform for mapping the coordinates applying the transformations of any QGraphicsView instances found. In mapFromGlobal(), use the inverse of it. This fixes the case of widget hierarchies embedded into QGraphicsView with transformations. Increase fuzz in the tests due to float rounding errors. Task-number: QTBUG-41135 Task-number: QTBUG-50030 Task-number: QTBUG-50136 Task-number: QTBUG-52507 Change-Id: I507e0bccd546250fe9c2d1b74ef38657d61490b4 Reviewed-by: Marc Mutz --- src/widgets/kernel/qwidget.cpp | 99 ++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 46 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 48334cd169..0376ab88ac 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12346,6 +12346,53 @@ static inline bool canMapPosition(QWindow *window) return window->handle() && !qt_window_private(window)->resizeEventPending; } +#ifndef QT_NO_GRAPHICSVIEW +static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w) +{ + QGraphicsProxyWidget *result = Q_NULLPTR; + const QWidgetPrivate *d = qt_widget_private(const_cast(w)); + if (d->extra) + result = d->extra->proxyWidget; + return result; +} +#endif // !QT_NO_GRAPHICSVIEW + +struct MapToGlobalTransformResult { + QTransform transform; + QWindow *window; +}; + +static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w) +{ + MapToGlobalTransformResult result; + result.window = Q_NULLPTR; + for ( ; w ; w = w->parentWidget()) { +#ifndef QT_NO_GRAPHICSVIEW + if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) { + if (const QGraphicsScene *scene = qgpw->scene()) { + const QList views = scene->views(); + if (!views.isEmpty()) { + result.transform *= qgpw->sceneTransform(); + result.transform *= views.first()->viewportTransform(); + w = views.first()->viewport(); + } + } + } +#endif // !QT_NO_GRAPHICSVIEW + QWindow *window = w->windowHandle(); + if (window && canMapPosition(window)) { + result.window = window; + break; + } + + const QPoint topLeft = w->geometry().topLeft(); + result.transform.translate(topLeft.x(), topLeft.y()); + if (w->isWindow()) + break; + } + return result; +} + /*! \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const @@ -12357,29 +12404,9 @@ static inline bool canMapPosition(QWindow *window) */ QPoint QWidget::mapToGlobal(const QPoint &pos) const { -#ifndef QT_NO_GRAPHICSVIEW - Q_D(const QWidget); - if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { - const QList views = d->extra->proxyWidget->scene()->views(); - if (!views.isEmpty()) { - const QPointF scenePos = d->extra->proxyWidget->mapToScene(pos); - const QPoint viewPortPos = views.first()->mapFromScene(scenePos); - return views.first()->viewport()->mapToGlobal(viewPortPos); - } - } -#endif // !QT_NO_GRAPHICSVIEW - int x = pos.x(), y = pos.y(); - const QWidget *w = this; - while (w) { - QWindow *window = w->windowHandle(); - if (window && canMapPosition(window)) - return window->mapToGlobal(QPoint(x, y)); - - x += w->data->crect.x(); - y += w->data->crect.y(); - w = w->isWindow() ? 0 : w->parentWidget(); - } - return QPoint(x, y); + const MapToGlobalTransformResult t = mapToGlobalTransform(this); + const QPoint g = t.transform.map(pos); + return t.window ? t.window->mapToGlobal(g) : g; } /*! @@ -12392,29 +12419,9 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const */ QPoint QWidget::mapFromGlobal(const QPoint &pos) const { -#ifndef QT_NO_GRAPHICSVIEW - Q_D(const QWidget); - if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { - const QList views = d->extra->proxyWidget->scene()->views(); - if (!views.isEmpty()) { - const QPoint viewPortPos = views.first()->viewport()->mapFromGlobal(pos); - const QPointF scenePos = views.first()->mapToScene(viewPortPos); - return d->extra->proxyWidget->mapFromScene(scenePos).toPoint(); - } - } -#endif // !QT_NO_GRAPHICSVIEW - int x = pos.x(), y = pos.y(); - const QWidget *w = this; - while (w) { - QWindow *window = w->windowHandle(); - if (window && canMapPosition(window)) - return window->mapFromGlobal(QPoint(x, y)); - - x -= w->data->crect.x(); - y -= w->data->crect.y(); - w = w->isWindow() ? 0 : w->parentWidget(); - } - return QPoint(x, y); + const MapToGlobalTransformResult t = mapToGlobalTransform(this); + const QPoint windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos; + return t.transform.inverted().map(windowLocal); } QWidget *qt_pressGrab = 0; -- cgit v1.2.3 From b627dd2c24c5962c1e8f9d72bcbe9ebdfe6dfceb Mon Sep 17 00:00:00 2001 From: Felix Bourbonnais Date: Tue, 10 May 2016 10:06:53 -0400 Subject: QMenuBar: nested parenting fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QMenuBar now receives a parent changed event for each of its parent, grand-parent, ... This fixes a crash caused by an invalid QWidget pointer and makes sure the keyboard shortcuts events are relayed to the menu bar in all parenting/re-parenting cases by installing an event filter on each parent Task-number: QTBUG-53205 Change-Id: I419e6cbc52e28a67fb08a848a7161b4cb8ae4ae5 Reviewed-by: Gabriel de Dietrich Reviewed-by: Błażej Szczygieł --- src/widgets/widgets/qmenubar.cpp | 55 +++++++++++++++++++++++----------------- src/widgets/widgets/qmenubar_p.h | 3 +-- 2 files changed, 33 insertions(+), 25 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index cca0853a8f..3f42a07f39 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -706,7 +706,6 @@ void QMenuBarPrivate::init() } #endif q->setBackgroundRole(QPalette::Button); - oldWindow = oldParent = 0; handleReparent(); q->setMouseTracking(q->style()->styleHint(QStyle::SH_MenuBar_MouseTracking, 0, q)); @@ -1330,30 +1329,41 @@ void QMenuBarPrivate::handleReparent() { Q_Q(QMenuBar); QWidget *newParent = q->parentWidget(); - //Note: if parent is reparented, then window may change even if parent doesn't - // we need to install an event filter on parent, and remove the old one - - if (oldParent != newParent) { - if (oldParent) - oldParent->removeEventFilter(q); - if (newParent) - newParent->installEventFilter(q); + //Note: if parent is reparented, then window may change even if parent doesn't. + // We need to install an avent filter on each parent up to the parent that is + // also a window (for shortcuts) + QWidget *newWindow = newParent ? newParent->window() : Q_NULLPTR; + + QVector > newParents; + // Remove event filters on ex-parents, keep them on still-parents + // The parents are always ordered in the vector + foreach (const QPointer &w, oldParents) { + if (w) { + if (newParent == w) { + newParents.append(w); + if (newParent != newWindow) //stop at the window + newParent = newParent->parentWidget(); + } else { + w->removeEventFilter(q); + } + } } - //we also need event filter on top-level (for shortcuts) - QWidget *newWindow = newParent ? newParent->window() : 0; - - if (oldWindow != newWindow) { - if (oldParent && oldParent != oldWindow) - oldWindow->removeEventFilter(q); - - if (newParent && newParent != newWindow) - newWindow->installEventFilter(q); + // At this point, newParent is the next one to be added to newParents + while (newParent && newParent != newWindow) { + //install event filters all the way up to (excluding) the window + newParents.append(newParent); + newParent->installEventFilter(q); + newParent = newParent->parentWidget(); } - oldParent = newParent; - oldWindow = newWindow; + if (newParent && newWindow) { + // Install the event filter on the window + newParents.append(newParent); + newParent->installEventFilter(q); + } + oldParents = newParents; if (platformMenuBar) { if (newWindow) { @@ -1465,10 +1475,9 @@ bool QMenuBar::event(QEvent *e) bool QMenuBar::eventFilter(QObject *object, QEvent *event) { Q_D(QMenuBar); - if (object == parent() && object) { - if (event->type() == QEvent::ParentChange) //GrandparentChange + if (object && (event->type() == QEvent::ParentChange)) //GrandparentChange d->handleReparent(); - } + if (object == d->leftWidget || object == d->rightWidget) { switch (event->type()) { case QEvent::ShowToParent: diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h index ee615e71f3..7ef696f50e 100644 --- a/src/widgets/widgets/qmenubar_p.h +++ b/src/widgets/widgets/qmenubar_p.h @@ -128,8 +128,7 @@ public: // reparenting void handleReparent(); - QWidget *oldParent; - QWidget *oldWindow; + QVector > oldParents; QList hiddenActions; //default action -- cgit v1.2.3