diff options
author | Liang Qi <liang.qi@qt.io> | 2016-05-12 07:31:50 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-05-12 08:33:08 +0200 |
commit | 990969655c5fb4d03682e96df9b12101f5ee9815 (patch) | |
tree | b8fb5c50285105c8bc5a938fb50f93ff9f24889d /src/widgets | |
parent | a213011a53f12f101d08a04afc8fdacd2d54a232 (diff) | |
parent | e64b2234e829cc47872225debcf80d6c06db18f0 (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
config_help.txt
configure
src/corelib/io/qprocess_wince.cpp
src/plugins/platforms/windows/qwindowstheme.cpp
src/plugins/platforms/xcb/qxcbbackingstore.cpp
tests/auto/corelib/tools/qtimezone/BLACKLIST
tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
Change-Id: I26644d1cb3b78412c8ff285e2a55bea1bd641c01
Diffstat (limited to 'src/widgets')
30 files changed, 324 insertions, 210 deletions
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 5357cf28f7..e5f11e78da 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3588,7 +3588,7 @@ void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index) } } else { // Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE) - if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) + if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, Q_NULLPTR, qFileDialogUi->treeView) || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL)) { q->accept(); } diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 2f7edd8d07..1d07c31476 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -867,9 +867,11 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in if (newName == idx.data().toString()) return true; + const QString parentPath = filePath(parent(idx)); + if (newName.isEmpty() || QDir::toNativeSeparators(newName).contains(QDir::separator()) - || !QDir(filePath(parent(idx))).rename(oldName, newName)) { + || !QDir(parentPath).rename(oldName, newName)) { #ifndef QT_NO_MESSAGEBOX QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"), QFileSystemModel::tr("<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.") @@ -896,7 +898,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in parentNode->visibleChildren.removeAt(visibleLocation); QFileSystemModelPrivate::QFileSystemNode * oldValue = parentNode->children.value(oldName); parentNode->children[newName] = oldValue; - QFileInfo info(d->rootDir, newName); + QFileInfo info(parentPath, newName); oldValue->fileName = newName; oldValue->parent = parentNode; #ifndef QT_NO_FILESYSTEMWATCHER @@ -908,7 +910,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in parentNode->visibleChildren.insert(visibleLocation, newName); d->delayedSort(); - emit fileRenamed(filePath(idx.parent()), oldName, newName); + emit fileRenamed(parentPath, oldName, newName); } return true; } diff --git a/src/widgets/dialogs/qfilesystemmodel.h b/src/widgets/dialogs/qfilesystemmodel.h index b7e77f31db..6d50d0b606 100644 --- a/src/widgets/dialogs/qfilesystemmodel.h +++ b/src/widgets/dialogs/qfilesystemmodel.h @@ -81,6 +81,7 @@ public: QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QModelIndex index(const QString &path, int column = 0) const; QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE; + using QObject::parent; QModelIndex sibling(int row, int column, const QModelIndex &idx) const Q_DECL_OVERRIDE; bool hasChildren(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE; diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 994015030f..3c46f4faca 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -2605,8 +2605,17 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb default: break; } - if (!tmpIcon.isNull()) - return tmpIcon.pixmap(iconSize, iconSize); + if (!tmpIcon.isNull()) { + QWindow *window = Q_NULLPTR; + if (mb) { + window = mb->windowHandle(); + if (!window) { + if (const QWidget *nativeParent = mb->nativeParentWidget()) + window = nativeParent->windowHandle(); + } + } + return tmpIcon.pixmap(window, QSize(iconSize, iconSize)); + } return QPixmap(); } diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 9306b20043..7b393463a6 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3013,30 +3013,41 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c { Q_D(const QHeaderView); const int max = d->modelSectionCount(); - if (d->orientation == Qt::Horizontal) { - int left = max; - int right = 0; - int rangeLeft, rangeRight; - for (const auto &r : selection) { - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items and we don't want invalid ranges - // FIXME an item inside the range may be the leftmost or rightmost - rangeLeft = visualIndex(r.left()); - if (rangeLeft == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeRight = visualIndex(r.right()); - if (rangeRight == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeLeft < left) - left = rangeLeft; - if (rangeRight > right) - right = rangeRight; + if (d->orientation == Qt::Horizontal) { + int logicalLeft = max; + int logicalRight = 0; + + if (d->visualIndices.empty()) { + // If no reordered sections, skip redundant visual-to-logical transformations + for (const auto &r : selection) { + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + if (r.left() < logicalLeft) + logicalLeft = r.left(); + if (r.right() > logicalRight) + logicalRight = r.right(); + } + } else { + int left = max; + int right = 0; + for (const auto &r : selection) { + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + for (int k = r.left(); k <= r.right(); ++k) { + int visual = visualIndex(k); + if (visual == -1) // in some cases users may change the selections + continue; // before we have a chance to do the layout + if (visual < left) + left = visual; + if (visual > right) + right = visual; + } + } + logicalLeft = logicalIndex(left); + logicalRight = logicalIndex(right); } - int logicalLeft = logicalIndex(left); - int logicalRight = logicalIndex(right); - if (logicalLeft < 0 || logicalLeft >= count() || logicalRight < 0 || logicalRight >= count()) return QRegion(); @@ -3047,31 +3058,44 @@ QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) c return QRect(leftPos, 0, rightPos - leftPos, height()); } // orientation() == Qt::Vertical - int top = max; - int bottom = 0; - int rangeTop, rangeBottom; - - for (const auto &r : selection) { - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items - // FIXME an item inside the range may be the leftmost or rightmost - rangeTop = visualIndex(r.top()); - if (rangeTop == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeBottom = visualIndex(r.bottom()); - if (rangeBottom == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeTop < top) - top = rangeTop; - if (rangeBottom > bottom) - bottom = rangeBottom; - } - - int logicalTop = logicalIndex(top); - int logicalBottom = logicalIndex(bottom); - - if (logicalTop == -1 || logicalBottom == -1) - return QRect(); + int logicalTop = max; + int logicalBottom = 0; + + if (d->visualIndices.empty()) { + // If no reordered sections, skip redundant visual-to-logical transformations + for (const auto &r : selection) { + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + if (r.top() < logicalTop) + logicalTop = r.top(); + if (r.bottom() > logicalBottom) + logicalBottom = r.bottom(); + } + } else { + int top = max; + int bottom = 0; + + for (const auto &r : selection) { + if (r.parent().isValid() || !r.isValid()) + continue; // we only know about toplevel items and we don't want invalid ranges + for (int k = r.top(); k <= r.bottom(); ++k) { + int visual = visualIndex(k); + if (visual == -1) // in some cases users may change the selections + continue; // before we have a chance to do the layout + if (visual < top) + top = visual; + if (visual > bottom) + bottom = visual; + } + } + + logicalTop = logicalIndex(top); + logicalBottom = logicalIndex(bottom); + } + + if (logicalTop < 0 || logicalTop >= count() || + logicalBottom < 0 || logicalBottom >= count()) + return QRegion(); int topPos = sectionViewportPosition(logicalTop); int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index a8a0968ff8..4ff466e04b 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -454,6 +454,9 @@ QDesktopWidget *qt_desktopWidget = 0; // root window widgets */ void QApplicationPrivate::process_cmdline() { + if (styleOverride.isEmpty() && qEnvironmentVariableIsSet("QT_STYLE_OVERRIDE")) + styleOverride = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE")); + if (!styleOverride.isEmpty()) { if (app_style) { delete app_style; @@ -1086,11 +1089,8 @@ QStyle *QApplication::style() // Compile-time search for default style // QString style; - QString envStyle = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE")); if (!QApplicationPrivate::styleOverride.isEmpty()) { style = QApplicationPrivate::styleOverride.toLower(); - } else if (!envStyle.isEmpty()) { - style = envStyle; } else { style = QApplicationPrivate::desktopStyleKey(); } diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp index 7adccb9ed3..6dedd3c2d0 100644 --- a/src/widgets/kernel/qmacgesturerecognizer.cpp +++ b/src/widgets/kernel/qmacgesturerecognizer.cpp @@ -121,7 +121,8 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e case Qt::ZoomNativeGesture: g->setLastScaleFactor(g->scaleFactor()); g->setLastRotationAngle(g->rotationAngle()); - g->setScaleFactor(g->scaleFactor() * (1 + ev->value())); + g->setScaleFactor(1 + ev->value()); + g->setTotalScaleFactor(g->totalScaleFactor() * g->scaleFactor()); g->setChangeFlags(QPinchGesture::ScaleFactorChanged); g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); g->setHotSpot(ev->screenPos()); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 426f206480..217a075b07 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -385,6 +385,7 @@ void QWidgetPrivate::updateWidgetTransform(QEvent *event) t.translate(p.x(), p.y()); QGuiApplication::inputMethod()->setInputItemTransform(t); QGuiApplication::inputMethod()->setInputItemRectangle(q->rect()); + QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle); } } @@ -5258,7 +5259,9 @@ QPixmap QWidget::grab(const QRect &rectangle) if (!r.intersects(rect())) return QPixmap(); - QPixmap res(r.size()); + const qreal dpr = devicePixelRatioF(); + QPixmap res((QSizeF(r.size()) * dpr).toSize()); + res.setDevicePixelRatio(dpr); if (!d->isOpaque) res.fill(Qt::transparent); d->render(&res, QPoint(), QRegion(r), renderFlags); @@ -9763,6 +9766,8 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const return inputMethodQuery(Qt::ImCursorPosition); case Qt::ImHints: return (int)inputMethodHints(); + case Qt::ImInputItemClipRectangle: + return d_func()->clipRect(); default: return QVariant(); } diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp index e59c35ed68..743166549b 100644 --- a/src/widgets/styles/qandroidstyle.cpp +++ b/src/widgets/styles/qandroidstyle.cpp @@ -838,7 +838,7 @@ int QAndroidStyle::Android9PatchDrawable::calculateStretch(int boundsLimit, void QAndroidStyle::Android9PatchDrawable::extractIntArray(const QVariantList &values, QVector<int> & array) { - foreach (QVariant value, values) + for (const QVariant &value : values) array << value.toInt(); } @@ -1140,8 +1140,8 @@ QAndroidStyle::AndroidStateDrawable::AndroidStateDrawable(const QVariantMap &dra QAndroidStyle::ItemType itemType) : AndroidDrawable(drawable, itemType) { - QVariantList states = drawable.value(QLatin1String("stateslist")).toList(); - foreach (QVariant stateVariant, states) { + const QVariantList states = drawable.value(QLatin1String("stateslist")).toList(); + for (const QVariant &stateVariant : states) { QVariantMap state = stateVariant.toMap(); const int s = extractState(state.value(QLatin1String("states")).toMap()); if (-1 == s) @@ -1158,7 +1158,7 @@ QAndroidStyle::AndroidStateDrawable::AndroidStateDrawable(const QVariantMap &dra QAndroidStyle::AndroidStateDrawable::~AndroidStateDrawable() { - foreach (const StateType type, m_states) + for (const StateType &type : qAsConst(m_states)) delete type.second; } @@ -1192,7 +1192,7 @@ const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::best } uint bestCost = 0xffff; - foreach (const StateType & state, m_states) { + for (const StateType & state : m_states) { if (int(opt->state) == state.first) return state.second; uint cost = 1; @@ -1234,8 +1234,9 @@ const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::best int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value) { QStyle::State state = QStyle::State_Enabled | QStyle::State_Active;; - foreach (const QString &key, value.keys()) { - bool val = value.value(key).toString() == QLatin1String("true"); + for (auto it = value.cbegin(), end = value.cend(); it != end; ++it) { + const QString &key = it.key(); + bool val = it.value().toString() == QLatin1String("true"); if (key == QLatin1String("enabled")) { state.setFlag(QStyle::State_Enabled, val); continue; @@ -1282,7 +1283,7 @@ int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value) void QAndroidStyle::AndroidStateDrawable::setPaddingLeftToSizeWidth() { - foreach (const StateType type, m_states) + for (const StateType &type : qAsConst(m_states)) const_cast<AndroidDrawable *>(type.second)->setPaddingLeftToSizeWidth(); } @@ -1293,8 +1294,8 @@ QAndroidStyle::AndroidLayerDrawable::AndroidLayerDrawable(const QVariantMap &dra m_id = 0; m_factor = 1; m_orientation = Qt::Horizontal; - QVariantList layers = drawable.value(QLatin1String("layers")).toList(); - foreach (QVariant layer, layers) { + const QVariantList layers = drawable.value(QLatin1String("layers")).toList(); + for (const QVariant &layer : layers) { QVariantMap layerMap = layer.toMap(); AndroidDrawable *ad = fromMap(layerMap, itemType); if (ad) { @@ -1308,7 +1309,7 @@ QAndroidStyle::AndroidLayerDrawable::AndroidLayerDrawable(const QVariantMap &dra QAndroidStyle::AndroidLayerDrawable::~AndroidLayerDrawable() { - foreach (const LayerType &layer, m_layers) + for (const LayerType &layer : qAsConst(m_layers)) delete layer.second; } @@ -1326,7 +1327,7 @@ void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::O void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const { - foreach (const LayerType &layer, m_layers) { + for (const LayerType &layer : m_layers) { if (layer.first == m_id) { QStyleOption copy(*opt); if (m_orientation == Qt::Horizontal) @@ -1342,7 +1343,7 @@ void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOp QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidLayerDrawable::layer(int id) const { - foreach (const LayerType &layer, m_layers) + for (const LayerType &layer : m_layers) if (layer.first == id) return layer.second; return 0; @@ -1351,7 +1352,7 @@ QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidLayerDrawable::layer(int i QSize QAndroidStyle::AndroidLayerDrawable::size() const { QSize sz; - foreach (const LayerType &layer, m_layers) + for (const LayerType &layer : m_layers) sz = sz.expandedTo(layer.second->size()); return sz; } diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 91d4bcc7ab..6b9e5577a4 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -4985,7 +4985,11 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget break; case SH_BlinkCursorWhenTextSelected: +#if defined(Q_OS_DARWIN) + ret = 0; +#else ret = 1; +#endif break; case SH_Table_GridLineColor: diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index a9cea0e2ab..8a768443d1 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -3414,12 +3414,28 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom QSize textSize = option->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget); int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); + + const int width = textSize.width() + + (option->subControls & QStyle::SC_GroupBoxCheckBox ? indicatorWidth + 5 : 0); + rect = QRect(); + + if (option->rect.width() > width) { + switch (groupBox->textAlignment & Qt::AlignHorizontal_Mask) { + case Qt::AlignHCenter: + rect.moveLeft((option->rect.width() - width) / 2); + break; + case Qt::AlignRight: + rect.moveLeft(option->rect.width() - width); + break; + } + } + if (subControl == SC_GroupBoxCheckBox) { rect.setWidth(indicatorWidth); rect.setHeight(indicatorHeight); rect.moveTop(textSize.height() > indicatorHeight ? (textSize.height() - indicatorHeight) / 2 : 0); - rect.moveLeft(1); + rect.translate(1, 0); } else if (subControl == SC_GroupBoxLabel) { rect.setSize(textSize); rect.moveTop(1); diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 16a11e6029..d72a898ee9 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -157,10 +157,10 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C Qt's built-in widgets use QStyle to perform nearly all of their drawing, ensuring that they look exactly like the equivalent - native widgets. The diagram below shows a QComboBox in eight + native widgets. The diagram below shows a QComboBox in nine different styles. - \image qstyle-comboboxes.png Eight combo boxes + \image qstyle-comboboxes.png Nine combo boxes Topics: diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 2b2b919818..dce0a93e10 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -426,9 +426,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt case PE_IndicatorBranch: { - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::TreeViewTheme); + XPThemeData theme(widget, painter, QWindowsXPStylePrivate::VistaTreeViewTheme); static int decoration_size = 0; - if (!decoration_size && d->initTreeViewTheming() && theme.isValid()) { + if (!decoration_size && theme.isValid()) { XPThemeData themeSize = theme; themeSize.partId = TVP_HOTGLYPH; themeSize.stateId = GLPS_OPENED; @@ -728,9 +728,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt QPainter pixmapPainter(&pixmap); XPThemeData theme(widget, &pixmapPainter, - QWindowsXPStylePrivate::TreeViewTheme, + QWindowsXPStylePrivate::VistaTreeViewTheme, LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height())); - if (d->initTreeViewTheming() && theme.isValid()) { + if (theme.isValid()) { d->drawBackground(theme); } else { QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget); @@ -1149,7 +1149,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) alignment |= Qt::TextHideMnemonic; - if (widget) { // Not needed for QtQuick Controls + if (widget && mbi->palette.color(QPalette::Window) != Qt::transparent) { // Not needed for QtQuick Controls //The rect adjustment is a workaround for the menu not really filling its background. XPThemeData theme(widget, painter, QWindowsXPStylePrivate::MenuTheme, @@ -2357,10 +2357,6 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) QWindowsXPStyle::unpolish(widget); QWindowsVistaStylePrivate *d = d_func(); - // Delete the tree view helper in case the XP style cleaned the - // theme handle map due to a theme or QStyle change (QProxyStyle). - if (!QWindowsXPStylePrivate::hasTheme(QWindowsXPStylePrivate::TreeViewTheme)) - d->cleanupTreeViewTheming(); d->stopAnimation(widget); @@ -2426,15 +2422,10 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const } QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : - QWindowsXPStylePrivate(), m_treeViewHelper(0) + QWindowsXPStylePrivate() { } -QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() -{ - cleanupTreeViewTheming(); -} - bool QWindowsVistaStylePrivate::transitionsEnabled() const { BOOL animEnabled = false; @@ -2446,58 +2437,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const return false; } -/* - * We need to set the windows "explorer" theme explicitly on a native - * window and open the "TREEVIEW" theme handle passing its window handle - * in order to get Vista-style item view themes (particulary drawBackground() - * for selected items needs this). - * We invoke a service of the native Windows interface to create - * a non-visible window handle, open the theme on it and insert it into - * the cache so that it is found by XPThemeData::handle() first. - */ - -static inline HWND createTreeViewHelperWindow() -{ - if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) { - void *hwnd = 0; - void *wndProc = reinterpret_cast<void *>(DefWindowProc); - if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, - Q_RETURN_ARG(void *, hwnd), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), - Q_ARG(void *, wndProc)) && hwnd) { - return reinterpret_cast<HWND>(hwnd); - } - } - return 0; -} - -bool QWindowsVistaStylePrivate::initTreeViewTheming() -{ - if (m_treeViewHelper) - return true; - - m_treeViewHelper = createTreeViewHelperWindow(); - if (Q_UNLIKELY(!m_treeViewHelper)) { - qWarning("Unable to create the treeview helper window."); - return false; - } - const HRESULT hr = QWindowsXPStylePrivate::pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); - if (Q_UNLIKELY(hr != S_OK)) { - qErrnoWarning("SetWindowTheme() failed."); - return false; - } - return QWindowsXPStylePrivate::createTheme(QWindowsXPStylePrivate::TreeViewTheme, m_treeViewHelper); -} - -void QWindowsVistaStylePrivate::cleanupTreeViewTheming() -{ - if (m_treeViewHelper) { - DestroyWindow(m_treeViewHelper); - m_treeViewHelper = 0; - } -} - /*! \reimp */ diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h index 7adfbb08ec..e207a27a66 100644 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p_p.h @@ -168,16 +168,10 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate public: QWindowsVistaStylePrivate(); - ~QWindowsVistaStylePrivate(); + static int fixedPixelMetric(QStyle::PixelMetric pm); static inline bool useVista(); bool transitionsEnabled() const; - -private: - bool initTreeViewTheming(); - void cleanupTreeViewTheming(); - - HWND m_treeViewHelper; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 1f910d41cb..b39cecbd73 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -54,6 +54,8 @@ #include <qbackingstore.h> #include <qapplication.h> #include <qpixmapcache.h> +#include <private/qapplication_p.h> +#include <qpa/qplatformnativeinterface.h> #include <qdesktopwidget.h> #include <qtoolbutton.h> @@ -163,7 +165,7 @@ static const wchar_t *themeNames[QWindowsXPStylePrivate::NThemes] = L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW", L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN", L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR", - L"TREEVIEW", L"WINDOW", L"STATUS" + L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW" }; static inline QBackingStore *backingStoreForWidget(const QWidget *widget) @@ -244,6 +246,7 @@ HRGN XPThemeData::mask(QWidget *widget) // QWindowsXPStylePrivate ------------------------------------------------------------------------- // Static initializations QPixmap *QWindowsXPStylePrivate::tabbody = 0; +HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = 0; HTHEME QWindowsXPStylePrivate::m_themes[NThemes]; bool QWindowsXPStylePrivate::use_xp = false; QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting @@ -327,6 +330,58 @@ void QWindowsXPStylePrivate::cleanup(bool force) tabbody = 0; } +/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch), + * we need to set the windows "explorer" theme explicitly on a native + * window and open the "TREEVIEW" theme handle passing its window handle + * in order to get Vista-style item view themes (particulary drawBackground() + * for selected items needs this). + * We invoke a service of the native Windows interface to create + * a non-visible window handle, open the theme on it and insert it into + * the cache so that it is found by XPThemeData::handle() first. + */ + +static inline HWND createTreeViewHelperWindow() +{ + if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) { + void *hwnd = 0; + void *wndProc = reinterpret_cast<void *>(DefWindowProc); + if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, + Q_RETURN_ARG(void *, hwnd), + Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), + Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), + Q_ARG(void *, wndProc)) && hwnd) { + return reinterpret_cast<HWND>(hwnd); + } + } + return 0; +} + +bool QWindowsXPStylePrivate::initVistaTreeViewTheming() +{ + if (m_vistaTreeViewHelper) + return true; + + m_vistaTreeViewHelper = createTreeViewHelperWindow(); + if (!m_vistaTreeViewHelper) { + qWarning("Unable to create the treeview helper window."); + return false; + } + if (FAILED(QWindowsXPStylePrivate::pSetWindowTheme(m_vistaTreeViewHelper, L"explorer", NULL))) { + qErrnoWarning("SetWindowTheme() failed."); + cleanupVistaTreeViewTheming(); + return false; + } + return true; +} + +void QWindowsXPStylePrivate::cleanupVistaTreeViewTheming() +{ + if (m_vistaTreeViewHelper) { + DestroyWindow(m_vistaTreeViewHelper); + m_vistaTreeViewHelper = 0; + } +} + /* \internal Closes all open theme data handles to ensure that we don't leak resources, and that we don't refere to old handles when for @@ -339,6 +394,7 @@ void QWindowsXPStylePrivate::cleanupHandleMap() pCloseThemeData(m_themes[i]); m_themes[i] = 0; } + QWindowsXPStylePrivate::cleanupVistaTreeViewTheming(); } HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd) @@ -349,6 +405,8 @@ HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd) } if (!m_themes[theme]) { const wchar_t *name = themeNames[theme]; + if (theme == VistaTreeViewTheme && QWindowsXPStylePrivate::initVistaTreeViewTheming()) + hwnd = QWindowsXPStylePrivate::m_vistaTreeViewHelper; m_themes[theme] = pOpenThemeData(hwnd, name); if (Q_UNLIKELY(!m_themes[theme])) qErrnoWarning("OpenThemeData() failed for theme %d (%s).", @@ -1952,7 +2010,7 @@ case PE_Frame: bef_v -= delta; aft_h += delta; aft_v += delta; - XPThemeData theme(0, p, QWindowsXPStylePrivate::TreeViewTheme); + XPThemeData theme(0, p, QWindowsXPStylePrivate::XpTreeViewTheme); theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size); theme.partId = TVP_GLYPH; theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; @@ -3740,10 +3798,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt { XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); if (buttontheme.isValid()) { - const QMarginsF borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF borderSize = buttontheme.margins() / devicePixelRatio; if (!borderSize.isNull()) { - sz.rwidth() += qRound(borderSize.left() + borderSize.right() - 2); - sz.rheight() += qRound(borderSize.bottom() + borderSize.top() - 2); + const qreal margin = qreal(2) / devicePixelRatio; + sz.rwidth() += qRound(borderSize.left() + borderSize.right() - margin); + sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin + devicePixelRatio - 1); } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 68aa10e12a..8ee4d1a641 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -356,9 +356,10 @@ public: ToolBarTheme, ToolTipTheme, TrackBarTheme, - TreeViewTheme, + XpTreeViewTheme, // '+'/'-' shape treeview indicators (XP) WindowTheme, StatusTheme, + VistaTreeViewTheme, // arrow shape treeview indicators (Vista) obtained from "explorer" theme. NThemes }; @@ -419,6 +420,9 @@ private: void showProperties(XPThemeData &themeData); #endif + static bool initVistaTreeViewTheming(); + static void cleanupVistaTreeViewTheming(); + static QBasicAtomicInt ref; static bool use_xp; static QPixmap *tabbody; @@ -430,6 +434,7 @@ private: uchar *bufferPixels; int bufferW, bufferH; + static HWND m_vistaTreeViewHelper; static HTHEME m_themes[NThemes]; }; diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 90cd6bde99..f1ede20f1f 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -310,7 +310,7 @@ void QAbstractScrollAreaPrivate::init() viewportFilter.reset(new QAbstractScrollAreaFilter(this)); viewport->installEventFilter(viewportFilter.data()); viewport->setFocusProxy(q); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); layoutChildren(); diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index 3f6185b4e7..4221ff40ef 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -734,9 +734,10 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb if (stepsToScroll == 0) { // We moved less than a line, but might still have accumulated partial scroll, // unless we already are at one of the ends. - if (offset_accumulated > 0.f && value < maximum) + const float effective_offset = invertedControls ? -offset_accumulated : offset_accumulated; + if (effective_offset > 0.f && value < maximum) return true; - if (offset_accumulated < 0.f && value > minimum) + if (effective_offset < 0.f && value > minimum) return true; offset_accumulated = 0; return false; diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h index 7ebd9db6bd..a54659ecaa 100644 --- a/src/widgets/widgets/qabstractspinbox_p.h +++ b/src/widgets/widgets/qabstractspinbox_p.h @@ -61,7 +61,6 @@ #include "QtCore/qdatetime.h" #include "QtCore/qvariant.h" #include "private/qwidget_p.h" -#include "private/qdatetime_p.h" QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 7992409265..51e23ca7f9 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3352,6 +3352,8 @@ QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query) const return QWidget::inputMethodQuery(query); } +/*!\internal +*/ QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const { Q_D(const QComboBox); diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h index 6abb3cd9a3..be7bc213a2 100644 --- a/src/widgets/widgets/qdatetimeedit_p.h +++ b/src/widgets/widgets/qdatetimeedit_p.h @@ -78,15 +78,14 @@ public: void init(const QVariant &var); void readLocaleSettings(); - void emitSignals(EmitPolicy ep, const QVariant &old); - QString textFromValue(const QVariant &f) const; - QVariant valueFromText(const QString &f) const; - QDateTime validateAndInterpret(QString &input, int &, QValidator::State &state, bool fixup = false) const; void clearSection(int index); // Override QAbstractSpinBoxPrivate: + void emitSignals(EmitPolicy ep, const QVariant &old) Q_DECL_OVERRIDE; + QString textFromValue(const QVariant &f) const Q_DECL_OVERRIDE; + QVariant valueFromText(const QString &f) const Q_DECL_OVERRIDE; void _q_editorCursorPositionChanged(int oldpos, int newpos) Q_DECL_OVERRIDE; void interpret(EmitPolicy ep) Q_DECL_OVERRIDE; void clearCache() const Q_DECL_OVERRIDE; @@ -94,16 +93,18 @@ public: void updateEditFieldGeometry() Q_DECL_OVERRIDE; QVariant getZeroVariant() const Q_DECL_OVERRIDE; void setRange(const QVariant &min, const QVariant &max) Q_DECL_OVERRIDE; + void updateEdit() Q_DECL_OVERRIDE; - // Override QDateTimePraser: + // Override QDateTimeParser: QString displayText() const Q_DECL_OVERRIDE { return edit->text(); } QDateTime getMinimum() const Q_DECL_OVERRIDE { return minimum.toDateTime(); } QDateTime getMaximum() const Q_DECL_OVERRIDE { return maximum.toDateTime(); } QLocale locale() const Q_DECL_OVERRIDE { return q_func()->locale(); } + QString getAmPmText(AmPm ap, Case cs) const Q_DECL_OVERRIDE; + int cursorPosition() const Q_DECL_OVERRIDE { return edit ? edit->cursorPosition() : -1; } int absoluteIndex(QDateTimeEdit::Section s, int index) const; int absoluteIndex(const SectionNode &s) const; - void updateEdit(); QDateTime stepBy(int index, int steps, bool test = false) const; int sectionAt(int pos) const; int closestSection(int index, bool forward) const; @@ -114,8 +115,6 @@ public: void updateTimeSpec(); QString valueToText(const QVariant &var) const { return textFromValue(var); } - QString getAmPmText(AmPm ap, Case cs) const; - int cursorPosition() const { return edit ? edit->cursorPosition() : -1; } void _q_resetButton(); void updateArrow(QStyle::StateFlag state); diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 9be20ebb74..3c9cab4e17 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1421,11 +1421,11 @@ bool QLineEdit::event(QEvent * e) d->control->processShortcutOverrideEvent(ke); #endif } else if (e->type() == QEvent::KeyRelease) { - d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + d->control->updateCursorBlinking(); } else if (e->type() == QEvent::Show) { //In order to get the cursor blinking if QComboBox::setEditable is called when the combobox has focus if (hasFocus()) { - d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + d->control->setBlinkingCursorEnabled(true); QStyleOptionFrame opt; initStyleOption(&opt); if ((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) @@ -1442,10 +1442,10 @@ bool QLineEdit::event(QEvent * e) if (e->type() == QEvent::EnterEditFocus) { end(false); d->setCursorVisible(true); - d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + d->control->setCursorBlinkEnabled(true); } else if (e->type() == QEvent::LeaveEditFocus) { d->setCursorVisible(false); - d->control->setCursorBlinkPeriod(0); + d->control->setCursorBlinkEnabled(false); if (d->control->hasAcceptableInput() || d->control->fixup()) emit editingFinished(); } @@ -1692,7 +1692,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) if (event->isAccepted()) { if (layoutDirection() != d->control->layoutDirection()) setLayoutDirection(d->control->layoutDirection()); - d->control->setCursorBlinkPeriod(0); + d->control->updateCursorBlinking(); } } @@ -1743,12 +1743,14 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e) #endif } +/*!\reimp +*/ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const { return inputMethodQuery(property, QVariant()); } -/*!\reimp +/*!\internal */ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const { @@ -1802,7 +1804,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e) #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason))) { #endif - d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + d->control->setBlinkingCursorEnabled(true); QStyleOptionFrame opt; initStyleOption(&opt); if((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) @@ -1846,7 +1848,7 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) deselect(); d->setCursorVisible(false); - d->control->setCursorBlinkPeriod(0); + d->control->setBlinkingCursorEnabled(false); #ifdef QT_KEYPAD_NAVIGATION // editingFinished() is already emitted on LeaveEditFocus if (!QApplication::keypadNavigationEnabled()) diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 1da8028efb..27f1b16f60 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -802,7 +802,7 @@ void QPlainTextEditPrivate::init(const QString &txt) viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setAttribute(Qt::WA_KeyCompression); q->setAttribute(Qt::WA_InputMethodEnabled); q->setInputMethodHints(Qt::ImhMultiLine); @@ -2198,8 +2198,13 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const { Q_D(const QPlainTextEdit); - if (query == Qt::ImHints) + switch (query) { + case Qt::ImHints: + case Qt::ImInputItemClipRectangle: return QWidget::inputMethodQuery(query); + default: + break; + } const QPointF offset = contentOffset(); switch (argument.type()) { diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 3f1fa2d015..910904e96e 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1096,6 +1096,8 @@ void QSplitter::resizeEvent(QResizeEvent *) If \a widget is already in the splitter, it will be moved to the new position. + \note The splitter takes ownership of the widget. + \sa insertWidget(), widget(), indexOf() */ void QSplitter::addWidget(QWidget *widget) @@ -1110,7 +1112,9 @@ void QSplitter::addWidget(QWidget *widget) If \a widget is already in the splitter, it will be moved to the new position. - if \a index is an invalid index, then the widget will be inserted at the end. + If \a index is an invalid index, then the widget will be inserted at the end. + + \note The splitter takes ownership of the widget. \sa addWidget(), indexOf(), widget() */ diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 9cc44007bd..8c808f98cb 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -971,6 +971,9 @@ void QTabBar::removeTab(int index) { Q_D(QTabBar); if (d->validIndex(index)) { + if (d->dragInProgress) + d->moveTabFinished(d->pressedIndex); + #ifndef QT_NO_SHORTCUT releaseShortcut(d->tabList.at(index).shortcutId); #endif diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index a81781bd4d..af6d13a647 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -177,7 +177,7 @@ void QTextEditPrivate::init(const QString &html) viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setAttribute(Qt::WA_KeyCompression); q->setAttribute(Qt::WA_InputMethodEnabled); q->setInputMethodHints(Qt::ImhMultiLine); @@ -1728,8 +1728,13 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const { Q_D(const QTextEdit); - if (query == Qt::ImHints) + switch (query) { + case Qt::ImHints: + case Qt::ImInputItemClipRectangle: return QWidget::inputMethodQuery(query); + default: + break; + } const QPointF offset(-d->horizontalOffset(), -d->verticalOffset()); switch (argument.type()) { diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index 24edca172b..86903dc0c3 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -636,7 +636,7 @@ void QWidgetLineControl::draw(QPainter *painter, const QPoint &offset, const QRe o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); } else { // mask selection - if(!m_blinkPeriod || m_blinkStatus){ + if (m_blinkStatus){ o.start = m_cursor; o.length = 1; o.format.setBackground(m_palette.brush(QPalette::Text)); @@ -653,7 +653,7 @@ void QWidgetLineControl::draw(QPainter *painter, const QPoint &offset, const QRe int cursor = m_cursor; if (m_preeditCursor != -1) cursor += m_preeditCursor; - if (!m_hideCursor && (!m_blinkPeriod || m_blinkStatus)) + if (!m_hideCursor && m_blinkStatus) textLayout()->drawCursor(painter, offset, cursor, m_cursorWidth); } } @@ -1486,38 +1486,55 @@ void QWidgetLineControl::complete(int key) void QWidgetLineControl::setReadOnly(bool enable) { + if (m_readOnly == enable) + return; + m_readOnly = enable; + updateCursorBlinking(); +} + +void QWidgetLineControl::setBlinkingCursorEnabled(bool enable) +{ + if (m_blinkEnabled == enable) + return; + + m_blinkEnabled = enable; + if (enable) - setCursorBlinkPeriod(0); + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QWidgetLineControl::updateCursorBlinking); else - setCursorBlinkPeriod(QApplication::cursorFlashTime()); + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QWidgetLineControl::updateCursorBlinking); + + updateCursorBlinking(); } -void QWidgetLineControl::setCursorBlinkPeriod(int msec) +void QWidgetLineControl::updateCursorBlinking() { - if (msec == m_blinkPeriod) - return; if (m_blinkTimer) { killTimer(m_blinkTimer); - } - if (msec > 0 && !m_readOnly) { - m_blinkTimer = startTimer(msec / 2); - m_blinkStatus = 1; - } else { m_blinkTimer = 0; - if (m_blinkStatus == 1) - emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); } - m_blinkPeriod = msec; + + if (m_blinkEnabled && !m_readOnly) { + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + if (flashTime >= 2) + m_blinkTimer = startTimer(flashTime / 2); + } + + m_blinkStatus = 1; + emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); } // This is still used by QDeclarativeTextInput in the qtquick1 repo void QWidgetLineControl::resetCursorBlinkTimer() { - if (m_blinkPeriod == 0 || m_blinkTimer == 0) + if (!m_blinkEnabled || m_blinkTimer == 0) return; killTimer(m_blinkTimer); - m_blinkTimer = startTimer(m_blinkPeriod / 2); + m_blinkTimer = 0; + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + if (flashTime >= 2) + m_blinkTimer = startTimer(flashTime / 2); m_blinkStatus = 1; } diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 8b723b0224..34d19d1e77 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -83,7 +83,7 @@ public: : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LayoutDirectionAuto), m_hideCursor(false), m_separator(0), m_readOnly(0), m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), - m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_validInput(1), m_blinkStatus(0), m_blinkEnabled(false), m_blinkTimer(0), m_deleteAllTimer(0), m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1), m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0), m_selstart(0), m_selend(0), m_passwordEchoEditing(false) @@ -354,8 +354,8 @@ public: void processInputMethodEvent(QInputMethodEvent *event); void processKeyEvent(QKeyEvent* ev); - int cursorBlinkPeriod() const { return m_blinkPeriod; } - void setCursorBlinkPeriod(int msec); + void setBlinkingCursorEnabled(bool enable); + void updateCursorBlinking(); void resetCursorBlinkTimer(); bool cursorBlinkStatus() const { return m_blinkStatus; } @@ -433,7 +433,7 @@ private: uint m_selDirty : 1; uint m_validInput : 1; uint m_blinkStatus : 1; - int m_blinkPeriod; // 0 for non-blinking cursor + uint m_blinkEnabled : 1; int m_blinkTimer; int m_deleteAllTimer; int m_ascent; diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index cc1726c362..77b5a4830b 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -112,7 +112,7 @@ static QTextLine currentTextLine(const QTextCursor &cursor) } QWidgetTextControlPrivate::QWidgetTextControlPrivate() - : doc(0), cursorOn(false), cursorIsFocusIndicator(false), + : doc(0), cursorOn(false), cursorVisible(false), cursorIsFocusIndicator(false), #ifndef Q_OS_ANDROID interactionFlags(Qt::TextEditorInteraction), #else @@ -685,17 +685,30 @@ void QWidgetTextControlPrivate::_q_documentLayoutChanged() } -void QWidgetTextControlPrivate::setBlinkingCursorEnabled(bool enable) +void QWidgetTextControlPrivate::setCursorVisible(bool visible) { - Q_Q(QWidgetTextControl); + if (cursorVisible == visible) + return; - if (enable && QApplication::cursorFlashTime() > 0) - cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q); + cursorVisible = visible; + updateCursorBlinking(); + + if (cursorVisible) + connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QWidgetTextControlPrivate::updateCursorBlinking); else - cursorBlinkTimer.stop(); + disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QWidgetTextControlPrivate::updateCursorBlinking); +} - cursorOn = enable; +void QWidgetTextControlPrivate::updateCursorBlinking() +{ + cursorBlinkTimer.stop(); + if (cursorVisible) { + int flashTime = QGuiApplication::styleHints()->cursorFlashTime(); + if (flashTime >= 2) + cursorBlinkTimer.start(flashTime / 2, q_func()); + } + cursorOn = cursorVisible; repaintCursor(); } @@ -2156,13 +2169,13 @@ void QWidgetTextControlPrivate::focusEvent(QFocusEvent *e) #endif cursorOn = (interactionFlags & (Qt::TextSelectableByKeyboard | Qt::TextEditable)); if (interactionFlags & Qt::TextEditable) { - setBlinkingCursorEnabled(true); + setCursorVisible(true); } #ifdef QT_KEYPAD_NAVIGATION } #endif } else { - setBlinkingCursorEnabled(false); + setCursorVisible(false); if (cursorIsFocusIndicator && e->reason() != Qt::ActiveWindowFocusReason @@ -2971,7 +2984,7 @@ void QWidgetTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags) d->interactionFlags = flags; if (d->hasFocus) - d->setBlinkingCursorEnabled(flags & Qt::TextEditable); + d->setCursorVisible(flags & Qt::TextEditable); } Qt::TextInteractionFlags QWidgetTextControl::textInteractionFlags() const diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h index 4feebdd9ef..fea72d98ff 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h @@ -111,7 +111,9 @@ public: void _q_emitCursorPosChanged(const QTextCursor &someCursor); void _q_contentsChanged(int from, int charsRemoved, int charsAdded); + void setCursorVisible(bool visible); void setBlinkingCursorEnabled(bool enable); + void updateCursorBlinking(); void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition); void extendBlockwiseSelection(int suggestedNewPosition); @@ -175,6 +177,7 @@ public: QTextDocument *doc; bool cursorOn; + bool cursorVisible; QTextCursor cursor; bool cursorIsFocusIndicator; QTextCharFormat lastCharFormat; |