From 4b975405d70529408b2422e42720a80152746c20 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 5 Oct 2016 14:27:55 +0200 Subject: QTextEdit: don't show placeholder text while composing text If using IM to compose text in QTextEdit, the placeholder text will show underneath until the text is committed. This patch will additionally check if the user is currently composing preedit text before deciding whether or not to draw the placeholder text. Task-number: QTBUG-55758 Change-Id: If7943c6c94fb96d46514a81caa118829e6e6a0f9 Reviewed-by: Liang Qi --- src/widgets/widgets/qtextedit.cpp | 2 +- src/widgets/widgets/qwidgettextcontrol.cpp | 5 +++++ src/widgets/widgets/qwidgettextcontrol_p.h | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 28666f76ce..7e4b86d8fd 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1506,7 +1506,7 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) if (layout) layout->setViewport(QRect()); - if (!placeholderText.isEmpty() && doc->isEmpty()) { + if (!placeholderText.isEmpty() && doc->isEmpty() && !control->isPreediting()) { QColor col = control->palette().text().color(); col.setAlpha(128); p->setPen(col); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index deca002bf5..4199ae537d 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -2557,6 +2557,11 @@ bool QWidgetTextControl::isWordSelectionEnabled() const return d->wordSelectionEnabled; } +bool QWidgetTextControl::isPreediting() +{ + return d_func()->isPreediting(); +} + #ifndef QT_NO_PRINTER void QWidgetTextControl::print(QPagedPaintDevice *printer) const { diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h index c1180fd665..cd5abf4f5d 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p.h @@ -166,6 +166,8 @@ public: bool isWordSelectionEnabled() const; void setWordSelectionEnabled(bool enabled); + bool isPreediting(); + void print(QPagedPaintDevice *printer) const; virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const; -- cgit v1.2.3 From 0bf0c3e184448e91a7ddbd20b03997538ae19f41 Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Thu, 29 Sep 2016 17:07:00 +0200 Subject: Use the same object in description as in described code Change-Id: If52ecfc8d29a83cb2949fbbf4672ae386ae5d739 Reviewed-by: Shawn Rutledge Reviewed-by: Venugopal Shivashankar --- src/widgets/doc/src/model-view-programming.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/doc/src/model-view-programming.qdoc b/src/widgets/doc/src/model-view-programming.qdoc index 784e25b1d9..7e278b8c91 100644 --- a/src/widgets/doc/src/model-view-programming.qdoc +++ b/src/widgets/doc/src/model-view-programming.qdoc @@ -737,7 +737,7 @@ \image spinboxdelegate-example.png - We subclass the delegate from \l QItemDelegate because we do not want + We subclass the delegate from \l QStyledItemDelegate because we do not want to write custom display functions. However, we must still provide functions to manage the editor widget: -- cgit v1.2.3 From daaa1a287bcccda61ce81941f8b3a69d2371e04a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 28 Sep 2016 10:37:59 +0200 Subject: Plug leak in QFormLayout::setWidget() Unlike layouts and spacer items, a QWidget is-not-a QLayoutItem. QWidgetItem simply wraps the QWidget, so in QFormLayout::setWidget(), we allocate a widget item for the widget passed, and hand that down to Private::setItem() for adding to the various data structures. Private::setItem() has a bunch of guard clauses, though, that return without deleting the item. A test triggered this code path and made asan complain. This is just one part of a larger problem: QFormLayout::setLayout() normally takes ownership of the layout passed, because QLayouts own their QLayoutItems, and QLayout is-a QLayoutItem. But setLayout() fails to live up to the owner role when it fails to add a layout, and there's no easy way for the API user to check for success. A fix for this breaks tst_qformlayout, and while those checks that break deserve to be broken, I'll refrain from proposing the larger fix for 5.6 LTS, but will propose it for 5.8 or 5.9 instead. This fix here only fixes the leak in setWidget() by adding a bool return to Private::setItem() informing Private::setWidget() of the need to manually delete the item it allocated for the widget. Change-Id: I81409c260f9bee2e95c9a98542d8c60bc19a1332 Reviewed-by: Thiago Macieira Reviewed-by: Giuseppe D'Angelo --- src/widgets/kernel/qformlayout.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index 24bf80f16c..0ae617d945 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -179,7 +179,7 @@ public: int insertRow(int row); void insertRows(int row, int count); - void setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item); + bool setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item); void setLayout(int row, QFormLayout::ItemRole role, QLayout *layout); void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget); @@ -941,21 +941,21 @@ void QFormLayoutPrivate::insertRows(int row, int count) } } -void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item) +bool QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item) { const bool fullRow = role == QFormLayout::SpanningRole; const int column = role == QFormLayout::SpanningRole ? 1 : static_cast(role); if (uint(row) >= uint(m_matrix.rowCount()) || uint(column) > 1U) { qWarning("QFormLayoutPrivate::setItem: Invalid cell (%d, %d)", row, column); - return; + return false; } if (!item) - return; + return false; if (m_matrix(row, column)) { qWarning("QFormLayoutPrivate::setItem: Cell (%d, %d) already occupied", row, column); - return; + return false; } QFormLayoutItem *i = new QFormLayoutItem(item); @@ -963,6 +963,7 @@ void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutIte m_matrix(row, column) = i; m_things.append(i); + return true; } void QFormLayoutPrivate::setLayout(int row, QFormLayout::ItemRole role, QLayout *layout) @@ -979,7 +980,9 @@ void QFormLayoutPrivate::setWidget(int row, QFormLayout::ItemRole role, QWidget if (widget) { Q_Q(QFormLayout); q->addChildWidget(widget); - setItem(row, role, QLayoutPrivate::createWidgetItem(q, widget)); + QWidgetItem *item = QLayoutPrivate::createWidgetItem(q, widget); + if (!setItem(row, role, item)) + delete item; } } -- cgit v1.2.3 From 237b36a72cf0646ba28e762bfde0cb398f4041e8 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Sep 2016 09:15:40 +0200 Subject: QGraphicsWidget: Fix UB (invalid member calls) in destruction sequence Found by UBSan: qgraphicswidget_p.h:72:5: runtime error: downcast of address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget' 0x2ab6a8021400: note: object is of type 'QGraphicsObject' 00 00 00 00 70 93 5c 91 b6 2a 00 00 f0 c0 01 a8 b6 2a 00 00 e8 81 5c 91 b6 2a 00 00 10 bf 01 a8 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QGraphicsObject' #0 0x2ab68f2fdd7c in QGraphicsWidgetPrivate::q_func() qgraphicswidget_p.h:72 #1 0x2ab68f2fdd7c in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:775 #2 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181 #3 0x2ab68f024f73 in QGraphicsItem::setParentItem(QGraphicsItem*) qgraphicsitem.cpp:1781 #4 0x2ab68f168401 in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) qgraphicsscene.cpp:620 #5 0x2ab68f02c166 in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1555 #6 0x2ab68f02ebb8 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766 #7 0x2ab68f2d8888 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231 #8 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175 #9 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175 #10 0x2ab68f02c9ec in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1550 #11 0x2ab68f02ebb8 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766 #12 0x2ab68f2d8888 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231 #13 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175 #14 0x4bce62 in SubQGraphicsWidget::~SubQGraphicsWidget() /tst_qgraphicswidget.cpp:175 #15 0x2ab68f128da4 in QGraphicsScene::clear() qgraphicsscene.cpp:2388 #16 0x2ab68f12936c in QGraphicsScene::~QGraphicsScene() qgraphicsscene.cpp:1682 #17 0x44d44c in tst_QGraphicsWidget::focusWidget() /tst_qgraphicswidget.cpp:435 qgraphicswidget_p.cpp:805:24: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget' 0x2ab6a8021400: note: object is of type 'QGraphicsObject' 00 00 00 00 70 93 5c 91 b6 2a 00 00 f0 c0 01 a8 b6 2a 00 00 e8 81 5c 91 b6 2a 00 00 10 bf 01 a8 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QGraphicsObject' #0 0x2ab68f2fdc68 in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:805 #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181 [... identical lines omitted ...] qgraphicswidget_p.cpp:806:23: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget' 0x2ab6a8021400: note: object is of type 'QGraphicsObject' 00 00 00 00 70 93 5c 91 b6 2a 00 00 f0 c0 01 a8 b6 2a 00 00 e8 81 5c 91 b6 2a 00 00 10 bf 01 a8 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QGraphicsObject' #0 0x2ab68f2fdb6b in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:806 #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181 [... identical lines omitted ...] qgraphicswidget_p.cpp:827:26: runtime error: member call on address 0x2ab6a8021400 which does not point to an object of type 'QGraphicsWidget' 0x2ab6a8021400: note: object is of type 'QGraphicsObject' 00 00 00 00 70 93 5c 91 b6 2a 00 00 f0 c0 01 a8 b6 2a 00 00 e8 81 5c 91 b6 2a 00 00 10 bf 01 a8 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QGraphicsObject' #0 0x2ab68f2fdf91 in QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget*, QGraphicsScene*, QGraphicsScene*) qgraphicswidget_p.cpp:827 #1 0x2ab68f020d2a in QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem*, QVariant const*, QVariant const*) qgraphicsitem.cpp:1181 [... identical lines omitted ...] Fix by moving the setParentItem(nullptr) call up the call stack into ~QGraphicsWidget(), ensuring that the object is still a QGraphicsWidget when these calls are made. Change-Id: I264779e33098e9752de9a312a146fb203578a3cc Reviewed-by: Thiago Macieira Reviewed-by: Giuseppe D'Angelo --- src/widgets/graphicsview/qgraphicswidget.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index 2700605a71..125174627d 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -267,6 +267,11 @@ QGraphicsWidget::~QGraphicsWidget() // Remove this graphics widget from widgetStyles widgetStyles()->setStyleForWidget(this, 0); + + // Unset the parent here, when we're still a QGraphicsWidget. + // It is otherwise done in ~QGraphicsItem() where we'd be + // calling QGraphicsWidget members on an ex-QGraphicsWidget object + setParentItem(Q_NULLPTR); } /*! -- cgit v1.2.3 From c353bf0033b0f1b433f803bd81922e484f1e3a98 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Thu, 6 Oct 2016 18:36:12 +0100 Subject: Link to topLevelChanged() in the docs of QDockWidget::floating topLevelChanged() is emitted when the floating property changes. It's not very well named, it's easy to miss. Change-Id: Iabaa4fb3dc6190df43d719ed7565f0586816c6de Reviewed-by: Martin Smith --- src/widgets/widgets/qdockwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 20f35cb211..03423be647 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1311,7 +1311,9 @@ QDockWidget::DockWidgetFeatures QDockWidget::features() const By default, this property is \c true. - \sa isWindow() + When this property changes, the \c {topLevelChanged()} signal is emitted. + + \sa isWindow(), topLevelChanged() */ void QDockWidget::setFloating(bool floating) { -- cgit v1.2.3 From 5cc0d92c2493aea8397a51eea80167abdd6a1fa6 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Wed, 18 May 2016 19:25:36 +0200 Subject: QAbstractItemView: use only a 1x1 QRect for selecting on mouse press MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before commit f1e90768095be37419ba4bf3c69ec5c860bdbcb6, mousePressEvent called the virtual method setSelection(const QRect&, SelectionFlags) with the 1x1 rectangle which contains only the clicked QPoint, unless the SelectionFlag "Current" was set because Shift was pressed during the mouse press. Since that commit, the behavior has been changed such that the rectangle is the one that is spanned by the center of the clicked item and the clicked pixel. In theory, the result should be the same (i.e., only the clicked item should be selected), but * the code path in QListView::setSelection for 1x1 QRects is more efficient, and * using a larger QRect can cause problems with custom views, see the comments in QTBUG-18009 This commit ensures that the 1x1 QRect is used again, unless the SelectionFlag "Current" is used. Change-Id: I70dd70c083c20a3af6cd6095aa89a489756b505f Task-number: QTBUG-18009 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qabstractitemview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index d36431c716..4dd8ad0215 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1735,13 +1735,18 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) d->autoScroll = false; d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); d->autoScroll = autoScroll; - QRect rect(visualRect(d->currentSelectionStartIndex).center(), pos); if (command.testFlag(QItemSelectionModel::Toggle)) { command &= ~QItemSelectionModel::Toggle; d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; command |= d->ctrlDragSelectionFlag; } - setSelection(rect, command); + + if ((command & QItemSelectionModel::Current) == 0) { + setSelection(QRect(pos, QSize(1, 1)), command); + } else { + QRect rect(visualRect(d->currentSelectionStartIndex).center(), pos); + setSelection(rect, command); + } // signal handlers may change the model emit pressed(index); -- cgit v1.2.3