summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/widgets')
-rw-r--r--src/widgets/widgets/qabstractbutton.cpp151
-rw-r--r--src/widgets/widgets/qabstractbutton.h42
-rw-r--r--src/widgets/widgets/qabstractbutton_p.h40
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp132
-rw-r--r--src/widgets/widgets/qabstractscrollarea.h46
-rw-r--r--src/widgets/widgets/qabstractscrollarea_p.h51
-rw-r--r--src/widgets/widgets/qabstractslider.cpp57
-rw-r--r--src/widgets/widgets/qabstractslider.h40
-rw-r--r--src/widgets/widgets/qabstractslider_p.h40
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp203
-rw-r--r--src/widgets/widgets/qabstractspinbox.h45
-rw-r--r--src/widgets/widgets/qabstractspinbox_p.h82
-rw-r--r--src/widgets/widgets/qbuttongroup.cpp64
-rw-r--r--src/widgets/widgets/qbuttongroup.h48
-rw-r--r--src/widgets/widgets/qbuttongroup_p.h40
-rw-r--r--src/widgets/widgets/qcalendarwidget.cpp269
-rw-r--r--src/widgets/widgets/qcalendarwidget.h78
-rw-r--r--src/widgets/widgets/qcheckbox.cpp80
-rw-r--r--src/widgets/widgets/qcheckbox.h46
-rw-r--r--src/widgets/widgets/qcombobox.cpp1024
-rw-r--r--src/widgets/widgets/qcombobox.h89
-rw-r--r--src/widgets/widgets/qcombobox_p.h142
-rw-r--r--src/widgets/widgets/qcommandlinkbutton.cpp65
-rw-r--r--src/widgets/widgets/qcommandlinkbutton.h48
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp563
-rw-r--r--src/widgets/widgets/qdatetimeedit.h93
-rw-r--r--src/widgets/widgets/qdatetimeedit_p.h70
-rw-r--r--src/widgets/widgets/qdial.cpp78
-rw-r--r--src/widgets/widgets/qdial.h42
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp379
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.h45
-rw-r--r--src/widgets/widgets/qdialogbuttonbox_p.h80
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp428
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h71
-rw-r--r--src/widgets/widgets/qdockwidget.cpp408
-rw-r--r--src/widgets/widgets/qdockwidget.h53
-rw-r--r--src/widgets/widgets/qdockwidget_p.h68
-rw-r--r--src/widgets/widgets/qeffects.cpp75
-rw-r--r--src/widgets/widgets/qeffects_p.h40
-rw-r--r--src/widgets/widgets/qfocusframe.cpp58
-rw-r--r--src/widgets/widgets/qfocusframe.h42
-rw-r--r--src/widgets/widgets/qfontcombobox.cpp254
-rw-r--r--src/widgets/widgets/qfontcombobox.h51
-rw-r--r--src/widgets/widgets/qframe.cpp51
-rw-r--r--src/widgets/widgets/qframe.h44
-rw-r--r--src/widgets/widgets/qframe_p.h43
-rw-r--r--src/widgets/widgets/qgroupbox.cpp79
-rw-r--r--src/widgets/widgets/qgroupbox.h42
-rw-r--r--src/widgets/widgets/qkeysequenceedit.cpp214
-rw-r--r--src/widgets/widgets/qkeysequenceedit.h57
-rw-r--r--src/widgets/widgets/qkeysequenceedit_p.h48
-rw-r--r--src/widgets/widgets/qlabel.cpp253
-rw-r--r--src/widgets/widgets/qlabel.h69
-rw-r--r--src/widgets/widgets/qlabel_p.h67
-rw-r--r--src/widgets/widgets/qlcdnumber.cpp92
-rw-r--r--src/widgets/widgets/qlcdnumber.h40
-rw-r--r--src/widgets/widgets/qlineedit.cpp683
-rw-r--r--src/widgets/widgets/qlineedit.h61
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp215
-rw-r--r--src/widgets/widgets/qlineedit_p.h78
-rw-r--r--src/widgets/widgets/qmaccocoaviewcontainer_mac.h67
-rw-r--r--src/widgets/widgets/qmaccocoaviewcontainer_mac.mm199
-rw-r--r--src/widgets/widgets/qmacnativewidget_mac.h66
-rw-r--r--src/widgets/widgets/qmacnativewidget_mac.mm166
-rw-r--r--src/widgets/widgets/qmainwindow.cpp181
-rw-r--r--src/widgets/widgets/qmainwindow.h53
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp956
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h163
-rw-r--r--src/widgets/widgets/qmdiarea.cpp232
-rw-r--r--src/widgets/widgets/qmdiarea.h40
-rw-r--r--src/widgets/widgets/qmdiarea_p.h70
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp162
-rw-r--r--src/widgets/widgets/qmdisubwindow.h41
-rw-r--r--src/widgets/widgets/qmdisubwindow_p.h47
-rw-r--r--src/widgets/widgets/qmenu.cpp828
-rw-r--r--src/widgets/widgets/qmenu.h160
-rw-r--r--src/widgets/widgets/qmenu_mac.mm154
-rw-r--r--src/widgets/widgets/qmenu_p.h69
-rw-r--r--src/widgets/widgets/qmenubar.cpp385
-rw-r--r--src/widgets/widgets/qmenubar.h72
-rw-r--r--src/widgets/widgets/qmenubar_p.h48
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp382
-rw-r--r--src/widgets/widgets/qplaintextedit.h59
-rw-r--r--src/widgets/widgets/qplaintextedit_p.h94
-rw-r--r--src/widgets/widgets/qprogressbar.cpp70
-rw-r--r--src/widgets/widgets/qprogressbar.h42
-rw-r--r--src/widgets/widgets/qpushbutton.cpp118
-rw-r--r--src/widgets/widgets/qpushbutton.h49
-rw-r--r--src/widgets/widgets/qpushbutton_p.h53
-rw-r--r--src/widgets/widgets/qradiobutton.cpp48
-rw-r--r--src/widgets/widgets/qradiobutton.h42
-rw-r--r--src/widgets/widgets/qrubberband.cpp40
-rw-r--r--src/widgets/widgets/qrubberband.h42
-rw-r--r--src/widgets/widgets/qscrollarea.cpp68
-rw-r--r--src/widgets/widgets/qscrollarea.h40
-rw-r--r--src/widgets/widgets/qscrollarea_p.h42
-rw-r--r--src/widgets/widgets/qscrollbar.cpp107
-rw-r--r--src/widgets/widgets/qscrollbar.h42
-rw-r--r--src/widgets/widgets/qscrollbar_p.h40
-rw-r--r--src/widgets/widgets/qsizegrip.cpp109
-rw-r--r--src/widgets/widgets/qsizegrip.h40
-rw-r--r--src/widgets/widgets/qslider.cpp82
-rw-r--r--src/widgets/widgets/qslider.h42
-rw-r--r--src/widgets/widgets/qspinbox.cpp162
-rw-r--r--src/widgets/widgets/qspinbox.h48
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp187
-rw-r--r--src/widgets/widgets/qsplashscreen.h44
-rw-r--r--src/widgets/widgets/qsplitter.cpp202
-rw-r--r--src/widgets/widgets/qsplitter.h46
-rw-r--r--src/widgets/widgets/qsplitter_p.h42
-rw-r--r--src/widgets/widgets/qstackedwidget.cpp49
-rw-r--r--src/widgets/widgets/qstackedwidget.h42
-rw-r--r--src/widgets/widgets/qstatusbar.cpp213
-rw-r--r--src/widgets/widgets/qstatusbar.h41
-rw-r--r--src/widgets/widgets/qtabbar.cpp849
-rw-r--r--src/widgets/widgets/qtabbar.h66
-rw-r--r--src/widgets/widgets/qtabbar_p.h199
-rw-r--r--src/widgets/widgets/qtabwidget.cpp139
-rw-r--r--src/widgets/widgets/qtabwidget.h59
-rw-r--r--src/widgets/widgets/qtextbrowser.cpp219
-rw-r--r--src/widgets/widgets/qtextbrowser.h54
-rw-r--r--src/widgets/widgets/qtextedit.cpp318
-rw-r--r--src/widgets/widgets/qtextedit.h62
-rw-r--r--src/widgets/widgets/qtextedit_p.h59
-rw-r--r--src/widgets/widgets/qtoolbar.cpp252
-rw-r--r--src/widgets/widgets/qtoolbar.h99
-rw-r--r--src/widgets/widgets/qtoolbar_p.h46
-rw-r--r--src/widgets/widgets/qtoolbararealayout.cpp172
-rw-r--r--src/widgets/widgets/qtoolbararealayout_p.h50
-rw-r--r--src/widgets/widgets/qtoolbarextension.cpp54
-rw-r--r--src/widgets/widgets/qtoolbarextension_p.h40
-rw-r--r--src/widgets/widgets/qtoolbarlayout.cpp82
-rw-r--r--src/widgets/widgets/qtoolbarlayout_p.h46
-rw-r--r--src/widgets/widgets/qtoolbarseparator.cpp40
-rw-r--r--src/widgets/widgets/qtoolbarseparator_p.h40
-rw-r--r--src/widgets/widgets/qtoolbox.cpp71
-rw-r--r--src/widgets/widgets/qtoolbox.h44
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp212
-rw-r--r--src/widgets/widgets/qtoolbutton.h53
-rw-r--r--src/widgets/widgets/qwidgetanimator.cpp47
-rw-r--r--src/widgets/widgets/qwidgetanimator_p.h40
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp249
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h74
-rw-r--r--src/widgets/widgets/qwidgetresizehandler.cpp171
-rw-r--r--src/widgets/widgets/qwidgetresizehandler_p.h74
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp376
-rw-r--r--src/widgets/widgets/qwidgettextcontrol_p.h65
-rw-r--r--src/widgets/widgets/qwidgettextcontrol_p_p.h48
-rw-r--r--src/widgets/widgets/widgets.pri371
149 files changed, 7654 insertions, 12028 deletions
diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp
index 29d28847f3..3a5fbe1b90 100644
--- a/src/widgets/widgets/qabstractbutton.cpp
+++ b/src/widgets/widgets/qabstractbutton.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qabstractbutton_p.h"
@@ -44,17 +8,20 @@
#endif
#if QT_CONFIG(buttongroup)
#include "qbuttongroup.h"
-#include "private/qapplication_p.h"
#include "private/qbuttongroup_p.h"
#endif
+#include "private/qapplication_p.h"
#include "qabstractbutton_p.h"
#include "qevent.h"
#include "qpainter.h"
#include "qapplication.h"
#include "qstyle.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
+#include <qpa/qplatformtheme.h>
+
+#include <QtCore/qpointer.h>
#include <algorithm>
@@ -190,7 +157,9 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
return group->d_func()->buttonList;
#endif
- QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
+ if (!parent)
+ return {};
+ QList<QAbstractButton *> candidates = parent->findChildren<QAbstractButton *>();
if (autoExclusive) {
auto isNoMemberOfMyAutoExclusiveGroup = [](QAbstractButton *candidate) {
return !candidate->autoExclusive()
@@ -199,9 +168,7 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
#endif
;
};
- candidates.erase(std::remove_if(candidates.begin(), candidates.end(),
- isNoMemberOfMyAutoExclusiveGroup),
- candidates.end());
+ candidates.removeIf(isNoMemberOfMyAutoExclusiveGroup);
}
return candidates;
}
@@ -215,10 +182,10 @@ QAbstractButton *QAbstractButtonPrivate::queryCheckedButton() const
Q_Q(const QAbstractButton);
QList<QAbstractButton *> buttonList = queryButtonList();
- if (!autoExclusive || buttonList.count() == 1) // no group
+ if (!autoExclusive || buttonList.size() == 1) // no group
return nullptr;
- for (int i = 0; i < buttonList.count(); ++i) {
+ for (int i = 0; i < buttonList.size(); ++i) {
QAbstractButton *b = buttonList.at(i);
if (b->d_func()->checked && b != q)
return b;
@@ -245,7 +212,7 @@ void QAbstractButtonPrivate::notifyChecked()
void QAbstractButtonPrivate::moveFocus(int key)
{
- QList<QAbstractButton *> buttonList = queryButtonList();;
+ QList<QAbstractButton *> buttonList = queryButtonList();
#if QT_CONFIG(buttongroup)
bool exclusive = group ? group->d_func()->exclusive : autoExclusive;
#else
@@ -262,10 +229,10 @@ void QAbstractButtonPrivate::moveFocus(int key)
QPoint goal = target.center();
uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
- for (int i = 0; i < buttonList.count(); ++i) {
+ for (int i = 0; i < buttonList.size(); ++i) {
QAbstractButton *button = buttonList.at(i);
if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() &&
- (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {
+ (exclusive || (button->focusPolicy() & focus_flag) == focus_flag)) {
QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0)));
QPoint p = buttonRect.center();
@@ -345,7 +312,7 @@ void QAbstractButtonPrivate::fixFocusPolicy()
return;
QList<QAbstractButton *> buttonList = queryButtonList();
- for (int i = 0; i < buttonList.count(); ++i) {
+ for (int i = 0; i < buttonList.size(); ++i) {
QAbstractButton *b = buttonList.at(i);
if (!b->isCheckable())
continue;
@@ -414,7 +381,7 @@ void QAbstractButtonPrivate::emitClicked()
emit q->clicked(checked);
#if QT_CONFIG(buttongroup)
if (guard && group) {
- emit group->buttonClicked(group->id(q));
+ emit group->idClicked(group->id(q));
if (guard && group)
emit group->buttonClicked(q);
}
@@ -428,7 +395,7 @@ void QAbstractButtonPrivate::emitPressed()
emit q->pressed();
#if QT_CONFIG(buttongroup)
if (guard && group) {
- emit group->buttonPressed(group->id(q));
+ emit group->idPressed(group->id(q));
if (guard && group)
emit group->buttonPressed(q);
}
@@ -442,7 +409,7 @@ void QAbstractButtonPrivate::emitReleased()
emit q->released();
#if QT_CONFIG(buttongroup)
if (guard && group) {
- emit group->buttonReleased(group->id(q));
+ emit group->idReleased(group->id(q));
if (guard && group)
emit group->buttonReleased(q);
}
@@ -456,7 +423,7 @@ void QAbstractButtonPrivate::emitToggled(bool checked)
emit q->toggled(checked);
#if QT_CONFIG(buttongroup)
if (guard && group) {
- emit group->buttonToggled(group->id(q), checked);
+ emit group->idToggled(group->id(q), checked);
if (guard && group)
emit group->buttonToggled(q, checked);
}
@@ -525,7 +492,7 @@ void QAbstractButton::setText(const QString &text)
d->sizeHint = QSize();
update();
updateGeometry();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
#endif
@@ -648,12 +615,13 @@ void QAbstractButton::setChecked(bool checked)
if (guard)
d->emitToggled(checked);
-
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::State s;
- s.checked = true;
- QAccessibleStateChangeEvent event(this, s);
- QAccessible::updateAccessibility(&event);
+#if QT_CONFIG(accessibility)
+ if (guard) {
+ QAccessible::State s;
+ s.checked = true;
+ QAccessibleStateChangeEvent event(this, s);
+ QAccessible::updateAccessibility(&event);
+ }
#endif
}
@@ -818,7 +786,7 @@ QButtonGroup *QAbstractButton::group() const
/*!
Performs an animated click: the button is pressed immediately, and
-released \a msec milliseconds later (the default is 100 ms).
+released 100ms later.
Calling this function again before the button is released resets
the release timer.
@@ -829,7 +797,7 @@ This function does nothing if the button is \l{setEnabled()}{disabled.}
\sa click()
*/
-void QAbstractButton::animateClick(int msec)
+void QAbstractButton::animateClick()
{
if (!isEnabled())
return;
@@ -840,7 +808,7 @@ void QAbstractButton::animateClick(int msec)
repaint();
if (!d->animateTimer.isActive())
d->emitPressed();
- d->animateTimer.start(msec, this);
+ d->animateTimer.start(100, this);
}
/*!
@@ -939,9 +907,6 @@ bool QAbstractButton::event(QEvent *e)
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::ContextMenu:
-#if QT_CONFIG(wheelevent)
- case QEvent::Wheel:
-#endif
return true;
default:
break;
@@ -976,7 +941,7 @@ void QAbstractButton::mousePressEvent(QMouseEvent *e)
e->ignore();
return;
}
- if (hitButton(e->pos())) {
+ if (hitButton(e->position().toPoint())) {
setDown(true);
d->pressed = true;
repaint();
@@ -1006,7 +971,7 @@ void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)
return;
}
- if (hitButton(e->pos())) {
+ if (hitButton(e->position().toPoint())) {
d->repeatTimer.stop();
d->click();
e->accept();
@@ -1025,7 +990,7 @@ void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
return;
}
- if (hitButton(e->pos()) != d->down) {
+ if (hitButton(e->position().toPoint()) != d->down) {
setDown(!d->down);
repaint();
if (d->down)
@@ -1033,7 +998,7 @@ void QAbstractButton::mouseMoveEvent(QMouseEvent *e)
else
d->emitReleased();
e->accept();
- } else if (!hitButton(e->pos())) {
+ } else if (!hitButton(e->position().toPoint())) {
e->ignore();
}
}
@@ -1043,19 +1008,19 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e)
{
Q_D(QAbstractButton);
bool next = true;
- switch (e->key()) {
- case Qt::Key_Enter:
- case Qt::Key_Return:
- e->ignore();
- break;
- case Qt::Key_Select:
- case Qt::Key_Space:
- if (!e->isAutoRepeat()) {
- setDown(true);
- repaint();
- d->emitPressed();
- }
- break;
+
+ const auto key = e->key();
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value<QList<Qt::Key>>();
+ if (buttonPressKeys.contains(key) && !e->isAutoRepeat()) {
+ setDown(true);
+ repaint();
+ d->emitPressed();
+ return;
+ }
+
+ switch (key) {
case Qt::Key_Up:
next = false;
Q_FALLTHROUGH();
@@ -1085,7 +1050,7 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e)
// cleaned up when fixing task 194373. It's here to ensure that we
// keep compatibility outside QAbstractItemView.
d->moveFocus(e->key());
- if (hasFocus()) // nothing happend, propagate
+ if (hasFocus()) // nothing happened, propagate
e->ignore();
} else {
// Prefer parent widget, use this if parent is absent
@@ -1120,15 +1085,15 @@ void QAbstractButton::keyReleaseEvent(QKeyEvent *e)
if (!e->isAutoRepeat())
d->repeatTimer.stop();
- switch (e->key()) {
- case Qt::Key_Select:
- case Qt::Key_Space:
- if (!e->isAutoRepeat() && d->down)
- d->click();
- break;
- default:
- e->ignore();
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value<QList<Qt::Key>>();
+ if (buttonPressKeys.contains(e->key()) && !e->isAutoRepeat() && d->down) {
+ d->click();
+ return;
}
+
+ e->ignore();
}
/*!\reimp
diff --git a/src/widgets/widgets/qabstractbutton.h b/src/widgets/widgets/qabstractbutton.h
index d44da2f4f3..7a1e55abdd 100644
--- a/src/widgets/widgets/qabstractbutton.h
+++ b/src/widgets/widgets/qabstractbutton.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTBUTTON_H
#define QABSTRACTBUTTON_H
@@ -116,7 +80,7 @@ public:
public Q_SLOTS:
void setIconSize(const QSize &size);
- void animateClick(int msec = 100);
+ void animateClick();
void click();
void toggle();
void setChecked(bool);
diff --git a/src/widgets/widgets/qabstractbutton_p.h b/src/widgets/widgets/qabstractbutton_p.h
index 39e2e399a7..6b6d5a2167 100644
--- a/src/widgets/widgets/qabstractbutton_p.h
+++ b/src/widgets/widgets/qabstractbutton_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTBUTTON_P_H
#define QABSTRACTBUTTON_P_H
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 320b3bf7ef..f6f8e8b795 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractscrollarea.h"
@@ -68,6 +32,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QAbstractScrollArea
\brief The QAbstractScrollArea widget provides a scrolling area with
@@ -127,13 +93,13 @@ QT_BEGIN_NAMESPACE
QWidget::move(). When the area contents or the viewport size
changes, we do the following:
- \snippet myscrollarea.cpp 1
+ \snippet myscrollarea/myscrollarea.cpp 1
When the scroll bars change value, we need to update the widget
position, i.e., find the part of the widget that is to be drawn in
the viewport:
- \snippet myscrollarea.cpp 0
+ \snippet myscrollarea/myscrollarea.cpp 0
In order to track scroll bar movements, reimplement the virtual
function scrollContentsBy(). In order to fine-tune scrolling
@@ -202,7 +168,7 @@ void QAbstractScrollAreaScrollBarContainer::addWidget(QWidget *widget, LogicalPo
}
/*! \internal
- Retuns a list of scroll bar widgets for the given position. The scroll bar
+ Returns a list of scroll-bar widgets for the given position. The scroll bar
itself is not returned.
*/
QWidgetList QAbstractScrollAreaScrollBarContainer::widgets(LogicalPosition position)
@@ -282,11 +248,11 @@ void QAbstractScrollAreaPrivate::init()
{
Q_Q(QAbstractScrollArea);
viewport = new QWidget(q);
- viewport->setObjectName(QLatin1String("qt_scrollarea_viewport"));
+ viewport->setObjectName("qt_scrollarea_viewport"_L1);
viewport->setBackgroundRole(QPalette::Base);
viewport->setAutoFillBackground(true);
scrollBarContainers[Qt::Horizontal] = new QAbstractScrollAreaScrollBarContainer(Qt::Horizontal, q);
- scrollBarContainers[Qt::Horizontal]->setObjectName(QLatin1String("qt_scrollarea_hcontainer"));
+ scrollBarContainers[Qt::Horizontal]->setObjectName("qt_scrollarea_hcontainer"_L1);
hbar = scrollBarContainers[Qt::Horizontal]->scrollBar;
hbar->setRange(0,0);
scrollBarContainers[Qt::Horizontal]->setVisible(false);
@@ -294,7 +260,7 @@ void QAbstractScrollAreaPrivate::init()
QObject::connect(hbar, SIGNAL(valueChanged(int)), q, SLOT(_q_hslide(int)));
QObject::connect(hbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
scrollBarContainers[Qt::Vertical] = new QAbstractScrollAreaScrollBarContainer(Qt::Vertical, q);
- scrollBarContainers[Qt::Vertical]->setObjectName(QLatin1String("qt_scrollarea_vcontainer"));
+ scrollBarContainers[Qt::Vertical]->setObjectName("qt_scrollarea_vcontainer"_L1);
vbar = scrollBarContainers[Qt::Vertical]->scrollBar;
vbar->setRange(0,0);
scrollBarContainers[Qt::Vertical]->setVisible(false);
@@ -308,7 +274,7 @@ void QAbstractScrollAreaPrivate::init()
q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layoutChildren();
-#ifndef Q_OS_OSX
+#ifndef Q_OS_MACOS
# ifndef QT_NO_GESTURES
viewport->grabGesture(Qt::PanGesture);
# endif
@@ -329,21 +295,24 @@ void QAbstractScrollAreaPrivate::layoutChildren()
void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrollbar, bool *needVerticalScrollbar)
{
Q_Q(QAbstractScrollArea);
- bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, hbar);
+ QStyleOptionSlider barOpt;
+
+ hbar->initStyleOption(&barOpt);
+ bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, &barOpt, hbar);
bool needh = *needHorizontalScrollbar || ((hbarpolicy != Qt::ScrollBarAlwaysOff) && ((hbarpolicy == Qt::ScrollBarAlwaysOn && !htransient)
|| ((hbarpolicy == Qt::ScrollBarAsNeeded || htransient)
&& hbar->minimum() < hbar->maximum() && !hbar->sizeHint().isEmpty())));
+ const int hscrollOverlap = hbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &barOpt, hbar);
- bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, vbar);
+ vbar->initStyleOption(&barOpt);
+ bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, &barOpt, vbar);
bool needv = *needVerticalScrollbar || ((vbarpolicy != Qt::ScrollBarAlwaysOff) && ((vbarpolicy == Qt::ScrollBarAlwaysOn && !vtransient)
|| ((vbarpolicy == Qt::ScrollBarAsNeeded || vtransient)
&& vbar->minimum() < vbar->maximum() && !vbar->sizeHint().isEmpty())));
+ const int vscrollOverlap = vbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &barOpt, vbar);
QStyleOption opt(0);
- opt.init(q);
-
- const int hscrollOverlap = hbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, hbar);
- const int vscrollOverlap = vbar->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, &opt, vbar);
+ opt.initFrom(q);
const int hsbExt = hbar->sizeHint().height();
const int vsbExt = vbar->sizeHint().width();
@@ -402,7 +371,7 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol
#if QT_CONFIG(itemviews)
if ((vscrollOverlap > 0 && needv) || (hscrollOverlap > 0 && needh)) {
const QList<QHeaderView *> headers = q->findChildren<QHeaderView*>();
- if (headers.count() <= 2) {
+ if (headers.size() <= 2) {
for (const QHeaderView *header : headers) {
const QRect geo = header->geometry();
if (header->orientation() == Qt::Vertical && header->isVisible() && QStyle::visualRect(opt.direction, opt.rect, geo).left() <= opt.rect.width() / 2)
@@ -442,8 +411,10 @@ void QAbstractScrollAreaPrivate::layoutChildren_helper(bool *needHorizontalScrol
viewportRect.adjust(right, top, -left, -bottom);
else
viewportRect.adjust(left, top, -right, -bottom);
+ viewportRect = QStyle::visualRect(opt.direction, opt.rect, viewportRect);
+ viewportRect.translate(-overshoot);
+ viewport->setGeometry(viewportRect); // resize the viewport last
- viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last
*needHorizontalScrollbar = needh;
*needVerticalScrollbar = needv;
}
@@ -512,8 +483,8 @@ QAbstractScrollArea::~QAbstractScrollArea()
Sets the viewport to be the given \a widget.
The QAbstractScrollArea will take ownership of the given \a widget.
- If \a widget is 0, QAbstractScrollArea will assign a new QWidget instance
- for the viewport.
+ If \a widget is \nullptr, QAbstractScrollArea will assign a new QWidget
+ instance for the viewport.
\sa viewport()
*/
@@ -564,15 +535,13 @@ scrolling range.
QSize QAbstractScrollArea::maximumViewportSize() const
{
Q_D(const QAbstractScrollArea);
- int hsbExt = d->hbar->sizeHint().height();
- int vsbExt = d->vbar->sizeHint().width();
-
int f = 2 * d->frameWidth;
QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
+ // Count the sizeHint of the bar only if it is displayed.
if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
- max.rwidth() -= vsbExt;
+ max.rwidth() -= d->vbar->sizeHint().width();
if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
- max.rheight() -= hsbExt;
+ max.rheight() -= d->hbar->sizeHint().height();
return max;
}
@@ -720,7 +689,7 @@ QWidget *QAbstractScrollArea::cornerWidget() const
You will probably also want to set at least one of the scroll bar
modes to \c AlwaysOn.
- Passing 0 shows no widget in the corner.
+ Passing \nullptr shows no widget in the corner.
Any previous corner widget is hidden.
@@ -836,7 +805,7 @@ QWidgetList QAbstractScrollArea::scrollBarWidgets(Qt::Alignment alignment)
/*!
Sets the margins around the scrolling area to \a left, \a top, \a
right and \a bottom. This is useful for applications such as
- spreadsheets with "locked" rows and columns. The marginal space is
+ spreadsheets with "locked" rows and columns. The marginal space
is left blank; put widgets in the unused area.
Note that this function is frequently called by QTreeView and
@@ -1131,7 +1100,7 @@ void QAbstractScrollArea::resizeEvent(QResizeEvent *)
This event handler can be reimplemented in a subclass to receive
paint events (passed in \a event), for the viewport() widget.
- \note If you open a painter, make sure to open it on the viewport().
+ \note If you create a QPainter, it must operate on the viewport().
\sa QWidget::paintEvent()
*/
@@ -1361,38 +1330,27 @@ void QAbstractScrollArea::scrollContentsBy(int, int)
viewport()->update();
}
-bool QAbstractScrollAreaPrivate::canStartScrollingAt( const QPoint &startPos )
+bool QAbstractScrollAreaPrivate::canStartScrollingAt(const QPoint &startPos) const
{
- Q_Q(QAbstractScrollArea);
-
-#if QT_CONFIG(graphicsview)
- // don't start scrolling when a drag mode has been set.
- // don't start scrolling on a movable item.
- if (QGraphicsView *view = qobject_cast<QGraphicsView *>(q)) {
- if (view->dragMode() != QGraphicsView::NoDrag)
- return false;
-
- QGraphicsItem *childItem = view->itemAt(startPos);
-
- if (childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
- return false;
- }
-#endif
+ Q_Q(const QAbstractScrollArea);
// don't start scrolling on a QAbstractSlider
- if (qobject_cast<QAbstractSlider *>(q->viewport()->childAt(startPos))) {
+ if (qobject_cast<QAbstractSlider *>(q->viewport()->childAt(startPos)))
return false;
- }
return true;
}
void QAbstractScrollAreaPrivate::flashScrollBars()
{
- bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, hbar);
+ QStyleOptionSlider opt;
+ hbar->initStyleOption(&opt);
+
+ bool htransient = hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, hbar);
if ((hbarpolicy != Qt::ScrollBarAlwaysOff) && (hbarpolicy == Qt::ScrollBarAsNeeded || htransient))
hbar->d_func()->flash();
- bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, vbar);
+ vbar->initStyleOption(&opt);
+ bool vtransient = vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, vbar);
if ((vbarpolicy != Qt::ScrollBarAlwaysOff) && (vbarpolicy == Qt::ScrollBarAsNeeded || vtransient))
vbar->d_func()->flash();
}
@@ -1473,9 +1431,9 @@ QSize QAbstractScrollArea::sizeHint() const
if (!d->sizeHint.isValid() || d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents) {
const int f = 2 * d->frameWidth;
- const QSize frame( f, f );
- const bool vbarHidden = d->vbar->isHidden() || d->vbarpolicy == Qt::ScrollBarAlwaysOff;
- const bool hbarHidden = d->hbar->isHidden() || d->hbarpolicy == Qt::ScrollBarAlwaysOff;
+ const QSize frame(f, f);
+ const bool vbarHidden = !d->vbar->isVisibleTo(this) || d->vbarpolicy == Qt::ScrollBarAlwaysOff;
+ const bool hbarHidden = !d->vbar->isVisibleTo(this) || d->hbarpolicy == Qt::ScrollBarAlwaysOff;
const QSize scrollbars(vbarHidden ? 0 : d->vbar->sizeHint().width(),
hbarHidden ? 0 : d->hbar->sizeHint().height());
d->sizeHint = frame + scrollbars + viewportSizeHint();
@@ -1505,7 +1463,7 @@ QSize QAbstractScrollArea::viewportSizeHint() const
/*!
\since 5.2
\property QAbstractScrollArea::sizeAdjustPolicy
- This property holds the policy describing how the size of the scroll area changes when the
+ \brief the policy describing how the size of the scroll area changes when the
size of the viewport changes.
The default policy is QAbstractScrollArea::AdjustIgnored.
diff --git a/src/widgets/widgets/qabstractscrollarea.h b/src/widgets/widgets/qabstractscrollarea.h
index 6d0d8fa6e6..33f4b76444 100644
--- a/src/widgets/widgets/qabstractscrollarea.h
+++ b/src/widgets/widgets/qabstractscrollarea.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSCROLLAREA_H
#define QABSTRACTSCROLLAREA_H
@@ -56,8 +20,10 @@ class Q_WIDGETS_EXPORT QAbstractScrollArea : public QFrame
{
Q_OBJECT
- Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy WRITE setVerticalScrollBarPolicy)
- Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy WRITE setHorizontalScrollBarPolicy)
+ Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy
+ WRITE setVerticalScrollBarPolicy)
+ Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy
+ WRITE setHorizontalScrollBarPolicy)
Q_PROPERTY(SizeAdjustPolicy sizeAdjustPolicy READ sizeAdjustPolicy WRITE setSizeAdjustPolicy)
public:
diff --git a/src/widgets/widgets/qabstractscrollarea_p.h b/src/widgets/widgets/qabstractscrollarea_p.h
index 6d78b9db6d..7224d489ce 100644
--- a/src/widgets/widgets/qabstractscrollarea_p.h
+++ b/src/widgets/widgets/qabstractscrollarea_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSCROLLAREA_P_H
#define QABSTRACTSCROLLAREA_P_H
@@ -54,6 +18,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "private/qframe_p.h"
#include "qabstractscrollarea.h"
+#include <QtGui/private/qgridlayoutengine_p.h>
QT_BEGIN_NAMESPACE
@@ -62,8 +27,7 @@ QT_BEGIN_NAMESPACE
class QScrollBar;
class QAbstractScrollAreaScrollBarContainer;
-// ### Qt 6: is the export still needed? If not, unexport QFramePrivate, too.
-class Q_WIDGETS_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
+class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
{
Q_DECLARE_PUBLIC(QAbstractScrollArea)
@@ -73,7 +37,7 @@ public:
void replaceScrollBar(QScrollBar *scrollBar, Qt::Orientation orientation);
- QAbstractScrollAreaScrollBarContainer *scrollBarContainers[Qt::Vertical + 1];
+ QHVContainer<QAbstractScrollAreaScrollBarContainer *> scrollBarContainers;
QScrollBar *hbar, *vbar;
Qt::ScrollBarPolicy vbarpolicy, hbarpolicy;
@@ -94,9 +58,8 @@ public:
void init();
void layoutChildren();
void layoutChildren_helper(bool *needHorizontalScrollbar, bool *needVerticalScrollbar);
- // ### Fix for 4.4, talk to Bjoern E or Girish.
virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {}
- bool canStartScrollingAt( const QPoint &startPos );
+ virtual bool canStartScrollingAt( const QPoint &startPos ) const;
void flashScrollBars();
void setScrollBarTransient(QScrollBar *scrollBar, bool transient);
@@ -117,7 +80,7 @@ class QAbstractScrollAreaFilter : public QObject
Q_OBJECT
public:
QAbstractScrollAreaFilter(QAbstractScrollAreaPrivate *p) : d(p)
- { setObjectName(QLatin1String("qt_abstractscrollarea_filter")); }
+ { setObjectName(QLatin1StringView("qt_abstractscrollarea_filter")); }
bool eventFilter(QObject *o, QEvent *e) override
{ return (o == d->viewport ? d->viewportEvent(e) : false); }
private:
diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp
index a0611565b8..4e65fbac88 100644
--- a/src/widgets/widgets/qabstractslider.cpp
+++ b/src/widgets/widgets/qabstractslider.cpp
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qapplication.h>
#include "qabstractslider.h"
#include "qevent.h"
#include "qabstractslider_p.h"
#include "qdebug.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <limits.h>
@@ -107,7 +71,7 @@ QT_BEGIN_NAMESPACE
\row \li \l sliderReleased()
\li the user releases the slider.
\row \li \l actionTriggered()
- \li a slider action was triggerd.
+ \li a slider action was triggered.
\row \li \l rangeChanged()
\li a the range has changed.
\endtable
@@ -534,18 +498,25 @@ void QAbstractSlider::setValue(int value)
value = d->bound(value);
if (d->value == value && d->position == value)
return;
+
+ // delay signal emission until sliderChanged() has been called
+ const bool emitValueChanged = (value != d->value);
d->value = value;
+
if (d->position != value) {
d->position = value;
if (d->pressed)
- emit sliderMoved((d->position = value));
+ emit sliderMoved(d->position);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(this, d->value);
QAccessible::updateAccessibility(&event);
#endif
sliderChange(SliderValueChange);
- emit valueChanged(value);
+
+ if (emitValueChanged)
+ emit valueChanged(value);
+
}
/*!
diff --git a/src/widgets/widgets/qabstractslider.h b/src/widgets/widgets/qabstractslider.h
index 7791d30d10..fa2261fda1 100644
--- a/src/widgets/widgets/qabstractslider.h
+++ b/src/widgets/widgets/qabstractslider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSLIDER_H
#define QABSTRACTSLIDER_H
diff --git a/src/widgets/widgets/qabstractslider_p.h b/src/widgets/widgets/qabstractslider_p.h
index 1b8c76c7ec..db4294e198 100644
--- a/src/widgets/widgets/qabstractslider_p.h
+++ b/src/widgets/widgets/qabstractslider_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSLIDER_P_H
#define QABSTRACTSLIDER_P_H
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 6a0d2f5019..f377275d23 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h>
#include <private/qabstractspinbox_p.h>
@@ -58,10 +22,11 @@
#include <qpalette.h>
#include <qstylepainter.h>
#include <qdebug.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include <qaccessible.h>
#endif
+#include <QtCore/qpointer.h>
//#define QABSTRACTSPINBOX_QSBDEBUG
#ifdef QABSTRACTSPINBOX_QSBDEBUG
@@ -72,6 +37,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QAbstractSpinBox
\brief The QAbstractSpinBox class provides a spinbox and a line edit to
@@ -420,7 +387,7 @@ bool QAbstractSpinBox::isAccelerated() const
\since 5.3
- This property holds whether a thousands separator is enabled. By default this
+ \brief whether a thousands separator is enabled. By default this
property is false.
*/
bool QAbstractSpinBox::isGroupSeparatorShown() const
@@ -570,7 +537,7 @@ void QAbstractSpinBox::clear()
QAbstractSpinBox::StepEnabled QAbstractSpinBox::stepEnabled() const
{
Q_D(const QAbstractSpinBox);
- if (d->readOnly || d->type == QVariant::Invalid)
+ if (d->readOnly || d->type == QMetaType::UnknownType)
return StepNone;
if (d->wrapping)
return StepEnabled(StepUpEnabled | StepDownEnabled);
@@ -671,7 +638,8 @@ void QAbstractSpinBox::stepBy(int steps)
} else if (e == AlwaysEmit) {
d->emitSignals(e, old);
}
- selectAll();
+ if (style()->styleHint(QStyle::SH_SpinBox_SelectOnStep, nullptr, this, nullptr))
+ selectAll();
}
/*!
@@ -723,15 +691,15 @@ void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
d->edit->setFocusProxy(this);
d->edit->setAcceptDrops(false);
- if (d->type != QVariant::Invalid) {
- connect(d->edit, SIGNAL(textChanged(QString)),
- this, SLOT(_q_editorTextChanged(QString)));
- connect(d->edit, SIGNAL(cursorPositionChanged(int,int)),
- this, SLOT(_q_editorCursorPositionChanged(int,int)));
- connect(d->edit, SIGNAL(cursorPositionChanged(int,int)),
- this, SLOT(updateMicroFocus()));
- connect(d->edit->d_func()->control, SIGNAL(updateMicroFocus()),
- this, SLOT(updateMicroFocus()));
+ if (d->type != QMetaType::UnknownType) {
+ QObjectPrivate::connect(d->edit, &QLineEdit::textChanged,
+ d, &QAbstractSpinBoxPrivate::editorTextChanged);
+ QObjectPrivate::connect(d->edit, &QLineEdit::cursorPositionChanged,
+ d, &QAbstractSpinBoxPrivate::editorCursorPositionChanged);
+ connect(d->edit, &QLineEdit::cursorPositionChanged,
+ this, [this]() { updateMicroFocus(); });
+ connect(d->edit->d_func()->control, &QWidgetLineControl::updateMicroFocus,
+ this, [this]() { updateMicroFocus(); });
}
d->updateEditFieldGeometry();
d->edit->setContextMenuPolicy(Qt::NoContextMenu);
@@ -795,7 +763,7 @@ bool QAbstractSpinBox::event(QEvent *event)
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
- d->updateHoverControl(static_cast<const QHoverEvent *>(event)->pos());
+ d->updateHoverControl(static_cast<const QHoverEvent *>(event)->position().toPoint());
break;
case QEvent::ShortcutOverride:
if (d->edit->event(event))
@@ -905,7 +873,7 @@ QSize QAbstractSpinBox::sizeHint() const
int h = d->edit->sizeHint().height();
int w = 0;
QString s;
- QString fixedContent = d->prefix + d->suffix + QLatin1Char(' ');
+ QString fixedContent = d->prefix + d->suffix + u' ';
s = d->textFromValue(d->minimum);
s.truncate(18);
s += fixedContent;
@@ -924,8 +892,7 @@ QSize QAbstractSpinBox::sizeHint() const
QStyleOptionSpinBox opt;
initStyleOption(&opt);
QSize hint(w, h);
- d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
- .expandedTo(QApplication::globalStrut());
+ d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this);
}
return d->cachedSizeHint;
}
@@ -946,7 +913,7 @@ QSize QAbstractSpinBox::minimumSizeHint() const
int w = 0;
QString s;
- QString fixedContent = d->prefix + QLatin1Char(' ');
+ QString fixedContent = d->prefix + u' ';
s = d->textFromValue(d->minimum);
s.truncate(18);
s += fixedContent;
@@ -966,8 +933,7 @@ QSize QAbstractSpinBox::minimumSizeHint() const
initStyleOption(&opt);
QSize hint(w, h);
- d->cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
- .expandedTo(QApplication::globalStrut());
+ d->cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this);
}
return d->cachedMinimumSizeHint;
}
@@ -1012,6 +978,8 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
{
Q_D(QAbstractSpinBox);
+ d->keyboardModifiers = event->modifiers();
+
if (!event->text().isEmpty() && d->edit->cursorPosition() < d->prefix.size())
d->edit->setCursorPosition(d->prefix.size());
@@ -1048,12 +1016,12 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
}
if (d->spinClickTimerId == -1)
stepBy(steps);
- if(event->isAutoRepeat() && !isPgUpOrDown) {
- if(d->spinClickThresholdTimerId == -1 && d->spinClickTimerId == -1) {
+ if (event->isAutoRepeat() && !isPgUpOrDown) {
+ if (d->spinClickThresholdTimerId == -1 && d->spinClickTimerId == -1) {
d->updateState(up, true);
}
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(this, d->value);
QAccessible::updateAccessibility(&event);
#endif
@@ -1095,7 +1063,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
case Qt::Key_U:
if (event->modifiers() & Qt::ControlModifier
- && QGuiApplication::platformName() == QLatin1String("xcb")) { // only X11
+ && QGuiApplication::platformName() == "xcb"_L1) { // only X11
event->accept();
if (!isReadOnly())
clear();
@@ -1152,6 +1120,7 @@ void QAbstractSpinBox::keyReleaseEvent(QKeyEvent *event)
{
Q_D(QAbstractSpinBox);
+ d->keyboardModifiers = event->modifiers();
if (d->buttonState & Keyboard && !event->isAutoRepeat()) {
d->reset();
} else {
@@ -1268,7 +1237,7 @@ void QAbstractSpinBox::timerEvent(QTimerEvent *event)
killTimer(d->spinClickThresholdTimerId);
d->spinClickThresholdTimerId = -1;
d->effectiveSpinRepeatRate = d->buttonState & Keyboard
- ? QGuiApplication::styleHints()->keyboardAutoRepeatRate()
+ ? QGuiApplication::styleHints()->keyboardAutoRepeatRateF()
: d->spinClickTimerInterval;
d->spinClickTimerId = startTimer(d->effectiveSpinRepeatRate);
doStep = true;
@@ -1284,7 +1253,7 @@ void QAbstractSpinBox::timerEvent(QTimerEvent *event)
}
if (doStep) {
- const bool increaseStepRate = QGuiApplication::keyboardModifiers() & d->stepModifier;
+ const bool increaseStepRate = d->keyboardModifiers & d->stepModifier;
const StepEnabled st = stepEnabled();
if (d->buttonState & Up) {
if (!(st & StepUpEnabled)) {
@@ -1361,7 +1330,8 @@ void QAbstractSpinBox::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QAbstractSpinBox);
- d->updateHoverControl(event->pos());
+ d->keyboardModifiers = event->modifiers();
+ d->updateHoverControl(event->position().toPoint());
// If we have a timer ID, update the state
if (d->spinClickTimerId != -1 && d->buttonSymbols != NoButtons) {
@@ -1384,11 +1354,12 @@ void QAbstractSpinBox::mousePressEvent(QMouseEvent *event)
{
Q_D(QAbstractSpinBox);
+ d->keyboardModifiers = event->modifiers();
if (event->button() != Qt::LeftButton || d->buttonState != None) {
return;
}
- d->updateHoverControl(event->pos());
+ d->updateHoverControl(event->position().toPoint());
event->accept();
const StepEnabled se = (d->buttonSymbols == NoButtons) ? StepEnabled(StepNone) : stepEnabled();
@@ -1408,6 +1379,7 @@ void QAbstractSpinBox::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QAbstractSpinBox);
+ d->keyboardModifiers = event->modifiers();
if ((d->buttonState & Mouse) != 0)
d->reset();
event->accept();
@@ -1421,15 +1393,9 @@ void QAbstractSpinBox::mouseReleaseEvent(QMouseEvent *event)
*/
QAbstractSpinBoxPrivate::QAbstractSpinBoxPrivate()
- : edit(nullptr), type(QVariant::Invalid), spinClickTimerId(-1),
- spinClickTimerInterval(100), spinClickThresholdTimerId(-1), spinClickThresholdTimerInterval(-1),
- effectiveSpinRepeatRate(1), buttonState(None), cachedText(QLatin1String("\x01")),
- cachedState(QValidator::Invalid), pendingEmit(false), readOnly(false), wrapping(false),
- ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true),
- cleared(false), ignoreUpdateEdit(false), correctionMode(QAbstractSpinBox::CorrectToPreviousValue),
- stepModifier(Qt::ControlModifier), acceleration(0), hoverControl(QStyle::SC_None),
- buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(nullptr), showGroupSeparator(0),
- wheelDeltaRemainder(0)
+ : pendingEmit(false), readOnly(false), wrapping(false),
+ ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true),
+ cleared(false), ignoreUpdateEdit(false), showGroupSeparator(false)
{
}
@@ -1484,7 +1450,7 @@ QStyle::SubControl QAbstractSpinBoxPrivate::newHoverControl(const QPoint &pos)
QString QAbstractSpinBoxPrivate::stripped(const QString &t, int *pos) const
{
- QStringRef text(&t);
+ QStringView text(t);
if (specialValueText.size() == 0 || text != specialValueText) {
int from = 0;
int size = text.size();
@@ -1545,7 +1511,7 @@ void QAbstractSpinBoxPrivate::emitSignals(EmitPolicy, const QVariant &)
signal.
*/
-void QAbstractSpinBoxPrivate::_q_editorTextChanged(const QString &t)
+void QAbstractSpinBoxPrivate::editorTextChanged(const QString &t)
{
Q_Q(QAbstractSpinBox);
@@ -1575,7 +1541,7 @@ void QAbstractSpinBoxPrivate::_q_editorTextChanged(const QString &t)
the different sections etc.
*/
-void QAbstractSpinBoxPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
+void QAbstractSpinBoxPrivate::editorCursorPositionChanged(int oldpos, int newpos)
{
if (!edit->hasSelectedText() && !ignoreCursorPositionChanged && !specialValue()) {
ignoreCursorPositionChanged = true;
@@ -1626,11 +1592,13 @@ void QAbstractSpinBoxPrivate::init()
Q_Q(QAbstractSpinBox);
q->setLineEdit(new QLineEdit(q));
- edit->setObjectName(QLatin1String("qt_spinbox_lineedit"));
+ edit->setObjectName("qt_spinbox_lineedit"_L1);
validator = new QSpinBoxValidator(q, this);
edit->setValidator(validator);
QStyleOptionSpinBox opt;
+ // ### This is called from the ctor and thus we shouldn't call initStyleOption yet
+ // ### as we only call the base class implementation of initStyleOption called.
q->initStyleOption(&opt);
spinClickTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, &opt, q);
spinClickThresholdTimerInterval = q->style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, &opt, q);
@@ -1678,13 +1646,13 @@ void QAbstractSpinBoxPrivate::updateState(bool up, bool fromKeyboard /* = false
reset();
if (q && (q->stepEnabled() & (up ? QAbstractSpinBox::StepUpEnabled
: QAbstractSpinBox::StepDownEnabled))) {
- spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval);
buttonState = (up ? Up : Down) | (fromKeyboard ? Keyboard : Mouse);
int steps = up ? 1 : -1;
- if (QGuiApplication::keyboardModifiers() & stepModifier)
+ if (keyboardModifiers & stepModifier)
steps *= 10;
q->stepBy(steps);
-#ifndef QT_NO_ACCESSIBILITY
+ spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval);
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(q, value);
QAccessible::updateAccessibility(&event);
#endif
@@ -1805,7 +1773,7 @@ void QAbstractSpinBoxPrivate::setValue(const QVariant &val, EmitPolicy ep,
void QAbstractSpinBoxPrivate::updateEdit()
{
Q_Q(QAbstractSpinBox);
- if (type == QVariant::Invalid)
+ if (type == QMetaType::UnknownType)
return;
const QString newText = specialValue() ? specialValueText : prefix + textFromValue(value) + suffix;
if (newText == edit->displayText() || cleared)
@@ -1865,8 +1833,8 @@ QVariant QAbstractSpinBoxPrivate::getZeroVariant() const
{
QVariant ret;
switch (type) {
- case QVariant::Int: ret = QVariant((int)0); break;
- case QVariant::Double: ret = QVariant((double)0.0); break;
+ case QMetaType::Int: ret = QVariant(0); break;
+ case QMetaType::Double: ret = QVariant(0.0); break;
default: break;
}
return ret;
@@ -1913,7 +1881,7 @@ QVariant QAbstractSpinBoxPrivate::valueFromText(const QString &) const
void QAbstractSpinBoxPrivate::interpret(EmitPolicy ep)
{
Q_Q(QAbstractSpinBox);
- if (type == QVariant::Invalid || cleared)
+ if (type == QMetaType::UnknownType || cleared)
return;
QVariant v = getZeroVariant();
@@ -1954,7 +1922,7 @@ void QAbstractSpinBoxPrivate::clearCache() const
QVariant QAbstractSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const
{
- Q_UNUSED(steps)
+ Q_UNUSED(steps);
return singleStep;
}
@@ -1968,7 +1936,7 @@ QVariant QAbstractSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const
QSpinBoxValidator::QSpinBoxValidator(QAbstractSpinBox *qp, QAbstractSpinBoxPrivate *dp)
: QValidator(qp), qptr(qp), dptr(dp)
{
- setObjectName(QLatin1String("qt_spinboxvalidator"));
+ setObjectName("qt_spinboxvalidator"_L1);
}
/*!
@@ -1985,7 +1953,7 @@ QValidator::State QSpinBoxValidator::validate(QString &input, int &pos) const
if (!dptr->prefix.isEmpty() && !input.startsWith(dptr->prefix)) {
input.prepend(dptr->prefix);
- pos += dptr->prefix.length();
+ pos += dptr->prefix.size();
}
if (!dptr->suffix.isEmpty() && !input.endsWith(dptr->suffix))
@@ -2013,11 +1981,11 @@ void QSpinBoxValidator::fixup(QString &input) const
QVariant operator+(const QVariant &arg1, const QVariant &arg2)
{
QVariant ret;
- if (Q_UNLIKELY(arg1.type() != arg2.type()))
+ if (Q_UNLIKELY(arg1.userType() != arg2.userType()))
qWarning("QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)",
arg1.typeName(), arg2.typeName(), __FILE__, __LINE__);
- switch (arg1.type()) {
- case QVariant::Int: {
+ switch (arg1.userType()) {
+ case QMetaType::Int: {
const int int1 = arg1.toInt();
const int int2 = arg2.toInt();
if (int1 > 0 && (int2 >= INT_MAX - int1)) {
@@ -2031,9 +1999,9 @@ QVariant operator+(const QVariant &arg1, const QVariant &arg2)
}
break;
}
- case QVariant::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble()); break;
+ case QMetaType::Double: ret = QVariant(arg1.toDouble() + arg2.toDouble()); break;
#if QT_CONFIG(datetimeparser)
- case QVariant::DateTime: {
+ case QMetaType::QDateTime: {
QDateTime a2 = arg2.toDateTime();
QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATE_MIN.daysTo(a2.date()));
a1.setTime(a1.time().addMSecs(a2.time().msecsSinceStartOfDay()));
@@ -2055,13 +2023,13 @@ QVariant operator+(const QVariant &arg1, const QVariant &arg2)
QVariant operator-(const QVariant &arg1, const QVariant &arg2)
{
QVariant ret;
- if (Q_UNLIKELY(arg1.type() != arg2.type()))
+ if (Q_UNLIKELY(arg1.userType() != arg2.userType()))
qWarning("QAbstractSpinBox: Internal error: Different types (%s vs %s) (%s:%d)",
arg1.typeName(), arg2.typeName(), __FILE__, __LINE__);
- switch (arg1.type()) {
- case QVariant::Int: ret = QVariant(arg1.toInt() - arg2.toInt()); break;
- case QVariant::Double: ret = QVariant(arg1.toDouble() - arg2.toDouble()); break;
- case QVariant::DateTime: {
+ switch (arg1.userType()) {
+ case QMetaType::Int: ret = QVariant(arg1.toInt() - arg2.toInt()); break;
+ case QMetaType::Double: ret = QVariant(arg1.toDouble() - arg2.toDouble()); break;
+ case QMetaType::QDateTime: {
QDateTime a1 = arg1.toDateTime();
QDateTime a2 = arg2.toDateTime();
int days = a2.daysTo(a1);
@@ -2075,6 +2043,7 @@ QVariant operator-(const QVariant &arg1, const QVariant &arg2)
dt.setTime(dt.time().addMSecs(msecs));
ret = QVariant(dt);
}
+ break;
}
default: break;
}
@@ -2090,13 +2059,13 @@ QVariant operator*(const QVariant &arg1, double multiplier)
{
QVariant ret;
- switch (arg1.type()) {
- case QVariant::Int:
+ switch (arg1.userType()) {
+ case QMetaType::Int:
ret = static_cast<int>(qBound<double>(INT_MIN, arg1.toInt() * multiplier, INT_MAX));
break;
- case QVariant::Double: ret = QVariant(arg1.toDouble() * multiplier); break;
+ case QMetaType::Double: ret = QVariant(arg1.toDouble() * multiplier); break;
#if QT_CONFIG(datetimeparser)
- case QVariant::DateTime: {
+ case QMetaType::QDateTime: {
double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier;
const qint64 daysInt = qint64(days);
days -= daysInt;
@@ -2119,17 +2088,17 @@ double operator/(const QVariant &arg1, const QVariant &arg2)
double a1 = 0;
double a2 = 0;
- switch (arg1.type()) {
- case QVariant::Int:
+ switch (arg1.userType()) {
+ case QMetaType::Int:
a1 = (double)arg1.toInt();
a2 = (double)arg2.toInt();
break;
- case QVariant::Double:
+ case QMetaType::Double:
a1 = arg1.toDouble();
a2 = arg2.toDouble();
break;
#if QT_CONFIG(datetimeparser)
- case QVariant::DateTime:
+ case QMetaType::QDateTime:
a1 = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDate());
a2 = QDATETIMEEDIT_DATE_MIN.daysTo(arg2.toDate());
a1 += arg1.toDateTime().time().msecsSinceStartOfDay() / (36e5 * 24);
@@ -2144,9 +2113,9 @@ double operator/(const QVariant &arg1, const QVariant &arg2)
int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant &arg2)
{
- switch (arg2.type()) {
- case QVariant::Date:
- Q_ASSERT_X(arg1.type() == QVariant::Date, "QAbstractSpinBoxPrivate::variantCompare",
+ switch (arg2.userType()) {
+ case QMetaType::QDate:
+ Q_ASSERT_X(arg1.userType() == QMetaType::QDate, "QAbstractSpinBoxPrivate::variantCompare",
qPrintable(QString::fromLatin1("Internal error 1 (%1)").
arg(QString::fromLatin1(arg1.typeName()))));
if (arg1.toDate() == arg2.toDate()) {
@@ -2156,8 +2125,8 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant
} else {
return 1;
}
- case QVariant::Time:
- Q_ASSERT_X(arg1.type() == QVariant::Time, "QAbstractSpinBoxPrivate::variantCompare",
+ case QMetaType::QTime:
+ Q_ASSERT_X(arg1.userType() == QMetaType::QTime, "QAbstractSpinBoxPrivate::variantCompare",
qPrintable(QString::fromLatin1("Internal error 2 (%1)").
arg(QString::fromLatin1(arg1.typeName()))));
if (arg1.toTime() == arg2.toTime()) {
@@ -2169,7 +2138,7 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant
}
- case QVariant::DateTime:
+ case QMetaType::QDateTime:
if (arg1.toDateTime() == arg2.toDateTime()) {
return 0;
} else if (arg1.toDateTime() < arg2.toDateTime()) {
@@ -2177,7 +2146,7 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant
} else {
return 1;
}
- case QVariant::Int:
+ case QMetaType::Int:
if (arg1.toInt() == arg2.toInt()) {
return 0;
} else if (arg1.toInt() < arg2.toInt()) {
@@ -2185,7 +2154,7 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant
} else {
return 1;
}
- case QVariant::Double:
+ case QMetaType::Double:
if (arg1.toDouble() == arg2.toDouble()) {
return 0;
} else if (arg1.toDouble() < arg2.toDouble()) {
@@ -2193,8 +2162,8 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant
} else {
return 1;
}
- case QVariant::Invalid:
- if (arg2.type() == QVariant::Invalid)
+ case QMetaType::UnknownType:
+ if (arg2.userType() == QMetaType::UnknownType)
return 0;
Q_FALLTHROUGH();
default:
diff --git a/src/widgets/widgets/qabstractspinbox.h b/src/widgets/widgets/qabstractspinbox.h
index 87d46c7326..91d3dcb8fc 100644
--- a/src/widgets/widgets/qabstractspinbox.h
+++ b/src/widgets/widgets/qabstractspinbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSPINBOX_H
#define QABSTRACTSPINBOX_H
@@ -160,7 +124,7 @@ protected:
void timerEvent(QTimerEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void showEvent(QShowEvent *event) override;
- void initStyleOption(QStyleOptionSpinBox *option) const;
+ virtual void initStyleOption(QStyleOptionSpinBox *option) const;
QLineEdit *lineEdit() const;
void setLineEdit(QLineEdit *edit);
@@ -172,9 +136,6 @@ protected:
QAbstractSpinBox(QAbstractSpinBoxPrivate &dd, QWidget *parent = nullptr);
private:
- Q_PRIVATE_SLOT(d_func(), void _q_editorTextChanged(const QString &))
- Q_PRIVATE_SLOT(d_func(), void _q_editorCursorPositionChanged(int, int))
-
Q_DECLARE_PRIVATE(QAbstractSpinBox)
Q_DISABLE_COPY(QAbstractSpinBox)
friend class QAccessibleAbstractSpinBox;
diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h
index ad169fde19..4252a01423 100644
--- a/src/widgets/widgets/qabstractspinbox_p.h
+++ b/src/widgets/widgets/qabstractspinbox_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTSPINBOX_P_H
#define QABSTRACTSPINBOX_P_H
@@ -110,8 +74,8 @@ public:
virtual QString textFromValue(const QVariant &n) const;
virtual QVariant valueFromText(const QString &input) const;
- void _q_editorTextChanged(const QString &);
- virtual void _q_editorCursorPositionChanged(int oldpos, int newpos);
+ void editorTextChanged(const QString &);
+ virtual void editorCursorPositionChanged(int oldpos, int newpos);
virtual QStyle::SubControl newHoverControl(const QPoint &pos);
bool updateHoverControl(const QPoint &pos);
@@ -124,17 +88,32 @@ public:
virtual QVariant calculateAdaptiveDecimalStep(int steps) const;
- QLineEdit *edit;
QString prefix, suffix, specialValueText;
QVariant value, minimum, maximum, singleStep;
- QVariant::Type type;
- int spinClickTimerId, spinClickTimerInterval, spinClickThresholdTimerId, spinClickThresholdTimerInterval;
- int effectiveSpinRepeatRate;
- uint buttonState;
- mutable QString cachedText;
+ QRect hoverRect;
+
+ mutable QString cachedText = { u'\x01' };
mutable QVariant cachedValue;
- mutable QValidator::State cachedState;
mutable QSize cachedSizeHint, cachedMinimumSizeHint;
+ QLineEdit *edit = nullptr;
+ QSpinBoxValidator *validator = nullptr;
+ QMetaType::Type type = QMetaType::UnknownType;
+ int spinClickTimerId = -1;
+ int spinClickTimerInterval = 100;
+ int spinClickThresholdTimerId = -1;
+ int spinClickThresholdTimerInterval = -1;
+ qreal effectiveSpinRepeatRate = 1;
+ int acceleration = 0;
+ int wheelDeltaRemainder = 0;
+
+ Qt::KeyboardModifiers keyboardModifiers = Qt::NoModifier;
+ Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
+ QAbstractSpinBox::CorrectionMode correctionMode = QAbstractSpinBox::CorrectToPreviousValue;
+ QAbstractSpinBox::StepType stepType = QAbstractSpinBox::StepType::DefaultStepType;
+ QAbstractSpinBox::ButtonSymbols buttonSymbols = QAbstractSpinBox::UpDownArrows;
+ QStyle::SubControl hoverControl = QStyle::SC_None;
+ mutable QValidator::State cachedState = QValidator::Invalid;
+ uint buttonState = None;
uint pendingEmit : 1;
uint readOnly : 1;
uint wrapping : 1;
@@ -144,16 +123,7 @@ public:
uint keyboardTracking : 1;
uint cleared : 1;
uint ignoreUpdateEdit : 1;
- QAbstractSpinBox::CorrectionMode correctionMode;
- QAbstractSpinBox::StepType stepType = QAbstractSpinBox::StepType::DefaultStepType;
- Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
- int acceleration;
- QStyle::SubControl hoverControl;
- QRect hoverRect;
- QAbstractSpinBox::ButtonSymbols buttonSymbols;
- QSpinBoxValidator *validator;
uint showGroupSeparator : 1;
- int wheelDeltaRemainder;
};
class QSpinBoxValidator : public QValidator
diff --git a/src/widgets/widgets/qbuttongroup.cpp b/src/widgets/widgets/qbuttongroup.cpp
index c3fd37d8e9..079ef45e90 100644
--- a/src/widgets/widgets/qbuttongroup.cpp
+++ b/src/widgets/widgets/qbuttongroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qbuttongroup_p.h"
@@ -50,7 +14,7 @@ void QButtonGroupPrivate::detectCheckedButton()
checkedButton = nullptr;
if (exclusive)
return;
- for (int i = 0; i < buttonList.count(); i++) {
+ for (int i = 0; i < buttonList.size(); i++) {
if (buttonList.at(i) != previous && buttonList.at(i)->isChecked()) {
checkedButton = buttonList.at(i);
return;
@@ -93,8 +57,8 @@ void QButtonGroupPrivate::detectCheckedButton()
In addition, QButtonGroup can map between integers and buttons.
You can assign an integer id to a button with setId(), and
retrieve it with id(). The id of the currently checked button is
- available with checkedId(), and there is an overloaded signal
- buttonClicked() which emits the id of the button. The id \c {-1}
+ available with checkedId(), and there is a signal
+ idClicked() that emits the id of the button. The id \c {-1}
is reserved by QButtonGroup to mean "no such button". The purpose
of the mapping mechanism is to simplify the representation of enum
values in a user interface.
@@ -118,7 +82,7 @@ QButtonGroup::QButtonGroup(QObject *parent)
QButtonGroup::~QButtonGroup()
{
Q_D(QButtonGroup);
- for (int i = 0; i < d->buttonList.count(); ++i)
+ for (int i = 0; i < d->buttonList.size(); ++i)
d->buttonList.at(i)->d_func()->group = nullptr;
}
@@ -163,7 +127,8 @@ void QButtonGroup::setExclusive(bool exclusive)
*/
/*!
- \fn void QButtonGroup::buttonClicked(int id)
+ \fn void QButtonGroup::idClicked(int id)
+ \since 5.15
This signal is emitted when a button with the given \a id is
clicked.
@@ -181,8 +146,8 @@ void QButtonGroup::setExclusive(bool exclusive)
*/
/*!
- \fn void QButtonGroup::buttonPressed(int id)
- \since 4.2
+ \fn void QButtonGroup::idPressed(int id)
+ \since 5.15
This signal is emitted when a button with the given \a id is
pressed down.
@@ -200,8 +165,8 @@ void QButtonGroup::setExclusive(bool exclusive)
*/
/*!
- \fn void QButtonGroup::buttonReleased(int id)
- \since 4.2
+ \fn void QButtonGroup::idReleased(int id)
+ \since 5.15
This signal is emitted when a button with the given \a id is
released.
@@ -220,8 +185,8 @@ void QButtonGroup::setExclusive(bool exclusive)
*/
/*!
- \fn void QButtonGroup::buttonToggled(int id, bool checked)
- \since 5.2
+ \fn void QButtonGroup::idToggled(int id, bool checked)
+ \since 5.15
This signal is emitted when a button with the given \a id is toggled.
\a checked is true if the button is checked, or false if the button is unchecked.
@@ -229,7 +194,6 @@ void QButtonGroup::setExclusive(bool exclusive)
\sa QAbstractButton::toggled()
*/
-
/*!
Adds the given \a button to the button group. If \a id is -1,
an id will be assigned to the button.
diff --git a/src/widgets/widgets/qbuttongroup.h b/src/widgets/widgets/qbuttongroup.h
index fec94ccb3e..2a399e5325 100644
--- a/src/widgets/widgets/qbuttongroup.h
+++ b/src/widgets/widgets/qbuttongroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBUTTONGROUP_H
#define QBUTTONGROUP_H
@@ -78,13 +42,13 @@ public:
Q_SIGNALS:
void buttonClicked(QAbstractButton *);
- void buttonClicked(int);
void buttonPressed(QAbstractButton *);
- void buttonPressed(int);
void buttonReleased(QAbstractButton *);
- void buttonReleased(int);
void buttonToggled(QAbstractButton *, bool);
- void buttonToggled(int, bool);
+ void idClicked(int);
+ void idPressed(int);
+ void idReleased(int);
+ void idToggled(int, bool);
private:
Q_DISABLE_COPY(QButtonGroup)
diff --git a/src/widgets/widgets/qbuttongroup_p.h b/src/widgets/widgets/qbuttongroup_p.h
index 148f572373..ffeab3fc0b 100644
--- a/src/widgets/widgets/qbuttongroup_p.h
+++ b/src/widgets/widgets/qbuttongroup_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBUTTONGROUP_P_H
#define QBUTTONGROUP_P_H
diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp
index fe1133c6c7..034127b4f3 100644
--- a/src/widgets/widgets/qcalendarwidget.cpp
+++ b/src/widgets/widgets/qcalendarwidget.cpp
@@ -1,46 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcalendarwidget.h"
#include <qabstractitemmodel.h>
-#include <qitemdelegate.h>
+#include <qstyleditemdelegate.h>
#include <qdatetime.h>
#include <qtableview.h>
#include <qlayout.h>
@@ -63,6 +27,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
enum {
RowCount = 6,
ColumnCount = 7,
@@ -71,13 +37,13 @@ enum {
MinimumDayOffset = 1
};
-namespace {
-
static QString formatNumber(int number, int fieldWidth)
{
- return QString::number(number).rightJustified(fieldWidth, QLatin1Char('0'));
+ return QString::number(number).rightJustified(fieldWidth, u'0');
}
+namespace QtPrivate {
+
class QCalendarDateSectionValidator
{
public:
@@ -105,9 +71,9 @@ protected:
QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos)
{
if (pos == 0)
- return QLatin1String("<b>") + str + QLatin1String("</b>");
- int startPos = str.length() - pos;
- return str.midRef(0, startPos) + QLatin1String("<b>") + str.midRef(startPos, pos) + QLatin1String("</b>");
+ return "<b>"_L1 + str + "</b>"_L1;
+ int startPos = str.size() - pos;
+ return QStringView{str}.mid(0, startPos) + "<b>"_L1 + QStringView{str}.mid(startPos, pos) + "</b>"_L1;
}
@@ -186,7 +152,7 @@ QDate QCalendarDayValidator::applyToDate(QDate date, QCalendar cal) const
auto parts = cal.partsFromDate(date);
if (!parts.isValid())
return QDate();
- parts.day = qMin(qMax(1, m_day), cal.daysInMonth(parts.year, parts.month));
+ parts.day = qMin(qMax(1, m_day), cal.daysInMonth(parts.month, parts.year));
return cal.dateFromParts(parts);
}
@@ -292,7 +258,7 @@ QDate QCalendarMonthValidator::applyToDate(QDate date, QCalendar cal) const
if (!parts.isValid())
return QDate();
parts.month = qMin(qMax(1, m_month), cal.monthsInYear(parts.year));
- parts.day = qMin(parts.day, cal.daysInMonth(parts.year, m_month)); // m_month or parts.month ?
+ parts.day = qMin(parts.day, cal.daysInMonth(m_month, parts.year)); // m_month or parts.month ?
return cal.dateFromParts(parts);
}
@@ -401,7 +367,7 @@ QDate QCalendarYearValidator::applyToDate(QDate date, QCalendar cal) const
return QDate();
// This widget does not support negative years (some calendars may support)
parts.year = qMax(1, m_year);
- parts.day = qMin(parts.day, cal.daysInMonth(parts.year, parts.month));
+ parts.day = qMin(parts.day, cal.daysInMonth(parts.month, parts.year));
return cal.dateFromParts(parts);
}
@@ -426,15 +392,17 @@ QString QCalendarYearValidator::text(QDate date, QCalendar cal, int repeat) cons
///////////////////////////////////
struct SectionToken {
- Q_DECL_CONSTEXPR SectionToken(QCalendarDateSectionValidator *v, int rep)
+ constexpr SectionToken(QCalendarDateSectionValidator *v, int rep)
: validator(v), repeat(rep) {}
QCalendarDateSectionValidator *validator;
int repeat;
};
-} // unnamed namespace
-Q_DECLARE_TYPEINFO(SectionToken, Q_PRIMITIVE_TYPE);
-namespace {
+} // namespace QtPrivate
+
+Q_DECLARE_TYPEINFO(QtPrivate::SectionToken, Q_PRIMITIVE_TYPE);
+
+namespace QtPrivate {
class QCalendarDateValidator
{
@@ -544,11 +512,11 @@ void QCalendarDateValidator::setFormat(const QString &format)
clear();
int pos = 0;
- const QLatin1Char quote('\'');
+ const auto quote = u'\'';
bool quoting = false;
QString separator;
while (pos < format.size()) {
- const QStringRef mid = format.midRef(pos);
+ const QStringView mid = QStringView{format}.mid(pos);
int offset = 1;
if (mid.startsWith(quote)) {
@@ -560,13 +528,13 @@ void QCalendarDateValidator::setFormat(const QString &format)
quoting = false;
} else {
QCalendarDateSectionValidator *validator = nullptr;
- if (nextChar == QLatin1Char('d')) {
+ if (nextChar == u'd') {
offset = qMin(4, countRepeat(format, pos));
validator = &m_dayValidator;
- } else if (nextChar == QLatin1Char('M')) {
+ } else if (nextChar == u'M') {
offset = qMin(4, countRepeat(format, pos));
validator = &m_monthValidator;
- } else if (nextChar == QLatin1Char('y')) {
+ } else if (nextChar == u'y') {
offset = qMin(4, countRepeat(format, pos));
validator = &m_yearValidator;
} else {
@@ -761,8 +729,8 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e)
{
if (m_widget) {
if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
- QKeyEvent* ke = (QKeyEvent*)e;
- if ((ke->text().length() > 0 && ke->text().at(0).isPrint()) || m_dateFrame) {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+ if ((ke->text().size() > 0 && ke->text().at(0).isPrint()) || m_dateFrame) {
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Select) {
applyDate();
emit editingFinished();
@@ -826,27 +794,23 @@ class StaticDayOfWeekAssociativeArray {
bool contained[7];
T data[7];
- static Q_DECL_CONSTEXPR int day2idx(Qt::DayOfWeek day) noexcept { return int(day) - 1; } // alt: day % 7
+ static constexpr int day2idx(Qt::DayOfWeek day) noexcept { return int(day) - 1; } // alt: day % 7
public:
- Q_DECL_CONSTEXPR StaticDayOfWeekAssociativeArray() noexcept(noexcept(T()))
-#ifdef Q_COMPILER_CONSTEXPR
+ constexpr StaticDayOfWeekAssociativeArray() noexcept(noexcept(T()))
: contained{}, data{} // arrays require uniform initialization
-#else
- : contained(), data()
-#endif
{}
- Q_DECL_CONSTEXPR bool contains(Qt::DayOfWeek day) const noexcept { return contained[day2idx(day)]; }
- Q_DECL_CONSTEXPR const T &value(Qt::DayOfWeek day) const noexcept { return data[day2idx(day)]; }
+ constexpr bool contains(Qt::DayOfWeek day) const noexcept { return contained[day2idx(day)]; }
+ constexpr const T &value(Qt::DayOfWeek day) const noexcept { return data[day2idx(day)]; }
- Q_DECL_RELAXED_CONSTEXPR T &operator[](Qt::DayOfWeek day) noexcept
+ constexpr T &operator[](Qt::DayOfWeek day) noexcept
{
const int idx = day2idx(day);
contained[idx] = true;
return data[idx];
}
- Q_DECL_RELAXED_CONSTEXPR void insert(Qt::DayOfWeek day, T v) noexcept
+ constexpr void insert(Qt::DayOfWeek day, T v) noexcept
{
operator[](day).swap(v);
}
@@ -860,38 +824,23 @@ class QCalendarModel : public QAbstractTableModel
public:
QCalendarModel(QObject *parent = nullptr);
- int rowCount(const QModelIndex &) const override
- { return RowCount + m_firstRow; }
- int columnCount(const QModelIndex &) const override
- { return ColumnCount + m_firstColumn; }
- QVariant data(const QModelIndex &index, int role) const override;
- Qt::ItemFlags flags(const QModelIndex &index) const override;
-
- bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
- {
- beginInsertRows(parent, row, row + count - 1);
- endInsertRows();
- return true;
- }
- bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
- {
- beginInsertColumns(parent, column, column + count - 1);
- endInsertColumns();
- return true;
- }
- bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override
+ int rowCount(const QModelIndex &parent) const override
{
- beginRemoveRows(parent, row, row + count - 1);
- endRemoveRows();
- return true;
+ if (parent.isValid())
+ return 0;
+ return RowCount + m_firstRow;
}
- bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override
+
+ int columnCount(const QModelIndex &parent) const override
{
- beginRemoveColumns(parent, column, column + count - 1);
- endRemoveColumns();
- return true;
+ if (parent.isValid())
+ return 0;
+ return ColumnCount + m_firstColumn;
}
+ QVariant data(const QModelIndex &index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
void showMonth(int year, int month);
void setDate(QDate d);
@@ -955,7 +904,7 @@ public:
void internalUpdate() { updateGeometries(); }
void setReadOnly(bool enable);
- virtual void keyboardSearch(const QString & search) override { Q_UNUSED(search) }
+ virtual void keyboardSearch(const QString &) override {}
signals:
void showDate(QDate date);
@@ -1130,16 +1079,17 @@ QTextCharFormat QCalendarModel::formatForCell(int row, int col) const
{
QPalette pal;
QPalette::ColorGroup cg = QPalette::Active;
+ QTextCharFormat format;
+
if (m_view) {
pal = m_view->palette();
if (!m_view->isEnabled())
cg = QPalette::Disabled;
else if (!m_view->isActiveWindow())
cg = QPalette::Inactive;
+ format.setFont(m_view->font());
}
- QTextCharFormat format;
- format.setFont(m_view->font());
bool header = (m_weekNumbersShown && col == HeaderColumn)
|| (m_horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow);
format.setBackground(pal.brush(cg, header ? QPalette::AlternateBase : QPalette::Base));
@@ -1157,7 +1107,7 @@ QTextCharFormat QCalendarModel::formatForCell(int row, int col) const
if (!header) {
QDate date = dateForCell(row, col);
format.merge(m_dateFormats.value(date));
- if(date < m_minimumDate || date > m_maximumDate)
+ if (date < m_minimumDate || date > m_maximumDate)
format.setBackground(pal.brush(cg, QPalette::Window));
if (m_shownMonth != date.month(m_calendar))
format.setForeground(pal.brush(QPalette::Disabled, QPalette::Text));
@@ -1173,7 +1123,7 @@ QVariant QCalendarModel::data(const QModelIndex &index, int role) const
int row = index.row();
int column = index.column();
- if(role == Qt::DisplayRole) {
+ if (role == Qt::DisplayRole) {
if (m_weekNumbersShown && column == HeaderColumn
&& row >= m_firstRow && row < m_firstRow + RowCount) {
QDate date = dateForCell(row, columnForDayOfWeek(Qt::Monday));
@@ -1303,11 +1253,13 @@ void QCalendarModel::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeader
int oldFormat = m_horizontalHeaderFormat;
m_horizontalHeaderFormat = format;
if (oldFormat == QCalendarWidget::NoHorizontalHeader) {
+ beginInsertRows(QModelIndex(), 0, 0);
m_firstRow = 1;
- insertRow(0);
+ endInsertRows();
} else if (m_horizontalHeaderFormat == QCalendarWidget::NoHorizontalHeader) {
+ beginRemoveRows(QModelIndex(), 0, 0);
m_firstRow = 0;
- removeRow(0);
+ endRemoveRows();
}
internalUpdate();
}
@@ -1338,11 +1290,13 @@ void QCalendarModel::setWeekNumbersShown(bool show)
m_weekNumbersShown = show;
if (show) {
+ beginInsertColumns(QModelIndex(), 0, 0);
m_firstColumn = 1;
- insertColumn(0);
+ endInsertColumns();
} else {
+ beginRemoveColumns(QModelIndex(), 0, 0);
m_firstColumn = 0;
- removeColumn(0);
+ endRemoveColumns();
}
internalUpdate();
}
@@ -1397,7 +1351,7 @@ QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardMod
case QAbstractItemView::MoveEnd: {
auto parts = cal.partsFromDate(currentDate);
if (parts.isValid()) {
- parts.day = cal.daysInMonth(parts.year, parts.month);
+ parts.day = cal.daysInMonth(parts.month, parts.year);
currentDate = cal.dateFromParts(parts);
}
}
@@ -1485,7 +1439,7 @@ QDate QCalendarView::handleMouseEvent(QMouseEvent *event)
if (!calendarModel)
return QDate();
- QPoint pos = event->pos();
+ QPoint pos = event->position().toPoint();
QModelIndex index = indexAt(pos);
QDate date = calendarModel->dateForCell(index.row(), index.column());
if (date.isValid() && date >= calendarModel->m_minimumDate
@@ -1594,13 +1548,12 @@ void QCalendarView::mouseReleaseEvent(QMouseEvent *event)
}
}
-// ### Qt6: QStyledItemDelegate
-class QCalendarDelegate : public QItemDelegate
+class QCalendarDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
QCalendarDelegate(QCalendarWidgetPrivate *w, QObject *parent = nullptr)
- : QItemDelegate(parent), calendarWidgetPrivate(w)
+ : QStyledItemDelegate(parent), calendarWidgetPrivate(w)
{ }
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
@@ -1621,7 +1574,7 @@ public:
protected:
void paintEvent(QPaintEvent *e) override
{
- Q_UNUSED(e)
+ Q_UNUSED(e);
QStyleOptionToolButton opt;
initStyleOption(&opt);
@@ -1655,7 +1608,20 @@ protected:
}
};
-} // unnamed namespace
+} // namespace QtPrivate
+
+using QCalendarDateSectionValidator = QtPrivate::QCalendarDateSectionValidator;
+using QCalendarDayValidator = QtPrivate::QCalendarDayValidator;
+using QCalendarMonthValidator = QtPrivate::QCalendarMonthValidator;
+using QCalendarYearValidator = QtPrivate::QCalendarYearValidator;
+using QCalendarDateValidator = QtPrivate::QCalendarDateValidator;
+using QPrevNextCalButton = QtPrivate::QPrevNextCalButton;
+using QCalendarDelegate = QtPrivate::QCalendarDelegate;
+using QCalToolButton = QtPrivate::QCalToolButton;
+using QCalendarDelegate = QtPrivate::QCalendarDelegate;
+using QCalendarModel = QtPrivate::QCalendarModel;
+using QCalendarView = QtPrivate::QCalendarView;
+using QCalendarTextNavigator = QtPrivate::QCalendarTextNavigator;
class QCalendarWidgetPrivate : public QWidgetPrivate
{
@@ -1717,7 +1683,7 @@ void QCalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt
QRect rect = option.rect;
calendarWidgetPrivate->paintCell(painter, rect, date);
} else {
- QItemDelegate::paint(painter, option, index);
+ QStyledItemDelegate::paint(painter, option, index);
}
}
@@ -1728,7 +1694,7 @@ void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, QDate da
int col = -1;
calendarWidgetPrivate->m_model->cellForDate(date, &row, &col);
QModelIndex idx = calendarWidgetPrivate->m_model->index(row, col);
- QItemDelegate::paint(painter, storedOption, idx);
+ QStyledItemDelegate::paint(painter, storedOption, idx);
}
QCalendarWidgetPrivate::QCalendarWidgetPrivate()
@@ -1773,7 +1739,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
{
Q_Q(QCalendarWidget);
navBarBackground = new QWidget(widget);
- navBarBackground->setObjectName(QLatin1String("qt_calendar_navigationbar"));
+ navBarBackground->setObjectName("qt_calendar_navigationbar"_L1);
navBarBackground->setAutoFillBackground(true);
navBarBackground->setBackgroundRole(QPalette::Highlight);
@@ -1834,11 +1800,11 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
monthButton->setFocusPolicy(Qt::NoFocus);
//set names for the header controls.
- prevMonth->setObjectName(QLatin1String("qt_calendar_prevmonth"));
- nextMonth->setObjectName(QLatin1String("qt_calendar_nextmonth"));
- monthButton->setObjectName(QLatin1String("qt_calendar_monthbutton"));
- yearButton->setObjectName(QLatin1String("qt_calendar_yearbutton"));
- yearEdit->setObjectName(QLatin1String("qt_calendar_yearedit"));
+ prevMonth->setObjectName("qt_calendar_prevmonth"_L1);
+ nextMonth->setObjectName("qt_calendar_nextmonth"_L1);
+ monthButton->setObjectName("qt_calendar_monthbutton"_L1);
+ yearButton->setObjectName("qt_calendar_yearbutton"_L1);
+ yearEdit->setObjectName("qt_calendar_yearedit"_L1);
updateMonthMenu();
showMonth(m_model->m_date.year(m_model->m_calendar), m_model->m_date.month(m_model->m_calendar));
@@ -1939,7 +1905,6 @@ void QCalendarWidgetPrivate::_q_nextMonthClicked()
void QCalendarWidgetPrivate::_q_yearEditingFinished()
{
Q_Q(QCalendarWidget);
- yearButton->setText(q->locale().toString(yearEdit->value()));
yearEdit->hide();
q->setFocusPolicy(oldFocusPolicy);
qApp->removeEventFilter(q);
@@ -1948,6 +1913,7 @@ void QCalendarWidgetPrivate::_q_yearEditingFinished()
QDate currentDate = getCurrentDate();
int newYear = q->locale().toInt(yearEdit->text());
currentDate = currentDate.addYears(newYear - currentDate.year(m_model->m_calendar), m_model->m_calendar);
+ yearButton->setText(q->locale().toString(currentDate, u"yyyy", m_model->m_calendar));
updateCurrentPage(currentDate);
}
@@ -2150,7 +2116,7 @@ QCalendarWidget::QCalendarWidget(QWidget *parent)
d->m_model->m_dayFormats.insert(Qt::Saturday, fmt);
d->m_model->m_dayFormats.insert(Qt::Sunday, fmt);
d->m_view = new QCalendarView(this);
- d->m_view->setObjectName(QLatin1String("qt_calendar_calendarview"));
+ d->m_view->setObjectName("qt_calendar_calendarview"_L1);
d->m_view->setModel(d->m_model);
d->m_model->setView(d->m_view);
d->m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
@@ -2232,7 +2198,9 @@ QSize QCalendarWidget::minimumSizeHint() const
int rows = 7;
int cols = 8;
- const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
+ QStyleOption option;
+ option.initFrom(this);
+ const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, this) + 1) * 2;
if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
rows = 6;
@@ -2291,7 +2259,7 @@ QSize QCalendarWidget::minimumSizeHint() const
headerW += monthW + buttonDecoMargin;
fm = d->yearButton->fontMetrics();
- headerW += fm.boundingRect(QLatin1String("5555")).width() + buttonDecoMargin;
+ headerW += fm.boundingRect("5555"_L1).width() + buttonDecoMargin;
headerSize = QSize(headerW, headerH);
}
@@ -2309,7 +2277,7 @@ QSize QCalendarWidget::minimumSizeHint() const
Paints the cell specified by the given \a date, using the given \a painter and \a rect.
*/
-void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
+void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, QDate date) const
{
Q_D(const QCalendarWidget);
d->m_delegate->paintCell(painter, rect, date);
@@ -2332,7 +2300,7 @@ QDate QCalendarWidget::selectedDate() const
return d->m_model->m_date;
}
-void QCalendarWidget::setSelectedDate(const QDate &date)
+void QCalendarWidget::setSelectedDate(QDate date)
{
Q_D(QCalendarWidget);
if (d->m_model->m_date == date && date == d->getCurrentDate())
@@ -2393,7 +2361,7 @@ void QCalendarWidget::setCurrentPage(int year, int month)
QDate currentDate = d->getCurrentDate();
QCalendar cal = d->m_model->m_calendar;
int day = currentDate.day(cal);
- int daysInMonths = cal.daysInMonth(year, month);
+ int daysInMonths = cal.daysInMonth(month, year);
if (day > daysInMonths)
day = daysInMonths;
@@ -2524,14 +2492,14 @@ void QCalendarWidget::showToday()
\snippet code/src_gui_widgets_qcalendarwidget.cpp 1
\endtable
- By default, the minimum date is the earliest date that the QDate
- class can handle.
-
When setting a minimum date, the maximumDate and selectedDate
properties are adjusted if the selection range becomes invalid. If
the provided date is not a valid QDate object, the
setMinimumDate() function does nothing.
+ The default minimum date is November 25, 4714 BCE.
+ You can restore this default by calling clearMinimumDate() (since Qt 6.6).
+
\sa setDateRange()
*/
@@ -2541,7 +2509,7 @@ QDate QCalendarWidget::minimumDate() const
return d->m_model->m_minimumDate;
}
-void QCalendarWidget::setMinimumDate(const QDate &date)
+void QCalendarWidget::setMinimumDate(QDate date)
{
Q_D(QCalendarWidget);
if (!date.isValid() || d->m_model->m_minimumDate == date)
@@ -2560,6 +2528,11 @@ void QCalendarWidget::setMinimumDate(const QDate &date)
}
}
+void QCalendarWidget::clearMinimumDate()
+{
+ setMinimumDate(QDate::fromJulianDay(1));
+}
+
/*!
\property QCalendarWidget::maximumDate
\brief the maximum date of the currently specified date range.
@@ -2575,14 +2548,14 @@ void QCalendarWidget::setMinimumDate(const QDate &date)
\snippet code/src_gui_widgets_qcalendarwidget.cpp 2
\endtable
- By default, the maximum date is the last day the QDate class can
- handle.
-
When setting a maximum date, the minimumDate and selectedDate
properties are adjusted if the selection range becomes invalid. If
the provided date is not a valid QDate object, the
setMaximumDate() function does nothing.
+ The default maximum date is December 31, 9999 CE.
+ You can restore this default by calling clearMaximumDate() (since Qt 6.6).
+
\sa setDateRange()
*/
@@ -2592,7 +2565,7 @@ QDate QCalendarWidget::maximumDate() const
return d->m_model->m_maximumDate;
}
-void QCalendarWidget::setMaximumDate(const QDate &date)
+void QCalendarWidget::setMaximumDate(QDate date)
{
Q_D(QCalendarWidget);
if (!date.isValid() || d->m_model->m_maximumDate == date)
@@ -2611,6 +2584,11 @@ void QCalendarWidget::setMaximumDate(const QDate &date)
}
}
+void QCalendarWidget::clearMaximumDate()
+{
+ setMaximumDate(QDate(9999, 12, 31));
+}
+
/*!
Defines a date range by setting the minimumDate and maximumDate
properties.
@@ -2630,7 +2608,7 @@ void QCalendarWidget::setMaximumDate(const QDate &date)
\sa setMinimumDate(), setMaximumDate()
*/
-void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
+void QCalendarWidget::setDateRange(QDate min, QDate max)
{
Q_D(QCalendarWidget);
if (d->m_model->m_minimumDate == min && d->m_model->m_maximumDate == max)
@@ -2895,10 +2873,10 @@ QMap<QDate, QTextCharFormat> QCalendarWidget::dateTextFormat() const
}
/*!
- Returns a QTextCharFormat for \a date. The char format can be be
+ Returns a QTextCharFormat for \a date. The char format can be
empty if the date is not renderd specially.
*/
-QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
+QTextCharFormat QCalendarWidget::dateTextFormat(QDate date) const
{
Q_D(const QCalendarWidget);
return d->m_model->m_dateFormats.value(date);
@@ -2909,7 +2887,7 @@ QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
If \a date is null, all date formats are cleared.
*/
-void QCalendarWidget::setDateTextFormat(const QDate &date, const QTextCharFormat &format)
+void QCalendarWidget::setDateTextFormat(QDate date, const QTextCharFormat &format)
{
Q_D(QCalendarWidget);
if (date.isNull())
@@ -2961,7 +2939,7 @@ void QCalendarWidget::setDateEditEnabled(bool enable)
\since 4.3
If the calendar widget's \l{dateEditEnabled}{date edit is enabled}, this
- property specifies the amount of time (in millseconds) that the date edit
+ property specifies the amount of time (in milliseconds) that the date edit
remains open after the most recent user input. Once this time has elapsed,
the date specified in the date edit is accepted and the popup is closed.
@@ -2987,7 +2965,7 @@ void QCalendarWidget::setDateEditAcceptDelay(int delay)
\sa updateCells(), yearShown(), monthShown()
*/
-void QCalendarWidget::updateCell(const QDate &date)
+void QCalendarWidget::updateCell(QDate date)
{
if (Q_UNLIKELY(!date.isValid())) {
qWarning("QCalendarWidget::updateCell: Invalid date");
@@ -3046,7 +3024,7 @@ void QCalendarWidget::updateCells()
*/
/*!
- \fn void QCalendarWidget::activated(const QDate &date)
+ \fn void QCalendarWidget::activated(QDate date)
This signal is emitted whenever the user presses the Return or
Enter key or double-clicks a \a date in the calendar
@@ -3054,7 +3032,7 @@ void QCalendarWidget::updateCells()
*/
/*!
- \fn void QCalendarWidget::clicked(const QDate &date)
+ \fn void QCalendarWidget::clicked(QDate date)
This signal is emitted when a mouse button is clicked. The date
the mouse was clicked on is specified by \a date. The signal is
@@ -3121,6 +3099,7 @@ bool QCalendarWidget::event(QEvent *event)
case QEvent::StyleChange:
d->cachedSizeHint = QSize();
d->m_view->updateGeometry();
+ break;
default:
break;
}
@@ -3143,7 +3122,7 @@ bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event)
if (!widget || widget->window() != tlw)
return QWidget::eventFilter(watched, event);
- QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->pos());
+ QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->position().toPoint());
QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size());
if (!geom.contains(mousePos)) {
event->accept();
@@ -3175,7 +3154,7 @@ void QCalendarWidget::resizeEvent(QResizeEvent * event)
// XXX Should really use a QWidgetStack for yearEdit and yearButton,
// XXX here we hide the year edit when the layout is likely to break
// XXX the manual positioning of the yearEdit over the yearButton.
- if(d->yearEdit->isVisible() && event->size().width() != event->oldSize().width())
+ if (d->yearEdit->isVisible() && event->size().width() != event->oldSize().width())
d->_q_yearEditingFinished();
QWidget::resizeEvent(event);
diff --git a/src/widgets/widgets/qcalendarwidget.h b/src/widgets/widgets/qcalendarwidget.h
index 08825a0ff3..034c95dd62 100644
--- a/src/widgets/widgets/qcalendarwidget.h
+++ b/src/widgets/widgets/qcalendarwidget.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCALENDARWIDGET_H
#define QCALENDARWIDGET_H
@@ -57,13 +21,15 @@ class Q_WIDGETS_EXPORT QCalendarWidget : public QWidget
Q_OBJECT
Q_ENUMS(Qt::DayOfWeek)
Q_PROPERTY(QDate selectedDate READ selectedDate WRITE setSelectedDate)
- Q_PROPERTY(QDate minimumDate READ minimumDate WRITE setMinimumDate)
- Q_PROPERTY(QDate maximumDate READ maximumDate WRITE setMaximumDate)
+ Q_PROPERTY(QDate minimumDate READ minimumDate WRITE setMinimumDate RESET clearMinimumDate)
+ Q_PROPERTY(QDate maximumDate READ maximumDate WRITE setMaximumDate RESET clearMaximumDate)
Q_PROPERTY(Qt::DayOfWeek firstDayOfWeek READ firstDayOfWeek WRITE setFirstDayOfWeek)
Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(HorizontalHeaderFormat horizontalHeaderFormat READ horizontalHeaderFormat WRITE setHorizontalHeaderFormat)
- Q_PROPERTY(VerticalHeaderFormat verticalHeaderFormat READ verticalHeaderFormat WRITE setVerticalHeaderFormat)
+ Q_PROPERTY(HorizontalHeaderFormat horizontalHeaderFormat READ horizontalHeaderFormat
+ WRITE setHorizontalHeaderFormat)
+ Q_PROPERTY(VerticalHeaderFormat verticalHeaderFormat READ verticalHeaderFormat
+ WRITE setVerticalHeaderFormat)
Q_PROPERTY(bool navigationBarVisible READ isNavigationBarVisible WRITE setNavigationBarVisible)
Q_PROPERTY(bool dateEditEnabled READ isDateEditEnabled WRITE setDateEditEnabled)
Q_PROPERTY(int dateEditAcceptDelay READ dateEditAcceptDelay WRITE setDateEditAcceptDelay)
@@ -101,10 +67,12 @@ public:
int monthShown() const;
QDate minimumDate() const;
- void setMinimumDate(const QDate &date);
+ void setMinimumDate(QDate date);
+ void clearMinimumDate();
QDate maximumDate() const;
- void setMaximumDate(const QDate &date);
+ void setMaximumDate(QDate date);
+ void clearMaximumDate();
Qt::DayOfWeek firstDayOfWeek() const;
void setFirstDayOfWeek(Qt::DayOfWeek dayOfWeek);
@@ -131,8 +99,8 @@ public:
void setWeekdayTextFormat(Qt::DayOfWeek dayOfWeek, const QTextCharFormat &format);
QMap<QDate, QTextCharFormat> dateTextFormat() const;
- QTextCharFormat dateTextFormat(const QDate &date) const;
- void setDateTextFormat(const QDate &date, const QTextCharFormat &format);
+ QTextCharFormat dateTextFormat(QDate date) const;
+ void setDateTextFormat(QDate date, const QTextCharFormat &format);
bool isDateEditEnabled() const;
void setDateEditEnabled(bool enable);
@@ -147,13 +115,13 @@ protected:
void resizeEvent(QResizeEvent * event) override;
void keyPressEvent(QKeyEvent * event) override;
- virtual void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
- void updateCell(const QDate &date);
+ virtual void paintCell(QPainter *painter, const QRect &rect, QDate date) const;
+ void updateCell(QDate date);
void updateCells();
public Q_SLOTS:
- void setSelectedDate(const QDate &date);
- void setDateRange(const QDate &min, const QDate &max);
+ void setSelectedDate(QDate date);
+ void setDateRange(QDate min, QDate max);
void setCurrentPage(int year, int month);
void setGridVisible(bool show);
void setNavigationBarVisible(bool visible);
@@ -166,17 +134,17 @@ public Q_SLOTS:
Q_SIGNALS:
void selectionChanged();
- void clicked(const QDate &date);
- void activated(const QDate &date);
+ void clicked(QDate date);
+ void activated(QDate date);
void currentPageChanged(int year, int month);
private:
Q_DECLARE_PRIVATE(QCalendarWidget)
Q_DISABLE_COPY(QCalendarWidget)
- Q_PRIVATE_SLOT(d_func(), void _q_slotShowDate(const QDate &date))
- Q_PRIVATE_SLOT(d_func(), void _q_slotChangeDate(const QDate &date))
- Q_PRIVATE_SLOT(d_func(), void _q_slotChangeDate(const QDate &date, bool changeMonth))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotShowDate(QDate date))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotChangeDate(QDate date))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotChangeDate(QDate date, bool changeMonth))
Q_PRIVATE_SLOT(d_func(), void _q_editingFinished())
Q_PRIVATE_SLOT(d_func(), void _q_prevMonthClicked())
Q_PRIVATE_SLOT(d_func(), void _q_nextMonthClicked())
diff --git a/src/widgets/widgets/qcheckbox.cpp b/src/widgets/widgets/qcheckbox.cpp
index 81bfd3af35..88cd603d70 100644
--- a/src/widgets/widgets/qcheckbox.cpp
+++ b/src/widgets/widgets/qcheckbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcheckbox.h"
#include "qapplication.h"
@@ -45,7 +9,7 @@
#include "qstyle.h"
#include "qstyleoption.h"
#include "qevent.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
@@ -64,7 +28,7 @@ public:
uint tristate : 1;
uint noChange : 1;
uint hovering : 1;
- uint publishedState : 2;
+ Qt::CheckState publishedState : 3;
void init();
};
@@ -95,7 +59,7 @@ public:
\endtable
Whenever a checkbox is checked or cleared, it emits the signal
- stateChanged(). Connect to this signal if you want to trigger an action
+ checkStateChanged(). Connect to this signal if you want to trigger an action
each time the checkbox changes state. You can use isChecked() to query
whether or not a checkbox is checked.
@@ -120,14 +84,21 @@ public:
setPixmap(), accel(), setAccel(), isToggleButton(), setDown(), isDown(),
isOn(), checkState(), autoRepeat(), isExclusiveToggle(), group(),
setAutoRepeat(), toggle(), pressed(), released(), clicked(), toggled(),
- checkState(), and stateChanged().
+ checkState(), and checkStateChanged().
- \sa QAbstractButton, QRadioButton, {fowler}{GUI Design Handbook: Check Box}
+ \sa QAbstractButton, QRadioButton
*/
/*!
\fn void QCheckBox::stateChanged(int state)
+ \deprecated [6.9] Use checkStateChanged(Qt::CheckState) instead.
+*/
+
+/*!
+ \fn void QCheckBox::checkStateChanged(Qt::CheckState state)
+ \since 6.7
+
This signal is emitted whenever the checkbox's state changes, i.e.,
whenever the user checks or unchecks it.
@@ -247,7 +218,7 @@ Qt::CheckState QCheckBox::checkState() const
void QCheckBox::setCheckState(Qt::CheckState state)
{
Q_D(QCheckBox);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
bool noChange = d->noChange;
#endif
if (state == Qt::PartiallyChecked) {
@@ -260,12 +231,17 @@ void QCheckBox::setCheckState(Qt::CheckState state)
setChecked(state != Qt::Unchecked);
d->blockRefresh = false;
d->refresh();
- if ((uint)state != d->publishedState) {
+ if (state != d->publishedState) {
d->publishedState = state;
+ emit checkStateChanged(state);
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_IGNORE_DEPRECATIONS(
emit stateChanged(state);
+ )
+#endif
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (noChange != d->noChange) {
QAccessible::State s;
s.checkStateMixed = true;
@@ -292,8 +268,7 @@ QSize QCheckBox::sizeHint() const
text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
- d->sizeHint = (style()->sizeFromContents(QStyle::CT_CheckBox, &opt, sz, this)
- .expandedTo(QApplication::globalStrut()));
+ d->sizeHint = style()->sizeFromContents(QStyle::CT_CheckBox, &opt, sz, this);
return d->sizeHint;
}
@@ -326,7 +301,7 @@ void QCheckBox::mouseMoveEvent(QMouseEvent *e)
if (testAttribute(Qt::WA_Hover)) {
bool hit = false;
if (underMouse())
- hit = hitButton(e->pos());
+ hit = hitButton(e->position().toPoint());
if (hit != d->hovering) {
update(rect());
@@ -356,9 +331,14 @@ void QCheckBox::checkStateSet()
Q_D(QCheckBox);
d->noChange = false;
Qt::CheckState state = checkState();
- if ((uint)state != d->publishedState) {
+ if (state != d->publishedState) {
d->publishedState = state;
+ emit checkStateChanged(state);
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_IGNORE_DEPRECATIONS(
emit stateChanged(state);
+ )
+#endif
}
}
diff --git a/src/widgets/widgets/qcheckbox.h b/src/widgets/widgets/qcheckbox.h
index 80cb22b82e..de623b7b9e 100644
--- a/src/widgets/widgets/qcheckbox.h
+++ b/src/widgets/widgets/qcheckbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCHECKBOX_H
#define QCHECKBOX_H
@@ -72,7 +36,11 @@ public:
void setCheckState(Qt::CheckState state);
Q_SIGNALS:
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_9("Use checkStateChanged() instead")
void stateChanged(int);
+#endif
+ void checkStateChanged(Qt::CheckState);
protected:
bool event(QEvent *e) override;
@@ -81,7 +49,7 @@ protected:
void nextCheckState() override;
void paintEvent(QPaintEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
- void initStyleOption(QStyleOptionButton *option) const;
+ virtual void initStyleOption(QStyleOptionButton *option) const;
private:
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index d786c7ff83..1fe9a8d7be 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcombobox.h"
@@ -44,13 +8,11 @@
#include <qpa/qplatformmenu.h>
#include <qlineedit.h>
#include <qapplication.h>
-#include <qdesktopwidget.h>
-#include <private/qdesktopwidget_p.h>
#include <qlistview.h>
#if QT_CONFIG(tableview)
#include <qtableview.h>
#endif
-#include <qitemdelegate.h>
+#include <qabstractitemdelegate.h>
#include <qmap.h>
#if QT_CONFIG(menu)
#include <qmenu.h>
@@ -83,24 +45,30 @@
# include <private/qeffects_p.h>
#endif
#include <private/qstyle_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
+#include <array>
+
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QComboBoxPrivate::QComboBoxPrivate()
: QWidgetPrivate(),
shownOnce(false),
- autoCompletion(true),
duplicatesEnabled(false),
frame(true),
- inserting(false)
+ inserting(false),
+ hidingPopup(false)
{
}
QComboBoxPrivate::~QComboBoxPrivate()
{
+ disconnectModel();
#ifdef Q_OS_MAC
cleanupNativePopup();
#endif
@@ -144,11 +112,11 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
menuOption.menuItemType = QStyleOptionMenuItem::Normal;
QVariant variant = index.model()->data(index, Qt::DecorationRole);
- switch (variant.type()) {
- case QVariant::Icon:
+ switch (variant.userType()) {
+ case QMetaType::QIcon:
menuOption.icon = qvariant_cast<QIcon>(variant);
break;
- case QVariant::Color: {
+ case QMetaType::QColor: {
static QPixmap pixmap(option.decorationSize);
pixmap.fill(qvariant_cast<QColor>(variant));
menuOption.icon = pixmap;
@@ -161,9 +129,8 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
menuOption.palette.setBrush(QPalette::All, QPalette::Window,
qvariant_cast<QBrush>(index.data(Qt::BackgroundRole)));
}
- menuOption.text = index.model()->data(index, Qt::DisplayRole).toString()
- .replace(QLatin1Char('&'), QLatin1String("&&"));
- menuOption.tabWidth = 0;
+ menuOption.text = index.model()->data(index, Qt::DisplayRole).toString().replace(u'&', "&&"_L1);
+ menuOption.reservedShortcutWidth = 0;
menuOption.maxIconWidth = option.decorationSize.width() + 4;
menuOption.menuRect = option.rect;
menuOption.rect = option.rect;
@@ -237,7 +204,7 @@ bool QComboMenuDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
}
#if QT_CONFIG(completer)
-void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index)
+void QComboBoxPrivate::completerActivated(const QModelIndex &index)
{
Q_Q(QComboBox);
#if QT_CONFIG(proxymodel)
@@ -263,15 +230,6 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index)
}
}
#endif
-
-# ifdef QT_KEYPAD_NAVIGATION
- if ( QApplicationPrivate::keypadNavigationEnabled()
- && q->isEditable()
- && q->completer()
- && q->completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ) {
- q->setEditFocus(false);
- }
-# endif // QT_KEYPAD_NAVIGATION
}
#endif // QT_CONFIG(completer)
@@ -286,29 +244,48 @@ void QComboBoxPrivate::updateArrow(QStyle::StateFlag state)
q->update(q->rect());
}
-void QComboBoxPrivate::_q_modelReset()
+void QComboBoxPrivate::modelReset()
{
Q_Q(QComboBox);
if (lineEdit) {
lineEdit->setText(QString());
updateLineEditGeometry();
}
- if (currentIndex.row() != indexBeforeChange)
- _q_emitCurrentIndexChanged(currentIndex);
+ trySetValidIndex();
modelChanged();
q->update();
}
-void QComboBoxPrivate::_q_modelDestroyed()
+void QComboBoxPrivate::modelDestroyed()
{
model = QAbstractItemModelPrivate::staticEmptyModel();
}
-QRect QComboBoxPrivate::popupGeometry(int screen) const
+void QComboBoxPrivate::trySetValidIndex()
+{
+ Q_Q(QComboBox);
+ bool currentReset = false;
+
+ const int rowCount = q->count();
+ for (int pos = 0; pos < rowCount; ++pos) {
+ const QModelIndex idx(model->index(pos, modelColumn, root));
+ if (idx.flags() & Qt::ItemIsEnabled) {
+ setCurrentIndex(idx);
+ currentReset = true;
+ break;
+ }
+ }
+
+ if (!currentReset)
+ setCurrentIndex(QModelIndex());
+}
+
+QRect QComboBoxPrivate::popupGeometry(const QPoint &globalPosition) const
{
+ Q_Q(const QComboBox);
return QStylePrivate::useFullScreenForPopup()
- ? QDesktopWidgetPrivate::screenGeometry(screen)
- : QDesktopWidgetPrivate::availableGeometry(screen);
+ ? QWidgetPrivate::screenGeometry(q, globalPosition)
+ : QWidgetPrivate::availableScreenGeometry(q, globalPosition);
}
bool QComboBoxPrivate::updateHoverControl(const QPoint &pos)
@@ -382,7 +359,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
case QComboBox::AdjustToContents:
case QComboBox::AdjustToContentsOnFirstShow:
if (count == 0) {
- sh.rwidth() = 7 * fm.horizontalAdvance(QLatin1Char('x'));
+ sh.rwidth() = 7 * fm.horizontalAdvance(u'x');
} else {
for (int i = 0; i < count; ++i) {
if (!q->itemIcon(i).isNull()) {
@@ -394,10 +371,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
}
}
break;
- case QComboBox::AdjustToMinimumContentsLength:
- for (int i = 0; i < count && !hasIcon; ++i)
- hasIcon = !q->itemIcon(i).isNull();
- default:
+ case QComboBox::AdjustToMinimumContentsLengthWithIcon:
;
}
} else {
@@ -405,7 +379,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
hasIcon = !q->itemIcon(i).isNull();
}
if (minimumContentsLength > 0)
- sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.horizontalAdvance(QLatin1Char('X')) + (hasIcon ? iconSize.width() + 4 : 0)));
+ sh.setWidth(qMax(sh.width(), minimumContentsLength * fm.horizontalAdvance(u'X') + (hasIcon ? iconSize.width() + 4 : 0)));
if (!placeholderText.isEmpty())
sh.setWidth(qMax(sh.width(), fm.boundingRect(placeholderText).width()));
@@ -421,7 +395,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const
q->initStyleOption(&opt);
sh = q->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, q);
}
- return sh.expandedTo(QApplication::globalStrut());
+ return sh;
}
void QComboBoxPrivate::adjustComboBoxSize()
@@ -518,21 +492,27 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView
setLineWidth(1);
}
- setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
-
if (top) {
layout->insertWidget(0, top);
- connect(top, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
+ connect(top, &QComboBoxPrivateScroller::doScroll,
+ this, &QComboBoxPrivateContainer::scrollItemView);
}
if (bottom) {
layout->addWidget(bottom);
- connect(bottom, SIGNAL(doScroll(int)), this, SLOT(scrollItemView(int)));
+ connect(bottom, &QComboBoxPrivateScroller::doScroll,
+ this, &QComboBoxPrivateContainer::scrollItemView);
}
// Some styles (Mac) have a margin at the top and bottom of the popup.
layout->insertSpacing(0, 0);
layout->addSpacing(0);
- updateTopBottomMargin();
+ updateStyleSettings();
+}
+
+QComboBoxPrivateContainer::~QComboBoxPrivateContainer()
+{
+ disconnect(view, &QAbstractItemView::destroyed,
+ this, &QComboBoxPrivateContainer::viewDestroyed);
}
void QComboBoxPrivateContainer::scrollItemView(int action)
@@ -615,13 +595,13 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
view->removeEventFilter(this);
view->viewport()->removeEventFilter(this);
#if QT_CONFIG(scrollbar)
- disconnect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
- this, SLOT(updateScrollers()));
- disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
- this, SLOT(updateScrollers()));
+ disconnect(view->verticalScrollBar(), &QScrollBar::valueChanged,
+ this, &QComboBoxPrivateContainer::updateScrollers);
+ disconnect(view->verticalScrollBar(), &QScrollBar::rangeChanged,
+ this, &QComboBoxPrivateContainer::updateScrollers);
#endif
- disconnect(view, SIGNAL(destroyed()),
- this, SLOT(viewDestroyed()));
+ disconnect(view, &QAbstractItemView::destroyed,
+ this, &QComboBoxPrivateContainer::viewDestroyed);
if (isAncestorOf(view))
delete view;
@@ -652,13 +632,13 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
view->setLineWidth(0);
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
#if QT_CONFIG(scrollbar)
- connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
- this, SLOT(updateScrollers()));
- connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
- this, SLOT(updateScrollers()));
+ connect(view->verticalScrollBar(), &QScrollBar::valueChanged,
+ this, &QComboBoxPrivateContainer::updateScrollers);
+ connect(view->verticalScrollBar(), &QScrollBar::rangeChanged,
+ this, &QComboBoxPrivateContainer::updateScrollers);
#endif
- connect(view, SIGNAL(destroyed()),
- this, SLOT(viewDestroyed()));
+ connect(view, &QAbstractItemView::destroyed,
+ this, &QComboBoxPrivateContainer::viewDestroyed);
}
/*!
@@ -715,14 +695,20 @@ void QComboBoxPrivateContainer::updateTopBottomMargin()
boxLayout->invalidate();
}
+void QComboBoxPrivateContainer::updateStyleSettings()
+{
+ // add scroller arrows if style needs them
+ QStyleOptionComboBox opt = comboStyleOption();
+ view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
+ combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo));
+ setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
+ updateTopBottomMargin();
+}
+
void QComboBoxPrivateContainer::changeEvent(QEvent *e)
{
- if (e->type() == QEvent::StyleChange) {
- QStyleOptionComboBox opt = comboStyleOption();
- view->setMouseTracking(combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
- combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo));
- setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
- }
+ if (e->type() == QEvent::StyleChange)
+ updateStyleSettings();
QFrame::changeEvent(e);
}
@@ -739,8 +725,9 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
#ifdef QT_KEYPAD_NAVIGATION
case Qt::Key_Select:
#endif
- if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
+ if (view->currentIndex().isValid() && view->currentIndex().flags().testFlag(Qt::ItemIsEnabled)) {
combo->hidePopup();
+ keyEvent->accept();
emit itemSelected(view->currentIndex());
}
return true;
@@ -750,11 +737,13 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
Q_FALLTHROUGH();
case Qt::Key_F4:
combo->hidePopup();
+ keyEvent->accept();
+ emit itemSelected(view->currentIndex());
return true;
default:
#if QT_CONFIG(shortcut)
- if (keyEvent->matches(QKeySequence::Cancel)) {
- combo->hidePopup();
+ if (keyEvent->matches(QKeySequence::Cancel) && isVisible()) {
+ keyEvent->accept();
return true;
}
#endif
@@ -766,10 +755,10 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
if (isVisible()) {
QMouseEvent *m = static_cast<QMouseEvent *>(e);
QWidget *widget = static_cast<QWidget *>(o);
- QPoint vector = widget->mapToGlobal(m->pos()) - initialClickPosition;
+ QPoint vector = widget->mapToGlobal(m->position().toPoint()) - initialClickPosition;
if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive())
blockMouseReleaseTimer.stop();
- QModelIndex indexUnderMouse = view->indexAt(m->pos());
+ QModelIndex indexUnderMouse = view->indexAt(m->position().toPoint());
if (indexUnderMouse.isValid()
&& !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
view->setCurrentIndex(indexUnderMouse);
@@ -783,10 +772,10 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
bool ignoreEvent = maybeIgnoreMouseButtonRelease && popupTimer.elapsed() < QApplication::doubleClickInterval();
QMouseEvent *m = static_cast<QMouseEvent *>(e);
- if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid()
+ if (isVisible() && view->rect().contains(m->position().toPoint()) && view->currentIndex().isValid()
&& !blockMouseReleaseTimer.isActive() && !ignoreEvent
- && (view->currentIndex().flags() & Qt::ItemIsEnabled)
- && (view->currentIndex().flags() & Qt::ItemIsSelectable)) {
+ && (view->currentIndex().flags().testFlag(Qt::ItemIsEnabled))
+ && (view->currentIndex().flags().testFlag(Qt::ItemIsSelectable))) {
combo->hidePopup();
emit itemSelected(view->currentIndex());
return true;
@@ -824,7 +813,7 @@ void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
opt.subControls = QStyle::SC_All;
opt.activeSubControls = QStyle::SC_ComboBoxArrow;
QStyle::SubControl sc = combo->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt,
- combo->mapFromGlobal(e->globalPos()),
+ combo->mapFromGlobal(e->globalPosition().toPoint()),
combo);
if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
|| (!combo->isEditable() && sc != QStyle::SC_None))
@@ -835,7 +824,7 @@ void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
void QComboBoxPrivateContainer::mouseReleaseEvent(QMouseEvent *e)
{
Q_UNUSED(e);
- if (!blockMouseReleaseTimer.isActive()){
+ if (!blockMouseReleaseTimer.isActive()) {
combo->hidePopup();
emit resetButton();
}
@@ -876,8 +865,8 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
\value AdjustToContents The combobox will always adjust to the contents
\value AdjustToContentsOnFirstShow The combobox will adjust to its contents the first time it is shown.
- \value AdjustToMinimumContentsLength Use AdjustToContents or AdjustToContentsOnFirstShow instead.
- \value AdjustToMinimumContentsLengthWithIcon The combobox will adjust to \l minimumContentsLength plus space for an icon. For performance reasons use this policy on large models.
+ \value AdjustToMinimumContentsLengthWithIcon The combobox will adjust to \l minimumContentsLength plus space for an icon.
+ For performance reasons use this policy on large models.
*/
/*!
@@ -886,28 +875,19 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
This signal is sent when the user chooses an item in the combobox.
The item's \a index is passed. Note that this signal is sent even
when the choice is not changed. If you need to know when the
- choice actually changes, use signal currentIndexChanged().
-
+ choice actually changes, use signal currentIndexChanged() or
+ currentTextChanged().
*/
/*!
- \fn void QComboBox::activated(const QString &text)
-
- This signal is sent when the user chooses an item in the combobox.
- The item's \a text is passed. Note that this signal is sent even
- when the choice is not changed. If you need to know when the
- choice actually changes, use signal currentIndexChanged().
-
- \obsolete Use QComboBox::textActivated() instead
-*/
-/*!
\fn void QComboBox::textActivated(const QString &text)
\since 5.14
This signal is sent when the user chooses an item in the combobox.
The item's \a text is passed. Note that this signal is sent even
when the choice is not changed. If you need to know when the
- choice actually changes, use signal currentIndexChanged().
+ choice actually changes, use signal currentIndexChanged() or
+ currentTextChanged().
*/
/*!
@@ -918,14 +898,6 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
*/
/*!
- \fn void QComboBox::highlighted(const QString &text)
-
- This signal is sent when an item in the combobox popup list is
- highlighted by the user. The item's \a text is passed.
-
- \obsolete Use textHighlighted() instead
-*/
-/*!
\fn void QComboBox::textHighlighted(const QString &text)
\since 5.14
@@ -944,20 +916,14 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
*/
/*!
- \fn void QComboBox::currentIndexChanged(const QString &text)
- \since 4.1
-
- This signal is sent whenever the currentIndex in the combobox
- changes either through user interaction or programmatically. The
- item's \a text is passed.
-*/
-
-/*!
\fn void QComboBox::currentTextChanged(const QString &text)
\since 5.0
- This signal is sent whenever currentText changes. The new value
- is passed as \a text.
+ This signal is emitted whenever currentText changes.
+ The new value is passed as \a text.
+
+ \note It is not emitted, if currentText remains the same,
+ even if currentIndex changes.
*/
/*!
@@ -981,41 +947,36 @@ QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
d->init();
}
-
/*!
\class QComboBox
- \brief The QComboBox widget is a combined button and popup list.
+ \brief The QComboBox widget combines a button with a dropdown list.
\ingroup basicwidgets
\inmodule QtWidgets
- \image windows-combobox.png
-
- A QComboBox provides a means of presenting a list of options to the user
- in a way that takes up the minimum amount of screen space.
-
- A combobox is a selection widget that displays the current item,
- and can pop up a list of selectable items. A combobox may be editable,
- allowing the user to modify each item in the list.
-
- Comboboxes can contain pixmaps as well as strings; the
- insertItem() and setItemText() functions are suitably overloaded.
- For editable comboboxes, the function clearEditText() is provided,
+ \table
+ \row
+ \li \inlineimage collapsed_combobox.png
+ \caption Collapsed QCombobox
+ \li
+ \inlineimage expanded_combobox.png
+ \caption Expanded QCombobox
+ \endtable
+
+ \section1 Display Features
+ A QComboBox is a compact way to present a list of options to the user.
+
+ A combobox is a selection widget that shows the current item,
+ and pops up a list of selectable items when clicked. Comboboxes can
+ contain pixmaps as well as strings if the insertItem() and setItemText()
+ functions are suitably overloaded.
+
+ \section1 Editing Features
+ A combobox may be editable, allowing the user to modify each item in the
+ list. For editable comboboxes, the function clearEditText() is provided,
to clear the displayed string without changing the combobox's
contents.
- There are two signals emitted if the current item of a combobox
- changes, currentIndexChanged() and activated().
- currentIndexChanged() is always emitted regardless if the change
- was done programmatically or by user interaction, while
- activated() is only emitted when the change is caused by user
- interaction. The highlighted() signal is emitted when the user
- highlights an item in the combobox popup list. All three signals
- exist in two versions, one with a QString argument and one with an
- \c int argument. If the user selects or highlights a pixmap, only
- the \c int signals are emitted. Whenever the text of an editable
- combobox is changed the editTextChanged() signal is emitted.
-
When the user enters a new string in an editable combobox, the
widget may or may not insert it, and it can insert it in several
locations. The default policy is \l InsertAtBottom but you can change
@@ -1038,27 +999,42 @@ QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent)
setCompleter() and whether or not the user can add duplicates
is set with setDuplicatesEnabled().
- QComboBox uses the \l{Model/View Programming}{model/view
- framework} for its popup list and to store its items. By default
- a QStandardItemModel stores the items and a QListView subclass
- displays the popuplist. You can access the model and view directly
- (with model() and view()), but QComboBox also provides functions
- to set and get item data (e.g., setItemData() and itemText()). You
- can also set a new model and view (with setModel() and setView()).
- For the text and icon in the combobox label, the data in the model
- that has the Qt::DisplayRole and Qt::DecorationRole is used. Note
- that you cannot alter the \l{QAbstractItemView::}{SelectionMode}
- of the view(), e.g., by using
+ \section1 Signals
+ There are three signals emitted if the current item of a combobox
+ changes: currentIndexChanged(), currentTextChanged(), and activated().
+ currentIndexChanged() and currentTextChanged() are always emitted
+ regardless if the change
+ was done programmatically or by user interaction, while
+ activated() is only emitted when the change is caused by user
+ interaction. The highlighted() signal is emitted when the user
+ highlights an item in the combobox popup list. All three signals
+ exist in two versions, one with a QString argument and one with an
+ \c int argument. If the user selects or highlights a pixmap, only
+ the \c int signals are emitted. Whenever the text of an editable
+ combobox is changed, the editTextChanged() signal is emitted.
+
+ \section1 Model/View Framework
+
+ QComboBox uses the \l{Model/View Programming}{model/view framework} for its
+ popup list and to store its items. By default a QStandardItemModel stores
+ the items and a QListView subclass displays the popuplist. You can access
+ the model and view directly (with model() and view()), but QComboBox also
+ provides functions to set and get item data, for example, setItemData() and
+ itemText(). You can also set a new model and view (with setModel()
+ and setView()). For the text and icon in the combobox label, the data in
+ the model that has the Qt::DisplayRole and Qt::DecorationRole is used.
+
+ \note You cannot alter the \l{QAbstractItemView::}{SelectionMode}
+ of the view(), for example, by using
\l{QAbstractItemView::}{setSelectionMode()}.
- \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup,
- {fowler}{GUI Design Handbook: Combo Box, Drop-Down List Box}
+ \sa QLineEdit, QSpinBox, QRadioButton, QButtonGroup
*/
void QComboBoxPrivate::init()
{
Q_Q(QComboBox);
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
// On OS X, only line edits and list views always get tab focus. It's only
// when we enable full keyboard access that other controls can get tab focus.
// When it's not editable, a combobox looks like a button, and it behaves as
@@ -1086,27 +1062,30 @@ QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
Q_Q(QComboBox);
container = new QComboBoxPrivateContainer(new QComboBoxListView(q), q);
+ disconnectModel();
container->itemView()->setModel(model);
+ connectModel();
container->itemView()->setTextElideMode(Qt::ElideMiddle);
updateDelegate(true);
updateLayoutDirection();
updateViewContainerPaletteAndOpacity();
- QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
- q, SLOT(_q_itemSelected(QModelIndex)));
- QObject::connect(container->itemView()->selectionModel(),
- SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_emitHighlighted(QModelIndex)));
- QObject::connect(container, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
+ QObjectPrivate::connect(container, &QComboBoxPrivateContainer::itemSelected,
+ this, &QComboBoxPrivate::itemSelected);
+ QObjectPrivate::connect(container->itemView()->selectionModel(),
+ &QItemSelectionModel::currentChanged,
+ this, &QComboBoxPrivate::emitHighlighted);
+ QObjectPrivate::connect(container, &QComboBoxPrivateContainer::resetButton,
+ this, &QComboBoxPrivate::resetButton);
return container;
}
-void QComboBoxPrivate::_q_resetButton()
+void QComboBoxPrivate::resetButton()
{
updateArrow(QStyle::State_None);
}
-void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+void QComboBoxPrivate::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
Q_Q(QComboBox);
if (inserting || topLeft.parent() != root)
@@ -1124,17 +1103,17 @@ void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIn
lineEdit->setText(text);
updateLineEditGeometry();
} else {
- emit q->currentTextChanged(text);
+ updateCurrentText(text);
}
q->update();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(q, text);
QAccessible::updateAccessibility(&event);
#endif
}
}
-void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end)
+void QComboBoxPrivate::rowsInserted(const QModelIndex &parent, int start, int end)
{
Q_Q(QComboBox);
if (inserting || parent != root)
@@ -1149,20 +1128,31 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int
// set current index if combo was previously empty and there is no placeholderText
if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid() &&
placeholderText.isEmpty()) {
+#if QT_CONFIG(accessibility)
+ // This might have been called by the model emitting rowInserted(), at which
+ // point the view won't have updated the accessibility bridge yet about its new
+ // dimensions. Do it now so that the change of the selection matches the row
+ // indexes of the accessibility bridge's representation.
+ if (container && container->itemView()) {
+ QAccessibleTableModelChangeEvent event(container->itemView(),
+ QAccessibleTableModelChangeEvent::ModelReset);
+ QAccessible::updateAccessibility(&event);
+ }
+#endif
q->setCurrentIndex(0);
// need to emit changed if model updated index "silently"
} else if (currentIndex.row() != indexBeforeChange) {
q->update();
- _q_emitCurrentIndexChanged(currentIndex);
+ emitCurrentIndexChanged(currentIndex);
}
}
-void QComboBoxPrivate::_q_updateIndexBeforeChange()
+void QComboBoxPrivate::updateIndexBeforeChange()
{
indexBeforeChange = currentIndex.row();
}
-void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
+void QComboBoxPrivate::rowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/)
{
Q_Q(QComboBox);
if (parent != root)
@@ -1174,6 +1164,12 @@ void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/,
q->updateGeometry();
}
+ // model has removed the last row
+ if (model->rowCount(root) == 0) {
+ setCurrentIndex(QModelIndex());
+ return;
+ }
+
// model has changed the currentIndex
if (currentIndex.row() != indexBeforeChange) {
if (!currentIndex.isValid() && q->count()) {
@@ -1185,7 +1181,7 @@ void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/,
updateLineEditGeometry();
}
q->update();
- _q_emitCurrentIndexChanged(currentIndex);
+ emitCurrentIndexChanged(currentIndex);
}
}
@@ -1215,7 +1211,7 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
void QComboBoxPrivate::updateFocusPolicy()
{
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
Q_Q(QComboBox);
// See comment in QComboBoxPrivate::init()
@@ -1252,8 +1248,12 @@ void QComboBox::initStyleOption(QStyleOptionComboBox *option) const
option->activeSubControls = d->hoverControl;
}
option->currentText = currentText();
- if (d->currentIndex.isValid())
+ if (d->currentIndex.isValid()) {
option->currentIcon = d->itemIcon(d->currentIndex);
+ QVariant alignment = d->model->data(d->currentIndex, Qt::TextAlignmentRole);
+ if (alignment.isValid())
+ option->textAlignment = static_cast<Qt::Alignment>(alignment.toUInt());
+ }
option->iconSize = iconSize();
if (d->container && d->container->isVisible())
option->state |= QStyle::State_On;
@@ -1290,7 +1290,7 @@ Qt::MatchFlags QComboBoxPrivate::matchFlags() const
}
-void QComboBoxPrivate::_q_editingFinished()
+void QComboBoxPrivate::editingFinished()
{
Q_Q(QComboBox);
if (!lineEdit)
@@ -1322,13 +1322,13 @@ void QComboBoxPrivate::_q_editingFinished()
}
-void QComboBoxPrivate::_q_returnPressed()
+void QComboBoxPrivate::returnPressed()
{
Q_Q(QComboBox);
// The insertion code below does not apply when the policy is QComboBox::NoInsert.
// In case a completer is installed, item activation via the completer is handled
- // in _q_completerActivated(). Otherwise _q_editingFinished() updates the current
+ // in completerActivated(). Otherwise editingFinished() updates the current
// index as appropriate.
if (insertPolicy == QComboBox::NoInsert)
return;
@@ -1370,7 +1370,7 @@ void QComboBoxPrivate::_q_returnPressed()
break;
case QComboBox::InsertAlphabetically:
index = 0;
- for (int i=0; i< q->count(); i++, index++ ) {
+ for (int i = 0; i < q->count(); ++i, ++index) {
if (text.toLower() < q->itemText(i).toLower())
break;
}
@@ -1386,7 +1386,7 @@ void QComboBoxPrivate::_q_returnPressed()
}
}
-void QComboBoxPrivate::_q_itemSelected(const QModelIndex &item)
+void QComboBoxPrivate::itemSelected(const QModelIndex &item)
{
Q_Q(QComboBox);
if (item != currentIndex) {
@@ -1406,15 +1406,9 @@ void QComboBoxPrivate::emitActivated(const QModelIndex &index)
QString text(itemText(index));
emit q->activated(index.row());
emit q->textActivated(text);
-#if QT_DEPRECATED_SINCE(5, 15)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- emit q->activated(text);
-QT_WARNING_POP
-#endif
}
-void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
+void QComboBoxPrivate::emitHighlighted(const QModelIndex &index)
{
Q_Q(QComboBox);
if (!index.isValid())
@@ -1422,29 +1416,17 @@ void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
QString text(itemText(index));
emit q->highlighted(index.row());
emit q->textHighlighted(text);
-#if QT_DEPRECATED_SINCE(5, 15)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- emit q->highlighted(text);
-QT_WARNING_POP
-#endif
}
-void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
+void QComboBoxPrivate::emitCurrentIndexChanged(const QModelIndex &index)
{
Q_Q(QComboBox);
const QString text = itemText(index);
emit q->currentIndexChanged(index.row());
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_WARNING_PUSH
- QT_WARNING_DISABLE_DEPRECATED
- emit q->currentIndexChanged(text);
- QT_WARNING_POP
-#endif
// signal lineEdit.textChanged already connected to signal currentTextChanged, so don't emit double here
if (!lineEdit)
- emit q->currentTextChanged(text);
-#ifndef QT_NO_ACCESSIBILITY
+ updateCurrentText(text);
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(q, text);
QAccessible::updateAccessibility(&event);
#endif
@@ -1469,11 +1451,13 @@ QComboBox::~QComboBox()
Q_D(QComboBox);
QT_TRY {
- disconnect(d->model, SIGNAL(destroyed()),
- this, SLOT(_q_modelDestroyed()));
+ d->disconnectModel();
} QT_CATCH(...) {
; // objects can't throw in destructor
}
+
+ // Dispose of container before QComboBox goes away
+ delete d->container;
}
/*!
@@ -1504,7 +1488,7 @@ void QComboBox::setMaxVisibleItems(int maxItems)
/*!
\property QComboBox::count
- \brief the number of items in the combobox
+ \brief the number of items in the combobox.
By default, for an empty combo box, this property has a value of 0.
*/
@@ -1516,7 +1500,7 @@ int QComboBox::count() const
/*!
\property QComboBox::maxCount
- \brief the maximum number of items allowed in the combobox
+ \brief the maximum number of items allowed in the combobox.
\note If you set the maximum number to be less then the current
amount of items in the combobox, the extra items will be
@@ -1547,108 +1531,9 @@ int QComboBox::maxCount() const
return d->maxCount;
}
-#if QT_CONFIG(completer)
-#if QT_DEPRECATED_SINCE(5, 13)
-
-/*!
- \property QComboBox::autoCompletion
- \brief whether the combobox provides auto-completion for editable items
- \since 4.1
- \obsolete
-
- Use setCompleter() instead.
-
- By default, this property is \c true.
-
- \sa editable
-*/
-
-/*!
- \obsolete
-
- Use completer() instead.
-*/
-bool QComboBox::autoCompletion() const
-{
- Q_D(const QComboBox);
- return d->autoCompletion;
-}
-
-/*!
- \obsolete
-
- Use setCompleter() instead.
-*/
-void QComboBox::setAutoCompletion(bool enable)
-{
- Q_D(QComboBox);
-
-#ifdef QT_KEYPAD_NAVIGATION
- if (Q_UNLIKELY(QApplicationPrivate::keypadNavigationEnabled() && !enable && isEditable()))
- qWarning("QComboBox::setAutoCompletion: auto completion is mandatory when combo box editable");
-#endif
-
- d->autoCompletion = enable;
- if (!d->lineEdit)
- return;
- if (enable) {
- if (d->lineEdit->completer())
- return;
- d->completer = new QCompleter(d->model, d->lineEdit);
- connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex)));
- d->completer->setCaseSensitivity(d->autoCompletionCaseSensitivity);
- d->completer->setCompletionMode(QCompleter::InlineCompletion);
- d->completer->setCompletionColumn(d->modelColumn);
- d->lineEdit->setCompleter(d->completer);
- d->completer->setWidget(this);
- } else {
- d->lineEdit->setCompleter(nullptr);
- }
-}
-
-/*!
- \property QComboBox::autoCompletionCaseSensitivity
- \brief whether string comparisons are case-sensitive or case-insensitive for auto-completion
- \obsolete
-
- By default, this property is Qt::CaseInsensitive.
-
- Use setCompleter() instead. Case sensitivity of the auto completion can be
- changed using QCompleter::setCaseSensitivity().
-
- \sa autoCompletion
-*/
-
-/*!
- \obsolete
-
- Use setCompleter() and QCompleter::setCaseSensitivity() instead.
-*/
-Qt::CaseSensitivity QComboBox::autoCompletionCaseSensitivity() const
-{
- Q_D(const QComboBox);
- return d->autoCompletionCaseSensitivity;
-}
-
-/*!
- \obsolete
-
- Use setCompleter() and QCompleter::setCaseSensitivity() instead.
-*/
-void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity)
-{
- Q_D(QComboBox);
- d->autoCompletionCaseSensitivity = sensitivity;
- if (d->lineEdit && d->lineEdit->completer())
- d->lineEdit->completer()->setCaseSensitivity(sensitivity);
-}
-#endif // QT_DEPRECATED_SINCE(5, 13)
-
-#endif // QT_CONFIG(completer)
-
/*!
\property QComboBox::duplicatesEnabled
- \brief whether the user can enter duplicate items into the combobox
+ \brief whether the user can enter duplicate items into the combobox.
Note that it is always possible to programmatically insert duplicate items into the
combobox.
@@ -1694,7 +1579,7 @@ int QComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) co
/*!
\property QComboBox::insertPolicy
\brief the policy used to determine where user-inserted items should
- appear in the combobox
+ appear in the combobox.
The default value is \l InsertAtBottom, indicating that new items will appear
at the bottom of the list of items.
@@ -1717,7 +1602,7 @@ void QComboBox::setInsertPolicy(InsertPolicy policy)
/*!
\property QComboBox::sizeAdjustPolicy
\brief the policy describing how the size of the combobox changes
- when the content changes
+ when the content changes.
The default value is \l AdjustToContentsOnFirstShow.
@@ -1768,8 +1653,7 @@ void QComboBox::setMinimumContentsLength(int characters)
d->minimumContentsLength = characters;
if (d->sizeAdjustPolicy == AdjustToContents
- || d->sizeAdjustPolicy == AdjustToMinimumContentsLength
- || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
+ || d->sizeAdjustPolicy == AdjustToMinimumContentsLengthWithIcon) {
d->sizeHint = QSize();
d->adjustComboBoxSize();
updateGeometry();
@@ -1809,7 +1693,7 @@ void QComboBox::setIconSize(const QSize &size)
/*!
\property QComboBox::placeholderText
- \brief Sets a \a placeholderText text shown when no valid index is set
+ \brief Sets a \a placeholderText text shown when no valid index is set.
The \a placeholderText will be shown when an invalid index is set. The
text is not accessible in the dropdown list. When this function is called
@@ -1831,7 +1715,7 @@ void QComboBox::setPlaceholderText(const QString &placeholderText)
d->placeholderText = placeholderText;
if (currentIndex() == -1) {
- if (d->placeholderText.isEmpty() && currentIndex() == -1)
+ if (d->placeholderText.isEmpty())
setCurrentIndex(0);
else
update();
@@ -1848,7 +1732,7 @@ QString QComboBox::placeholderText() const
/*!
\property QComboBox::editable
- \brief whether the combo box can be edited by the user
+ \brief whether the combo box can be edited by the user.
By default, this property is \c false. The effect of editing depends
on the insert policy.
@@ -1887,8 +1771,10 @@ void QComboBoxPrivate::updateDelegate(bool force)
QIcon QComboBoxPrivate::itemIcon(const QModelIndex &index) const
{
+ if (!index.isValid())
+ return {};
QVariant decoration = model->data(index, Qt::DecorationRole);
- if (decoration.type() == QVariant::Pixmap)
+ if (decoration.userType() == QMetaType::QPixmap)
return QIcon(qvariant_cast<QPixmap>(decoration));
else
return qvariant_cast<QIcon>(decoration);
@@ -1908,6 +1794,7 @@ void QComboBox::setEditable(bool editable)
view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
}
QLineEdit *le = new QLineEdit(this);
+ le->setPalette(palette());
setLineEdit(le);
} else {
if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
@@ -1932,6 +1819,9 @@ void QComboBox::setEditable(bool editable)
Sets the line \a edit to use instead of the current line edit widget.
The combo box takes ownership of the line edit.
+
+ \note Since the combobox's line edit owns the QCompleter, any previous
+ call to setCompleter() will no longer have any effect.
*/
void QComboBox::setLineEdit(QLineEdit *edit)
{
@@ -1953,38 +1843,42 @@ void QComboBox::setLineEdit(QLineEdit *edit)
#endif
if (d->lineEdit->parent() != this)
d->lineEdit->setParent(this);
- connect(d->lineEdit, SIGNAL(returnPressed()), this, SLOT(_q_returnPressed()));
- connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
- connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
- connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString)));
- connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus()));
- connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus()));
- connect(d->lineEdit->d_func()->control, SIGNAL(updateMicroFocus()), this, SLOT(updateMicroFocus()));
+ QObjectPrivate::connect(d->lineEdit, &QLineEdit::returnPressed,
+ d, &QComboBoxPrivate::returnPressed);
+ QObjectPrivate::connect(d->lineEdit, &QLineEdit::editingFinished,
+ d, &QComboBoxPrivate::editingFinished);
+ connect(d->lineEdit, &QLineEdit::textChanged, this, &QComboBox::editTextChanged);
+ connect(d->lineEdit, &QLineEdit::textChanged, this, &QComboBox::currentTextChanged);
+ QObjectPrivate::connect(d->lineEdit, &QLineEdit::cursorPositionChanged,
+ d, &QComboBoxPrivate::updateMicroFocus);
+ QObjectPrivate::connect(d->lineEdit, &QLineEdit::selectionChanged,
+ d, &QComboBoxPrivate::updateMicroFocus);
+ QObjectPrivate::connect(d->lineEdit->d_func()->control, &QWidgetLineControl::updateMicroFocus,
+ d, &QComboBoxPrivate::updateMicroFocus);
d->lineEdit->setFrame(false);
d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
d->updateFocusPolicy();
d->lineEdit->setFocusProxy(this);
d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
-#if QT_DEPRECATED_SINCE(5, 13)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
+
#if QT_CONFIG(completer)
- setAutoCompletion(d->autoCompletion);
+ // create a default completer
+ if (!d->lineEdit->completer()) {
+ QCompleter *completer = new QCompleter(d->model, d->lineEdit);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ completer->setCompletionMode(QCompleter::InlineCompletion);
+ completer->setCompletionColumn(d->modelColumn);
#ifdef QT_KEYPAD_NAVIGATION
- if (QApplicationPrivate::keypadNavigationEnabled()) {
// Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion.
// This means that when the user enters edit mode they are immediately presented with a
// list of possible completions.
- setAutoCompletion(true);
- if (d->completer) {
- d->completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
- connect(d->completer, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated()));
- }
- }
-#endif
+ if (QApplicationPrivate::keypadNavigationEnabled())
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
#endif
-QT_WARNING_POP
+ // sets up connections
+ setCompleter(completer);
+ }
#endif
setAttribute(Qt::WA_InputMethodEnabled);
@@ -2044,12 +1938,13 @@ const QValidator *QComboBox::validator() const
\since 4.2
Sets the \a completer to use instead of the current completer.
- If \a completer is 0, auto completion is disabled.
+ If \a completer is \nullptr, auto completion is disabled.
By default, for an editable combo box, a QCompleter that
performs case insensitive inline completion is automatically created.
- \note The completer is removed when the \l editable property becomes \c false.
+ \note The completer is removed when the \l editable property becomes \c false,
+ or when the line edit is replaced by a call to setLineEdit().
Setting a completer on a QComboBox that is not editable will be ignored.
*/
void QComboBox::setCompleter(QCompleter *c)
@@ -2061,7 +1956,8 @@ void QComboBox::setCompleter(QCompleter *c)
}
d->lineEdit->setCompleter(c);
if (c) {
- connect(c, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex)));
+ QObjectPrivate::connect(c, QOverload<const QModelIndex &>::of(&QCompleter::activated),
+ d, &QComboBoxPrivate::completerActivated);
c->setWidget(this);
}
}
@@ -2096,6 +1992,9 @@ QAbstractItemDelegate *QComboBox::itemDelegate() const
Sets the item \a delegate for the popup list view.
The combobox takes ownership of the delegate.
+ Any existing delegate will be removed, but not deleted. QComboBox
+ does not take ownership of \a delegate.
+
\warning You should not share the same instance of a delegate between comboboxes,
widget mappers or views. Doing so can cause incorrect or unintuitive editing behavior
since each view connected to a given delegate may receive the
@@ -2110,7 +2009,6 @@ void QComboBox::setItemDelegate(QAbstractItemDelegate *delegate)
qWarning("QComboBox::setItemDelegate: cannot set a 0 delegate");
return;
}
- delete view()->itemDelegate();
view()->setItemDelegate(delegate);
}
@@ -2132,7 +2030,10 @@ QAbstractItemModel *QComboBox::model() const
Sets the model to be \a model. \a model must not be \nullptr.
If you want to clear the contents of a model, call clear().
- \sa clear()
+ \note If the combobox is editable, then the \a model will also be
+ set on the completer of the line edit.
+
+ \sa clear() setCompleter()
*/
void QComboBox::setModel(QAbstractItemModel *model)
{
@@ -2147,74 +2048,61 @@ void QComboBox::setModel(QAbstractItemModel *model)
return;
#if QT_CONFIG(completer)
- if (d->lineEdit && d->lineEdit->completer()
- && d->lineEdit->completer() == d->completer)
+ if (d->lineEdit && d->lineEdit->completer())
d->lineEdit->completer()->setModel(model);
#endif
- if (d->model) {
- disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateIndexBeforeChange()));
- disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateIndexBeforeChange()));
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(destroyed()),
- this, SLOT(_q_modelDestroyed()));
- disconnect(d->model, SIGNAL(modelAboutToBeReset()),
- this, SLOT(_q_updateIndexBeforeChange()));
- disconnect(d->model, SIGNAL(modelReset()),
- this, SLOT(_q_modelReset()));
- if (d->model->QObject::parent() == this)
- delete d->model;
+ d->disconnectModel();
+ if (d->model && d->model->QObject::parent() == this) {
+ delete d->model;
+ d->model = nullptr;
}
d->model = model;
- connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateIndexBeforeChange()));
- connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateIndexBeforeChange()));
- connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(destroyed()),
- this, SLOT(_q_modelDestroyed()));
- connect(model, SIGNAL(modelAboutToBeReset()),
- this, SLOT(_q_updateIndexBeforeChange()));
- connect(model, SIGNAL(modelReset()),
- this, SLOT(_q_modelReset()));
-
if (d->container) {
d->container->itemView()->setModel(model);
- connect(d->container->itemView()->selectionModel(),
- SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_emitHighlighted(QModelIndex)), Qt::UniqueConnection);
+ QObjectPrivate::connect(d->container->itemView()->selectionModel(),
+ &QItemSelectionModel::currentChanged,
+ d, &QComboBoxPrivate::emitHighlighted, Qt::UniqueConnection);
}
+ d->connectModel();
+
setRootModelIndex(QModelIndex());
- bool currentReset = false;
+ d->trySetValidIndex();
+ d->modelChanged();
+}
- const int rowCount = count();
- for (int pos=0; pos < rowCount; pos++) {
- if (d->model->index(pos, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled) {
- setCurrentIndex(pos);
- currentReset = true;
- break;
- }
- }
+void QComboBoxPrivate::connectModel()
+{
+ if (!model)
+ return;
- if (!currentReset)
- setCurrentIndex(-1);
+ modelConnections = {
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ this, &QComboBoxPrivate::dataChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeInserted,
+ this, &QComboBoxPrivate::updateIndexBeforeChange),
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsInserted,
+ this, &QComboBoxPrivate::rowsInserted),
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, &QComboBoxPrivate::updateIndexBeforeChange),
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsRemoved,
+ this, &QComboBoxPrivate::rowsRemoved),
+ QObjectPrivate::connect(model, &QObject::destroyed,
+ this, &QComboBoxPrivate::modelDestroyed),
+ QObjectPrivate::connect(model, &QAbstractItemModel::modelAboutToBeReset,
+ this, &QComboBoxPrivate::updateIndexBeforeChange),
+ QObjectPrivate::connect(model, &QAbstractItemModel::modelReset,
+ this, &QComboBoxPrivate::modelReset)
+ };
+}
- d->modelChanged();
+void QComboBoxPrivate::disconnectModel()
+{
+ for (auto &connection : modelConnections)
+ QObject::disconnect(connection);
}
/*!
@@ -2262,7 +2150,7 @@ int QComboBox::currentIndex() const
void QComboBox::setCurrentIndex(int index)
{
Q_D(QComboBox);
- QModelIndex mi = d->model->index(index, d->modelColumn, d->root);
+ QModelIndex mi = index >= 0 ? d->model->index(index, d->modelColumn, d->root) : QModelIndex();
d->setCurrentIndex(mi);
}
@@ -2299,9 +2187,24 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
}
updateLineEditGeometry();
}
- if (indexChanged) {
+ // If the model was reset to an empty one, currentIndex will be invalidated
+ // (because it's a QPersistentModelIndex), but the index change will never
+ // be advertised. So an explicit check for this condition is needed.
+ // The variable used for that check has to be reset when a previously valid
+ // index becomes invalid.
+ const bool modelResetToEmpty = !normalized.isValid() && indexBeforeChange != -1;
+ if (modelResetToEmpty)
+ indexBeforeChange = -1;
+
+ if (indexChanged || modelResetToEmpty) {
+ QItemSelectionModel::SelectionFlags selectionMode = QItemSelectionModel::ClearAndSelect;
+ if (q->view()->selectionBehavior() == QAbstractItemView::SelectRows)
+ selectionMode.setFlag(QItemSelectionModel::Rows);
+ if (auto *model = q->view()->selectionModel())
+ model->setCurrentIndex(currentIndex, selectionMode);
+
q->update();
- _q_emitCurrentIndexChanged(currentIndex);
+ emitCurrentIndexChanged(currentIndex);
}
}
@@ -2324,10 +2227,9 @@ QString QComboBox::currentText() const
Q_D(const QComboBox);
if (d->lineEdit)
return d->lineEdit->text();
- else if (d->currentIndex.isValid())
+ if (d->currentIndex.isValid())
return d->itemText(d->currentIndex);
- else
- return d->placeholderText;
+ return {};
}
/*!
@@ -2366,7 +2268,7 @@ QIcon QComboBox::itemIcon(int index) const
/*!
Returns the data for the given \a role in the given \a index in the
- combobox, or QVariant::Invalid if there is no data for this role.
+ combobox, or an invalid QVariant if there is no data for this role.
*/
QVariant QComboBox::itemData(int index, int role) const
{
@@ -2431,7 +2333,7 @@ void QComboBox::insertItem(int index, const QIcon &icon, const QString &text, co
if (!values.isEmpty()) d->model->setItemData(item, values);
}
d->inserting = false;
- d->_q_rowsInserted(d->root, index, index);
+ d->rowsInserted(d->root, index, index);
++itemCount;
} else {
d->inserting = false;
@@ -2458,7 +2360,7 @@ void QComboBox::insertItems(int index, const QStringList &list)
if (list.isEmpty())
return;
index = qBound(0, index, count());
- int insertCount = qMin(d->maxCount - index, list.count());
+ int insertCount = qMin(d->maxCount - index, list.size());
if (insertCount <= 0)
return;
// For the common case where we are using the built in QStandardItemModel
@@ -2479,7 +2381,7 @@ void QComboBox::insertItems(int index, const QStringList &list)
d->model->setData(item, list.at(i), Qt::EditRole);
}
d->inserting = false;
- d->_q_rowsInserted(d->root, index, index + insertCount - 1);
+ d->rowsInserted(d->root, index, index + insertCount - 1);
} else {
d->inserting = false;
}
@@ -2589,8 +2491,11 @@ void QComboBox::setView(QAbstractItemView *itemView)
return;
}
- if (itemView->model() != d->model)
+ if (itemView->model() != d->model) {
+ d->disconnectModel();
itemView->setModel(d->model);
+ d->connectModel();
+ }
d->viewContainer()->setItemView(itemView);
}
@@ -2622,12 +2527,13 @@ void QComboBoxPrivate::cleanupNativePopup()
if (!m_platformMenu)
return;
+ m_platformMenu->setVisible(false);
int count = int(m_platformMenu->tag());
for (int i = 0; i < count; ++i)
m_platformMenu->menuItemAt(i)->deleteLater();
delete m_platformMenu;
- m_platformMenu = 0;
+ m_platformMenu = nullptr;
}
/*!
@@ -2650,7 +2556,7 @@ bool QComboBoxPrivate::showNativePopup()
int itemsCount = q->count();
m_platformMenu->setTag(quintptr(itemsCount));
- QPlatformMenuItem *currentItem = 0;
+ QPlatformMenuItem *currentItem = nullptr;
int currentIndex = q->currentIndex();
for (int i = 0; i < itemsCount; ++i) {
@@ -2659,15 +2565,17 @@ bool QComboBoxPrivate::showNativePopup()
QVariant textVariant = model->data(rowIndex, Qt::EditRole);
item->setText(textVariant.toString());
QVariant iconVariant = model->data(rowIndex, Qt::DecorationRole);
+ const Qt::ItemFlags itemFlags = model->flags(rowIndex);
if (iconVariant.canConvert<QIcon>())
item->setIcon(iconVariant.value<QIcon>());
item->setCheckable(true);
item->setChecked(i == currentIndex);
+ item->setEnabled(itemFlags & Qt::ItemIsEnabled);
if (!currentItem || i == currentIndex)
currentItem = item;
IndexSetter setter = { i, q };
- QObject::connect(item, &QPlatformMenuItem::activated, setter);
+ QObject::connect(item, &QPlatformMenuItem::activated, q, setter);
m_platformMenu->insertMenuItem(item, 0);
m_platformMenu->syncMenuItem(item);
@@ -2682,15 +2590,18 @@ bool QComboBoxPrivate::showNativePopup()
else if (q->testAttribute(Qt::WA_MacMiniSize))
offset = QPoint(-2, 6);
+ [[maybe_unused]] QPointer<QComboBox> guard(q);
const QRect targetRect = QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize());
m_platformMenu->showPopup(tlw, QHighDpi::toNativePixels(targetRect, tlw), currentItem);
-#ifdef Q_OS_OSX
- // The Cocoa popup will swallow any mouse release event.
- // We need to fake one here to un-press the button.
- QMouseEvent mouseReleased(QEvent::MouseButtonRelease, q->pos(), Qt::LeftButton,
- Qt::MouseButtons(Qt::LeftButton), Qt::KeyboardModifiers());
- QCoreApplication::sendEvent(q, &mouseReleased);
+#ifdef Q_OS_MACOS
+ if (guard) {
+ // The Cocoa popup will swallow any mouse release event.
+ // We need to fake one here to un-press the button.
+ QMouseEvent mouseReleased(QEvent::MouseButtonRelease, q->pos(), q->mapToGlobal(QPoint(0, 0)),
+ Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton), {});
+ QCoreApplication::sendEvent(q, &mouseReleased);
+ }
#endif
return true;
@@ -2728,30 +2639,17 @@ void QComboBox::showPopup()
return;
#endif // Q_OS_MAC
-#ifdef QT_KEYPAD_NAVIGATION
-#if QT_CONFIG(completer)
- if (QApplicationPrivate::keypadNavigationEnabled() && d->completer) {
- // editable combo box is line edit plus completer
- setEditFocus(true);
- d->completer->complete(); // show popup
- return;
- }
-#endif
-#endif
-
- // set current item and select it
- view()->selectionModel()->setCurrentIndex(d->currentIndex,
- QItemSelectionModel::ClearAndSelect);
QComboBoxPrivateContainer* container = d->viewContainer();
QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt,
QStyle::SC_ComboBoxListBoxPopup, this));
- QRect screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(this));
+ QRect screen = d->popupGeometry(mapToGlobal(listRect.topLeft()));
QPoint below = mapToGlobal(listRect.bottomLeft());
int belowHeight = screen.bottom() - below.y();
QPoint above = mapToGlobal(listRect.topLeft());
int aboveHeight = above.y() - screen.y();
bool boundToScreen = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+ const auto listView = qobject_cast<QListView *>(d->viewContainer()->itemView());
{
int listHeight = 0;
@@ -2766,6 +2664,8 @@ void QComboBox::showPopup()
while (!toCheck.isEmpty()) {
QModelIndex parent = toCheck.pop();
for (int i = 0, end = d->model->rowCount(parent); i < end; ++i) {
+ if (listView && listView->isRowHidden(i))
+ continue;
QModelIndex idx = d->model->index(i, d->modelColumn, parent);
if (!idx.isValid())
continue;
@@ -2838,8 +2738,14 @@ void QComboBox::showPopup()
// Position horizontally.
listRect.moveLeft(above.x());
- // Position vertically so the curently selected item lines up
- // with the combo box.
+ // Position vertically so the currently selected item lines up
+ // with the combo box. In order to do that, make sure that the item
+ // view is scrolled to the top first, otherwise calls to view()->visualRect()
+ // will return the geometry the selected item had the last time the popup
+ // was visible (and perhaps scrolled). And this will not match the geometry
+ // it will actually have when we resize the container to fit all the items
+ // further down in this function.
+ view()->scrollToTop();
const QRect currentItemRect = view()->visualRect(view()->currentIndex());
const int offset = listRect.top() - currentItemRect.top();
listRect.moveTop(above.y() + offset - listRect.top());
@@ -2872,13 +2778,15 @@ void QComboBox::showPopup()
QGuiApplication::inputMethod()->reset();
}
- QScrollBar *sb = view()->horizontalScrollBar();
- Qt::ScrollBarPolicy policy = view()->horizontalScrollBarPolicy();
- bool needHorizontalScrollBar = (policy == Qt::ScrollBarAsNeeded || policy == Qt::ScrollBarAlwaysOn)
- && sb->minimum() < sb->maximum();
- if (needHorizontalScrollBar) {
+ const QScrollBar *sb = view()->horizontalScrollBar();
+ const auto needHorizontalScrollBar = [this, sb]{
+ const Qt::ScrollBarPolicy policy = view()->horizontalScrollBarPolicy();
+ return (policy == Qt::ScrollBarAsNeeded || policy == Qt::ScrollBarAlwaysOn)
+ && sb->minimum() < sb->maximum();
+ };
+ const bool neededHorizontalScrollBar = needHorizontalScrollBar();
+ if (neededHorizontalScrollBar)
listRect.adjust(0, 0, 0, sb->height());
- }
// Hide the scrollers here, so that the listrect gets the full height of the container
// If the scrollers are truly needed, the later call to container->updateScrollers()
@@ -2921,6 +2829,11 @@ void QComboBox::showPopup()
}
}
container->show();
+ if (!neededHorizontalScrollBar && needHorizontalScrollBar()) {
+ listRect.adjust(0, 0, 0, sb->height());
+ container->setGeometry(listRect);
+ }
+
container->updateScrollers();
view()->setFocus();
@@ -2934,10 +2847,6 @@ void QComboBox::showPopup()
#endif
container->update();
-#ifdef QT_KEYPAD_NAVIGATION
- if (QApplicationPrivate::keypadNavigationEnabled())
- view()->setEditFocus(true);
-#endif
if (startTimer) {
container->popupTimer.start();
container->maybeIgnoreMouseButtonRelease = true;
@@ -2957,60 +2866,64 @@ void QComboBox::showPopup()
void QComboBox::hidePopup()
{
Q_D(QComboBox);
- if (d->container && d->container->isVisible()) {
+ if (d->hidingPopup)
+ return;
+ d->hidingPopup = true;
+ // can't use QBoolBlocker on a bitfield
+ auto resetHidingPopup = qScopeGuard([d]{
+ d->hidingPopup = false;
+ });
+
+ if (!d->container || !d->container->isVisible())
+ return;
+
#if QT_CONFIG(effects)
- QSignalBlocker modelBlocker(d->model);
- QSignalBlocker viewBlocker(d->container->itemView());
- QSignalBlocker containerBlocker(d->container);
- // Flash selected/triggered item (if any).
- if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)) {
- QItemSelectionModel *selectionModel = view() ? view()->selectionModel() : nullptr;
- if (selectionModel && selectionModel->hasSelection()) {
- QEventLoop eventLoop;
- const QItemSelection selection = selectionModel->selection();
-
- // Deselect item and wait 60 ms.
+ QItemSelectionModel *selectionModel = d->container->itemView()
+ ? d->container->itemView()->selectionModel() : nullptr;
+ // Flash selected/triggered item (if any) before hiding the popup.
+ if (style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem) &&
+ selectionModel && selectionModel->hasSelection()) {
+ const QItemSelection selection = selectionModel->selection();
+
+ QTimer::singleShot(0, d->container, [d, selection, selectionModel]{
+ QSignalBlocker modelBlocker(d->model);
+ QSignalBlocker viewBlocker(d->container->itemView());
+ QSignalBlocker containerBlocker(d->container);
+
+ // Deselect item and wait 60 ms.
+ selectionModel->select(selection, QItemSelectionModel::Toggle);
+ QTimer::singleShot(60, d->container, [d, selection, selectionModel]{
+ QSignalBlocker modelBlocker(d->model);
+ QSignalBlocker viewBlocker(d->container->itemView());
+ QSignalBlocker containerBlocker(d->container);
selectionModel->select(selection, QItemSelectionModel::Toggle);
- QTimer::singleShot(60, &eventLoop, SLOT(quit()));
- eventLoop.exec();
+ QTimer::singleShot(20, d->container, [d] {
+ d->doHidePopup();
+ });
+ });
+ });
+ } else
+#endif // QT_CONFIG(effects)
+ {
+ d->doHidePopup();
+ }
+}
- // Select item and wait 20 ms.
- selectionModel->select(selection, QItemSelectionModel::Toggle);
- QTimer::singleShot(20, &eventLoop, SLOT(quit()));
- eventLoop.exec();
- }
- }
+void QComboBoxPrivate::doHidePopup()
+{
+ if (container && container->isVisible())
+ container->hide();
- // Fade out.
- bool needFade = style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
- bool didFade = false;
- if (needFade) {
-#if defined(Q_OS_MAC)
- QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface();
- int at = platformNativeInterface->metaObject()->indexOfMethod("fadeWindow()");
- if (at != -1) {
- QMetaMethod windowFade = platformNativeInterface->metaObject()->method(at);
- windowFade.invoke(platformNativeInterface, Q_ARG(QWindow *, d->container->windowHandle()));
- didFade = true;
- }
+ resetButton();
+}
-#endif // Q_OS_MAC
- // Other platform implementations welcome :-)
- }
- containerBlocker.unblock();
- viewBlocker.unblock();
- modelBlocker.unblock();
+void QComboBoxPrivate::updateCurrentText(const QString &text)
+{
+ if (text == currentText)
+ return;
- if (!didFade)
-#endif // QT_CONFIG(effects)
- // Fade should implicitly hide as well ;-)
- d->container->hide();
- }
-#ifdef QT_KEYPAD_NAVIGATION
- if (QApplicationPrivate::keypadNavigationEnabled() && isEditable() && hasFocus())
- setEditFocus(true);
-#endif
- d->_q_resetButton();
+ currentText = text;
+ emit q_func()->currentTextChanged(text);
}
/*!
@@ -3023,7 +2936,7 @@ void QComboBox::clear()
{
Q_D(QComboBox);
d->model->removeRows(0, d->model->rowCount(d->root), d->root);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(this, QString());
QAccessible::updateAccessibility(&event);
#endif
@@ -3037,7 +2950,7 @@ void QComboBox::clearEditText()
Q_D(QComboBox);
if (d->lineEdit)
d->lineEdit->clear();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(this, QString());
QAccessible::updateAccessibility(&event);
#endif
@@ -3051,7 +2964,7 @@ void QComboBox::setEditText(const QString &text)
Q_D(QComboBox);
if (d->lineEdit)
d->lineEdit->setText(text);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleValueChangeEvent event(this, text);
QAccessible::updateAccessibility(&event);
#endif
@@ -3090,7 +3003,10 @@ void QComboBox::changeEvent(QEvent *e)
Q_D(QComboBox);
switch (e->type()) {
case QEvent::StyleChange:
+ if (d->container)
+ d->container->updateStyleSettings();
d->updateDelegate();
+
#ifdef Q_OS_MAC
case QEvent::MacSizeChange:
#endif
@@ -3101,7 +3017,7 @@ void QComboBox::changeEvent(QEvent *e)
d->updateLineEditGeometry();
d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
- if (e->type() == QEvent::MacSizeChange){
+ if (e->type() == QEvent::MacSizeChange) {
QPlatformTheme::Font f = QPlatformTheme::SystemFont;
if (testAttribute(Qt::WA_MacSmallSize))
f = QPlatformTheme::SmallFont;
@@ -3123,12 +3039,14 @@ void QComboBox::changeEvent(QEvent *e)
d->updateViewContainerPaletteAndOpacity();
break;
}
- case QEvent::FontChange:
+ case QEvent::FontChange: {
d->sizeHint = QSize(); // invalidate size hint
d->viewContainer()->setFont(font());
+ d->viewContainer()->itemView()->doItemsLayout();
if (d->lineEdit)
d->updateLineEditGeometry();
break;
+ }
default:
break;
}
@@ -3157,8 +3075,10 @@ void QComboBox::paintEvent(QPaintEvent *)
initStyleOption(&opt);
painter.drawComplexControl(QStyle::CC_ComboBox, opt);
- if (currentIndex() < 0)
- opt.palette.setBrush(QPalette::ButtonText, opt.palette.brush(QPalette::ButtonText).color().lighter());
+ if (currentIndex() < 0 && !placeholderText().isEmpty()) {
+ opt.palette.setBrush(QPalette::ButtonText, opt.palette.placeholderText());
+ opt.currentText = placeholderText();
+ }
// draw the icon and text
painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
@@ -3202,7 +3122,7 @@ bool QComboBox::event(QEvent *event)
case QEvent::HoverLeave:
case QEvent::HoverMove:
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
- d->updateHoverControl(he->pos());
+ d->updateHoverControl(he->position().toPoint());
break;
case QEvent::ShortcutOverride:
if (d->lineEdit)
@@ -3210,9 +3130,7 @@ bool QComboBox::event(QEvent *event)
break;
#ifdef QT_KEYPAD_NAVIGATION
case QEvent::EnterEditFocus:
- if (!d->lineEdit)
- setEditFocus(false); // We never want edit focus if we are not editable
- else
+ if (d->lineEdit)
d->lineEdit->event(event); //so cursor starts
break;
case QEvent::LeaveEditFocus:
@@ -3241,7 +3159,7 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
Q_Q(QComboBox);
QStyleOptionComboBox opt;
q->initStyleOption(&opt);
- QStyle::SubControl sc = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), q);
+ QStyle::SubControl sc = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->position().toPoint(), q);
if (e->button() == Qt::LeftButton
&& !(sc == QStyle::SC_None && e->type() == QEvent::MouseButtonRelease)
@@ -3252,14 +3170,17 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
#ifdef QT_KEYPAD_NAVIGATION
//if the container already exists, then d->viewContainer() is safe to call
if (container) {
+#else
+ if (true) {
#endif
// We've restricted the next couple of lines, because by not calling
// viewContainer(), we avoid creating the QComboBoxPrivateContainer.
- viewContainer()->initialClickPosition = q->mapToGlobal(e->pos());
-#ifdef QT_KEYPAD_NAVIGATION
+ viewContainer()->initialClickPosition = q->mapToGlobal(e->position().toPoint());
}
-#endif
+ QPointer<QComboBox> guard = q;
q->showPopup();
+ if (!guard)
+ return;
// The code below ensures that regular mousepress and pick item still works
// If it was not called the viewContainer would ignore event since it didn't have
// a mousePressEvent first.
@@ -3311,7 +3232,23 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
Move move = NoMove;
int newIndex = currentIndex();
- switch (e->key()) {
+
+ bool pressLikeButton = !d->lineEdit;
+#ifdef QT_KEYPAD_NAVIGATION
+ pressLikeButton |= QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus();
+#endif
+ auto key = e->key();
+ if (pressLikeButton) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value<QList<Qt::Key>>();
+ if (buttonPressKeys.contains(key)) {
+ showPopup();
+ return;
+ }
+ }
+
+ switch (key) {
case Qt::Key_Up:
if (e->modifiers() & Qt::ControlModifier)
break; // pass to line edit for auto completion
@@ -3353,12 +3290,6 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
return;
}
break;
- case Qt::Key_Space:
- if (!d->lineEdit) {
- showPopup();
- return;
- }
- break;
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Escape:
@@ -3366,13 +3297,6 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
e->ignore();
break;
#ifdef QT_KEYPAD_NAVIGATION
- case Qt::Key_Select:
- if (QApplicationPrivate::keypadNavigationEnabled()
- && (!hasEditFocus() || !d->lineEdit)) {
- showPopup();
- return;
- }
- break;
case Qt::Key_Left:
case Qt::Key_Right:
if (QApplicationPrivate::keypadNavigationEnabled() && !hasEditFocus())
@@ -3383,14 +3307,22 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
if (!hasEditFocus() || !d->lineEdit)
e->ignore();
} else {
- e->ignore(); // let the surounding dialog have it
+ e->ignore(); // let the surrounding dialog have it
}
break;
#endif
default:
+#if QT_CONFIG(shortcut)
+ if (d->container && d->container->isVisible() && e->matches(QKeySequence::Cancel)) {
+ hidePopup();
+ e->accept();
+ }
+#endif
+
if (!d->lineEdit) {
- if (!e->text().isEmpty())
- d->keyboardSearchString(e->text());
+ const auto text = e->text();
+ if (!text.isEmpty() && text.at(0).isPrint())
+ d->keyboardSearchString(text);
else
e->ignore();
}
@@ -3588,7 +3520,7 @@ QVariant QComboBox::inputMethodQuery(Qt::InputMethodQuery query, const QVariant
/*!
\property QComboBox::frame
- \brief whether the combo box draws itself with a frame
+ \brief whether the combo box draws itself with a frame.
If enabled (the default) the combo box draws itself inside a
@@ -3618,6 +3550,9 @@ void QComboBox::setFrame(bool enable)
default value).
By default, this property has a value of 0.
+
+ \note In an editable combobox, the visible column will also become
+ the \l{QCompleter::completionColumn}{completion column}.
*/
int QComboBox::modelColumn() const
{
@@ -3633,8 +3568,7 @@ void QComboBox::setModelColumn(int visibleColumn)
if (lv)
lv->setModelColumn(visibleColumn);
#if QT_CONFIG(completer)
- if (d->lineEdit && d->lineEdit->completer()
- && d->lineEdit->completer() == d->completer)
+ if (d->lineEdit && d->lineEdit->completer())
d->lineEdit->completer()->setCompletionColumn(visibleColumn);
#endif
setCurrentIndex(currentIndex()); //update the text to the text of the new column;
diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h
index 1b80f90c74..1689d0fa1e 100644
--- a/src/widgets/widgets/qcombobox.h
+++ b/src/widgets/widgets/qcombobox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOMBOBOX_H
#define QCOMBOBOX_H
@@ -62,7 +26,8 @@ class Q_WIDGETS_EXPORT QComboBox : public QWidget
Q_PROPERTY(bool editable READ isEditable WRITE setEditable)
Q_PROPERTY(int count READ count)
- Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged USER true)
+ Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged
+ USER true)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(QVariant currentData READ currentData)
Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems)
@@ -72,14 +37,6 @@ class Q_WIDGETS_EXPORT QComboBox : public QWidget
Q_PROPERTY(int minimumContentsLength READ minimumContentsLength WRITE setMinimumContentsLength)
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
-
-#if QT_CONFIG(completer)
-#if QT_DEPRECATED_SINCE(5, 13)
- Q_PROPERTY(bool autoCompletion READ autoCompletion WRITE setAutoCompletion DESIGNABLE false)
- Q_PROPERTY(Qt::CaseSensitivity autoCompletionCaseSensitivity READ autoCompletionCaseSensitivity WRITE setAutoCompletionCaseSensitivity DESIGNABLE false)
-#endif
-#endif // QT_CONFIG(completer)
-
Q_PROPERTY(bool duplicatesEnabled READ duplicatesEnabled WRITE setDuplicatesEnabled)
Q_PROPERTY(bool frame READ hasFrame WRITE setFrame)
Q_PROPERTY(int modelColumn READ modelColumn WRITE setModelColumn)
@@ -95,19 +52,6 @@ public:
void setMaxCount(int max);
int maxCount() const;
-#if QT_CONFIG(completer)
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use completer() instead.")
- bool autoCompletion() const;
- QT_DEPRECATED_X("Use setCompleter() instead.")
- void setAutoCompletion(bool enable);
- QT_DEPRECATED_X("Use completer()->caseSensitivity() instead.")
- Qt::CaseSensitivity autoCompletionCaseSensitivity() const;
- QT_DEPRECATED_X("Use completer()->setCaseSensitivity() instead.")
- void setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity);
-#endif
-#endif
-
bool duplicatesEnabled() const;
void setDuplicatesEnabled(bool enable);
@@ -137,7 +81,6 @@ public:
enum SizeAdjustPolicy {
AdjustToContents,
AdjustToContentsOnFirstShow,
- AdjustToMinimumContentsLength, // ### Qt 6: remove
AdjustToMinimumContentsLengthWithIcon
};
Q_ENUM(SizeAdjustPolicy)
@@ -231,14 +174,7 @@ Q_SIGNALS:
void highlighted(int index);
void textHighlighted(const QString &);
void currentIndexChanged(int index);
- void currentIndexChanged(const QString &);
void currentTextChanged(const QString &);
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X(5, 15, "Use textActivated() instead")
- void activated(const QString &);
- QT_DEPRECATED_VERSION_X(5, 15, "Use textHighlighted() instead")
- void highlighted(const QString &);
-#endif
protected:
void focusInEvent(QFocusEvent *e) override;
@@ -259,7 +195,7 @@ protected:
void contextMenuEvent(QContextMenuEvent *e) override;
#endif // QT_NO_CONTEXTMENU
void inputMethodEvent(QInputMethodEvent *) override;
- void initStyleOption(QStyleOptionComboBox *option) const;
+ virtual void initStyleOption(QStyleOptionComboBox *option) const;
protected:
@@ -268,21 +204,6 @@ protected:
private:
Q_DECLARE_PRIVATE(QComboBox)
Q_DISABLE_COPY(QComboBox)
- Q_PRIVATE_SLOT(d_func(), void _q_itemSelected(const QModelIndex &item))
- Q_PRIVATE_SLOT(d_func(), void _q_emitHighlighted(const QModelIndex &))
- Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentIndexChanged(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_editingFinished())
- Q_PRIVATE_SLOT(d_func(), void _q_returnPressed())
- Q_PRIVATE_SLOT(d_func(), void _q_resetButton())
- Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &, const QModelIndex &))
- Q_PRIVATE_SLOT(d_func(), void _q_updateIndexBeforeChange())
- Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end))
- Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
- Q_PRIVATE_SLOT(d_func(), void _q_modelReset())
-#if QT_CONFIG(completer)
- Q_PRIVATE_SLOT(d_func(), void _q_completerActivated(const QModelIndex &index))
-#endif
};
inline void QComboBox::addItem(const QString &atext, const QVariant &auserData)
diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h
index 7a3fcf6e0f..723d637ae2 100644
--- a/src/widgets/widgets/qcombobox_p.h
+++ b/src/widgets/widgets/qcombobox_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOMBOBOX_P_H
#define QCOMBOBOX_P_H
@@ -56,14 +20,13 @@
#include "QtWidgets/qabstractslider.h"
#include "QtWidgets/qapplication.h"
-#include "QtWidgets/qitemdelegate.h"
+#include "QtWidgets/qstyleditemdelegate.h"
#include "QtGui/qstandarditemmodel.h"
#include "QtWidgets/qlineedit.h"
#include "QtWidgets/qlistview.h"
#include "QtGui/qpainter.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qstyleoption.h"
-#include "QtCore/qpair.h"
#include "QtCore/qtimer.h"
#include "private/qwidget_p.h"
#include "QtCore/qpointer.h"
@@ -85,7 +48,11 @@ class QComboBoxListView : public QListView
{
Q_OBJECT
public:
- QComboBoxListView(QComboBox *cmb = nullptr) : combo(cmb) {}
+ QComboBoxListView(QComboBox *cmb = nullptr) : combo(cmb)
+ {
+ if (cmb)
+ setScreen(cmb->screen());
+ }
protected:
void resizeEvent(QResizeEvent *event) override
@@ -94,13 +61,12 @@ protected:
QListView::resizeEvent(event);
}
- QStyleOptionViewItem viewOptions() const override
+ void initViewItemOption(QStyleOptionViewItem *option) const override
{
- QStyleOptionViewItem option = QListView::viewOptions();
- option.showDecorationSelected = true;
+ QListView::initViewItemOption(option);
+ option->showDecorationSelected = true;
if (combo)
- option.font = combo->font();
- return option;
+ option->font = combo->font();
}
void paintEvent(QPaintEvent *e) override
@@ -118,7 +84,7 @@ protected:
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.menuRect = e->rect();
menuOpt.maxIconWidth = 0;
- menuOpt.tabWidth = 0;
+ menuOpt.reservedShortcutWidth = 0;
QPainter p(viewport());
combo->style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
}
@@ -142,7 +108,7 @@ public:
setAttribute(Qt::WA_NoMousePropagation);
}
QSize sizeHint() const override {
- return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight));
+ return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight, nullptr, this));
}
protected:
@@ -155,7 +121,7 @@ protected:
fast = false;
}
- void enterEvent(QEvent *) override {
+ void enterEvent(QEnterEvent *) override {
startTimer();
}
@@ -178,8 +144,8 @@ protected:
void mouseMoveEvent(QMouseEvent *e) override
{
// Enable fast scrolling if the cursor is directly above or below the popup.
- const int mouseX = e->pos().x();
- const int mouseY = e->pos().y();
+ const int mouseX = e->position().toPoint().x();
+ const int mouseY = e->position().toPoint().y();
const bool horizontallyInside = pos().x() < mouseX && mouseX < rect().right() + 1;
const bool verticallyOutside = (sliderAction == QAbstractSlider::SliderSingleStepAdd) ?
rect().bottom() + 1 < mouseY : mouseY < pos().y();
@@ -190,11 +156,11 @@ protected:
void paintEvent(QPaintEvent *) override {
QPainter p(this);
QStyleOptionMenuItem menuOpt;
- menuOpt.init(this);
+ menuOpt.initFrom(this);
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.menuRect = rect();
menuOpt.maxIconWidth = 0;
- menuOpt.tabWidth = 0;
+ menuOpt.reservedShortcutWidth = 0;
menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
if (sliderAction == QAbstractSlider::SliderSingleStepAdd)
menuOpt.state |= QStyle::State_DownArrow;
@@ -217,12 +183,14 @@ class Q_WIDGETS_EXPORT QComboBoxPrivateContainer : public QFrame
public:
QComboBoxPrivateContainer(QAbstractItemView *itemView, QComboBox *parent);
+ ~QComboBoxPrivateContainer();
QAbstractItemView *itemView() const;
void setItemView(QAbstractItemView *itemView);
int spacing() const;
int topMargin() const;
int bottomMargin() const { return topMargin(); }
void updateTopBottomMargin();
+ void updateStyleSettings();
QTimer blockMouseReleaseTimer;
QBasicTimer adjustSizeTimer;
@@ -294,17 +262,17 @@ private:
int pressedIndex;
};
-// ### Qt6: QStyledItemDelegate ?
-// Note that this class is intentionally not using QStyledItemDelegate
-// Vista does not use the new theme for combo boxes and there might
-// be other side effects from using the new class
-class Q_AUTOTEST_EXPORT QComboBoxDelegate : public QItemDelegate
-{ Q_OBJECT
+class Q_AUTOTEST_EXPORT QComboBoxDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
public:
- QComboBoxDelegate(QObject *parent, QComboBox *cmb) : QItemDelegate(parent), mCombo(cmb) {}
+ QComboBoxDelegate(QObject *parent, QComboBox *cmb)
+ : QStyledItemDelegate(parent), mCombo(cmb)
+ {}
static bool isSeparator(const QModelIndex &index) {
- return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
+ return index.data(Qt::AccessibleDescriptionRole).toString()
+ == QLatin1StringView("separator");
}
static void setSeparator(QAbstractItemModel *model, const QModelIndex &index) {
model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
@@ -325,7 +293,7 @@ protected:
opt.rect = rect;
mCombo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, mCombo);
} else {
- QItemDelegate::paint(painter, option, index);
+ QStyledItemDelegate::paint(painter, option, index);
}
}
@@ -335,7 +303,7 @@ protected:
int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, mCombo);
return QSize(pm, pm);
}
- return QItemDelegate::sizeHint(option, index);
+ return QStyledItemDelegate::sizeHint(option, index);
}
private:
QComboBox *mCombo;
@@ -351,27 +319,29 @@ public:
QComboBoxPrivateContainer* viewContainer();
void updateLineEditGeometry();
Qt::MatchFlags matchFlags() const;
- void _q_editingFinished();
- void _q_returnPressed();
- void _q_complete();
- void _q_itemSelected(const QModelIndex &item);
+ void editingFinished();
+ void returnPressed();
+ void complete();
+ void itemSelected(const QModelIndex &item);
bool contains(const QString &text, int role);
void emitActivated(const QModelIndex &index);
- void _q_emitHighlighted(const QModelIndex &index);
- void _q_emitCurrentIndexChanged(const QModelIndex &index);
- void _q_modelDestroyed();
- void _q_modelReset();
+ void emitHighlighted(const QModelIndex &index);
+ void emitCurrentIndexChanged(const QModelIndex &index);
+ void modelDestroyed();
+ void modelReset();
+ void updateMicroFocus() { q_func()->updateMicroFocus(); } // PMF connect doesn't handle default args
#if QT_CONFIG(completer)
- void _q_completerActivated(const QModelIndex &index);
+ void completerActivated(const QModelIndex &index);
#endif
- void _q_resetButton();
- void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
- void _q_updateIndexBeforeChange();
- void _q_rowsInserted(const QModelIndex &parent, int start, int end);
- void _q_rowsRemoved(const QModelIndex &parent, int start, int end);
+ void resetButton();
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void updateIndexBeforeChange();
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsRemoved(const QModelIndex &parent, int start, int end);
void updateArrow(QStyle::StateFlag state);
bool updateHoverControl(const QPoint &pos);
- QRect popupGeometry(int screen = -1) const;
+ void trySetValidIndex();
+ QRect popupGeometry(const QPoint &globalPos) const;
QStyle::SubControl newHoverControl(const QPoint &pos);
int computeWidthHint() const;
QSize recomputeSizeHint(QSize &sh) const;
@@ -387,6 +357,10 @@ public:
void updateViewContainerPaletteAndOpacity();
void updateFocusPolicy();
void showPopupFromMouseEvent(QMouseEvent *e);
+ void doHidePopup();
+ void updateCurrentText(const QString &text);
+ void connectModel();
+ void disconnectModel();
#ifdef Q_OS_MAC
void cleanupNativePopup();
@@ -403,18 +377,17 @@ public:
};
#endif
+ std::array<QMetaObject::Connection, 8> modelConnections;
QAbstractItemModel *model = nullptr;
QLineEdit *lineEdit = nullptr;
- QComboBoxPrivateContainer *container = nullptr;
+ QPointer<QComboBoxPrivateContainer> container;
#ifdef Q_OS_MAC
QPlatformMenu *m_platformMenu = nullptr;
#endif
-#if QT_CONFIG(completer)
- QPointer<QCompleter> completer;
-#endif
QPersistentModelIndex currentIndex;
QPersistentModelIndex root;
QString placeholderText;
+ QString currentText;
QRect hoverRect;
QSize iconSize;
mutable QSize minimumSizeHint;
@@ -423,18 +396,17 @@ public:
QComboBox::SizeAdjustPolicy sizeAdjustPolicy = QComboBox::AdjustToContentsOnFirstShow;
QStyle::StateFlag arrowState = QStyle::State_None;
QStyle::SubControl hoverControl = QStyle::SC_None;
- Qt::CaseSensitivity autoCompletionCaseSensitivity = Qt::CaseInsensitive;
int minimumContentsLength = 0;
int indexBeforeChange = -1;
int maxVisibleItems = 10;
- int maxCount = std::numeric_limits<int>::max();
+ int maxCount = (std::numeric_limits<int>::max)();
int modelColumn = 0;
int placeholderIndex = -1;
bool shownOnce : 1;
- bool autoCompletion : 1;
bool duplicatesEnabled : 1;
bool frame : 1;
bool inserting : 1;
+ bool hidingPopup : 1;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qcommandlinkbutton.cpp b/src/widgets/widgets/qcommandlinkbutton.cpp
index 2b9258fd91..5c7d2601d9 100644
--- a/src/widgets/widgets/qcommandlinkbutton.cpp
+++ b/src/widgets/widgets/qcommandlinkbutton.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcommandlinkbutton.h"
#include "qstylepainter.h"
@@ -207,8 +171,8 @@ bool QCommandLinkButtonPrivate::usingVistaStyle() const
Q_Q(const QCommandLinkButton);
//### This is a hack to detect if we are indeed running Vista style themed and not in classic
// When we add api to query for this, we should change this implementation to use it.
- return q->style()->inherits("QWindowsVistaStyle")
- && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
+ return q->property("_qt_usingVistaStyle").toBool()
+ && q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, nullptr, q) == 0;
}
void QCommandLinkButtonPrivate::init()
@@ -216,6 +180,7 @@ void QCommandLinkButtonPrivate::init()
Q_Q(QCommandLinkButton);
QPushButtonPrivate::init();
q->setAttribute(Qt::WA_Hover);
+ q->setAttribute(Qt::WA_MacShowFocusRect, false);
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::PushButton);
policy.setHeightForWidth(true);
@@ -224,7 +189,7 @@ void QCommandLinkButtonPrivate::init()
q->setIconSize(QSize(20, 20));
QStyleOptionButton opt;
q->initStyleOption(&opt);
- q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt));
+ q->setIcon(q->style()->standardIcon(QStyle::SP_CommandLink, &opt, q));
}
// Calculates the height of the description text based on widget width
@@ -264,6 +229,12 @@ QSize QCommandLinkButton::minimumSizeHint() const
return size;
}
+void QCommandLinkButton::initStyleOption(QStyleOptionButton *option) const
+{
+ QPushButton::initStyleOption(option);
+ option->features |= QStyleOptionButton::CommandLinkButton;
+}
+
/*!
Constructs a command link with no text and a \a parent.
*/
@@ -349,14 +320,14 @@ void QCommandLinkButton::paintEvent(QPaintEvent *)
QStyleOptionButton option;
initStyleOption(&option);
- //Enable command link appearance on Vista
- option.features |= QStyleOptionButton::CommandLinkButton;
option.text = QString();
option.icon = QIcon(); //we draw this ourselves
QSize pixmapSize = icon().actualSize(iconSize());
- int vOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical) : 0;
- int hOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal) : 0;
+ const int vOffset = isDown()
+ ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, this) : 0;
+ const int hOffset = isDown()
+ ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, this) : 0;
//Draw icon
p.drawControl(QStyle::CE_PushButton, option);
@@ -368,9 +339,9 @@ void QCommandLinkButton::paintEvent(QPaintEvent *)
//Draw title
QColor textColor = palette().buttonText().color();
if (isEnabled() && d->usingVistaStyle()) {
- textColor = QColor(21, 28, 85);
+ textColor = option.palette.buttonText().color();
if (underMouse() && !isDown())
- textColor = QColor(7, 64, 229);
+ textColor = option.palette.brightText().color();
//A simple text color transition
d->currentColor = d->mergedColors(textColor, d->currentColor, 60);
option.palette.setColor(QPalette::ButtonText, d->currentColor);
diff --git a/src/widgets/widgets/qcommandlinkbutton.h b/src/widgets/widgets/qcommandlinkbutton.h
index 3d2dd5784d..7979b992f4 100644
--- a/src/widgets/widgets/qcommandlinkbutton.h
+++ b/src/widgets/widgets/qcommandlinkbutton.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOMMANDLINKBUTTON_H
#define QCOMMANDLINKBUTTON_H
@@ -66,15 +30,11 @@ public:
QString description() const;
void setDescription(const QString &description);
- // QTBUG-68722
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-protected:
-#else
-public:
-#endif
QSize sizeHint() const override;
int heightForWidth(int) const override;
QSize minimumSizeHint() const override;
+ void initStyleOption(QStyleOptionButton *option) const override;
+
protected:
bool event(QEvent *e) override;
void paintEvent(QPaintEvent *) override;
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index e4abb89636..01e52b2fa6 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -1,49 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qapplication_p.h>
#include <private/qdatetimeedit_p.h>
#include <qabstractspinbox.h>
#include <qapplication.h>
#include <qdatetimeedit.h>
-#include <qdesktopwidget.h>
-#include <private/qdesktopwidget_p.h>
#include <qdebug.h>
#include <qevent.h>
#include <qlineedit.h>
@@ -53,9 +15,7 @@
#include <qlayout.h>
#include <qset.h>
#include <qstyle.h>
-#if QT_CONFIG(timezone)
-#include <QTimeZone>
-#endif
+#include <qstylepainter.h>
#include <algorithm>
@@ -70,6 +30,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// --- QDateTimeEdit ---
/*!
@@ -106,6 +68,23 @@ QT_BEGIN_NAMESPACE
calendar pop-up by calling the setCalendarWidget() function. The existing
calendar widget can be retrieved with calendarWidget().
+ \section1 Keyboard Tracking
+
+ When \l{QAbstractSpinBox::keyboardTracking}{keyboard tracking} is enabled
+ (the default), every keystroke of editing a field triggers signals for value
+ changes.
+
+ When the allowed \l{QDateTimeEdit::setDateTimeRange}{range} is narrower than
+ some time interval whose end it straddles, keyboard tracking prevents the
+ user editing the date or time to access the later part of the interval. For
+ example, for a range from 29.04.2020 to 02.05.2020 and an initial date of
+ 30.04.2020, the user can change neither the month (May 30th is outside the
+ range) nor the day (April 2nd is outside the range).
+
+ When keyboard tracking is disabled, changes are only signalled when focus
+ leaves the text field after edits have modified the content. This allows the
+ user to edit via an invalid date-time to reach a valid one.
+
\sa QDateEdit, QTimeEdit, QDate, QTime
*/
@@ -130,20 +109,26 @@ QT_BEGIN_NAMESPACE
This signal is emitted whenever the date or time is changed. The
new date and time is passed in \a datetime.
+
+ \sa {Keyboard Tracking}
*/
/*!
- \fn void QDateTimeEdit::timeChanged(const QTime &time)
+ \fn void QDateTimeEdit::timeChanged(QTime time)
This signal is emitted whenever the time is changed. The new time
is passed in \a time.
+
+ \sa {Keyboard Tracking}
*/
/*!
- \fn void QDateTimeEdit::dateChanged(const QDate &date)
+ \fn void QDateTimeEdit::dateChanged(QDate date)
This signal is emitted whenever the date is changed. The new date
is passed in \a date.
+
+ \sa {Keyboard Tracking}
*/
@@ -171,13 +156,13 @@ QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent)
}
/*!
- \fn QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
+ \fn QDateTimeEdit::QDateTimeEdit(QDate date, QWidget *parent)
Constructs an empty date time editor with a \a parent.
The value is set to \a date.
*/
-QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
+QDateTimeEdit::QDateTimeEdit(QDate date, QWidget *parent)
: QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
{
Q_D(QDateTimeEdit);
@@ -185,13 +170,13 @@ QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
}
/*!
- \fn QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
+ \fn QDateTimeEdit::QDateTimeEdit(QTime time, QWidget *parent)
Constructs an empty date time editor with a \a parent.
The value is set to \a time.
*/
-QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
+QDateTimeEdit::QDateTimeEdit(QTime time, QWidget *parent)
: QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
{
Q_D(QDateTimeEdit);
@@ -201,9 +186,10 @@ QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
/*!
\internal
*/
-
-QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWidget *parent)
- : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
+QDateTimeEdit::QDateTimeEdit(const QVariant &var, QMetaType::Type parserType, QWidget *parent)
+ : QAbstractSpinBox(*new QDateTimeEditPrivate(parserType == QMetaType::QDateTime
+ ? QTimeZone::LocalTime : QTimeZone::UTC),
+ parent)
{
Q_D(QDateTimeEdit);
d->parserType = parserType;
@@ -221,8 +207,8 @@ QDateTimeEdit::~QDateTimeEdit()
\property QDateTimeEdit::dateTime
\brief The QDateTime that is set in the QDateTimeEdit.
- When setting this property, the new QDateTime is converted to the timespec of
- the QDateTimeEdit, which thus remains unchanged.
+ When setting this property, the new QDateTime is converted to the time system
+ of the QDateTimeEdit, which thus remains unchanged.
By default, this property is set to the start of 2000 CE. It can only be set
to a valid QDateTime value. If any operation causes this property to have an
@@ -233,7 +219,7 @@ QDateTimeEdit::~QDateTimeEdit()
widget's date-range to start and end on the date of the new value of this
property.
- \sa date, time, minimumDateTime, maximumDateTime
+ \sa date, time, minimumDateTime, maximumDateTime, timeZone
*/
QDateTime QDateTimeEdit::dateTime() const
@@ -246,8 +232,8 @@ void QDateTimeEdit::setDateTime(const QDateTime &datetime)
{
Q_D(QDateTimeEdit);
if (datetime.isValid()) {
- QDateTime when = d->convertTimeSpec(datetime);
- Q_ASSERT(when.timeSpec() == d->spec);
+ QDateTime when = d->convertTimeZone(datetime);
+ Q_ASSERT(when.timeRepresentation() == d->timeZone);
d->clearCache();
const QDate date = when.date();
@@ -275,7 +261,7 @@ QDate QDateTimeEdit::date() const
return d->value.toDate();
}
-void QDateTimeEdit::setDate(const QDate &date)
+void QDateTimeEdit::setDate(QDate date)
{
Q_D(QDateTimeEdit);
if (date.isValid()) {
@@ -283,14 +269,10 @@ void QDateTimeEdit::setDate(const QDate &date)
setDateRange(date, date);
d->clearCache();
- QDateTime when(date, d->value.toTime(), d->spec);
- // The specified time might not exist on the specified day,
- // i.e. the time is in the gap a spring-forward jumps over.
- if (!when.isValid())
- when = QDateTime::fromMSecsSinceEpoch(when.toMSecsSinceEpoch(), d->spec);
+ QDateTime when = d->dateTimeValue(date, d->value.toTime());
Q_ASSERT(when.isValid());
d->setValue(when, EmitIfChanged);
- d->updateTimeSpec();
+ d->updateTimeZone();
}
}
@@ -312,12 +294,12 @@ QTime QDateTimeEdit::time() const
return d->value.toTime();
}
-void QDateTimeEdit::setTime(const QTime &time)
+void QDateTimeEdit::setTime(QTime time)
{
Q_D(QDateTimeEdit);
if (time.isValid()) {
d->clearCache();
- d->setValue(QDateTime(d->value.toDate(), time, d->spec), EmitIfChanged);
+ d->setValue(d->dateTimeValue(d->value.toDate(), time), EmitIfChanged);
}
}
@@ -348,14 +330,15 @@ void QDateTimeEdit::setCalendar(QCalendar calendar)
minimumTime properties to the date and time parts of this property,
respectively. When setting this property, the \l maximumDateTime is adjusted,
if necessary, to ensure that the range remains valid. Otherwise, changing this
- property preserves the \l minimumDateTime property.
+ property preserves the \l maximumDateTime property.
This property can only be set to a valid QDateTime value. The earliest
date-time that setMinimumDateTime() accepts is the start of 100 CE. The
property's default is the start of September 14, 1752 CE. This default can be
restored with clearMinimumDateTime().
- \sa maximumDateTime, minimumTime, minimumDate, setDateTimeRange(), QDateTime::isValid()
+ \sa maximumDateTime, minimumTime, minimumDate, setDateTimeRange(),
+ QDateTime::isValid(), {Keyboard Tracking}
*/
QDateTime QDateTimeEdit::minimumDateTime() const
@@ -373,7 +356,7 @@ void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
{
Q_D(QDateTimeEdit);
if (dt.isValid() && dt.date() >= QDATETIMEEDIT_DATE_MIN) {
- const QDateTime m = dt.toTimeSpec(d->spec);
+ const QDateTime m = dt.toTimeZone(d->timeZone);
const QDateTime max = d->maximum.toDateTime();
d->setRange(m, (max > m ? max : m));
}
@@ -396,7 +379,8 @@ void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
default for this property. This default can be restored with
clearMaximumDateTime().
- \sa minimumDateTime, maximumTime, maximumDate(), setDateTimeRange(), QDateTime::isValid()
+ \sa minimumDateTime, maximumTime, maximumDate(), setDateTimeRange(),
+ QDateTime::isValid(), {Keyboard Tracking}
*/
QDateTime QDateTimeEdit::maximumDateTime() const
@@ -414,7 +398,7 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
{
Q_D(QDateTimeEdit);
if (dt.isValid() && dt.date() <= QDATETIMEEDIT_DATE_MAX) {
- const QDateTime m = dt.toTimeSpec(d->spec);
+ const QDateTime m = dt.toTimeZone(d->timeZone);
const QDateTime min = d->minimum.toDateTime();
d->setRange((min < m ? min : m), m);
}
@@ -436,15 +420,20 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
If either \a min or \a max is invalid, this function does nothing. If \a max
is less than \a min, \a min is used also as \a max.
- \sa minimumDateTime, maximumDateTime, setDateRange(), setTimeRange(), QDateTime::isValid()
+ If the range is narrower then a time interval whose end it spans, for example
+ a week that spans the end of a month, users can only edit the date-time to one
+ in the later part of the range if keyboard-tracking is disabled.
+
+ \sa minimumDateTime, maximumDateTime, setDateRange(), setTimeRange(),
+ QDateTime::isValid(), {Keyboard Tracking}
*/
void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
{
Q_D(QDateTimeEdit);
// FIXME: does none of the range checks applied to setMin/setMax methods !
- const QDateTime minimum = min.toTimeSpec(d->spec);
- const QDateTime maximum = (min > max ? minimum : max.toTimeSpec(d->spec));
+ const QDateTime minimum = min.toTimeZone(d->timeZone);
+ const QDateTime maximum = (min > max ? minimum : max.toTimeZone(d->timeZone));
d->setRange(minimum, maximum);
}
@@ -466,7 +455,8 @@ void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
default for this property is September 14, 1752 CE. This default can be
restored with clearMinimumDateTime().
- \sa maximumDate, minimumTime, minimumDateTime, setDateRange(), QDate::isValid()
+ \sa maximumDate, minimumTime, minimumDateTime, setDateRange(),
+ QDate::isValid(), {Keyboard Tracking}
*/
QDate QDateTimeEdit::minimumDate() const
@@ -475,12 +465,11 @@ QDate QDateTimeEdit::minimumDate() const
return d->minimum.toDate();
}
-void QDateTimeEdit::setMinimumDate(const QDate &min)
+void QDateTimeEdit::setMinimumDate(QDate min)
{
Q_D(QDateTimeEdit);
- if (min.isValid() && min >= QDATETIMEEDIT_DATE_MIN) {
- setMinimumDateTime(QDateTime(min, d->minimum.toTime(), d->spec));
- }
+ if (min.isValid() && min >= QDATETIMEEDIT_DATE_MIN)
+ setMinimumDateTime(d->dateTimeValue(min, d->minimum.toTime()));
}
void QDateTimeEdit::clearMinimumDate()
@@ -506,7 +495,8 @@ void QDateTimeEdit::clearMinimumDate()
default for this property. This default can be restored with
clearMaximumDateTime().
- \sa minimumDate, maximumTime, maximumDateTime, setDateRange(), QDate::isValid()
+ \sa minimumDate, maximumTime, maximumDateTime, setDateRange(),
+ QDate::isValid(), {Keyboard Tracking}
*/
QDate QDateTimeEdit::maximumDate() const
@@ -515,11 +505,11 @@ QDate QDateTimeEdit::maximumDate() const
return d->maximum.toDate();
}
-void QDateTimeEdit::setMaximumDate(const QDate &max)
+void QDateTimeEdit::setMaximumDate(QDate max)
{
Q_D(QDateTimeEdit);
if (max.isValid())
- setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
+ setMaximumDateTime(d->dateTimeValue(max, d->maximum.toTime()));
}
void QDateTimeEdit::clearMaximumDate()
@@ -543,7 +533,8 @@ void QDateTimeEdit::clearMaximumDate()
contains a time of 00:00:00 and 0 milliseconds. This default can be restored
with clearMinimumTime().
- \sa maximumTime, minimumDate, minimumDateTime, setTimeRange(), QTime::isValid()
+ \sa maximumTime, minimumDate, minimumDateTime, setTimeRange(),
+ QTime::isValid(), {Keyboard Tracking}
*/
QTime QDateTimeEdit::minimumTime() const
@@ -552,13 +543,11 @@ QTime QDateTimeEdit::minimumTime() const
return d->minimum.toTime();
}
-void QDateTimeEdit::setMinimumTime(const QTime &min)
+void QDateTimeEdit::setMinimumTime(QTime min)
{
Q_D(QDateTimeEdit);
- if (min.isValid()) {
- const QDateTime m(d->minimum.toDate(), min, d->spec);
- setMinimumDateTime(m);
- }
+ if (min.isValid())
+ setMinimumDateTime(d->dateTimeValue(d->minimum.toDate(), min));
}
void QDateTimeEdit::clearMinimumTime()
@@ -582,7 +571,8 @@ void QDateTimeEdit::clearMinimumTime()
contains a time of 23:59:59 and 999 milliseconds. This default can be restored
with clearMaximumTime().
- \sa minimumTime, maximumDate, maximumDateTime, setTimeRange(), QTime::isValid()
+ \sa minimumTime, maximumDate, maximumDateTime, setTimeRange(),
+ QTime::isValid(), {Keyboard Tracking}
*/
QTime QDateTimeEdit::maximumTime() const
{
@@ -590,13 +580,11 @@ QTime QDateTimeEdit::maximumTime() const
return d->maximum.toTime();
}
-void QDateTimeEdit::setMaximumTime(const QTime &max)
+void QDateTimeEdit::setMaximumTime(QTime max)
{
Q_D(QDateTimeEdit);
- if (max.isValid()) {
- const QDateTime m(d->maximum.toDate(), max, d->spec);
- setMaximumDateTime(m);
- }
+ if (max.isValid())
+ setMaximumDateTime(d->dateTimeValue(d->maximum.toDate(), max));
}
void QDateTimeEdit::clearMaximumTime()
@@ -623,15 +611,19 @@ void QDateTimeEdit::clearMaximumTime()
minimumTime property, the \l maximumTime property is set to the \l minimumTime
property. Otherwise, this preserves the \l maximumTime property.
- \sa minimumDate, maximumDate, setDateTimeRange(), QDate::isValid()
+ If the range is narrower then a time interval whose end it spans, for example
+ a week that spans the end of a month, users can only edit the date to one in
+ the later part of the range if keyboard-tracking is disabled.
+
+ \sa minimumDate, maximumDate, setDateTimeRange(), QDate::isValid(), {Keyboard Tracking}
*/
-void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
+void QDateTimeEdit::setDateRange(QDate min, QDate max)
{
Q_D(QDateTimeEdit);
if (min.isValid() && max.isValid()) {
- setDateTimeRange(QDateTime(min, d->minimum.toTime(), d->spec),
- QDateTime(max, d->maximum.toTime(), d->spec));
+ setDateTimeRange(d->dateTimeValue(min, d->minimum.toTime()),
+ d->dateTimeValue(max, d->maximum.toTime()));
}
}
@@ -657,15 +649,20 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
function preserves the \l minimumDate and \l maximumDate properties. If those
properties coincide and \a max is less than \a min, \a min is used as \a max.
- \sa minimumTime, maximumTime, setDateTimeRange(), QTime::isValid()
+ If the range is narrower then a time interval whose end it spans, for example
+ the interval from ten to an hour to ten past the same hour, users can only
+ edit the time to one in the later part of the range if keyboard-tracking is
+ disabled.
+
+ \sa minimumTime, maximumTime, setDateTimeRange(), QTime::isValid(), {Keyboard Tracking}
*/
-void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
+void QDateTimeEdit::setTimeRange(QTime min, QTime max)
{
Q_D(QDateTimeEdit);
if (min.isValid() && max.isValid()) {
- setDateTimeRange(QDateTime(d->minimum.toDate(), min, d->spec),
- QDateTime(d->maximum.toDate(), max, d->spec));
+ setDateTimeRange(d->dateTimeValue(d->minimum.toDate(), min),
+ d->dateTimeValue(d->maximum.toDate(), max));
}
}
@@ -675,7 +672,8 @@ void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
\brief The currently displayed fields of the date time edit.
Returns a bit set of the displayed sections for this format.
- \a setDisplayFormat(), displayFormat()
+
+ \sa setDisplayFormat(), displayFormat()
*/
QDateTimeEdit::Sections QDateTimeEdit::displayedSections() const
@@ -688,7 +686,6 @@ QDateTimeEdit::Sections QDateTimeEdit::displayedSections() const
\property QDateTimeEdit::currentSection
\brief The current section of the spinbox.
- \a setCurrentSection()
*/
QDateTimeEdit::Section QDateTimeEdit::currentSection() const
@@ -768,8 +765,7 @@ int QDateTimeEdit::sectionCount() const
the cursorPosition is 5, currentSectionIndex returns 1. If the
cursorPosition is 3, currentSectionIndex is 0, and so on.
- \a setCurrentSection()
- \sa currentSection()
+ \sa setCurrentSection(), currentSection()
*/
int QDateTimeEdit::currentSectionIndex() const
@@ -949,10 +945,10 @@ void QDateTimeEdit::setDisplayFormat(const QString &format)
}
} else if (dateShown && !timeShown) {
setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
- d->value = QDateTime(d->value.toDate(), QTime(), d->spec);
+ d->value = d->value.toDate().startOfDay(d->timeZone);
}
d->updateEdit();
- d->_q_editorCursorPositionChanged(-1, 0);
+ d->editorCursorPositionChanged(-1, 0);
}
}
@@ -988,24 +984,70 @@ void QDateTimeEdit::setCalendarPopup(bool enable)
update();
}
+#if QT_DEPRECATED_SINCE(6, 10)
/*!
\property QDateTimeEdit::timeSpec
- \brief The current timespec used by the date time edit.
\since 4.4
+ \deprecated[6.10] Use QDateTimeEdit::timeZone instead.
+ \brief The current timespec used by the date time edit.
+
+ Since Qt 6.7 this is an indirect accessor for the timeZone property.
+
+ \sa QDateTimeEdit::timeZone
*/
Qt::TimeSpec QDateTimeEdit::timeSpec() const
{
Q_D(const QDateTimeEdit);
- return d->spec;
+ return d->timeZone.timeSpec();
}
void QDateTimeEdit::setTimeSpec(Qt::TimeSpec spec)
{
Q_D(QDateTimeEdit);
- if (spec != d->spec) {
- d->spec = spec;
- d->updateTimeSpec();
+ if (spec != d->timeZone.timeSpec()) {
+ switch (spec) {
+ case Qt::UTC:
+ setTimeZone(QTimeZone::UTC);
+ break;
+ case Qt::LocalTime:
+ setTimeZone(QTimeZone::LocalTime);
+ break;
+ default:
+ qWarning() << "Ignoring attempt to set time-spec" << spec
+ << "which needs ancillary data: see setTimeZone()";
+ return;
+ }
+ }
+}
+#endif // 6.10 deprecation
+
+// TODO: enable user input to control timeZone, when the format includes it.
+/*!
+ \property QDateTimeEdit::timeZone
+ \since 6.7
+ \brief The current timezone used by the datetime editing widget
+
+ If the datetime format in use includes a timezone indicator - that is, a
+ \c{t}, \c{tt}, \c{ttt} or \c{tttt} format specifier - the user's input is
+ re-expressed in this timezone whenever it is parsed, overriding any timezone
+ the user may have specified.
+
+ \sa QDateTimeEdit::displayFormat
+*/
+
+QTimeZone QDateTimeEdit::timeZone() const
+{
+ Q_D(const QDateTimeEdit);
+ return d->timeZone;
+}
+
+void QDateTimeEdit::setTimeZone(const QTimeZone &zone)
+{
+ Q_D(QDateTimeEdit);
+ if (zone != d->timeZone) {
+ d->timeZone = zone;
+ d->updateTimeZone();
}
}
@@ -1023,9 +1065,9 @@ QSize QDateTimeEdit::sizeHint() const
int h = d->edit->sizeHint().height();
int w = 0;
QString s;
- s = d->textFromValue(d->minimum) + QLatin1Char(' ');
+ s = d->textFromValue(d->minimum) + u' ';
w = qMax<int>(w, fm.horizontalAdvance(s));
- s = d->textFromValue(d->maximum) + QLatin1Char(' ');
+ s = d->textFromValue(d->maximum) + u' ';
w = qMax<int>(w, fm.horizontalAdvance(s));
if (d->specialValueText.size()) {
s = d->specialValueText;
@@ -1044,8 +1086,7 @@ QSize QDateTimeEdit::sizeHint() const
{
QStyleOptionSpinBox opt;
initStyleOption(&opt);
- d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
- .expandedTo(QApplication::globalStrut());
+ d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this);
}
d->cachedMinimumSizeHint = d->cachedSizeHint;
@@ -1257,9 +1298,9 @@ void QDateTimeEdit::focusInEvent(QFocusEvent *event)
{
Q_D(QDateTimeEdit);
QAbstractSpinBox::focusInEvent(event);
- QString *frm = nullptr;
const int oldPos = d->edit->cursorPosition();
if (!d->formatExplicitlySet) {
+ QString *frm = nullptr;
if (d->displayFormat == d->defaultTimeFormat) {
frm = &d->defaultTimeFormat;
} else if (d->displayFormat == d->defaultDateFormat) {
@@ -1290,6 +1331,7 @@ void QDateTimeEdit::focusInEvent(QFocusEvent *event)
case Qt::ActiveWindowFocusReason:
if (oldHasHadFocus)
return;
+ break;
case Qt::ShortcutFocusReason:
case Qt::TabFocusReason:
default:
@@ -1382,7 +1424,7 @@ void QDateTimeEdit::stepBy(int steps)
d->updateCache(d->value, d->displayText());
d->setSelected(d->currentSectionIndex);
- d->updateTimeSpec();
+ d->updateTimeZone();
}
/*!
@@ -1440,7 +1482,12 @@ void QDateTimeEdit::fixup(QString &input) const
QValidator::State state;
int copy = d->edit->cursorPosition();
- d->validateAndInterpret(input, copy, state, true);
+ QDateTime value = d->validateAndInterpret(input, copy, state, true);
+ // CorrectToPreviousValue correction is handled by QAbstractSpinBox.
+ // The value might not match the input if the input represents a date-time
+ // skipped over by its time representation, such as a spring-forward.
+ if (d->correctionMode == QAbstractSpinBox::CorrectToNearestValue)
+ input = textFromDateTime(value);
}
@@ -1464,7 +1511,7 @@ QDateTimeEdit::StepEnabled QDateTimeEdit::stepEnabled() const
if (d->wrapping)
return StepEnabled(StepUpEnabled | StepDownEnabled);
// 3 cases. date, time, datetime. each case look
- // at just the relavant component.
+ // at just the relevant component.
QVariant max, min, val;
if (!(d->sections & DateSections_Mask)) {
// time only, no date
@@ -1522,7 +1569,7 @@ void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
QAbstractSpinBox::mousePressEvent(event);
return;
}
- d->updateHoverControl(event->pos());
+ d->updateHoverControl(event->position().toPoint());
if (d->hoverControl == QStyle::SC_ComboBoxArrow) {
event->accept();
if (d->readOnly) {
@@ -1570,7 +1617,7 @@ void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
QTimeEdit::QTimeEdit(QWidget *parent)
- : QDateTimeEdit(QDATETIMEEDIT_TIME_MIN, QVariant::Time, parent)
+ : QDateTimeEdit(QDATETIMEEDIT_TIME_MIN, QMetaType::QTime, parent)
{
connect(this, &QTimeEdit::timeChanged, this, &QTimeEdit::userTimeChanged);
}
@@ -1580,8 +1627,8 @@ QTimeEdit::QTimeEdit(QWidget *parent)
to \a time.
*/
-QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
- : QDateTimeEdit(time, QVariant::Time, parent)
+QTimeEdit::QTimeEdit(QTime time, QWidget *parent)
+ : QDateTimeEdit(time.isValid() ? time : QDATETIMEEDIT_TIME_MIN, QMetaType::QTime, parent)
{
connect(this, &QTimeEdit::timeChanged, this, &QTimeEdit::userTimeChanged);
}
@@ -1600,7 +1647,7 @@ QTimeEdit::~QTimeEdit()
*/
/*!
- \fn void QTimeEdit::userTimeChanged(const QTime &time)
+ \fn void QTimeEdit::userTimeChanged(QTime time)
This signal only exists to fully implement the time Q_PROPERTY on the class.
Normally timeChanged should be used instead.
@@ -1640,7 +1687,7 @@ QTimeEdit::~QTimeEdit()
*/
QDateEdit::QDateEdit(QWidget *parent)
- : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QVariant::Date, parent)
+ : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QMetaType::QDate, parent)
{
connect(this, &QDateEdit::dateChanged, this, &QDateEdit::userDateChanged);
}
@@ -1650,8 +1697,8 @@ QDateEdit::QDateEdit(QWidget *parent)
to \a date.
*/
-QDateEdit::QDateEdit(const QDate &date, QWidget *parent)
- : QDateTimeEdit(date, QVariant::Date, parent)
+QDateEdit::QDateEdit(QDate date, QWidget *parent)
+ : QDateTimeEdit(date.isValid() ? date : QDATETIMEEDIT_DATE_INITIAL, QMetaType::QDate, parent)
{
connect(this, &QDateEdit::dateChanged, this, &QDateEdit::userDateChanged);
}
@@ -1670,7 +1717,7 @@ QDateEdit::~QDateEdit()
*/
/*!
- \fn void QDateEdit::userDateChanged(const QDate &date)
+ \fn void QDateEdit::userDateChanged(QDate date)
This signal only exists to fully implement the date Q_PROPERTY on the class.
Normally dateChanged should be used instead.
@@ -1687,62 +1734,42 @@ QDateEdit::~QDateEdit()
*/
-QDateTimeEditPrivate::QDateTimeEditPrivate()
- : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit, QCalendar())
+QDateTimeEditPrivate::QDateTimeEditPrivate(const QTimeZone &zone)
+ : QDateTimeParser(QMetaType::QDateTime, QDateTimeParser::DateTimeEdit, QCalendar()),
+ timeZone(zone)
{
- hasHadFocus = false;
- formatExplicitlySet = false;
- cacheGuard = false;
fixday = true;
- type = QVariant::DateTime;
- sections = { };
- cachedDay = -1;
+ type = QMetaType::QDateTime;
currentSectionIndex = FirstSectionIndex;
first.pos = 0;
- calendarPopup = false;
- minimum = QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay();
- maximum = QDATETIMEEDIT_DATE_MAX.endOfDay();
- arrowState = QStyle::State_None;
- monthCalendar = nullptr;
+ minimum = QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay(timeZone);
+ maximum = QDATETIMEEDIT_DATE_MAX.endOfDay(timeZone);
readLocaleSettings();
+}
-#ifdef QT_KEYPAD_NAVIGATION
- focusOnButton = false;
-#endif
+QDateTime QDateTimeEditPrivate::convertTimeZone(const QDateTime &datetime)
+{
+ return datetime.toTimeZone(timeZone);
}
-QDateTime QDateTimeEditPrivate::convertTimeSpec(const QDateTime &datetime)
+QDateTime QDateTimeEditPrivate::dateTimeValue(QDate date, QTime time) const
{
- Q_ASSERT(value.toDateTime().timeSpec() == spec);
- switch (spec) {
- case Qt::UTC:
- return datetime.toUTC();
- case Qt::LocalTime:
- return datetime.toLocalTime();
- case Qt::OffsetFromUTC:
- return datetime.toOffsetFromUtc(value.toDateTime().offsetFromUtc());
-#if QT_CONFIG(timezone)
- case Qt::TimeZone:
- return datetime.toTimeZone(value.toDateTime().timeZone());
-#endif
- }
- Q_UNREACHABLE();
+ return QDateTime(date, time, timeZone);
}
-// FIXME: architecturaly incompatible with OffsetFromUTC or TimeZone as spec (QTBUG-80417).
-void QDateTimeEditPrivate::updateTimeSpec()
+void QDateTimeEditPrivate::updateTimeZone()
{
- minimum = minimum.toDateTime().toTimeSpec(spec);
- maximum = maximum.toDateTime().toTimeSpec(spec);
- value = value.toDateTime().toTimeSpec(spec);
+ minimum = minimum.toDateTime().toTimeZone(timeZone);
+ maximum = maximum.toDateTime().toTimeZone(timeZone);
+ value = value.toDateTime().toTimeZone(timeZone);
// time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range)
const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
if (!dateShown) {
if (minimum.toTime() >= maximum.toTime()){
- minimum = value.toDate().startOfDay(spec);
- maximum = value.toDate().endOfDay(spec);
+ minimum = value.toDate().startOfDay(timeZone);
+ maximum = value.toDate().endOfDay(timeZone);
}
}
}
@@ -1777,6 +1804,27 @@ void QDateTimeEditPrivate::updateEdit()
}
}
+QDateTime QDateTimeEditPrivate::getMinimum() const
+{
+ if (keyboardTracking)
+ return minimum.toDateTime();
+
+ if (timeZone.timeSpec() == Qt::LocalTime)
+ return QDateTimeParser::getMinimum();
+
+ return QDATETIMEEDIT_DATE_MIN.startOfDay(timeZone);
+}
+
+QDateTime QDateTimeEditPrivate::getMaximum() const
+{
+ if (keyboardTracking)
+ return maximum.toDateTime();
+
+ if (timeZone.timeSpec() == Qt::LocalTime)
+ return QDateTimeParser::getMaximum();
+
+ return QDATETIMEEDIT_DATE_MAX.endOfDay(timeZone);
+}
/*!
\internal
@@ -1822,7 +1870,7 @@ int QDateTimeEditPrivate::sectionAt(int pos) const
const int textSize = text.size();
if (textSize - pos < separators.last().size() + 1) {
if (separators.last().size() == 0) {
- return sectionNodes.count() - 1;
+ return sectionNodes.size() - 1;
}
return (pos == textSize ? LastSectionIndex : NoSectionIndex);
}
@@ -1852,7 +1900,7 @@ int QDateTimeEditPrivate::closestSection(int pos, bool forward) const
const QString text = displayText();
if (text.size() - pos < separators.last().size() + 1)
- return forward ? LastSectionIndex : sectionNodes.size() - 1;
+ return forward ? LastSectionIndex : int(sectionNodes.size() - 1);
updateCache(value, text);
for (int i=0; i<sectionNodes.size(); ++i) {
@@ -1884,7 +1932,7 @@ int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
switch (current) {
case FirstSectionIndex: return forward ? 0 : FirstSectionIndex;
- case LastSectionIndex: return (forward ? LastSectionIndex : sectionNodes.size() - 1);
+ case LastSectionIndex: return (forward ? LastSectionIndex : int(sectionNodes.size() - 1));
case NoSectionIndex: return FirstSectionIndex;
default: break;
}
@@ -1908,7 +1956,7 @@ int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
void QDateTimeEditPrivate::clearSection(int index)
{
- const QLatin1Char space(' ');
+ const auto space = u' ';
int cursorPos = edit->cursorPosition();
const QSignalBlocker blocker(edit);
QString t = edit->text();
@@ -1985,8 +2033,18 @@ QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &positi
return minimum.toDateTime();
}
}
+
StateNode tmp = parse(input, position, value.toDateTime(), fixup);
- input = tmp.input;
+ // Take note of any corrections imposed during parsing:
+ input = m_text;
+ // TODO: if the format specifies time-zone, update timeZone to match the
+ // parsed text; but we're in const context, so can't - QTBUG-118393.
+ // Impose this widget's time system:
+ tmp.value = tmp.value.toTimeZone(timeZone);
+ // ... but that might turn a valid datetime into an invalid one:
+ if (!tmp.value.isValid() && tmp.state == Acceptable)
+ tmp.state = Intermediate;
+
position += tmp.padded;
state = QValidator::State(int(tmp.state));
if (state == QValidator::Acceptable) {
@@ -2028,7 +2086,7 @@ QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
QVariant QDateTimeEditPrivate::valueFromText(const QString &f) const
{
Q_Q(const QDateTimeEdit);
- return q->dateTimeFromText(f).toTimeSpec(spec);
+ return q->dateTimeFromText(f).toTimeZone(timeZone);
}
@@ -2050,40 +2108,73 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
int pos = edit->cursorPosition();
const SectionNode sn = sectionNode(sectionIndex);
- int val;
// to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
- if (!test && pendingEmit) {
- if (q->validate(str, pos) != QValidator::Acceptable) {
- v = value.toDateTime();
- } else {
- v = q->dateTimeFromText(str);
- }
- val = getDigit(v, sectionIndex);
- } else {
- val = getDigit(v, sectionIndex);
- }
-
- val += steps;
+ if (!test && pendingEmit && q->validate(str, pos) == QValidator::Acceptable)
+ v = q->dateTimeFromText(str);
+ int val = getDigit(v, sectionIndex);
const int min = absoluteMin(sectionIndex);
const int max = absoluteMax(sectionIndex, value.toDateTime());
- if (val < min) {
- val = (wrapping ? max - (min - val) + 1 : min);
- } else if (val > max) {
- val = (wrapping ? min + val - max - 1 : max);
+ if (sn.type & DayOfWeekSectionMask) {
+ // Must take locale's first day of week into account when *not*
+ // wrapping; min and max don't help us.
+#ifndef QT_ALWAYS_WRAP_WEEKDAY // (documentation, not an actual define)
+ if (!wrapping) {
+ /* It's not clear this is ever really a desirable behavior.
+
+ It refuses to step backwards from the first day of the week or
+ forwards from the day before, only allowing day-of-week stepping
+ from start to end of one week. That's strictly what non-wrapping
+ behavior must surely mean, when put in locale-neutral terms.
+
+ It is, however, likely that users would prefer the "more natural"
+ behavior of cycling through the week.
+ */
+ const int first = int(locale().firstDayOfWeek()); // Mon = 1 through 7 = Sun
+ val = qBound(val < first ? first - 7 : first,
+ val + steps,
+ val < first ? first - 1 : first + 6);
+ } else
+#endif
+ {
+ val += steps;
+ }
+
+ // Restore to range from 1 through 7:
+ val = val % 7;
+ if (val <= 0)
+ val += 7;
+ } else {
+ val += steps;
+ const int span = max - min + 1;
+ if (val < min)
+ val = wrapping ? val + span : min;
+ else if (val > max)
+ val = wrapping ? val - span : max;
}
const int oldDay = v.date().day(calendar);
- setDigit(v, sectionIndex, val);
+ /*
+ Stepping into a daylight saving time that doesn't exist (setDigit() is
+ true when date and time are valid, even if the date-time returned
+ isn't), so use the time that has the same distance from epoch.
+ */
+ if (setDigit(v, sectionIndex, val) && getDigit(v, sectionIndex) != val
+ && sn.type & HourSectionMask && steps < 0) {
+ // decreasing from e.g 3am to 2am would get us back to 3am, but we want 1am
+ auto msecsSinceEpoch = v.toMSecsSinceEpoch() - 3600 * 1000;
+ v = QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch, v.timeRepresentation());
+ }
// if this sets year or month it will make
// sure that days are lowered if needed.
const QDateTime minimumDateTime = minimum.toDateTime();
const QDateTime maximumDateTime = maximum.toDateTime();
// changing one section should only modify that section, if possible
- if (sn.type != AmPmSection && (v < minimumDateTime || v > maximumDateTime)) {
+ if (sn.type != AmPmSection && !(sn.type & DayOfWeekSectionMask)
+ && (v < minimumDateTime || v > maximumDateTime)) {
const int localmin = getDigit(minimumDateTime, sectionIndex);
const int localmax = getDigit(maximumDateTime, sectionIndex);
@@ -2170,8 +2261,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
}
}
- const QDateTime ret = bound(v, value, steps).toDateTime().toTimeSpec(spec);
- return ret;
+ return bound(v, value, steps).toDateTime().toTimeZone(timeZone);
}
/*!
@@ -2207,7 +2297,7 @@ void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
\internal
*/
-void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
+void QDateTimeEditPrivate::editorCursorPositionChanged(int oldpos, int newpos)
{
if (ignoreCursorPositionChanged || specialValue())
return;
@@ -2265,7 +2355,7 @@ void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos
currentSectionIndex = s;
Q_ASSERT_X(currentSectionIndex < sectionNodes.size(),
- "QDateTimeEditPrivate::_q_editorCursorPositionChanged()",
+ "QDateTimeEditPrivate::editorCursorPositionChanged()",
qPrintable(QString::fromLatin1("Internal error (%1 %2)").
arg(currentSectionIndex).
arg(sectionNodes.size())));
@@ -2348,7 +2438,7 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
QStyleOptionComboBox optCombo;
- optCombo.init(this);
+ optCombo.initFrom(this);
optCombo.editable = true;
optCombo.frame = opt.frame;
optCombo.subControls = opt.subControls;
@@ -2358,8 +2448,8 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
optCombo.state &= ~QStyle::State_Enabled;
}
- QPainter p(this);
- style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
+ QStylePainter p(this);
+ p.drawComplexControl(QStyle::CC_ComboBox, optCombo);
}
int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
@@ -2389,7 +2479,7 @@ void QDateTimeEditPrivate::interpret(EmitPolicy ep)
|| currentSectionIndex < 0
|| !(fieldInfo(currentSectionIndex) & AllowPartial))) {
setValue(value, ep);
- updateTimeSpec();
+ updateTimeZone();
} else {
QAbstractSpinBoxPrivate::interpret(ep);
}
@@ -2428,27 +2518,27 @@ void QDateTimeEdit::initStyleOption(QStyleOptionSpinBox *option) const
void QDateTimeEditPrivate::init(const QVariant &var)
{
Q_Q(QDateTimeEdit);
- switch (var.type()) {
- case QVariant::Date:
- value = var.toDate().startOfDay();
- updateTimeSpec();
+ switch (var.userType()) {
+ case QMetaType::QDate:
+ value = var.toDate().startOfDay(timeZone);
+ updateTimeZone();
q->setDisplayFormat(defaultDateFormat);
if (sectionNodes.isEmpty()) // ### safeguard for broken locale
- q->setDisplayFormat(QLatin1String("dd/MM/yyyy"));
+ q->setDisplayFormat("dd/MM/yyyy"_L1);
break;
- case QVariant::DateTime:
+ case QMetaType::QDateTime:
value = var;
- updateTimeSpec();
+ updateTimeZone();
q->setDisplayFormat(defaultDateTimeFormat);
if (sectionNodes.isEmpty()) // ### safeguard for broken locale
- q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss"));
+ q->setDisplayFormat("dd/MM/yyyy hh:mm:ss"_L1);
break;
- case QVariant::Time:
- value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
- updateTimeSpec();
+ case QMetaType::QTime:
+ value = dateTimeValue(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
+ updateTimeZone();
q->setDisplayFormat(defaultTimeFormat);
if (sectionNodes.isEmpty()) // ### safeguard for broken locale
- q->setDisplayFormat(QLatin1String("hh:mm:ss"));
+ q->setDisplayFormat("hh:mm:ss"_L1);
break;
default:
Q_ASSERT_X(0, "QDateTimeEditPrivate::init", "Internal error");
@@ -2496,7 +2586,7 @@ QStyle::SubControl QDateTimeEditPrivate::newHoverControl(const QPoint &pos)
Q_Q(QDateTimeEdit);
QStyleOptionComboBox optCombo;
- optCombo.init(q);
+ optCombo.initFrom(q);
optCombo.editable = true;
optCombo.subControls = QStyle::SC_All;
hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &optCombo, pos, q);
@@ -2513,7 +2603,7 @@ void QDateTimeEditPrivate::updateEditFieldGeometry()
Q_Q(QDateTimeEdit);
QStyleOptionComboBox optCombo;
- optCombo.init(q);
+ optCombo.initFrom(q);
optCombo.editable = true;
optCombo.subControls = QStyle::SC_ComboBoxEditField;
edit->setGeometry(q->style()->subControlRect(QStyle::CC_ComboBox, &optCombo,
@@ -2522,8 +2612,8 @@ void QDateTimeEditPrivate::updateEditFieldGeometry()
QVariant QDateTimeEditPrivate::getZeroVariant() const
{
- Q_ASSERT(type == QVariant::DateTime);
- return QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime(), spec);
+ Q_ASSERT(type == QMetaType::QDateTime);
+ return QDATETIMEEDIT_DATE_INITIAL.startOfDay(timeZone);
}
void QDateTimeEditPrivate::setRange(const QVariant &min, const QVariant &max)
@@ -2552,7 +2642,7 @@ void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
Q_Q(QDateTimeEdit);
if (!monthCalendar) {
monthCalendar = new QCalendarPopup(q, cw, calendar);
- monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
+ monthCalendar->setObjectName("qt_datetimedit_calendar"_L1);
QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
QObject::connect(monthCalendar, SIGNAL(activated(QDate)), q, SLOT(setDate(QDate)));
@@ -2572,28 +2662,31 @@ void QDateTimeEditPrivate::positionCalendarPopup()
pos = q->mapToGlobal(pos);
pos2 = q->mapToGlobal(pos2);
QSize size = monthCalendar->sizeHint();
- QRect screen = QDesktopWidgetPrivate::availableGeometry(pos);
+ QScreen *screen = QGuiApplication::screenAt(pos);
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ const QRect screenRect = screen->availableGeometry();
//handle popup falling "off screen"
if (q->layoutDirection() == Qt::RightToLeft) {
pos.setX(pos.x()-size.width());
pos2.setX(pos2.x()-size.width());
- if (pos.x() < screen.left())
- pos.setX(qMax(pos.x(), screen.left()));
- else if (pos.x()+size.width() > screen.right())
- pos.setX(qMax(pos.x()-size.width(), screen.right()-size.width()));
+ if (pos.x() < screenRect.left())
+ pos.setX(qMax(pos.x(), screenRect.left()));
+ else if (pos.x()+size.width() > screenRect.right())
+ pos.setX(qMax(pos.x()-size.width(), screenRect.right()-size.width()));
} else {
- if (pos.x()+size.width() > screen.right())
- pos.setX(screen.right()-size.width());
- pos.setX(qMax(pos.x(), screen.left()));
+ if (pos.x()+size.width() > screenRect.right())
+ pos.setX(screenRect.right()-size.width());
+ pos.setX(qMax(pos.x(), screenRect.left()));
}
- if (pos.y() + size.height() > screen.bottom())
+ if (pos.y() + size.height() > screenRect.bottom())
pos.setY(pos2.y() - size.height());
- else if (pos.y() < screen.top())
- pos.setY(screen.top());
- if (pos.y() < screen.top())
- pos.setY(screen.top());
- if (pos.y()+size.height() > screen.bottom())
- pos.setY(screen.bottom()-size.height());
+ else if (pos.y() < screenRect.top())
+ pos.setY(screenRect.top());
+ if (pos.y() < screenRect.top())
+ pos.setY(screenRect.top());
+ if (pos.y()+size.height() > screenRect.bottom())
+ pos.setY(screenRect.bottom()-size.height());
monthCalendar->move(pos);
}
@@ -2681,11 +2774,11 @@ void QCalendarPopup::mousePressEvent(QMouseEvent *event)
QDateTimeEdit *dateTime = qobject_cast<QDateTimeEdit *>(parentWidget());
if (dateTime) {
QStyleOptionComboBox opt;
- opt.init(dateTime);
+ opt.initFrom(dateTime);
QRect arrowRect = dateTime->style()->subControlRect(QStyle::CC_ComboBox, &opt,
QStyle::SC_ComboBoxArrow, dateTime);
arrowRect.moveTo(dateTime->mapToGlobal(arrowRect .topLeft()));
- if (arrowRect.contains(event->globalPos()) || rect().contains(event->pos()))
+ if (arrowRect.contains(event->globalPosition().toPoint()) || rect().contains(event->position().toPoint()))
setAttribute(Qt::WA_NoMouseReplay);
}
QWidget::mousePressEvent(event);
diff --git a/src/widgets/widgets/qdatetimeedit.h b/src/widgets/widgets/qdatetimeedit.h
index 03994675ae..f7c0dd7374 100644
--- a/src/widgets/widgets/qdatetimeedit.h
+++ b/src/widgets/widgets/qdatetimeedit.h
@@ -1,47 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATETIMEEDIT_H
#define QDATETIMEEDIT_H
#include <QtWidgets/qtwidgetsglobal.h>
-#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
#include <QtCore/qcalendar.h>
#include <QtCore/qvariant.h>
#include <QtWidgets/qabstractspinbox.h>
@@ -61,8 +25,10 @@ class Q_WIDGETS_EXPORT QDateTimeEdit : public QAbstractSpinBox
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged USER true)
Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged)
Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged)
- Q_PROPERTY(QDateTime maximumDateTime READ maximumDateTime WRITE setMaximumDateTime RESET clearMaximumDateTime)
- Q_PROPERTY(QDateTime minimumDateTime READ minimumDateTime WRITE setMinimumDateTime RESET clearMinimumDateTime)
+ Q_PROPERTY(QDateTime maximumDateTime READ maximumDateTime WRITE setMaximumDateTime
+ RESET clearMaximumDateTime)
+ Q_PROPERTY(QDateTime minimumDateTime READ minimumDateTime WRITE setMinimumDateTime
+ RESET clearMinimumDateTime)
Q_PROPERTY(QDate maximumDate READ maximumDate WRITE setMaximumDate RESET clearMaximumDate)
Q_PROPERTY(QDate minimumDate READ minimumDate WRITE setMinimumDate RESET clearMinimumDate)
Q_PROPERTY(QTime maximumTime READ maximumTime WRITE setMaximumTime RESET clearMaximumTime)
@@ -73,7 +39,10 @@ class Q_WIDGETS_EXPORT QDateTimeEdit : public QAbstractSpinBox
Q_PROPERTY(bool calendarPopup READ calendarPopup WRITE setCalendarPopup)
Q_PROPERTY(int currentSectionIndex READ currentSectionIndex WRITE setCurrentSectionIndex)
Q_PROPERTY(int sectionCount READ sectionCount)
+#if QT_DEPRECATED_SINCE(6, 10)
Q_PROPERTY(Qt::TimeSpec timeSpec READ timeSpec WRITE setTimeSpec)
+#endif
+ Q_PROPERTY(QTimeZone timeZone READ timeZone WRITE setTimeZone)
public:
enum Section { // a sub-type of QDateTimeParser's like-named enum.
NoSection = 0x0000,
@@ -95,8 +64,8 @@ public:
explicit QDateTimeEdit(QWidget *parent = nullptr);
explicit QDateTimeEdit(const QDateTime &dt, QWidget *parent = nullptr);
- explicit QDateTimeEdit(const QDate &d, QWidget *parent = nullptr);
- explicit QDateTimeEdit(const QTime &t, QWidget *parent = nullptr);
+ explicit QDateTimeEdit(QDate d, QWidget *parent = nullptr);
+ explicit QDateTimeEdit(QTime t, QWidget *parent = nullptr);
~QDateTimeEdit();
QDateTime dateTime() const;
@@ -117,24 +86,24 @@ public:
void setDateTimeRange(const QDateTime &min, const QDateTime &max);
QDate minimumDate() const;
- void setMinimumDate(const QDate &min);
+ void setMinimumDate(QDate min);
void clearMinimumDate();
QDate maximumDate() const;
- void setMaximumDate(const QDate &max);
+ void setMaximumDate(QDate max);
void clearMaximumDate();
- void setDateRange(const QDate &min, const QDate &max);
+ void setDateRange(QDate min, QDate max);
QTime minimumTime() const;
- void setMinimumTime(const QTime &min);
+ void setMinimumTime(QTime min);
void clearMinimumTime();
QTime maximumTime() const;
- void setMaximumTime(const QTime &max);
+ void setMaximumTime(QTime max);
void clearMaximumTime();
- void setTimeRange(const QTime &min, const QTime &max);
+ void setTimeRange(QTime min, QTime max);
Sections displayedSections() const;
Section currentSection() const;
@@ -159,8 +128,14 @@ public:
bool calendarPopup() const;
void setCalendarPopup(bool enable);
+#if QT_DEPRECATED_SINCE(6, 10)
+ QT_DEPRECATED_VERSION_X_6_10("Use timeZone() instead")
Qt::TimeSpec timeSpec() const;
+ QT_DEPRECATED_VERSION_X_6_10("Use setTimeZone() instead")
void setTimeSpec(Qt::TimeSpec spec);
+#endif
+ QTimeZone timeZone() const;
+ void setTimeZone(const QTimeZone &zone);
QSize sizeHint() const override;
@@ -170,13 +145,13 @@ public:
bool event(QEvent *event) override;
Q_SIGNALS:
void dateTimeChanged(const QDateTime &dateTime);
- void timeChanged(const QTime &time);
- void dateChanged(const QDate &date);
+ void timeChanged(QTime time);
+ void dateChanged(QDate date);
public Q_SLOTS:
void setDateTime(const QDateTime &dateTime);
- void setDate(const QDate &date);
- void setTime(const QTime &time);
+ void setDate(QDate date);
+ void setTime(QTime time);
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -193,9 +168,9 @@ protected:
StepEnabled stepEnabled() const override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
- void initStyleOption(QStyleOptionSpinBox *option) const;
+ void initStyleOption(QStyleOptionSpinBox *option) const override;
- QDateTimeEdit(const QVariant &val, QVariant::Type parserType, QWidget *parent = nullptr);
+ QDateTimeEdit(const QVariant &val, QMetaType::Type parserType, QWidget *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QDateTimeEdit)
Q_DISABLE_COPY(QDateTimeEdit)
@@ -209,11 +184,11 @@ class Q_WIDGETS_EXPORT QTimeEdit : public QDateTimeEdit
Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY userTimeChanged USER true)
public:
explicit QTimeEdit(QWidget *parent = nullptr);
- explicit QTimeEdit(const QTime &time, QWidget *parent = nullptr);
+ explicit QTimeEdit(QTime time, QWidget *parent = nullptr);
~QTimeEdit();
Q_SIGNALS:
- void userTimeChanged(const QTime &time);
+ void userTimeChanged(QTime time);
};
class Q_WIDGETS_EXPORT QDateEdit : public QDateTimeEdit
@@ -222,11 +197,11 @@ class Q_WIDGETS_EXPORT QDateEdit : public QDateTimeEdit
Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY userDateChanged USER true)
public:
explicit QDateEdit(QWidget *parent = nullptr);
- explicit QDateEdit(const QDate &date, QWidget *parent = nullptr);
+ explicit QDateEdit(QDate date, QWidget *parent = nullptr);
~QDateEdit();
Q_SIGNALS:
- void userDateChanged(const QDate &date);
+ void userDateChanged(QDate date);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeEdit::Sections)
diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h
index 0a4433846f..215ee75bfe 100644
--- a/src/widgets/widgets/qdatetimeedit_p.h
+++ b/src/widgets/widgets/qdatetimeedit_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATETIMEEDIT_P_H
#define QDATETIMEEDIT_P_H
@@ -53,6 +17,8 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtCore/qcalendar.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
#include "QtWidgets/qcalendarwidget.h"
#include "QtWidgets/qspinbox.h"
#include "QtWidgets/qtoolbutton.h"
@@ -62,6 +28,7 @@
#include "private/qdatetimeparser_p.h"
#include "qdebug.h"
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -70,7 +37,7 @@ class Q_AUTOTEST_EXPORT QDateTimeEditPrivate : public QAbstractSpinBoxPrivate, p
{
Q_DECLARE_PUBLIC(QDateTimeEdit)
public:
- QDateTimeEditPrivate();
+ QDateTimeEditPrivate(const QTimeZone &zone = QTimeZone::LocalTime);
void init(const QVariant &var);
void readLocaleSettings();
@@ -83,7 +50,7 @@ public:
void emitSignals(EmitPolicy ep, const QVariant &old) override;
QString textFromValue(const QVariant &f) const override;
QVariant valueFromText(const QString &f) const override;
- void _q_editorCursorPositionChanged(int oldpos, int newpos) override;
+ void editorCursorPositionChanged(int oldpos, int newpos) override;
void interpret(EmitPolicy ep) override;
void clearCache() const override;
QStyle::SubControl newHoverControl(const QPoint &pos) override;
@@ -94,8 +61,8 @@ public:
// Override QDateTimeParser:
QString displayText() const override { return edit->text(); }
- QDateTime getMinimum() const override { return minimum.toDateTime(); }
- QDateTime getMaximum() const override { return maximum.toDateTime(); }
+ QDateTime getMinimum() const override;
+ QDateTime getMaximum() const override;
QLocale locale() const override { return q_func()->locale(); }
int cursorPosition() const override { return edit ? edit->cursorPosition() : -1; }
@@ -109,9 +76,10 @@ public:
void updateCache(const QVariant &val, const QString &str) const;
- QDateTime convertTimeSpec(const QDateTime &datetime);
- void updateTimeSpec();
+ QDateTime convertTimeZone(const QDateTime &datetime);
+ void updateTimeZone();
QString valueToText(const QVariant &var) const { return textFromValue(var); }
+ QDateTime dateTimeValue(QDate date, QTime time) const;
void _q_resetButton();
void updateArrow(QStyle::StateFlag state);
@@ -126,18 +94,20 @@ public:
void initCalendarPopup(QCalendarWidget *cw = nullptr);
void positionCalendarPopup();
- QDateTimeEdit::Sections sections;
- mutable bool cacheGuard;
+ QDateTimeEdit::Sections sections = {};
+ mutable bool cacheGuard = false;
QString defaultDateFormat, defaultTimeFormat, defaultDateTimeFormat, unreversedFormat;
mutable QVariant conflictGuard;
- bool hasHadFocus, formatExplicitlySet, calendarPopup;
- QStyle::StateFlag arrowState;
- QCalendarPopup *monthCalendar;
+ bool hasHadFocus = false, formatExplicitlySet = false, calendarPopup = false;
+ QStyle::StateFlag arrowState = QStyle::State_None;
+ QCalendarPopup *monthCalendar = nullptr;
#ifdef QT_KEYPAD_NAVIGATION
- bool focusOnButton;
+ bool focusOnButton = false;
#endif
+
+ QTimeZone timeZone;
};
diff --git a/src/widgets/widgets/qdial.cpp b/src/widgets/widgets/qdial.cpp
index 25d57970bf..14e96f8dc3 100644
--- a/src/widgets/widgets/qdial.cpp
+++ b/src/widgets/widgets/qdial.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdial.h"
@@ -52,7 +16,7 @@
#include <qslider.h>
#include <private/qabstractslider_p.h>
#include <private/qmath_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <qmath.h>
@@ -94,6 +58,8 @@ int QDialPrivate::bound(int val) const
if (wrapping) {
if ((val >= minimum) && (val <= maximum))
return val;
+ if (minimum == maximum)
+ return minimum;
val = minimum + ((val - minimum) % (maximum - minimum));
if (val < minimum)
val += maximum - minimum;
@@ -222,11 +188,11 @@ int QDialPrivate::valueFromPoint(const QPoint &p) const
If you are using the mouse wheel to adjust the dial, the increment
value is determined by the lesser value of
- \l{QApplication::wheelScrollLines()} {wheelScrollLines} multipled
+ \l{QApplication::wheelScrollLines()} {wheelScrollLines} multiplied
by \l {QAbstractSlider::singleStep} {singleStep}, and
\l {QAbstractSlider::pageStep} {pageStep}.
- \sa QScrollBar, QSpinBox, QSlider, {fowler}{GUI Design Handbook: Slider}, {Sliders Example}
+ \sa QScrollBar, QSpinBox, QSlider, {Sliders Example}
*/
/*!
@@ -280,7 +246,7 @@ void QDial::mousePressEvent(QMouseEvent *e)
return;
}
e->accept();
- setSliderPosition(d->valueFromPoint(e->pos()));
+ setSliderPosition(d->valueFromPoint(e->position().toPoint()));
// ### This isn't quite right,
// we should be doing a hit test and only setting this if it's
// the actual dial thingie (similar to what QSlider does), but we have no
@@ -302,7 +268,7 @@ void QDial::mouseReleaseEvent(QMouseEvent * e)
return;
}
e->accept();
- setValue(d->valueFromPoint(e->pos()));
+ setValue(d->valueFromPoint(e->position().toPoint()));
setSliderDown(false);
}
@@ -320,7 +286,7 @@ void QDial::mouseMoveEvent(QMouseEvent * e)
}
e->accept();
d->doNotEmit = true;
- setSliderPosition(d->valueFromPoint(e->pos()));
+ setSliderPosition(d->valueFromPoint(e->position().toPoint()));
d->doNotEmit = false;
}
@@ -370,12 +336,10 @@ bool QDial::wrapping() const
\property QDial::notchSize
\brief the current notch size
- The notch size is in range control units, not pixels, and if
- possible it is a multiple of singleStep() that results in an
+ The notch size is in range control units, not pixels, and is
+ calculated to be a multiple of singleStep() that results in an
on-screen notch size near notchTarget().
- By default, this property has a value of 1.
-
\sa notchTarget(), singleStep()
*/
@@ -383,21 +347,17 @@ int QDial::notchSize() const
{
Q_D(const QDial);
// radius of the arc
- int r = qMin(width(), height())/2;
+ qreal r = qMin(width(), height())/2.0;
// length of the whole arc
- int l = (int)(r * (d->wrapping ? 6 : 5) * Q_PI / 6);
+ int l = qRound(r * (d->wrapping ? 6.0 : 5.0) * Q_PI / 6.0);
// length of the arc from minValue() to minValue()+pageStep()
if (d->maximum > d->minimum + d->pageStep)
- l = (int)(0.5 + l * d->pageStep / (d->maximum - d->minimum));
+ l = qRound(l * d->pageStep / double(d->maximum - d->minimum));
// length of a singleStep arc
- l = l * d->singleStep / (d->pageStep ? d->pageStep : 1);
- if (l < 1)
- l = 1;
+ l = qMax(l * d->singleStep / (d->pageStep ? d->pageStep : 1), 1);
// how many times singleStep can be draw in d->target pixels
- l = (int)(0.5 + d->target / l);
- // we want notchSize() to be a non-zero multiple of lineStep()
- if (!l)
- l = 1;
+ l = qMax(qRound(d->target / l), 1);
+ // we want notchSize() to be a non-zero multiple of singleStep()
return d->singleStep * l;
}
@@ -464,7 +424,7 @@ QSize QDial::minimumSizeHint() const
QSize QDial::sizeHint() const
{
- return QSize(100, 100).expandedTo(QApplication::globalStrut());
+ return QSize(100, 100);
}
/*!
diff --git a/src/widgets/widgets/qdial.h b/src/widgets/widgets/qdial.h
index 1db1f9bb07..af08a41048 100644
--- a/src/widgets/widgets/qdial.h
+++ b/src/widgets/widgets/qdial.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDIAL_H
@@ -90,7 +54,7 @@ protected:
void mouseMoveEvent(QMouseEvent *me) override;
void sliderChange(SliderChange change) override;
- void initStyleOption(QStyleOptionSlider *option) const;
+ virtual void initStyleOption(QStyleOptionSlider *option) const;
private:
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index 2e12320bc3..30ace89fa8 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qhash.h>
#include <QtWidgets/qpushbutton.h>
@@ -47,9 +11,12 @@
#include <private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformdialoghelper.h>
#include <QtGui/qpa/qplatformtheme.h>
-#include <QtWidgets/qaction.h>
+#include <QtGui/qaction.h>
#include "qdialogbuttonbox.h"
+#include "qdialogbuttonbox_p.h"
+
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -89,7 +56,7 @@ QT_BEGIN_NAMESPACE
the buttons (or button texts) yourself and add them to the button box,
specifying their role.
- \snippet dialogs/extension/finddialog.cpp 1
+ \snippet dialogs/dialogs.cpp buttonbox
Alternatively, QDialogButtonBox provides several standard buttons (e.g. OK, Cancel, Save)
that you can use. They exist as flags so you can OR them together in the constructor.
@@ -147,39 +114,25 @@ QT_BEGIN_NAMESPACE
\sa QMessageBox, QPushButton, QDialog
*/
-
-class QDialogButtonBoxPrivate : public QWidgetPrivate
+QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
+ : orientation(orient), buttonLayout(nullptr), center(false)
{
- Q_DECLARE_PUBLIC(QDialogButtonBox)
-
-public:
- QDialogButtonBoxPrivate(Qt::Orientation orient);
-
- QList<QAbstractButton *> buttonLists[QDialogButtonBox::NRoles];
- QHash<QPushButton *, QDialogButtonBox::StandardButton> standardButtonHash;
-
- Qt::Orientation orientation;
- QDialogButtonBox::ButtonLayout layoutPolicy;
- QBoxLayout *buttonLayout;
- bool internalRemove;
- bool center;
+ struct EventFilter : public QObject
+ {
+ EventFilter(QDialogButtonBoxPrivate *d) : d(d) {};
+
+ bool eventFilter(QObject *obj, QEvent *event) override
+ {
+ QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
+ return button ? d->handleButtonShowAndHide(button, event) : false;
+ }
- void createStandardButtons(QDialogButtonBox::StandardButtons buttons);
+ private:
+ QDialogButtonBoxPrivate *d;
- void layoutButtons();
- void initLayout();
- void resetLayout();
- QPushButton *createButton(QDialogButtonBox::StandardButton button, bool doLayout = true);
- void addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role, bool doLayout = true);
- void _q_handleButtonDestroyed();
- void _q_handleButtonClicked();
- void addButtonsToLayout(const QList<QAbstractButton *> &buttonList, bool reverse);
- void retranslateStrings();
-};
+ };
-QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
- : orientation(orient), buttonLayout(nullptr), internalRemove(false), center(false)
-{
+ filter.reset(new EventFilter(this));
}
void QDialogButtonBoxPrivate::initLayout()
@@ -213,7 +166,6 @@ void QDialogButtonBoxPrivate::initLayout()
void QDialogButtonBoxPrivate::resetLayout()
{
- //delete buttonLayout;
initLayout();
layoutButtons();
}
@@ -221,8 +173,8 @@ void QDialogButtonBoxPrivate::resetLayout()
void QDialogButtonBoxPrivate::addButtonsToLayout(const QList<QAbstractButton *> &buttonList,
bool reverse)
{
- int start = reverse ? buttonList.count() - 1 : 0;
- int end = reverse ? -1 : buttonList.count();
+ int start = reverse ? buttonList.size() - 1 : 0;
+ int end = reverse ? -1 : buttonList.size();
int step = reverse ? -1 : 1;
for (int i = start; i != end; i += step) {
@@ -237,6 +189,7 @@ void QDialogButtonBoxPrivate::layoutButtons()
Q_Q(QDialogButtonBox);
const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item
+ QBoolBlocker blocker(ignoreShowAndHide);
for (int i = buttonLayout->count() - 1; i >= 0; --i) {
QLayoutItem *item = buttonLayout->takeAt(i);
if (QWidget *widget = item->widget())
@@ -329,16 +282,20 @@ void QDialogButtonBoxPrivate::layoutButtons()
++currentLayout;
}
- QWidget *lastWidget = nullptr;
- q->setFocusProxy(nullptr);
+ QWidgetList layoutWidgets;
for (int i = 0; i < buttonLayout->count(); ++i) {
- QLayoutItem *item = buttonLayout->itemAt(i);
- if (QWidget *widget = item->widget()) {
- if (lastWidget)
- QWidget::setTabOrder(lastWidget, widget);
- else
- q->setFocusProxy(widget);
- lastWidget = widget;
+ if (auto *widget = buttonLayout->itemAt(i)->widget())
+ layoutWidgets << widget;
+ }
+
+ q->setFocusProxy(nullptr);
+ if (!layoutWidgets.isEmpty()) {
+ QWidget *prev = layoutWidgets.constLast();
+ for (QWidget *here : layoutWidgets) {
+ QWidget::setTabOrder(prev, here);
+ prev = here;
+ if (auto *pushButton = qobject_cast<QPushButton *>(prev); pushButton && pushButton->isDefault())
+ q->setFocusProxy(pushButton);
}
}
@@ -347,7 +304,7 @@ void QDialogButtonBoxPrivate::layoutButtons()
}
QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton,
- bool doLayout)
+ LayoutRule layoutRule)
{
Q_Q(QDialogButtonBox);
int icon = 0;
@@ -422,7 +379,7 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut
if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))
qWarning("QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
else
- addButton(button, static_cast<QDialogButtonBox::ButtonRole>(role), doLayout);
+ addButton(button, static_cast<QDialogButtonBox::ButtonRole>(role), layoutRule);
#if QT_CONFIG(shortcut)
const QKeySequence standardShortcut = QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton);
if (!standardShortcut.isEmpty())
@@ -432,23 +389,36 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut
}
void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,
- bool doLayout)
+ LayoutRule layoutRule, AddRule addRule)
{
- Q_Q(QDialogButtonBox);
- QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_handleButtonClicked()));
- QObject::connect(button, SIGNAL(destroyed()), q, SLOT(_q_handleButtonDestroyed()));
buttonLists[role].append(button);
- if (doLayout)
+ switch (addRule) {
+ case AddRule::Connect:
+ QObjectPrivate::connect(button, &QAbstractButton::clicked,
+ this, &QDialogButtonBoxPrivate::handleButtonClicked);
+ QObjectPrivate::connect(button, &QAbstractButton::destroyed,
+ this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
+ button->installEventFilter(filter.get());
+ break;
+ case AddRule::SkipConnect:
+ break;
+ }
+
+ switch (layoutRule) {
+ case LayoutRule::DoLayout:
layoutButtons();
+ break;
+ case LayoutRule::SkipLayout:
+ break;
+ }
}
void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardButtons buttons)
{
uint i = QDialogButtonBox::FirstButton;
while (i <= QDialogButtonBox::LastButton) {
- if (i & buttons) {
- createButton(QDialogButtonBox::StandardButton(i), false);
- }
+ if (i & buttons)
+ createButton(QDialogButtonBox::StandardButton(i), LayoutRule::SkipLayout);
i = i << 1;
}
layoutButtons();
@@ -456,13 +426,10 @@ void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardBu
void QDialogButtonBoxPrivate::retranslateStrings()
{
- typedef QHash<QPushButton *, QDialogButtonBox::StandardButton>::iterator Iterator;
-
- const Iterator end = standardButtonHash.end();
- for (Iterator it = standardButtonHash.begin(); it != end; ++it) {
- const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(it.value());
+ for (auto &&[key, value] : std::as_const(standardButtonHash).asKeyValueRange()) {
+ const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(value);
if (!text.isEmpty())
- it.key()->setText(text);
+ key->setText(text);
}
}
@@ -518,6 +485,14 @@ QDialogButtonBox::QDialogButtonBox(StandardButtons buttons, Qt::Orientation orie
*/
QDialogButtonBox::~QDialogButtonBox()
{
+ Q_D(QDialogButtonBox);
+
+ d->ignoreShowAndHide = true;
+
+ // QObjectPrivate::connect requires explicit disconnect in destructor
+ // otherwise the connection may kick in on child destruction and reach
+ // the parent's destroyed private object
+ d->disconnectAll();
}
/*!
@@ -672,34 +647,45 @@ void QDialogButtonBox::clear()
d->standardButtonHash.clear();
for (int i = 0; i < NRoles; ++i) {
QList<QAbstractButton *> &list = d->buttonLists[i];
- while (list.count()) {
+ while (list.size()) {
QAbstractButton *button = list.takeAt(0);
- QObject::disconnect(button, SIGNAL(destroyed()), this, SLOT(_q_handleButtonDestroyed()));
+ QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
+ d, &QDialogButtonBoxPrivate::handleButtonDestroyed);
delete button;
}
}
}
/*!
- Returns a list of all the buttons that have been added to the button box.
+ Returns a list of all buttons that have been added to the button box.
\sa buttonRole(), addButton(), removeButton()
*/
QList<QAbstractButton *> QDialogButtonBox::buttons() const
{
Q_D(const QDialogButtonBox);
+ return d->allButtons();
+}
+
+QList<QAbstractButton *> QDialogButtonBoxPrivate::visibleButtons() const
+{
QList<QAbstractButton *> finalList;
- for (int i = 0; i < NRoles; ++i) {
- const QList<QAbstractButton *> &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j)
+ for (int i = 0; i < QDialogButtonBox::NRoles; ++i) {
+ const QList<QAbstractButton *> &list = buttonLists[i];
+ for (int j = 0; j < list.size(); ++j)
finalList.append(list.at(j));
}
return finalList;
}
+QList<QAbstractButton *> QDialogButtonBoxPrivate::allButtons() const
+{
+ return visibleButtons() << hiddenButtons.keys();
+}
+
/*!
Returns the button role for the specified \a button. This function returns
- \l InvalidRole if \a button is 0 or has not been added to the button box.
+ \l InvalidRole if \a button is \nullptr or has not been added to the button box.
\sa buttons(), addButton()
*/
@@ -708,12 +694,12 @@ QDialogButtonBox::ButtonRole QDialogButtonBox::buttonRole(QAbstractButton *butto
Q_D(const QDialogButtonBox);
for (int i = 0; i < NRoles; ++i) {
const QList<QAbstractButton *> &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j) {
+ for (int j = 0; j < list.size(); ++j) {
if (list.at(j) == button)
return ButtonRole(i);
}
}
- return InvalidRole;
+ return d->hiddenButtons.value(button, InvalidRole);
}
/*!
@@ -724,27 +710,45 @@ QDialogButtonBox::ButtonRole QDialogButtonBox::buttonRole(QAbstractButton *butto
void QDialogButtonBox::removeButton(QAbstractButton *button)
{
Q_D(QDialogButtonBox);
+ d->removeButton(button, QDialogButtonBoxPrivate::RemoveReason::ManualRemove);
+}
+/*!
+ \internal
+ Removes \param button.
+ \param reason determines the behavior following the removal:
+ \list
+ \li \c ManualRemove disconnects all signals and removes the button from standardButtonHash.
+ \li \c HideEvent keeps connections alive, standard buttons remain in standardButtonHash.
+ \li \c Destroyed removes the button from standardButtonHash. Signals remain untouched, because
+ the button might already be only a QObject, the destructor of which handles disconnecting.
+ \endlist
+ */
+void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason reason)
+{
if (!button)
return;
- // Remove it from the standard button hash first and then from the roles
- d->standardButtonHash.remove(reinterpret_cast<QPushButton *>(button));
- for (int i = 0; i < NRoles; ++i) {
- QList<QAbstractButton *> &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j) {
- if (list.at(j) == button) {
- list.takeAt(j);
- if (!d->internalRemove) {
- disconnect(button, SIGNAL(clicked()), this, SLOT(_q_handleButtonClicked()));
- disconnect(button, SIGNAL(destroyed()), this, SLOT(_q_handleButtonDestroyed()));
- }
- break;
- }
- }
- }
- if (!d->internalRemove)
+ // Remove button from hidden buttons and roles
+ hiddenButtons.remove(button);
+ for (int i = 0; i < QDialogButtonBox::NRoles; ++i)
+ buttonLists[i].removeOne(button);
+
+ switch (reason) {
+ case RemoveReason::ManualRemove:
button->setParent(nullptr);
+ QObjectPrivate::disconnect(button, &QAbstractButton::clicked,
+ this, &QDialogButtonBoxPrivate::handleButtonClicked);
+ QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
+ this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
+ button->removeEventFilter(filter.get());
+ Q_FALLTHROUGH();
+ case RemoveReason::Destroyed:
+ standardButtonHash.remove(reinterpret_cast<QPushButton *>(button));
+ break;
+ case RemoveReason::HideEvent:
+ break;
+ }
}
/*!
@@ -814,7 +818,7 @@ void QDialogButtonBox::setStandardButtons(StandardButtons buttons)
{
Q_D(QDialogButtonBox);
// Clear out all the old standard buttons, then recreate them.
- qDeleteAll(d->standardButtonHash.keys());
+ qDeleteAll(d->standardButtonHash.keyBegin(), d->standardButtonHash.keyEnd());
d->standardButtonHash.clear();
d->createStandardButtons(buttons);
@@ -856,7 +860,7 @@ QDialogButtonBox::StandardButton QDialogButtonBox::standardButton(QAbstractButto
return d->standardButtonHash.value(static_cast<QPushButton *>(button));
}
-void QDialogButtonBoxPrivate::_q_handleButtonClicked()
+void QDialogButtonBoxPrivate::handleButtonClicked()
{
Q_Q(QDialogButtonBox);
if (QAbstractButton *button = qobject_cast<QAbstractButton *>(q->sender())) {
@@ -890,20 +894,51 @@ void QDialogButtonBoxPrivate::_q_handleButtonClicked()
}
}
-void QDialogButtonBoxPrivate::_q_handleButtonDestroyed()
+void QDialogButtonBoxPrivate::handleButtonDestroyed()
+{
+ Q_Q(QDialogButtonBox);
+ if (QObject *object = q->sender())
+ removeButton(reinterpret_cast<QAbstractButton *>(object), RemoveReason::Destroyed);
+}
+
+bool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event)
{
Q_Q(QDialogButtonBox);
- if (QObject *object = q->sender()) {
- QBoolBlocker skippy(internalRemove);
- q->removeButton(reinterpret_cast<QAbstractButton *>(object));
+
+ const QEvent::Type type = event->type();
+
+ if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide)
+ return false;
+
+ switch (type) {
+ case QEvent::HideToParent: {
+ const QDialogButtonBox::ButtonRole role = q->buttonRole(button);
+ if (role != QDialogButtonBox::ButtonRole::InvalidRole) {
+ removeButton(button, RemoveReason::HideEvent);
+ hiddenButtons.insert(button, role);
+ layoutButtons();
+ }
+ break;
}
+ case QEvent::ShowToParent:
+ if (hiddenButtons.contains(button)) {
+ const auto role = hiddenButtons.take(button);
+ addButton(button, role, LayoutRule::DoLayout, AddRule::SkipConnect);
+ if (role == QDialogButtonBox::AcceptRole)
+ ensureFirstAcceptIsDefault();
+ }
+ break;
+ default: break;
+ }
+
+ return false;
}
/*!
\property QDialogButtonBox::centerButtons
\brief whether the buttons in the button box are centered
- By default, this property is \c false. This behavior is appopriate
+ By default, this property is \c false. This behavior is appropriate
for most types of dialogs. A notable exception is message boxes
on most platforms (e.g. Windows), where the button box is
centered horizontally.
@@ -954,36 +989,80 @@ void QDialogButtonBox::changeEvent(QEvent *event)
}
}
+void QDialogButtonBoxPrivate::ensureFirstAcceptIsDefault()
+{
+ Q_Q(QDialogButtonBox);
+ const QList<QAbstractButton *> &acceptRoleList = buttonLists[QDialogButtonBox::AcceptRole];
+ QPushButton *firstAcceptButton = acceptRoleList.isEmpty()
+ ? nullptr
+ : qobject_cast<QPushButton *>(acceptRoleList.at(0));
+
+ if (!firstAcceptButton)
+ return;
+
+ bool hasDefault = false;
+ QWidget *dialog = nullptr;
+ QWidget *p = q;
+ while (p && !p->isWindow()) {
+ p = p->parentWidget();
+ if ((dialog = qobject_cast<QDialog *>(p)))
+ break;
+ }
+
+ QWidget *parent = dialog ? dialog : q;
+ Q_ASSERT(parent);
+
+ const auto pushButtons = parent->findChildren<QPushButton *>();
+ for (QPushButton *pushButton : pushButtons) {
+ if (pushButton->isDefault() && pushButton != firstAcceptButton) {
+ hasDefault = true;
+ break;
+ }
+ }
+ if (!hasDefault && firstAcceptButton) {
+ firstAcceptButton->setDefault(true);
+ // When the QDialogButtonBox is focused, and it doesn't have an
+ // explicit focus widget, it will transfer focus to its focus
+ // proxy, which is the first button in the layout. This behavior,
+ // combined with the behavior that QPushButtons in a QDialog will
+ // by default have their autoDefault set to true, results in the
+ // focus proxy/first button stealing the default button status
+ // immediately when the button box is focused, which is not what
+ // we want. Account for this by explicitly making the firstAcceptButton
+ // focused as well, unless an explicit focus widget has been set, or
+ // a dialog child has Qt::StrongFocus.
+ if (dialog && !(QWidgetPrivate::get(dialog)->hasChildWithFocusPolicy(Qt::StrongFocus, q)
+ || dialog->focusWidget()))
+ firstAcceptButton->setFocus();
+ }
+}
+
+void QDialogButtonBoxPrivate::disconnectAll()
+{
+ Q_Q(QDialogButtonBox);
+ const auto buttons = q->findChildren<QAbstractButton *>();
+ for (auto *button : buttons)
+ button->disconnect(q);
+}
+
/*!
\reimp
*/
bool QDialogButtonBox::event(QEvent *event)
{
Q_D(QDialogButtonBox);
- if (event->type() == QEvent::Show) {
- QList<QAbstractButton *> acceptRoleList = d->buttonLists[AcceptRole];
- QPushButton *firstAcceptButton = acceptRoleList.isEmpty() ? 0 : qobject_cast<QPushButton *>(acceptRoleList.at(0));
- bool hasDefault = false;
- QWidget *dialog = nullptr;
- QWidget *p = this;
- while (p && !p->isWindow()) {
- p = p->parentWidget();
- if ((dialog = qobject_cast<QDialog *>(p)))
- break;
- }
+ switch (event->type()) {
+ case QEvent::Show:
+ d->ensureFirstAcceptIsDefault();
+ break;
- const auto pbs = (dialog ? dialog : this)->findChildren<QPushButton *>();
- for (QPushButton *pb : pbs) {
- if (pb->isDefault() && pb != firstAcceptButton) {
- hasDefault = true;
- break;
- }
- }
- if (!hasDefault && firstAcceptButton)
- firstAcceptButton->setDefault(true);
- }else if (event->type() == QEvent::LanguageChange) {
+ case QEvent::LanguageChange:
d->retranslateStrings();
+ break;
+
+ default: break;
}
+
return QWidget::event(event);
}
diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h
index a9a1a3453d..d967494d0d 100644
--- a/src/widgets/widgets/qdialogbuttonbox.h
+++ b/src/widgets/widgets/qdialogbuttonbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDIALOGBUTTONBOX_H
#define QDIALOGBUTTONBOX_H
@@ -113,8 +77,7 @@ public:
MacLayout,
KdeLayout,
GnomeLayout,
- // MacModelessLayout,
- AndroidLayout = GnomeLayout + 2 // ### Qt 6: reorder
+ AndroidLayout
};
QDialogButtonBox(QWidget *parent = nullptr);
@@ -157,8 +120,6 @@ protected:
private:
Q_DISABLE_COPY(QDialogButtonBox)
Q_DECLARE_PRIVATE(QDialogButtonBox)
- Q_PRIVATE_SLOT(d_func(), void _q_handleButtonClicked())
- Q_PRIVATE_SLOT(d_func(), void _q_handleButtonDestroyed())
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDialogButtonBox::StandardButtons)
diff --git a/src/widgets/widgets/qdialogbuttonbox_p.h b/src/widgets/widgets/qdialogbuttonbox_p.h
new file mode 100644
index 0000000000..c3d7e03489
--- /dev/null
+++ b/src/widgets/widgets/qdialogbuttonbox_p.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QDIALOGBUTTONBOX_P_H
+#define QDIALOGBUTTONBOX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qwidget_p.h>
+#include <qdialogbuttonbox.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QDialogButtonBoxPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QDialogButtonBox)
+
+public:
+ enum class RemoveReason {
+ HideEvent,
+ ManualRemove,
+ Destroyed,
+ };
+ enum class LayoutRule {
+ DoLayout,
+ SkipLayout,
+ };
+ enum class AddRule {
+ Connect,
+ SkipConnect,
+ };
+
+ QDialogButtonBoxPrivate(Qt::Orientation orient);
+
+ QList<QAbstractButton *> buttonLists[QDialogButtonBox::NRoles];
+ QHash<QPushButton *, QDialogButtonBox::StandardButton> standardButtonHash;
+ QHash<QAbstractButton *, QDialogButtonBox::ButtonRole> hiddenButtons;
+
+ Qt::Orientation orientation;
+ QDialogButtonBox::ButtonLayout layoutPolicy;
+ QBoxLayout *buttonLayout;
+ std::unique_ptr<QObject> filter;
+ bool center;
+ bool ignoreShowAndHide = false;
+
+ void createStandardButtons(QDialogButtonBox::StandardButtons buttons);
+
+ void removeButton(QAbstractButton *button, RemoveReason reason);
+ void layoutButtons();
+ void initLayout();
+ void resetLayout();
+ QPushButton *createButton(QDialogButtonBox::StandardButton button,
+ LayoutRule layoutRule = LayoutRule::DoLayout);
+ void addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,
+ LayoutRule layoutRule = LayoutRule::DoLayout,
+ AddRule addRule = AddRule::Connect);
+ void handleButtonDestroyed();
+ void handleButtonClicked();
+ bool handleButtonShowAndHide(QAbstractButton *button, QEvent *event);
+ void addButtonsToLayout(const QList<QAbstractButton *> &buttonList, bool reverse);
+ void ensureFirstAcceptIsDefault();
+ void retranslateStrings();
+ void disconnectAll();
+ QList<QAbstractButton *> allButtons() const;
+ QList<QAbstractButton *> visibleButtons() const;
+ QDialogButtonBox::ButtonRole buttonRole(QAbstractButton *button) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDIALOGBUTTONBOX_P_H
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 87f4519dd6..da0e987171 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "QtWidgets/qapplication.h"
#include "QtWidgets/qwidget.h"
@@ -44,8 +8,6 @@
#include "QtWidgets/qtabbar.h"
#endif
#include "QtWidgets/qstyle.h"
-#include "QtWidgets/qdesktopwidget.h"
-#include <private/qdesktopwidget_p.h>
#include "QtWidgets/qapplication.h"
#include "QtCore/qvariant.h"
#include "qdockarealayout_p.h"
@@ -62,6 +24,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpaDockWidgets, "qt.widgets.dockwidgets");
+
// qmainwindow.cpp
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
@@ -127,7 +91,7 @@ bool QDockAreaLayoutItem::skip() const
return widgetItem->isEmpty();
if (subinfo != nullptr) {
- for (int i = 0; i < subinfo->item_list.count(); ++i) {
+ for (int i = 0; i < subinfo->item_list.size(); ++i) {
if (!subinfo->item_list.at(i).skip())
return false;
}
@@ -184,7 +148,11 @@ QSize QDockAreaLayoutItem::sizeHint() const
QDockAreaLayoutItem
&QDockAreaLayoutItem::operator = (const QDockAreaLayoutItem &other)
{
+ if (this == &other)
+ return *this;
+
widgetItem = other.widgetItem;
+ delete subinfo;
if (other.subinfo == nullptr)
subinfo = nullptr;
else
@@ -203,6 +171,38 @@ QDockAreaLayoutItem
return *this;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QDockAreaLayoutItem *item)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ return item ? dbg << *item : dbg << "QDockAreaLayoutItem(0x0)";
+}
+
+QDebug operator<<(QDebug dbg, const QDockAreaLayoutItem &item)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "QDockAreaLayoutItem(" << static_cast<const void *>(&item) << "->";
+ if (item.widgetItem) {
+ QWidget *widget = item.widgetItem->widget();
+ if (auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
+ dbg << "widgetItem(" << dockWidget << ")";
+ } else if (auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+ dbg << "widgetItem(" << groupWindow << "->(" << groupWindow->dockWidgets() << "))";
+ } else {
+ dbg << "widgetItem(" << widget << ")";
+ }
+ } else if (item.subinfo) {
+ dbg << "subInfo(" << item.subinfo << "->(" << item.subinfo->item_list << ")";
+ } else if (item.placeHolderItem) {
+ dbg << "placeHolderItem(" << item.placeHolderItem << ")";
+ }
+ dbg << ")";
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
/******************************************************************************
** QDockAreaLayoutInfo
*/
@@ -544,7 +544,7 @@ void QDockAreaLayoutInfo::fitItems()
}
#endif
- QVector<QLayoutStruct> layout_struct_list(item_list.size()*2);
+ QList<QLayoutStruct> layout_struct_list(item_list.size() * 2);
int j = 0;
int size = pick(o, rect.size());
@@ -854,7 +854,7 @@ static inline int grow(QLayoutStruct &ls, int delta)
return ls.size - old_size;
}
-static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delta, int sep)
+static int separatorMoveHelper(QList<QLayoutStruct> &list, int index, int delta, int sep)
{
// adjust sizes
int pos = -1;
@@ -884,7 +884,7 @@ static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delt
delta = growlimit;
int d = 0;
- for (int i = index + 1; d < delta && i < list.count(); ++i)
+ for (int i = index + 1; d < delta && i < list.size(); ++i)
d += shrink(list[i], delta - d);
delta = d;
d = 0;
@@ -892,7 +892,7 @@ static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delt
d += grow(list[i], delta - d);
} else if (delta < 0) {
int growlimit = 0;
- for (int i = index + 1; i < list.count(); ++i) {
+ for (int i = index + 1; i < list.size(); ++i) {
const QLayoutStruct &ls = list.at(i);
if (ls.empty)
continue;
@@ -910,7 +910,7 @@ static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delt
d += shrink(list[i], -delta - d);
delta = -d;
d = 0;
- for (int i = index + 1; d < -delta && i < list.count(); ++i)
+ for (int i = index + 1; d < -delta && i < list.size(); ++i)
d += grow(list[i], -delta - d);
}
@@ -938,7 +938,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
Q_ASSERT(!tabbed);
#endif
- QVector<QLayoutStruct> list(item_list.size());
+ QList<QLayoutStruct> list(item_list.size());
for (int i = 0; i < list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
QLayoutStruct &ls = list[i];
@@ -981,12 +981,12 @@ void QDockAreaLayoutInfo::unnest(int index)
QDockAreaLayoutItem &item = item_list[index];
if (item.subinfo == nullptr)
return;
- if (item.subinfo->item_list.count() > 1)
+ if (item.subinfo->item_list.size() > 1)
return;
- if (item.subinfo->item_list.count() == 0) {
+ if (item.subinfo->item_list.size() == 0) {
item_list.removeAt(index);
- } else if (item.subinfo->item_list.count() == 1) {
+ } else if (item.subinfo->item_list.size() == 1) {
QDockAreaLayoutItem &child = item.subinfo->item_list.first();
if (child.widgetItem != nullptr) {
item.widgetItem = child.widgetItem;
@@ -1006,7 +1006,7 @@ void QDockAreaLayoutInfo::remove(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
- if (path.count() > 1) {
+ if (path.size() > 1) {
const int index = path.first();
QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != nullptr);
@@ -1018,6 +1018,14 @@ void QDockAreaLayoutInfo::remove(const QList<int> &path)
}
}
+void QDockAreaLayoutInfo::remove(QWidget *widget)
+{
+ const QList<int> path = indexOf(widget);
+ if (path.isEmpty())
+ return;
+ remove(path);
+}
+
QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
@@ -1026,7 +1034,7 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
if (index < 0)
index = -index - 1;
- if (path.count() > 1) {
+ if (path.size() > 1) {
QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != nullptr);
return item.subinfo->plug(path.mid(1));
@@ -1045,7 +1053,7 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
Q_ASSERT(!path.isEmpty());
const int index = path.first();
- if (path.count() > 1) {
+ if (path.size() > 1) {
QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != nullptr);
return item.subinfo->unplug(path.mid(1));
@@ -1122,6 +1130,21 @@ static QRect dockedGeometry(QWidget *widget)
return result;
}
+bool QDockAreaLayoutInfo::hasGapItem(const QList<int> &path) const
+{
+ // empty path has no gap item
+ if (path.isEmpty())
+ return false;
+
+ // Index -1 isn't a gap
+ // Index out of range points at a position to be created. That isn't a gap either.
+ const int index = path.constFirst();
+ if (index < 0 || index >= item_list.count())
+ return false;
+
+ return item_list[index].flags & QDockAreaLayoutItem::GapItem;
+}
+
bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
{
Q_ASSERT(!path.isEmpty());
@@ -1133,9 +1156,7 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
index = -index - 1;
}
-// dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
-
- if (path.count() > 1) {
+ if (path.size() > 1) {
QDockAreaLayoutItem &item = item_list[index];
if (item.subinfo == nullptr
@@ -1217,12 +1238,14 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
break;
}
} else {
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
continue;
- Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
+ Q_ASSERT_X(!(item.flags & QDockAreaLayoutItem::GapItem),
+ "QDockAreaLayoutInfo::insertGap", "inserting two gaps after each other");
space += item.size - pick(o, item.minimumSize());
+ qCDebug(lcQpaDockWidgets) << "Item space:" << item.flags << this;
}
}
@@ -1247,15 +1270,14 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
// finally, insert the gap
item_list.insert(index, gap_item);
-
-// dump(qDebug() << "insertGap() after:" << index << tabIndex, *this, QString());
+ qCDebug(lcQpaDockWidgets) << "Insert gap after:" << index << this;
return true;
}
QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
{
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
continue;
@@ -1282,9 +1304,9 @@ QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
int index = path.first();
if (index < 0)
index = -index - 1;
- if (index >= item_list.count())
+ if (index >= item_list.size())
return this;
- if (path.count() == 1 || item_list[index].subinfo == nullptr)
+ if (path.size() == 1 || item_list[index].subinfo == nullptr)
return this;
return item_list[index].subinfo->info(path.mid(1));
}
@@ -1339,7 +1361,7 @@ QRect QDockAreaLayoutInfo::itemRect(const QList<int> &path) const
Q_ASSERT(!path.isEmpty());
const int index = path.first();
- if (path.count() > 1) {
+ if (path.size() > 1) {
const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != nullptr);
return item.subinfo->itemRect(path.mid(1));
@@ -1372,7 +1394,7 @@ QRect QDockAreaLayoutInfo::separatorRect(const QList<int> &path) const
Q_ASSERT(!path.isEmpty());
const int index = path.first();
- if (path.count() > 1) {
+ if (path.size() > 1) {
const QDockAreaLayoutItem &item = item_list.at(index);
Q_ASSERT(item.subinfo != nullptr);
return item.subinfo->separatorRect(path.mid(1));
@@ -1597,7 +1619,7 @@ QRegion QDockAreaLayoutInfo::separatorRegion() const
return result;
#endif
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -1627,7 +1649,7 @@ void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
return;
#endif
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -1712,7 +1734,7 @@ QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
{
Q_ASSERT(!path.isEmpty());
const int index = path.first();
- if (path.count() > 1) {
+ if (path.size() > 1) {
const QDockAreaLayoutItem &item = item_list[index];
Q_ASSERT(item.subinfo != nullptr);
return item.subinfo->item(path.mid(1));
@@ -1722,7 +1744,7 @@ QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
{
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.placeHolderItem != nullptr)
continue;
@@ -1739,7 +1761,7 @@ QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
{
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.placeHolderItem != nullptr)
continue;
@@ -1762,9 +1784,29 @@ QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
return nullptr;
}
+// Add a dock widget or dock widget group window to the item list
+void QDockAreaLayoutInfo::add(QWidget *widget)
+{
+ // Do not add twice
+ if (!indexOf(widget).isEmpty())
+ return;
+
+ if (auto *dockWidget = qobject_cast<QDockWidget *>(widget)) {
+ item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(dockWidget)));
+ return;
+ }
+
+ if (auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+ item_list.append(QDockAreaLayoutItem(new QDockWidgetGroupWindowItem(groupWindow)));
+ return;
+ }
+
+ qFatal("Coding error. Add supports only QDockWidget and QDockWidgetGroupWindow");
+}
+
void QDockAreaLayoutInfo::deleteAllLayoutItems()
{
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item= item_list[i];
if (item.subinfo) {
item.subinfo->deleteAllLayoutItems();
@@ -1784,7 +1826,7 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
// write the index in item_list of the widget that's currently on top.
quintptr id = currentTabId();
int index = -1;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
if (tabId(item_list.at(i)) == id) {
index = i;
break;
@@ -1797,9 +1839,9 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
stream << (uchar) SequenceMarker;
}
- stream << (uchar) o << item_list.count();
+ stream << (uchar) o << int(item_list.size());
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.widgetItem != nullptr) {
stream << (uchar) WidgetMarker;
@@ -1895,7 +1937,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
}
QDockWidget *widget = nullptr;
- for (int j = 0; j < widgets.count(); ++j) {
+ for (int j = 0; j < widgets.size(); ++j) {
if (widgets.at(j)->objectName() == name) {
widget = widgets.takeAt(j);
break;
@@ -1955,6 +1997,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
if (testing) {
//was it is not really added to the layout, we need to delete the object here
delete item.widgetItem;
+ item.widgetItem = nullptr;
}
}
} else if (nextMarker == SequenceMarker) {
@@ -1981,7 +2024,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
}
#if QT_CONFIG(tabbar)
- if (!testing && tabbed && index >= 0 && index < item_list.count()) {
+ if (!testing && tabbed && index >= 0 && index < item_list.size()) {
updateTabBar();
setCurrentTabId(tabId(item_list.at(index)));
}
@@ -2001,7 +2044,7 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
}
int j = 0;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -2020,14 +2063,20 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
break;
QWidget *sepWidget;
- if (j < separatorWidgets.size() && separatorWidgets.at(j)) {
+ if (j < separatorWidgets.size()) {
sepWidget = separatorWidgets.at(j);
+ if (!sepWidget) {
+ qWarning("QDockAreaLayoutInfo::updateSeparatorWidgets: null separator widget");
+ sepWidget = mainWindowLayout()->getSeparatorWidget();
+ separatorWidgets[j] = sepWidget;
+ }
} else {
sepWidget = mainWindowLayout()->getSeparatorWidget();
separatorWidgets.append(sepWidget);
}
j++;
+ Q_ASSERT(sepWidget);
sepWidget->raise();
QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
@@ -2040,7 +2089,6 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
separatorWidgets[k]->hide();
}
separatorWidgets.resize(j);
- Q_ASSERT(separatorWidgets.size() == j);
}
/*! \internal
@@ -2053,7 +2101,7 @@ void QDockAreaLayoutInfo::reparentWidgets(QWidget *parent)
if (tabBar)
tabBar->setParent(parent);
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.flags & QDockAreaLayoutItem::GapItem)
continue;
@@ -2093,7 +2141,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const
const quintptr oldCurrentId = currentTabId();
int tab_idx = 0;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
continue;
@@ -2109,7 +2157,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const
quintptr id = tabId(item);
if (tab_idx == tabBar->count()) {
tabBar->insertTab(tab_idx, title);
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
tabBar->setTabToolTip(tab_idx, title);
#endif
tabBar->setTabData(tab_idx, id);
@@ -2119,7 +2167,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const
tabBar->removeTab(tab_idx);
else {
tabBar->insertTab(tab_idx, title);
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
tabBar->setTabToolTip(tab_idx, title);
#endif
tabBar->setTabData(tab_idx, id);
@@ -2128,7 +2176,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const
if (title != tabBar->tabText(tab_idx)) {
tabBar->setTabText(tab_idx, title);
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
tabBar->setTabToolTip(tab_idx, title);
#endif
}
@@ -2158,7 +2206,7 @@ void QDockAreaLayoutInfo::setTabBarShape(int shape)
if (tabBar != nullptr)
tabBar->setShape(static_cast<QTabBar::Shape>(shape));
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.subinfo != nullptr)
item.subinfo->setTabBarShape(shape);
@@ -2190,7 +2238,7 @@ QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
result.insert(tabBar);
}
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.subinfo != nullptr)
result += item.subinfo->usedTabBars();
@@ -2204,13 +2252,13 @@ QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- const int numSeparatorWidgets = separatorWidgets.count();
+ const int numSeparatorWidgets = separatorWidgets.size();
result.reserve(numSeparatorWidgets);
for (int i = 0; i < numSeparatorWidgets; ++i)
result << separatorWidgets.at(i);
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.subinfo != nullptr)
result += item.subinfo->usedSeparatorWidgets();
@@ -2257,7 +2305,7 @@ int QDockAreaLayoutInfo::tabIndexToListIndex(int tabIndex) const
{
Q_ASSERT(tabbed && tabBar);
quintptr data = qvariant_cast<quintptr>(tabBar->tabData(tabIndex));
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
if (tabId(item_list.at(i)) == data)
return i;
}
@@ -2427,23 +2475,7 @@ QList<int> QDockAreaLayout::gapIndex(const QPoint &pos, bool disallowTabs) const
const QDockAreaLayoutInfo &info = docks[i];
if (info.isEmpty()) {
- QRect r;
- switch (i) {
- case QInternal::LeftDock:
- r = QRect(rect.left(), rect.top(), EmptyDropAreaSize, rect.height());
- break;
- case QInternal::RightDock:
- r = QRect(rect.right() - EmptyDropAreaSize, rect.top(),
- EmptyDropAreaSize, rect.height());
- break;
- case QInternal::TopDock:
- r = QRect(rect.left(), rect.top(), rect.width(), EmptyDropAreaSize);
- break;
- case QInternal::BottomDock:
- r = QRect(rect.left(), rect.bottom() - EmptyDropAreaSize,
- rect.width(), EmptyDropAreaSize);
- break;
- }
+ const QRect r = gapRect(static_cast<QInternal::DockPosition>(i));
if (r.contains(pos)) {
if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
//in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
@@ -2459,6 +2491,43 @@ QList<int> QDockAreaLayout::gapIndex(const QPoint &pos, bool disallowTabs) const
return QList<int>();
}
+QRect QDockAreaLayout::gapRect(QInternal::DockPosition dockPos) const
+{
+ Q_ASSERT_X(mainWindow, "QDockAreaLayout::gapRect", "Called without valid mainWindow pointer.");
+
+ // Determine gap size depending on MainWindow size (QTBUG-101657)
+ const QSize gapSize = (mainWindow->size()/2).boundedTo(QSize(EmptyDropAreaSize, EmptyDropAreaSize));
+
+ // Warn if main window is too small to create proper docks.
+ // Do not fail because this can be triggered by a user making MainWindow too small
+ if (mainWindow->height() < (2 * sep)) {
+ qCWarning(lcQpaDockWidgets,
+ "QDockAreaLayout::gapRect: Main window height %i is too small. Docking will not be possible.",
+ mainWindow->height());
+
+ }
+ if (mainWindow->width() < (2 * sep)) {
+ qCWarning(lcQpaDockWidgets,
+ "QDockAreaLayout::gapRect: Main window width %i is too small. Docking will not be possible.",
+ mainWindow->width());
+ }
+
+ // Calculate rectangle of requested dock
+ switch (dockPos) {
+ case QInternal::LeftDock:
+ return QRect(rect.left(), rect.top(), gapSize.width(), rect.height());
+ case QInternal::RightDock:
+ return QRect(rect.right() - gapSize.width(), rect.top(), gapSize.width(), rect.height());
+ case QInternal::TopDock:
+ return QRect(rect.left(), rect.top(), rect.width(), gapSize.height());
+ case QInternal::BottomDock:
+ return QRect(rect.left(), rect.bottom() - gapSize.height(), rect.width(), gapSize.height());
+ case QInternal::DockCount:
+ break;
+ }
+ return QRect();
+}
+
QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
{
QList<int> result;
@@ -2500,7 +2569,7 @@ QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path)
const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- if (path.count() == 1)
+ if (path.size() == 1)
return &docks[index];
return docks[index].info(path.mid(1));
@@ -2555,7 +2624,7 @@ QRect QDockAreaLayout::separatorRect(const QList<int> &path) const
const int index = path.first();
Q_ASSERT(index >= 0 && index < QInternal::DockCount);
- if (path.count() == 1)
+ if (path.size() == 1)
return separatorRect(index);
else
return docks[index].separatorRect(path.mid(1));
@@ -2605,7 +2674,7 @@ void QDockAreaLayout::removePlaceHolder(const QString &name)
if (!index.isEmpty())
remove(index);
const auto groups =
- mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+ mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups) {
index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
if (!index.isEmpty()) {
@@ -2617,8 +2686,8 @@ void QDockAreaLayout::removePlaceHolder(const QString &name)
static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
-void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
- QVector<QLayoutStruct> *_hor_struct_list)
+void QDockAreaLayout::getGrid(QList<QLayoutStruct> *_ver_struct_list,
+ QList<QLayoutStruct> *_hor_struct_list)
{
QSize center_hint(0, 0);
QSize center_min(0, 0);
@@ -2671,7 +2740,7 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
if (_ver_struct_list != nullptr) {
- QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
+ QList<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
ver_struct_list.resize(3);
// top --------------------------------------------------
@@ -2733,7 +2802,7 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
}
if (_hor_struct_list != nullptr) {
- QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
+ QList<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
hor_struct_list.resize(3);
// left --------------------------------------------------
@@ -2795,8 +2864,8 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
}
}
-void QDockAreaLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
- QVector<QLayoutStruct> *hor_struct_list)
+void QDockAreaLayout::setGrid(QList<QLayoutStruct> *ver_struct_list,
+ QList<QLayoutStruct> *hor_struct_list)
{
// top ---------------------------------------------------
@@ -2893,8 +2962,8 @@ void QDockAreaLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
void QDockAreaLayout::fitLayout()
{
- QVector<QLayoutStruct> ver_struct_list(3);
- QVector<QLayoutStruct> hor_struct_list(3);
+ QList<QLayoutStruct> ver_struct_list(3);
+ QList<QLayoutStruct> hor_struct_list(3);
getGrid(&ver_struct_list, &hor_struct_list);
qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
@@ -2912,7 +2981,8 @@ void QDockAreaLayout::clear()
centralWidgetRect = QRect();
}
-QSize QDockAreaLayout::sizeHint() const
+template<typename SizePMF, typename CenterPMF>
+QSize QDockAreaLayout::size_helper(SizePMF sizeFn, CenterPMF centerFn) const
{
int left_sep = 0;
int right_sep = 0;
@@ -2926,11 +2996,12 @@ QSize QDockAreaLayout::sizeHint() const
bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
}
- QSize left = docks[QInternal::LeftDock].sizeHint() + QSize(left_sep, 0);
- QSize right = docks[QInternal::RightDock].sizeHint() + QSize(right_sep, 0);
- QSize top = docks[QInternal::TopDock].sizeHint() + QSize(0, top_sep);
- QSize bottom = docks[QInternal::BottomDock].sizeHint() + QSize(0, bottom_sep);
- QSize center = centralWidgetItem == nullptr ? QSize(0, 0) : centralWidgetItem->sizeHint();
+ const QSize left = (docks[QInternal::LeftDock].*sizeFn)() + QSize(left_sep, 0);
+ const QSize right = (docks[QInternal::RightDock].*sizeFn)() + QSize(right_sep, 0);
+ const QSize top = (docks[QInternal::TopDock].*sizeFn)() + QSize(0, top_sep);
+ const QSize bottom = (docks[QInternal::BottomDock].*sizeFn)() + QSize(0, bottom_sep);
+ const QSize center = centralWidgetItem == nullptr
+ ? QSize(0, 0) : (centralWidgetItem->*centerFn)();
int row1 = top.width();
int row2 = left.width() + center.width() + right.width();
@@ -2962,54 +3033,24 @@ QSize QDockAreaLayout::sizeHint() const
return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
}
-QSize QDockAreaLayout::minimumSize() const
+QSize QDockAreaLayout::sizeHint() const
{
- int left_sep = 0;
- int right_sep = 0;
- int top_sep = 0;
- int bottom_sep = 0;
-
- if (centralWidgetItem != nullptr) {
- left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
- right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
- top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
- bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
- }
-
- QSize left = docks[QInternal::LeftDock].minimumSize() + QSize(left_sep, 0);
- QSize right = docks[QInternal::RightDock].minimumSize() + QSize(right_sep, 0);
- QSize top = docks[QInternal::TopDock].minimumSize() + QSize(0, top_sep);
- QSize bottom = docks[QInternal::BottomDock].minimumSize() + QSize(0, bottom_sep);
- QSize center = centralWidgetItem == nullptr ? QSize(0, 0) : centralWidgetItem->minimumSize();
-
- int row1 = top.width();
- int row2 = left.width() + center.width() + right.width();
- int row3 = bottom.width();
- int col1 = left.height();
- int col2 = top.height() + center.height() + bottom.height();
- int col3 = right.height();
-
- if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
- row1 += left.width();
- else
- col1 += top.height();
-
- if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
- row1 += right.width();
- else
- col3 += top.height();
+ return size_helper(&QDockAreaLayoutInfo::sizeHint, &QLayoutItem::sizeHint);
+}
- if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
- row3 += left.width();
- else
- col1 += bottom.height();
+QSize QDockAreaLayout::minimumSize() const
+{
+ return size_helper(&QDockAreaLayoutInfo::minimumSize, &QLayoutItem::minimumSize);
+}
- if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
- row3 += right.width();
- else
- col3 += bottom.height();
+/*!
+ \internal
- return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
+ Returns the smallest size that doesn't change the size of any of the dock areas.
+*/
+QSize QDockAreaLayout::minimumStableSize() const
+{
+ return size_helper(&QDockAreaLayoutInfo::size, &QLayoutItem::minimumSize);
}
/*! \internal
@@ -3020,19 +3061,20 @@ QSize QDockAreaLayout::minimumSize() const
*/
QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
{
- QRect desktop;
- if (QDesktopWidgetPrivate::isVirtualDesktop())
- desktop = QDesktopWidgetPrivate::screenGeometry(rect.topLeft());
- else
- desktop = QDesktopWidgetPrivate::screenGeometry(widget);
+ QScreen *screen = nullptr;
+ if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
+ screen = QGuiApplication::screenAt(rect.topLeft());
+ if (!screen)
+ screen = widget->screen();
- if (desktop.isValid()) {
- rect.setWidth(qMin(rect.width(), desktop.width()));
- rect.setHeight(qMin(rect.height(), desktop.height()));
- rect.moveLeft(qMax(rect.left(), desktop.left()));
- rect.moveTop(qMax(rect.top(), desktop.top()));
- rect.moveRight(qMin(rect.right(), desktop.right()));
- rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
+ const QRect screenRect = screen->geometry();
+ if (screenRect.isValid()) {
+ rect.setWidth(qMin(rect.width(), screenRect.width()));
+ rect.setHeight(qMin(rect.height(), screenRect.height()));
+ rect.moveLeft(qMax(rect.left(), screenRect.left()));
+ rect.moveTop(qMax(rect.top(), screenRect.top()));
+ rect.moveRight(qMin(rect.right(), screenRect.right()));
+ rect.moveBottom(qMin(rect.bottom(), screenRect.bottom()));
}
return rect;
@@ -3042,7 +3084,7 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
{
QDockAreaLayoutItem *item = nullptr;
const auto groups =
- mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+ mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups) {
QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty()) {
@@ -3080,7 +3122,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
{
QLayoutItem *dockWidgetItem = new QDockWidgetItem(dockWidget);
QDockAreaLayoutInfo &info = docks[pos];
- if (orientation == info.o || info.item_list.count() <= 1) {
+ if (orientation == info.o || info.item_list.size() <= 1) {
// empty dock areas, or dock areas containing exactly one widget can have their orientation
// switched.
info.o = orientation;
@@ -3126,11 +3168,11 @@ void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation o)
{
- if (Q_UNLIKELY(docks.count() != sizes.count())) {
+ if (Q_UNLIKELY(docks.size() != sizes.size())) {
qWarning("QMainWidget::resizeDocks: size of the lists are not the same");
return;
}
- int count = docks.count();
+ int count = docks.size();
fallbackToSizeHints = false;
for (int i = 0; i < count; ++i) {
QList<int> path = indexOf(docks[i]);
@@ -3150,7 +3192,7 @@ void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
if (!info->tabbed && info->o == o) {
info->item_list[path.constLast()].size = size;
int totalSize = 0;
- for (const QDockAreaLayoutItem &item : qAsConst(info->item_list)) {
+ for (const QDockAreaLayoutItem &item : std::as_const(info->item_list)) {
if (!item.skip()) {
if (totalSize != 0)
totalSize += sep;
@@ -3243,7 +3285,7 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or
int delta = 0;
int index = separator.last();
- if (separator.count() > 1) {
+ if (separator.size() > 1) {
QDockAreaLayoutInfo *info = this->info(separator);
delta = pick(info->o, dest - origin);
if (delta != 0)
@@ -3252,7 +3294,7 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or
return delta;
}
- QVector<QLayoutStruct> list;
+ QList<QLayoutStruct> list;
if (index == QInternal::LeftDock || index == QInternal::RightDock)
getGrid(nullptr, &list);
@@ -3295,7 +3337,7 @@ int QDockAreaLayoutInfo::separatorMove(const QList<int> &separator, const QPoint
#if QT_CONFIG(tabbar)
// Sets the correct positions for the separator widgets
-// Allocates new sepearator widgets with getSeparatorWidget
+// Allocates new separator widgets with getSeparatorWidget
void QDockAreaLayout::updateSeparatorWidgets() const
{
int j = 0;
@@ -3308,12 +3350,18 @@ void QDockAreaLayout::updateSeparatorWidgets() const
QWidget *sepWidget;
if (j < separatorWidgets.size()) {
sepWidget = separatorWidgets.at(j);
+ if (!sepWidget) {
+ qWarning("QDockAreaLayout::updateSeparatorWidgets: null separator widget");
+ sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
+ separatorWidgets[j] = sepWidget;
+ }
} else {
sepWidget = qt_mainwindow_layout(mainWindow)->getSeparatorWidget();
separatorWidgets.append(sepWidget);
}
j++;
+ Q_ASSERT(sepWidget);
sepWidget->raise();
QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
@@ -3384,7 +3432,7 @@ QSet<QTabBar*> QDockAreaLayout::usedTabBars() const
QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- const int numSeparators = separatorWidgets.count();
+ const int numSeparators = separatorWidgets.size();
result.reserve(numSeparators);
for (int i = 0; i < numSeparators; ++i)
result << separatorWidgets.at(i);
@@ -3402,7 +3450,7 @@ QRect QDockAreaLayout::gapRect(const QList<int> &path) const
if (info == nullptr)
return QRect();
int index = path.last();
- if (index < 0 || index >= info->item_list.count())
+ if (index < 0 || index >= info->item_list.size())
return QRect();
return info->itemRect(index, true);
}
diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h
index 81384bd1b7..aa39bf9913 100644
--- a/src/widgets/widgets/qdockarealayout_p.h
+++ b/src/widgets/widgets/qdockarealayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDOCKAREALAYOUT_P_H
#define QDOCKAREALAYOUT_P_H
@@ -52,11 +16,9 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include "QtCore/qrect.h"
-#include "QtCore/qpair.h"
-#include "QtCore/qlist.h"
-#include "QtCore/qvector.h"
#include "QtWidgets/qlayout.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qrect.h"
QT_REQUIRE_CONFIG(dockwidget);
@@ -85,7 +47,7 @@ class QTabBar;
// A path indetifies uniquely one object in this tree, the first number being the side and all the following
// indexes into the QDockAreaLayoutInfo::item_list.
-struct QDockAreaLayoutItem
+struct Q_AUTOTEST_EXPORT QDockAreaLayoutItem
{
enum ItemFlags { NoFlags = 0, GapItem = 1, KeepSize = 2 };
@@ -110,6 +72,10 @@ struct QDockAreaLayoutItem
int pos;
int size;
uint flags;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_AUTOTEST_EXPORT QDebug operator<<(QDebug dbg, const QDockAreaLayoutItem &item);
+ friend Q_AUTOTEST_EXPORT QDebug operator<<(QDebug dbg, const QDockAreaLayoutItem *item);
+#endif
};
class Q_AUTOTEST_EXPORT QPlaceHolderItem
@@ -142,6 +108,7 @@ public:
QList<int> gapIndex(const QPoint &pos, bool nestingEnabled,
TabMode tabMode) const;
void remove(const QList<int> &path);
+ void remove(QWidget *widget);
void unnest(int index);
void split(int index, Qt::Orientation orientation, QLayoutItem *dockWidgetItem);
#if QT_CONFIG(tabbar)
@@ -169,6 +136,7 @@ public:
void clear();
bool isEmpty() const;
+ bool hasGapItem(const QList<int> &path) const;
bool onlyHasPlaceholders() const;
bool hasFixedSize() const;
QList<int> findSeparator(const QPoint &pos) const;
@@ -188,12 +156,13 @@ public:
QLayoutItem *itemAt(int *x, int index) const;
QLayoutItem *takeAt(int *x, int index);
+ void add(QWidget *widget);
void deleteAllLayoutItems();
QMainWindowLayout *mainWindowLayout() const;
const int *sep;
- mutable QVector<QWidget*> separatorWidgets;
+ mutable QList<QWidget *> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
QRect rect;
@@ -236,9 +205,9 @@ public:
QRect centralWidgetRect;
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
- int sep; // separator extent
+ int sep; // margin between a dock widget and its frame
bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the separator is moved by user)
- mutable QVector<QWidget*> separatorWidgets;
+ mutable QList<QWidget *> separatorWidgets;
bool isValid() const;
@@ -272,6 +241,9 @@ public:
QSize sizeHint() const;
QSize minimumSize() const;
+ QSize minimumStableSize() const;
+ template<typename SizePMF, typename CenterPMF>
+ QSize size_helper(SizePMF sizeFn, CenterPMF centerFn) const;
void addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget, Qt::Orientation orientation);
bool restoreDockWidget(QDockWidget *dockWidget);
@@ -296,12 +268,11 @@ public:
QLayoutItem *takeAt(int *x, int index);
void deleteAllLayoutItems();
- void getGrid(QVector<QLayoutStruct> *ver_struct_list,
- QVector<QLayoutStruct> *hor_struct_list);
- void setGrid(QVector<QLayoutStruct> *ver_struct_list,
- QVector<QLayoutStruct> *hor_struct_list);
+ void getGrid(QList<QLayoutStruct> *ver_struct_list, QList<QLayoutStruct> *hor_struct_list);
+ void setGrid(QList<QLayoutStruct> *ver_struct_list, QList<QLayoutStruct> *hor_struct_list);
QRect gapRect(const QList<int> &path) const;
+ QRect gapRect(QInternal::DockPosition dockPos) const;
void keepSize(QDockWidget *w);
#if QT_CONFIG(tabbar)
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 299e5da8d3..706306000c 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1,47 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdockwidget.h"
#include <qaction.h>
#include <qapplication.h>
-#include <qdesktopwidget.h>
#include <qdrawutil.h>
#include <qevent.h>
#include <qfontmetrics.h>
@@ -57,11 +20,14 @@
#include <private/qstylesheetstyle_p.h>
#include <qpa/qplatformtheme.h>
+#include <private/qhighdpiscaling_p.h>
#include "qdockwidget_p.h"
#include "qmainwindowlayout_p.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); // qwidget.cpp
// qmainwindow.cpp
@@ -130,7 +96,7 @@ public:
QSize minimumSizeHint() const override
{ return sizeHint(); }
- void enterEvent(QEvent *event) override;
+ void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
@@ -153,7 +119,7 @@ bool QDockWidgetTitleButton::event(QEvent *event)
{
switch (event->type()) {
case QEvent::StyleChange:
- case QEvent::ScreenChangeInternal:
+ case QEvent::DevicePixelRatioChange:
m_iconSize = -1;
break;
default:
@@ -162,33 +128,12 @@ bool QDockWidgetTitleButton::event(QEvent *event)
return QAbstractButton::event(event);
}
-static inline bool isWindowsStyle(const QStyle *style)
-{
- // Note: QStyleSheetStyle inherits QWindowsStyle
- const QStyle *effectiveStyle = style;
-
-#if QT_CONFIG(style_stylesheet)
- if (style->inherits("QStyleSheetStyle"))
- effectiveStyle = static_cast<const QStyleSheetStyle *>(style)->baseStyle();
-#endif
-#if !defined(QT_NO_STYLE_PROXY)
- if (style->inherits("QProxyStyle"))
- effectiveStyle = static_cast<const QProxyStyle *>(style)->baseStyle();
-#endif
-
- return effectiveStyle->inherits("QWindowsStyle");
-}
-
QSize QDockWidgetTitleButton::dockButtonIconSize() const
{
if (m_iconSize < 0) {
m_iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this);
- // Dock Widget title buttons on Windows where historically limited to size 10
- // (from small icon size 16) since only a 10x10 XPM was provided.
- // Adding larger pixmaps to the icons thus caused the icons to grow; limit
- // this to qpiScaled(10) here.
- if (isWindowsStyle(style()))
- m_iconSize = qMin((10 * logicalDpiX()) / 96, m_iconSize);
+ if (style()->styleHint(QStyle::SH_DockWidget_ButtonsHaveFrame, nullptr, this))
+ m_iconSize = (m_iconSize * 5) / 8; // 16 -> 10
}
return QSize(m_iconSize, m_iconSize);
}
@@ -206,7 +151,7 @@ QSize QDockWidgetTitleButton::sizeHint() const
return QSize(size, size);
}
-void QDockWidgetTitleButton::enterEvent(QEvent *event)
+void QDockWidgetTitleButton::enterEvent(QEnterEvent *event)
{
if (isEnabled()) update();
QAbstractButton::enterEvent(event);
@@ -220,21 +165,23 @@ void QDockWidgetTitleButton::leaveEvent(QEvent *event)
void QDockWidgetTitleButton::paintEvent(QPaintEvent *)
{
- QPainter p(this);
+ QStylePainter p(this);
QStyleOptionToolButton opt;
- opt.init(this);
+ opt.initFrom(this);
opt.state |= QStyle::State_AutoRaise;
- if (style()->styleHint(QStyle::SH_DockWidget_ButtonsHaveFrame, nullptr, this))
- {
+ if (style()->styleHint(QStyle::SH_DockWidget_ButtonsHaveFrame, nullptr, this)) {
if (isEnabled() && underMouse() && !isChecked() && !isDown())
opt.state |= QStyle::State_Raised;
if (isChecked())
opt.state |= QStyle::State_On;
if (isDown())
opt.state |= QStyle::State_Sunken;
- style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &p, this);
+ p.drawPrimitive(QStyle::PE_PanelButtonTool, opt);
+ } else if (isDown() || isChecked()) {
+ // no frame, but the icon might have explicit pixmaps for QIcon::On
+ opt.state |= QStyle::State_On | QStyle::State_Sunken;
}
opt.icon = icon();
@@ -243,7 +190,7 @@ void QDockWidgetTitleButton::paintEvent(QPaintEvent *)
opt.features = QStyleOptionToolButton::None;
opt.arrowType = Qt::NoArrow;
opt.iconSize = dockButtonIconSize();
- style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &p, this);
+ p.drawComplexControl(QStyle::CC_ToolButton, opt);
}
/******************************************************************************
@@ -284,8 +231,10 @@ bool QDockWidgetLayout::wmSupportsNativeWindowDeco()
#if defined(Q_OS_ANDROID)
return false;
#else
- static const bool xcb = !QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive);
- return !xcb;
+ static const bool xcb = !QGuiApplication::platformName().compare("xcb"_L1, Qt::CaseInsensitive);
+ static const bool wayland =
+ QGuiApplication::platformName().startsWith("wayland"_L1, Qt::CaseInsensitive);
+ return !(xcb || wayland);
#endif
}
@@ -296,7 +245,7 @@ bool QDockWidgetLayout::wmSupportsNativeWindowDeco()
*/
bool QDockWidgetLayout::nativeWindowDeco(bool floating) const
{
- return wmSupportsNativeWindowDeco() && floating && item_list.at(QDockWidgetLayout::TitleBar) == 0;
+ return wmSupportsNativeWindowDeco() && floating && item_list.at(QDockWidgetLayout::TitleBar) == nullptr;
}
@@ -309,7 +258,7 @@ void QDockWidgetLayout::addItem(QLayoutItem*)
QLayoutItem *QDockWidgetLayout::itemAt(int index) const
{
int cnt = 0;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
QLayoutItem *item = item_list.at(i);
if (item == nullptr)
continue;
@@ -322,7 +271,7 @@ QLayoutItem *QDockWidgetLayout::itemAt(int index) const
QLayoutItem *QDockWidgetLayout::takeAt(int index)
{
int j = 0;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
QLayoutItem *item = item_list.at(i);
if (item == nullptr)
continue;
@@ -339,7 +288,7 @@ QLayoutItem *QDockWidgetLayout::takeAt(int index)
int QDockWidgetLayout::count() const
{
int result = 0;
- for (int i = 0; i < item_list.count(); ++i) {
+ for (int i = 0; i < item_list.size(); ++i) {
if (item_list.at(i))
++result;
}
@@ -658,13 +607,14 @@ void QDockWidgetPrivate::init()
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
QAbstractButton *button = new QDockWidgetTitleButton(q);
- button->setObjectName(QLatin1String("qt_dockwidget_floatbutton"));
- QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_toggleTopLevel()));
+ button->setObjectName("qt_dockwidget_floatbutton"_L1);
+ QObjectPrivate::connect(button, &QAbstractButton::clicked,
+ this, &QDockWidgetPrivate::toggleTopLevel);
layout->setWidgetForRole(QDockWidgetLayout::FloatButton, button);
button = new QDockWidgetTitleButton(q);
- button->setObjectName(QLatin1String("qt_dockwidget_closebutton"));
- QObject::connect(button, SIGNAL(clicked()), q, SLOT(close()));
+ button->setObjectName("qt_dockwidget_closebutton"_L1);
+ QObject::connect(button, &QAbstractButton::clicked, q, &QDockWidget::close);
layout->setWidgetForRole(QDockWidgetLayout::CloseButton, button);
font = QApplication::font("QDockWidgetTitle");
@@ -675,8 +625,8 @@ void QDockWidgetPrivate::init()
toggleViewAction->setMenuRole(QAction::NoRole);
fixedWindowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q);
toggleViewAction->setText(fixedWindowTitle);
- QObject::connect(toggleViewAction, SIGNAL(triggered(bool)),
- q, SLOT(_q_toggleView(bool)));
+ QObjectPrivate::connect(toggleViewAction, &QAction::triggered,
+ this, &QDockWidgetPrivate::toggleView);
#endif
updateButtons();
@@ -711,7 +661,7 @@ void QDockWidget::initStyleOption(QStyleOptionDockWidget *option) const
option->verticalTitleBar = l->verticalTitleBar;
}
-void QDockWidgetPrivate::_q_toggleView(bool b)
+void QDockWidgetPrivate::toggleView(bool b)
{
Q_Q(QDockWidget);
if (b == q->isHidden()) {
@@ -741,7 +691,7 @@ void QDockWidgetPrivate::updateButtons()
= qobject_cast<QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
button->setVisible(canFloat && !hideButtons);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
//: Accessible name for button undocking a dock widget (floating state)
button->setAccessibleName(QDockWidget::tr("Float"));
button->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget"));
@@ -750,18 +700,16 @@ void QDockWidgetPrivate::updateButtons()
= qobject_cast <QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::CloseButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
button->setVisible(canClose && !hideButtons);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
//: Accessible name for button closing a dock widget
button->setAccessibleName(QDockWidget::tr("Close"));
button->setAccessibleDescription(QDockWidget::tr("Closes the dock widget"));
#endif
- q->setAttribute(Qt::WA_ContentsPropagated,
- (canFloat || canClose) && !hideButtons);
layout->invalidate();
}
-void QDockWidgetPrivate::_q_toggleTopLevel()
+void QDockWidgetPrivate::toggleTopLevel()
{
Q_Q(QDockWidget);
q->setFloating(!q->isFloating());
@@ -787,6 +735,8 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
state = new QDockWidgetPrivate::DragState;
state->pressPos = pos;
+ state->globalPressPos = q->mapToGlobal(pos);
+ state->widgetInitialPos = q->isFloating() ? q->pos() : q->mapToGlobal(QPoint(0, 0));
state->dragging = false;
state->widgetItem = nullptr;
state->ownWidgetItem = false;
@@ -800,7 +750,7 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
tabbed widgets, and false if the dock widget should always be dragged
alone.
*/
-void QDockWidgetPrivate::startDrag(bool group)
+void QDockWidgetPrivate::startDrag(DragScope scope)
{
Q_Q(QDockWidget);
@@ -810,12 +760,16 @@ void QDockWidgetPrivate::startDrag(bool group)
QMainWindowLayout *layout = qt_mainwindow_layout_from_dock(q);
Q_ASSERT(layout != nullptr);
- state->widgetItem = layout->unplug(q, group);
+#if QT_CONFIG(draganddrop)
+ bool wasFloating = q->isFloating();
+#endif
+
+ state->widgetItem = layout->unplug(q, scope);
if (state->widgetItem == nullptr) {
- /* I have a QMainWindow parent, but I was never inserted with
+ /* Dock widget has a QMainWindow parent, but was never inserted with
QMainWindow::addDockWidget, so the QMainWindowLayout has no
- widget item for me. :( I have to create it myself, and then
- delete it if I don't get dropped into a dock area. */
+ widget item for it. It will be newly created and deleted if it doesn't
+ get dropped into a dock area. */
QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
if (floatingTab && !q->isFloating())
state->widgetItem = new QDockWidgetGroupWindowItem(floatingTab);
@@ -828,6 +782,20 @@ void QDockWidgetPrivate::startDrag(bool group)
layout->restore();
state->dragging = true;
+
+#if QT_CONFIG(draganddrop)
+ if (QMainWindowLayout::needsPlatformDrag()) {
+ Qt::DropAction result =
+ layout->performPlatformWidgetDrag(state->widgetItem, state->pressPos);
+ if (result == Qt::IgnoreAction && !wasFloating) {
+ layout->revert(state->widgetItem);
+ delete state;
+ state = nullptr;
+ } else {
+ endDrag(QDockWidgetPrivate::EndDragMode::LocationChange);
+ }
+ }
+#endif
}
/*! \internal
@@ -835,7 +803,7 @@ void QDockWidgetPrivate::startDrag(bool group)
The \a abort parameter specifies that it ends because of programmatic state
reset rather than mouse release event.
*/
-void QDockWidgetPrivate::endDrag(bool abort)
+void QDockWidgetPrivate::endDrag(EndDragMode mode)
{
Q_Q(QDockWidget);
Q_ASSERT(state != nullptr);
@@ -847,7 +815,11 @@ void QDockWidgetPrivate::endDrag(bool abort)
Q_ASSERT(mainWindow != nullptr);
QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
- if (abort || !mwLayout->plug(state->widgetItem)) {
+ // if mainWindow is being deleted in an ongoing drag, make it a no-op instead of crashing
+ if (!mwLayout)
+ return;
+
+ if (mode == EndDragMode::Abort || !mwLayout->plug(state->widgetItem)) {
if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
// This QDockWidget will now stay in the floating state.
if (state->ownWidgetItem) {
@@ -869,8 +841,21 @@ void QDockWidgetPrivate::endDrag(bool abort)
if (q->isFloating()) { // Might not be floating when dragging a QDockWidgetGroupWindow
undockedGeometry = q->geometry();
#if QT_CONFIG(tabwidget)
- tabPosition = mwLayout->tabPosition(mainWindow->dockWidgetArea(q));
+ // is the widget located within the mainwindow?
+ const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(q);
+ if (area != Qt::NoDockWidgetArea) {
+ tabPosition = mwLayout->tabPosition(area);
+ } else if (auto dwgw = qobject_cast<QDockWidgetGroupWindow *>(q->parent())) {
+ // DockWidget wasn't found in one of the docks within mainwindow
+ // => derive tabPosition from parent
+ tabPosition = mwLayout->tabPosition(toDockWidgetArea(dwgw->layoutInfo()->dockPos));
+ }
#endif
+ // Reparent, if the drag was out of a dock widget group window
+ if (mode == EndDragMode::LocationChange) {
+ if (auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(q->parentWidget()))
+ groupWindow->reparent(q);
+ }
}
q->activateWindow();
} else {
@@ -884,15 +869,29 @@ void QDockWidgetPrivate::endDrag(bool abort)
state = nullptr;
}
+Qt::DockWidgetArea QDockWidgetPrivate::toDockWidgetArea(QInternal::DockPosition pos)
+{
+ switch (pos) {
+ case QInternal::LeftDock: return Qt::LeftDockWidgetArea;
+ case QInternal::RightDock: return Qt::RightDockWidgetArea;
+ case QInternal::TopDock: return Qt::TopDockWidgetArea;
+ case QInternal::BottomDock: return Qt::BottomDockWidgetArea;
+ default: break;
+ }
+ return Qt::NoDockWidgetArea;
+}
+
void QDockWidgetPrivate::setResizerActive(bool active)
{
Q_Q(QDockWidget);
- if (active && !resizer) {
+ const auto *dwLayout = qobject_cast<QDockWidgetLayout *>(layout);
+ if (dwLayout->nativeWindowDeco(q->isFloating()))
+ return;
+
+ if (active && !resizer)
resizer = new QWidgetResizeHandler(q);
- resizer->setMovingEnabled(false);
- }
if (resizer)
- resizer->setActive(QWidgetResizeHandler::Resize, active);
+ resizer->setEnabled(active);
}
bool QDockWidgetPrivate::isAnimating() const
@@ -920,16 +919,16 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
if (event->button() != Qt::LeftButton ||
- !titleArea.contains(event->pos()) ||
+ !titleArea.contains(event->position().toPoint()) ||
// check if the tool window is movable... do nothing if it
// is not (but allow moving if the window is floating)
(!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
- (qobject_cast<QMainWindow*>(parent) == 0 && !floatingTab) ||
+ (qobject_cast<QMainWindow*>(parent) == nullptr && !floatingTab) ||
isAnimating() || state != nullptr) {
return false;
}
- initDrag(event->pos(), false);
+ initDrag(event->position().toPoint(), false);
if (state)
state->ctrlDrag = (hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier) ||
@@ -949,15 +948,24 @@ bool QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event)
if (!dwLayout->nativeWindowDeco()) {
QRect titleArea = dwLayout->titleArea();
- if (event->button() == Qt::LeftButton && titleArea.contains(event->pos()) &&
+ if (event->button() == Qt::LeftButton && titleArea.contains(event->position().toPoint()) &&
hasFeature(this, QDockWidget::DockWidgetFloatable)) {
- _q_toggleTopLevel();
+ toggleTopLevel();
return true;
}
}
return false;
}
+bool QDockWidgetPrivate::isTabbed() const
+{
+ Q_Q(const QDockWidget);
+ QDockWidget *that = const_cast<QDockWidget *>(q);
+ auto *mwLayout = qt_mainwindow_layout_from_dock(that);
+ Q_ASSERT(mwLayout);
+ return mwLayout->isDockWidgetTabbed(q);
+}
+
bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
{
bool ret = false;
@@ -973,27 +981,75 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
if (!dwlayout->nativeWindowDeco()) {
if (!state->dragging
&& mwlayout->pluggingWidget == nullptr
- && (event->pos() - state->pressPos).manhattanLength()
+ && (event->position().toPoint() - state->pressPos).manhattanLength()
> QApplication::startDragDistance()) {
- startDrag();
- q->grabMouse();
- ret = true;
+
+#ifdef Q_OS_MACOS
+ if (windowHandle() && !q->isFloating()) {
+ // When using native widgets on mac, we have not yet been successful in
+ // starting a drag on an NSView that belongs to one window (QMainWindow),
+ // but continue the drag on another (QDockWidget). This is what happens if
+ // we try to make this widget floating during a drag. So as a fall back
+ // solution, we simply make this widget floating instead, when we would
+ // otherwise start a drag.
+ q->setFloating(true);
+ } else
+#endif
+ {
+ const DragScope scope = isTabbed() ? DragScope::Group : DragScope::Widget;
+ startDrag(scope);
+ q->grabMouse();
+ ret = true;
+ }
}
}
- if (state->dragging && !state->nca) {
+ if (state && state->dragging && !state->nca) {
QMargins windowMargins = q->window()->windowHandle()->frameMargins();
QPoint windowMarginOffset = QPoint(windowMargins.left(), windowMargins.top());
- QPoint pos = event->globalPos() - state->pressPos - windowMarginOffset;
+
+ // TODO maybe use QScreen API (if/when available) to simplify the below code.
+ const QScreen *orgWdgScreen = QGuiApplication::screenAt(state->widgetInitialPos);
+ const QScreen *screenFrom = QGuiApplication::screenAt(state->globalPressPos);
+ const QScreen *screenTo = QGuiApplication::screenAt(event->globalPosition().toPoint());
+ const QScreen *wdgScreen = q->screen();
+
+ QPoint pos;
+ if (Q_LIKELY(screenFrom && screenTo && wdgScreen && orgWdgScreen)) {
+ const QPoint nativeWdgOrgPos = QHighDpiScaling::mapPositionToNative(
+ state->widgetInitialPos, orgWdgScreen->handle());
+ const QPoint nativeTo = QHighDpiScaling::mapPositionToNative(
+ event->globalPosition().toPoint(), screenTo->handle());
+ const QPoint nativeFrom = QHighDpiScaling::mapPositionToNative(state->globalPressPos,
+ screenFrom->handle());
+
+ // Calculate new nativePos based on startPos + mouse delta move.
+ const QPoint nativeNewPos = nativeWdgOrgPos + (nativeTo - nativeFrom);
+ pos = QHighDpiScaling::mapPositionFromNative(nativeNewPos, wdgScreen->handle())
+ - windowMarginOffset;
+ } else {
+ // Fallback in the unlikely case that source and target screens could not be established
+ qCDebug(lcQpaDockWidgets)
+ << "QDockWidget failed to find relevant screen info. screenFrom:" << screenFrom
+ << "screenTo:" << screenTo << " wdgScreen:" << wdgScreen << "orgWdgScreen"
+ << orgWdgScreen;
+ pos = event->globalPosition().toPoint() - state->pressPos - windowMarginOffset;
+ }
+
+ // If the newly floating dock widget has got a native title bar,
+ // offset the position by the native title bar's height or width
+ const int dx = q->geometry().x() - q->x();
+ const int dy = q->geometry().y() - q->y();
+ pos.rx() += dx;
+ pos.ry() += dy;
QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
if (floatingTab && !q->isFloating())
floatingTab->move(pos);
else
q->move(pos);
-
if (state && !state->ctrlDrag)
- mwlayout->hover(state->widgetItem, event->globalPos());
+ mwlayout->hover(state->widgetItem, event->globalPosition().toPoint());
ret = true;
}
@@ -1005,9 +1061,15 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
bool QDockWidgetPrivate::mouseReleaseEvent(QMouseEvent *event)
{
#if QT_CONFIG(mainwindow)
+#if QT_CONFIG(draganddrop)
+ // if we are peforming a platform drag ignore the release here and end the drag when the actual
+ // drag ends.
+ if (QMainWindowLayout::needsPlatformDrag())
+ return false;
+#endif
if (event->button() == Qt::LeftButton && state && !state->nca) {
- endDrag();
+ endDrag(EndDragMode::LocationChange);
return true; //filter out the event
}
@@ -1033,39 +1095,38 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
switch (event->type()) {
case QEvent::NonClientAreaMouseButtonPress:
- if (!titleRect.contains(event->globalPos()))
+ if (!titleRect.contains(event->globalPosition().toPoint()))
break;
if (state != nullptr)
break;
- if (qobject_cast<QMainWindow*>(parent) == 0 && qobject_cast<QDockWidgetGroupWindow*>(parent) == 0)
+ if (qobject_cast<QMainWindow*>(parent) == nullptr && qobject_cast<QDockWidgetGroupWindow*>(parent) == nullptr)
break;
if (isAnimating())
break;
- initDrag(event->pos(), true);
+ initDrag(event->position().toPoint(), true);
if (state == nullptr)
break;
state->ctrlDrag = (event->modifiers() & Qt::ControlModifier) ||
(!hasFeature(this, QDockWidget::DockWidgetMovable) && q->isFloating());
- startDrag();
+ startDrag(DragScope::Group);
break;
case QEvent::NonClientAreaMouseMove:
if (state == nullptr || !state->dragging)
break;
-#ifndef Q_OS_MAC
- if (state->nca) {
- endDrag();
- }
+#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
+ if (state->nca)
+ endDrag(EndDragMode::LocationChange);
#endif
break;
case QEvent::NonClientAreaMouseButtonRelease:
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) || defined(Q_OS_WASM)
if (state)
- endDrag();
+ endDrag(EndDragMode::LocationChange);
#endif
break;
case QEvent::NonClientAreaMouseButtonDblClick:
- _q_toggleTopLevel();
+ toggleTopLevel();
break;
default:
break;
@@ -1088,7 +1149,7 @@ void QDockWidgetPrivate::moveEvent(QMoveEvent *event)
if (state == nullptr || !state->dragging || !state->nca)
return;
- if (!q->isWindow() && qobject_cast<QDockWidgetGroupWindow*>(parent) == 0)
+ if (!q->isWindow() && qobject_cast<QDockWidgetGroupWindow*>(parent) == nullptr)
return;
// When the native window frame is being dragged, all we get is these mouse
@@ -1131,10 +1192,10 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
return; // this dockwidget can't be redocked
}
- bool wasFloating = q->isFloating();
+ const bool wasFloating = q->isFloating();
if (wasFloating) // Prevent repetitive unplugging from nested invocations (QTBUG-42818)
unplug = false;
- bool hidden = q->isHidden();
+ const bool hidden = q->isHidden();
if (q->isVisible())
q->hide();
@@ -1152,8 +1213,12 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
flags |= Qt::FramelessWindowHint;
}
- if (unplug)
+#if QT_CONFIG(draganddrop)
+ // If we are performing a platform drag the flag is not needed and we want to avoid recreating
+ // the platform window when it would be removed later
+ if (unplug && !QMainWindowLayout::needsPlatformDrag())
flags |= Qt::X11BypassWindowManagerHint;
+#endif
q->setWindowFlags(flags);
@@ -1224,15 +1289,18 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
on whether it is docked; a docked QDockWidget has no frame and a smaller title
bar.
- \sa QMainWindow, {Dock Widgets Example}
+ \note On macOS, if the QDockWidget has a native window handle (for example,
+ if winId() is called on it or the child widget), then due to a limitation it will not be
+ possible to drag the dock widget when undocking. Starting the drag will undock
+ the dock widget, but a second drag will be needed to move the dock widget itself.
+
+ \sa QMainWindow
*/
/*!
\enum QDockWidget::DockWidgetFeature
- \value DockWidgetClosable The dock widget can be closed. On some systems the dock
- widget always has a close button when it's floating
- (for example on MacOS 10.5).
+ \value DockWidgetClosable The dock widget can be closed.
\value DockWidgetMovable The dock widget can be moved between docks
by the user.
\value DockWidgetFloatable The dock widget can be detached from the
@@ -1242,11 +1310,6 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
bar on its left side. This can be used to
increase the amount of vertical space in
a QMainWindow.
- \value AllDockWidgetFeatures (Deprecated) The dock widget can be closed, moved,
- and floated. Since new features might be added in future
- releases, the look and behavior of dock widgets might
- change if you use this flag. Please specify individual
- flags instead.
\value NoDockWidgetFeatures The dock widget cannot be closed, moved,
or floated.
@@ -1369,9 +1432,12 @@ QDockWidget::DockWidgetFeatures QDockWidget::features() const
\property QDockWidget::floating
\brief whether the dock widget is floating
- A floating dock widget is presented to the user as an independent
- window "on top" of its parent QMainWindow, instead of being
- docked in the QMainWindow.
+ A floating dock widget is presented to the user as a single, independent
+ window "on top" of its parent QMainWindow, instead of being docked
+ either in the QMainWindow, or in a group of tabbed dock widgets.
+
+ Floating dock widgets can be individually positioned and resized, both
+ programmatically or by mouse interaction.
By default, this property is \c true.
@@ -1385,7 +1451,7 @@ void QDockWidget::setFloating(bool floating)
// the initial click of a double-click may have started a drag...
if (d->state != nullptr)
- d->endDrag(true);
+ d->endDrag(QDockWidgetPrivate::EndDragMode::Abort);
QRect r = d->undockedGeometry;
// Keep position when undocking for the first time.
@@ -1440,8 +1506,14 @@ void QDockWidget::changeEvent(QEvent *event)
QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout());
switch (event->type()) {
- case QEvent::ModifiedChange:
case QEvent::WindowTitleChange:
+ if (isFloating() && windowHandle() && d->topData() && windowHandle()->isVisible()) {
+ // From QWidget::setWindowTitle(): Propagate window title without signal emission
+ d->topData()->caption = windowHandle()->title();
+ d->setWindowTitle_helper(windowHandle()->title());
+ }
+ Q_FALLTHROUGH();
+ case QEvent::ModifiedChange:
update(layout->titleArea());
#ifndef QT_NO_ACTION
d->fixedWindowTitle = qt_setWindowTitle_helperHelper(windowTitle(), this);
@@ -1467,14 +1539,20 @@ void QDockWidget::closeEvent(QCloseEvent *event)
{
Q_D(QDockWidget);
if (d->state)
- d->endDrag(true);
- QWidget::closeEvent(event);
+ d->endDrag(QDockWidgetPrivate::EndDragMode::Abort);
+
+ // For non-closable widgets, don't allow closing, except when the mainwindow
+ // is hidden, as otherwise an application wouldn't be able to be shut down.
+ const QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget());
+ const bool canClose = (d->features & DockWidgetClosable)
+ || (!win || !win->isVisible());
+ event->setAccepted(canClose);
}
/*! \reimp */
void QDockWidget::paintEvent(QPaintEvent *event)
{
- Q_UNUSED(event)
+ Q_UNUSED(event);
Q_D(QDockWidget);
QDockWidgetLayout *layout
@@ -1488,7 +1566,7 @@ void QDockWidget::paintEvent(QPaintEvent *event)
// when not floating.
if (isFloating()) {
QStyleOptionFrame framOpt;
- framOpt.init(this);
+ framOpt.initFrom(this);
p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt);
}
@@ -1544,7 +1622,7 @@ bool QDockWidget::event(QEvent *event)
bool onTop = false;
if (win != nullptr) {
const QObjectList &siblings = win->children();
- onTop = siblings.count() > 0 && siblings.last() == (QObject*)this;
+ onTop = siblings.size() > 0 && siblings.last() == (QObject*)this;
}
#if QT_CONFIG(tabbar)
if (!isFloating() && layout != nullptr && onTop)
@@ -1596,8 +1674,8 @@ bool QDockWidget::event(QEvent *event)
// Usually the window won't get resized while it's being moved, but it can happen,
// for example on Windows when moving to a screen with bigger scale factor
- // (and Qt::AA_EnableHighDpiScaling is enabled). If that happens we should
- // update state->pressPos, otherwise it will be outside the window when the window shrinks.
+ // If that happens we should update state->pressPos, otherwise it will be outside
+ // the window when the window shrinks.
if (d->state && d->state->dragging)
d->recalculatePressPos(static_cast<QResizeEvent*>(event));
break;
@@ -1658,6 +1736,10 @@ QAction * QDockWidget::toggleViewAction() const
invisible). This happens when the widget is hidden or shown, as
well as when it is docked in a tabbed dock area and its tab
becomes selected or unselected.
+
+ \note The signal can differ from QWidget::isVisible(). This can be the case, if
+ a dock widget is minimized or tabified and associated to a non-selected or
+ inactive tab.
*/
/*!
@@ -1674,8 +1756,8 @@ QAction * QDockWidget::toggleViewAction() const
\since 4.3
Sets an arbitrary \a widget as the dock widget's title bar. If \a widget
- is 0, any custom title bar widget previously set on the dock widget is
- removed, but not deleted, and the default title bar will be used
+ is \nullptr, any custom title bar widget previously set on the dock widget
+ is removed, but not deleted, and the default title bar will be used
instead.
If a title bar widget is set, QDockWidget will not use native window
@@ -1739,6 +1821,26 @@ QWidget *QDockWidget::titleBarWidget() const
return layout->widgetForRole(QDockWidgetLayout::TitleBar);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QDockWidget *dockWidget)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+
+ if (!dockWidget) {
+ dbg << "QDockWidget(0x0)";
+ return dbg;
+ }
+
+ dbg << "QDockWidget(" << static_cast<const void *>(dockWidget);
+ dbg << "->(ObjectName=" << dockWidget->objectName();
+ dbg << "; floating=" << dockWidget->isFloating();
+ dbg << "; features=" << dockWidget->features();
+ dbg << ";))";
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
#include "qdockwidget.moc"
diff --git a/src/widgets/widgets/qdockwidget.h b/src/widgets/widgets/qdockwidget.h
index b53a991dae..2efa1d3c2f 100644
--- a/src/widgets/widgets/qdockwidget.h
+++ b/src/widgets/widgets/qdockwidget.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICDOCKWIDGET_H
#define QDYNAMICDOCKWIDGET_H
@@ -56,7 +20,7 @@ class Q_WIDGETS_EXPORT QDockWidget : public QWidget
{
Q_OBJECT
- Q_PROPERTY(bool floating READ isFloating WRITE setFloating)
+ Q_PROPERTY(bool floating READ isFloating WRITE setFloating NOTIFY topLevelChanged)
Q_PROPERTY(DockWidgetFeatures features READ features WRITE setFeatures NOTIFY featuresChanged)
Q_PROPERTY(Qt::DockWidgetAreas allowedAreas READ allowedAreas
WRITE setAllowedAreas NOTIFY allowedAreasChanged)
@@ -78,7 +42,6 @@ public:
DockWidgetVerticalTitleBar = 0x08,
DockWidgetFeatureMask = 0x0f,
- AllDockWidgetFeatures = DockWidgetClosable|DockWidgetMovable|DockWidgetFloatable, // ### Qt 6: remove
NoDockWidgetFeatures = 0x00,
Reserved = 0xff
@@ -101,6 +64,10 @@ public:
inline bool isAreaAllowed(Qt::DockWidgetArea area) const
{ return (allowedAreas() & area) == area; }
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_WIDGETS_EXPORT QDebug operator<<(QDebug dbg, const QDockWidget *dockWidget);
+#endif
+
#ifndef QT_NO_ACTION
QAction *toggleViewAction() const;
#endif
@@ -109,7 +76,7 @@ Q_SIGNALS:
void featuresChanged(QDockWidget::DockWidgetFeatures features);
void topLevelChanged(bool topLevel);
void allowedAreasChanged(Qt::DockWidgetAreas allowedAreas);
- void visibilityChanged(bool visible);
+ void visibilityChanged(bool visible); // ### Qt7: Deprecate this. Better listen to hide/show events
void dockLocationChanged(Qt::DockWidgetArea area);
protected:
@@ -117,13 +84,11 @@ protected:
void closeEvent(QCloseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
bool event(QEvent *event) override;
- void initStyleOption(QStyleOptionDockWidget *option) const;
+ virtual void initStyleOption(QStyleOptionDockWidget *option) const;
private:
Q_DECLARE_PRIVATE(QDockWidget)
Q_DISABLE_COPY(QDockWidget)
- Q_PRIVATE_SLOT(d_func(), void _q_toggleView(bool))
- Q_PRIVATE_SLOT(d_func(), void _q_toggleTopLevel())
friend class QDockAreaLayout;
friend class QDockWidgetItem;
friend class QMainWindowLayout;
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index e663ec4c2d..fa936599c6 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICDOCKWIDGET_P_H
#define QDYNAMICDOCKWIDGET_P_H
@@ -77,6 +41,8 @@ class QDockWidgetPrivate : public QWidgetPrivate
struct DragState {
QPoint pressPos;
+ QPoint globalPressPos;
+ QPoint widgetInitialPos;
bool dragging;
QLayoutItem *widgetItem;
bool ownWidgetItem;
@@ -85,11 +51,22 @@ class QDockWidgetPrivate : public QWidgetPrivate
};
public:
+ enum class DragScope {
+ Group,
+ Widget
+ };
+
+ enum class EndDragMode {
+ LocationChange,
+ Abort
+ };
+
void init();
- void _q_toggleView(bool); // private slot
- void _q_toggleTopLevel(); // private slot
+ void toggleView(bool);
+ void toggleTopLevel();
void updateButtons();
+ static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos);
#if QT_CONFIG(tabwidget)
QTabWidget::TabPosition tabPosition = QTabWidget::North;
@@ -119,8 +96,8 @@ public:
void setWindowState(bool floating, bool unplug = false, const QRect &rect = QRect());
void nonClientAreaMouseEvent(QMouseEvent *event);
void initDrag(const QPoint &pos, bool nca);
- void startDrag(bool group = true);
- void endDrag(bool abort = false);
+ void startDrag(DragScope scope);
+ void endDrag(EndDragMode mode);
void moveEvent(QMoveEvent *event);
void recalculatePressPos(QResizeEvent *event);
@@ -129,6 +106,7 @@ public:
void setResizerActive(bool active);
bool isAnimating() const;
+ bool isTabbed() const;
private:
QWidgetResizeHandler *resizer = nullptr;
@@ -172,7 +150,7 @@ public:
bool verticalTitleBar;
private:
- QVector<QLayoutItem*> item_list;
+ QList<QLayoutItem *> item_list;
QRect _titleArea;
};
@@ -201,11 +179,7 @@ inline QLayoutItem *QDockWidgetItem::dockWidgetChildItem() const
inline QDockWidgetLayout *QDockWidgetItem::dockWidgetLayout() const
{
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QWidget *w = const_cast<QDockWidgetItem*>(this)->widget();
-#else
QWidget *w = widget();
-#endif
if (w != nullptr)
return qobject_cast<QDockWidgetLayout*>(w->layout());
return nullptr;
diff --git a/src/widgets/widgets/qeffects.cpp b/src/widgets/widgets/qeffects.cpp
index ee4095cb36..74ac24a2b0 100644
--- a/src/widgets/widgets/qeffects.cpp
+++ b/src/widgets/widgets/qeffects.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
-#include "qdesktopwidget.h"
+#include "qdebug.h"
#include "qeffects_p.h"
+#include "qelapsedtimer.h"
#include "qevent.h"
#include "qimage.h"
#include "qpainter.h"
@@ -47,10 +12,10 @@
#include "qpixmap.h"
#include "qpointer.h"
#include "qtimer.h"
-#include "qelapsedtimer.h"
-#include "qdebug.h"
+#include "qwidget.h"
+#include "private/qwidget_p.h"
+#include "qwindow.h"
-#include <private/qdesktopwidget_p.h>
QT_BEGIN_NAMESPACE
@@ -98,12 +63,10 @@ static QAlphaWidget* q_blend = nullptr;
/*
Constructs a QAlphaWidget.
*/
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED // ### Qt 6: Find a replacement for QDesktopWidget::screen()
QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f)
- : QWidget(QApplication::desktop()->screen(QDesktopWidgetPrivate::screenNumber(w)), f)
+ : QWidget(nullptr, f)
{
-QT_WARNING_POP
+ QWidgetPrivate::get(this)->setScreen(w->screen());
#ifndef Q_OS_WIN
setEnabled(false);
#endif
@@ -152,7 +115,7 @@ void QAlphaWidget::run(int time)
qApp->installEventFilter(this);
widget->setWindowOpacity(0.0);
widget->show();
- connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
+ connect(&anim, &QTimer::timeout, this, &QAlphaWidget::render);
anim.start(1);
#else
//This is roughly equivalent to calling setVisible(true) without actually showing the widget
@@ -165,7 +128,7 @@ void QAlphaWidget::run(int time)
resize(widget->size().width(), widget->size().height());
frontImage = widget->grab().toImage();
- backImage = QGuiApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId(),
+ backImage = QGuiApplication::primaryScreen()->grabWindow(0,
widget->geometry().x(), widget->geometry().y(),
widget->geometry().width(), widget->geometry().height()).toImage();
@@ -175,7 +138,7 @@ void QAlphaWidget::run(int time)
show();
setEnabled(false);
- connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
+ connect(&anim, &QTimer::timeout, this, &QAlphaWidget::render);
anim.start(1);
} else {
duration = 0;
@@ -208,7 +171,7 @@ bool QAlphaWidget::eventFilter(QObject *o, QEvent *e)
break;
case QEvent::KeyPress: {
#ifndef QT_NO_SHORTCUT
- QKeyEvent *ke = (QKeyEvent*)e;
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
if (ke->matches(QKeySequence::Cancel)) {
showWidget = false;
} else
@@ -305,7 +268,7 @@ void QAlphaWidget::alphaBlend()
const int sw = frontImage.width();
const int sh = frontImage.height();
- const int bpl = frontImage.bytesPerLine();
+ const qsizetype bpl = frontImage.bytesPerLine();
switch(frontImage.depth()) {
case 32:
{
@@ -329,6 +292,7 @@ void QAlphaWidget::alphaBlend()
back_data += bpl;
front_data += bpl;
}
+ break;
}
default:
break;
@@ -385,6 +349,7 @@ static QRollEffect* q_roll = nullptr;
QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
: QWidget(nullptr, f), orientation(orient)
{
+ QWidgetPrivate::get(this)->setScreen(w->screen());
#ifndef Q_OS_WIN
setEnabled(false);
#endif
@@ -464,7 +429,7 @@ void QRollEffect::run(int time)
duration = qMin(qMax(dist/3, 50), 120);
}
- connect(&anim, SIGNAL(timeout()), this, SLOT(scroll()));
+ connect(&anim, &QTimer::timeout, this, &QRollEffect::scroll);
move(widget->geometry().x(),widget->geometry().y());
resize(qMin(currentWidth, totalWidth), qMin(currentHeight, totalHeight));
@@ -499,14 +464,12 @@ void QRollEffect::scroll()
+ (2 * totalWidth * (elapsed%duration) + duration)
/ (2 * duration);
// equiv. to int((totalWidth*elapsed) / duration + 0.5)
- done = (currentWidth >= totalWidth);
}
if (currentHeight != totalHeight) {
currentHeight = totalHeight * (elapsed/duration)
+ (2 * totalHeight * (elapsed%duration) + duration)
/ (2 * duration);
// equiv. to int((totalHeight*elapsed) / duration + 0.5)
- done = (currentHeight >= totalHeight);
}
done = (currentHeight >= totalHeight) &&
(currentWidth >= totalWidth);
@@ -555,7 +518,7 @@ void QRollEffect::scroll()
}
}
-/*!
+/*
Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2
(horizontal) or 3 (diagonal).
*/
@@ -578,7 +541,7 @@ void qScrollEffect(QWidget* w, QEffects::DirFlags orient, int time)
q_roll->run(time);
}
-/*!
+/*
Fade in widget \a w in \a time ms.
*/
void qFadeEffect(QWidget* w, int time)
diff --git a/src/widgets/widgets/qeffects_p.h b/src/widgets/widgets/qeffects_p.h
index 92f459651f..794ef030a0 100644
--- a/src/widgets/widgets/qeffects_p.h
+++ b/src/widgets/widgets/qeffects_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEFFECTS_P_H
#define QEFFECTS_P_H
diff --git a/src/widgets/widgets/qfocusframe.cpp b/src/widgets/widgets/qfocusframe.cpp
index 4d64c24db3..d66faedbac 100644
--- a/src/widgets/widgets/qfocusframe.cpp
+++ b/src/widgets/widgets/qfocusframe.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfocusframe.h"
#include "qstyle.h"
@@ -86,20 +50,22 @@ void QFocusFramePrivate::updateSize()
if (!widget)
return;
- int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin),
- hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QStyleOption opt;
+ q->initStyleOption(&opt);
+ int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &opt, q),
+ hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &opt, q);
QPoint pos(widget->x(), widget->y());
if (q->parentWidget() != widget->parentWidget())
pos = widget->parentWidget()->mapTo(q->parentWidget(), pos);
QRect geom(pos.x()-hmargin, pos.y()-vmargin,
widget->width()+(hmargin*2), widget->height()+(vmargin*2));
- if(q->geometry() == geom)
+ if (q->geometry() == geom)
return;
q->setGeometry(geom);
+
+ opt.rect = q->rect();
QStyleHintReturnMask mask;
- QStyleOption opt;
- q->initStyleOption(&opt);
if (q->style()->styleHint(QStyle::SH_FocusFrame_Mask, &opt, q, &mask))
q->setMask(mask.region);
}
@@ -263,8 +229,8 @@ QFocusFrame::paintEvent(QPaintEvent *)
QStylePainter p(this);
QStyleOption option;
initStyleOption(&option);
- int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
- int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ const int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &option, this);
+ const int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, this);
QWidgetPrivate *wd = qt_widget_private(d->widget);
QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2);
p.setClipRect(rect);
@@ -277,7 +243,7 @@ bool
QFocusFrame::eventFilter(QObject *o, QEvent *e)
{
Q_D(QFocusFrame);
- if(o == d->widget) {
+ if (o == d->widget) {
switch(e->type()) {
case QEvent::Move:
case QEvent::Resize:
diff --git a/src/widgets/widgets/qfocusframe.h b/src/widgets/widgets/qfocusframe.h
index 73d5b42bd8..a281b0dbe3 100644
--- a/src/widgets/widgets/qfocusframe.h
+++ b/src/widgets/widgets/qfocusframe.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFOCUSFRAME_H
#define QFOCUSFRAME_H
@@ -64,7 +28,7 @@ protected:
bool eventFilter(QObject *, QEvent *) override;
void paintEvent(QPaintEvent *) override;
- void initStyleOption(QStyleOption *option) const;
+ virtual void initStyleOption(QStyleOption *option) const;
private:
Q_DECLARE_PRIVATE(QFocusFrame)
diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp
index 4a99b0f962..c80687c7ed 100644
--- a/src/widgets/widgets/qfontcombobox.cpp
+++ b/src/widgets/widgets/qfontcombobox.cpp
@@ -1,57 +1,24 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontcombobox.h"
+#include <qabstractitemdelegate.h>
+#include <qaccessible.h>
#include <qstringlistmodel.h>
-#include <qitemdelegate.h>
#include <qlistview.h>
#include <qpainter.h>
#include <qevent.h>
#include <qapplication.h>
#include <private/qcombobox_p.h>
-#include <QDesktopWidget>
-#include <private/qdesktopwidget_p.h>
#include <qdebug.h>
+#include <array>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QFontDatabase::WritingSystem writingSystemFromScript(QLocale::Script script)
{
switch (script) {
@@ -136,8 +103,8 @@ static QFontDatabase::WritingSystem writingSystemFromLocale()
static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool *hasLatin)
{
- QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase().writingSystems(font.family());
-// qDebug() << font.family() << writingSystems;
+ QList<QFontDatabase::WritingSystem> writingSystems = QFontDatabase::writingSystems(font.families().constFirst());
+// qDebug() << font.families().first() << writingSystems;
// this just confuses the algorithm below. Vietnamese is Latin with lots of special chars
writingSystems.removeOne(QFontDatabase::Vietnamese);
@@ -168,23 +135,39 @@ static QFontDatabase::WritingSystem writingSystemForFont(const QFont &font, bool
return system;
}
- if (writingSystems.count() == 1 && system > QFontDatabase::Cyrillic)
+ if (writingSystems.size() == 1 && system > QFontDatabase::Cyrillic)
return system;
- if (writingSystems.count() <= 2 && system > QFontDatabase::Armenian && system < QFontDatabase::Vietnamese)
+ if (writingSystems.size() <= 2 && system > QFontDatabase::Armenian && system < QFontDatabase::Vietnamese)
return system;
- if (writingSystems.count() <= 5 && system >= QFontDatabase::SimplifiedChinese && system <= QFontDatabase::Korean)
+ if (writingSystems.size() <= 5 && system >= QFontDatabase::SimplifiedChinese && system <= QFontDatabase::Korean)
return system;
return QFontDatabase::Any;
}
+class QFontComboBoxPrivate : public QComboBoxPrivate
+{
+public:
+ QFontComboBox::FontFilters filters = QFontComboBox::AllFonts;
+ QFont currentFont;
+ QHash<QFontDatabase::WritingSystem, QString> sampleTextForWritingSystem;
+ QHash<QString, QString> sampleTextForFontFamily;
+ QHash<QString, QFont> displayFontForFontFamily;
+ std::array<QMetaObject::Connection, 2> connections;
+
+ void updateModel();
+ void currentChanged(const QString &);
+
+ Q_DECLARE_PUBLIC(QFontComboBox)
+};
+
class QFontFamilyDelegate : public QAbstractItemDelegate
{
Q_OBJECT
public:
- explicit QFontFamilyDelegate(QObject *parent);
+ explicit QFontFamilyDelegate(QObject *parent, QFontComboBoxPrivate *comboP);
// painting
void paint(QPainter *painter,
@@ -197,13 +180,15 @@ public:
const QIcon truetype;
const QIcon bitmap;
QFontDatabase::WritingSystem writingSystem;
+ QFontComboBoxPrivate *comboPrivate;
};
-QFontFamilyDelegate::QFontFamilyDelegate(QObject *parent)
+QFontFamilyDelegate::QFontFamilyDelegate(QObject *parent, QFontComboBoxPrivate *comboP)
: QAbstractItemDelegate(parent),
truetype(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fonttruetype-16.png")),
bitmap(QStringLiteral(":/qt-project.org/styles/commonstyle/images/fontbitmap-16.png")),
- writingSystem(QFontDatabase::Any)
+ writingSystem(QFontDatabase::Any),
+ comboPrivate(comboP)
{
}
@@ -215,13 +200,15 @@ void QFontFamilyDelegate::paint(QPainter *painter,
QFont font(option.font);
font.setPointSize(QFontInfo(font).pointSize() * 3 / 2);
QFont font2 = font;
- font2.setFamily(text);
+ font2.setFamilies(QStringList{text});
bool hasLatin;
QFontDatabase::WritingSystem system = writingSystemForFont(font2, &hasLatin);
if (hasLatin)
font = font2;
+ font = comboPrivate->displayFontForFontFamily.value(text, font);
+
QRect r = option.rect;
if (option.state & QStyle::State_Selected) {
@@ -233,7 +220,7 @@ void QFontFamilyDelegate::paint(QPainter *painter,
}
const QIcon *icon = &bitmap;
- if (QFontDatabase().isSmoothlyScalable(text)) {
+ if (QFontDatabase::isSmoothlyScalable(text)) {
icon = &truetype;
}
const QSize actualSize = icon->actualSize(r.size());
@@ -266,10 +253,11 @@ void QFontFamilyDelegate::paint(QPainter *painter,
if (writingSystem != QFontDatabase::Any)
system = writingSystem;
- if (system != QFontDatabase::Any) {
- int w = painter->fontMetrics().horizontalAdvance(text + QLatin1String(" "));
+ const QString sampleText = comboPrivate->sampleTextForFontFamily.value(text, comboPrivate->sampleTextForWritingSystem.value(system));
+ if (system != QFontDatabase::Any || !sampleText.isEmpty()) {
+ int w = painter->fontMetrics().horizontalAdvance(text + " "_L1);
painter->setFont(font2);
- QString sample = QFontDatabase().writingSystemSample(system);
+ const QString sample = !sampleText.isEmpty() ? sampleText : QFontDatabase::writingSystemSample(system);
if (option.direction == Qt::RightToLeft)
r.setRight(r.right() - w);
else
@@ -288,31 +276,20 @@ QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,
{
QString text = index.data(Qt::DisplayRole).toString();
QFont font(option.font);
-// font.setFamily(text);
+// font.setFamilies(QStringList{text});
font.setPointSize(QFontInfo(font).pointSize() * 3/2);
QFontMetrics fontMetrics(font);
return QSize(fontMetrics.horizontalAdvance(text), fontMetrics.height());
}
-class QFontComboBoxPrivate : public QComboBoxPrivate
+void QFontComboBoxPrivate::updateModel()
{
-public:
- inline QFontComboBoxPrivate() { filters = QFontComboBox::AllFonts; }
-
- QFontComboBox::FontFilters filters;
- QFont currentFont;
-
- void _q_updateModel();
- void _q_currentChanged(const QString &);
-
- Q_DECLARE_PUBLIC(QFontComboBox)
-};
+ Q_Q(QFontComboBox);
+ if (QCoreApplication::closingDown())
+ return;
-void QFontComboBoxPrivate::_q_updateModel()
-{
- Q_Q(QFontComboBox);
const int scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
const int spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
@@ -322,30 +299,28 @@ void QFontComboBoxPrivate::_q_updateModel()
QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(q->view()->itemDelegate());
QFontDatabase::WritingSystem system = delegate ? delegate->writingSystem : QFontDatabase::Any;
- QFontDatabase fdb;
- QStringList list = fdb.families(system);
+ const QStringList list = QFontDatabase::families(system);
QStringList result;
int offset = 0;
QFontInfo fi(currentFont);
- for (int i = 0; i < list.size(); ++i) {
- if (fdb.isPrivateFamily(list.at(i)))
+ for (const auto &family : list) {
+ if (QFontDatabase::isPrivateFamily(family))
continue;
if ((filters & scalableMask) && (filters & scalableMask) != scalableMask) {
- if (bool(filters & QFontComboBox::ScalableFonts) != fdb.isSmoothlyScalable(list.at(i)))
+ if (bool(filters & QFontComboBox::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family))
continue;
}
if ((filters & spacingMask) && (filters & spacingMask) != spacingMask) {
- if (bool(filters & QFontComboBox::MonospacedFonts) != fdb.isFixedPitch(list.at(i)))
+ if (bool(filters & QFontComboBox::MonospacedFonts) != QFontDatabase::isFixedPitch(family))
continue;
}
- result += list.at(i);
- if (list.at(i) == fi.family() || list.at(i).startsWith(fi.family() + QLatin1String(" [")))
- offset = result.count() - 1;
+ result += family;
+ if (family == fi.family() || family.startsWith(fi.family() + " ["_L1))
+ offset = result.size() - 1;
}
- list = result;
//we need to block the signals so that the model doesn't emit reset
//this prevents the current index from changing
@@ -353,10 +328,17 @@ void QFontComboBoxPrivate::_q_updateModel()
///TODO: we should finda way to avoid blocking signals and have a real update of the model
{
const QSignalBlocker blocker(m);
- m->setStringList(list);
+ m->setStringList(result);
+ // Since the modelReset signal is blocked the view will not emit an accessibility event
+ #if QT_CONFIG(accessibility)
+ if (QAccessible::isActive()) {
+ QAccessibleTableModelChangeEvent accessibleEvent(q->view(), QAccessibleTableModelChangeEvent::ModelReset);
+ QAccessible::updateAccessibility(&accessibleEvent);
+ }
+ #endif
}
- if (list.isEmpty()) {
+ if (result.isEmpty()) {
if (currentFont != QFont()) {
currentFont = QFont();
emit q->currentFontChanged(currentFont);
@@ -367,11 +349,12 @@ void QFontComboBoxPrivate::_q_updateModel()
}
-void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
+void QFontComboBoxPrivate::currentChanged(const QString &text)
{
Q_Q(QFontComboBox);
- if (currentFont.family() != text) {
- currentFont.setFamily(text);
+ const QStringList families = currentFont.families();
+ if (families.isEmpty() || families.first() != text) {
+ currentFont.setFamilies(QStringList{text});
emit q->currentFontChanged(currentFont);
}
}
@@ -406,7 +389,7 @@ void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
\image windowsvista-fontcombobox.png Screenshot of QFontComboBox on Windows Vista
- \sa QComboBox, QFont, QFontInfo, QFontMetrics, QFontDatabase, {Character Map Example}
+ \sa QComboBox, QFont, QFontInfo, QFontMetrics, QFontDatabase
*/
/*!
@@ -421,17 +404,18 @@ QFontComboBox::QFontComboBox(QWidget *parent)
QStringListModel *m = new QStringListModel(this);
setModel(m);
- setItemDelegate(new QFontFamilyDelegate(this));
+ setItemDelegate(new QFontFamilyDelegate(this, d));
QListView *lview = qobject_cast<QListView*>(view());
if (lview)
lview->setUniformItemSizes(true);
setWritingSystem(QFontDatabase::Any);
- connect(this, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(_q_currentChanged(QString)));
-
- connect(qApp, SIGNAL(fontDatabaseChanged()),
- this, SLOT(_q_updateModel()));
+ d->connections = {
+ QObjectPrivate::connect(this, &QFontComboBox::currentTextChanged,
+ d, &QFontComboBoxPrivate::currentChanged),
+ QObjectPrivate::connect(qApp, &QGuiApplication::fontDatabaseChanged,
+ d, &QFontComboBoxPrivate::updateModel),
+ };
}
@@ -440,6 +424,9 @@ QFontComboBox::QFontComboBox(QWidget *parent)
*/
QFontComboBox::~QFontComboBox()
{
+ Q_D(const QFontComboBox);
+ for (const QMetaObject::Connection &connection : d->connections)
+ QObject::disconnect(connection);
}
/*!
@@ -458,7 +445,7 @@ void QFontComboBox::setWritingSystem(QFontDatabase::WritingSystem script)
QFontFamilyDelegate *delegate = qobject_cast<QFontFamilyDelegate *>(view()->itemDelegate());
if (delegate)
delegate->writingSystem = script;
- d->_q_updateModel();
+ d->updateModel();
}
QFontDatabase::WritingSystem QFontComboBox::writingSystem() const
@@ -494,7 +481,7 @@ void QFontComboBox::setFontFilters(FontFilters filters)
{
Q_D(QFontComboBox);
d->filters = filters;
- d->_q_updateModel();
+ d->updateModel();
}
QFontComboBox::FontFilters QFontComboBox::fontFilters() const
@@ -520,8 +507,8 @@ void QFontComboBox::setCurrentFont(const QFont &font)
Q_D(QFontComboBox);
if (font != d->currentFont) {
d->currentFont = font;
- d->_q_updateModel();
- if (d->currentFont == font) { //else the signal has already be emitted by _q_updateModel
+ d->updateModel();
+ if (d->currentFont == font) { //else the signal has already be emitted by updateModel
emit currentFontChanged(d->currentFont);
}
}
@@ -545,7 +532,7 @@ bool QFontComboBox::event(QEvent *e)
QListView *lview = qobject_cast<QListView*>(view());
if (lview) {
lview->window()->setFixedWidth(qMin(width() * 5 / 3,
- QDesktopWidgetPrivate::availableGeometry(lview).width()));
+ QWidgetPrivate::availableScreenGeometry(lview).width()));
}
}
return QComboBox::event(e);
@@ -558,10 +545,81 @@ QSize QFontComboBox::sizeHint() const
{
QSize sz = QComboBox::sizeHint();
QFontMetrics fm(font());
- sz.setWidth(fm.horizontalAdvance(QLatin1Char('m'))*14);
+ sz.setWidth(fm.horizontalAdvance(u'm') * 14);
return sz;
}
+/*!
+ Sets the \a sampleText to show after the font name (when the combo is open) for a given \a writingSystem.
+
+ The sample text given with setSampleTextForFont() has priority.
+
+ \since 6.3
+*/
+void QFontComboBox::setSampleTextForSystem(QFontDatabase::WritingSystem writingSystem, const QString &sampleText)
+{
+ Q_D(QFontComboBox);
+ d->sampleTextForWritingSystem[writingSystem] = sampleText;
+}
+
+
+/*!
+ Returns the sample text to show after the font name (when the combo is open) for a given \a writingSystem.
+
+ \since 6.3
+*/
+QString QFontComboBox::sampleTextForSystem(QFontDatabase::WritingSystem writingSystem) const
+{
+ Q_D(const QFontComboBox);
+ return d->sampleTextForWritingSystem.value(writingSystem);
+}
+
+/*!
+ Sets the \a sampleText to show after the font name (when the combo is open) for a given \a fontFamily.
+
+ The sample text given with this function has priority over the one set with setSampleTextForSystem().
+
+ \since 6.3
+*/
+void QFontComboBox::setSampleTextForFont(const QString &fontFamily, const QString &sampleText)
+{
+ Q_D(QFontComboBox);
+ d->sampleTextForFontFamily[fontFamily] = sampleText;
+}
+
+/*!
+ Returns the sample text to show after the font name (when the combo is open) for a given \a fontFamily.
+
+ \since 6.3
+*/
+QString QFontComboBox::sampleTextForFont(const QString &fontFamily) const
+{
+ Q_D(const QFontComboBox);
+ return d->sampleTextForFontFamily.value(fontFamily);
+}
+
+/*!
+ Sets the \a font to be used to display a given \a fontFamily (when the combo is open).
+
+ \since 6.3
+*/
+void QFontComboBox::setDisplayFont(const QString &fontFamily, const QFont &font)
+{
+ Q_D(QFontComboBox);
+ d->displayFontForFontFamily[fontFamily] = font;
+}
+
+/*!
+ Returns the font (if set) to be used to display a given \a fontFamily (when the combo is open).
+
+ \since 6.3
+*/
+std::optional<QFont> QFontComboBox::displayFont(const QString &fontFamily) const
+{
+ Q_D(const QFontComboBox);
+ return d->displayFontForFontFamily.value(fontFamily, {});
+}
+
QT_END_NAMESPACE
#include "qfontcombobox.moc"
diff --git a/src/widgets/widgets/qfontcombobox.h b/src/widgets/widgets/qfontcombobox.h
index 6c1871dd2d..9c5432b332 100644
--- a/src/widgets/widgets/qfontcombobox.h
+++ b/src/widgets/widgets/qfontcombobox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTCOMBOBOX_H
#define QFONTCOMBOBOX_H
@@ -80,6 +44,15 @@ public:
QFont currentFont() const;
QSize sizeHint() const override;
+ void setSampleTextForSystem(QFontDatabase::WritingSystem writingSystem, const QString &sampleText);
+ QString sampleTextForSystem(QFontDatabase::WritingSystem writingSystem) const;
+
+ void setSampleTextForFont(const QString &fontFamily, const QString &sampleText);
+ QString sampleTextForFont(const QString &fontFamily) const;
+
+ void setDisplayFont(const QString &fontFamily, const QFont &font);
+ std::optional<QFont> displayFont(const QString &fontFamily) const;
+
public Q_SLOTS:
void setCurrentFont(const QFont &f);
@@ -92,8 +65,6 @@ protected:
private:
Q_DISABLE_COPY(QFontComboBox)
Q_DECLARE_PRIVATE(QFontComboBox)
- Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QString &))
- Q_PRIVATE_SLOT(d_func(), void _q_updateModel())
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFontComboBox::FontFilters)
diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp
index 1661c5c881..db8dc20be2 100644
--- a/src/widgets/widgets/qframe.cpp
+++ b/src/widgets/widgets/qframe.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qframe.h"
#include "qbitmap.h"
@@ -44,6 +8,7 @@
#include "qpainter.h"
#include "qstyle.h"
#include "qstyleoption.h"
+#include "qstylepainter.h"
#include "qapplication.h"
#include "qframe_p.h"
@@ -463,9 +428,9 @@ int QFrame::frameWidth() const
\brief the frame's rectangle
The frame's rectangle is the rectangle the frame is drawn in. By
- default, this is the entire widget. Setting the rectangle does
- does \e not cause a widget update. The frame rectangle is
- automatically adjusted when the widget changes size.
+ default, this is the entire widget. Setting the rectangle \e doesn't
+ cause a widget update. The frame rectangle is automatically adjusted
+ when the widget changes size.
If you set the rectangle to a null rectangle (for example,
QRect(0, 0, 0, 0)), then the resulting frame rectangle is
@@ -511,8 +476,8 @@ QSize QFrame::sizeHint() const
void QFrame::paintEvent(QPaintEvent *)
{
- QPainter paint(this);
- drawFrame(&paint);
+ QStylePainter p(this);
+ drawFrame(&p);
}
/*!
diff --git a/src/widgets/widgets/qframe.h b/src/widgets/widgets/qframe.h
index 595dfa929d..0c8a6f81d1 100644
--- a/src/widgets/widgets/qframe.h
+++ b/src/widgets/widgets/qframe.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFRAME_H
#define QFRAME_H
@@ -116,13 +80,15 @@ protected:
protected:
QFrame(QFramePrivate &dd, QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
- void initStyleOption(QStyleOptionFrame *option) const;
+ virtual void initStyleOption(QStyleOptionFrame *option) const;
private:
Q_DISABLE_COPY(QFrame)
Q_DECLARE_PRIVATE(QFrame)
};
+Q_DECLARE_MIXED_ENUM_OPERATORS_SYMMETRIC(int, QFrame::Shape, QFrame::Shadow)
+
QT_END_NAMESPACE
#endif // QFRAME_H
diff --git a/src/widgets/widgets/qframe_p.h b/src/widgets/widgets/qframe_p.h
index e3c101e87c..a45f5735dd 100644
--- a/src/widgets/widgets/qframe_p.h
+++ b/src/widgets/widgets/qframe_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFRAME_P_H
#define QFRAME_P_H
@@ -57,8 +21,7 @@
QT_BEGIN_NAMESPACE
-// ### unexport this class when and if QAbstractScrollAreaPrivate is unexported
-class Q_WIDGETS_EXPORT QFramePrivate : public QWidgetPrivate
+class QFramePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QFrame)
public:
diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp
index 048fe42948..eb37599382 100644
--- a/src/widgets/widgets/qgroupbox.cpp
+++ b/src/widgets/widgets/qgroupbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgroupbox.h"
@@ -50,12 +14,15 @@
#include "qstyle.h"
#include "qstyleoption.h"
#include "qstylepainter.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <private/qwidget_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
#include "qdebug.h"
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -166,9 +133,9 @@ void QGroupBoxPrivate::click()
widgets). The following example shows how we can set up a
QGroupBox with a layout:
- \snippet widgets/groupbox/window.cpp 2
+ \snippet code/src_gui_widgets_qgroupbox.cpp Set up QGroupBox with layout
- \sa QButtonGroup, {Group Box Example}
+ \sa QButtonGroup
*/
@@ -234,7 +201,7 @@ void QGroupBox::setTitle(const QString &title)
update();
updateGeometry();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
#endif
@@ -339,7 +306,7 @@ bool QGroupBox::event(QEvent *e)
case QEvent::HoverEnter:
case QEvent::HoverMove: {
QStyle::SubControl control = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
- static_cast<QHoverEvent *>(e)->pos(),
+ static_cast<QHoverEvent *>(e)->position().toPoint(),
this);
bool oldHover = d->hover;
d->hover = d->checkable && (control == QStyle::SC_GroupBoxLabel || control == QStyle::SC_GroupBoxCheckBox);
@@ -360,7 +327,10 @@ bool QGroupBox::event(QEvent *e)
return true;
case QEvent::KeyPress: {
QKeyEvent *k = static_cast<QKeyEvent*>(e);
- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value<QList<Qt::Key>>();
+ if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
d->pressedControl = QStyle::SC_GroupBoxCheckBox;
update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this));
return true;
@@ -369,7 +339,10 @@ bool QGroupBox::event(QEvent *e)
}
case QEvent::KeyRelease: {
QKeyEvent *k = static_cast<QKeyEvent*>(e);
- if (!k->isAutoRepeat() && (k->key() == Qt::Key_Select || k->key() == Qt::Key_Space)) {
+ const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme()
+ ->themeHint(QPlatformTheme::ButtonPressKeys)
+ .value<QList<Qt::Key>>();
+ if (!k->isAutoRepeat() && buttonPressKeys.contains(k->key())) {
bool toggle = (d->pressedControl == QStyle::SC_GroupBoxLabel
|| d->pressedControl == QStyle::SC_GroupBoxCheckBox);
d->pressedControl = QStyle::SC_None;
@@ -488,12 +461,12 @@ QSize QGroupBox::minimumSizeHint() const
QFontMetrics metrics(fontMetrics());
- int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(QLatin1Char(' '));
+ int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(u' ');
int baseHeight = metrics.height();
if (d->checkable) {
- baseWidth += style()->pixelMetric(QStyle::PM_IndicatorWidth);
- baseWidth += style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing);
- baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight));
+ baseWidth += style()->pixelMetric(QStyle::PM_IndicatorWidth, &option, this);
+ baseWidth += style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &option, this);
+ baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight, &option, this));
}
QSize size = style()->sizeFromContents(QStyle::CT_GroupBox, &option, QSize(baseWidth, baseHeight), this);
@@ -637,7 +610,7 @@ void QGroupBox::setChecked(bool b)
update();
d->checked = b;
d->_q_setChildrenEnabled(b);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State st;
st.checked = true;
QAccessibleStateChangeEvent e(this, st);
@@ -702,7 +675,7 @@ void QGroupBox::mousePressEvent(QMouseEvent *event)
QStyleOptionGroupBox box;
initStyleOption(&box);
d->pressedControl = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
- event->pos(), this);
+ event->position().toPoint(), this);
if (d->checkable && (d->pressedControl & (QStyle::SC_GroupBoxCheckBox | QStyle::SC_GroupBoxLabel))) {
d->overCheckBox = true;
update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this));
@@ -718,7 +691,7 @@ void QGroupBox::mouseMoveEvent(QMouseEvent *event)
QStyleOptionGroupBox box;
initStyleOption(&box);
QStyle::SubControl pressed = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
- event->pos(), this);
+ event->position().toPoint(), this);
bool oldOverCheckBox = d->overCheckBox;
d->overCheckBox = (pressed == QStyle::SC_GroupBoxCheckBox || pressed == QStyle::SC_GroupBoxLabel);
if (d->checkable && (d->pressedControl == QStyle::SC_GroupBoxCheckBox || d->pressedControl == QStyle::SC_GroupBoxLabel)
@@ -744,7 +717,7 @@ void QGroupBox::mouseReleaseEvent(QMouseEvent *event)
QStyleOptionGroupBox box;
initStyleOption(&box);
QStyle::SubControl released = style()->hitTestComplexControl(QStyle::CC_GroupBox, &box,
- event->pos(), this);
+ event->position().toPoint(), this);
bool toggle = d->checkable && (released == QStyle::SC_GroupBoxLabel
|| released == QStyle::SC_GroupBoxCheckBox);
d->pressedControl = QStyle::SC_None;
diff --git a/src/widgets/widgets/qgroupbox.h b/src/widgets/widgets/qgroupbox.h
index bd8394b43b..dd4a5b8a93 100644
--- a/src/widgets/widgets/qgroupbox.h
+++ b/src/widgets/widgets/qgroupbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGROUPBOX_H
#define QGROUPBOX_H
@@ -94,7 +58,7 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
- void initStyleOption(QStyleOptionGroupBox *option) const;
+ virtual void initStyleOption(QStyleOptionGroupBox *option) const;
private:
diff --git a/src/widgets/widgets/qkeysequenceedit.cpp b/src/widgets/widgets/qkeysequenceedit.cpp
index b63b0b4d72..65ed7a465a 100644
--- a/src/widgets/widgets/qkeysequenceedit.cpp
+++ b/src/widgets/widgets/qkeysequenceedit.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Ivan Komissarov.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Ivan Komissarov.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qkeysequenceedit.h"
#include "qkeysequenceedit_p.h"
@@ -47,7 +11,7 @@
QT_BEGIN_NAMESPACE
-Q_STATIC_ASSERT(QKeySequencePrivate::MaxKeyCount == 4); // assumed by the code around here
+static_assert(QKeySequencePrivate::MaxKeyCount == 4); // assumed by the code around here
void QKeySequenceEditPrivate::init()
{
@@ -55,15 +19,23 @@ void QKeySequenceEditPrivate::init()
lineEdit = new QLineEdit(q);
lineEdit->setObjectName(QStringLiteral("qt_keysequenceedit_lineedit"));
+ lineEdit->setClearButtonEnabled(false);
+ q->connect(lineEdit, &QLineEdit::textChanged, q, [q](const QString& text) {
+ // Clear the shortcut if the user clicked on the clear icon
+ if (text.isEmpty())
+ q->clear();
+ });
+
keyNum = 0;
prevKey = -1;
releaseTimer = 0;
+ finishingKeyCombinations = {Qt::Key_Tab, Qt::Key_Backtab};
QVBoxLayout *layout = new QVBoxLayout(q);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(lineEdit);
- key[0] = key[1] = key[2] = key[3] = 0;
+ std::fill_n(key, QKeySequencePrivate::MaxKeyCount, QKeyCombination::fromCombined(0));
lineEdit->setFocusProxy(q);
lineEdit->installEventFilter(q);
@@ -73,8 +45,6 @@ void QKeySequenceEditPrivate::init()
q->setFocusPolicy(Qt::StrongFocus);
q->setAttribute(Qt::WA_MacShowFocusRect, true);
q->setAttribute(Qt::WA_InputMethodEnabled, false);
-
- // TODO: add clear button
}
int QKeySequenceEditPrivate::translateModifiers(Qt::KeyboardModifiers state, const QString &text)
@@ -167,6 +137,9 @@ QKeySequenceEdit::~QKeySequenceEdit()
\brief This property contains the currently chosen key sequence.
The shortcut can be changed by the user or via setter function.
+
+ \note If the QKeySequence is longer than the maximumSequenceLength
+ property, the key sequence is truncated.
*/
QKeySequence QKeySequenceEdit::keySequence() const
{
@@ -175,6 +148,89 @@ QKeySequence QKeySequenceEdit::keySequence() const
return d->keySequence;
}
+/*!
+ \property QKeySequenceEdit::clearButtonEnabled
+ \brief Whether the key sequence edit displays a clear button when it is not
+ empty.
+
+ If enabled, the key sequence edit displays a trailing \e clear button when
+ it contains some text, otherwise the line edit does not show a clear button
+ (the default).
+
+ \since 6.4
+*/
+void QKeySequenceEdit::setClearButtonEnabled(bool enable)
+{
+ Q_D(QKeySequenceEdit);
+
+ d->lineEdit->setClearButtonEnabled(enable);
+}
+
+bool QKeySequenceEdit::isClearButtonEnabled() const
+{
+ Q_D(const QKeySequenceEdit);
+
+ return d->lineEdit->isClearButtonEnabled();
+}
+
+/*!
+ \property QKeySequenceEdit::maximumSequenceLength
+ \brief The maximum sequence length.
+
+ The maximum number of key sequences a user can enter. The value needs to
+ be between 1 and 4, with 4 being the default.
+
+ \since 6.5
+*/
+qsizetype QKeySequenceEdit::maximumSequenceLength() const
+{
+ Q_D(const QKeySequenceEdit);
+ return d->maximumSequenceLength;
+}
+
+void QKeySequenceEdit::setMaximumSequenceLength(qsizetype count)
+{
+ Q_D(QKeySequenceEdit);
+
+ if (count < 1 || count > QKeySequencePrivate::MaxKeyCount) {
+ qWarning("QKeySequenceEdit: maximumSequenceLength %lld is out of range (1..%d)",
+ qlonglong(count), QKeySequencePrivate::MaxKeyCount);
+ return;
+ }
+ d->maximumSequenceLength = int(count);
+ if (d->keyNum > count) {
+ for (qsizetype i = d->keyNum; i < count; ++i)
+ d->key[i] = QKeyCombination::fromCombined(0);
+ d->keyNum = count;
+ d->rebuildKeySequence();
+ }
+}
+
+/*!
+ \property QKeySequenceEdit::finishingKeyCombinations
+ \brief The list of key combinations that finish editing the key sequences.
+
+ Any combination in the list will finish the editing of key sequences.
+ All other key combinations can be recorded as part of a key sequence. By
+ default, Qt::Key_Tab and Qt::Key_Backtab will finish recording the key
+ sequence.
+
+ \since 6.5
+*/
+void QKeySequenceEdit::setFinishingKeyCombinations(const QList<QKeyCombination> &finishingKeyCombinations)
+{
+ Q_D(QKeySequenceEdit);
+
+ d->finishingKeyCombinations = finishingKeyCombinations;
+}
+
+QList<QKeyCombination> QKeySequenceEdit::finishingKeyCombinations() const
+{
+ Q_D(const QKeySequenceEdit);
+
+ return d->finishingKeyCombinations;
+}
+
void QKeySequenceEdit::setKeySequence(const QKeySequence &keySequence)
{
Q_D(QKeySequenceEdit);
@@ -184,16 +240,24 @@ void QKeySequenceEdit::setKeySequence(const QKeySequence &keySequence)
if (d->keySequence == keySequence)
return;
- d->keySequence = keySequence;
+ const auto desiredCount = keySequence.count();
+ if (desiredCount > d->maximumSequenceLength) {
+ qWarning("QKeySequenceEdit: setting a key sequence of length %d "
+ "when maximumSequenceLength is %d, truncating.",
+ desiredCount, d->maximumSequenceLength);
+ }
- d->key[0] = d->key[1] = d->key[2] = d->key[3] = 0;
- d->keyNum = keySequence.count();
+ d->keyNum = std::min(desiredCount, d->maximumSequenceLength);
for (int i = 0; i < d->keyNum; ++i)
d->key[i] = keySequence[i];
+ for (int i = d->keyNum; i < QKeySequencePrivate::MaxKeyCount; ++i)
+ d->key[i] = QKeyCombination::fromCombined(0);
- d->lineEdit->setText(keySequence.toString(QKeySequence::NativeText));
+ d->rebuildKeySequence();
- emit keySequenceChanged(keySequence);
+ d->lineEdit->setText(d->keySequence.toString(QKeySequence::NativeText));
+
+ emit keySequenceChanged(d->keySequence);
}
/*!
@@ -218,13 +282,23 @@ void QKeySequenceEdit::clear()
*/
bool QKeySequenceEdit::event(QEvent *e)
{
+ Q_D(const QKeySequenceEdit);
+
switch (e->type()) {
case QEvent::Shortcut:
return true;
case QEvent::ShortcutOverride:
e->accept();
return true;
- default :
+ case QEvent::KeyPress: {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+ if (!d->finishingKeyCombinations.contains(ke->keyCombination())) {
+ keyPressEvent(ke);
+ return true;
+ }
+ }
+ break;
+ default:
break;
}
@@ -238,6 +312,11 @@ void QKeySequenceEdit::keyPressEvent(QKeyEvent *e)
{
Q_D(QKeySequenceEdit);
+ if (d->finishingKeyCombinations.contains(e->keyCombination())) {
+ d->finishEditing();
+ return;
+ }
+
int nextKey = e->key();
if (d->prevKey == -1) {
@@ -261,38 +340,38 @@ void QKeySequenceEdit::keyPressEvent(QKeyEvent *e)
return;
}
- if (d->keyNum >= QKeySequencePrivate::MaxKeyCount)
+ if (d->keyNum >= d->maximumSequenceLength)
return;
if (e->modifiers() & Qt::ShiftModifier) {
- QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
- int pkTotal = possibleKeys.count();
+ const QList<QKeyCombination> possibleKeys = QKeyMapper::possibleKeys(e);
+ int pkTotal = possibleKeys.size();
if (!pkTotal)
return;
bool found = false;
for (int i = 0; i < possibleKeys.size(); ++i) {
- if (possibleKeys.at(i) - nextKey == int(e->modifiers())
- || (possibleKeys.at(i) == nextKey && e->modifiers() == Qt::ShiftModifier)) {
- nextKey = possibleKeys.at(i);
+ const int key = possibleKeys.at(i).toCombined();
+ if (key - nextKey == int(e->modifiers())
+ || (key == nextKey && e->modifiers() == Qt::ShiftModifier)) {
+ nextKey = key;
found = true;
break;
}
}
// Use as fallback
if (!found)
- nextKey = possibleKeys.first();
+ nextKey = possibleKeys.first().toCombined();
} else {
nextKey |= d->translateModifiers(e->modifiers(), e->text());
}
- d->key[d->keyNum] = nextKey;
+ d->key[d->keyNum] = QKeyCombination::fromCombined(nextKey);
d->keyNum++;
- QKeySequence key(d->key[0], d->key[1], d->key[2], d->key[3]);
- d->keySequence = key;
- QString text = key.toString(QKeySequence::NativeText);
- if (d->keyNum < QKeySequencePrivate::MaxKeyCount) {
+ d->rebuildKeySequence();
+ QString text = d->keySequence.toString(QKeySequence::NativeText);
+ if (d->keyNum < d->maximumSequenceLength) {
//: This text is an "unfinished" shortcut, expands like "Ctrl+A, ..."
text = tr("%1, ...").arg(text);
}
@@ -308,7 +387,7 @@ void QKeySequenceEdit::keyReleaseEvent(QKeyEvent *e)
Q_D(QKeySequenceEdit);
if (d->prevKey == e->key()) {
- if (d->keyNum < QKeySequencePrivate::MaxKeyCount)
+ if (d->keyNum < d->maximumSequenceLength)
d->releaseTimer = startTimer(1000);
else
d->finishEditing();
@@ -330,6 +409,17 @@ void QKeySequenceEdit::timerEvent(QTimerEvent *e)
QWidget::timerEvent(e);
}
+/*!
+ \reimp
+*/
+void QKeySequenceEdit::focusOutEvent(QFocusEvent *e)
+{
+ Q_D(QKeySequenceEdit);
+ if (e->reason() != Qt::PopupFocusReason)
+ d->finishEditing();
+ QWidget::focusOutEvent(e);
+}
+
QT_END_NAMESPACE
#include "moc_qkeysequenceedit.cpp"
diff --git a/src/widgets/widgets/qkeysequenceedit.h b/src/widgets/widgets/qkeysequenceedit.h
index 85d76f14a3..db0c4c80dd 100644
--- a/src/widgets/widgets/qkeysequenceedit.h
+++ b/src/widgets/widgets/qkeysequenceedit.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Ivan Komissarov.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Ivan Komissarov.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKEYSEQUENCEEDIT_H
#define QKEYSEQUENCEEDIT_H
@@ -52,7 +16,11 @@ class QKeySequenceEditPrivate;
class Q_WIDGETS_EXPORT QKeySequenceEdit : public QWidget
{
Q_OBJECT
- Q_PROPERTY(QKeySequence keySequence READ keySequence WRITE setKeySequence NOTIFY keySequenceChanged USER true)
+ Q_PROPERTY(QKeySequence keySequence READ keySequence WRITE setKeySequence
+ NOTIFY keySequenceChanged USER true)
+ Q_PROPERTY(bool clearButtonEnabled READ isClearButtonEnabled WRITE setClearButtonEnabled)
+ Q_PROPERTY(qsizetype maximumSequenceLength READ maximumSequenceLength WRITE setMaximumSequenceLength)
+ Q_PROPERTY(QList<QKeyCombination> finishingKeyCombinations READ finishingKeyCombinations WRITE setFinishingKeyCombinations)
public:
explicit QKeySequenceEdit(QWidget *parent = nullptr);
@@ -60,10 +28,18 @@ public:
~QKeySequenceEdit();
QKeySequence keySequence() const;
+ qsizetype maximumSequenceLength() const;
+
+ void setClearButtonEnabled(bool enable);
+ bool isClearButtonEnabled() const;
+
+ void setFinishingKeyCombinations(const QList<QKeyCombination> &finishingKeyCombinations);
+ QList<QKeyCombination> finishingKeyCombinations() const;
public Q_SLOTS:
void setKeySequence(const QKeySequence &keySequence);
void clear();
+ void setMaximumSequenceLength(qsizetype count);
Q_SIGNALS:
void editingFinished();
@@ -76,6 +52,7 @@ protected:
void keyPressEvent(QKeyEvent *) override;
void keyReleaseEvent(QKeyEvent *) override;
void timerEvent(QTimerEvent *) override;
+ void focusOutEvent(QFocusEvent *) override;
private:
Q_DISABLE_COPY(QKeySequenceEdit)
diff --git a/src/widgets/widgets/qkeysequenceedit_p.h b/src/widgets/widgets/qkeysequenceedit_p.h
index 7af034e735..bdf3bfe788 100644
--- a/src/widgets/widgets/qkeysequenceedit_p.h
+++ b/src/widgets/widgets/qkeysequenceedit_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Ivan Komissarov.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Ivan Komissarov.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKEYSEQUENCEEDIT_P_H
#define QKEYSEQUENCEEDIT_P_H
@@ -72,13 +36,17 @@ public:
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
void resetState();
void finishEditing();
+ void rebuildKeySequence()
+ { keySequence = QKeySequence(key[0], key[1], key[2], key[3]); }
QLineEdit *lineEdit;
QKeySequence keySequence;
int keyNum;
- int key[QKeySequencePrivate::MaxKeyCount];
+ int maximumSequenceLength = QKeySequencePrivate::MaxKeyCount;
+ QKeyCombination key[QKeySequencePrivate::MaxKeyCount];
int prevKey;
int releaseTimer;
+ QList<QKeyCombination> finishingKeyCombinations;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index 7bd7283adf..f4155de0a0 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpainter.h"
#include "qevent.h"
@@ -54,22 +18,24 @@
#include "private/qstylesheetstyle_p.h"
#include <qmath.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <qaccessible.h>
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QLabelPrivate::QLabelPrivate()
: QFramePrivate(),
sh(),
msh(),
text(),
- pixmap(nullptr),
- scaledpixmap(nullptr),
- cachedimage(nullptr),
+ pixmap(),
+ scaledpixmap(),
+ cachedimage(),
#ifndef QT_NO_PICTURE
- picture(nullptr),
+ picture(),
#endif
#if QT_CONFIG(movie)
movie(),
@@ -100,7 +66,8 @@ QLabelPrivate::QLabelPrivate()
validCursor(false),
onAnchor(false),
#endif
- openExternalLinks(false)
+ openExternalLinks(false),
+ resourceProvider(nullptr)
{
}
@@ -182,22 +149,35 @@ QLabelPrivate::~QLabelPrivate()
was a button (inheriting from QAbstractButton), triggering the
mnemonic would emulate a button click.
- \sa QLineEdit, QTextEdit, QPixmap, QMovie,
- {fowler}{GUI Design Handbook: Label}
+ \sa QLineEdit, QTextEdit, QPixmap, QMovie
*/
#ifndef QT_NO_PICTURE
/*!
- Returns the label's picture or nullptr if the label doesn't have a
- picture.
+ \fn QPicture QLabel::picture(Qt::ReturnByValueConstant) const
+ \deprecated Use the overload without argument instead.
+ \since 5.15
+
+ Returns the label's picture.
+
+ Previously, Qt provided a version of \c picture() which returned the picture
+ by-pointer. That version is now removed. This overload allowed to
+ explicitly differentiate between the by-pointer function and the by-value.
*/
-const QPicture *QLabel::picture() const
+/*!
+ \since 6.0
+
+ Returns the label's picture.
+*/
+QPicture QLabel::picture() const
{
Q_D(const QLabel);
- return d->picture;
+ if (d->picture)
+ return *(d->picture);
+ return QPicture();
}
-#endif
+#endif // QT_NO_PICTURE
/*!
@@ -324,7 +304,7 @@ void QLabel::setText(const QString &text)
d->updateLabel();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (accessibleName().isEmpty()) {
QAccessibleEvent event(this, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
@@ -351,9 +331,7 @@ void QLabel::clear()
/*!
\property QLabel::pixmap
- \brief the label's pixmap
-
- If no pixmap has been set this will return nullptr.
+ \brief the label's pixmap.
Setting the pixmap clears any previous content. The buddy
shortcut, if any, is disabled.
@@ -363,21 +341,37 @@ void QLabel::setPixmap(const QPixmap &pixmap)
Q_D(QLabel);
if (!d->pixmap || d->pixmap->cacheKey() != pixmap.cacheKey()) {
d->clearContents();
- d->pixmap = new QPixmap(pixmap);
+ d->pixmap = pixmap;
}
- if (d->pixmap->depth() == 1 && !d->pixmap->mask())
- d->pixmap->setMask(*((QBitmap *)d->pixmap));
-
d->updateLabel();
}
-const QPixmap *QLabel::pixmap() const
+QPixmap QLabel::pixmap() const
{
Q_D(const QLabel);
- return d->pixmap;
+ if (d->pixmap)
+ return *(d->pixmap);
+ return QPixmap();
}
+/*!
+ \fn QPixmap QLabel::pixmap(Qt::ReturnByValueConstant) const
+
+ \deprecated Use the overload without argument instead.
+ \since 5.15
+
+ Returns the label's pixmap.
+
+ Previously, Qt provided a version of \c pixmap() which returned the pixmap
+ by-pointer. That version has now been removed. This overload allowed to
+ explicitly differentiate between the by-pointer function and the by-value.
+
+ \code
+ QPixmap pixmapVal = label->pixmap(Qt::ReturnByValue);
+ \endcode
+*/
+
#ifndef QT_NO_PICTURE
/*!
Sets the label contents to \a picture. Any previous content is
@@ -392,7 +386,7 @@ void QLabel::setPicture(const QPicture &picture)
{
Q_D(QLabel);
d->clearContents();
- d->picture = new QPicture(picture);
+ d->picture = picture;
d->updateLabel();
}
@@ -560,7 +554,7 @@ void QLabel::setMargin(int margin)
QSize QLabelPrivate::sizeForWidth(int w) const
{
Q_Q(const QLabel);
- if(q->minimumWidth() > 0)
+ if (q->minimumWidth() > 0)
w = qMax(w, q->minimumWidth());
QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);
@@ -572,7 +566,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const
if (pixmap && !pixmap->isNull()) {
br = pixmap->rect();
- br.setSize(br.size() / pixmap->devicePixelRatio());
+ br.setSize(pixmap->deviceIndependentSize().toSize());
#ifndef QT_NO_PICTURE
} else if (picture && !picture->isNull()) {
br = picture->boundingRect();
@@ -580,7 +574,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const
#if QT_CONFIG(movie)
} else if (movie && !movie->currentPixmap().isNull()) {
br = movie->currentPixmap().rect();
- br.setSize(br.size() / movie->currentPixmap().devicePixelRatio());
+ br.setSize(movie->currentPixmap().deviceIndependentSize().toSize());
#endif
} else if (isTextLabel) {
int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));
@@ -588,7 +582,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const
int m = indent;
if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
- m = fm.horizontalAdvance(QLatin1Char('x')) - margin*2;
+ m = fm.horizontalAdvance(u'x') - margin*2;
if (m > 0) {
if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
hextra += m;
@@ -994,6 +988,9 @@ bool QLabel::event(QEvent *e)
) {
d->setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
d->updateLabel();
+ } else if (type == QEvent::Polish) {
+ if (d->needTextControl())
+ d->ensureTextControl();
}
return QFrame::event(e);
@@ -1094,17 +1091,19 @@ void QLabel::paintEvent(QPaintEvent *)
#endif
if (d->pixmap && !d->pixmap->isNull()) {
QPixmap pix;
- if (d->scaledcontents) {
- QSize scaledSize = cr.size() * devicePixelRatioF();
+ const qreal dpr = devicePixelRatio();
+ if (d->scaledcontents || dpr != d->pixmap->devicePixelRatio()) {
+ QSize scaledSize = d->scaledcontents ? (cr.size() * dpr)
+ : (d->pixmap->size() * (dpr / d->pixmap->devicePixelRatio()));
if (!d->scaledpixmap || d->scaledpixmap->size() != scaledSize) {
if (!d->cachedimage)
- d->cachedimage = new QImage(d->pixmap->toImage());
- delete d->scaledpixmap;
+ d->cachedimage = d->pixmap->toImage();
+ d->scaledpixmap.reset();
QImage scaledImage =
d->cachedimage->scaled(scaledSize,
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- d->scaledpixmap = new QPixmap(QPixmap::fromImage(std::move(scaledImage)));
- d->scaledpixmap->setDevicePixelRatio(devicePixelRatioF());
+ d->scaledpixmap = QPixmap::fromImage(std::move(scaledImage));
+ d->scaledpixmap->setDevicePixelRatio(dpr);
}
pix = *d->scaledpixmap;
} else
@@ -1172,12 +1171,14 @@ void QLabel::setBuddy(QWidget *buddy)
Q_D(QLabel);
if (d->buddy)
- disconnect(d->buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted()));
+ QObjectPrivate::disconnect(d->buddy, &QObject::destroyed,
+ d, &QLabelPrivate::buddyDeleted);
d->buddy = buddy;
if (buddy)
- connect(buddy, SIGNAL(destroyed()), this, SLOT(_q_buddyDeleted()));
+ QObjectPrivate::connect(buddy, &QObject::destroyed,
+ d, &QLabelPrivate::buddyDeleted);
if (d->isTextLabel) {
if (d->shortcutId)
@@ -1213,14 +1214,14 @@ void QLabelPrivate::updateShortcut()
// But then we do want to hide the ampersands, so we can't use shortcutId.
hasShortcut = false;
- if (!text.contains(QLatin1Char('&')))
+ if (!text.contains(u'&'))
return;
hasShortcut = true;
shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
}
-void QLabelPrivate::_q_buddyDeleted()
+void QLabelPrivate::buddyDeleted()
{
Q_Q(QLabel);
q->setBuddy(nullptr);
@@ -1229,7 +1230,7 @@ void QLabelPrivate::_q_buddyDeleted()
#endif // QT_NO_SHORTCUT
#if QT_CONFIG(movie)
-void QLabelPrivate::_q_movieUpdated(const QRect& rect)
+void QLabelPrivate::movieUpdated(const QRect &rect)
{
Q_Q(QLabel);
if (movie && movie->isValid()) {
@@ -1252,12 +1253,12 @@ void QLabelPrivate::_q_movieUpdated(const QRect& rect)
}
}
-void QLabelPrivate::_q_movieResized(const QSize& size)
+void QLabelPrivate::movieResized(const QSize &size)
{
Q_Q(QLabel);
- q->update(); //we need to refresh the whole background in case the new size is smaler
+ q->update(); //we need to refresh the whole background in case the new size is smaller
valid_hints = false;
- _q_movieUpdated(QRect(QPoint(0,0), size));
+ movieUpdated(QRect(QPoint(0,0), size));
q->updateGeometry();
}
@@ -1279,8 +1280,10 @@ void QLabel::setMovie(QMovie *movie)
return;
d->movie = movie;
- connect(movie, SIGNAL(resized(QSize)), this, SLOT(_q_movieResized(QSize)));
- connect(movie, SIGNAL(updated(QRect)), this, SLOT(_q_movieUpdated(QRect)));
+ d->movieConnections = {
+ QObjectPrivate::connect(movie, &QMovie::resized, d, &QLabelPrivate::movieResized),
+ QObjectPrivate::connect(movie, &QMovie::updated, d, &QLabelPrivate::movieUpdated),
+ };
// Assume that if the movie is running,
// resize/update signals will come soon enough
@@ -1304,15 +1307,11 @@ void QLabelPrivate::clearContents()
hasShortcut = false;
#ifndef QT_NO_PICTURE
- delete picture;
- picture = nullptr;
+ picture.reset();
#endif
- delete scaledpixmap;
- scaledpixmap = nullptr;
- delete cachedimage;
- cachedimage = nullptr;
- delete pixmap;
- pixmap = nullptr;
+ scaledpixmap.reset();
+ cachedimage.reset();
+ pixmap.reset();
text.clear();
Q_Q(QLabel);
@@ -1322,10 +1321,8 @@ void QLabelPrivate::clearContents()
shortcutId = 0;
#endif
#if QT_CONFIG(movie)
- if (movie) {
- QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
- QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
- }
+ for (const auto &conn : std::as_const(movieConnections))
+ QObject::disconnect(conn);
movie = nullptr;
#endif
#ifndef QT_NO_CURSOR
@@ -1390,12 +1387,38 @@ void QLabel::setTextFormat(Qt::TextFormat format)
}
/*!
+ \since 6.1
+
+ Returns the resource provider for rich text of this label.
+*/
+QTextDocument::ResourceProvider QLabel::resourceProvider() const
+{
+ Q_D(const QLabel);
+ return d->control ? d->control->document()->resourceProvider() : d->resourceProvider;
+}
+
+/*!
+ \since 6.1
+
+ Sets the \a provider of resources for rich text of this label.
+
+ \note The label \e{does not} take ownership of the \a provider.
+*/
+void QLabel::setResourceProvider(const QTextDocument::ResourceProvider &provider)
+{
+ Q_D(QLabel);
+ d->resourceProvider = provider;
+ if (d->control != nullptr)
+ d->control->document()->setResourceProvider(provider);
+}
+
+/*!
\reimp
*/
void QLabel::changeEvent(QEvent *ev)
{
Q_D(QLabel);
- if(ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
+ if (ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
if (d->isTextLabel) {
if (d->control)
d->control->document()->setDefaultFont(font());
@@ -1432,10 +1455,8 @@ void QLabel::setScaledContents(bool enable)
return;
d->scaledcontents = enable;
if (!enable) {
- delete d->scaledpixmap;
- d->scaledpixmap = nullptr;
- delete d->cachedimage;
- d->cachedimage = nullptr;
+ d->scaledpixmap.reset();
+ d->cachedimage.reset();
}
update(contentsRect());
}
@@ -1462,7 +1483,7 @@ QRect QLabelPrivate::documentRect() const
: q->layoutDirection(), QFlag(this->align));
int m = indent;
if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
- m = q->fontMetrics().horizontalAdvance(QLatin1Char('x')) / 2 - margin;
+ m = q->fontMetrics().horizontalAdvance(u'x') / 2 - margin;
if (m > 0) {
if (align & Qt::AlignLeft)
cr.setLeft(cr.left() + m);
@@ -1504,11 +1525,11 @@ void QLabelPrivate::ensureTextPopulated() const
int from = 0;
bool found = false;
QTextCursor cursor;
- while (!(cursor = control->document()->find((QLatin1String("&")), from)).isNull()) {
+ while (!(cursor = control->document()->find(("&"_L1), from)).isNull()) {
cursor.deleteChar(); // remove the ampersand
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
from = cursor.position();
- if (!found && cursor.selectedText() != QLatin1String("&")) { //not a second &
+ if (!found && cursor.selectedText() != "&"_L1) { //not a second &
found = true;
shortcutCursor = cursor;
}
@@ -1555,16 +1576,18 @@ void QLabelPrivate::ensureTextControl() const
control = new QWidgetTextControl(const_cast<QLabel *>(q));
control->document()->setUndoRedoEnabled(false);
control->document()->setDefaultFont(q->font());
+ if (resourceProvider != nullptr)
+ control->document()->setResourceProvider(resourceProvider);
control->setTextInteractionFlags(textInteractionFlags);
control->setOpenExternalLinks(openExternalLinks);
control->setPalette(q->palette());
control->setFocus(q->hasFocus());
- QObject::connect(control, SIGNAL(updateRequest(QRectF)),
- q, SLOT(update()));
- QObject::connect(control, SIGNAL(linkHovered(QString)),
- q, SLOT(_q_linkHovered(QString)));
- QObject::connect(control, SIGNAL(linkActivated(QString)),
- q, SIGNAL(linkActivated(QString)));
+ QObject::connect(control, &QWidgetTextControl::updateRequest,
+ q, qOverload<>(&QLabel::update));
+ QObject::connect(control, &QWidgetTextControl::linkActivated,
+ q, &QLabel::linkActivated);
+ QObjectPrivate::connect(control, &QWidgetTextControl::linkHovered,
+ this, &QLabelPrivate::linkHovered);
textLayoutDirty = true;
textDirty = true;
}
@@ -1580,7 +1603,7 @@ void QLabelPrivate::sendControlEvent(QEvent *e)
control->processEvent(e, -layoutRect().topLeft(), q);
}
-void QLabelPrivate::_q_linkHovered(const QString &anchor)
+void QLabelPrivate::linkHovered(const QString &anchor)
{
Q_Q(QLabel);
#ifndef QT_NO_CURSOR
@@ -1611,7 +1634,7 @@ QRectF QLabelPrivate::layoutRect() const
if (!control)
return cr;
ensureTextLayouted();
- // Caculate y position manually
+ // Calculate y position manually
qreal rh = control->document()->documentLayout()->documentSize().height();
qreal yo = 0;
if (align & Qt::AlignVCenter)
@@ -1631,16 +1654,10 @@ QPoint QLabelPrivate::layoutPoint(const QPoint& p) const
#ifndef QT_NO_CONTEXTMENU
QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
{
- QString linkToCopy;
- QPoint p;
- if (control && effectiveTextFormat != Qt::PlainText) {
- p = layoutPoint(pos);
- linkToCopy = control->document()->documentLayout()->anchorAt(p);
- }
-
- if (linkToCopy.isEmpty() && !control)
+ if (!control)
return nullptr;
+ const QPoint p = layoutPoint(pos);
return control->createStandardContextMenu(p, q_func());
}
#endif
diff --git a/src/widgets/widgets/qlabel.h b/src/widgets/widgets/qlabel.h
index 2f5db5a7d3..3749ec366a 100644
--- a/src/widgets/widgets/qlabel.h
+++ b/src/widgets/widgets/qlabel.h
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLABEL_H
#define QLABEL_H
#include <QtWidgets/qtwidgetsglobal.h>
#include <QtWidgets/qframe.h>
+#include <QtGui/qpicture.h>
+#include <QtGui/qtextdocument.h>
QT_REQUIRE_CONFIG(label);
@@ -62,7 +28,8 @@ class Q_WIDGETS_EXPORT QLabel : public QFrame
Q_PROPERTY(int margin READ margin WRITE setMargin)
Q_PROPERTY(int indent READ indent WRITE setIndent)
Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
- Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags
+ WRITE setTextInteractionFlags)
Q_PROPERTY(bool hasSelectedText READ hasSelectedText)
Q_PROPERTY(QString selectedText READ selectedText)
@@ -72,9 +39,17 @@ public:
~QLabel();
QString text() const;
- const QPixmap *pixmap() const;
+
+#if QT_DEPRECATED_SINCE(6,6)
+ QPixmap pixmap(Qt::ReturnByValueConstant) const { return pixmap(); }
+#endif
+ QPixmap pixmap() const;
+
#ifndef QT_NO_PICTURE
- const QPicture *picture() const;
+#if QT_DEPRECATED_SINCE(6,6)
+ QPicture picture(Qt::ReturnByValueConstant) const { return picture(); }
+#endif
+ QPicture picture() const;
#endif
#if QT_CONFIG(movie)
QMovie *movie() const;
@@ -83,6 +58,9 @@ public:
Qt::TextFormat textFormat() const;
void setTextFormat(Qt::TextFormat);
+ QTextDocument::ResourceProvider resourceProvider() const;
+ void setResourceProvider(const QTextDocument::ResourceProvider &provider);
+
Qt::Alignment alignment() const;
void setAlignment(Qt::Alignment);
@@ -152,15 +130,6 @@ protected:
private:
Q_DISABLE_COPY(QLabel)
Q_DECLARE_PRIVATE(QLabel)
-#if QT_CONFIG(movie)
- Q_PRIVATE_SLOT(d_func(), void _q_movieUpdated(const QRect&))
- Q_PRIVATE_SLOT(d_func(), void _q_movieResized(const QSize&))
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_linkHovered(const QString &))
-
-#ifndef QT_NO_SHORTCUT
- Q_PRIVATE_SLOT(d_func(), void _q_buddyDeleted())
-#endif
friend class QTipLabel;
friend class QMessageBoxPrivate;
friend class QBalloonTip;
diff --git a/src/widgets/widgets/qlabel_p.h b/src/widgets/widgets/qlabel_p.h
index 6b3fbc5f0c..fb6ccb04eb 100644
--- a/src/widgets/widgets/qlabel_p.h
+++ b/src/widgets/widgets/qlabel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLABEL_P_H
#define QLABEL_P_H
@@ -69,6 +33,11 @@
#include "qmenu.h"
#endif
+#include <QtCore/qpointer.h>
+
+#include <array>
+#include <optional>
+
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QLabelPrivate : public QFramePrivate
@@ -84,17 +53,19 @@ public:
QSize sizeForWidth(int w) const;
#if QT_CONFIG(movie)
- void _q_movieUpdated(const QRect&);
- void _q_movieResized(const QSize&);
+ void movieUpdated(const QRect &rect);
+ void movieResized(const QSize &size);
#endif
#ifndef QT_NO_SHORTCUT
void updateShortcut();
- void _q_buddyDeleted();
+ void buddyDeleted();
#endif
inline bool needTextControl() const {
+ Q_Q(const QLabel);
return isTextLabel
&& (effectiveTextFormat != Qt::PlainText
- || (textInteractionFlags & (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard)));
+ || (textInteractionFlags & (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard))
+ || q->focusPolicy() != Qt::NoFocus);
}
void ensureTextPopulated() const;
@@ -102,7 +73,7 @@ public:
void ensureTextControl() const;
void sendControlEvent(QEvent *e);
- void _q_linkHovered(const QString &link);
+ void linkHovered(const QString &link);
QRectF layoutRect() const;
QRect documentRect() const;
@@ -115,14 +86,15 @@ public:
mutable QSize sh;
mutable QSize msh;
QString text;
- QPixmap *pixmap;
- QPixmap *scaledpixmap;
- QImage *cachedimage;
+ std::optional<QPixmap> pixmap;
+ std::optional<QPixmap> scaledpixmap;
+ std::optional<QImage> cachedimage;
#ifndef QT_NO_PICTURE
- QPicture *picture;
+ std::optional<QPicture> picture;
#endif
#if QT_CONFIG(movie)
QPointer<QMovie> movie;
+ std::array<QMetaObject::Connection, 2> movieConnections;
#endif
mutable QWidgetTextControl *control;
mutable QTextCursor shortcutCursor;
@@ -152,6 +124,7 @@ public:
#endif
uint openExternalLinks : 1;
// <-- space for more bit field values here
+ QTextDocument::ResourceProvider resourceProvider;
friend class QMessageBoxPrivate;
};
diff --git a/src/widgets/widgets/qlcdnumber.cpp b/src/widgets/widgets/qlcdnumber.cpp
index 3ddada4514..3a65b06415 100644
--- a/src/widgets/widgets/qlcdnumber.cpp
+++ b/src/widgets/widgets/qlcdnumber.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlcdnumber.h"
@@ -52,7 +16,7 @@ public:
void init();
void internalSetString(const QString& s);
void drawString(const QString& s, QPainter &, QBitArray * = nullptr, bool = true);
- //void drawString(const QString &, QPainter &, QBitArray * = 0) const;
+ //void drawString(const QString &, QPainter &, QBitArray * = nullptr) const;
void drawDigit(const QPoint &, QPainter &, int, char, char = ' ');
void drawSegment(const QPoint &, char, QPainter &, int, bool = false);
@@ -105,7 +69,7 @@ public:
Incidentally, QLCDNumber is the very oldest part of Qt, tracing
its roots back to a BASIC program on the \l{Sinclair Spectrum}{Sinclair Spectrum}.
- \sa QLabel, QFrame, {Digital Clock Example}, {Tetrix Example}
+ \sa QLabel, QFrame
*/
/*!
@@ -179,25 +143,25 @@ static QString int2string(int num, int base, int ndigits, bool *oflow)
} while (n != 0);
len = ndigits - len;
if (len > 0)
- s += QString(len, QLatin1Char(' '));
- s += QLatin1String(p);
+ s += QString(len, u' ');
+ s += QLatin1StringView(p);
}
break;
}
if (negative) {
- for (int i=0; i<(int)s.length(); i++) {
- if (s[i] != QLatin1Char(' ')) {
+ for (int i=0; i<(int)s.size(); i++) {
+ if (s[i] != u' ') {
if (i != 0) {
- s[i-1] = QLatin1Char('-');
+ s[i-1] = u'-';
} else {
- s.insert(0, QLatin1Char('-'));
+ s.insert(0, u'-');
}
break;
}
}
}
if (oflow)
- *oflow = (int)s.length() > ndigits;
+ *oflow = (int)s.size() > ndigits;
return s;
}
@@ -217,15 +181,15 @@ static QString double2string(double num, int base, int ndigits, bool *oflow)
int nd = ndigits;
do {
s = QString::asprintf("%*.*g", ndigits, nd, num);
- int i = s.indexOf(QLatin1Char('e'));
- if (i > 0 && s[i+1]==QLatin1Char('+')) {
- s[i] = QLatin1Char(' ');
- s[i+1] = QLatin1Char('e');
+ qsizetype i = s.indexOf(u'e');
+ if (i > 0 && s[i+1]==u'+') {
+ s[i] = u' ';
+ s[i+1] = u'e';
}
- } while (nd-- && (int)s.length() > ndigits);
+ } while (nd-- && (int)s.size() > ndigits);
}
if (oflow)
- *oflow = (int)s.length() > ndigits;
+ *oflow = (int)s.size() > ndigits;
return s;
}
@@ -408,9 +372,9 @@ void QLCDNumber::setDigitCount(int numDigits)
}
if (d->digitStr.isNull()) { // from constructor
d->ndigits = numDigits;
- d->digitStr.fill(QLatin1Char(' '), d->ndigits);
+ d->digitStr.fill(u' ', d->ndigits);
d->points.fill(0, d->ndigits);
- d->digitStr[d->ndigits - 1] = QLatin1Char('0'); // "0" is the default number
+ d->digitStr[d->ndigits - 1] = u'0'; // "0" is the default number
} else {
bool doDisplay = d->ndigits == 0;
if (numDigits == d->ndigits) // no change
@@ -420,7 +384,7 @@ void QLCDNumber::setDigitCount(int numDigits)
if (numDigits > d->ndigits) { // expand
dif = numDigits - d->ndigits;
QString buf;
- buf.fill(QLatin1Char(' '), dif);
+ buf.fill(u' ', dif);
d->digitStr.insert(0, buf);
d->points.resize(numDigits);
for (i=numDigits-1; i>=dif; i--)
@@ -432,7 +396,7 @@ void QLCDNumber::setDigitCount(int numDigits)
d->digitStr = d->digitStr.right(numDigits);
QBitArray tmpPoints = d->points;
d->points.resize(numDigits);
- for (i=0; i<(int)numDigits; i++)
+ for (i=0; i<numDigits; i++)
d->points.setBit(i, tmpPoints.testBit(i+dif));
}
d->ndigits = numDigits;
@@ -713,27 +677,27 @@ void QLCDNumber::paintEvent(QPaintEvent *)
void QLCDNumberPrivate::internalSetString(const QString& s)
{
Q_Q(QLCDNumber);
- QString buffer;
+ QString buffer(ndigits, QChar());
int i;
- int len = s.length();
+ int len = s.size();
QBitArray newPoints(ndigits);
if (!smallPoint) {
if (len == ndigits)
buffer = s;
else
- buffer = s.right(ndigits).rightJustified(ndigits, QLatin1Char(' '));
+ buffer = s.right(ndigits).rightJustified(ndigits, u' ');
} else {
int index = -1;
bool lastWasPoint = true;
newPoints.clearBit(0);
for (i=0; i<len; i++) {
- if (s[i] == QLatin1Char('.')) {
+ if (s[i] == u'.') {
if (lastWasPoint) { // point already set for digit?
if (index == ndigits - 1) // no more digits
break;
index++;
- buffer[index] = QLatin1Char(' '); // 2 points in a row, add space
+ buffer[index] = u' '; // 2 points in a row, add space
}
newPoints.setBit(index); // set decimal point
lastWasPoint = true;
@@ -753,7 +717,7 @@ void QLCDNumberPrivate::internalSetString(const QString& s)
newPoints.testBit(i));
}
for(i=0; i<ndigits-index-1; i++) {
- buffer[i] = QLatin1Char(' ');
+ buffer[i] = u' ';
newPoints.clearBit(i);
}
}
@@ -1159,7 +1123,7 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter
/*!
\property QLCDNumber::segmentStyle
- \brief the style of the LCDNumber
+ \brief the style of the LCDNumber.
\table
\header \li Style \li Result
diff --git a/src/widgets/widgets/qlcdnumber.h b/src/widgets/widgets/qlcdnumber.h
index 644c39eaf3..bcd0623d02 100644
--- a/src/widgets/widgets/qlcdnumber.h
+++ b/src/widgets/widgets/qlcdnumber.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLCDNUMBER_H
#define QLCDNUMBER_H
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index bd5e0b047e..8909ac80d9 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlineedit.h"
#include "qlineedit_p.h"
@@ -64,7 +28,6 @@
#include "qtimer.h"
#include "qvalidator.h"
#include "qvariant.h"
-#include "qvector.h"
#include "qdebug.h"
#if QT_CONFIG(textedit)
#include "qtextedit.h"
@@ -72,7 +35,7 @@
#endif
#include <private/qwidgettextcontrol_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#if QT_CONFIG(itemviews)
@@ -84,10 +47,9 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include "qkeysequence.h"
-#define ACCEL_KEY(k) ((!QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus) \
- && QGuiApplication::styleHints()->showShortcutsInContextMenus()) \
+#define ACCEL_KEY(k) (!QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) \
&& !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(k) ? \
- QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
+ u'\t' + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
#else
#define ACCEL_KEY(k) QString()
#endif
@@ -99,6 +61,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
Initialize \a option with the values from this QLineEdit. This method
is useful for subclasses when they need a QStyleOptionFrame, but don't want
@@ -136,54 +100,66 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
\image windows-lineedit.png
- A line edit allows the user to enter and edit a single line of
- plain text with a useful collection of editing functions,
- including undo and redo, cut and paste, and drag and drop (see
- \l setDragEnabled()).
+ A line edit allows users to enter and edit a single line of
+ plain text with useful editing functions, including undo and redo, cut and
+ paste, and drag and drop.
By changing the echoMode() of a line edit, it can also be used as
- a "write-only" field, for inputs such as passwords.
-
- The length of the text can be constrained to maxLength(). The text
- can be arbitrarily constrained using a validator() or an
- inputMask(), or both. When switching between a validator and an input mask
- on the same line edit, it is best to clear the validator or input mask to
- prevent undefined behavior.
+ a write-only field for inputs such as passwords.
- A related class is QTextEdit which allows multi-line, rich text
+ QTextEdit is a related class that allows multi-line, rich text
editing.
- You can change the text with setText() or insert(). The text is
- retrieved with text(); the displayed text (which may be different,
- see \l{EchoMode}) is retrieved with displayText(). Text can be
- selected with setSelection() or selectAll(), and the selection can
- be cut(), copy()ied and paste()d. The text can be aligned with
- setAlignment().
-
- When the text changes the textChanged() signal is emitted; when
- the text changes other than by calling setText() the textEdited()
- signal is emitted; when the cursor is moved the
- cursorPositionChanged() signal is emitted; and when the Return or
- Enter key is pressed the returnPressed() signal is emitted.
-
- When editing is finished, either because the line edit lost focus
- or Return/Enter is pressed the editingFinished() signal is
- emitted.
-
- Note that if there is a validator set on the line edit, the
- returnPressed()/editingFinished() signals will only be emitted if
- the validator returns QValidator::Acceptable.
-
- By default, QLineEdits have a frame as specified by platform
- style guides; you can turn it off by calling
- setFrame(false).
-
- The default key bindings are described below. The line edit also
- provides a context menu (usually invoked by a right mouse click)
- that presents some of these editing options.
+ \section1 Constraining Text
+
+ Use \l maxLength to define the maximum permitted length of a text. You can
+ use a \l inputMask and \l setValidator() to further constrain the text
+ content.
+
+ \section1 Editing Text
+
+ You can change the text with setText() or insert(). Use text() to retrieve
+ the text and displayText() to retrieve the displayed text (which may be
+ different, see \l{EchoMode}). You can select the text with setSelection() or
+ selectAll(), and you can cut(), copy(), and paste() the selection. To align
+ the text, use setAlignment().
+
+ When the text changes, the textChanged() signal is emitted. When the text
+ changes in some other way than by calling setText(), the textEdited() signal
+ is emitted. When the cursor is moved, the cursorPositionChanged() signal is
+ emitted. And when the Return or Enter key is selected, the returnPressed()
+ signal is emitted.
+
+ When text editing is finished, either because the line edit lost focus
+ or Return/Enter was selected, the editingFinished() signal is emitted.
+
+ If the line edit focus is lost without any text changes, the
+ editingFinished() signal won't be emitted.
+
+ If there is a validator set on the line edit, the
+ returnPressed()/editingFinished() signals will only be emitted if the
+ validator returns QValidator::Acceptable.
+
+ For more information on the many ways that QLineEdit can be used, see
+ \l {Line Edits Example}, which also provides a selection of line edit
+ examples that show the effects of various properties and validators on the
+ input and output supplied by the user.
+
+ \section1 Setting a Frame
+
+ By default, QLineEdits have a frame as specified in the platform
+ style guides. You can turn the frame off by calling setFrame(false).
+
+ \section1 Default Key Bindings
+
+ The table below describes the default key bindings.
+
+ \note The line edit also provides a context menu (usually invoked by a
+ right-click) that presents some of the editing options listed below.
+
\target desc
\table
- \header \li Keypress \li Action
+ \header \li Keystroke \li Action
\row \li Left Arrow \li Moves the cursor one character to the left.
\row \li Shift+Left Arrow \li Moves and selects text one character to the left.
\row \li Right Arrow \li Moves the cursor one character to the right.
@@ -194,7 +170,7 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
\row \li Ctrl+Backspace \li Deletes the word to the left of the cursor.
\row \li Delete \li Deletes the character to the right of the cursor.
\row \li Ctrl+Delete \li Deletes the word to the right of the cursor.
- \row \li Ctrl+A \li Select all.
+ \row \li Ctrl+A \li Selects all.
\row \li Ctrl+C \li Copies the selected text to the clipboard.
\row \li Ctrl+Insert \li Copies the selected text to the clipboard.
\row \li Ctrl+K \li Deletes to the end of the line.
@@ -206,10 +182,10 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const
\row \li Ctrl+Y \li Redoes the last undone operation.
\endtable
- Any other key sequence that represents a valid character, will
- cause the character to be inserted into the line edit.
+ Any other keystroke that represents a valid character, will cause the
+ character to be inserted into the line edit.
- \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}, {Line Edits Example}
+ \sa QTextEdit, QLabel, QComboBox, {Line Edits Example}
*/
@@ -265,13 +241,11 @@ QLineEdit::QLineEdit(QWidget* parent)
}
/*!
- Constructs a line edit containing the text \a contents.
-
- The cursor position is set to the end of the line and the maximum
- text length to 32767 characters.
+ Constructs a line edit containing the text \a contents as a child of
+ \a parent.
- The \a parent and argument is sent to the QWidget
- constructor.
+ The cursor position is set to the end of the line and the maximum text
+ length to 32767 characters.
\sa text(), setMaxLength()
*/
@@ -295,10 +269,10 @@ QLineEdit::~QLineEdit()
/*!
\property QLineEdit::text
- \brief the line edit's text.
+ \brief The line edit's text.
Setting this property clears the selection, clears the undo/redo
- history, moves the cursor to the end of the line and resets the
+ history, moves the cursor to the end of the line, and resets the
\l modified property to false. The text is not validated when
inserted with setText().
@@ -324,7 +298,7 @@ void QLineEdit::setText(const QString& text)
\since 4.7
\property QLineEdit::placeholderText
- \brief the line edit's placeholder text.
+ \brief The line edit's placeholder text.
Setting this property makes the line edit display a grayed-out
placeholder text as long as the line edit is empty.
@@ -356,12 +330,12 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText)
/*!
\property QLineEdit::displayText
- \brief the displayed text.
+ \brief The displayed text.
- If \l echoMode is \l Normal this returns the same as text(); if
- \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of
- platform-dependent password mask characters text().length() in size,
- e.g. "******"; if \l EchoMode is \l NoEcho returns an empty string, "".
+ If \l echoMode is \l Normal, this returns the same as text(). If
+ \l EchoMode is \l Password or \l PasswordEchoOnEdit, it returns a string of
+ platform-dependent password mask characters (e.g. "******"). If \l EchoMode
+ is \l NoEcho, it returns an empty string.
By default, this property contains an empty string.
@@ -377,12 +351,12 @@ QString QLineEdit::displayText() const
/*!
\property QLineEdit::maxLength
- \brief the maximum permitted length of the text.
+ \brief The maximum permitted length of the text.
If the text is too long, it is truncated at the limit.
- If truncation occurs any selected text will be unselected, the
- cursor position is set to 0 and the first part of the string is
+ If truncation occurs, any selected text will be unselected, the
+ cursor position is set to 0, and the first part of the string is
shown.
If the line edit has an input mask, the mask defines the maximum
@@ -407,10 +381,10 @@ void QLineEdit::setMaxLength(int maxLength)
/*!
\property QLineEdit::frame
- \brief whether the line edit draws itself with a frame.
+ \brief Whether the line edit draws itself with a frame.
- If enabled (the default) the line edit draws itself inside a
- frame, otherwise the line edit draws itself without any frame.
+ If enabled (the default), the line edit draws itself inside a
+ frame. Otherwise, the line edit draws itself without any frame.
*/
bool QLineEdit::hasFrame() const
{
@@ -470,9 +444,9 @@ QAction *QLineEdit::addAction(const QIcon &icon, ActionPosition position)
\property QLineEdit::clearButtonEnabled
\brief Whether the line edit displays a clear button when it is not empty.
- If enabled, the line edit displays a trailing \e clear button when it contains
- some text, otherwise the line edit does not show a clear button (the
- default).
+ If enabled, the line edit displays a trailing \uicontrol clear button when
+ it contains some text. Otherwise, the line edit does not show a
+ \uicontrol clear button (the default).
\sa addAction(), removeAction()
\since 5.2
@@ -489,13 +463,13 @@ void QLineEdit::setClearButtonEnabled(bool enable)
if (enable) {
QAction *clearAction = new QAction(d->clearButtonIcon(), QString(), this);
clearAction->setEnabled(!isReadOnly());
- clearAction->setObjectName(QLatin1String(clearButtonActionNameC));
+ clearAction->setObjectName(QLatin1StringView(clearButtonActionNameC));
int flags = QLineEditPrivate::SideWidgetClearButton | QLineEditPrivate::SideWidgetFadeInWithText;
auto widgetAction = d->addAction(clearAction, nullptr, QLineEdit::TrailingPosition, flags);
widgetAction->setVisible(!text().isEmpty());
} else {
- QAction *clearAction = findChild<QAction *>(QLatin1String(clearButtonActionNameC));
+ QAction *clearAction = findChild<QAction *>(QLatin1StringView(clearButtonActionNameC));
Q_ASSERT(clearAction);
d->removeAction(clearAction);
delete clearAction;
@@ -508,7 +482,7 @@ void QLineEdit::setClearButtonEnabled(bool enable)
bool QLineEdit::isClearButtonEnabled() const
{
#if QT_CONFIG(action)
- return findChild<QAction *>(QLatin1String(clearButtonActionNameC));
+ return findChild<QAction *>(QLatin1StringView(clearButtonActionNameC));
#else
return false;
#endif
@@ -536,9 +510,8 @@ void QLineEdit::setFrame(bool enable)
password should be kept secret.
\value Password Display platform-dependent password mask characters instead
of the characters actually entered.
- \value PasswordEchoOnEdit Display characters as they are entered
- while editing otherwise display characters as with
- \c Password.
+ \value PasswordEchoOnEdit Display characters only while they are entered.
+ Otherwise, display characters as with \c Password.
\sa setEchoMode(), echoMode()
*/
@@ -546,13 +519,13 @@ void QLineEdit::setFrame(bool enable)
/*!
\property QLineEdit::echoMode
- \brief the line edit's echo mode.
+ \brief The line edit's echo mode.
The echo mode determines how the text entered in the line edit is
displayed (or echoed) to the user.
The most common setting is \l Normal, in which the text entered by the
- user is displayed verbatim, but QLineEdit also supports modes that allow
+ user is displayed verbatim. QLineEdit also supports modes that allow
the entered text to be suppressed or obscured: these include \l NoEcho,
\l Password and \l PasswordEchoOnEdit.
@@ -601,15 +574,23 @@ const QValidator * QLineEdit::validator() const
}
/*!
- Sets this line edit to only accept input that the validator, \a v,
- will accept. This allows you to place any arbitrary constraints on
- the text which may be entered.
+ Sets the validator for values of line edit to \a v.
+
+ The line edit's returnPressed() and editingFinished() signals will only
+ be emitted if \a v validates the line edit's content as \l{QValidator::}{Acceptable}.
+ The user may change the content to any \l{QValidator::}{Intermediate}
+ value during editing, but will be prevented from editing the text to a
+ value that \a v validates as \l{QValidator::}{Invalid}.
- If \a v == 0, setValidator() removes the current input validator.
- The initial setting is to have no input validator (i.e. any input
- is accepted up to maxLength()).
+ This allows you to constrain the text that will be stored when editing is
+ done while leaving users with enough freedom to edit the text from one valid
+ state to another.
- \sa validator(), hasAcceptableInput(), QIntValidator, QDoubleValidator, QRegExpValidator
+ To remove the current input validator, pass \c nullptr. The initial setting
+ is to have no input validator (any input is accepted up to maxLength()).
+
+ \sa validator(), hasAcceptableInput(), QIntValidator, QDoubleValidator,
+ QRegularExpressionValidator
*/
void QLineEdit::setValidator(const QValidator *v)
@@ -631,8 +612,7 @@ void QLineEdit::setValidator(const QValidator *v)
use the QSortFilterProxyModel to ensure that the QCompleter's model contains
only valid entries.
- If \a c == 0, setCompleter() removes the current completer, effectively
- disabling auto completion.
+ To remove the completer and disable auto-completion, pass a \c nullptr.
\sa QCompleter
*/
@@ -642,7 +622,7 @@ void QLineEdit::setCompleter(QCompleter *c)
if (c == d->control->completer())
return;
if (d->control->completer()) {
- disconnect(d->control->completer(), nullptr, this, nullptr);
+ d->disconnectCompleter();
d->control->completer()->setWidget(nullptr);
if (d->control->completer()->parent() == this)
delete d->control->completer();
@@ -652,12 +632,8 @@ void QLineEdit::setCompleter(QCompleter *c)
return;
if (c->widget() == nullptr)
c->setWidget(this);
- if (hasFocus()) {
- QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
- this, SLOT(setText(QString)));
- QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
- this, SLOT(_q_completionHighlighted(QString)));
- }
+ if (hasFocus())
+ d->connectCompleter();
}
/*!
@@ -690,20 +666,19 @@ QSize QLineEdit::sizeHint() const
int h = qMax(fm.height(), qMax(14, iconSize - 2)) + 2 * QLineEditPrivate::verticalMargin
+ tm.top() + tm.bottom()
+ d->topmargin + d->bottommargin;
- int w = fm.horizontalAdvance(QLatin1Char('x')) * 17 + 2 * QLineEditPrivate::horizontalMargin
+ int w = fm.horizontalAdvance(u'x') * 17 + 2 * QLineEditPrivate::horizontalMargin
+ tm.left() + tm.right()
+ d->leftmargin + d->rightmargin; // "some"
QStyleOptionFrame opt;
initStyleOption(&opt);
- return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
- expandedTo(QApplication::globalStrut()), this));
+ return style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h), this);
}
/*!
Returns a minimum size for the line edit.
- The width returned is enough for at least one character.
+ The width returned is usually enough for at least one character.
*/
QSize QLineEdit::minimumSizeHint() const
@@ -715,19 +690,18 @@ QSize QLineEdit::minimumSizeHint() const
int h = fm.height() + qMax(2 * QLineEditPrivate::verticalMargin, fm.leading())
+ tm.top() + tm.bottom()
+ d->topmargin + d->bottommargin;
- int w = fm.maxWidth()
+ int w = fm.maxWidth() + 2 * QLineEditPrivate::horizontalMargin
+ tm.left() + tm.right()
+ d->leftmargin + d->rightmargin;
QStyleOptionFrame opt;
initStyleOption(&opt);
- return (style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h).
- expandedTo(QApplication::globalStrut()), this));
+ return style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h), this);
}
/*!
\property QLineEdit::cursorPosition
- \brief the current cursor position for this line edit.
+ \brief The current cursor position for this line edit.
Setting the cursor position causes a repaint when appropriate.
@@ -760,7 +734,7 @@ int QLineEdit::cursorPositionAt(const QPoint &pos)
/*!
\property QLineEdit::alignment
- \brief the alignment of the line edit.
+ \brief The alignment of the line edit.
Both horizontal and vertical alignment is allowed here, Qt::AlignJustify
will map to Qt::AlignLeft.
@@ -785,9 +759,9 @@ void QLineEdit::setAlignment(Qt::Alignment alignment)
/*!
- Moves the cursor forward \a steps characters. If \a mark is true
- each character moved over is added to the selection; if \a mark is
- false the selection is cleared.
+ Moves the cursor forward \a steps characters. If \a mark is true,
+ each character moved over is added to the selection. If \a mark is
+ false, the selection is cleared.
\sa cursorBackward()
*/
@@ -800,9 +774,9 @@ void QLineEdit::cursorForward(bool mark, int steps)
/*!
- Moves the cursor back \a steps characters. If \a mark is true each
- character moved over is added to the selection; if \a mark is
- false the selection is cleared.
+ Moves the cursor back \a steps characters. If \a mark is true, each
+ character moved over is added to the selection. If \a mark is
+ false, the selection is cleared.
\sa cursorForward()
*/
@@ -839,9 +813,9 @@ void QLineEdit::cursorWordBackward(bool mark)
/*!
If no text is selected, deletes the character to the left of the
- text cursor and moves the cursor one position to the left. If any
+ text cursor, and moves the cursor one position to the left. If any
text is selected, the cursor is moved to the beginning of the
- selected text and the selected text is deleted.
+ selected text, and the selected text is deleted.
\sa del()
*/
@@ -854,7 +828,7 @@ void QLineEdit::backspace()
/*!
If no text is selected, deletes the character to the right of the
text cursor. If any text is selected, the cursor is moved to the
- beginning of the selected text and the selected text is deleted.
+ beginning of the selected text, and the selected text is deleted.
\sa backspace()
*/
@@ -868,7 +842,7 @@ void QLineEdit::del()
/*!
Moves the text cursor to the beginning of the line unless it is
already there. If \a mark is true, text is selected towards the
- first position; otherwise, any selected text is unselected if the
+ first position. Otherwise, any selected text is unselected if the
cursor is moved.
\sa end()
@@ -883,7 +857,7 @@ void QLineEdit::home(bool mark)
/*!
Moves the text cursor to the end of the line unless it is already
there. If \a mark is true, text is selected towards the last
- position; otherwise, any selected text is unselected if the cursor
+ position. Otherwise, any selected text is unselected if the cursor
is moved.
\sa home()
@@ -898,14 +872,14 @@ void QLineEdit::end(bool mark)
/*!
\property QLineEdit::modified
- \brief whether the line edit's contents has been modified by the user.
+ \brief Whether the line edit's contents has been modified by the user.
The modified flag is never read by QLineEdit; it has a default value
of false and is changed to true whenever the user changes the line
edit's contents.
This is useful for things that need to provide a default value but
- do not start out knowing what the default should be (perhaps it
+ do not start out knowing what the default should be (for example, it
depends on other fields on the form). Start the line edit without
the best default, and when the default is known, if modified()
returns \c false (the user hasn't entered any text), insert the
@@ -928,10 +902,10 @@ void QLineEdit::setModified(bool modified)
/*!
\property QLineEdit::hasSelectedText
- \brief whether there is any text selected.
+ \brief Whether there is any text selected.
hasSelectedText() returns \c true if some or all of the text has been
- selected by the user; otherwise returns \c false.
+ selected by the user. Otherwise, it returns \c false.
By default, this property is \c false.
@@ -947,9 +921,9 @@ bool QLineEdit::hasSelectedText() const
/*!
\property QLineEdit::selectedText
- \brief the selected text.
+ \brief The selected text.
- If there is no selected text this property's value is
+ If there is no selected text, this property's value is
an empty string.
By default, this property contains an empty string.
@@ -965,7 +939,7 @@ QString QLineEdit::selectedText() const
/*!
Returns the index of the first selected character in the
- line edit or -1 if no text is selected.
+ line edit (or -1 if no text is selected).
\sa selectedText()
\sa selectionEnd()
@@ -980,7 +954,7 @@ int QLineEdit::selectionStart() const
/*!
Returns the index of the character directly after the selection
- in the line edit or -1 if no text is selected.
+ in the line edit (or -1 if no text is selected).
\since 5.10
\sa selectedText()
@@ -1034,7 +1008,7 @@ void QLineEdit::setSelection(int start, int length)
/*!
\property QLineEdit::undoAvailable
- \brief whether undo is available.
+ \brief Whether undo is available.
Undo becomes available once the user has modified the text in the line edit.
@@ -1049,10 +1023,10 @@ bool QLineEdit::isUndoAvailable() const
/*!
\property QLineEdit::redoAvailable
- \brief whether redo is available.
+ \brief Whether redo is available.
Redo becomes available once the user has performed one or more undo operations
- on text in the line edit.
+ on the text in the line edit.
By default, this property is \c false.
*/
@@ -1065,7 +1039,7 @@ bool QLineEdit::isRedoAvailable() const
/*!
\property QLineEdit::dragEnabled
- \brief whether the lineedit starts a drag if the user presses and
+ \brief Whether the line edit starts a drag if the user presses and
moves the mouse on some selected text.
Dragging is disabled by default.
@@ -1085,17 +1059,18 @@ void QLineEdit::setDragEnabled(bool b)
/*!
\property QLineEdit::cursorMoveStyle
- \brief the movement style of cursor in this line edit.
+ \brief The movement style of the cursor in this line edit.
\since 4.8
- When this property is set to Qt::VisualMoveStyle, the line edit will use visual
- movement style. Pressing the left arrow key will always cause the cursor to move
- left, regardless of the text's writing direction. The same behavior applies to
- right arrow key.
+ When this property is set to Qt::VisualMoveStyle, the line edit will use a
+ visual movement style. Using the left arrow key will always cause the
+ cursor to move left, regardless of the text's writing direction. The same
+ behavior applies to the right arrow key.
- When the property is Qt::LogicalMoveStyle (the default), within a LTR text block,
- increase cursor position when pressing left arrow key, decrease cursor position
- when pressing the right arrow key. If the text block is right to left, the opposite
+ When the property is set to Qt::LogicalMoveStyle (the default), within a
+ left-to-right (LTR) text block, using the left arrow key will increase
+ the cursor position, whereas using the right arrow key will decrease the
+ cursor position. If the text block is right-to-left (RTL), the opposite
behavior applies.
*/
@@ -1113,7 +1088,7 @@ void QLineEdit::setCursorMoveStyle(Qt::CursorMoveStyle style)
/*!
\property QLineEdit::acceptableInput
- \brief whether the input satisfies the inputMask and the
+ \brief Whether the input satisfies the inputMask and the
validator.
By default, this property is \c true.
@@ -1127,11 +1102,11 @@ bool QLineEdit::hasAcceptableInput() const
}
/*!
+ \since 4.5
Sets the margins around the text inside the frame to have the
sizes \a left, \a top, \a right, and \a bottom.
- \since 4.5
- See also textMargins().
+ \sa textMargins()
*/
void QLineEdit::setTextMargins(int left, int top, int right, int bottom)
{
@@ -1142,7 +1117,7 @@ void QLineEdit::setTextMargins(int left, int top, int right, int bottom)
\since 4.6
Sets the \a margins around the text inside the frame.
- See also textMargins().
+ \sa textMargins()
*/
void QLineEdit::setTextMargins(const QMargins &margins)
{
@@ -1152,30 +1127,6 @@ void QLineEdit::setTextMargins(const QMargins &margins)
update();
}
-#if QT_DEPRECATED_SINCE(5, 14)
-/*!
- \obsolete
- Use textMargins()
-
- Returns the widget's text margins for \a left, \a top, \a right, and \a bottom.
- \since 4.5
-
- \sa setTextMargins()
-*/
-void QLineEdit::getTextMargins(int *left, int *top, int *right, int *bottom) const
-{
- QMargins m = textMargins();
- if (left)
- *left = m.left();
- if (top)
- *top = m.top();
- if (right)
- *right = m.right();
- if (bottom)
- *bottom = m.bottom();
-}
-#endif
-
/*!
\since 4.6
Returns the widget's text margins.
@@ -1192,37 +1143,47 @@ QMargins QLineEdit::textMargins() const
\property QLineEdit::inputMask
\brief The validation input mask.
- If no mask is set, inputMask() returns an empty string.
-
Sets the QLineEdit's validation mask. Validators can be used
- instead of, or in conjunction with masks; see setValidator().
+ instead of, or in conjunction with masks; see setValidator(). The default is
+ an empty string, which means that no input mask is used.
- Unset the mask and return to normal QLineEdit operation by passing
- an empty string ("").
+ To unset the mask and return to normal QLineEdit operation, pass an empty
+ string.
- The input mask is an input template string. It can contain the following elements:
+ The input mask is an input template string. It can contain the following
+ elements:
\table
- \row \li Mask Characters \li Defines the class of input characters that are
- considered valid in this position
- \row \li Meta Characters \li Various special meanings
- \row \li Separators \li All other characters are regarded as immutable separators
+ \row \li Mask Characters \li Defines the \l {QChar::} {Category} of input
+ characters that are considered valid in this position.
+ \row \li Meta Characters \li Various special meanings (see details below).
+ \row \li Separators \li All other characters are regarded as immutable
+ separators.
\endtable
- The following table shows the mask and meta characters that can be used in an input mask.
+ The following table shows the mask and meta characters that can be used in
+ an input mask.
\table
\header \li Mask Character \li Meaning
- \row \li \c A \li ASCII alphabetic character required. A-Z, a-z.
- \row \li \c a \li ASCII alphabetic character permitted but not required.
- \row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9.
- \row \li \c n \li ASCII alphanumeric character permitted but not required.
+ \row \li \c A \li Character of the Letter category required, such as A-Z,
+ a-z.
+ \row \li \c a \li Character of the Letter category permitted but not
+ required.
+ \row \li \c N \li Character of the Letter or Number category required, such
+ as A-Z, a-z, 0-9.
+ \row \li \c n \li Character of the Letter or Number category permitted but
+ not required.
\row \li \c X \li Any non-blank character required.
\row \li \c x \li Any non-blank character permitted but not required.
- \row \li \c 9 \li ASCII digit required. 0-9.
- \row \li \c 0 \li ASCII digit permitted but not required.
- \row \li \c D \li ASCII digit required. 1-9.
- \row \li \c d \li ASCII digit permitted but not required (1-9).
- \row \li \c # \li ASCII digit or plus/minus sign permitted but not required.
+ \row \li \c 9 \li Character of the Number category required, such as 0-9.
+ \row \li \c 0 \li Character of the Number category permitted but not
+ required.
+ \row \li \c D \li Character of the Number category and larger than zero
+ required, such as 1-9.
+ \row \li \c d \li Character of the Number category and larger than zero
+ permitted but not required, such as 1-9.
+ \row \li \c # \li Character of the Number category, or plus/minus sign
+ permitted but not required.
\row \li \c H \li Hexadecimal character required. A-F, a-f, 0-9.
\row \li \c h \li Hexadecimal character permitted but not required.
\row \li \c B \li Binary character required. 0-1.
@@ -1231,11 +1192,11 @@ QMargins QLineEdit::textMargins() const
\row \li \c > \li All following alphabetic characters are uppercased.
\row \li \c < \li All following alphabetic characters are lowercased.
\row \li \c ! \li Switch off case conversion.
- \row \li \c {;c} \li Terminates the input mask and sets the \e{blank} character to \e{c}.
+ \row \li \c {;c} \li Terminates the input mask and sets the \e{blank}
+ character to \e{c}.
\row \li \c {[ ] { }} \li Reserved.
- \row \li \tt{\\} \li Use \tt{\\} to escape the special
- characters listed above to use them as
- separators.
+ \row \li \tt{\\} \li Use \tt{\\} to escape the special characters listed
+ above to use them as separators.
\endtable
When created or cleared, the line edit will be filled with a copy of the
@@ -1248,7 +1209,7 @@ QMargins QLineEdit::textMargins() const
unmodified content can be read using displayText().
The hasAcceptableInput() method returns false if the current content of the
- line edit does not fulfil the requirements of the input mask.
+ line edit does not fulfill the requirements of the input mask.
Examples:
\table
@@ -1264,7 +1225,7 @@ QMargins QLineEdit::textMargins() const
To get range control (e.g., for an IP address) use masks together
with \l{setValidator()}{validators}.
- \sa maxLength
+ \sa maxLength, QChar::isLetter(), QChar::isNumber(), QChar::digitValue()
*/
QString QLineEdit::inputMask() const
{
@@ -1279,8 +1240,10 @@ void QLineEdit::setInputMask(const QString &inputMask)
}
/*!
- Selects all the text (i.e. highlights it) and moves the cursor to
- the end. This is useful when a default value has been inserted
+ Selects all the text (highlights it) and moves the cursor to
+ the end.
+
+ \note This is useful when a default value has been inserted
because if the user types before clicking on the widget, the
selected text will be deleted.
@@ -1308,7 +1271,7 @@ void QLineEdit::deselect()
/*!
Deletes any selected text, inserts \a newText, and validates the
- result. If it is valid, it sets it as the new contents of the line
+ result. If it is valid, it sets the new text as the new contents of the line
edit.
\sa setText(), clear()
@@ -1357,7 +1320,7 @@ void QLineEdit::redo()
/*!
\property QLineEdit::readOnly
- \brief whether the line edit is read only.
+ \brief Whether the line edit is read-only.
In read-only mode, the user can still copy the text to the
clipboard, or drag and drop the text (if echoMode() is \l Normal),
@@ -1390,7 +1353,7 @@ void QLineEdit::setReadOnly(bool enable)
QEvent event(QEvent::ReadOnlyChange);
QCoreApplication::sendEvent(this, &event);
update();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State changedState;
changedState.readOnly = true;
QAccessibleStateChangeEvent ev(this, changedState);
@@ -1437,7 +1400,7 @@ void QLineEdit::copy() const
Inserts the clipboard's text at the cursor position, deleting any
selected text, providing the line edit is not \l{QLineEdit::readOnly}{read-only}.
- If the end result would not be acceptable to the current
+ If the end result would be invalid to the current
\l{setValidator()}{validator}, nothing happens.
\sa copy(), cut()
@@ -1451,37 +1414,44 @@ void QLineEdit::paste()
#endif // !QT_NO_CLIPBOARD
-/*! \reimp
+/*!
+ \reimp
*/
-bool QLineEdit::event(QEvent * e)
+void QLineEdit::timerEvent(QTimerEvent *e)
{
Q_D(QLineEdit);
- if (e->type() == QEvent::Timer) {
- // ### Qt6: move to timerEvent, is here for binary compatibility
- int timerId = ((QTimerEvent*)e)->timerId();
- if (false) {
+ int timerId = ((QTimerEvent*)e)->timerId();
+ if (false) {
#if QT_CONFIG(draganddrop)
- } else if (timerId == d->dndTimer.timerId()) {
- d->drag();
+ } else if (timerId == d->dndTimer.timerId()) {
+ d->drag();
#endif
- }
- else if (timerId == d->tripleClickTimer.timerId())
- d->tripleClickTimer.stop();
- } else if (e->type() == QEvent::ContextMenu) {
+ }
+ else if (timerId == d->tripleClickTimer.timerId())
+ d->tripleClickTimer.stop();
+}
+
+/*! \reimp
+*/
+bool QLineEdit::event(QEvent * e)
+{
+ Q_D(QLineEdit);
+ if (e->type() == QEvent::ContextMenu) {
#ifndef QT_NO_IM
if (d->control->composeMode())
return true;
#endif
//d->separate();
} else if (e->type() == QEvent::WindowActivate) {
- QTimer::singleShot(0, this, SLOT(_q_handleWindowActivate()));
+ QTimer::singleShot(0, this, [this]() {
+ Q_D(QLineEdit);
+ d->handleWindowActivate();
+ });
#ifndef QT_NO_SHORTCUT
} else if (e->type() == QEvent::ShortcutOverride) {
QKeyEvent *ke = static_cast<QKeyEvent*>(e);
d->control->processShortcutOverrideEvent(ke);
#endif
- } else if (e->type() == QEvent::KeyRelease) {
- 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()) {
@@ -1492,6 +1462,8 @@ bool QLineEdit::event(QEvent * e)
|| style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(true);
}
+ } else if (e->type() == QEvent::Hide) {
+ d->control->setBlinkingCursorEnabled(false);
#if QT_CONFIG(action)
} else if (e->type() == QEvent::ActionRemoved) {
d->removeAction(static_cast<QActionEvent *>(e)->action());
@@ -1527,7 +1499,7 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
{
Q_D(QLineEdit);
- d->mousePressPos = e->pos();
+ d->mousePressPos = e->position().toPoint();
if (d->sendMouseEventToInputContext(e))
return;
@@ -1541,7 +1513,7 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
d->control->completer()->complete();
}
#endif
- if (d->tripleClickTimer.isActive() && (e->pos() - d->tripleClick).manhattanLength() <
+ if (d->tripleClickTimer.isActive() && (e->position().toPoint() - d->tripleClick).manhattanLength() <
QApplication::startDragDistance()) {
selectAll();
return;
@@ -1550,10 +1522,10 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
#ifdef Q_OS_ANDROID
mark = mark && (d->imHints & Qt::ImhNoPredictiveText);
#endif // Q_OS_ANDROID
- int cursor = d->xToPos(e->pos().x());
+ int cursor = d->xToPos(e->position().toPoint().x());
#if QT_CONFIG(draganddrop)
if (!mark && d->dragEnabled && d->control->echoMode() == Normal &&
- e->button() == Qt::LeftButton && d->inSelection(e->pos().x())) {
+ e->button() == Qt::LeftButton && d->inSelection(e->position().toPoint().x())) {
if (!d->dndTimer.isActive())
d->dndTimer.start(QApplication::startDragTime(), this);
} else
@@ -1572,7 +1544,7 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
if (e->buttons() & Qt::LeftButton) {
#if QT_CONFIG(draganddrop)
if (d->dndTimer.isActive()) {
- if ((d->mousePressPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
+ if ((d->mousePressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance())
d->drag();
} else
#endif
@@ -1583,26 +1555,26 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
const bool select = (d->imHints & Qt::ImhNoPredictiveText);
#endif
#ifndef QT_NO_IM
- if (d->mouseYThreshold > 0 && e->pos().y() > d->mousePressPos.y() + d->mouseYThreshold) {
+ if (d->mouseYThreshold > 0 && e->position().toPoint().y() > d->mousePressPos.y() + d->mouseYThreshold) {
if (layoutDirection() == Qt::RightToLeft)
d->control->home(select);
else
d->control->end(select);
- } else if (d->mouseYThreshold > 0 && e->pos().y() + d->mouseYThreshold < d->mousePressPos.y()) {
+ } else if (d->mouseYThreshold > 0 && e->position().toPoint().y() + d->mouseYThreshold < d->mousePressPos.y()) {
if (layoutDirection() == Qt::RightToLeft)
d->control->end(select);
else
d->control->home(select);
} else if (d->control->composeMode() && select) {
int startPos = d->xToPos(d->mousePressPos.x());
- int currentPos = d->xToPos(e->pos().x());
+ int currentPos = d->xToPos(e->position().toPoint().x());
if (startPos != currentPos)
d->control->setSelection(startPos, currentPos - startPos);
} else
#endif
{
- d->control->moveCursor(d->xToPos(e->pos().x()), select);
+ d->control->moveCursor(d->xToPos(e->position().toPoint().x()), select);
}
}
}
@@ -1630,14 +1602,14 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
if (QGuiApplication::clipboard()->supportsSelection()) {
if (e->button() == Qt::LeftButton) {
d->control->copy(QClipboard::Selection);
- } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) {
+ } else if (!d->control->isReadOnly() && e->button() == Qt::MiddleButton) {
deselect();
d->control->paste(QClipboard::Selection);
}
}
#endif
- if (!isReadOnly() && rect().contains(e->pos()))
+ if (!isReadOnly() && rect().contains(e->position().toPoint()))
d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
d->clickCausedFocus = 0;
}
@@ -1649,14 +1621,14 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
Q_D(QLineEdit);
if (e->button() == Qt::LeftButton) {
- int position = d->xToPos(e->pos().x());
+ int position = d->xToPos(e->position().toPoint().x());
// exit composition mode
#ifndef QT_NO_IM
if (d->control->composeMode()) {
int preeditPos = d->control->cursor();
int posInPreedit = position - d->control->cursor();
- int preeditLength = d->control->preeditAreaText().length();
+ int preeditLength = d->control->preeditAreaText().size();
bool positionOnPreedit = false;
if (posInPreedit >= 0 && posInPreedit <= preeditLength)
@@ -1683,7 +1655,7 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
d->control->selectWordAtPos(position);
d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
- d->tripleClick = e->pos();
+ d->tripleClick = e->position().toPoint();
} else {
d->sendMouseEventToInputContext(e);
}
@@ -1692,8 +1664,9 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
/*!
\fn void QLineEdit::returnPressed()
- This signal is emitted when the Return or Enter key is pressed.
- Note that if there is a validator() or inputMask() set on the line
+ This signal is emitted when the Return or Enter key is used.
+
+ \note If there is a validator() or inputMask() set on the line
edit, the returnPressed() signal will only be emitted if the input
follows the inputMask() and the validator() returns
QValidator::Acceptable.
@@ -1702,38 +1675,39 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
/*!
\fn void QLineEdit::editingFinished()
- This signal is emitted when the Return or Enter key is pressed or
- the line edit loses focus. Note that if there is a validator() or
- inputMask() set on the line edit and enter/return is pressed, the
- editingFinished() signal will only be emitted if the input follows
- the inputMask() and the validator() returns QValidator::Acceptable.
+ This signal is emitted when the Return or Enter key is used, or if the line
+ edit loses focus and its contents have changed since the last time this
+ signal was emitted.
+
+ \note If there is a validator() or inputMask() set on the line edit and
+ enter/return is used, the editingFinished() signal will only be emitted
+ if the input follows the inputMask() and the validator() returns
+ QValidator::Acceptable.
*/
/*!
\fn void QLineEdit::inputRejected()
\since 5.12
- This signal is emitted when the user presses a key that is not
- considered to be acceptable input. For example, if a key press
- results in a validator's validate() call to return Invalid.
- Another case is when trying to enter in more characters beyond the
- maximum length of the line edit.
+ This signal is emitted when the user uses a key that is not
+ considered to be valid input. For example, if using a key results in a
+ validator's \l {QValidator::validate()}{validate()} call to return
+ \l {QValidator::Invalid}{Invalid}. Another case is when trying
+ to enter more characters beyond the maximum length of the line edit.
- Note: This signal will still be emitted in a case where part of
- the text is accepted but not all of it is. For example, if there
- is a maximum length set and the clipboard text is longer than the
- maximum length when it is pasted.
+ \note This signal will still be emitted when only a part of the text is
+ accepted. For example, if there is a maximum length set and the clipboard
+ text is longer than the maximum length when it is pasted.
*/
/*!
Converts the given key press \a event into a line edit action.
- If Return or Enter is pressed and the current text is valid (or
+ If Return or Enter is used and the current text is valid (or
can be \l{QValidator::fixup()}{made valid} by the
validator), the signal returnPressed() is emitted.
- The default key bindings are listed in the class's detailed
- description.
+ \sa {Default Key Bindings}
*/
void QLineEdit::keyPressEvent(QKeyEvent *event)
@@ -1782,17 +1756,26 @@ void QLineEdit::keyPressEvent(QKeyEvent *event)
}
#endif
d->control->processKeyEvent(event);
- if (event->isAccepted()) {
- if (layoutDirection() != d->control->layoutDirection())
- setLayoutDirection(d->control->layoutDirection());
+ if (event->isAccepted())
d->control->updateCursorBlinking();
- }
+}
+
+/*!
+ \reimp
+*/
+void QLineEdit::keyReleaseEvent(QKeyEvent *e)
+{
+ Q_D(QLineEdit);
+ if (!isReadOnly())
+ d->handleSoftwareInputPanel();
+ d->control->updateCursorBlinking();
+ QWidget::keyReleaseEvent(e);
}
/*!
\since 4.4
- Returns a rectangle that includes the lineedit cursor.
+ Returns a rectangle that includes the line edit cursor.
*/
QRect QLineEdit::cursorRect() const
{
@@ -1805,10 +1788,6 @@ QRect QLineEdit::cursorRect() const
void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
{
Q_D(QLineEdit);
- if (d->control->isReadOnly()) {
- e->ignore();
- return;
- }
if (echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing()) {
// Clear the edit and reset to normal echo mode while entering input
@@ -1840,6 +1819,22 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
*/
QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
{
+#ifdef Q_OS_ANDROID
+ // QTBUG-61652
+ if (property == Qt::ImEnterKeyType) {
+ QWidget *next = nextInFocusChain();
+ while (next && next != this && next->focusPolicy() == Qt::NoFocus)
+ next = next->nextInFocusChain();
+ if (next) {
+ const auto nextYPos = next->mapToGlobal(QPoint(0, 0)).y();
+ const auto currentYPos = mapToGlobal(QPoint(0, 0)).y();
+ if (currentYPos < nextYPos)
+ // Set EnterKey to KeyNext type only if the next widget
+ // in the focus chain is below current QLineEdit
+ return Qt::EnterKeyNext;
+ }
+ }
+#endif
return inputMethodQuery(property, QVariant());
}
@@ -1849,12 +1844,15 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant arg
{
Q_D(const QLineEdit);
switch(property) {
+ case Qt::ImEnabled:
+ return isEnabled() && !isReadOnly();
case Qt::ImCursorRectangle:
return d->cursorRect();
case Qt::ImAnchorRectangle:
return d->adjustedControlRect(d->control->anchorRect());
case Qt::ImFont:
return font();
+ case Qt::ImAbsolutePosition:
case Qt::ImCursorPosition: {
const QPointF pt = argument.toPointF();
if (!pt.isNull())
@@ -1873,6 +1871,20 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant arg
return QVariant(d->control->selectionEnd());
else
return QVariant(d->control->selectionStart());
+ case Qt::ImReadOnly:
+ return isReadOnly();
+ case Qt::ImTextBeforeCursor: {
+ const QPointF pt = argument.toPointF();
+ if (!pt.isNull())
+ return d->textBeforeCursor(d->xToPos(pt.x(), QTextLine::CursorBetweenCharacters));
+ else
+ return d->textBeforeCursor(d->control->cursor()); }
+ case Qt::ImTextAfterCursor: {
+ const QPointF pt = argument.toPointF();
+ if (!pt.isNull())
+ return d->textAfterCursor(d->xToPos(pt.x(), QTextLine::CursorBetweenCharacters));
+ else
+ return d->textAfterCursor(d->control->cursor()); }
default:
return QWidget::inputMethodQuery(property);
}
@@ -1891,8 +1903,11 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
d->control->moveCursor(d->control->nextMaskBlank(0));
else if (!d->control->hasSelectedText())
selectAll();
+ else
+ updateMicroFocus();
} else if (e->reason() == Qt::MouseFocusReason) {
d->clickCausedFocus = 1;
+ updateMicroFocus();
}
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplicationPrivate::keypadNavigationEnabled() || (hasEditFocus() && ( e->reason() == Qt::PopupFocusReason))) {
@@ -1900,7 +1915,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
d->control->setBlinkingCursorEnabled(true);
QStyleOptionFrame opt;
initStyleOption(&opt);
- if((!hasSelectedText() && d->control->preeditAreaText().isEmpty())
+ if ((!hasSelectedText() && d->control->preeditAreaText().isEmpty())
|| style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(true);
#ifdef QT_KEYPAD_NAVIGATION
@@ -1910,10 +1925,7 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
#if QT_CONFIG(completer)
if (d->control->completer()) {
d->control->completer()->setWidget(this);
- QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
- this, SLOT(setText(QString)));
- QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
- this, SLOT(_q_completionHighlighted(QString)));
+ d->connectCompleter();
}
#endif
update();
@@ -1952,9 +1964,8 @@ void QLineEdit::focusOutEvent(QFocusEvent *e)
d->control->setCancelText(QString());
#endif
#if QT_CONFIG(completer)
- if (d->control->completer()) {
- QObject::disconnect(d->control->completer(), nullptr, this, nullptr);
- }
+ if (d->control->completer())
+ d->disconnectCompleter();
#endif
QWidget::focusOutEvent(e);
}
@@ -1975,21 +1986,28 @@ void QLineEdit::paintEvent(QPaintEvent *)
p.setClipRect(r);
QFontMetrics fm = fontMetrics();
+ int fmHeight = 0;
+ if (d->shouldShowPlaceholderText())
+ fmHeight = fm.boundingRect(d->placeholderText).height();
+ else
+ fmHeight = fm.boundingRect(d->control->text() + d->control->preeditAreaText()).height();
+ fmHeight = qMax(fmHeight, fm.height());
+
Qt::Alignment va = QStyle::visualAlignment(d->control->layoutDirection(), QFlag(d->alignment));
switch (va & Qt::AlignVertical_Mask) {
case Qt::AlignBottom:
- d->vscroll = r.y() + r.height() - fm.height() - QLineEditPrivate::verticalMargin;
+ d->vscroll = r.y() + r.height() - fmHeight - QLineEditPrivate::verticalMargin;
break;
case Qt::AlignTop:
d->vscroll = r.y() + QLineEditPrivate::verticalMargin;
break;
default:
//center
- d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2;
+ d->vscroll = r.y() + (r.height() - fmHeight + 1) / 2;
break;
}
QRect lineRect(r.x() + QLineEditPrivate::horizontalMargin, d->vscroll,
- r.width() - 2 * QLineEditPrivate::horizontalMargin, fm.height());
+ r.width() - 2 * QLineEditPrivate::horizontalMargin, fmHeight);
if (d->shouldShowPlaceholderText()) {
if (!d->placeholderText.isEmpty()) {
@@ -2046,6 +2064,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
}
// the y offset is there to keep the baseline constant in case we have script changes in the text.
+ // Needs to be kept in sync with QLineEditPrivate::adjustedControlRect
QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
// draw text, selections and cursors
@@ -2071,11 +2090,13 @@ void QLineEdit::paintEvent(QPaintEvent *)
// Asian users see an IM selection text as cursor on candidate
// selection phase of input method, so the ordinary cursor should be
- // invisible if we have a preedit string.
- if (d->cursorVisible && !d->control->isReadOnly())
+ // invisible if we have a preedit string. another condition is when inputmask
+ // isn't empty,we don't need draw cursor,because cursor and character overlapping
+ // area is white.
+ if (d->cursorVisible && !d->control->isReadOnly() && d->control->inputMask().isEmpty())
flags |= QWidgetLineControl::DrawCursor;
- d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth, &panel, this));
d->control->draw(&p, topLeft, r, flags);
}
@@ -2087,9 +2108,9 @@ void QLineEdit::paintEvent(QPaintEvent *)
void QLineEdit::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QLineEdit);
- if (!d->control->isReadOnly() && e->mimeData()->hasFormat(QLatin1String("text/plain"))) {
+ if (!d->control->isReadOnly() && e->mimeData()->hasFormat("text/plain"_L1)) {
e->acceptProposedAction();
- d->control->moveCursor(d->xToPos(e->pos().x()), false);
+ d->control->moveCursor(d->xToPos(e->position().toPoint().x()), false);
d->cursorVisible = true;
update();
}
@@ -2120,7 +2141,7 @@ void QLineEdit::dropEvent(QDropEvent* e)
if (!str.isNull() && !d->control->isReadOnly()) {
if (e->source() == this && e->dropAction() == Qt::CopyAction)
deselect();
- int cursorPos = d->xToPos(e->pos().x());
+ int cursorPos = d->xToPos(e->position().toPoint().x());
int selStart = cursorPos;
int oldSelStart = d->control->selectionStart();
int oldSelEnd = d->control->selectionEnd();
@@ -2131,13 +2152,13 @@ void QLineEdit::dropEvent(QDropEvent* e)
if (e->source() == this) {
if (e->dropAction() == Qt::MoveAction) {
if (selStart > oldSelStart && selStart <= oldSelEnd)
- setSelection(oldSelStart, str.length());
+ setSelection(oldSelStart, str.size());
else if (selStart > oldSelEnd)
- setSelection(selStart - str.length(), str.length());
+ setSelection(selStart - str.size(), str.size());
else
- setSelection(selStart, str.length());
+ setSelection(selStart, str.size());
} else {
- setSelection(selStart, str.length());
+ setSelection(selStart, str.size());
}
}
} else {
@@ -2154,10 +2175,10 @@ void QLineEdit::dropEvent(QDropEvent* e)
createStandardContextMenu().
If you do not want the line edit to have a context menu, you can set
- its \l contextMenuPolicy to Qt::NoContextMenu. If you want to
- customize the context menu, reimplement this function. If you want
- to extend the standard context menu, reimplement this function, call
- createStandardContextMenu() and extend the menu returned.
+ its \l contextMenuPolicy to Qt::NoContextMenu. To customize the context
+ menu, reimplement this function. To extend the standard context menu,
+ reimplement this function, call createStandardContextMenu(), and extend the
+ menu returned.
\snippet code/src_gui_widgets_qlineedit.cpp 0
@@ -2174,14 +2195,7 @@ void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
}
}
-static inline void setActionIcon(QAction *action, const QString &name)
-{
- const QIcon icon = QIcon::fromTheme(name);
- if (!icon.isNull())
- action->setIcon(icon);
-}
-
-/*! This function creates the standard context menu which is shown
+/*! Creates the standard context menu, which is shown
when the user clicks on the line edit with the right mouse
button. It is called from the default contextMenuEvent() handler.
The popup menu's ownership is transferred to the caller.
@@ -2191,19 +2205,19 @@ QMenu *QLineEdit::createStandardContextMenu()
{
Q_D(QLineEdit);
QMenu *popup = new QMenu(this);
- popup->setObjectName(QLatin1String("qt_edit_menu"));
+ popup->setObjectName("qt_edit_menu"_L1);
QAction *action = nullptr;
if (!isReadOnly()) {
action = popup->addAction(QLineEdit::tr("&Undo") + ACCEL_KEY(QKeySequence::Undo));
action->setEnabled(d->control->isUndoAvailable());
setActionIcon(action, QStringLiteral("edit-undo"));
- connect(action, SIGNAL(triggered()), SLOT(undo()));
+ connect(action, &QAction::triggered, this, &QLineEdit::undo);
action = popup->addAction(QLineEdit::tr("&Redo") + ACCEL_KEY(QKeySequence::Redo));
action->setEnabled(d->control->isRedoAvailable());
setActionIcon(action, QStringLiteral("edit-redo"));
- connect(action, SIGNAL(triggered()), SLOT(redo()));
+ connect(action, &QAction::triggered, this, &QLineEdit::redo);
popup->addSeparator();
}
@@ -2214,20 +2228,20 @@ QMenu *QLineEdit::createStandardContextMenu()
action->setEnabled(!d->control->isReadOnly() && d->control->hasSelectedText()
&& d->control->echoMode() == QLineEdit::Normal);
setActionIcon(action, QStringLiteral("edit-cut"));
- connect(action, SIGNAL(triggered()), SLOT(cut()));
+ connect(action, &QAction::triggered, this, &QLineEdit::cut);
}
action = popup->addAction(QLineEdit::tr("&Copy") + ACCEL_KEY(QKeySequence::Copy));
action->setEnabled(d->control->hasSelectedText()
&& d->control->echoMode() == QLineEdit::Normal);
setActionIcon(action, QStringLiteral("edit-copy"));
- connect(action, SIGNAL(triggered()), SLOT(copy()));
+ connect(action, &QAction::triggered, this, &QLineEdit::copy);
if (!isReadOnly()) {
action = popup->addAction(QLineEdit::tr("&Paste") + ACCEL_KEY(QKeySequence::Paste));
action->setEnabled(!d->control->isReadOnly() && !QGuiApplication::clipboard()->text().isEmpty());
setActionIcon(action, QStringLiteral("edit-paste"));
- connect(action, SIGNAL(triggered()), SLOT(paste()));
+ connect(action, &QAction::triggered, this, &QLineEdit::paste);
}
#endif
@@ -2235,7 +2249,8 @@ QMenu *QLineEdit::createStandardContextMenu()
action = popup->addAction(QLineEdit::tr("Delete"));
action->setEnabled(!d->control->isReadOnly() && !d->control->text().isEmpty() && d->control->hasSelectedText());
setActionIcon(action, QStringLiteral("edit-delete"));
- connect(action, SIGNAL(triggered()), d->control, SLOT(_q_deleteSelected()));
+ connect(action, &QAction::triggered,
+ d->control, &QWidgetLineControl::_q_deleteSelected);
}
if (!popup->isEmpty())
@@ -2245,7 +2260,7 @@ QMenu *QLineEdit::createStandardContextMenu()
action->setEnabled(!d->control->text().isEmpty() && !d->control->allSelected());
setActionIcon(action, QStringLiteral("edit-select-all"));
d->selectAllAction = action;
- connect(action, SIGNAL(triggered()), SLOT(selectAll()));
+ connect(action, &QAction::triggered, this, &QLineEdit::selectAll);
if (!d->control->isReadOnly() && QGuiApplication::styleHints()->useRtlExtensions()) {
popup->addSeparator();
@@ -2273,7 +2288,7 @@ void QLineEdit::changeEvent(QEvent *ev)
{
QStyleOptionFrame opt;
initStyleOption(&opt);
- d->control->setPasswordCharacter(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this));
+ d->control->setPasswordCharacter(char16_t(style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, this)));
d->control->setPasswordMaskDelay(style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, this));
}
update();
diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h
index 1cf1f24449..8955a67895 100644
--- a/src/widgets/widgets/qlineedit.h
+++ b/src/widgets/widgets/qlineedit.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLINEEDIT_H
#define QLINEEDIT_H
@@ -172,10 +136,6 @@ public:
void setTextMargins(int left, int top, int right, int bottom);
void setTextMargins(const QMargins &margins);
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_X("use textMargins()")
- void getTextMargins(int *left, int *top, int *right, int *bottom) const;
-#endif
QMargins textMargins() const;
#if QT_CONFIG(action)
@@ -218,6 +178,7 @@ protected:
void mouseReleaseEvent(QMouseEvent *) override;
void mouseDoubleClickEvent(QMouseEvent *) override;
void keyPressEvent(QKeyEvent *) override;
+ void keyReleaseEvent(QKeyEvent *) override;
void focusInEvent(QFocusEvent *) override;
void focusOutEvent(QFocusEvent *) override;
void paintEvent(QPaintEvent *) override;
@@ -233,10 +194,11 @@ protected:
#endif
void inputMethodEvent(QInputMethodEvent *) override;
- void initStyleOption(QStyleOptionFrame *option) const;
+ virtual void initStyleOption(QStyleOptionFrame *option) const;
public:
QVariant inputMethodQuery(Qt::InputMethodQuery) const override;
Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const;
+ void timerEvent(QTimerEvent *) override;
bool event(QEvent *) override;
protected:
QRect cursorRect() const;
@@ -252,19 +214,6 @@ private:
#endif
Q_DISABLE_COPY(QLineEdit)
Q_DECLARE_PRIVATE(QLineEdit)
- Q_PRIVATE_SLOT(d_func(), void _q_handleWindowActivate())
- Q_PRIVATE_SLOT(d_func(), void _q_textEdited(const QString &))
- Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged(int, int))
-#if QT_CONFIG(completer)
- Q_PRIVATE_SLOT(d_func(), void _q_completionHighlighted(const QString &))
-#endif
-#ifdef QT_KEYPAD_NAVIGATION
- Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool))
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &))
- Q_PRIVATE_SLOT(d_func(), void _q_textChanged(const QString &))
- Q_PRIVATE_SLOT(d_func(), void _q_clearButtonClicked())
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 29e0ae3b39..fdd6a3aa4f 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlineedit.h"
#include "qlineedit_p.h"
@@ -51,7 +15,7 @@
# include "qwidgetaction.h"
#endif
#include "qclipboard.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#ifndef QT_NO_IM
@@ -70,12 +34,13 @@ QT_BEGIN_NAMESPACE
const int QLineEditPrivate::verticalMargin(1);
const int QLineEditPrivate::horizontalMargin(2);
+// Needs to be kept in sync with QLineEdit::paintEvent
QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const
{
QRect widgetRect = !rect.isEmpty() ? rect : q_func()->rect();
QRect cr = adjustedContentsRect();
int cix = cr.x() - hscroll + horizontalMargin;
- return widgetRect.translated(QPoint(cix, vscroll));
+ return widgetRect.translated(QPoint(cix, vscroll - control->ascent() + q_func()->fontMetrics().ascent()));
}
int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
@@ -85,6 +50,18 @@ int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
return control->xToPos(x, betweenOrOn);
}
+QString QLineEditPrivate::textBeforeCursor(int curPos) const
+{
+ const QString &text = control->text();
+ return text.mid(0, curPos);
+}
+
+QString QLineEditPrivate::textAfterCursor(int curPos) const
+{
+ const QString &text = control->text();
+ return text.mid(curPos);
+}
+
bool QLineEditPrivate::inSelection(int x) const
{
x -= adjustedContentsRect().x() - hscroll + horizontalMargin;
@@ -97,8 +74,25 @@ QRect QLineEditPrivate::cursorRect() const
}
#if QT_CONFIG(completer)
+void QLineEditPrivate::connectCompleter()
+{
+ Q_Q(const QLineEdit);
+ QObject::connect(control->completer(), qOverload<const QString &>(&QCompleter::activated),
+ q, &QLineEdit::setText);
+ QObjectPrivate::connect(control->completer(), qOverload<const QString &>(&QCompleter::highlighted),
+ this, &QLineEditPrivate::completionHighlighted);
+}
-void QLineEditPrivate::_q_completionHighlighted(const QString &newText)
+void QLineEditPrivate::disconnectCompleter()
+{
+ Q_Q(const QLineEdit);
+ QObject::disconnect(control->completer(), qOverload<const QString &>(&QCompleter::activated),
+ q, &QLineEdit::setText);
+ QObjectPrivate::disconnect(control->completer(), qOverload<const QString &>(&QCompleter::highlighted),
+ this, &QLineEditPrivate::completionHighlighted);
+}
+
+void QLineEditPrivate::completionHighlighted(const QString &newText)
{
Q_Q(QLineEdit);
if (control->completer()->completionMode() != QCompleter::InlineCompletion) {
@@ -106,7 +100,7 @@ void QLineEditPrivate::_q_completionHighlighted(const QString &newText)
} else {
int c = control->cursor();
QString text = control->text();
- q->setText(text.leftRef(c) + newText.midRef(c));
+ q->setText(QStringView{text}.left(c) + QStringView{newText}.mid(c));
control->moveCursor(control->end(), false);
#ifndef Q_OS_ANDROID
const bool mark = true;
@@ -119,14 +113,14 @@ void QLineEditPrivate::_q_completionHighlighted(const QString &newText)
#endif // QT_CONFIG(completer)
-void QLineEditPrivate::_q_handleWindowActivate()
+void QLineEditPrivate::handleWindowActivate()
{
Q_Q(QLineEdit);
if (!q->hasFocus() && control->hasSelectedText())
control->deselect();
}
-void QLineEditPrivate::_q_textEdited(const QString &text)
+void QLineEditPrivate::textEdited(const QString &text)
{
Q_Q(QLineEdit);
edited = true;
@@ -138,7 +132,7 @@ void QLineEditPrivate::_q_textEdited(const QString &text)
#endif
}
-void QLineEditPrivate::_q_cursorPositionChanged(int from, int to)
+void QLineEditPrivate::cursorPositionChanged(int from, int to)
{
Q_Q(QLineEdit);
q->update();
@@ -146,14 +140,14 @@ void QLineEditPrivate::_q_cursorPositionChanged(int from, int to)
}
#ifdef QT_KEYPAD_NAVIGATION
-void QLineEditPrivate::_q_editFocusChange(bool e)
+void QLineEditPrivate::editFocusChange(bool e)
{
Q_Q(QLineEdit);
q->setEditFocus(e);
}
#endif
-void QLineEditPrivate::_q_selectionChanged()
+void QLineEditPrivate::selectionChanged()
{
Q_Q(QLineEdit);
if (control->preeditAreaText().isEmpty()) {
@@ -166,14 +160,14 @@ void QLineEditPrivate::_q_selectionChanged()
}
emit q->selectionChanged();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextSelectionEvent ev(q, control->selectionStart(), control->selectionEnd());
ev.setCursorPosition(control->cursorPosition());
QAccessible::updateAccessibility(&ev);
#endif
}
-void QLineEditPrivate::_q_updateNeeded(const QRect &rect)
+void QLineEditPrivate::updateNeeded(const QRect &rect)
{
q_func()->update(adjustedControlRect(rect));
}
@@ -181,51 +175,55 @@ void QLineEditPrivate::_q_updateNeeded(const QRect &rect)
void QLineEditPrivate::init(const QString& txt)
{
Q_Q(QLineEdit);
+
+ const auto qUpdateMicroFocus = [q]()
+ {
+ q->updateMicroFocus();
+ };
control = new QWidgetLineControl(txt);
control->setParent(q);
control->setFont(q->font());
- QObject::connect(control, SIGNAL(textChanged(QString)),
- q, SIGNAL(textChanged(QString)));
- QObject::connect(control, SIGNAL(textEdited(QString)),
- q, SLOT(_q_textEdited(QString)));
- QObject::connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(_q_cursorPositionChanged(int,int)));
- QObject::connect(control, SIGNAL(selectionChanged()),
- q, SLOT(_q_selectionChanged()));
- QObject::connect(control, SIGNAL(accepted()),
- q, SIGNAL(returnPressed()));
- QObject::connect(control, SIGNAL(editingFinished()),
- q, SIGNAL(editingFinished()));
+ QObject::connect(control, &QWidgetLineControl::textChanged,
+ q, &QLineEdit::textChanged);
+ QObjectPrivate::connect(control, &QWidgetLineControl::textEdited,
+ this, &QLineEditPrivate::textEdited);
+ QObjectPrivate::connect(control, &QWidgetLineControl::cursorPositionChanged,
+ this, &QLineEditPrivate::cursorPositionChanged);
+ QObjectPrivate::connect(control, &QWidgetLineControl::selectionChanged,
+ this, &QLineEditPrivate::selectionChanged);
+ QObjectPrivate::connect(control, &QWidgetLineControl::editingFinished,
+ this, &QLineEditPrivate::controlEditingFinished);
#ifdef QT_KEYPAD_NAVIGATION
- QObject::connect(control, SIGNAL(editFocusChange(bool)),
- q, SLOT(_q_editFocusChange(bool)));
+ QObject::connect(control, &QWidgetLineControl::editFocusChange,
+ this, &QLineEditPrivate::editFocusChange);
#endif
- QObject::connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(updateMicroFocus()));
+ QObject::connect(control, &QWidgetLineControl::cursorPositionChanged,
+ q, qUpdateMicroFocus);
- QObject::connect(control, SIGNAL(textChanged(QString)),
- q, SLOT(updateMicroFocus()));
+ QObject::connect(control, &QWidgetLineControl::textChanged,
+ q, qUpdateMicroFocus);
- QObject::connect(control, SIGNAL(updateMicroFocus()),
- q, SLOT(updateMicroFocus()));
+ QObject::connect(control, &QWidgetLineControl::updateMicroFocus,
+ q, qUpdateMicroFocus);
// for now, going completely overboard with updates.
- QObject::connect(control, SIGNAL(selectionChanged()),
- q, SLOT(update()));
+ QObject::connect(control, &QWidgetLineControl::selectionChanged,
+ q, qOverload<>(&QLineEdit::update));
- QObject::connect(control, SIGNAL(selectionChanged()),
- q, SLOT(updateMicroFocus()));
+ QObject::connect(control, &QWidgetLineControl::selectionChanged,
+ q, qUpdateMicroFocus);
- QObject::connect(control, SIGNAL(displayTextChanged(QString)),
- q, SLOT(update()));
+ QObject::connect(control, &QWidgetLineControl::displayTextChanged,
+ q, qOverload<>(&QLineEdit::update));
- QObject::connect(control, SIGNAL(updateNeeded(QRect)),
- q, SLOT(_q_updateNeeded(QRect)));
- QObject::connect(control, SIGNAL(inputRejected()), q, SIGNAL(inputRejected()));
+ QObjectPrivate::connect(control, &QWidgetLineControl::updateNeeded,
+ this, &QLineEditPrivate::updateNeeded);
+ QObject::connect(control, &QWidgetLineControl::inputRejected,
+ q, &QLineEdit::inputRejected);
QStyleOptionFrame opt;
q->initStyleOption(&opt);
- control->setPasswordCharacter(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q));
+ control->setPasswordCharacter(char16_t(q->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, q)));
control->setPasswordMaskDelay(q->style()->styleHint(QStyle::SH_LineEdit_PasswordMaskDelay, &opt, q));
#ifndef QT_NO_CURSOR
q->setCursor(Qt::IBeamCursor);
@@ -302,9 +300,9 @@ bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
{
#if !defined QT_NO_IM
if ( control->composeMode() ) {
- int tmp_cursor = xToPos(e->pos().x());
+ int tmp_cursor = xToPos(e->position().toPoint().x());
int mousePos = tmp_cursor - control->cursor();
- if ( mousePos < 0 || mousePos > control->preeditAreaText().length() )
+ if ( mousePos < 0 || mousePos > control->preeditAreaText().size() )
mousePos = -1;
if (mousePos >= 0) {
@@ -354,14 +352,13 @@ QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const
void QLineEditIconButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
- QWindow *window = qt_widget_private(this)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
QIcon::Mode state = QIcon::Disabled;
if (isEnabled())
state = isDown() ? QIcon::Active : QIcon::Normal;
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);
+ const QPixmap iconPixmap = icon().pixmap(iconSize, devicePixelRatio(), state, QIcon::Off);
QRect pixmapRect = QRect(QPoint(0, 0), iconSize);
pixmapRect.moveCenter(rect().center());
painter.setOpacity(m_opacity);
@@ -408,8 +405,9 @@ void QLineEditIconButton::setHideWithText(bool hide)
void QLineEditIconButton::onAnimationFinished()
{
- if (shouldHideWithText() && isVisible() && !m_wasHidden) {
+ if (shouldHideWithText() && isVisible() && m_fadingOut) {
hide();
+ m_fadingOut = false;
// Invalidate previous geometry to take into account new size of side widgets
if (auto le = lineEditPrivate())
@@ -419,7 +417,7 @@ void QLineEditIconButton::onAnimationFinished()
void QLineEditIconButton::animateShow(bool visible)
{
- m_wasHidden = visible;
+ m_fadingOut = !visible;
if (shouldHideWithText() && !isVisible()) {
show();
@@ -434,7 +432,7 @@ void QLineEditIconButton::animateShow(bool visible)
void QLineEditIconButton::startOpacityAnimation(qreal endValue)
{
- QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"));
+ QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity"), this);
connect(animation, &QPropertyAnimation::finished, this, &QLineEditIconButton::onAnimationFinished);
animation->setDuration(160);
@@ -461,7 +459,7 @@ static void displayWidgets(const QLineEditPrivate::SideWidgetEntryList &widgets,
}
#endif
-void QLineEditPrivate::_q_textChanged(const QString &text)
+void QLineEditPrivate::textChanged(const QString &text)
{
if (hasSideWidgets()) {
const int newTextSize = text.size();
@@ -476,21 +474,29 @@ void QLineEditPrivate::_q_textChanged(const QString &text)
}
}
-void QLineEditPrivate::_q_clearButtonClicked()
+void QLineEditPrivate::clearButtonClicked()
{
Q_Q(QLineEdit);
if (!q->text().isEmpty()) {
q->clear();
- emit q->textEdited(QString());
+ textEdited(QString());
}
}
+void QLineEditPrivate::controlEditingFinished()
+{
+ Q_Q(QLineEdit);
+ edited = false;
+ emit q->returnPressed();
+ emit q->editingFinished();
+}
+
QLineEditPrivate::SideWidgetParameters QLineEditPrivate::sideWidgetParameters() const
{
Q_Q(const QLineEdit);
SideWidgetParameters result;
- result.iconSize = q->style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, q);
- result.margin = result.iconSize / 4;
+ result.iconSize = q->style()->pixelMetric(QStyle::PM_LineEditIconSize, nullptr, q);
+ result.margin = q->style()->pixelMetric(QStyle::PM_LineEditIconMargin, nullptr, q);
result.widgetWidth = result.iconSize + 6;
result.widgetHeight = result.iconSize + 2;
return result;
@@ -548,7 +554,7 @@ void QLineEditPrivate::positionSideWidgets()
}
#if QT_CONFIG(action)
-QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QGuiAction *a) const
+QLineEditPrivate::SideWidgetLocation QLineEditPrivate::findSideWidget(const QAction *a) const
{
int i = 0;
for (const auto &e : leadingSideWidgets) {
@@ -571,7 +577,8 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
if (!newAction)
return nullptr;
if (!hasSideWidgets()) { // initial setup.
- QObject::connect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
+ QObjectPrivate::connect(q, &QLineEdit::textChanged,
+ this, &QLineEditPrivate::textChanged);
lastTextSize = q->text().size();
}
QWidget *w = nullptr;
@@ -587,7 +594,8 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
toolButton->setIcon(newAction->icon());
toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0);
if (flags & SideWidgetClearButton) {
- QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(_q_clearButtonClicked()));
+ QObjectPrivate::connect(toolButton, &QToolButton::clicked,
+ this, &QLineEditPrivate::clearButtonClicked);
#if QT_CONFIG(animation)
// The clear button is handled only by this widget. The button should be really
@@ -635,7 +643,7 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE
return w;
}
-void QLineEditPrivate::removeAction(QGuiAction *action)
+void QLineEditPrivate::removeAction(QAction *action)
{
Q_Q(QLineEdit);
const auto location = findSideWidget(action);
@@ -650,7 +658,8 @@ void QLineEditPrivate::removeAction(QGuiAction *action)
delete entry.widget;
positionSideWidgets();
if (!hasSideWidgets()) // Last widget, remove connection
- QObject::disconnect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
+ QObjectPrivate::connect(q, &QLineEdit::textChanged,
+ this, &QLineEditPrivate::textChanged);
q->update();
}
#endif // QT_CONFIG(action)
@@ -661,10 +670,18 @@ static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWi
if (widgets.empty())
return defaultMargin;
- return defaultMargin + (parameters.margin + parameters.widgetWidth) *
- int(std::count_if(widgets.begin(), widgets.end(),
+ const auto visibleSideWidgetCount = std::count_if(widgets.begin(), widgets.end(),
[](const QLineEditPrivate::SideWidgetEntry &e) {
- return e.widget->isVisibleTo(e.widget->parentWidget()); }));
+#if QT_CONFIG(toolbutton) && QT_CONFIG(animation)
+ // a button that's fading out doesn't get any space
+ if (auto* iconButton = qobject_cast<QLineEditIconButton*>(e.widget))
+ return iconButton->needsSpace();
+
+#endif
+ return e.widget->isVisibleTo(e.widget->parentWidget());
+ });
+
+ return defaultMargin + (parameters.margin + parameters.widgetWidth) * visibleSideWidgetCount;
}
QMargins QLineEditPrivate::effectiveTextMargins() const
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index 9fe571b4bb..3737ac8fe6 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLINEEDIT_P_H
#define QLINEEDIT_P_H
@@ -95,6 +59,11 @@ public:
bool shouldHideWithText() const;
void setHideWithText(bool hide);
+ bool needsSpace() const {
+ if (m_fadingOut)
+ return false;
+ return isVisibleTo(parentWidget());
+ }
#endif
protected:
@@ -118,7 +87,7 @@ private:
#if QT_CONFIG(animation)
bool m_hideWithText = false;
- bool m_wasHidden = false;
+ bool m_fadingOut = false;
#endif
};
@@ -179,13 +148,19 @@ public:
void setCursorVisible(bool visible);
void setText(const QString& text);
+ QString textBeforeCursor(int curPos) const;
+ QString textAfterCursor(int curPos) const;
void updatePasswordEchoEditing(bool);
void resetInputMethod();
inline bool shouldEnableInputMethod() const
{
+#if defined (Q_OS_ANDROID)
+ return !control->isReadOnly() || control->isSelectableByMouse();
+#else
return !control->isReadOnly();
+#endif
}
inline bool shouldShowPlaceholderText() const
{
@@ -215,24 +190,27 @@ public:
QRect adjustedContentsRect() const;
- void _q_handleWindowActivate();
- void _q_textEdited(const QString &);
- void _q_cursorPositionChanged(int, int);
+ void handleWindowActivate();
+ void textEdited(const QString &);
+ void cursorPositionChanged(int, int);
#ifdef QT_KEYPAD_NAVIGATION
- void _q_editFocusChange(bool);
+ void editFocusChange(bool);
#endif
- void _q_selectionChanged();
- void _q_updateNeeded(const QRect &);
+ void selectionChanged();
+ void updateNeeded(const QRect &);
#if QT_CONFIG(completer)
- void _q_completionHighlighted(const QString &);
+ void connectCompleter();
+ void disconnectCompleter();
+ void completionHighlighted(const QString &);
#endif
QPoint mousePressPos;
#if QT_CONFIG(draganddrop)
QBasicTimer dndTimer;
void drag();
#endif
- void _q_textChanged(const QString &);
- void _q_clearButtonClicked();
+ void textChanged(const QString &);
+ void clearButtonClicked();
+ void controlEditingFinished();
QMargins textMargins; // use effectiveTextMargins() in case of icon.
@@ -240,7 +218,7 @@ public:
#if QT_CONFIG(action)
QWidget *addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition, int flags = 0);
- void removeAction(QGuiAction *action);
+ void removeAction(QAction *action);
#endif
SideWidgetParameters sideWidgetParameters() const;
QIcon clearButtonIcon() const;
@@ -264,7 +242,7 @@ private:
friend class QTypeInfo<SideWidgetLocation>;
#if QT_CONFIG(action)
- SideWidgetLocation findSideWidget(const QGuiAction *a) const;
+ SideWidgetLocation findSideWidget(const QAction *a) const;
#endif
SideWidgetEntryList leadingSideWidgets;
diff --git a/src/widgets/widgets/qmaccocoaviewcontainer_mac.h b/src/widgets/widgets/qmaccocoaviewcontainer_mac.h
deleted file mode 100644
index 0de3989167..0000000000
--- a/src/widgets/widgets/qmaccocoaviewcontainer_mac.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QCOCOAVIEWCONTAINER_H
-#define QCOCOAVIEWCONTAINER_H
-
-#include <QtWidgets/qtwidgetsglobal.h>
-#include <QtWidgets/QWidget>
-
-Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
-
-QT_BEGIN_NAMESPACE
-
-class QMacCocoaViewContainerPrivate;
-class Q_WIDGETS_EXPORT QMacCocoaViewContainer : public QWidget
-{
- Q_OBJECT
-public:
- QMacCocoaViewContainer(NSView *cocoaViewToWrap, QWidget *parent = nullptr);
- virtual ~QMacCocoaViewContainer();
-
- void setCocoaView(NSView *view);
- NSView *cocoaView() const;
-
-private:
- Q_DECLARE_PRIVATE(QMacCocoaViewContainer)
-};
-
-QT_END_NAMESPACE
-
-#endif // QCOCOAVIEWCONTAINER_H
diff --git a/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm b/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm
deleted file mode 100644
index f261314c64..0000000000
--- a/src/widgets/widgets/qmaccocoaviewcontainer_mac.mm
+++ /dev/null
@@ -1,199 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#import <AppKit/AppKit.h>
-#include "qmaccocoaviewcontainer_mac.h"
-
-#include <QtCore/QDebug>
-#include <QtGui/QWindow>
-#include <qpa/qplatformnativeinterface.h>
-#include <private/qwidget_p.h>
-#include <private/qwindow_p.h>
-
-/*!
- \class QMacCocoaViewContainer
- \since 4.5
-
- \brief The QMacCocoaViewContainer class provides a widget for \macos that can be used to wrap arbitrary
- Cocoa views (i.e., NSView subclasses) and insert them into Qt hierarchies.
-
- \ingroup advanced
- \inmodule QtWidgets
-
- While Qt offers a lot of classes for writing your application, Apple's
- Cocoa frameworks offer functionality that is not currently available (or
- may never end up) in Qt. Using QMacCocoaViewContainer, it is possible to take an
- arbitrary NSView-derived class from Cocoa and put it in a Qt widgets hierarchy.
- Depending on the level of integration you need, you can use QMacCocoaViewContainer
- directly or subclass it to wrap more functionality of the underlying NSView.
-
- It should be also noted that, at the Cocoa level, there is a difference
- between top-level windows and views (widgets that are inside a window).
- For this reason, make sure that the NSView that you are wrapping doesn't
- end up as a top-level window. The best way to ensure this is to make sure
- QMacCocoaViewContainer's parent widget is not null.
-
- If you are using QMacCocoaViewContainer as a subclass and are accessing Cocoa API,
- it is probably simpler to have your file end with \tt{.mm} instead of \tt{.cpp}.
- Most Apple tools will correctly identify the source as Objective-C++.
-
- QMacCocoaViewContainer requires knowledge of how Cocoa works, especially in
- regard to its reference counting (retain/release) nature. It is noted in
- the functions below if there is any change in the reference count. Cocoa
- views often generate temporary objects that are released by an autorelease
- pool. If this is done outside of a running event loop, it is up to the
- developer to provide the autorelease pool.
-
- The following is a snippet showing how to subclass QMacCocoaViewContainer
- to wrap an NSSearchField.
-
- \code
- SearchWidget::SearchWidget(QWidget *parent)
- : QMacCocoaViewContainer(0, parent)
- {
- // Many Cocoa objects create temporary autorelease objects,
- // so create a pool to catch them.
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- // Create the NSSearchField, set it on the QCocoaViewContainer.
- NSSearchField *search = [[NSSearchField alloc] init];
- setCocoaView(search);
-
- // Use a Qt menu for the search field menu.
- QMenu *qtMenu = createMenu(this);
- NSMenu *nsMenu = qtMenu->macMenu(0);
- [[search cell] setSearchMenuTemplate:nsMenu];
-
- // Release our reference, since our super class takes ownership and we
- // don't need it anymore.
- [search release];
-
- // Clean up our pool as we no longer need it.
- [pool release];
- }
- \endcode
-*/
-
-QT_BEGIN_NAMESPACE
-
-class QMacCocoaViewContainerPrivate : public QWidgetPrivate
-{
- Q_DECLARE_PUBLIC(QMacCocoaViewContainer)
-public:
- NSView *nsview;
- QMacCocoaViewContainerPrivate();
- ~QMacCocoaViewContainerPrivate();
-};
-
-QMacCocoaViewContainerPrivate::QMacCocoaViewContainerPrivate()
- : nsview(0)
-{
-}
-
-QMacCocoaViewContainerPrivate::~QMacCocoaViewContainerPrivate()
-{
- [nsview release];
-}
-
-/*!
- Create a new QMacCocoaViewContainer using the NSView pointer in
- the \a view with parent, \a parent. QMacCocoaViewContainer will
- retain the \a view.
-
-*/
-QMacCocoaViewContainer::QMacCocoaViewContainer(NSView *view, QWidget *parent)
- : QWidget(*new QMacCocoaViewContainerPrivate, parent, {})
-{
- // Ensures that we have a QWindow, even if we're not a top level widget
- setAttribute(Qt::WA_NativeWindow);
-
- setCocoaView(view);
-}
-
-/*!
- Destroy the QMacCocoaViewContainer and release the wrapped view.
-*/
-QMacCocoaViewContainer::~QMacCocoaViewContainer()
-{
-
-}
-
-/*!
- Returns the NSView that has been set on this container.
-*/
-NSView *QMacCocoaViewContainer::cocoaView() const
-{
- Q_D(const QMacCocoaViewContainer);
- return d->nsview;
-}
-
-/*!
- Sets \a view as the NSView to contain and retains it. If this
- container already had a view set, it will release the previously set view.
-*/
-void QMacCocoaViewContainer::setCocoaView(NSView *view)
-{
- Q_D(QMacCocoaViewContainer);
- NSView *oldView = d->nsview;
- [view retain];
- d->nsview = view;
-
- // Get rid of QWindow completely, and re-create a new vanilla one, which
- // we will then re-configure to be a foreign window.
- destroy();
- create();
-
- // Can't use QWindow::fromWinId() here due to QWidget controlling its
- // QWindow, and can't use QWidget::createWindowContainer() due to the
- // QMacCocoaViewContainer class being public API instead of a factory
- // function.
- QWindow *window = windowHandle();
- window->destroy();
- qt_window_private(window)->create(false, WId(view));
- Q_ASSERT(window->handle());
-
- [oldView release];
-
- // The QWindow::destroy()) call above will explicitly hide this widget.
- // Clear the hidden state here so it can be implicitly shown again.
- setAttribute(Qt::WA_WState_Hidden, false);
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qmacnativewidget_mac.h b/src/widgets/widgets/qmacnativewidget_mac.h
deleted file mode 100644
index 6fd90516ac..0000000000
--- a/src/widgets/widgets/qmacnativewidget_mac.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMACNATIVEWIDGET_H
-#define QMACNATIVEWIDGET_H
-
-#include <QtWidgets/qtwidgetsglobal.h>
-#include <QtWidgets/QWidget>
-
-Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
-
-QT_BEGIN_NAMESPACE
-
-class Q_WIDGETS_EXPORT QMacNativeWidget : public QWidget
-{
- Q_OBJECT
-public:
- QMacNativeWidget(NSView *parentView = nullptr);
- ~QMacNativeWidget();
-
- QSize sizeHint() const override;
- NSView *nativeView() const;
-
-protected:
- bool event(QEvent *ev) override;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMACNATIVEWIDGET_H
diff --git a/src/widgets/widgets/qmacnativewidget_mac.mm b/src/widgets/widgets/qmacnativewidget_mac.mm
deleted file mode 100644
index 874ca84b61..0000000000
--- a/src/widgets/widgets/qmacnativewidget_mac.mm
+++ /dev/null
@@ -1,166 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#import <AppKit/AppKit.h>
-#include "qmacnativewidget_mac.h"
-
-#include <QtCore/qdebug.h>
-#include <QtGui/qwindow.h>
-#include <QtGui/qguiapplication.h>
-#include <qpa/qplatformnativeinterface.h>
-
-/*!
- \class QMacNativeWidget
- \since 4.5
- \brief The QMacNativeWidget class provides a widget for \macos that provides
- a way to put Qt widgets into Cocoa hierarchies.
-
- \ingroup advanced
- \inmodule QtWidgets
-
- On \macos, there is a difference between a window and view;
- normally expressed as widgets in Qt. Qt makes assumptions about its
- parent-child hierarchy that make it complex to put an arbitrary Qt widget
- into a hierarchy of "normal" views from Apple frameworks. QMacNativeWidget
- bridges the gap between views and windows and makes it possible to put a
- hierarchy of Qt widgets into a non-Qt window or view.
-
- QMacNativeWidget pretends it is a window (i.e. isWindow() will return true),
- but it cannot be shown on its own. It needs to be put into a window
- when it is created or later through a native call.
-
- Here is an example showing how to put a QPushButton into a NSWindow:
-
- \snippet qmacnativewidget/main.mm 0
-
- Note that QMacNativeWidget requires knowledge of Cocoa. All it
- does is get the Qt hierarchy into a window not owned by Qt. It is then up
- to the programmer to ensure it is placed correctly in the window and
- responds correctly to events.
-*/
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-// TODO use QtMacExtras copy of this function when available.
-inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePlatformFunction(const QByteArray &functionName)
-{
- QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
- nativeInterface->nativeResourceFunctionForIntegration(functionName);
- if (Q_UNLIKELY(!function))
- qWarning("Qt could not resolve function %s from "
- "QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration()",
- functionName.constData());
- return function;
-}
-} //namespsace
-
-NSView *getEmbeddableView(QWindow *qtWindow)
-{
- // Make sure the platform window is created
- qtWindow->create();
-
- // Inform the window that it's a subwindow of a non-Qt window. This must be
- // done after create() because we need to have a QPlatformWindow instance.
- // The corresponding NSWindow will not be shown and can be deleted later.
- typedef void (*SetEmbeddedInForeignViewFunction)(QPlatformWindow *window, bool embedded);
- reinterpret_cast<SetEmbeddedInForeignViewFunction>(resolvePlatformFunction("setEmbeddedInForeignView"))(qtWindow->handle(), true);
-
- // Get the Qt content NSView for the QWindow from the Qt platform plugin
- QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface();
- NSView *qtView = (NSView *)platformNativeInterface->nativeResourceForWindow("nsview", qtWindow);
- return qtView; // qtView is ready for use.
-}
-
-/*!
- Create a QMacNativeWidget with \a parentView as its "superview" (i.e.,
- parent). The \a parentView is a NSView pointer.
-*/
-QMacNativeWidget::QMacNativeWidget(NSView *parentView)
- : QWidget(0)
-{
- Q_UNUSED(parentView);
-
- //d_func()->topData()->embedded = true;
- setPalette(QPalette(Qt::transparent));
- setAttribute(Qt::WA_SetPalette, false);
- setAttribute(Qt::WA_LayoutUsesWidgetRect);
- setAttribute(Qt::WA_TranslucentBackground);
- setAttribute(Qt::WA_NoSystemBackground, false);
-}
-
-/*!
- Destroy the QMacNativeWidget.
-*/
-QMacNativeWidget::~QMacNativeWidget()
-{
-}
-
-/*!
- \reimp
-*/
-QSize QMacNativeWidget::sizeHint() const
-{
- // QMacNativeWidget really does not have any other choice
- // than to fill its designated area.
- if (windowHandle())
- return windowHandle()->size();
- return QWidget::sizeHint();
-}
-
-/*!
- Returns the native view backing the QMacNativeWidget.
-
-*/
-NSView *QMacNativeWidget::nativeView() const
-{
- winId();
- return getEmbeddableView(windowHandle());
-}
-
-/*!
- \reimp
-*/
-bool QMacNativeWidget::event(QEvent *ev)
-{
- return QWidget::event(ev);
-}
-
-QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 4f94b81b19..4534058d45 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QT_EXPERIMENTAL_CLIENT_DECORATIONS
@@ -61,40 +25,42 @@
#include <qstyle.h>
#include <qdebug.h>
#include <qpainter.h>
+#include <qmimedata.h>
#include <private/qwidget_p.h>
#if QT_CONFIG(toolbar)
#include "qtoolbar_p.h"
#endif
#include "qwidgetanimator_p.h"
-#ifdef Q_OS_OSX
-#include <qpa/qplatformnativeinterface.h>
-#endif
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformwindow_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QMainWindowPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMainWindow)
public:
inline QMainWindowPrivate()
: layout(nullptr), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly)
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
, useUnifiedToolBar(false)
#endif
{ }
- QMainWindowLayout *layout;
+ QPointer<QMainWindowLayout> layout;
QSize iconSize;
bool explicitIconSize;
Qt::ToolButtonStyle toolButtonStyle;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
bool useUnifiedToolBar;
#endif
void init();
static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow)
{
- return mainWindow ? mainWindow->d_func()->layout : static_cast<QMainWindowLayout *>(nullptr);
+ return mainWindow ? mainWindow->d_func()->layout.data() : static_cast<QMainWindowLayout *>(nullptr);
}
};
@@ -158,6 +124,7 @@ void QMainWindowPrivate::init()
const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, nullptr, q);
iconSize = QSize(metric, metric);
q->setAttribute(Qt::WA_Hover);
+ q->setAcceptDrops(true);
}
/*
@@ -214,9 +181,6 @@ void QMainWindowPrivate::init()
\image mainwindowlayout.png
- \note Creating a main window without a central widget is not supported.
- You must have a central widget even if it is just a placeholder.
-
\section1 Creating Main Window Components
A central widget will typically be a standard Qt widget such
@@ -316,9 +280,7 @@ void QMainWindowPrivate::init()
is the position and size (relative to the size of the main window)
of the toolbars and dock widgets that are stored.
- \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Application
- Example}, {Dock Widgets Example}, {MDI Example}, {SDI Example},
- {Menus Example}
+ \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Menus Example}
*/
/*!
@@ -523,10 +485,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
{
QLayout *topLayout = layout();
- if (topLayout->menuBar() && topLayout->menuBar() != menuBar) {
+ if (QWidget *existingMenuBar = topLayout->menuBar(); existingMenuBar && existingMenuBar != menuBar) {
// Reparent corner widgets before we delete the old menu bar.
- QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(topLayout->menuBar());
- if (menuBar) {
+ QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(existingMenuBar);
+ if (oldMenuBar && menuBar) {
// TopLeftCorner widget.
QWidget *cornerWidget = oldMenuBar->cornerWidget(Qt::TopLeftCorner);
if (cornerWidget)
@@ -536,9 +498,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
if (cornerWidget)
menuBar->setCornerWidget(cornerWidget, Qt::TopRightCorner);
}
- oldMenuBar->hide();
- oldMenuBar->setParent(nullptr);
- oldMenuBar->deleteLater();
+
+ existingMenuBar->hide();
+ existingMenuBar->setParent(nullptr);
+ existingMenuBar->deleteLater();
}
topLayout->setMenuBar(menuBar);
}
@@ -615,7 +578,7 @@ void QMainWindow::setStatusBar(QStatusBar *statusbar)
/*!
Returns the central widget for the main window. This function
- returns zero if the central widget has not been set.
+ returns \nullptr if the central widget has not been set.
\sa setCentralWidget()
*/
@@ -762,7 +725,7 @@ void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
disconnect(this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
- if(toolbar->d_func()->state && toolbar->d_func()->state->dragging) {
+ if (toolbar->d_func()->state && toolbar->d_func()->state->dragging) {
//removing a toolbar which is dragging will cause crash
#if QT_CONFIG(dockwidget)
bool animated = isAnimated();
@@ -851,11 +814,7 @@ void QMainWindow::removeToolBar(QToolBar *toolbar)
\sa addToolBar(), addToolBarBreak(), Qt::ToolBarArea
*/
-Qt::ToolBarArea QMainWindow::toolBarArea(
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
- const
-#endif
- QToolBar *toolbar) const
+Qt::ToolBarArea QMainWindow::toolBarArea(const QToolBar *toolbar) const
{ return d_func()->layout->toolBarArea(toolbar); }
/*!
@@ -954,10 +913,10 @@ void QMainWindow::setDockNestingEnabled(bool enabled)
\since 4.2
If this property is set to false, dock areas containing tabbed dock widgets
- display horizontal tabs, simmilar to Visual Studio.
+ display horizontal tabs, similar to Visual Studio.
If this property is set to true, then the right and left dock areas display vertical
- tabs, simmilar to KDevelop.
+ tabs, similar to KDevelop.
This property should be set before any dock widgets are added to the main window.
*/
@@ -1164,21 +1123,8 @@ void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const
{
- QList<QDockWidget*> ret;
- const QDockAreaLayoutInfo *info = d_func()->layout->layoutState.dockAreaLayout.info(dockwidget);
- if (info && info->tabbed && info->tabBar) {
- for(int i = 0; i < info->item_list.count(); ++i) {
- const QDockAreaLayoutItem &item = info->item_list.at(i);
- if (item.widgetItem) {
- if (QDockWidget *dock = qobject_cast<QDockWidget*>(item.widgetItem->widget())) {
- if (dock != dockwidget) {
- ret += dock;
- }
- }
- }
- }
- }
- return ret;
+ Q_D(const QMainWindow);
+ return d->layout ? d->layout->tabifiedDockWidgets(dockwidget) : QList<QDockWidget *>();
}
#endif // QT_CONFIG(tabbar)
@@ -1223,7 +1169,7 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
resized such that the yellowWidget is twice as big as the blueWidget
If some widgets are grouped in tabs, only one widget per group should be
- specified. Widgets not in the list might be changed to repect the constraints.
+ specified. Widgets not in the list might be changed to respect the constraints.
*/
void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation orientation)
@@ -1260,6 +1206,7 @@ QByteArray QMainWindow::saveState(int version) const
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_5_0);
stream << QMainWindowLayout::VersionMarker;
stream << version;
d_func()->layout->saveState(stream);
@@ -1288,6 +1235,7 @@ bool QMainWindow::restoreState(const QByteArray &state, int version)
return false;
QByteArray sd = state;
QDataStream stream(&sd, QIODevice::ReadOnly);
+ stream.setVersion(QDataStream::Qt_5_0);
int marker, v;
stream >> marker;
stream >> v;
@@ -1311,6 +1259,7 @@ bool QMainWindow::event(QEvent *event)
#if QT_CONFIG(toolbar)
case QEvent::ToolBarChange: {
+ Q_ASSERT(d->layout);
d->layout->toggleToolBarsVisible();
return true;
}
@@ -1319,6 +1268,7 @@ bool QMainWindow::event(QEvent *event)
#if QT_CONFIG(statustip)
case QEvent::StatusTip:
#if QT_CONFIG(statusbar)
+ Q_ASSERT(d->layout);
if (QStatusBar *sb = d->layout->statusBar())
sb->showMessage(static_cast<QStatusTipEvent*>(event)->tip());
else
@@ -1329,11 +1279,34 @@ bool QMainWindow::event(QEvent *event)
case QEvent::StyleChange:
#if QT_CONFIG(dockwidget)
+ Q_ASSERT(d->layout);
d->layout->layoutState.dockAreaLayout.styleChangedEvent();
#endif
if (!d->explicitIconSize)
setIconSize(QSize());
break;
+#if QT_CONFIG(draganddrop)
+ case QEvent::DragEnter:
+ case QEvent::Drop:
+ if (!d->layout->draggingWidget)
+ break;
+ event->accept();
+ return true;
+ case QEvent::DragMove: {
+ if (!d->layout->draggingWidget)
+ break;
+ auto dragMoveEvent = static_cast<QDragMoveEvent *>(event);
+ d->layout->hover(d->layout->draggingWidget,
+ mapToGlobal(dragMoveEvent->position()).toPoint());
+ event->accept();
+ return true;
+ }
+ case QEvent::DragLeave:
+ if (!d->layout->draggingWidget)
+ break;
+ d->layout->hover(d->layout->draggingWidget, pos() - QPoint(-1, -1));
+ return true;
+#endif
default:
break;
}
@@ -1349,40 +1322,42 @@ bool QMainWindow::event(QEvent *event)
Note that the Qt 5 implementation has several limitations compared to Qt 4:
\list
- \li Use in windows with OpenGL content is not supported. This includes QGLWidget and QOpenGLWidget.
+ \li Use in windows with OpenGL content is not supported. This includes QOpenGLWidget.
\li Using dockable or movable toolbars may result in painting errors and is not recommended
\endlist
\since 5.2
*/
-void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
+void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool enabled)
{
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
+ if (!isWindow())
+ return;
+
Q_D(QMainWindow);
- if (isWindow()) {
- d->useUnifiedToolBar = set;
- createWinId();
-
- QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- if (!nativeInterface)
- return; // Not Cocoa platform plugin.
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
- nativeInterface->nativeResourceFunctionForIntegration("setContentBorderEnabled");
- if (!function)
- return; // Not Cocoa platform plugin.
-
- typedef void (*SetContentBorderEnabledFunction)(QWindow *window, bool enable);
- (reinterpret_cast<SetContentBorderEnabledFunction>(function))(window()->windowHandle(), set);
- update();
- }
+ d->useUnifiedToolBar = enabled;
+
+ // The unified toolbar is drawn by the macOS style with a transparent background.
+ // To ensure a suitable surface format is used we need to first create backing
+ // QWindow so we have something to update the surface format on, and then let
+ // QWidget know about the translucency, which it will propagate to the surface.
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_TranslucentBackground, enabled);
+
+ d->create(); // Create first, before querying the platform window
+ using namespace QNativeInterface::Private;
+ if (auto *platformWindow = dynamic_cast<QCocoaWindow*>(window()->windowHandle()->handle()))
+ platformWindow->setContentBorderEnabled(enabled);
+
+ update();
#else
- Q_UNUSED(set)
+ Q_UNUSED(enabled);
#endif
}
bool QMainWindow::unifiedTitleAndToolBarOnMac() const
{
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
return d_func()->useUnifiedToolBar;
#endif
return false;
diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h
index c69451fa3e..a050093417 100644
--- a/src/widgets/widgets/qmainwindow.h
+++ b/src/widgets/widgets/qmainwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICMAINWINDOW_H
#define QDYNAMICMAINWINDOW_H
@@ -75,7 +39,8 @@ class Q_WIDGETS_EXPORT QMainWindow : public QWidget
#endif // QT_CONFIG(dockwidget)
Q_PROPERTY(DockOptions dockOptions READ dockOptions WRITE setDockOptions)
#if QT_CONFIG(toolbar)
- Q_PROPERTY(bool unifiedTitleAndToolBarOnMac READ unifiedTitleAndToolBarOnMac WRITE setUnifiedTitleAndToolBarOnMac)
+ Q_PROPERTY(bool unifiedTitleAndToolBarOnMac READ unifiedTitleAndToolBarOnMac
+ WRITE setUnifiedTitleAndToolBarOnMac)
#endif
public:
@@ -158,13 +123,10 @@ public:
bool unifiedTitleAndToolBarOnMac() const;
- Qt::ToolBarArea toolBarArea(
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
- const
-#endif
- QToolBar *toolbar) const;
+ Qt::ToolBarArea toolBarArea(const QToolBar *toolbar) const;
bool toolBarBreak(QToolBar *toolbar) const;
-#endif
+#endif // QT_CONFIG(toolbar)
+
#if QT_CONFIG(dockwidget)
void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget);
void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget,
@@ -216,6 +178,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QMainWindow)
Q_DISABLE_COPY(QMainWindow)
+ friend class QDockWidgetGroupWindow;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QMainWindow::DockOptions)
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 30562d8270..85c58fd70f 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmainwindowlayout_p.h"
@@ -60,6 +24,10 @@
#endif
#include <qapplication.h>
+#if QT_CONFIG(draganddrop)
+#include <qdrag.h>
+#endif
+#include <qmimedata.h>
#if QT_CONFIG(statusbar)
#include <qstatusbar.h>
#endif
@@ -82,8 +50,12 @@
#include <private/qlayoutengine_p.h>
#include <private/qwidgetresizehandler_p.h>
+#include <QScopedValueRollback>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
/******************************************************************************
@@ -100,14 +72,14 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QStri
<< "pos: " << item.pos << " size:" << item.size
<< " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
<< " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
- indent += QLatin1String(" ");
+ indent += " "_L1;
if (item.widgetItem != nullptr) {
qout << indent << "widget: "
<< item.widgetItem->widget()->metaObject()->className()
<< " \"" << item.widgetItem->widget()->windowTitle() << "\"\n";
} else if (item.subinfo != nullptr) {
qout << indent << "subinfo:\n";
- dumpLayout(qout, *item.subinfo, indent + QLatin1String(" "));
+ dumpLayout(qout, *item.subinfo, indent + " "_L1);
} else if (item.placeHolderItem != nullptr) {
QRect r = item.placeHolderItem->topLevelRect;
qout << indent << "placeHolder: "
@@ -138,11 +110,11 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QSt
#endif
<< '\n';
- indent += QLatin1String(" ");
+ indent += " "_L1;
- for (int i = 0; i < layout.item_list.count(); ++i) {
+ for (int i = 0; i < layout.item_list.size(); ++i) {
qout << indent << "Item: " << i << '\n';
- dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String(" "));
+ dumpLayout(qout, layout.item_list.at(i), indent + " "_L1);
}
}
@@ -155,13 +127,13 @@ static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout)
<< layout.rect.height() << '\n';
qout << "TopDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::TopDock], QLatin1String(" "));
+ dumpLayout(qout, layout.docks[QInternal::TopDock], " "_L1);
qout << "LeftDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::LeftDock], QLatin1String(" "));
+ dumpLayout(qout, layout.docks[QInternal::LeftDock], " "_L1);
qout << "RightDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::RightDock], QLatin1String(" "));
+ dumpLayout(qout, layout.docks[QInternal::RightDock], " "_L1);
qout << "BottomDockArea:\n";
- dumpLayout(qout, layout.docks[QInternal::BottomDock], QLatin1String(" "));
+ dumpLayout(qout, layout.docks[QInternal::BottomDock], " "_L1);
}
QDebug operator<<(QDebug debug, const QDockAreaLayout &layout)
@@ -179,18 +151,57 @@ QDebug operator<<(QDebug debug, const QMainWindowLayout *layout)
return debug;
}
+// Use this to dump item lists of all populated main window docks.
+// Use DUMP macro inside QMainWindowLayout
+#if 0
+static void dumpItemLists(const QMainWindowLayout *layout, const char *function, const char *comment)
+{
+ for (int i = 0; i < QInternal::DockCount; ++i) {
+ const auto &list = layout->layoutState.dockAreaLayout.docks[i].item_list;
+ if (list.isEmpty())
+ continue;
+ qDebug() << function << comment << "Dock" << i << list;
+ }
+}
+#define DUMP(comment) dumpItemLists(this, __FUNCTION__, comment)
+#endif // 0
+
#endif // QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG)
-/******************************************************************************
- ** QDockWidgetGroupWindow
- */
-// QDockWidgetGroupWindow is the floating window containing several QDockWidgets floating together.
-// (QMainWindow::GroupedDragging feature)
-// QDockWidgetGroupLayout is the layout of that window and use a QDockAreaLayoutInfo to layout
-// the QDockWidgets inside it.
-// If there is only one QDockWidgets, or all QDockWidgets are tabbed together, it is equivalent
-// of a floating QDockWidget (the title of the QDockWidget is the title of the window). But if there
-// are nested QDockWidget, an additional title bar is there.
+
+/*!
+ \internal
+ QDockWidgetGroupWindow is a floating window, containing several QDockWidgets floating together.
+ This requires QMainWindow::GroupedDragging to be enabled.
+ QDockWidgets floating jointly in a QDockWidgetGroupWindow are considered to be docked.
+ Their \c isFloating property is \c false.
+ QDockWidget children of a QDockWidgetGroupWindow are either:
+ \list
+ \li tabbed (as long as Qt is compiled with the \c tabbar feature), or
+ \li arranged next to each other, equivalent to the default on a main window dock.
+ \endlist
+
+ QDockWidgetGroupWindow uses QDockWidgetGroupLayout to lay out its QDockWidget children.
+ It stores layout information in a QDockAreaLayoutInfo, including temporary spacer items
+ and rubber bands.
+
+ If its QDockWidget children are tabbed, the QDockWidgetGroupWindow shows the active QDockWidget's
+ title as its own window title.
+
+ QDockWidgetGroupWindow is designed to hold more than one QDockWidget.
+ A QDockWidgetGroupWindow with only one QDockWidget child may occur only temporarily
+ \list
+ \li in its construction phase, or
+ \li during a hover: While QDockWidget A is hovered over B, B is converted into a QDockWidgetGroupWindow.
+ \endlist
+
+ A QDockWidgetGroupWindow with only one QDockWidget child must never get focus, be dragged or dropped.
+ To enforce this restriction, QDockWidgetGrouWindow will remove itself after its second QDockWidget
+ child has been removed. It will make its last QDockWidget child a single, floating QDockWidget.
+ Eventually, the empty QDockWidgetGroupWindow will call deleteLater() on itself.
+*/
+
+
#if QT_CONFIG(dockwidget)
class QDockWidgetGroupLayout : public QLayout,
public QMainWindowLayoutSeparatorHelper<QDockWidgetGroupLayout>
@@ -200,7 +211,6 @@ public:
QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) {
setSizeConstraint(QLayout::SetMinAndMaxSize);
resizer = new QWidgetResizeHandler(parent);
- resizer->setMovingEnabled(false);
}
~QDockWidgetGroupLayout() {
layoutState.deleteAllLayoutItems();
@@ -259,7 +269,7 @@ public:
li->apply(false);
if (savedState.rect.isValid())
savedState.rect = li->rect;
- resizer->setActive(QWidgetResizeHandler::Resize, !nativeWindowDeco());
+ resizer->setEnabled(!nativeWindowDeco());
}
QDockAreaLayoutInfo *dockAreaLayoutInfo() { return &layoutState; }
@@ -295,7 +305,6 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
#if QT_CONFIG(tabbar)
// Forward the close to the QDockWidget just as if its close button was pressed
if (QDockWidget *dw = activeTabbedDockWidget()) {
- e->ignore();
dw->close();
adjustFlags();
}
@@ -329,6 +338,7 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
case QEvent::Resize:
updateCurrentGapRect();
emit resized();
+ break;
default:
break;
}
@@ -342,7 +352,7 @@ void QDockWidgetGroupWindow::paintEvent(QPaintEvent *)
if (!nativeDeco) {
QStyleOptionFrame framOpt;
- framOpt.init(this);
+ framOpt.initFrom(this);
QStylePainter p(this);
p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt);
}
@@ -402,7 +412,7 @@ QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget() const
}
}
if (!dw) {
- for (int i = 0; !dw && i < info->item_list.count(); ++i) {
+ for (int i = 0; !dw && i < info->item_list.size(); ++i) {
const QDockAreaLayoutItem &item = info->item_list.at(i);
if (item.skip())
continue;
@@ -421,22 +431,24 @@ QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget() const
*/
void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
{
- if (!layoutInfo()->isEmpty()) {
+ const QDockAreaLayoutInfo *info = layoutInfo();
+ if (!info->isEmpty()) {
show(); // It might have been hidden,
return;
}
// There might still be placeholders
- if (!layoutInfo()->item_list.isEmpty()) {
+ if (!info->item_list.isEmpty()) {
hide();
return;
}
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
- const auto dockWidgets = findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly);
- for (QDockWidget *dw : dockWidgets) {
- bool wasFloating = dw->isFloating();
- bool wasHidden = dw->isHidden();
+ const auto dockWidgetsList = dockWidgets();
+ for (QDockWidget *dw : dockWidgetsList) {
+ const bool wasFloating = dw->isFloating();
+ const bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
+ qCDebug(lcQpaDockWidgets) << "Reparented:" << dw << "to" << parentWidget() << "by" << this;
if (wasFloating) {
dw->setFloating(true);
} else {
@@ -445,20 +457,35 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
qt_mainwindow_layout(static_cast<QMainWindow *>(parentWidget()));
Qt::DockWidgetArea area = ml->dockWidgetArea(this);
if (area == Qt::NoDockWidgetArea)
- area = Qt::LeftDockWidgetArea;
+ area = Qt::LeftDockWidgetArea; // FIXME: DockWidget doesn't save original docking area
static_cast<QMainWindow *>(parentWidget())->addDockWidget(area, dw);
+ qCDebug(lcQpaDockWidgets) << "Redocked to Mainwindow:" << area << dw << "by" << this;
}
if (!wasHidden)
dw->show();
}
-#if QT_CONFIG(tabbar)
- const auto tabBars = findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly);
- for (QTabBar *tb : tabBars)
- tb->setParent(parentWidget());
-#endif
deleteLater();
}
+/*!
+ \internal
+ \return \c true if the group window has at least one visible QDockWidget child,
+ otherwise false.
+ */
+bool QDockWidgetGroupWindow::hasVisibleDockWidgets() const
+{
+ const auto &children = findChildren<QDockWidget *>(Qt::FindChildrenRecursively);
+ for (auto child : children) {
+ // WA_WState_Visible is set on the dock widget, associated to the active tab
+ // and unset on all others.
+ // WA_WState_Hidden is set if the dock widgets have been explicitly hidden.
+ // This is the relevant information to check (equivalent to !child->isHidden()).
+ if (!child->testAttribute(Qt::WA_WState_Hidden))
+ return true;
+ }
+ return false;
+}
+
/*! \internal
Sets the flags of this window in accordance to the capabilities of the dock widgets
*/
@@ -507,7 +534,7 @@ void QDockWidgetGroupWindow::adjustFlags()
m_removedFrameSize = QSize();
}
- show(); // setWindowFlags hides the window
+ setVisible(hasVisibleDockWidgets());
}
QWidget *titleBarOf = top ? top : parentWidget();
@@ -568,8 +595,12 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP
auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode);
Q_ASSERT(!newGapPos.isEmpty());
- if (newGapPos == currentGapPos)
- return false; // gap is already there
+
+ // Do not insert a new gap item, if the current position already is a gap,
+ // or if the group window contains one
+ if (newGapPos == currentGapPos || newState.hasGapItem(newGapPos))
+ return false;
+
currentGapPos = newGapPos;
newState.insertGap(currentGapPos, widgetItem);
newState.fitItems();
@@ -616,6 +647,108 @@ void QDockWidgetGroupWindow::apply()
layoutInfo()->apply(false);
}
+void QDockWidgetGroupWindow::childEvent(QChildEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::ChildRemoved:
+ if (auto *dockWidget = qobject_cast<QDockWidget *>(event->child()))
+ dockWidget->removeEventFilter(this);
+ destroyIfSingleItemLeft();
+ break;
+ case QEvent::ChildAdded:
+ if (auto *dockWidget = qobject_cast<QDockWidget *>(event->child()))
+ dockWidget->installEventFilter(this);
+ break;
+ default:
+ break;
+ }
+}
+
+bool QDockWidgetGroupWindow::eventFilter(QObject *obj, QEvent *event)
+{
+ auto *dockWidget = qobject_cast<QDockWidget *>(obj);
+ if (!dockWidget)
+ return QWidget::eventFilter(obj, event);
+
+ switch (event->type()) {
+ case QEvent::Close:
+ // We don't want closed dock widgets in a floating tab
+ // => dock it to the main dock, before closing;
+ reparent(dockWidget);
+ dockWidget->setFloating(false);
+ break;
+
+ case QEvent::Hide:
+ // if the dock widget is not an active tab, it is hidden anyway.
+ // if it is the active tab, hide the whole group.
+ if (dockWidget->isVisible())
+ hide();
+ break;
+
+ default:
+ break;
+ }
+ return QWidget::eventFilter(obj, event);
+}
+
+void QDockWidgetGroupWindow::destroyIfSingleItemLeft()
+{
+ const auto &dockWidgets = this->dockWidgets();
+
+ // Handle only the last dock
+ if (dockWidgets.count() != 1)
+ return;
+
+ auto *lastDockWidget = dockWidgets.at(0);
+
+ // If the last remaining dock widget is not in the group window's item_list,
+ // a group window is being docked on a main window docking area.
+ // => don't interfere
+ if (layoutInfo()->indexOf(lastDockWidget).isEmpty())
+ return;
+
+ auto *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
+
+ // Unplug the last remaining dock widget and hide the group window, to avoid flickering
+ mwLayout->unplug(lastDockWidget, QDockWidgetPrivate::DragScope::Widget);
+ lastDockWidget->setGeometry(geometry());
+ hide();
+
+ // Get the layout info for the main window dock, where dock widgets need to go
+ QDockAreaLayoutInfo &parentInfo = mwLayout->layoutState.dockAreaLayout.docks[layoutInfo()->dockPos];
+
+ // Re-parent last dock widget
+ reparent(lastDockWidget);
+
+ // the group window could still have placeholder items => clear everything
+ layoutInfo()->item_list.clear();
+
+ // remove the group window and the dock's item_list pointing to it.
+ parentInfo.remove(this);
+ destroyOrHideIfEmpty();
+}
+
+void QDockWidgetGroupWindow::reparent(QDockWidget *dockWidget)
+{
+ // reparent a dockWidget to the main window
+ // - remove it from the floating dock's layout info
+ // - insert it to the main dock's layout info
+ // Finally, set draggingDock to nullptr, since the drag is finished.
+ auto *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
+ Q_ASSERT(mainWindow);
+ QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
+ Q_ASSERT(mwLayout);
+ QDockAreaLayoutInfo &parentInfo = mwLayout->layoutState.dockAreaLayout.docks[layoutInfo()->dockPos];
+ dockWidget->removeEventFilter(this);
+ parentInfo.add(dockWidget);
+ layoutInfo()->remove(dockWidget);
+ const bool wasFloating = dockWidget->isFloating();
+ const bool wasVisible = dockWidget->isVisible();
+ dockWidget->setParent(mainWindow);
+ dockWidget->setFloating(wasFloating);
+ dockWidget->setVisible(wasVisible);
+}
#endif
/******************************************************************************
@@ -647,7 +780,7 @@ QSize QMainWindowLayoutState::sizeHint() const
#if QT_CONFIG(dockwidget)
result = dockAreaLayout.sizeHint();
#else
- if (centralWidgetItem != 0)
+ if (centralWidgetItem)
result = centralWidgetItem->sizeHint();
#endif
@@ -665,7 +798,7 @@ QSize QMainWindowLayoutState::minimumSize() const
#if QT_CONFIG(dockwidget)
result = dockAreaLayout.minimumSize();
#else
- if (centralWidgetItem != 0)
+ if (centralWidgetItem)
result = centralWidgetItem->minimumSize();
#endif
@@ -676,6 +809,31 @@ QSize QMainWindowLayoutState::minimumSize() const
return result;
}
+/*!
+ \internal
+
+ Returns whether the layout fits into the main window.
+*/
+bool QMainWindowLayoutState::fits() const
+{
+ Q_ASSERT(mainWindow);
+
+ QSize size;
+
+#if QT_CONFIG(dockwidget)
+ size = dockAreaLayout.minimumStableSize();
+#endif
+
+#if QT_CONFIG(toolbar)
+ size.rwidth() += toolBarAreaLayout.docks[QInternal::LeftDock].rect.width();
+ size.rwidth() += toolBarAreaLayout.docks[QInternal::RightDock].rect.width();
+ size.rheight() += toolBarAreaLayout.docks[QInternal::TopDock].rect.height();
+ size.rheight() += toolBarAreaLayout.docks[QInternal::BottomDock].rect.height();
+#endif
+
+ return size.width() <= mainWindow->width() && size.height() <= mainWindow->height();
+}
+
void QMainWindowLayoutState::apply(bool animated)
{
#if QT_CONFIG(toolbar)
@@ -686,9 +844,9 @@ void QMainWindowLayoutState::apply(bool animated)
// dumpLayout(dockAreaLayout, QString());
dockAreaLayout.apply(animated);
#else
- if (centralWidgetItem != 0) {
+ if (centralWidgetItem) {
QMainWindowLayout *layout = qt_mainwindow_layout(mainWindow);
- Q_ASSERT(layout != 0);
+ Q_ASSERT(layout);
layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
}
#endif
@@ -745,7 +903,7 @@ QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const
if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
return ret;
#else
- if (centralWidgetItem != 0 && (*x)++ == index)
+ if (centralWidgetItem && (*x)++ == index)
return centralWidgetItem;
#endif
@@ -763,9 +921,9 @@ QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x)
if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
return ret;
#else
- if (centralWidgetItem != 0 && (*x)++ == index) {
+ if (centralWidgetItem && (*x)++ == index) {
QLayoutItem *ret = centralWidgetItem;
- centralWidgetItem = 0;
+ centralWidgetItem = nullptr;
return ret;
}
#endif
@@ -808,7 +966,7 @@ bool QMainWindowLayoutState::contains(QWidget *widget) const
if (!dockAreaLayout.indexOf(widget).isEmpty())
return true;
#else
- if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget)
+ if (centralWidgetItem && centralWidgetItem->widget() == widget)
return true;
#endif
@@ -857,7 +1015,7 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
#if QT_CONFIG(toolbar)
// is it a toolbar?
- if (qobject_cast<QToolBar*>(widget) != 0) {
+ if (qobject_cast<QToolBar*>(widget) != nullptr) {
result = toolBarAreaLayout.gapIndex(pos);
if (!result.isEmpty())
result.prepend(0);
@@ -867,7 +1025,7 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
#if QT_CONFIG(dockwidget)
// is it a dock widget?
- if (qobject_cast<QDockWidget *>(widget) != 0
+ if (qobject_cast<QDockWidget *>(widget) != nullptr
|| qobject_cast<QDockWidgetGroupWindow *>(widget)) {
bool disallowTabs = false;
#if QT_CONFIG(tabbar)
@@ -895,7 +1053,7 @@ bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item
#if QT_CONFIG(toolbar)
if (i == 0) {
- Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
+ Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != nullptr);
return toolBarAreaLayout.insertGap(path.mid(1), item);
}
#endif
@@ -1057,7 +1215,7 @@ void QMainWindowLayoutState::saveState(QDataStream &stream) const
dockAreaLayout.saveState(stream);
#if QT_CONFIG(tabbar)
const QList<QDockWidgetGroupWindow *> floatingTabs =
- mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+ mainWindow->findChildren<QDockWidgetGroupWindow *>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *floating : floatingTabs) {
if (floating->layoutInfo()->isEmpty())
@@ -1172,10 +1330,12 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
}
QDataStream ds(copy);
+ ds.setVersion(_stream.version());
if (!checkFormat(ds))
return false;
QDataStream stream(copy);
+ stream.setVersion(_stream.version());
while (!stream.atEnd()) {
uchar marker;
@@ -1201,7 +1361,7 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
if (info == nullptr) {
continue;
}
- info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
+ info->add(w);
}
}
}
@@ -1211,8 +1371,9 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
{
auto dockWidgets = allMyDockWidgets(mainWindow);
QDockWidgetGroupWindow* floatingTab = qt_mainwindow_layout(mainWindow)->createTabbedDockWindow();
- *floatingTab->layoutInfo() = QDockAreaLayoutInfo(&dockAreaLayout.sep, QInternal::LeftDock,
- Qt::Horizontal, QTabBar::RoundedSouth, mainWindow);
+ *floatingTab->layoutInfo() = QDockAreaLayoutInfo(
+ &dockAreaLayout.sep, QInternal::LeftDock, // FIXME: DockWidget doesn't save original docking area
+ Qt::Horizontal, QTabBar::RoundedSouth, mainWindow);
QRect geometry;
stream >> geometry;
QDockAreaLayoutInfo *info = floatingTab->layoutInfo();
@@ -1270,17 +1431,18 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
#if QT_CONFIG(toolbar)
-static inline void validateToolBarArea(Qt::ToolBarArea &area)
+static constexpr Qt::ToolBarArea validateToolBarArea(Qt::ToolBarArea area)
{
switch (area) {
case Qt::LeftToolBarArea:
case Qt::RightToolBarArea:
case Qt::TopToolBarArea:
case Qt::BottomToolBarArea:
- break;
+ return area;
default:
- area = Qt::TopToolBarArea;
+ break;
}
+ return Qt::TopToolBarArea;
}
static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
@@ -1316,7 +1478,7 @@ static inline Qt::ToolBarArea toToolBarArea(int pos)
void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
{
- validateToolBarArea(area);
+ area = validateToolBarArea(area);
layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
if (savedState.isValid())
@@ -1370,7 +1532,7 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
QToolBar *toolbar,
bool)
{
- validateToolBarArea(area);
+ area = validateToolBarArea(area);
// let's add the toolbar to the layout
addChildWidget(toolbar);
QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
@@ -1465,23 +1627,46 @@ static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
return QInternal::DockCount;
}
-static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
+inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
{
- switch (pos) {
- case QInternal::LeftDock : return Qt::LeftDockWidgetArea;
- case QInternal::RightDock : return Qt::RightDockWidgetArea;
- case QInternal::TopDock : return Qt::TopDockWidgetArea;
- case QInternal::BottomDock : return Qt::BottomDockWidgetArea;
- default:
- break;
- }
-
- return Qt::NoDockWidgetArea;
+ return QDockWidgetPrivate::toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
}
-inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
+// Checks if QDockWidgetGroupWindow or QDockWidget can be plugged the area indicated by path.
+// Returns false if called with invalid widget type or if compiled without dockwidget support.
+static bool isAreaAllowed(QWidget *widget, const QList<int> &path)
{
- return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
+ Q_ASSERT_X((path.size() > 1), "isAreaAllowed", "invalid path size");
+ const Qt::DockWidgetArea area = toDockWidgetArea(path[1]);
+
+ // Read permissions directly from a single dock widget
+ if (QDockWidget *dw = qobject_cast<QDockWidget *>(widget)) {
+ const bool allowed = dw->isAreaAllowed(area);
+ if (!allowed)
+ qCDebug(lcQpaDockWidgets) << "No permission for single DockWidget" << widget << "to dock on" << area;
+ return allowed;
+ }
+
+ // Read permissions from a DockWidgetGroupWindow depending on its DockWidget children
+ if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+ const QList<QDockWidget *> children = dwgw->findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly);
+
+ if (children.size() == 1) {
+ // Group window has a single child => read its permissions
+ const bool allowed = children.at(0)->isAreaAllowed(area);
+ if (!allowed)
+ qCDebug(lcQpaDockWidgets) << "No permission for DockWidgetGroupWindow" << widget << "to dock on" << area;
+ return allowed;
+ } else {
+ // Group window has more than one or no children => dock it anywhere
+ qCDebug(lcQpaDockWidgets) << "DockWidgetGroupWindow" << widget << "has" << children.size() << "children:";
+ qCDebug(lcQpaDockWidgets) << children;
+ qCDebug(lcQpaDockWidgets) << "DockWidgetGroupWindow" << widget << "can dock at" << area << "and anywhere else.";
+ return true;
+ }
+ }
+ qCDebug(lcQpaDockWidgets) << "Docking requested for invalid widget type (coding error)." << widget << area;
+ return false;
}
void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
@@ -1499,6 +1684,25 @@ Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
return layoutState.dockAreaLayout.corners[corner];
}
+// Returns the rectangle of a dockWidgetArea
+// if max is true, the maximum possible rectangle for dropping is returned
+// the current visible rectangle otherwise
+QRect QMainWindowLayout::dockWidgetAreaRect(const Qt::DockWidgetArea area, DockWidgetAreaSize size) const
+{
+ const QInternal::DockPosition dockPosition = toDockPos(area);
+
+ // Called with invalid dock widget area
+ if (dockPosition == QInternal::DockCount) {
+ qCDebug(lcQpaDockWidgets) << "QMainWindowLayout::dockWidgetAreaRect called with" << area;
+ return QRect();
+ }
+
+ const QDockAreaLayout dl = layoutState.dockAreaLayout;
+
+ // Return maximum or visible rectangle
+ return (size == Maximum) ? dl.gapRect(dockPosition) : dl.docks[dockPosition].rect;
+}
+
void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
QDockWidget *dockwidget,
Qt::Orientation orientation)
@@ -1528,6 +1732,7 @@ bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
#if QT_CONFIG(tabbar)
void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
{
+ applyRestoredState();
addChildWidget(second);
layoutState.dockAreaLayout.tabifyDockWidget(first, second);
emit second->dockLocationChanged(dockWidgetArea(first));
@@ -1547,9 +1752,9 @@ void QMainWindowLayout::setDocumentMode(bool enabled)
_documentMode = enabled;
// Update the document mode for all tab bars
- for (QTabBar *bar : qAsConst(usedTabBars))
+ for (QTabBar *bar : std::as_const(usedTabBars))
bar->setDocumentMode(_documentMode);
- for (QTabBar *bar : qAsConst(unusedTabBars))
+ for (QTabBar *bar : std::as_const(unusedTabBars))
bar->setDocumentMode(_documentMode);
}
@@ -1581,7 +1786,11 @@ void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
{
- return tabPositions[toDockPos(area)];
+ const QInternal::DockPosition dockPos = toDockPos(area);
+ if (dockPos < QInternal::DockCount)
+ return tabPositions[dockPos];
+ qWarning("QMainWindowLayout::tabPosition called with out-of-bounds value '%d'", int(area));
+ return QTabWidget::North;
}
void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
@@ -1606,19 +1815,7 @@ void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::Ta
updateTabBarShapes();
}
-static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
-{
- const bool rounded = (shape == QTabWidget::Rounded);
- if (position == QTabWidget::North)
- return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
- if (position == QTabWidget::South)
- return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
- if (position == QTabWidget::East)
- return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
- if (position == QTabWidget::West)
- return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
- return QTabBar::RoundedNorth;
-}
+QTabBar::Shape _q_tb_tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position);
#endif // QT_CONFIG(tabwidget)
void QMainWindowLayout::updateTabBarShapes()
@@ -1644,7 +1841,7 @@ void QMainWindowLayout::updateTabBarShapes()
for (int i = 0; i < QInternal::DockCount; ++i) {
#if QT_CONFIG(tabwidget)
QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
- QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos);
+ QTabBar::Shape shape = _q_tb_tabBarShapeFrom(_tabShape, pos);
#else
QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
#endif
@@ -1657,6 +1854,7 @@ void QMainWindowLayout::splitDockWidget(QDockWidget *after,
QDockWidget *dockwidget,
Qt::Orientation orientation)
{
+ applyRestoredState();
addChildWidget(dockwidget);
layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
emit dockwidget->dockLocationChanged(dockWidgetArea(after));
@@ -1681,10 +1879,15 @@ void QMainWindowLayout::keepSize(QDockWidget *w)
// Handle custom tooltip, and allow to drag tabs away.
class QMainWindowTabBar : public QTabBar
{
+ Q_OBJECT
QMainWindow *mainWindow;
QPointer<QDockWidget> draggingDock; // Currently dragging (detached) dock widget
public:
QMainWindowTabBar(QMainWindow *parent);
+ ~QMainWindowTabBar();
+ QDockWidget *dockAt(int index) const;
+ QList<QDockWidget *> dockWidgets() const;
+ bool contains(const QDockWidget *dockWidget) const;
protected:
bool event(QEvent *e) override;
void mouseReleaseEvent(QMouseEvent*) override;
@@ -1692,12 +1895,65 @@ protected:
};
+QMainWindowTabBar *QMainWindowLayout::findTabBar(const QDockWidget *dockWidget) const
+{
+ for (auto *bar : usedTabBars) {
+ Q_ASSERT(qobject_cast<QMainWindowTabBar *>(bar));
+ auto *tabBar = static_cast<QMainWindowTabBar *>(bar);
+ if (tabBar->contains(dockWidget))
+ return tabBar;
+ }
+ return nullptr;
+}
+
QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent)
: QTabBar(parent), mainWindow(parent)
{
setExpanding(false);
}
+QList<QDockWidget *> QMainWindowTabBar::dockWidgets() const
+{
+ QList<QDockWidget *> docks;
+ for (int i = 0; i < count(); ++i) {
+ if (QDockWidget *dock = dockAt(i))
+ docks << dock;
+ }
+ return docks;
+}
+
+bool QMainWindowTabBar::contains(const QDockWidget *dockWidget) const
+{
+ for (int i = 0; i < count(); ++i) {
+ if (dockAt(i) == dockWidget)
+ return true;
+ }
+ return false;
+}
+
+// When a dock widget is removed from a floating tab,
+// Events need to be processed for the tab bar to realize that the dock widget is gone.
+// In this case count() counts the dock widget in transition and accesses dockAt
+// with an out-of-bounds index.
+// => return nullptr in contrast to other xxxxxAt() functions
+QDockWidget *QMainWindowTabBar::dockAt(int index) const
+{
+ QMainWindowTabBar *that = const_cast<QMainWindowTabBar *>(this);
+ QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow);
+ QDockAreaLayoutInfo *info = mlayout->dockInfo(that);
+ if (!info)
+ return nullptr;
+
+ const int itemIndex = info->tabIndexToListIndex(index);
+ if (itemIndex >= 0) {
+ Q_ASSERT(itemIndex < info->item_list.count());
+ const QDockAreaLayoutItem &item = info->item_list.at(itemIndex);
+ return item.widgetItem ? qobject_cast<QDockWidget *>(item.widgetItem->widget()) : nullptr;
+ }
+
+ return nullptr;
+}
+
void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
{
// The QTabBar handles the moving (reordering) of tabs.
@@ -1710,14 +1966,9 @@ void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
int offset = QApplication::startDragDistance() + 1;
offset *= 3;
QRect r = rect().adjusted(-offset, -offset, offset, offset);
- if (d->dragInProgress && !r.contains(e->pos()) && d->validIndex(d->pressedIndex)) {
- QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow);
- QDockAreaLayoutInfo *info = mlayout->dockInfo(this);
- Q_ASSERT(info);
- int idx = info->tabIndexToListIndex(d->pressedIndex);
- const QDockAreaLayoutItem &item = info->item_list.at(idx);
- if (item.widgetItem
- && (draggingDock = qobject_cast<QDockWidget *>(item.widgetItem->widget()))) {
+ if (d->dragInProgress && !r.contains(e->position().toPoint()) && d->validIndex(d->pressedIndex)) {
+ draggingDock = dockAt(d->pressedIndex);
+ if (draggingDock) {
// We should drag this QDockWidget away by unpluging it.
// First cancel the QTabBar's internal move
d->moveTabFinished(d->pressedIndex);
@@ -1730,7 +1981,7 @@ void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
QDockWidgetLayout *dwlayout = static_cast<QDockWidgetLayout *>(draggingDock->layout());
dockPriv->initDrag(dwlayout->titleArea().center(), true);
- dockPriv->startDrag(false);
+ dockPriv->startDrag(QDockWidgetPrivate::DragScope::Widget);
if (dockPriv->state)
dockPriv->state->ctrlDrag = e->modifiers() & Qt::ControlModifier;
}
@@ -1740,7 +1991,7 @@ void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
if (draggingDock) {
QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
if (dockPriv->state && dockPriv->state->dragging) {
- QPoint pos = e->globalPos() - dockPriv->state->pressPos;
+ QPoint pos = e->globalPosition().toPoint() - dockPriv->state->pressPos;
draggingDock->move(pos);
// move will call QMainWindowLayout::hover
}
@@ -1748,13 +1999,28 @@ void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e)
QTabBar::mouseMoveEvent(e);
}
+QMainWindowTabBar::~QMainWindowTabBar()
+{
+ if (!mainWindow || mainWindow == parentWidget())
+ return;
+
+ // tab bar is not parented to the main window
+ // => can only be a dock widget group window
+ // => remove itself from used and unused tab bar containers
+ auto *mwLayout = qt_mainwindow_layout(mainWindow);
+ if (!mwLayout)
+ return;
+ mwLayout->unusedTabBars.removeOne(this);
+ mwLayout->usedTabBars.remove(this);
+}
+
void QMainWindowTabBar::mouseReleaseEvent(QMouseEvent *e)
{
if (draggingDock && e->button() == Qt::LeftButton) {
QDockWidgetPrivate *dockPriv = static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(draggingDock));
- if (dockPriv->state && dockPriv->state->dragging) {
- dockPriv->endDrag();
- }
+ if (dockPriv->state && dockPriv->state->dragging)
+ dockPriv->endDrag(QDockWidgetPrivate::EndDragMode::LocationChange);
+
draggingDock = nullptr;
}
QTabBar::mouseReleaseEvent(e);
@@ -1778,8 +2044,39 @@ bool QMainWindowTabBar::event(QEvent *e)
return true;
}
+QList<QDockWidget *> QMainWindowLayout::tabifiedDockWidgets(const QDockWidget *dockWidget) const
+{
+ const auto *bar = findTabBar(dockWidget);
+ if (!bar)
+ return {};
+
+ QList<QDockWidget *> buddies = bar->dockWidgets();
+ // Return only other dock widgets associated with dockWidget in a tab bar.
+ // If dockWidget is alone in a tab bar, return an empty list.
+ buddies.removeOne(dockWidget);
+ return buddies;
+}
+
+bool QMainWindowLayout::isDockWidgetTabbed(const QDockWidget *dockWidget) const
+{
+ // A single dock widget in a tab bar is not considered to be tabbed.
+ // This is to make sure, we don't drag an empty QDockWidgetGroupWindow around.
+ // => only consider tab bars with two or more tabs.
+ const auto *bar = findTabBar(dockWidget);
+ return bar && bar->count() > 1;
+}
+
QTabBar *QMainWindowLayout::getTabBar()
{
+ if (!usedTabBars.isEmpty() && !isInRestoreState) {
+ /*
+ If dock widgets have been removed and added while the main window was
+ hidden, then the layout hasn't been activated yet, and tab bars from empty
+ docking areas haven't been put in the cache yet.
+ */
+ activate();
+ }
+
QTabBar *result = nullptr;
if (!unusedTabBars.isEmpty()) {
result = unusedTabBars.takeLast();
@@ -1807,7 +2104,7 @@ QWidget *QMainWindowLayout::getSeparatorWidget()
result = new QWidget(parentWidget());
result->setAttribute(Qt::WA_MouseNoMask, true);
result->setAutoFillBackground(false);
- result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter"));
+ result->setObjectName("qt_qmainwindow_extended_splitter"_L1);
}
usedSeparatorWidgets.insert(result);
return result;
@@ -1823,7 +2120,7 @@ QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget)
if (info)
return info;
const auto groups =
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups) {
info = dwgw->layoutInfo()->info(widget);
if (info)
@@ -1883,8 +2180,10 @@ void QMainWindowLayout::raise(QDockWidget *widget)
int QMainWindowLayout::count() const
{
- qWarning("QMainWindowLayout::count: ?");
- return 0; //#################################################
+ int result = 0;
+ while (itemAt(result))
+ ++result;
+ return result;
}
QLayoutItem *QMainWindowLayout::itemAt(int index) const
@@ -1941,9 +2240,37 @@ QLayoutItem *QMainWindowLayout::takeAt(int index)
return nullptr;
}
+
+/*!
+ \internal
+
+ restoredState stores what we earlier read from storage, but it couldn't
+ be applied as the mainwindow wasn't large enough (yet) to fit the state.
+ Usually, the restored state would be applied lazily in setGeometry below.
+ However, if the mainwindow's layout is modified (e.g. by a call to tabify or
+ splitDockWidgets), then we have to forget the restored state as it might contain
+ dangling pointers (QDockWidgetLayoutItem has a copy constructor that copies the
+ layout item pointer, and splitting or tabify might have to delete some of those
+ layout structures).
+
+ Functions that might result in the QMainWindowLayoutState storing dangling pointers
+ have to call this function first, so that the restoredState becomes the actual state
+ first, and is forgotten afterwards.
+*/
+void QMainWindowLayout::applyRestoredState()
+{
+ if (restoredState) {
+ layoutState = *restoredState;
+ restoredState.reset();
+ discardRestoredStateTimer.stop();
+ }
+}
+
void QMainWindowLayout::setGeometry(const QRect &_r)
{
- if (savedState.isValid())
+ // Check if the state is valid, and avoid replacing it again if it is currently used
+ // in applyState
+ if (savedState.isValid() || (restoredState && isInApplyState))
return;
QRect r = _r;
@@ -1960,11 +2287,47 @@ void QMainWindowLayout::setGeometry(const QRect &_r)
r.setBottom(sbr.top() - 1);
}
+ if (restoredState) {
+ /*
+ The main window was hidden and was going to be maximized or full-screened when
+ the state was restored. The state might have been for a larger window size than
+ the current size (in _r), and the window might still be in the process of being
+ shown and transitioning to the final size (there's no reliable way of knowing
+ this across different platforms). Try again with the restored state.
+ */
+ layoutState = *restoredState;
+ if (restoredState->fits()) {
+ restoredState.reset();
+ discardRestoredStateTimer.stop();
+ } else {
+ /*
+ Try again in the next setGeometry call, but discard the restored state
+ after 150ms without any further tries. That's a reasonably short amount of
+ time during which we can expect the windowing system to either have completed
+ showing the window, or resized the window once more (which then restarts the
+ timer in timerEvent).
+ If the windowing system is done, then the user won't have had a chance to
+ change the layout interactively AND trigger another resize.
+ */
+ discardRestoredStateTimer.start(150, this);
+ }
+ }
+
layoutState.rect = r;
+
layoutState.fitLayout();
applyState(layoutState, false);
}
+void QMainWindowLayout::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == discardRestoredStateTimer.timerId()) {
+ discardRestoredStateTimer.stop();
+ restoredState.reset();
+ }
+ QLayout::timerEvent(e);
+}
+
void QMainWindowLayout::addItem(QLayoutItem *)
{ qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
@@ -2090,7 +2453,7 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
// Let's remove the widget from any possible group window
const auto groups =
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups) {
if (dwgw == currentHoveredFloat)
continue;
@@ -2120,7 +2483,7 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
#if QT_CONFIG(dockwidget)
// Let's remove the widget from any possible group window
const auto groups =
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups) {
QList<int> path = dwgw->layoutInfo()->indexOf(widget);
if (!path.isEmpty())
@@ -2141,7 +2504,7 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
QRect globalRect = currentGapRect;
globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
#if QT_CONFIG(dockwidget)
- if (qobject_cast<QDockWidget*>(widget) != 0) {
+ if (qobject_cast<QDockWidget*>(widget) != nullptr) {
QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
if (layout->nativeWindowDeco()) {
globalRect.adjust(0, layout->titleHeight(), 0, 0);
@@ -2248,7 +2611,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
#if QT_CONFIG(dockwidget)
#if QT_CONFIG(tabbar)
- if (qobject_cast<QDockWidget*>(widget) != 0) {
+ if (qobject_cast<QDockWidget*>(widget) != nullptr) {
// info() might return null if the widget is destroyed while
// animating but before the animationFinished signal is received.
if (QDockAreaLayoutInfo *info = dockInfo(widget))
@@ -2320,7 +2683,7 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLay
#endif // QT_CONFIG(dockwidget)
pluggingWidget = nullptr;
- setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
+ setObjectName(mainwindow->objectName() + "_layout"_L1);
}
QMainWindowLayout::~QMainWindowLayout()
@@ -2395,7 +2758,6 @@ static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
return false;
// The QDockWidget is part of a group of tab and we need to unplug them all.
-
QDockWidgetGroupWindow *floatingTabs = layout->createTabbedDockWindow();
QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
*info = std::move(*parentItem.subinfo);
@@ -2410,6 +2772,30 @@ static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
}
#endif
+#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
+static QTabBar::Shape tabwidgetPositionToTabBarShape(QWidget *w)
+{
+ QTabBar::Shape result = QTabBar::RoundedSouth;
+ if (qobject_cast<QDockWidget *>(w)) {
+ switch (static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
+ case QTabWidget::North:
+ result = QTabBar::RoundedNorth;
+ break;
+ case QTabWidget::South:
+ result = QTabBar::RoundedSouth;
+ break;
+ case QTabWidget::West:
+ result = QTabBar::RoundedWest;
+ break;
+ case QTabWidget::East:
+ result = QTabBar::RoundedEast;
+ break;
+ }
+ }
+ return result;
+}
+#endif // QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
+
/*! \internal
Unplug \a widget (QDockWidget or QToolBar) from it's parent container.
@@ -2420,33 +2806,35 @@ static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
Returns the QLayoutItem of the dragged element.
The layout item is kept in the layout but set as a gap item.
*/
-QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
+QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, QDockWidgetPrivate::DragScope scope)
{
#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
auto *groupWindow = qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget());
if (!widget->isWindow() && groupWindow) {
- if (group && groupWindow->tabLayoutInfo()) {
+ if (scope == QDockWidgetPrivate::DragScope::Group && groupWindow->tabLayoutInfo()) {
// We are just dragging a floating window as it, not need to do anything, we just have to
// look up the corresponding QWidgetItem* if it exists
if (QDockAreaLayoutInfo *info = dockInfo(widget->parentWidget())) {
QList<int> groupWindowPath = info->indexOf(widget->parentWidget());
return groupWindowPath.isEmpty() ? nullptr : info->item(groupWindowPath).widgetItem;
}
+ qCDebug(lcQpaDockWidgets) << "Drag only:" << widget << "Group:" << (scope == QDockWidgetPrivate::DragScope::Group);
return nullptr;
}
QList<int> path = groupWindow->layoutInfo()->indexOf(widget);
- QLayoutItem *item = groupWindow->layoutInfo()->item(path).widgetItem;
- if (group && path.size() > 1
- && unplugGroup(this, &item,
- groupWindow->layoutInfo()->item(path.mid(0, path.size() - 1)))) {
+ QDockAreaLayoutItem parentItem = groupWindow->layoutInfo()->item(path);
+ QLayoutItem *item = parentItem.widgetItem;
+ if (scope == QDockWidgetPrivate::DragScope::Group && path.size() > 1
+ && unplugGroup(this, &item, parentItem)) {
+ qCDebug(lcQpaDockWidgets) << "Unplugging:" << widget << "from" << item;
return item;
} else {
- // We are unplugging a dock widget from a floating window.
- QDockWidget *dw = qobject_cast<QDockWidget *>(widget);
- Q_ASSERT(dw); // cannot be a QDockWidgetGroupWindow because it's not floating.
- dw->d_func()->unplug(widget->geometry());
- groupWindow->layoutInfo()->fitItems();
- groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
+ // We are unplugging a single dock widget from a floating window.
+ QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget);
+ Q_ASSERT(dockWidget); // cannot be a QDockWidgetGroupWindow because it's not floating.
+ dockWidget->d_func()->unplug(widget->geometry());
+
+ qCDebug(lcQpaDockWidgets) << "Unplugged from floating dock:" << widget << "from" << parentItem.widgetItem;
return item;
}
}
@@ -2466,7 +2854,7 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
Q_ASSERT(path.constFirst() == 1);
#if QT_CONFIG(tabwidget)
- if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3
+ if (scope == QDockWidgetPrivate::DragScope::Group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3
&& unplugGroup(this, &item,
layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)))) {
path.removeLast();
@@ -2474,6 +2862,36 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
} else
#endif // QT_CONFIG(tabwidget)
{
+ // Dock widget is unplugged from a main window dock
+ // => height or width need to be decreased by separator size
+ switch (dockWidgetArea(dw)) {
+ case Qt::LeftDockWidgetArea:
+ case Qt::RightDockWidgetArea:
+ r.setHeight(r.height() - sep);
+ break;
+ case Qt::TopDockWidgetArea:
+ case Qt::BottomDockWidgetArea:
+ r.setWidth(r.width() - sep);
+ break;
+ case Qt::NoDockWidgetArea:
+ case Qt::DockWidgetArea_Mask:
+ break;
+ }
+
+ // Depending on the title bar layout (vertical / horizontal),
+ // width and height have to provide minimum space for window handles
+ // and mouse dragging.
+ // Assuming horizontal title bar, if the dock widget does not have a layout.
+ const auto *layout = qobject_cast<QDockWidgetLayout *>(dw->layout());
+ const bool verticalTitleBar = layout ? layout->verticalTitleBar : false;
+ const int tbHeight = QApplication::style()
+ ? QApplication::style()->pixelMetric(QStyle::PixelMetric::PM_TitleBarHeight, nullptr, dw)
+ : 20;
+ const int minHeight = verticalTitleBar ? 2 * tbHeight : tbHeight;
+ const int minWidth = verticalTitleBar ? tbHeight : 2 * tbHeight;
+ r.setSize(r.size().expandedTo(QSize(minWidth, minHeight)));
+ qCDebug(lcQpaDockWidgets) << dw << "will be unplugged with size" << r.size();
+
dw->d_func()->unplug(r);
}
}
@@ -2485,7 +2903,7 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
#endif
#if !QT_CONFIG(dockwidget) || !QT_CONFIG(tabbar)
- Q_UNUSED(group);
+ Q_UNUSED(scope);
#endif
layoutState.unplug(path ,&savedState);
@@ -2515,58 +2933,45 @@ void QMainWindowLayout::updateGapIndicator()
if (!gapIndicator) {
gapIndicator = new QRubberBand(QRubberBand::Rectangle, expectedParent);
// For accessibility to identify this special widget.
- gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
+ gapIndicator->setObjectName("qt_rubberband"_L1);
} else if (gapIndicator->parent() != expectedParent) {
gapIndicator->setParent(expectedParent);
}
+ // Prevent re-entry in case of size change
+ const bool sigBlockState = gapIndicator->signalsBlocked();
+ auto resetSignals = qScopeGuard([this, sigBlockState](){ gapIndicator->blockSignals(sigBlockState); });
+ gapIndicator->blockSignals(true);
+
#if QT_CONFIG(dockwidget)
if (currentHoveredFloat)
gapIndicator->setGeometry(currentHoveredFloat->currentGapRect);
else
#endif
gapIndicator->setGeometry(currentGapRect);
+
gapIndicator->show();
gapIndicator->raise();
+
+ // Reset signal state
+
} else if (gapIndicator) {
gapIndicator->hide();
}
-#endif // QT_CONFIG(rubberband)
-}
-#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
-static QTabBar::Shape tabwidgetPositionToTabBarShape(QWidget *w)
-{
- QTabBar::Shape result = QTabBar::RoundedSouth;
- if (qobject_cast<QDockWidget *>(w)) {
- switch (static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
- case QTabWidget::North:
- result = QTabBar::RoundedNorth;
- break;
- case QTabWidget::South:
- result = QTabBar::RoundedSouth;
- break;
- case QTabWidget::West:
- result = QTabBar::RoundedWest;
- break;
- case QTabWidget::East:
- result = QTabBar::RoundedEast;
- break;
- }
- }
- return result;
+#endif // QT_CONFIG(rubberband)
}
-#endif // QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
-void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
-{
- if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
- || pluggingWidget != nullptr || widgetItem == nullptr)
- return;
+void QMainWindowLayout::hover(QLayoutItem *hoverTarget,
+ const QPoint &mousePos) {
+ if (!parentWidget()->isVisible() || parentWidget()->isMinimized() ||
+ pluggingWidget != nullptr || hoverTarget == nullptr)
+ return;
- QWidget *widget = widgetItem->widget();
+ QWidget *widget = hoverTarget->widget();
#if QT_CONFIG(dockwidget)
+ widget->raise();
if ((dockOptions & QMainWindow::GroupedDragging) && (qobject_cast<QDockWidget*>(widget)
|| qobject_cast<QDockWidgetGroupWindow *>(widget))) {
@@ -2577,12 +2982,20 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
QWidget *w = qobject_cast<QWidget*>(c);
if (!w)
continue;
+
+ // Handle only dock widgets and group windows
if (!qobject_cast<QDockWidget*>(w) && !qobject_cast<QDockWidgetGroupWindow *>(w))
continue;
- if (w != widget && w->isTopLevel() && w->isVisible() && !w->isMinimized())
+
+ // Check permission to dock on another dock widget or floating dock
+ // FIXME in Qt 7
+
+ if (w != widget && w->isWindow() && w->isVisible() && !w->isMinimized())
candidates << w;
+
if (QDockWidgetGroupWindow *group = qobject_cast<QDockWidgetGroupWindow *>(w)) {
- // Sometimes, there are floating QDockWidget that have a QDockWidgetGroupWindow as a parent.
+ // floating QDockWidgets have a QDockWidgetGroupWindow as a parent,
+ // if they have been hovered over
const auto groupChildren = group->children();
for (QObject *c : groupChildren) {
if (QDockWidget *dw = qobject_cast<QDockWidget*>(c)) {
@@ -2592,6 +3005,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
}
}
}
+
for (QWidget *w : candidates) {
const QScreen *screen1 = qt_widget_private(widget)->associatedScreen();
const QScreen *screen2 = qt_widget_private(w)->associatedScreen();
@@ -2602,36 +3016,63 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
#if QT_CONFIG(tabwidget)
if (auto dropTo = qobject_cast<QDockWidget *>(w)) {
- // dropping to a normal widget, we mutate it in a QDockWidgetGroupWindow with two
- // tabs
- QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); // FIXME
- floatingTabs->setGeometry(dropTo->geometry());
- QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
- const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
- *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock,
- Qt::Horizontal, shape,
- static_cast<QMainWindow *>(parentWidget()));
- info->tabbed = true;
- QLayout *parentLayout = dropTo->parentWidget()->layout();
- info->item_list.append(
- QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo))));
-
- dropTo->setParent(floatingTabs);
+
+ // w is the drop target's widget
+ w = dropTo->widget();
+
+ // Create a floating tab, unless already existing
+ if (!qobject_cast<QDockWidgetGroupWindow *>(w)) {
+ QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
+ floatingTabs->setGeometry(dropTo->geometry());
+ QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
+ const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
+
+ // dropTo and widget may be in a state where they transition
+ // from being a group window child to a single floating dock widget.
+ // In that case, their path to a main window dock may not have been
+ // updated yet.
+ // => ask both and fall back to dock 1 (right dock)
+ QInternal::DockPosition dockPosition = toDockPos(dockWidgetArea(dropTo));
+ if (dockPosition == QInternal::DockPosition::DockCount)
+ dockPosition = toDockPos(dockWidgetArea(widget));
+ if (dockPosition == QInternal::DockPosition::DockCount)
+ dockPosition = QInternal::DockPosition::RightDock;
+
+ *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, dockPosition,
+ Qt::Horizontal, shape,
+ static_cast<QMainWindow *>(parentWidget()));
+ info->tabBar = getTabBar();
+ info->tabbed = true;
+ info->add(dropTo);
+ QDockAreaLayoutInfo &parentInfo = layoutState.dockAreaLayout.docks[dockPosition];
+ parentInfo.add(floatingTabs);
+ dropTo->setParent(floatingTabs);
+ qCDebug(lcQpaDockWidgets) << "Wrapping" << widget << "into floating tabs" << floatingTabs;
+ w = floatingTabs;
+ }
+
+ // Show the drop target and raise widget to foreground
dropTo->show();
- dropTo->d_func()->plug(QRect());
- w = floatingTabs;
- widget->raise(); // raise, as our newly created drop target is now on top
+ qCDebug(lcQpaDockWidgets) << "Showing" << dropTo;
+ widget->raise();
+ qCDebug(lcQpaDockWidgets) << "Raising" << widget;
}
#endif
- Q_ASSERT(qobject_cast<QDockWidgetGroupWindow *>(w));
- auto group = static_cast<QDockWidgetGroupWindow *>(w);
- if (group->hover(widgetItem, group->mapFromGlobal(mousePos))) {
- setCurrentHoveredFloat(group);
+ auto *groupWindow = qobject_cast<QDockWidgetGroupWindow *>(w);
+ Q_ASSERT(groupWindow);
+ if (groupWindow->hover(hoverTarget, groupWindow->mapFromGlobal(mousePos))) {
+ setCurrentHoveredFloat(groupWindow);
applyState(layoutState); // update the tabbars
}
return;
}
}
+
+ // If a temporary group window has been created during a hover,
+ // remove it, if it has only one dockwidget child
+ if (currentHoveredFloat)
+ currentHoveredFloat->destroyIfSingleItemLeft();
+
setCurrentHoveredFloat(nullptr);
layoutState.dockAreaLayout.fallbackToSizeHints = false;
#endif // QT_CONFIG(dockwidget)
@@ -2647,11 +3088,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
bool allowed = false;
#if QT_CONFIG(dockwidget)
- if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
- allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
-
- if (qobject_cast<QDockWidgetGroupWindow *>(widget))
- allowed = true;
+ allowed = isAreaAllowed(widget, path);
#endif
#if QT_CONFIG(toolbar)
if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
@@ -2667,16 +3104,16 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
currentGapPos = path;
if (path.isEmpty()) {
- fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal
+ fixToolBarOrientation(hoverTarget, 2); // 2 = top dock, ie. horizontal
restore(true);
return;
}
- fixToolBarOrientation(widgetItem, currentGapPos.at(1));
+ fixToolBarOrientation(hoverTarget, currentGapPos.at(1));
QMainWindowLayoutState newState = savedState;
- if (!newState.insertGap(path, widgetItem)) {
+ if (!newState.insertGap(path, hoverTarget)) {
restore(true); // not enough space
return;
}
@@ -2713,10 +3150,16 @@ QDockWidgetGroupWindow *QMainWindowLayout::createTabbedDockWindow()
void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
{
+ // applying the state can lead to showing separator widgets, which would lead to a re-layout
+ // (even though the separator widgets are not really part of the layout)
+ // break the loop
+ if (isInApplyState)
+ return;
+ isInApplyState = true;
#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
const auto groups =
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ parent()->findChildren<QDockWidgetGroupWindow*>(Qt::FindDirectChildrenOnly);
for (QDockWidgetGroupWindow *dwgw : groups)
used += dwgw->layoutInfo()->usedTabBars();
@@ -2735,6 +3178,7 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat
usedSeparatorWidgets = usedSeps;
for (QWidget *sepWidget : retiredSeps) {
unusedSeparatorWidgets.append(sepWidget);
+ sepWidget->hide();
}
}
@@ -2743,6 +3187,7 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat
#endif // QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);
+ isInApplyState = false;
}
void QMainWindowLayout::saveState(QDataStream &stream) const
@@ -2752,6 +3197,7 @@ void QMainWindowLayout::saveState(QDataStream &stream) const
bool QMainWindowLayout::restoreState(QDataStream &stream)
{
+ QScopedValueRollback<bool> guard(isInRestoreState, true);
savedState = layoutState;
layoutState.clear();
layoutState.rect = savedState.rect;
@@ -2767,6 +3213,18 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
if (parentWidget()->isVisible()) {
layoutState.fitLayout();
applyState(layoutState, false);
+ } else {
+ /*
+ The state might not fit into the size of the widget as it gets shown, but
+ if the window is expected to be maximized or full screened, then we might
+ get several resizes as part of that transition, at the end of which the
+ state might fit. So keep the restored state around for now and try again
+ later in setGeometry.
+ */
+ if ((parentWidget()->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
+ && !layoutState.fits()) {
+ restoredState.reset(new QMainWindowLayoutState(layoutState));
+ }
}
savedState.deleteAllLayoutItems();
@@ -2775,7 +3233,7 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
#if QT_CONFIG(dockwidget)
if (parentWidget()->isVisible()) {
#if QT_CONFIG(tabbar)
- for (QTabBar *tab_bar : qAsConst(usedTabBars))
+ for (QTabBar *tab_bar : std::as_const(usedTabBars))
tab_bar->show();
#endif
@@ -2785,6 +3243,42 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
return true;
}
+#if QT_CONFIG(draganddrop)
+bool QMainWindowLayout::needsPlatformDrag()
+{
+ static const bool wayland =
+ QGuiApplication::platformName().startsWith("wayland"_L1, Qt::CaseInsensitive);
+ return wayland;
+}
+
+Qt::DropAction QMainWindowLayout::performPlatformWidgetDrag(QLayoutItem *widgetItem,
+ const QPoint &pressPosition)
+{
+ draggingWidget = widgetItem;
+ QWidget *widget = widgetItem->widget();
+ auto drag = QDrag(widget);
+ auto mimeData = new QMimeData();
+ auto window = widgetItem->widget()->windowHandle();
+
+ auto serialize = [](const auto &object) {
+ QByteArray data;
+ QDataStream dataStream(&data, QIODevice::WriteOnly);
+ dataStream << object;
+ return data;
+ };
+ mimeData->setData("application/x-qt-mainwindowdrag-window"_L1,
+ serialize(reinterpret_cast<qintptr>(window)));
+ mimeData->setData("application/x-qt-mainwindowdrag-position"_L1, serialize(pressPosition));
+ drag.setMimeData(mimeData);
+
+ auto result = drag.exec();
+
+ draggingWidget = nullptr;
+ return result;
+}
+#endif
+
QT_END_NAMESPACE
+#include "qmainwindowlayout.moc"
#include "moc_qmainwindowlayout_p.cpp"
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index d4f0bd4517..55a27e4849 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDYNAMICMAINWINDOWLAYOUT_P_H
-#define QDYNAMICMAINWINDOWLAYOUT_P_H
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMAINWINDOWLAYOUT_P_H
+#define QMAINWINDOWLAYOUT_P_H
//
// W A R N I N G
@@ -60,23 +24,36 @@
#include "QtGui/qpainter.h"
#include "QtGui/qevent.h"
#endif
-#include "QtCore/qvector.h"
-#include "QtCore/qset.h"
#include "QtCore/qbasictimer.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qset.h"
#include "private/qlayoutengine_p.h"
#include "private/qwidgetanimator_p.h"
-
#if QT_CONFIG(dockwidget)
+#include "private/qdockwidget_p.h"
+
#include "qdockarealayout_p.h"
+#include "qdockwidget.h"
+#else
+struct QDockWidgetPrivate {
+ enum class DragScope {
+ Group
+ };
+};
#endif
#if QT_CONFIG(toolbar)
#include "qtoolbararealayout_p.h"
#endif
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(mainwindow);
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcQpaDockWidgets);
+
class QToolBar;
class QRubberBand;
@@ -210,7 +187,7 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
#if QT_CONFIG(cursor)
case QEvent::HoverMove: {
- adjustCursor(static_cast<QHoverEvent *>(event)->pos());
+ adjustCursor(static_cast<QHoverEvent *>(event)->position().toPoint());
break;
}
@@ -228,7 +205,7 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
case QEvent::MouseButtonPress: {
QMouseEvent *e = static_cast<QMouseEvent *>(event);
- if (e->button() == Qt::LeftButton && startSeparatorMove(e->pos())) {
+ if (e->button() == Qt::LeftButton && startSeparatorMove(e->position().toPoint())) {
// The click was on a separator, eat this event
e->accept();
return true;
@@ -240,10 +217,10 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
QMouseEvent *e = static_cast<QMouseEvent *>(event);
#if QT_CONFIG(cursor)
- adjustCursor(e->pos());
+ adjustCursor(e->position().toPoint());
#endif
if (e->buttons() & Qt::LeftButton) {
- if (separatorMove(e->pos())) {
+ if (separatorMove(e->position().toPoint())) {
// We're moving a separator, eat this event
e->accept();
return true;
@@ -255,7 +232,7 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
case QEvent::MouseButtonRelease: {
QMouseEvent *e = static_cast<QMouseEvent *>(event);
- if (endSeparatorMove(e->pos())) {
+ if (endSeparatorMove(e->position().toPoint())) {
// We've released a separator, eat this event
e->accept();
return true;
@@ -334,18 +311,21 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(const QPoint &)
return true;
}
-class QDockWidgetGroupWindow : public QWidget
+class Q_AUTOTEST_EXPORT QDockWidgetGroupWindow : public QWidget
{
Q_OBJECT
public:
- explicit QDockWidgetGroupWindow(QWidget* parent = nullptr, Qt::WindowFlags f = { })
- : QWidget(parent, f) {}
+ explicit QDockWidgetGroupWindow(QWidget *parent = nullptr, Qt::WindowFlags f = {})
+ : QWidget(parent, f)
+ {
+ }
QDockAreaLayoutInfo *layoutInfo() const;
#if QT_CONFIG(tabbar)
const QDockAreaLayoutInfo *tabLayoutInfo() const;
QDockWidget *activeTabbedDockWidget() const;
#endif
void destroyOrHideIfEmpty();
+ bool hasVisibleDockWidgets() const;
void adjustFlags();
bool hasNativeDecos() const;
@@ -353,6 +333,10 @@ public:
void updateCurrentGapRect();
void restore();
void apply();
+ void childEvent(QChildEvent *event) override;
+ void reparent(QDockWidget *dockWidget);
+ void destroyIfSingleItemLeft();
+ QList<QDockWidget *> dockWidgets() const { return findChildren<QDockWidget *>(); }
QRect currentGapRect;
QList<int> currentGapPos;
@@ -362,6 +346,7 @@ signals:
protected:
bool event(QEvent *) override;
+ bool eventFilter(QObject *obj, QEvent *event) override;
void paintEvent(QPaintEvent*) override;
private:
@@ -369,14 +354,35 @@ private:
};
// This item will be used in the layout for the gap item. We cannot use QWidgetItem directly
-// because QWidgetItem functions return an empty size for widgets that are are floating.
+// because QWidgetItem functions return an empty size for widgets that are floating.
class QDockWidgetGroupWindowItem : public QWidgetItem
{
public:
explicit QDockWidgetGroupWindowItem(QDockWidgetGroupWindow *parent) : QWidgetItem(parent) {}
- QSize minimumSize() const override { return lay()->minimumSize(); }
- QSize maximumSize() const override { return lay()->maximumSize(); }
- QSize sizeHint() const override { return lay()->sizeHint(); }
+
+ // when the item contains a dock widget, obtain its size (to prevent infinite loop)
+ // ask the layout otherwise
+ QSize minimumSize() const override
+ {
+ if (auto dw = widget()->findChild<QDockWidget *>())
+ return dw->minimumSize();
+ return lay()->minimumSize();
+ }
+ QSize maximumSize() const override
+ {
+ auto dw = widget()->findChild<QDockWidget *>();
+ if (dw)
+ return dw->maximumSize();
+ return lay()->maximumSize();
+ }
+ QSize sizeHint() const override
+ {
+ auto dw = widget()->findChild<QDockWidget *>();
+ if (dw)
+ return dw->sizeHint();
+ return lay()->sizeHint();
+ }
+ QWidget* widget() const override { return wid; }
private:
QLayout *lay() const { return const_cast<QDockWidgetGroupWindowItem *>(this)->widget()->layout(); }
@@ -384,12 +390,12 @@ private:
#endif // QT_CONFIG(dockwidget)
/* This data structure represents the state of all the tool-bars and dock-widgets. It's value based
- so it can be easilly copied into a temporary variable. All operations are performed without moving
+ so it can be easily copied into a temporary variable. All operations are performed without moving
any widgets. Only when we are sure we have the desired state, we call apply(), which moves the
widgets.
*/
-class QMainWindowLayoutState
+class Q_AUTOTEST_EXPORT QMainWindowLayoutState
{
public:
QRect rect;
@@ -414,6 +420,7 @@ public:
QSize sizeHint() const;
QSize minimumSize() const;
+ bool fits() const;
void fitLayout();
QLayoutItem *itemAt(int index, int *x) const;
@@ -443,6 +450,7 @@ public:
bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState);
};
+class QMainWindowTabBar;
class Q_AUTOTEST_EXPORT QMainWindowLayout
: public QLayout,
public QMainWindowLayoutSeparatorHelper<QMainWindowLayout>
@@ -451,6 +459,7 @@ class Q_AUTOTEST_EXPORT QMainWindowLayout
public:
QMainWindowLayoutState layoutState, savedState;
+ std::unique_ptr<QMainWindowLayoutState> restoredState;
QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout);
~QMainWindowLayout();
@@ -458,22 +467,19 @@ public:
QMainWindow::DockOptions dockOptions;
void setDockOptions(QMainWindow::DockOptions opts);
- // status bar
-
QLayoutItem *statusbar;
+ // status bar
#if QT_CONFIG(statusbar)
QStatusBar *statusBar() const;
void setStatusBar(QStatusBar *sb);
#endif
// central widget
-
QWidget *centralWidget() const;
void setCentralWidget(QWidget *cw);
// toolbars
-
#if QT_CONFIG(toolbar)
void addToolBarBreak(Qt::ToolBarArea area);
void insertToolBarBreak(QToolBar *before);
@@ -490,10 +496,11 @@ public:
#endif
// dock widgets
-
#if QT_CONFIG(dockwidget)
void setCorner(Qt::Corner corner, Qt::DockWidgetArea area);
Qt::DockWidgetArea corner(Qt::Corner corner) const;
+ enum DockWidgetAreaSize {Visible, Maximum};
+ QRect dockWidgetAreaRect(Qt::DockWidgetArea area, DockWidgetAreaSize size = Maximum) const;
void addDockWidget(Qt::DockWidgetArea area,
QDockWidget *dockwidget,
Qt::Orientation orientation);
@@ -523,7 +530,7 @@ public:
int sep; // separator extent
#if QT_CONFIG(tabwidget)
- QTabWidget::TabPosition tabPositions[4];
+ QTabWidget::TabPosition tabPositions[QInternal::DockCount];
QTabWidget::TabShape _tabShape;
QTabWidget::TabShape tabShape() const;
@@ -540,15 +547,14 @@ public:
#endif // QT_CONFIG(dockwidget)
// save/restore
-
enum VersionMarkers { // sentinel values used to validate state data
VersionMarker = 0xff
};
void saveState(QDataStream &stream) const;
bool restoreState(QDataStream &stream);
+ QBasicTimer discardRestoredStateTimer;
// QLayout interface
-
void addItem(QLayoutItem *item) override;
void setGeometry(const QRect &r) override;
QLayoutItem *itemAt(int index) const override;
@@ -562,7 +568,6 @@ public:
void invalidate() override;
// animations
-
QWidgetAnimator widgetAnimator;
QList<int> currentGapPos;
QRect currentGapRect;
@@ -573,17 +578,32 @@ public:
#if QT_CONFIG(dockwidget)
QPointer<QDockWidgetGroupWindow> currentHoveredFloat; // set when dragging over a floating dock widget
void setCurrentHoveredFloat(QDockWidgetGroupWindow *w);
+#if QT_CONFIG(tabbar)
+ bool isDockWidgetTabbed(const QDockWidget *dockWidget) const;
+ QList<QDockWidget *> tabifiedDockWidgets(const QDockWidget *dockWidget) const;
+ QMainWindowTabBar *findTabBar(const QDockWidget *dockWidget) const;
#endif
+#endif
+ bool isInApplyState = false;
- void hover(QLayoutItem *widgetItem, const QPoint &mousePos);
+ void hover(QLayoutItem *hoverTarget, const QPoint &mousePos);
bool plug(QLayoutItem *widgetItem);
- QLayoutItem *unplug(QWidget *widget, bool group = false);
+ QLayoutItem *unplug(QWidget *widget, QDockWidgetPrivate::DragScope scope);
void revert(QLayoutItem *widgetItem);
- void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip);
void applyState(QMainWindowLayoutState &newState, bool animate = true);
+ void applyRestoredState();
void restore(bool keepSavedState = false);
void animationFinished(QWidget *widget);
+#if QT_CONFIG(draganddrop)
+ static bool needsPlatformDrag();
+ Qt::DropAction performPlatformWidgetDrag(QLayoutItem *widgetItem, const QPoint &pressPosition);
+ QLayoutItem *draggingWidget = nullptr;
+#endif
+
+protected:
+ void timerEvent(QTimerEvent *e) override;
+
private Q_SLOTS:
void updateGapIndicator();
#if QT_CONFIG(dockwidget)
@@ -596,6 +616,7 @@ private:
#if QT_CONFIG(tabbar)
void updateTabBarShapes();
#endif
+ bool isInRestoreState = false;
};
#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
@@ -606,4 +627,4 @@ QDebug operator<<(QDebug debug, const QMainWindowLayout *layout);
QT_END_NAMESPACE
-#endif // QDYNAMICMAINWINDOWLAYOUT_P_H
+#endif // QMAINWINDOWLAYOUT_P_H
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 3272ac440b..79b83453ac 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QMdiArea
@@ -51,7 +15,7 @@
applications, but can also be placed in any layout. The following
code adds an area to a main window:
- \snippet mdiareasnippets.cpp 0
+ \snippet mdiarea/mdiareasnippets.cpp 0
Unlike the window managers for top-level windows, all window flags
(Qt::WindowFlags) are supported by QMdiArea as long as the flags
@@ -63,7 +27,7 @@
Subwindows in QMdiArea are instances of QMdiSubWindow. They
are added to an MDI area with addSubWindow(). It is common to pass
a QWidget, which is set as the internal widget, to this function,
- but it is also possible to pass a QMdiSubWindow directly.The class
+ but it is also possible to pass a QMdiSubWindow directly. The class
inherits QWidget, and you can use the same API as with a normal
top-level window when programming. QMdiSubWindow also has behavior
that is specific to MDI windows. See the QMdiSubWindow class
@@ -103,8 +67,8 @@
\fn void QMdiArea::subWindowActivated(QMdiSubWindow *window)
QMdiArea emits this signal after \a window has been activated. When \a
- window is 0, QMdiArea has just deactivated its last active window, and
- there are no active windows on the workspace.
+ window is \nullptr, QMdiArea has just deactivated its last active window,
+ and there are no active windows on the workspace.
\sa QMdiArea::activeSubWindow()
*/
@@ -165,8 +129,6 @@
#include <QPainter>
#include <QFontMetrics>
#include <QStyleOption>
-#include <QDesktopWidget>
-#include <private/qdesktopwidget_p.h>
#include <QDebug>
#include <qmath.h>
#if QT_CONFIG(menu)
@@ -178,6 +140,7 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
using namespace QMdi;
// Asserts in debug mode, gives warning otherwise.
@@ -257,19 +220,7 @@ static inline QMdiArea *mdiAreaParent(QWidget *widget)
}
#if QT_CONFIG(tabwidget)
-static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
-{
- const bool rounded = (shape == QTabWidget::Rounded);
- if (position == QTabWidget::North)
- return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
- if (position == QTabWidget::South)
- return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
- if (position == QTabWidget::East)
- return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
- if (position == QTabWidget::West)
- return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
- return QTabBar::RoundedNorth;
-}
+QTabBar::Shape _q_tb_tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position);
#endif // QT_CONFIG(tabwidget)
static inline QString tabTextFor(QMdiSubWindow *subWindow)
@@ -279,7 +230,7 @@ static inline QString tabTextFor(QMdiSubWindow *subWindow)
QString title = subWindow->windowTitle();
if (subWindow->isWindowModified()) {
- title.replace(QLatin1String("[*]"), QLatin1String("*"));
+ title.replace("[*]"_L1, "*"_L1);
} else {
extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*);
title = qt_setWindowTitle_helperHelper(title, subWindow);
@@ -410,7 +361,7 @@ void IconTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const
\internal
Calculates the accumulated overlap (intersection area) between 'source' and 'rects'.
*/
-int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRect> &rects)
+int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QList<QRect> &rects)
{
int accOverlap = 0;
for (const QRect &rect : rects) {
@@ -426,7 +377,7 @@ int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRec
Finds among 'source' the rectangle with the minimum accumulated overlap with the
rectangles in 'rects'.
*/
-QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects)
+QRect MinOverlapPlacer::findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects)
{
int minAccOverlap = -1;
QRect minAccOverlapRect;
@@ -444,16 +395,16 @@ QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const Q
\internal
Gets candidates for the final placement.
*/
-QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QVector<QRect> &rects,
- const QRect &domain)
+QList<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QList<QRect> &rects,
+ const QRect &domain)
{
- QVector<QRect> result;
+ QList<QRect> result;
- QVector<int> xlist;
+ QList<int> xlist;
xlist.reserve(2 + rects.size());
xlist << domain.left() << domain.right() - size.width() + 1;
- QVector<int> ylist;
+ QList<int> ylist;
ylist.reserve(2 + rects.size());
ylist << domain.top();
if (domain.bottom() - size.height() + 1 >= 0)
@@ -471,8 +422,8 @@ QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const
ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());
result.reserve(ylist.size() * xlist.size());
- for (int y : qAsConst(ylist))
- for (int x : qAsConst(xlist))
+ for (int y : std::as_const(ylist))
+ for (int x : std::as_const(xlist))
result << QRect(QPoint(x, y), size);
return result;
}
@@ -482,14 +433,14 @@ QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const
Finds all rectangles in 'source' not completely inside 'domain'. The result is stored
in 'result' and also removed from 'source'.
*/
-QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)
+QList<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QList<QRect> &source)
{
const auto containedInDomain =
[domain](const QRect &srcRect) { return domain.contains(srcRect); };
const auto firstOut = std::stable_partition(source.begin(), source.end(), containedInDomain);
- QVector<QRect> result;
+ QList<QRect> result;
result.reserve(source.end() - firstOut);
std::copy(firstOut, source.end(), std::back_inserter(result));
@@ -503,9 +454,9 @@ QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QR
Finds all rectangles in 'source' that overlaps 'domain' by the maximum overlap area
between 'domain' and any rectangle in 'source'. The result is stored in 'result'.
*/
-QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QVector<QRect> &source)
+QList<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QList<QRect> &source)
{
- QVector<QRect> result;
+ QList<QRect> result;
result.reserve(source.size());
int maxOverlap = -1;
@@ -530,15 +481,15 @@ QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const Q
placement that overlaps the rectangles in 'rects' as little as possible while at the
same time being as much as possible inside 'domain'.
*/
-QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QRect> &rects,
- QVector<QRect> &source)
+QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QList<QRect> &rects,
+ QList<QRect> &source)
{
- const QVector<QRect> nonInsiders = findNonInsiders(domain, source);
+ const QList<QRect> nonInsiders = findNonInsiders(domain, source);
if (!source.empty())
return findMinOverlapRect(source, rects).topLeft();
- QVector<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);
+ QList<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);
return findMinOverlapRect(maxOverlappers, rects).topLeft();
}
@@ -549,7 +500,7 @@ QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QR
overlaps 'rects' as little as possible and 'domain' as much as possible.
Returns the position of the resulting rectangle.
*/
-QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,
+QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects,
const QRect &domain) const
{
if (size.isEmpty() || !domain.isValid())
@@ -559,7 +510,7 @@ QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,
return QPoint();
}
- QVector<QRect> candidates = getCandidatePlacements(size, rects, domain);
+ QList<QRect> candidates = getCandidatePlacements(size, rects, domain);
return findBestPlacement(domain, rects, candidates);
}
@@ -584,12 +535,12 @@ private:
*/
void QMdiAreaTabBar::mousePressEvent(QMouseEvent *event)
{
- if (event->button() != Qt::MidButton) {
+ if (event->button() != Qt::MiddleButton) {
QTabBar::mousePressEvent(event);
return;
}
- QMdiSubWindow *subWindow = subWindowFromIndex(tabAt(event->pos()));
+ QMdiSubWindow *subWindow = subWindowFromIndex(tabAt(event->position().toPoint()));
if (!subWindow) {
event->ignore();
return;
@@ -720,12 +671,16 @@ void QMdiAreaPrivate::_q_deactivateAllWindows(QMdiSubWindow *aboutToActivate)
aboutToBecomeActive = aboutToActivate;
Q_ASSERT(aboutToBecomeActive);
- foreach (QMdiSubWindow *child, childWindows) {
+ // Take a copy because child->showNormal() could indirectly call
+ // QCoreApplication::sendEvent(), which could call unknown code that e.g.
+ // recurses into the class modifying childWindows.
+ const auto subWindows = childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::deactivateAllWindows") || aboutToBecomeActive == child)
continue;
// We don't want to handle signals caused by child->showNormal().
ignoreWindowStateChange = true;
- if(!(options & QMdiArea::DontMaximizeSubWindowOnActivation) && !showActiveWindowMaximized)
+ if (!(options & QMdiArea::DontMaximizeSubWindowOnActivation) && !showActiveWindowMaximized)
showActiveWindowMaximized = child->isMaximized() && child->isVisible();
if (showActiveWindowMaximized && child->isMaximized()) {
if (q->updatesEnabled()) {
@@ -787,7 +742,7 @@ void QMdiAreaPrivate::_q_currentTabChanged(int index)
// If the previous active sub-window was hidden, disable the tab.
if (indexToLastActiveTab >= 0 && indexToLastActiveTab < tabBar->count()
- && indexToLastActiveTab < childWindows.count()) {
+ && indexToLastActiveTab < childWindows.size()) {
QMdiSubWindow *lastActive = childWindows.at(indexToLastActiveTab);
if (lastActive && lastActive->isHidden())
tabBar->setTabEnabled(indexToLastActiveTab, false);
@@ -861,7 +816,7 @@ void QMdiAreaPrivate::appendChild(QMdiSubWindow *child)
if (tabBar) {
tabBar->addTab(child->windowIcon(), tabTextFor(child));
updateTabBarGeometry();
- if (childWindows.count() == 1 && !(options & QMdiArea::DontMaximizeSubWindowOnActivation))
+ if (childWindows.size() == 1 && !(options & QMdiArea::DontMaximizeSubWindowOnActivation))
showActiveWindowMaximized = true;
}
#endif
@@ -892,10 +847,10 @@ void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child)
return;
}
- QVector<QRect> rects;
+ QList<QRect> rects;
rects.reserve(childWindows.size());
QRect parentRect = q->rect();
- foreach (QMdiSubWindow *window, childWindows) {
+ for (QMdiSubWindow *window : std::as_const(childWindows)) {
if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q)
|| !window->testAttribute(Qt::WA_Moved)) {
continue;
@@ -937,7 +892,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
const bool reverseList = rearranger->type() == Rearranger::RegularTiler;
const QList<QMdiSubWindow *> subWindows = subWindowList(activationOrder, reverseList);
QSize minSubWindowSize;
- foreach (QMdiSubWindow *child, subWindows) {
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::rearrange") || !child->isVisible())
continue;
if (rearranger->type() == Rearranger::IconTiler) {
@@ -956,7 +911,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
QRect domain = viewport->rect();
if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
- domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
+ domain = resizeToMinimumTileSize(minSubWindowSize, widgets.size());
rearranger->rearrange(widgets, domain);
@@ -1002,6 +957,10 @@ void QMdiAreaPrivate::activateWindow(QMdiSubWindow *child)
if (child->isHidden() || child == active)
return;
+
+ if (child->d_func()->isActive && active == nullptr)
+ child->d_func()->isActive = false;
+
child->d_func()->setActive(true);
}
@@ -1329,7 +1288,7 @@ bool QMdiAreaPrivate::scrollBarsEnabled() const
*/
bool QMdiAreaPrivate::lastWindowAboutToBeDestroyed() const
{
- if (childWindows.count() != 1)
+ if (childWindows.size() != 1)
return false;
QMdiSubWindow *last = childWindows.at(0);
@@ -1347,7 +1306,7 @@ bool QMdiAreaPrivate::lastWindowAboutToBeDestroyed() const
*/
void QMdiAreaPrivate::setChildActivationEnabled(bool enable, bool onlyNextActivationEvent) const
{
- foreach (QMdiSubWindow *subWindow, childWindows) {
+ for (QMdiSubWindow *subWindow : childWindows) {
if (!subWindow || !subWindow->isVisible())
continue;
if (onlyNextActivationEvent)
@@ -1369,7 +1328,11 @@ void QMdiAreaPrivate::scrollBarPolicyChanged(Qt::Orientation orientation, Qt::Sc
const QMdiSubWindow::SubWindowOption option = orientation == Qt::Horizontal ?
QMdiSubWindow::AllowOutsideAreaHorizontally : QMdiSubWindow::AllowOutsideAreaVertically;
const bool enable = policy != Qt::ScrollBarAlwaysOff;
- foreach (QMdiSubWindow *child, childWindows) {
+ // Take a copy because child->setOption() may indirectly call QCoreApplication::sendEvent(),
+ // the latter could call unknown code that could e.g. recurse into the class
+ // modifying childWindows.
+ const auto subWindows = childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::scrollBarPolicyChanged"))
continue;
child->setOption(option, enable);
@@ -1385,7 +1348,7 @@ QMdiAreaPrivate::subWindowList(QMdiArea::WindowOrder order, bool reversed) const
return list;
if (order == QMdiArea::CreationOrder) {
- foreach (QMdiSubWindow *child, childWindows) {
+ for (QMdiSubWindow *child : childWindows) {
if (!child)
continue;
if (!reversed)
@@ -1405,7 +1368,7 @@ QMdiAreaPrivate::subWindowList(QMdiArea::WindowOrder order, bool reversed) const
}
} else { // ActivationHistoryOrder
Q_ASSERT(indicesToActivatedChildren.size() == childWindows.size());
- for (int i = indicesToActivatedChildren.count() - 1; i >= 0; --i) {
+ for (int i = indicesToActivatedChildren.size() - 1; i >= 0; --i) {
QMdiSubWindow *child = childWindows.at(indicesToActivatedChildren.at(i));
if (!child)
continue;
@@ -1513,7 +1476,7 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)
if (!rubberBand) {
rubberBand = new QRubberBand(QRubberBand::Rectangle, q);
// For accessibility to identify this special widget.
- rubberBand->setObjectName(QLatin1String("qt_rubberband"));
+ rubberBand->setObjectName("qt_rubberband"_L1);
rubberBand->setWindowFlags(rubberBand->windowFlags() | Qt::WindowStaysOnTopHint);
}
#endif
@@ -1566,12 +1529,17 @@ void QMdiAreaPrivate::setViewMode(QMdiArea::ViewMode mode)
tabBar->setTabsClosable(tabsClosable);
tabBar->setMovable(tabsMovable);
#if QT_CONFIG(tabwidget)
- tabBar->setShape(tabBarShapeFrom(tabShape, tabPosition));
+ tabBar->setShape(_q_tb_tabBarShapeFrom(tabShape, tabPosition));
#endif
isSubWindowsTiled = false;
- foreach (QMdiSubWindow *subWindow, childWindows)
+ // Take a copy as tabBar->addTab() will (indirectly) create a connection between
+ // the tab close button clicked() signal and the _q_closeTab() slot, which may
+ // indirectly call QCoreApplication::sendEvent(), the latter could result in
+ // invoking unknown code that could e.g. recurse into the class modifying childWindows.
+ const auto subWindows = childWindows;
+ for (QMdiSubWindow *subWindow : subWindows)
tabBar->addTab(subWindow->windowIcon(), tabTextFor(subWindow));
QMdiSubWindow *current = q->currentSubWindow();
@@ -1630,7 +1598,7 @@ void QMdiAreaPrivate::updateTabBarGeometry()
Q_Q(QMdiArea);
#if QT_CONFIG(tabwidget)
- Q_ASSERT(tabBarShapeFrom(tabShape, tabPosition) == tabBar->shape());
+ Q_ASSERT(_q_tb_tabBarShapeFrom(tabShape, tabPosition) == tabBar->shape());
#endif
const QSize tabBarSizeHint = tabBar->sizeHint();
@@ -1687,7 +1655,7 @@ void QMdiAreaPrivate::refreshTabBar()
tabBar->setTabsClosable(tabsClosable);
tabBar->setMovable(tabsMovable);
#if QT_CONFIG(tabwidget)
- tabBar->setShape(tabBarShapeFrom(tabShape, tabPosition));
+ tabBar->setShape(_q_tb_tabBarShapeFrom(tabShape, tabPosition));
#endif
updateTabBarGeometry();
}
@@ -1733,7 +1701,7 @@ QMdiArea::~QMdiArea()
*/
QSize QMdiArea::sizeHint() const
{
- // Calculate a proper scale factor for QDesktopWidget::size().
+ // Calculate a proper scale factor for the desktop's size.
// This also takes into account that we can have nested workspaces.
int nestedCount = 0;
QWidget *widget = this->parentWidget();
@@ -1744,14 +1712,14 @@ QSize QMdiArea::sizeHint() const
}
const int scaleFactor = 3 * (nestedCount + 1);
- QSize desktopSize = QDesktopWidgetPrivate::size();
+ QSize desktopSize = QGuiApplication::primaryScreen()->virtualSize();
QSize size(desktopSize.width() * 2 / scaleFactor, desktopSize.height() * 2 / scaleFactor);
for (QMdiSubWindow *child : d_func()->childWindows) {
if (!sanityCheck(child, "QMdiArea::sizeHint"))
continue;
size = size.expandedTo(child->sizeHint());
}
- return size.expandedTo(QApplication::globalStrut());
+ return size;
}
/*!
@@ -1770,7 +1738,7 @@ QSize QMdiArea::minimumSizeHint() const
size = size.expandedTo(child->minimumSizeHint());
}
}
- return size.expandedTo(QApplication::globalStrut());
+ return size;
}
/*!
@@ -1794,7 +1762,7 @@ QMdiSubWindow *QMdiArea::currentSubWindow() const
if (d->isActivated && !window()->isMinimized())
return nullptr;
- Q_ASSERT(d->indicesToActivatedChildren.count() > 0);
+ Q_ASSERT(d->indicesToActivatedChildren.size() > 0);
int index = d->indicesToActivatedChildren.at(0);
Q_ASSERT(index >= 0 && index < d->childWindows.size());
QMdiSubWindow *current = d->childWindows.at(index);
@@ -1893,7 +1861,11 @@ void QMdiArea::closeAllSubWindows()
return;
d->isSubWindowsTiled = false;
- foreach (QMdiSubWindow *child, d->childWindows) {
+ // Take a copy because the child->close() call below may end up indirectly calling
+ // QCoreApplication::send{Spontaneous}Event(), which may call unknown code that
+ // could e.g. recurse into the class modifying d->childWindows.
+ const auto subWindows = d->childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::closeAllSubWindows"))
continue;
child->close();
@@ -1950,7 +1922,7 @@ void QMdiArea::activatePreviousSubWindow()
\note Once the subwindow has been added, its parent will be the
\e{viewport widget} of the QMdiArea.
- \snippet mdiareasnippets.cpp 1
+ \snippet mdiarea/mdiareasnippets.cpp 1
When you create your own subwindow, you must set the
Qt::WA_DeleteOnClose widget attribute if you want the window to be
@@ -2032,7 +2004,11 @@ void QMdiArea::removeSubWindow(QWidget *widget)
}
bool found = false;
- foreach (QMdiSubWindow *child, d->childWindows) {
+ // Take a copy because child->setWidget(nullptr) will indirectly
+ // QCoreApplication::sendEvent(); the latter could call unknown code that could
+ // e.g. recurse into the class modifying d->childWindows.
+ const auto subWindows = d->childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::removeSubWindow"))
continue;
if (child->widget() == widget) {
@@ -2313,10 +2289,21 @@ void QMdiArea::resizeEvent(QResizeEvent *resizeEvent)
// Resize maximized views.
bool hasMaximizedSubWindow = false;
- foreach (QMdiSubWindow *child, d->childWindows) {
+ // Take a copy because child->resize() may call QCoreApplication::sendEvent()
+ // which may invoke unknown code, that could e.g. recurse into the class
+ // modifying d->childWindows.
+ const auto subWindows = d->childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (sanityCheck(child, "QMdiArea::resizeEvent") && child->isMaximized()
&& child->size() != resizeEvent->size()) {
- child->resize(resizeEvent->size());
+ auto realSize = resizeEvent->size();
+ const auto minSizeHint = child->minimumSizeHint();
+ // QMdiSubWindow is no tlw so minimumSize() is not set by the layout manager
+ // and therefore we have to take care by ourself that we're not getting smaller
+ // than allowed
+ if (minSizeHint.isValid())
+ realSize = realSize.expandedTo(minSizeHint);
+ child->resize(realSize);
if (!hasMaximizedSubWindow)
hasMaximizedSubWindow = true;
}
@@ -2365,7 +2352,9 @@ void QMdiArea::showEvent(QShowEvent *showEvent)
Q_D(QMdiArea);
if (!d->pendingRearrangements.isEmpty()) {
bool skipPlacement = false;
- foreach (Rearranger *rearranger, d->pendingRearrangements) {
+ // Take a copy because d->rearrange() may modify d->pendingRearrangements
+ const auto pendingRearrange = d->pendingRearrangements;
+ for (Rearranger *rearranger : pendingRearrange) {
// If this is the case, we don't have to lay out pending child windows
// since the rearranger will find a placement for them.
if (rearranger->type() != Rearranger::IconTiler && !skipPlacement)
@@ -2379,9 +2368,19 @@ void QMdiArea::showEvent(QShowEvent *showEvent)
}
if (!d->pendingPlacements.isEmpty()) {
- foreach (QMdiSubWindow *window, d->pendingPlacements) {
+ // Nothing obvious in the loop body changes the container (in this code path)
+ // during iteration, this is calling into a non-const method that does change
+ // the container when called from other places. So take a copy anyway for good
+ // measure.
+ const auto copy = d->pendingPlacements;
+ for (QMdiSubWindow *window : copy) {
if (!window)
continue;
+ if (d->viewMode == TabbedView && window->d_func()->isActive && !d->active) {
+ d->showActiveWindowMaximized = true;
+ d->emitWindowActivated(window); // Also maximizes the window
+ continue;
+ }
if (!window->testAttribute(Qt::WA_Resized)) {
QSize newSize(window->sizeHint().boundedTo(viewport()->size()));
window->resize(newSize.expandedTo(qSmartMinSize(window)));
@@ -2515,12 +2514,16 @@ bool QMdiArea::event(QEvent *event)
d->isSubWindowsTiled = true;
}
break;
- case QEvent::WindowIconChange:
- foreach (QMdiSubWindow *window, d->childWindows) {
+ case QEvent::WindowIconChange: {
+ // Take a copy because QCoreApplication::sendEvent() may call unknown code,
+ // that may cause recursing into the class
+ const auto subWindows = d->childWindows;
+ for (QMdiSubWindow *window : subWindows) {
if (sanityCheck(window, "QMdiArea::WindowIconChange"))
QCoreApplication::sendEvent(window, event);
}
break;
+ }
case QEvent::Hide:
d->setActive(d->active, false, false);
d->setChildActivationEnabled(false);
@@ -2549,7 +2552,7 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event)
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
- // Ingore key events without a Ctrl modifier (except for press/release on the modifier itself).
+ // Ignore key events without a Ctrl modifier (except for press/release on the modifier itself).
if (!(keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() != Qt::Key_Control)
return QAbstractScrollArea::eventFilter(object, event);
@@ -2675,7 +2678,10 @@ void QMdiArea::setupViewport(QWidget *viewport)
Q_D(QMdiArea);
if (viewport)
viewport->setAttribute(Qt::WA_OpaquePaintEvent, d->background.isOpaque());
- foreach (QMdiSubWindow *child, d->childWindows) {
+ // Take a copy because the child->setParent() call below may call QCoreApplication::sendEvent()
+ // which may call unknown code that could e.g. recurse into the class modifying d->childWindows.
+ const auto subWindows = d->childWindows;
+ for (QMdiSubWindow *child : subWindows) {
if (!sanityCheck(child, "QMdiArea::setupViewport"))
continue;
child->setParent(viewport, child->windowFlags());
diff --git a/src/widgets/widgets/qmdiarea.h b/src/widgets/widgets/qmdiarea.h
index 35edde9eb8..c1442bc645 100644
--- a/src/widgets/widgets/qmdiarea.h
+++ b/src/widgets/widgets/qmdiarea.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMDIAREA_H
#define QMDIAREA_H
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 0a6368044a..e57b9772ca 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMDIAREA_P_H
#define QMDIAREA_P_H
@@ -58,13 +22,15 @@
QT_REQUIRE_CONFIG(mdiarea);
#include <QList>
-#include <QVector>
+#include <QList>
#include <QRect>
#include <QPoint>
#include <QtWidgets/qapplication.h>
#include <private/qmdisubwindow_p.h>
#include <private/qabstractscrollarea_p.h>
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
namespace QMdi {
@@ -115,20 +81,22 @@ class Placer
public:
// Places the rectangle defined by 'size' relative to 'rects' and 'domain'.
// Returns the position of the resulting rectangle.
- virtual QPoint place(
- const QSize &size, const QVector<QRect> &rects, const QRect &domain) const = 0;
+ virtual QPoint place(const QSize &size, const QList<QRect> &rects,
+ const QRect &domain) const = 0;
virtual ~Placer() {}
};
class MinOverlapPlacer : public Placer
{
- QPoint place(const QSize &size, const QVector<QRect> &rects, const QRect &domain) const override;
- static int accumulatedOverlap(const QRect &source, const QVector<QRect> &rects);
- static QRect findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects);
- static QVector<QRect> getCandidatePlacements(const QSize &size, const QVector<QRect> &rects, const QRect &domain);
- static QPoint findBestPlacement(const QRect &domain, const QVector<QRect> &rects, QVector<QRect> &source);
- static QVector<QRect> findNonInsiders(const QRect &domain, QVector<QRect> &source);
- static QVector<QRect> findMaxOverlappers(const QRect &domain, const QVector<QRect> &source);
+ QPoint place(const QSize &size, const QList<QRect> &rects, const QRect &domain) const override;
+ static int accumulatedOverlap(const QRect &source, const QList<QRect> &rects);
+ static QRect findMinOverlapRect(const QList<QRect> &source, const QList<QRect> &rects);
+ static QList<QRect> getCandidatePlacements(const QSize &size, const QList<QRect> &rects,
+ const QRect &domain);
+ static QPoint findBestPlacement(const QRect &domain, const QList<QRect> &rects,
+ QList<QRect> &source);
+ static QList<QRect> findNonInsiders(const QRect &domain, QList<QRect> &source);
+ static QList<QRect> findMaxOverlappers(const QRect &domain, const QList<QRect> &source);
};
} // namespace QMdi
@@ -149,9 +117,9 @@ public:
#endif
QMdiAreaTabBar *tabBar;
QList<QMdi::Rearranger *> pendingRearrangements;
- QVector< QPointer<QMdiSubWindow> > pendingPlacements;
- QVector< QPointer<QMdiSubWindow> > childWindows;
- QVector<int> indicesToActivatedChildren;
+ QList<QPointer<QMdiSubWindow>> pendingPlacements;
+ QList<QPointer<QMdiSubWindow>> childWindows;
+ QList<int> indicesToActivatedChildren;
QPointer<QMdiSubWindow> active;
QPointer<QMdiSubWindow> aboutToBecomeActive;
QBrush background;
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index f8460a4718..d8700e3df2 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QMdiSubWindow
@@ -154,7 +118,9 @@
#if QT_CONFIG(whatsthis)
#include <QWhatsThis>
#endif
+#if QT_CONFIG(tooltip)
#include <QToolTip>
+#endif
#if QT_CONFIG(mainwindow)
#include <QMainWindow>
#endif
@@ -168,9 +134,12 @@
#if QT_CONFIG(menu)
#include <QMenu>
#endif
+#include <QProxyStyle>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
using namespace QMdi;
static const QStyle::SubControl SubControls[] =
@@ -201,7 +170,9 @@ static const int BoundaryMargin = 5;
static inline bool isMacStyle(QStyle *style)
{
- return style->inherits("QMacStyle");
+ auto proxyStyle = qobject_cast<QProxyStyle *>(style);
+ auto styleToCheck = proxyStyle ? proxyStyle->baseStyle() : style;
+ return styleToCheck->inherits("QMacStyle");
}
static inline int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag,
@@ -258,13 +229,30 @@ static inline ControlElement<T> *ptr(QWidget *widget)
return nullptr;
}
+QString QMdiSubWindowPrivate::originalWindowTitleHelper() const
+{
+ Q_Q(const QMdiSubWindow);
+ // QTBUG-92240: When DontMaximizeSubWindowOnActivation is set and
+ // there is another subwindow maximized, use its original title.
+ if (auto *mdiArea = q->mdiArea()) {
+ const auto &subWindows = mdiArea->subWindowList();
+ for (auto *subWindow : subWindows) {
+ if (subWindow != q && subWindow->isMaximized()) {
+ auto *subWindowD = static_cast<QMdiSubWindowPrivate *>(qt_widget_private(subWindow));
+ if (!subWindowD->originalTitle.isNull())
+ return subWindowD->originalTitle;
+ }
+ }
+ }
+ return q->window()->windowTitle();
+}
+
QString QMdiSubWindowPrivate::originalWindowTitle()
{
- Q_Q(QMdiSubWindow);
if (originalTitle.isNull()) {
- originalTitle = q->window()->windowTitle();
+ originalTitle = originalWindowTitleHelper();
if (originalTitle.isNull())
- originalTitle = QLatin1String("");
+ originalTitle = ""_L1;
}
return originalTitle;
}
@@ -277,11 +265,17 @@ void QMdiSubWindowPrivate::setNewWindowTitle()
return;
QString original = originalWindowTitle();
if (!original.isEmpty()) {
- if (!original.contains(QMdiSubWindow::tr("- [%1]").arg(childTitle)))
- q->window()->setWindowTitle(QMdiSubWindow::tr("%1 - [%2]").arg(original, childTitle));
+ if (!original.contains(QMdiSubWindow::tr("- [%1]").arg(childTitle))) {
+ auto title = QMdiSubWindow::tr("%1 - [%2]").arg(original, childTitle);
+ ignoreWindowTitleChange = true;
+ q->window()->setWindowTitle(title);
+ ignoreWindowTitleChange = false;
+ }
} else {
+ ignoreWindowTitleChange = true;
q->window()->setWindowTitle(childTitle);
+ ignoreWindowTitleChange = false;
}
}
@@ -290,7 +284,7 @@ static inline bool isHoverControl(QStyle::SubControl control)
return control != QStyle::SC_None && control != QStyle::SC_TitleBarLabel;
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOptionComplex &opt,
QStyle::ComplexControl complexControl, QStyle::SubControl subControl)
{
@@ -355,7 +349,7 @@ static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOpti
const QRect rect = widget->style()->subControlRect(complexControl, &opt, subControl, widget);
QToolTip::showText(helpEvent->globalPos(), toolTip, widget, rect);
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
namespace QMdi {
/*
@@ -394,7 +388,7 @@ ControlLabel::ControlLabel(QMdiSubWindow *subWindow, QWidget *parent)
Q_UNUSED(subWindow);
setFocusPolicy(Qt::NoFocus);
updateWindowIcon();
- setFixedSize(label.size());
+ setFixedSize(label.deviceIndependentSize().toSize());
}
/*
@@ -402,7 +396,7 @@ ControlLabel::ControlLabel(QMdiSubWindow *subWindow, QWidget *parent)
*/
QSize ControlLabel::sizeHint() const
{
- return label.size();
+ return label.deviceIndependentSize().toSize();
}
/*
@@ -416,7 +410,7 @@ bool ControlLabel::event(QEvent *event)
updateWindowIcon();
setFixedSize(label.size());
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
else if (event->type() == QEvent::ToolTip) {
QStyleOptionTitleBar options;
options.initFrom(this);
@@ -611,7 +605,7 @@ void ControllerWidget::mousePressEvent(QMouseEvent *event)
event->ignore();
return;
}
- activeControl = getSubControl(event->pos());
+ activeControl = getSubControl(event->position().toPoint());
update();
}
@@ -625,7 +619,7 @@ void ControllerWidget::mouseReleaseEvent(QMouseEvent *event)
return;
}
- QStyle::SubControl under_mouse = getSubControl(event->pos());
+ QStyle::SubControl under_mouse = getSubControl(event->position().toPoint());
if (under_mouse == activeControl) {
switch (activeControl) {
case QStyle::SC_MdiCloseButton:
@@ -651,7 +645,7 @@ void ControllerWidget::mouseReleaseEvent(QMouseEvent *event)
*/
void ControllerWidget::mouseMoveEvent(QMouseEvent *event)
{
- QStyle::SubControl under_mouse = getSubControl(event->pos());
+ QStyle::SubControl under_mouse = getSubControl(event->position().toPoint());
//test if hover state changes
if (hoverControl != under_mouse) {
hoverControl = under_mouse;
@@ -673,14 +667,14 @@ void ControllerWidget::leaveEvent(QEvent * /*event*/)
*/
bool ControllerWidget::event(QEvent *event)
{
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
if (event->type() == QEvent::ToolTip) {
QStyleOptionComplex opt;
initStyleOption(&opt);
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
showToolTip(helpEvent, this, opt, QStyle::CC_MdiControls, getSubControl(helpEvent->pos()));
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
return QWidget::event(event);
}
@@ -739,7 +733,7 @@ ControlContainer::~ControlContainer()
QMenuBar *QMdiSubWindowPrivate::menuBar() const
{
#if !QT_CONFIG(mainwindow)
- return 0;
+ return nullptr;
#else
Q_Q(const QMdiSubWindow);
if (!q->isMaximized() || drawTitleBarWhenMaximized() || isChildOfTabbedQMdiArea(q))
@@ -1891,7 +1885,7 @@ void QMdiSubWindowPrivate::enterRubberBandMode()
if (!rubberBand) {
rubberBand = new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
// For accessibility to identify this special widget.
- rubberBand->setObjectName(QLatin1String("qt_rubberband"));
+ rubberBand->setObjectName("qt_rubberband"_L1);
}
QPoint rubberBandPos = q->mapToParent(QPoint(0, 0));
rubberBand->setGeometry(rubberBandPos.x(), rubberBandPos.y(),
@@ -1920,20 +1914,16 @@ QPalette QMdiSubWindowPrivate::desktopPalette() const
Q_Q(const QMdiSubWindow);
QPalette newPalette = q->palette();
- bool colorsInitialized = false;
-
- if (!colorsInitialized) {
- newPalette.setColor(QPalette::Active, QPalette::Highlight,
- newPalette.color(QPalette::Active, QPalette::Highlight));
- newPalette.setColor(QPalette::Active, QPalette::Base,
- newPalette.color(QPalette::Active, QPalette::Highlight));
- newPalette.setColor(QPalette::Inactive, QPalette::Highlight,
- newPalette.color(QPalette::Inactive, QPalette::Dark));
- newPalette.setColor(QPalette::Inactive, QPalette::Base,
- newPalette.color(QPalette::Inactive, QPalette::Dark));
- newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
- newPalette.color(QPalette::Inactive, QPalette::Window));
- }
+ newPalette.setColor(QPalette::Active, QPalette::Highlight,
+ newPalette.color(QPalette::Active, QPalette::Highlight));
+ newPalette.setColor(QPalette::Active, QPalette::Base,
+ newPalette.color(QPalette::Active, QPalette::Highlight));
+ newPalette.setColor(QPalette::Inactive, QPalette::Highlight,
+ newPalette.color(QPalette::Inactive, QPalette::Dark));
+ newPalette.setColor(QPalette::Inactive, QPalette::Base,
+ newPalette.color(QPalette::Inactive, QPalette::Dark));
+ newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ newPalette.color(QPalette::Inactive, QPalette::Window));
return newPalette;
}
@@ -2188,7 +2178,7 @@ void QMdiSubWindowPrivate::updateInternalWindowTitle()
Q_Q(QMdiSubWindow);
if (q->isWindowModified()) {
windowTitle = q->windowTitle();
- windowTitle.replace(QLatin1String("[*]"), QLatin1String("*"));
+ windowTitle.replace("[*]"_L1, "*"_L1);
} else {
windowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q);
}
@@ -2306,10 +2296,8 @@ void QMdiSubWindow::setWidget(QWidget *widget)
d->updateWindowTitle(true);
isWindowModified = d->baseWidget->isWindowModified();
}
- if (!this->isWindowModified() && isWindowModified
- && windowTitle().contains(QLatin1String("[*]"))) {
+ if (!this->isWindowModified() && isWindowModified && windowTitle().contains("[*]"_L1))
setWindowModified(isWindowModified);
- }
d->lastChildWindowTitle = d->baseWidget->windowTitle();
d->ignoreWindowTitleChange = false;
@@ -2657,12 +2645,12 @@ bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
if (d->systemMenu && d->systemMenu == object) {
if (event->type() == QEvent::MouseButtonDblClick) {
const QMouseEvent *mouseEvent = static_cast<const QMouseEvent *>(event);
- const QAction *action = d->systemMenu->actionAt(mouseEvent->pos());
+ const QAction *action = d->systemMenu->actionAt(mouseEvent->position().toPoint());
if (!action || action->isEnabled())
close();
} else if (event->type() == QEvent::MouseMove) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
- d->hoveredSubControl = d->getSubControl(mapFromGlobal(mouseEvent->globalPos()));
+ d->hoveredSubControl = d->getSubControl(mapFromGlobal(mouseEvent->globalPosition().toPoint()));
} else if (event->type() == QEvent::Hide) {
d->activeSubControl = QStyle::SC_None;
update(QRegion(0, 0, width(), d->titleBarHeight()));
@@ -2676,7 +2664,7 @@ bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
if (event->type() != QEvent::MouseButtonPress || !testOption(QMdiSubWindow::RubberBandResize))
return QWidget::eventFilter(object, event);
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
- d->mousePressPosition = parentWidget()->mapFromGlobal(mouseEvent->globalPos());
+ d->mousePressPosition = parentWidget()->mapFromGlobal(mouseEvent->globalPosition().toPoint());
d->oldGeometry = geometry();
d->currentOperation = isLeftToRight() ? QMdiSubWindowPrivate::BottomRightResize
: QMdiSubWindowPrivate::BottomLeftResize;
@@ -2742,7 +2730,7 @@ bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
bool windowModified = d->baseWidget->isWindowModified();
if (!windowModified && d->baseWidget->windowTitle() != windowTitle())
break;
- if (windowTitle().contains(QLatin1String("[*]")))
+ if (windowTitle().contains("[*]"_L1))
setWindowModified(windowModified);
break;
}
@@ -2843,7 +2831,7 @@ bool QMdiSubWindow::event(QEvent *event)
d->updateInternalWindowTitle();
break;
case QEvent::ModifiedChange:
- if (!windowTitle().contains(QLatin1String("[*]")))
+ if (!windowTitle().contains("[*]"_L1))
break;
#if QT_CONFIG(menubar)
if (maximizedButtonsWidget() && d->controlContainer->menuBar() && d->controlContainer->menuBar()
@@ -2874,7 +2862,7 @@ bool QMdiSubWindow::event(QEvent *event)
case QEvent::FontChange:
d->font = font();
break;
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
case QEvent::ToolTip:
showToolTip(static_cast<QHelpEvent *>(event), this, d->titleBarOptions(),
QStyle::CC_TitleBar, d->hoveredSubControl);
@@ -3171,7 +3159,7 @@ void QMdiSubWindow::mousePressEvent(QMouseEvent *mouseEvent)
if (d->currentOperation != QMdiSubWindowPrivate::None) {
d->updateCursor();
- d->mousePressPosition = mapToParent(mouseEvent->pos());
+ d->mousePressPosition = mapToParent(mouseEvent->position().toPoint());
if (d->resizeEnabled || d->moveEnabled)
d->oldGeometry = geometry();
#if QT_CONFIG(rubberband)
@@ -3262,10 +3250,10 @@ void QMdiSubWindow::mouseReleaseEvent(QMouseEvent *mouseEvent)
d->oldGeometry = geometry();
}
- d->currentOperation = d->getOperation(mouseEvent->pos());
+ d->currentOperation = d->getOperation(mouseEvent->position().toPoint());
d->updateCursor();
- d->hoveredSubControl = d->getSubControl(mouseEvent->pos());
+ d->hoveredSubControl = d->getSubControl(mouseEvent->position().toPoint());
if (d->activeSubControl != QStyle::SC_None
&& d->activeSubControl == d->hoveredSubControl) {
d->processClickedSubControl();
@@ -3290,7 +3278,7 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
// Find previous and current hover region.
const QStyleOptionTitleBar options = d->titleBarOptions();
QStyle::SubControl oldHover = d->hoveredSubControl;
- d->hoveredSubControl = d->getSubControl(mouseEvent->pos());
+ d->hoveredSubControl = d->getSubControl(mouseEvent->position().toPoint());
QRegion hoverRegion;
if (isHoverControl(oldHover) && oldHover != d->hoveredSubControl)
hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options, oldHover, this);
@@ -3310,13 +3298,13 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
if ((d->isResizeOperation() && d->resizeEnabled) || (d->isMoveOperation() && d->moveEnabled)) {
// As setNewGeometry moves the window, it invalidates the pos() value of any mouse move events that are
// currently queued in the event loop. Map to parent using globalPos() instead.
- d->setNewGeometry(parentWidget()->mapFromGlobal(mouseEvent->globalPos()));
+ d->setNewGeometry(parentWidget()->mapFromGlobal(mouseEvent->globalPosition().toPoint()));
}
return;
}
// Do not resize/move if not allowed.
- d->currentOperation = d->getOperation(mouseEvent->pos());
+ d->currentOperation = d->getOperation(mouseEvent->position().toPoint());
if ((d->isResizeOperation() && !d->resizeEnabled) || (d->isMoveOperation() && !d->moveEnabled))
d->currentOperation = QMdiSubWindowPrivate::None;
d->updateCursor();
@@ -3516,7 +3504,7 @@ QSize QMdiSubWindow::minimumSizeHint() const
minHeight = qMax(minHeight, decorationHeight + sizeGripHeight);
#endif
- return QSize(minWidth, minHeight).expandedTo(QApplication::globalStrut());
+ return QSize(minWidth, minHeight);
}
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qmdisubwindow.h b/src/widgets/widgets/qmdisubwindow.h
index 302522e1c3..4227f02dac 100644
--- a/src/widgets/widgets/qmdisubwindow.h
+++ b/src/widgets/widgets/qmdisubwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMDISUBWINDOW_H
#define QMDISUBWINDOW_H
@@ -137,6 +101,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_enterInteractiveMode())
Q_PRIVATE_SLOT(d_func(), void _q_processFocusChanged(QWidget *, QWidget *))
friend class QMdiAreaPrivate;
+ friend class QMdiArea;
#if QT_CONFIG(tabbar)
friend class QMdiAreaTabBar;
#endif
diff --git a/src/widgets/widgets/qmdisubwindow_p.h b/src/widgets/widgets/qmdisubwindow_p.h
index d3513b6708..2a1f83269a 100644
--- a/src/widgets/widgets/qmdisubwindow_p.h
+++ b/src/widgets/widgets/qmdisubwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMDISUBWINDOW_P_H
#define QMDISUBWINDOW_P_H
@@ -75,7 +39,7 @@ class QMouseEvent;
namespace QMdi {
template<typename T>
-class ControlElement : public T
+class ControlElement : public T // ELFVERSION:ignore
{
public:
ControlElement(QMdiSubWindow *child) : T(child, nullptr)
@@ -94,7 +58,7 @@ public:
QPointer<QMdiSubWindow> mdiChild;
};
-class ControlContainer : public QObject
+class ControlContainer : public QObject // ELFVERSION:ignore
{
public:
ControlContainer(QMdiSubWindow *mdiChild);
@@ -121,7 +85,7 @@ private:
};
} // namespace QMdi
-class QMdiSubWindowPrivate : public QWidgetPrivate
+class Q_AUTOTEST_EXPORT QMdiSubWindowPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMdiSubWindow)
public:
@@ -286,6 +250,7 @@ public:
#endif
void updateInternalWindowTitle();
QString originalWindowTitle();
+ QString originalWindowTitleHelper() const;
void setNewWindowTitle();
inline int titleBarHeight() const
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index fc7e2dbbcb..db00f8a650 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1,59 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmenu.h"
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/private/qwidgetwindow_p.h>
+#include "qactiongroup.h"
#include "qdebug.h"
#include "qstyle.h"
#include "qevent.h"
#include "qtimer.h"
#include "qlayout.h"
-#include "qpainter.h"
+#include "qstylepainter.h"
#include <qpa/qplatformtheme.h>
-#ifdef Q_OS_OSX
-#include "qmacnativewidget_mac.h"
-#endif
#include "qapplication.h"
-#include "qdesktopwidget.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "qaccessible.h"
#endif
#if QT_CONFIG(effects)
@@ -72,13 +34,14 @@
#include "qtoolbutton.h"
#endif
#include "qpushbutton.h"
+#if QT_CONFIG(tooltip)
#include "qtooltip.h"
+#endif
#include <qwindow.h>
#include <private/qpushbutton_p.h>
#include <private/qaction_p.h>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
-#include <private/qdesktopwidget_p.h>
#include <private/qstyle_p.h>
QT_BEGIN_NAMESPACE
@@ -105,7 +68,7 @@ class QTornOffMenu : public QMenu
Q_Q(QTornOffMenu);
QSize size = menuSize;
const QPoint p = (!initialized) ? causedMenu->pos() : q->pos();
- QRect screen = popupGeometry(QDesktopWidgetPrivate::screenNumber(p));
+ const QRect screen = popupGeometry(QGuiApplication::screenAt(p));
const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
const int titleBarHeight = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, q);
if (scroll && (size.height() > screen.height() - titleBarHeight || size.width() > screen.width())) {
@@ -118,9 +81,9 @@ class QTornOffMenu : public QMenu
q->setFixedSize(size);
}
- QVector<QPointer<QWidget> > calcCausedStack() const override { return causedStack; }
+ QList<QPointer<QWidget>> calcCausedStack() const override { return causedStack; }
QPointer<QMenu> causedMenu;
- QVector<QPointer<QWidget> > causedStack;
+ QList<QPointer<QWidget>> causedStack;
bool initialized;
};
@@ -130,7 +93,9 @@ public:
Q_D(QTornOffMenu);
// make the torn-off menu a sibling of p (instead of a child)
QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.constLast();
- if (parentWidget->parentWidget())
+ if (!parentWidget && p)
+ parentWidget = p;
+ if (parentWidget && parentWidget->parentWidget())
parentWidget = parentWidget->parentWidget();
setParent(parentWidget, Qt::Window | Qt::Tool);
setAttribute(Qt::WA_DeleteOnClose, true);
@@ -147,7 +112,7 @@ public:
//QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onTrigger(QAction*)));
//QObject::connect(this, SIGNAL(hovered(QAction*)), this, SLOT(onHovered(QAction*)));
QList<QAction*> items = p->actions();
- for(int i = 0; i < items.count(); i++)
+ for(int i = 0; i < items.size(); i++)
addAction(items.at(i));
d->setMenuSize(sizeHint());
d->initialized = true;
@@ -155,7 +120,7 @@ public:
void syncWithMenu(QMenu *menu, QActionEvent *act)
{
Q_D(QTornOffMenu);
- if(menu != d->causedMenu)
+ if (menu != d->causedMenu)
return;
auto action = static_cast<QAction *>(act->action());
if (act->type() == QEvent::ActionAdded) {
@@ -198,8 +163,9 @@ void QMenuPrivate::init()
#endif
q->setAttribute(Qt::WA_X11NetWmWindowTypePopupMenu);
defaultMenuAction = menuAction = new QAction(q);
- menuAction->d_func()->menu = q;
- QObject::connect(menuAction, &QAction::changed, [this] {
+ menuAction->setMenu(q); // this calls setOverrideMenuAction
+ setOverrideMenuAction(nullptr);
+ QObject::connect(menuAction, &QAction::changed, q, [this] {
if (!tornPopup.isNull())
tornPopup->updateWindowTitle();
});
@@ -251,15 +217,23 @@ void QMenuPrivate::syncPlatformMenu()
platformMenu->setEnabled(q->isEnabled());
}
+static QWidget *getParentWidget(const QAction *action)
+{
+ auto result = action->parent();
+ while (result && !qobject_cast<QWidget *>(result))
+ result = result->parent();
+ return static_cast<QWidget *>(result);
+}
+
void QMenuPrivate::copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item)
{
item->setText(action->text());
item->setIsSeparator(action->isSeparator());
if (action->isIconVisibleInMenu()) {
item->setIcon(action->icon());
- if (QWidget *w = action->parentWidget()) {
+ if (QWidget *w = getParentWidget(action)) {
QStyleOption opt;
- opt.init(w);
+ opt.initFrom(w);
item->setIconSize(w->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, w));
} else {
QStyleOption opt;
@@ -305,7 +279,7 @@ QPlatformMenuItem * QMenuPrivate::insertActionInPlatformMenu(const QAction *acti
int QMenuPrivate::scrollerHeight() const
{
Q_Q(const QMenu);
- return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, nullptr, q));
+ return q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, nullptr, q);
}
// Windows and KDE allow menus to cover the taskbar, while GNOME and macOS
@@ -315,24 +289,26 @@ inline bool QMenuPrivate::useFullScreenForPopup() const
return !tornoff && QStylePrivate::useFullScreenForPopup();
}
-QRect QMenuPrivate::popupGeometry() const
+QRect QMenuPrivate::popupGeometry(QScreen *screen) const
{
Q_Q(const QMenu);
- return useFullScreenForPopup()
- ? QDesktopWidgetPrivate::screenGeometry(q)
- : QDesktopWidgetPrivate::availableGeometry(q);
-}
-
-QRect QMenuPrivate::popupGeometry(int screen) const
-{
- return useFullScreenForPopup()
- ? QDesktopWidgetPrivate::screenGeometry(screen)
- : QDesktopWidgetPrivate::availableGeometry(screen);
+ if (screen == nullptr
+#if QT_CONFIG(graphicsview)
+ && q->graphicsProxyWidget() == nullptr
+#endif
+ ) {
+ screen = q->isVisible() ? q->screen() : popupScreen.data();
+ }
+ if (useFullScreenForPopup())
+ return screen ? screen->geometry()
+ : QWidgetPrivate::screenGeometry(q);
+ return screen ? screen->availableGeometry()
+ : QWidgetPrivate::availableScreenGeometry(q);
}
-QVector<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
+QList<QPointer<QWidget>> QMenuPrivate::calcCausedStack() const
{
- QVector<QPointer<QWidget> > ret;
+ QList<QPointer<QWidget>> ret;
for(QWidget *widget = causedPopup.widget; widget; ) {
ret.append(widget);
if (QTornOffMenu *qtmenu = qobject_cast<QTornOffMenu*>(widget))
@@ -347,7 +323,11 @@ QVector<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
bool QMenuPrivate::isContextMenu() const
{
+#if QT_CONFIG(menubar)
return qobject_cast<const QMenuBar *>(topCausedWidget()) == nullptr;
+#else
+ return true;
+#endif
}
void QMenuPrivate::updateActionRects() const
@@ -364,14 +344,14 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
q->ensurePolished();
//let's reinitialize the buffer
- actionRects.resize(actions.count());
+ actionRects.resize(actions.size());
actionRects.fill(QRect());
int lastVisibleAction = getLastVisibleAction();
QStyle *style = q->style();
QStyleOption opt;
- opt.init(q);
+ opt.initFrom(q);
const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q),
vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q),
icone = style->pixelMetric(QStyle::PM_SmallIconSize, &opt, q);
@@ -389,7 +369,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
hasCheckableItems = false;
ncols = 1;
- for (int i = 0; i < actions.count(); ++i) {
+ for (int i = 0; i < actions.size(); ++i) {
QAction *action = actions.at(i);
if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action))
continue;
@@ -433,7 +413,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
sz = QSize(2, 2);
} else {
QString s = action->text();
- int t = s.indexOf(QLatin1Char('\t'));
+ qsizetype t = s.indexOf(u'\t');
if (t != -1) {
tabWidth = qMax(int(tabWidth), qfm.horizontalAdvance(s.mid(t+1)));
s = s.left(t);
@@ -473,8 +453,8 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
}
max_column_width += tabWidth; //finally add in the tab width
- if (!tornoff || (tornoff && scroll)) { // exclude non-scrollable tear-off menu since the tear-off menu has a fixed size
- const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width();
+ if (!tornoff || scroll) { // exclude non-scrollable tear-off menu since the tear-off menu has a fixed size
+ const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QSize(0, 0), q).width();
const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
max_column_width = qMax(min_column_width, max_column_width);
}
@@ -483,7 +463,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
int x = hmargin + fw + leftmargin;
y = base_y;
- for(int i = 0; i < actions.count(); i++) {
+ for(int i = 0; i < actions.size(); i++) {
QRect &rect = actionRects[i];
if (rect.isNull())
continue;
@@ -508,7 +488,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
int QMenuPrivate::getLastVisibleAction() const
{
//let's try to get the last visible action
- int lastVisibleAction = actions.count() - 1;
+ int lastVisibleAction = actions.size() - 1;
for (;lastVisibleAction >= 0; --lastVisibleAction) {
const QAction *action = actions.at(lastVisibleAction);
if (action->isVisible()) {
@@ -566,20 +546,59 @@ void QMenuPrivate::hideMenu(QMenu *menu)
{
if (!menu)
return;
+
+ // See two execs below. They may trigger an akward situation
+ // when 'menu' (also known as 'q' or 'this' in the many functions
+ // around) to become a dangling pointer if the loop manages
+ // to execute 'deferred delete' ... posted while executing
+ // this same loop. Not good!
+ struct Reposter : QObject
+ {
+ Reposter(QMenu *menu) : q(menu)
+ {
+ Q_ASSERT(q);
+ q->installEventFilter(this);
+ }
+ ~Reposter()
+ {
+ if (deleteLater)
+ q->deleteLater();
+ }
+ bool eventFilter(QObject *obj, QEvent *event) override
+ {
+ if (obj == q && event->type() == QEvent::DeferredDelete)
+ return deleteLater = true;
+
+ return QObject::eventFilter(obj, event);
+ }
+ QMenu *q = nullptr;
+ bool deleteLater = false;
+ };
+
#if QT_CONFIG(effects)
- QSignalBlocker blocker(menu);
+ // If deleteLater has been called and the event loop spins, while waiting
+ // for visual effects to happen, menu might become stale.
+ // To prevent a QSignalBlocker from restoring a stale object, block and restore signals manually.
+ QPointer<QMenu> stillAlive(menu);
+ const bool signalsBlocked = menu->signalsBlocked();
+ menu->blockSignals(true);
+
aboutToHide = true;
// Flash item which is about to trigger (if any).
- if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)
+ if (menu && menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)
&& currentAction && currentAction == actionAboutToTrigger
&& menu->actions().contains(currentAction)) {
QEventLoop eventLoop;
QAction *activeAction = currentAction;
menu->setActiveAction(nullptr);
+ const Reposter deleteDeleteLate(menu);
QTimer::singleShot(60, &eventLoop, SLOT(quit()));
eventLoop.exec();
+ if (!stillAlive)
+ return;
+
// Select and wait 20 ms.
menu->setActiveAction(activeAction);
QTimer::singleShot(20, &eventLoop, SLOT(quit()));
@@ -587,15 +606,44 @@ void QMenuPrivate::hideMenu(QMenu *menu)
}
aboutToHide = false;
- blocker.unblock();
+
+ if (stillAlive)
+ menu->blockSignals(signalsBlocked);
+ else
+ return;
+
#endif // QT_CONFIG(effects)
if (activeMenu == menu)
activeMenu = nullptr;
+
menu->d_func()->causedPopup.action = nullptr;
menu->close();
menu->d_func()->causedPopup.widget = nullptr;
}
+QWindow *QMenuPrivate::transientParentWindow() const
+{
+ Q_Q(const QMenu);
+ if (const QWidget *parent = q->nativeParentWidget()) {
+ if (parent->windowHandle())
+ return parent->windowHandle();
+ }
+
+ if (const QWindow *w = q->windowHandle()) {
+ if (w->transientParent())
+ return w->transientParent();
+ }
+
+ if (causedPopup.widget) {
+ if (const QWidget *w = causedPopup.widget.data()) {
+ if (const QWidget *ww = w->window())
+ return ww->windowHandle();
+ }
+ }
+
+ return nullptr;
+}
+
void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
{
Q_Q(QMenu);
@@ -619,7 +667,7 @@ void QMenuPrivate::setSyncAction()
{
Q_Q(QMenu);
QAction *current = currentAction;
- if(current && (!current->isEnabled() || current->menu() || current->isSeparator()))
+ if (current && (!current->isEnabled() || current->menu() || current->isSeparator()))
current = nullptr;
for(QWidget *caused = q; caused;) {
if (QMenu *m = qobject_cast<QMenu*>(caused)) {
@@ -637,7 +685,7 @@ void QMenuPrivate::setFirstActionActive()
{
Q_Q(QMenu);
updateActionRects();
- for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ for(int i = 0, saccum = 0; i < actions.size(); i++) {
const QRect &rect = actionRects.at(i);
if (rect.isNull())
continue;
@@ -874,7 +922,7 @@ QAction *QMenuPrivate::actionAt(QPoint p) const
if (!rect().contains(p)) //sanity check
return nullptr;
- for(int i = 0; i < actionRects.count(); i++) {
+ for(int i = 0; i < actionRects.size(); i++) {
if (actionRects.at(i).contains(p))
return actions.at(i);
}
@@ -929,7 +977,7 @@ void QMenuPrivate::drawScroller(QPainter *painter, QMenuPrivate::ScrollerTearOff
menuOpt.state = QStyle::State_None;
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.maxIconWidth = 0;
- menuOpt.tabWidth = 0;
+ menuOpt.reservedShortcutWidth = 0;
menuOpt.rect = rect;
menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
menuOpt.state |= QStyle::State_Enabled;
@@ -954,7 +1002,7 @@ void QMenuPrivate::drawTearOff(QPainter *painter, const QRect &rect)
menuOpt.state = QStyle::State_None;
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.maxIconWidth = 0;
- menuOpt.tabWidth = 0;
+ menuOpt.reservedShortcutWidth = 0;
menuOpt.rect = rect;
menuOpt.menuItemType = QStyleOptionMenuItem::TearOff;
if (tearoffHighlighted)
@@ -969,7 +1017,7 @@ QRect QMenuPrivate::rect() const
Q_Q(const QMenu);
QStyle *style = q->style();
QStyleOption opt(0);
- opt.init(q);
+ opt.initFrom(q);
const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
@@ -1024,6 +1072,16 @@ QAction *QMenu::menuAction() const
}
/*!
+ \fn static QMenu *QMenu::menuInAction(const QAction *action)
+
+ Returns the menu contained by \a action, or \nullptr if \a action does not
+ contain a menu.
+
+ In widget applications, actions that contain menus can be used to create menu
+ items with submenus, or inserted into toolbars to create buttons with popup menus.
+*/
+
+/*!
\property QMenu::title
\brief The title of the menu
@@ -1075,7 +1133,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
if (location == QMenuScroller::ScrollTop) {
- for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ for(int i = 0, saccum = 0; i < actions.size(); i++) {
if (actions.at(i) == action) {
newOffset = topScroll - saccum;
break;
@@ -1083,7 +1141,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
saccum += actionRects.at(i).height();
}
} else {
- for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ for(int i = 0, saccum = 0; i < actions.size(); i++) {
saccum += actionRects.at(i).height();
if (actions.at(i) == action) {
if (location == QMenuScroller::ScrollCenter)
@@ -1093,7 +1151,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
break;
}
}
- if(newOffset)
+ if (newOffset)
newOffset -= fw * 2;
}
@@ -1102,7 +1160,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
if (newOffset < 0) //easy and cheap one
newScrollFlags |= QMenuScroller::ScrollUp;
int saccum = newOffset;
- for(int i = 0; i < actionRects.count(); i++) {
+ for(int i = 0; i < actionRects.size(); i++) {
saccum += actionRects.at(i).height();
if (saccum > q->height()) {
newScrollFlags |= QMenuScroller::ScrollDown;
@@ -1129,9 +1187,9 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
QRect geom = q->geometry();
if (newOffset > scroll->scrollOffset && (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollUp)) { //scroll up
const int newHeight = geom.height()-(newOffset-scroll->scrollOffset);
- if(newHeight > geom.height())
+ if (newHeight > geom.height())
geom.setHeight(newHeight);
- } else if(scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) {
+ } else if (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) {
int newTop = geom.top() + (newOffset-scroll->scrollOffset);
if (newTop < desktopFrame+screen.top())
newTop = desktopFrame+screen.top();
@@ -1159,7 +1217,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc
const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative
if (!itemsDirty && delta) {
//we've scrolled so we need to update the action rects
- for (int i = 0; i < actionRects.count(); ++i) {
+ for (int i = 0; i < actionRects.size(); ++i) {
QRect &current = actionRects[i];
current.moveTop(current.top() + delta);
@@ -1180,7 +1238,7 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool activ
{
Q_Q(QMenu);
updateActionRects();
- if(location == QMenuScroller::ScrollBottom) {
+ if (location == QMenuScroller::ScrollBottom) {
for(int i = actions.size()-1; i >= 0; --i) {
QAction *act = actions.at(i);
if (actionRects.at(i).isNull())
@@ -1188,14 +1246,14 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool activ
if (!act->isSeparator() &&
(q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
|| act->isEnabled())) {
- if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
+ if (scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollBottom, active);
- else if(active)
+ else if (active)
setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
break;
}
}
- } else if(location == QMenuScroller::ScrollTop) {
+ } else if (location == QMenuScroller::ScrollTop) {
for(int i = 0; i < actions.size(); ++i) {
QAction *act = actions.at(i);
if (actionRects.at(i).isNull())
@@ -1203,9 +1261,9 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool activ
if (!act->isSeparator() &&
(q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
|| act->isEnabled())) {
- if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
+ if (scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollTop, active);
- else if(active)
+ else if (active)
setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
break;
}
@@ -1226,7 +1284,7 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag
const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
const int offset = topScroll ? topScroll-vmargin : 0;
if (direction == QMenuScroller::ScrollUp) {
- for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ for(int i = 0, saccum = 0; i < actions.size(); i++) {
saccum -= actionRects.at(i).height();
if (saccum <= scroll->scrollOffset-offset) {
scrollMenu(actions.at(i), page ? QMenuScroller::ScrollBottom : QMenuScroller::ScrollTop, active);
@@ -1235,13 +1293,13 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag
}
} else if (direction == QMenuScroller::ScrollDown) {
bool scrolled = false;
- for(int i = 0, saccum = 0; i < actions.count(); i++) {
+ for(int i = 0, saccum = 0; i < actions.size(); i++) {
const int iHeight = actionRects.at(i).height();
saccum -= iHeight;
if (saccum <= scroll->scrollOffset-offset) {
const int scrollerArea = q->height() - botScroll - fw*2;
int visible = (scroll->scrollOffset-offset) - saccum;
- for(i++ ; i < actions.count(); i++) {
+ for(i++ ; i < actions.size(); i++) {
visible += actionRects.at(i).height();
if (visible > scrollerArea - topScroll) {
scrolled = true;
@@ -1252,7 +1310,7 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag
break;
}
}
- if(!scrolled) {
+ if (!scrolled) {
scroll->scrollFlags &= ~QMenuScroller::ScrollDown;
q->update();
}
@@ -1264,11 +1322,11 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag
bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
{
Q_Q(QMenu);
- QPoint pos = q->mapFromGlobal(e->globalPos());
+ QPoint pos = q->mapFromGlobal(e->globalPosition().toPoint());
QStyle *style = q->style();
QStyleOption opt(0);
- opt.init(q);
+ opt.initFrom(q);
const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
@@ -1303,7 +1361,7 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
if (scroll && scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
tearRect.translate(0, scrollerHeight());
q->update(tearRect);
- if (tearRect.contains(pos) && hasMouseMoved(e->globalPos())) {
+ if (tearRect.contains(pos) && hasMouseMoved(e->globalPosition().toPoint())) {
setCurrentAction(nullptr);
tearoffHighlighted = 1;
if (e->type() == QEvent::MouseButtonRelease) {
@@ -1318,26 +1376,27 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
tearoffHighlighted = 0;
}
- if (q->frameGeometry().contains(e->globalPos()))
+ if (q->frameGeometry().contains(e->globalPosition().toPoint()))
return false; //otherwise if the event is in our rect we want it..
for(QWidget *caused = causedPopup.widget; caused;) {
bool passOnEvent = false;
QWidget *next_widget = nullptr;
- QPoint cpos = caused->mapFromGlobal(e->globalPos());
+ QPointF cpos = caused->mapFromGlobal(e->globalPosition());
#if QT_CONFIG(menubar)
if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
- passOnEvent = mb->rect().contains(cpos);
+ passOnEvent = mb->rect().contains(cpos.toPoint());
} else
#endif
if (QMenu *m = qobject_cast<QMenu*>(caused)) {
- passOnEvent = m->rect().contains(cpos);
+ passOnEvent = m->rect().contains(cpos.toPoint());
next_widget = m->d_func()->causedPopup.widget;
}
if (passOnEvent) {
if (e->type() != QEvent::MouseButtonRelease || mouseDown == caused) {
- QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(),
- e->button(), e->buttons(), e->modifiers(), e->source());
+ QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->globalPosition(),
+ e->button(), e->buttons(), e->modifiers(),
+ e->source(), e->pointingDevice());
QCoreApplication::sendEvent(caused, &new_e);
return true;
}
@@ -1349,11 +1408,21 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
return false;
}
-void QMenuPrivate::activateCausedStack(const QVector<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self)
+void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget>> &causedStack, QAction *action,
+ QAction::ActionEvent action_e, bool self)
{
- QBoolBlocker guard(activationRecursionGuard);
- if(self)
+ Q_Q(QMenu);
+ // can't use QBoolBlocker here
+ const bool activationRecursionGuardReset = activationRecursionGuard;
+ activationRecursionGuard = true;
+ QPointer<QMenu> guard(q);
+ if (self)
action->activate(action_e);
+ if (!guard)
+ return;
+ auto boolBlocker = qScopeGuard([this, activationRecursionGuardReset]{
+ activationRecursionGuard = activationRecursionGuardReset;
+ });
for(int i = 0; i < causedStack.size(); ++i) {
QPointer<QWidget> widget = causedStack.at(i);
@@ -1397,7 +1466,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
/* I have to save the caused stack here because it will be undone after popup execution (ie in the hide).
Then I iterate over the list to actually send the events. --Sam
*/
- const QVector<QPointer<QWidget> > causedStack = calcCausedStack();
+ const QList<QPointer<QWidget>> causedStack = calcCausedStack();
if (action_e == QAction::Trigger) {
#if QT_CONFIG(whatsthis)
if (!inWhatsThisMode)
@@ -1409,7 +1478,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
} else {
for(QWidget *widget = QApplication::activePopupWidget(); widget; ) {
if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
- if(qmenu == q)
+ if (qmenu == q)
hideUpToMenuBar();
widget = qmenu->d_func()->causedPopup.widget;
} else {
@@ -1429,12 +1498,13 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
#endif
}
-
+ QPointer<QMenu> thisGuard(q);
activateCausedStack(causedStack, action, action_e, self);
-
+ if (!thisGuard)
+ return;
if (action_e == QAction::Hover) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
int actionIndex = indexOf(action);
QAccessibleEvent focusEvent(q, QAccessible::Focus);
@@ -1459,7 +1529,7 @@ void QMenuPrivate::_q_actionTriggered()
if (!activationRecursionGuard && actionGuard) {
//in case the action has not been activated by the mouse
//we check the parent hierarchy
- QVector< QPointer<QWidget> > list;
+ QList<QPointer<QWidget>> list;
for(QWidget *widget = q->parentWidget(); widget; ) {
if (qobject_cast<QMenu*>(widget)
#if QT_CONFIG(menubar)
@@ -1473,6 +1543,9 @@ void QMenuPrivate::_q_actionTriggered()
}
}
activateCausedStack(list, action, QAction::Trigger, false);
+ // if a widget action fires, we need to hide the menu explicitly
+ if (qobject_cast<QWidgetAction*>(action))
+ hideUpToMenuBar();
}
}
}
@@ -1491,7 +1564,7 @@ void QMenuPrivate::_q_platformMenuAboutToShow()
emit q->aboutToShow();
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
if (platformMenu) {
const auto actions = q->actions();
for (QAction *action : actions) {
@@ -1570,14 +1643,14 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
QString textAndAccel = action->text();
#ifndef QT_NO_SHORTCUT
if ((action->isShortcutVisibleInContextMenu() || !d->isContextMenu())
- && textAndAccel.indexOf(QLatin1Char('\t')) == -1) {
+ && textAndAccel.indexOf(u'\t') == -1) {
QKeySequence seq = action->shortcut();
if (!seq.isEmpty())
- textAndAccel += QLatin1Char('\t') + seq.toString(QKeySequence::NativeText);
+ textAndAccel += u'\t' + seq.toString(QKeySequence::NativeText);
}
#endif
option->text = textAndAccel;
- option->tabWidth = d->tabWidth;
+ option->reservedShortcutWidth = d->tabWidth;
option->maxIconWidth = d->maxIconWidth;
option->menuRect = rect();
}
@@ -1620,7 +1693,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
and all other items are considered action items.
When inserting action items you usually specify a receiver and a
- slot. The receiver will be notifed whenever the item is
+ slot. The receiver will be notified whenever the item is
\l{QAction::triggered()}{triggered()}. In addition, QMenu provides
two signals, triggered() and hovered(), which signal the
QAction that was triggered from the menu.
@@ -1640,13 +1713,13 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
Widgets can be inserted into menus with the QWidgetAction class.
Instances of this class are used to hold widgets, and are inserted
- into menus with the addAction() overload that takes a QAction.
-
- Conversely, actions can be added to widgets with the addAction(),
- addActions() and insertAction() functions.
+ into menus with the addAction() overload that takes a QAction. If the
+ QWidgetAction fires the triggered() signal, the menu will close.
\warning To make QMenu visible on the screen, exec() or popup() should be
- used instead of show().
+ used instead of show() or setVisible(). To hide or disable the menu in the
+ menubar, or in another menu to which it was added as a submenu, use the
+ respective properties of menuAction() instead.
\section1 QMenu on \macos with Qt Build Against Cocoa
@@ -1659,8 +1732,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
\b{Important inherited functions:} addAction(), removeAction(), clear(),
addSeparator(), and addMenu().
- \sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up},
- {Application Example}, {Menus Example}
+ \sa QMenuBar, {Menus Example}
*/
@@ -1725,162 +1797,75 @@ QMenu::~QMenu()
hideTearOffMenu();
}
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
- This convenience function creates a new action with \a text.
- The function adds the newly created action to the menu's
- list of actions, and returns it.
+ \fn QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut)
+ \obsolete
- QMenu takes ownership of the returned QAction.
-
- \sa QWidget::addAction()
+ Use \c{QWidget::addAction(text, shortcut, receiver, member)} instead.
*/
-QAction *QMenu::addAction(const QString &text)
-{
- QAction *ret = new QAction(text, this);
- addAction(ret);
- return ret;
-}
-
-/*!
- \overload
-
- This convenience function creates a new action with an \a icon
- and some \a text. The function adds the newly created action to
- the menu's list of actions, and returns it.
-
- QMenu takes ownership of the returned QAction.
-
- \sa QWidget::addAction()
-*/
-QAction *QMenu::addAction(const QIcon &icon, const QString &text)
-{
- QAction *ret = new QAction(icon, text, this);
- addAction(ret);
- return ret;
-}
-
-/*!
- \overload
-
- This convenience function creates a new action with the text \a
- text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a receiver's \a member slot. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenu takes ownership of the returned QAction.
-
- \sa QWidget::addAction()
-*/
-QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member
#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut
-#endif
- )
+QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut)
{
- QAction *action = new QAction(text, this);
-#if QT_CONFIG(shortcut)
- action->setShortcut(shortcut);
-#endif
- QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
- addAction(action);
- return action;
+ return QWidget::addAction(text, shortcut, receiver, member);
}
+#endif
-/*!\fn template<typename Functor> QAction *QMenu::addAction(const QString &text, Functor functor, const QKeySequence &shortcut = 0)
+/*!
+ \fn template<typename Functor> QAction *QMenu::addAction(const QString &text, Functor functor, const QKeySequence &shortcut)
\since 5.6
+ \obsolete
- \overload
-
- This convenience function creates a new action with the text \a
- text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenu takes ownership of the returned QAction.
+ Use QWidget::addAction(text, shortcut, functor) instead.
*/
-/*!\fn template<typename Functor> QAction *QMenu::addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut)
+/*!
+ \fn template<typename Functor> QAction *QMenu::addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut)
\since 5.6
+ \obsolete
- \overload
-
- This convenience function creates a new action with the text \a
- text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The functor can be a pointer to a member function of
- the \a context object. The newly created action is added to the
- menu's list of actions and a pointer to it is returned.
-
- If the \a context object is destroyed, the functor will not be called.
-
- QMenu takes ownership of the returned QAction.
+ Use QWidget::addAction(text, shortcut, context, functor) instead.
*/
-/*!\fn template<typename Functor> QAction *QMenu::addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut = 0)
+/*!
+ \fn template<typename Functor> QAction *QMenu::addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
\since 5.6
+ \obsolete
- \overload
-
- This convenience function creates a new action with an \a icon
- and some \a text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenu takes ownership of the returned QAction.
+ Use QWidget::addAction(icon, text, shortcut, functor) instead.
*/
-/*!\fn template<typename Functor> QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut)
+/*!
+ \fn template<typename Functor> QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut)
\since 5.6
+ \obsolete
- \overload
-
- This convenience function creates a new action with an \a icon
- and some \a text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The \a functor can be a pointer to a member function
- of the \a context object. The newly created action is added to the
- menu's list of actions and a pointer to it is returned.
-
- If \a context is destroyed, the functor will not be called.
-
- QMenu takes ownership of the returned QAction.
+ Use QWidget::addAction(icon, text, shortcut, context, functor) instead.
*/
/*!
- \overload
+ \fn QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut)
- This convenience function creates a new action with an \a icon and
- some \a text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a member slot of the \a receiver object. The function adds the
- newly created action to the menu's list of actions, and returns it.
+ \obsolete
- QMenu takes ownership of the returned QAction.
-
- \sa QWidget::addAction()
+ Use QWidget::addAction(icon, text, shortcut, receiver, member) instead.
*/
-QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver,
- const char* member
#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut
-#endif
- )
+QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver,
+ const char* member, const QKeySequence &shortcut)
{
QAction *action = new QAction(icon, text, this);
-#if QT_CONFIG(shortcut)
action->setShortcut(shortcut);
-#endif
QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
addAction(action);
return action;
}
+#endif
+#endif // QT_DEPRECATED_SINCE(6, 4)
/*!
This convenience function adds \a menu as a submenu to this menu.
@@ -2196,7 +2181,7 @@ void QMenu::setActiveAction(QAction *act)
{
Q_D(QMenu);
d->setCurrentAction(act, 0);
- if (d->scroll)
+ if (d->scroll && act)
d->scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollCenter);
}
@@ -2222,7 +2207,7 @@ QAction *QMenu::activeAction() const
bool QMenu::isEmpty() const
{
bool ret = true;
- for(int i = 0; ret && i < actions().count(); ++i) {
+ for(int i = 0; ret && i < actions().size(); ++i) {
const QAction *action = actions().at(i);
if (!action->isSeparator() && action->isVisible()) {
ret = false;
@@ -2243,7 +2228,7 @@ void QMenu::clear()
for(int i = 0; i < acts.size(); i++) {
removeAction(acts[i]);
- if (acts[i]->parent() == this && acts[i]->d_func()->widgets.isEmpty())
+ if (acts[i]->parent() == this && acts[i]->d_func()->associatedObjects.isEmpty())
delete acts[i];
}
}
@@ -2287,7 +2272,7 @@ QSize QMenu::sizeHint() const
d->updateActionRects();
QSize s;
- for (int i = 0; i < d->actionRects.count(); ++i) {
+ for (int i = 0; i < d->actionRects.size(); ++i) {
const QRect &rect = d->actionRects.at(i);
if (rect.isNull())
continue;
@@ -2300,13 +2285,12 @@ QSize QMenu::sizeHint() const
// the top and left margins, so we only need to add margins for
// the bottom and right.
QStyleOption opt(0);
- opt.init(this);
+ opt.initFrom(this);
const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this);
s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this) + fw + d->rightmargin;
s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) + fw + d->bottommargin;
- return style()->sizeFromContents(QStyle::CT_Menu, &opt,
- s.expandedTo(QApplication::globalStrut()), this);
+ return style()->sizeFromContents(QStyle::CT_Menu, &opt, s, this);
}
/*!
@@ -2326,76 +2310,105 @@ QSize QMenu::sizeHint() const
void QMenu::popup(const QPoint &p, QAction *atAction)
{
Q_D(QMenu);
- if (d->scroll) { // reset scroll state from last popup
- if (d->scroll->scrollOffset)
- d->itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll
- d->scroll->scrollOffset = 0;
- d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
+ d->popup(p, atAction);
+}
+
+void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction)
+{
+ Q_Q(QMenu);
+ popupScreen = QGuiApplication::screenAt(p);
+ QScopeGuard popupScreenGuard([this](){ popupScreen.clear(); });
+
+ if (scroll) { // reset scroll state from last popup
+ if (scroll->scrollOffset)
+ itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll
+ scroll->scrollOffset = 0;
+ scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
}
- d->tearoffHighlighted = 0;
- d->motions = 0;
- d->doChildEffects = true;
- d->updateLayoutDirection();
+ tearoffHighlighted = 0;
+ motions = 0;
+ doChildEffects = true;
+ updateLayoutDirection();
+
+ q->ensurePolished(); // Get the right font
// Ensure that we get correct sizeHints by placing this window on the correct screen.
- // However if the QMenu was constructed with a QDesktopScreenWidget as its parent,
+ // However if the QMenu was constructed with a Qt::Desktop widget as its parent,
// then initialScreenIndex was set, so we should respect that for the lifetime of this menu.
- // Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing.
// However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162)
- if (!d->eventLoop) {
- const int screenIndex = d->topData()->initialScreenIndex;
- if (screenIndex >= 0)
- d->popupScreen = screenIndex;
- if (auto s = QGuiApplication::screens().value(d->popupScreen)) {
- if (d->setScreen(s))
- d->itemsDirty = true;
- } else if (d->setScreenForPoint(p)) {
- d->itemsDirty = true;
- }
+ if (!eventLoop) {
+ bool screenSet = false;
+ QScreen *screen = topData()->initialScreen;
+ if (screen) {
+ if (setScreen(screen))
+ itemsDirty = true;
+ screenSet = true;
+ } else if (QMenu *parentMenu = qobject_cast<QMenu *>(parent)) {
+ // a submenu is always opened from an open parent menu,
+ // so show it on the same screen where the parent is. (QTBUG-76162)
+ if (setScreen(parentMenu->screen()))
+ itemsDirty = true;
+ screenSet = true;
+ }
+ if (!screenSet && setScreenForPoint(p))
+ itemsDirty = true;
+ }
+
+ const bool contextMenu = isContextMenu();
+ if (lastContextMenu != contextMenu) {
+ itemsDirty = true;
+ lastContextMenu = contextMenu;
}
- const bool contextMenu = d->isContextMenu();
- if (d->lastContextMenu != contextMenu) {
- d->itemsDirty = true;
- d->lastContextMenu = contextMenu;
+ // Until QWidget::metric accepts the screen set on a widget (without having a window handle)
+ // we need to make sure we get a window handle. This must be done near here because
+ // we want the screen to be correctly set and items to be marked dirty.
+ // (and screen set could 'fail' on oldscreen == newScreen if created before causing the
+ // itemsDirty not to be set though needed to get the correct size on first show).
+ if (!windowHandle()) {
+ createWinId();
}
#if QT_CONFIG(menubar)
// if this menu is part of a chain attached to a QMenuBar, set the
// _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type
- setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(d->topCausedWidget()) != 0);
+ q->setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(topCausedWidget()) != nullptr);
#endif
- ensurePolished(); // Get the right font
- emit aboutToShow();
- const bool actionListChanged = d->itemsDirty;
+ emit q->aboutToShow();
+ const bool actionListChanged = itemsDirty;
QRect screen;
#if QT_CONFIG(graphicsview)
- bool isEmbedded = !bypassGraphicsProxyWidget(this) && QMenuPrivate::nearestGraphicsProxyWidget(this);
+ bool isEmbedded = !bypassGraphicsProxyWidget(q) && QMenuPrivate::nearestGraphicsProxyWidget(q);
if (isEmbedded)
- screen = d->popupGeometry();
+ screen = popupGeometry();
else
#endif
- screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(p));
- d->updateActionRects(screen);
+ screen = popupGeometry(QGuiApplication::screenAt(p));
+ updateActionRects(screen);
QPoint pos;
- QPushButton *causedButton = qobject_cast<QPushButton*>(d->causedPopup.widget);
+ QPushButton *causedButton = qobject_cast<QPushButton*>(causedPopup.widget);
if (actionListChanged && causedButton)
pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition();
else
pos = p;
+ popupScreen = QGuiApplication::screenAt(pos);
- const QSize menuSizeHint(sizeHint());
+ const QSize menuSizeHint(q->sizeHint());
QSize size = menuSizeHint;
- const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, this);
- bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+
+ if (positionFunction)
+ pos = positionFunction(menuSizeHint);
+
+ const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
+ bool adjustToDesktop = !q->window()->testAttribute(Qt::WA_DontShowOnScreen);
// if the screens have very different geometries and the menu is too big, we have to recalculate
if ((size.height() > screen.height() || size.width() > screen.width()) ||
// Layout is not right, we might be able to save horizontal space
- (d->ncols >1 && size.height() < screen.height())) {
+ (ncols >1 && size.height() < screen.height())) {
size.setWidth(qMin(menuSizeHint.width(), screen.width() - desktopFrame * 2));
size.setHeight(qMin(menuSizeHint.height(), screen.height() - desktopFrame * 2));
adjustToDesktop = true;
@@ -2404,61 +2417,61 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
#ifdef QT_KEYPAD_NAVIGATION
if (!atAction && QApplicationPrivate::keypadNavigationEnabled()) {
// Try to have one item activated
- if (d->defaultAction && d->defaultAction->isEnabled()) {
- atAction = d->defaultAction;
+ if (defaultAction && defaultAction->isEnabled()) {
+ atAction = defaultAction;
// TODO: This works for first level menus, not yet sub menus
} else {
- for (QAction *action : qAsConst(d->actions))
+ for (QAction *action : std::as_const(actions))
if (action->isEnabled()) {
atAction = action;
break;
}
}
- d->currentAction = atAction;
+ currentAction = atAction;
}
#endif
- if (d->ncols > 1) {
+ if (ncols > 1) {
pos.setY(screen.top() + desktopFrame);
} else if (atAction) {
- for (int i = 0, above_height = 0; i < d->actions.count(); i++) {
- QAction *action = d->actions.at(i);
+ for (int i = 0, above_height = 0; i < actions.size(); i++) {
+ QAction *action = actions.at(i);
if (action == atAction) {
int newY = pos.y() - above_height;
- if (d->scroll && newY < desktopFrame) {
- d->scroll->scrollFlags = d->scroll->scrollFlags
+ if (scroll && newY < desktopFrame) {
+ scroll->scrollFlags = scroll->scrollFlags
| QMenuPrivate::QMenuScroller::ScrollUp;
- d->scroll->scrollOffset = newY;
+ scroll->scrollOffset = newY;
newY = desktopFrame;
}
pos.setY(newY);
- if (d->scroll && d->scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone
- && !style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, nullptr, this)) {
- int below_height = above_height + d->scroll->scrollOffset;
- for (int i2 = i; i2 < d->actionRects.count(); i2++)
- below_height += d->actionRects.at(i2).height();
+ if (scroll && scroll->scrollFlags != QMenuPrivate::QMenuScroller::ScrollNone
+ && !q->style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, nullptr, q)) {
+ int below_height = above_height + scroll->scrollOffset;
+ for (int i2 = i; i2 < actionRects.size(); i2++)
+ below_height += actionRects.at(i2).height();
size.setHeight(below_height);
}
break;
} else {
- above_height += d->actionRects.at(i).height();
+ above_height += actionRects.at(i).height();
}
}
}
QPoint mouse = QCursor::pos();
- d->mousePopupPos = mouse;
- const bool snapToMouse = !d->causedPopup.widget && (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse));
+ mousePopupPos = mouse;
+ const bool snapToMouse = !causedPopup.widget && (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse));
if (adjustToDesktop) {
// handle popup falling "off screen"
- if (isRightToLeft()) {
+ if (q->isRightToLeft()) {
if (snapToMouse) // position flowing left from the mouse
pos.setX(mouse.x() - size.width());
#if QT_CONFIG(menubar)
// if the menu is in a menubar or is a submenu, it should be right-aligned
- if (qobject_cast<QMenuBar*>(d->causedPopup.widget) || qobject_cast<QMenu*>(d->causedPopup.widget))
+ if (qobject_cast<QMenuBar*>(causedPopup.widget) || qobject_cast<QMenu*>(causedPopup.widget))
pos.rx() -= size.width();
#endif // QT_CONFIG(menubar)
@@ -2473,7 +2486,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
pos.setX(screen.left() + desktopFrame);
}
if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
- if(snapToMouse)
+ if (snapToMouse)
pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
else
pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
@@ -2482,8 +2495,8 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (pos.y() < screen.top() + desktopFrame)
pos.setY(screen.top() + desktopFrame);
if (pos.y() + menuSizeHint.height() - 1 > screen.bottom() - desktopFrame) {
- if (d->scroll) {
- d->scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown);
+ if (scroll) {
+ scroll->scrollFlags |= uint(QMenuPrivate::QMenuScroller::ScrollDown);
int y = qMax(screen.y(),pos.y());
size.setHeight(screen.bottom() - (desktopFrame * 2) - y);
} else {
@@ -2492,13 +2505,13 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
}
}
- const int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, this);
- QMenu *caused = qobject_cast<QMenu*>(d_func()->causedPopup.widget);
+ const int subMenuOffset = q->style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, q);
+ QMenu *caused = qobject_cast<QMenu*>(causedPopup.widget);
if (caused && caused->geometry().width() + menuSizeHint.width() + subMenuOffset < screen.width()) {
QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft());
parentActionRect.moveTopLeft(actionTopLeft);
- if (isRightToLeft()) {
+ if (q->isRightToLeft()) {
if ((pos.x() + menuSizeHint.width() > parentActionRect.left() - subMenuOffset)
&& (pos.x() < parentActionRect.right()))
{
@@ -2520,61 +2533,62 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
}
}
- setGeometry(QRect(pos, size));
+ popupScreen = QGuiApplication::screenAt(pos);
+ q->setGeometry(QRect(pos, size));
#if QT_CONFIG(effects)
- int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
+ int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
int vGuess = QEffects::DownScroll;
- if (isRightToLeft()) {
+ if (q->isRightToLeft()) {
if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) ||
- (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 > d->causedPopup.widget->x()))
+ (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 > causedPopup.widget->x()))
hGuess = QEffects::RightScroll;
} else {
if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) ||
- (qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width() / 2 < d->causedPopup.widget->x()))
+ (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 < causedPopup.widget->x()))
hGuess = QEffects::LeftScroll;
}
#if QT_CONFIG(menubar)
if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) ||
- (qobject_cast<QMenuBar*>(d->causedPopup.widget) &&
- pos.y() + size.width() / 2 < d->causedPopup.widget->mapToGlobal(d->causedPopup.widget->pos()).y()))
+ (qobject_cast<QMenuBar*>(causedPopup.widget) &&
+ pos.y() + size.width() / 2 < causedPopup.widget->mapToGlobal(causedPopup.widget->pos()).y()))
vGuess = QEffects::UpScroll;
#endif
if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu)) {
bool doChildEffects = true;
#if QT_CONFIG(menubar)
- if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget)) {
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(causedPopup.widget)) {
doChildEffects = mb->d_func()->doChildEffects;
mb->d_func()->doChildEffects = false;
} else
#endif
- if (QMenu *m = qobject_cast<QMenu*>(d->causedPopup.widget)) {
+ if (QMenu *m = qobject_cast<QMenu*>(causedPopup.widget)) {
doChildEffects = m->d_func()->doChildEffects;
m->d_func()->doChildEffects = false;
}
if (doChildEffects) {
if (QApplication::isEffectEnabled(Qt::UI_FadeMenu))
- qFadeEffect(this);
- else if (d->causedPopup.widget)
- qScrollEffect(this, qobject_cast<QMenu*>(d->causedPopup.widget) ? hGuess : vGuess);
+ qFadeEffect(q);
+ else if (causedPopup.widget)
+ qScrollEffect(q, qobject_cast<QMenu*>(causedPopup.widget) ? hGuess : vGuess);
else
- qScrollEffect(this, hGuess | vGuess);
+ qScrollEffect(q, hGuess | vGuess);
} else {
// kill any running effect
qFadeEffect(nullptr);
qScrollEffect(nullptr);
- show();
+ q->show();
}
} else
#endif
{
- show();
+ q->show();
}
-#ifndef QT_NO_ACCESSIBILITY
- QAccessibleEvent event(this, QAccessible::PopupMenuStart);
+#if QT_CONFIG(accessibility)
+ QAccessibleEvent event(q, QAccessible::PopupMenuStart);
QAccessible::updateAccessibility(&event);
#endif
}
@@ -2640,20 +2654,27 @@ QAction *QMenu::exec()
QAction *QMenu::exec(const QPoint &p, QAction *action)
{
Q_D(QMenu);
- ensurePolished();
- createWinId();
- QEventLoop eventLoop;
- d->eventLoop = &eventLoop;
- popup(p, action);
-
- QPointer<QObject> guard = this;
- (void) eventLoop.exec();
+ return d->exec(p, action);
+}
+
+QAction *QMenuPrivate::exec(const QPoint &p, QAction *action, PositionFunction positionFunction)
+{
+ Q_Q(QMenu);
+ q->ensurePolished();
+ q->createWinId();
+ QEventLoop evtLoop;
+ eventLoop = &evtLoop;
+ popup(p, action, positionFunction);
+
+ QPointer<QObject> guard = q;
+ (void) evtLoop.exec();
if (guard.isNull())
return nullptr;
- action = d->syncAction;
- d->syncAction = nullptr;
- d->eventLoop = nullptr;
+ action = syncAction;
+ syncAction = nullptr;
+ eventLoop = nullptr;
+ popupScreen.clear();
return action;
}
@@ -2679,11 +2700,7 @@ QAction *QMenu::exec(const QPoint &p, QAction *action)
\sa popup(), QWidget::mapToGlobal()
*/
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QAction *QMenu::exec(const QList<QAction *> &actions, const QPoint &pos, QAction *at, QWidget *parent)
-#else
-QAction *QMenu::exec(QList<QAction*> actions, const QPoint &pos, QAction *at, QWidget *parent)
-#endif
{
QMenu menu(parent);
menu.addActions(actions);
@@ -2700,7 +2717,7 @@ void QMenu::hideEvent(QHideEvent *)
if (d->eventLoop)
d->eventLoop->exit();
d->setCurrentAction(nullptr);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::PopupMenuEnd);
QAccessible::updateAccessibility(&event);
#endif
@@ -2726,7 +2743,7 @@ void QMenu::paintEvent(QPaintEvent *e)
{
Q_D(QMenu);
d->updateActionRects();
- QPainter p(this);
+ QStylePainter p(this);
QRegion emptyArea = QRegion(rect());
QStyleOptionMenuItem menuOpt;
@@ -2734,8 +2751,8 @@ void QMenu::paintEvent(QPaintEvent *e)
menuOpt.state = QStyle::State_None;
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.maxIconWidth = 0;
- menuOpt.tabWidth = 0;
- style()->drawPrimitive(QStyle::PE_PanelMenu, &menuOpt, &p, this);
+ menuOpt.reservedShortcutWidth = 0;
+ p.drawPrimitive(QStyle::PE_PanelMenu, menuOpt);
//calculate the scroll up / down rect
const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this);
@@ -2767,7 +2784,7 @@ void QMenu::paintEvent(QPaintEvent *e)
//draw the items that need updating..
QRect scrollUpTearOffRect = scrollUpRect.united(tearOffRect);
- for (int i = 0; i < d->actions.count(); ++i) {
+ for (int i = 0; i < d->actions.size(); ++i) {
QAction *action = d->actions.at(i);
QRect actionRect = d->actionRects.at(i);
if (!e->rect().intersects(actionRect)
@@ -2803,7 +2820,7 @@ void QMenu::paintEvent(QPaintEvent *e)
QStyleOptionMenuItem opt;
initStyleOption(&opt, action);
opt.rect = actionRect;
- style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
+ p.drawControl(QStyle::CE_MenuItem, opt);
}
emptyArea -= QRegion(scrollUpTearOffRect);
@@ -2835,9 +2852,9 @@ void QMenu::paintEvent(QPaintEvent *e)
frame.rect = rect();
frame.palette = palette();
frame.state = QStyle::State_None;
- frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth);
+ frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &frame, this);
frame.midLineWidth = 0;
- style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, &p, this);
+ p.drawPrimitive(QStyle::PE_FrameMenu, frame);
}
//finally the rest of the spaces
@@ -2847,7 +2864,7 @@ void QMenu::paintEvent(QPaintEvent *e)
menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
menuOpt.rect = rect();
menuOpt.menuRect = rect();
- style()->drawControl(QStyle::CE_MenuEmptyArea, &menuOpt, &p, this);
+ p.drawControl(QStyle::CE_MenuEmptyArea, menuOpt);
}
#if QT_CONFIG(wheelevent)
@@ -2875,9 +2892,9 @@ void QMenu::mousePressEvent(QMouseEvent *e)
// and mouse clicks on second screen, e->pos() is QPoint(0,0) and the menu doesn't hide. This trick makes
// possible to hide the menu when mouse clicks on another screen (e->screenPos() returns correct value).
// Only when mouse clicks in QPoint(0,0) on second screen, the menu doesn't hide.
- if ((e->pos().isNull() && !e->screenPos().isNull()) || !rect().contains(e->pos())) {
+ if ((e->position().toPoint().isNull() && !e->globalPosition().isNull()) || !rect().contains(e->position().toPoint())) {
if (d->noReplayFor
- && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPos()))
+ && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPosition().toPoint()))
setAttribute(Qt::WA_NoMouseReplay);
if (d->eventLoop) // synchronous operation
d->syncAction = nullptr;
@@ -2886,7 +2903,7 @@ void QMenu::mousePressEvent(QMouseEvent *e)
}
QMenuPrivate::mouseDown = this;
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
d->setCurrentAction(action, 20);
update();
}
@@ -2906,17 +2923,17 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
QMenuPrivate::mouseDown = nullptr;
d->setSyncAction();
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
if (action && action == d->currentAction) {
- if (!action->menu()){
+ if (!action->menu()) {
#if defined(Q_OS_WIN)
//On Windows only context menus can be activated with the right button
if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
#endif
d->activateAction(action, QAction::Trigger);
}
- } else if ((!action || action->isEnabled()) && d->hasMouseMoved(e->globalPos())) {
+ } else if ((!action || action->isEnabled()) && d->hasMouseMoved(e->globalPosition().toPoint())) {
d->hideUpToMenuBar();
}
}
@@ -2954,8 +2971,7 @@ void QMenu::changeEvent(QEvent *e)
/*!
\reimp
*/
-bool
-QMenu::event(QEvent *e)
+bool QMenu::event(QEvent *e)
{
Q_D(QMenu);
switch (e->type()) {
@@ -2963,7 +2979,7 @@ QMenu::event(QEvent *e)
d->updateLayoutDirection();
break;
case QEvent::ShortcutOverride: {
- QKeyEvent *kev = static_cast<QKeyEvent*>(e);
+ QKeyEvent *kev = static_cast<QKeyEvent *>(e);
if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down
|| kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right
|| kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return
@@ -2977,7 +2993,7 @@ QMenu::event(QEvent *e)
}
break;
case QEvent::KeyPress: {
- QKeyEvent *ke = (QKeyEvent*)e;
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
keyPressEvent(ke);
return true;
@@ -3010,8 +3026,10 @@ QMenu::event(QEvent *e)
d->sloppyState.reset();
if (d->currentAction)
d->popupAction(d->currentAction, 0, false);
+ if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent())
+ window()->windowHandle()->setTransientParent(d->transientParentWindow());
break;
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
case QEvent::ToolTip:
if (d->toolTipsVisible) {
const QHelpEvent *ev = static_cast<const QHelpEvent*>(e);
@@ -3019,11 +3037,13 @@ QMenu::event(QEvent *e)
const QString toolTip = action->d_func()->tooltip;
if (!toolTip.isEmpty())
QToolTip::showText(ev->globalPos(), toolTip, this);
+ else
+ QToolTip::hideText();
return true;
}
}
break;
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(whatsthis)
case QEvent::QueryWhatsThis:
e->setAccepted(d->whatsThis.size());
@@ -3086,7 +3106,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
case Qt::Key_PageUp:
key_consumed = true;
if (d->currentAction && d->scroll) {
- if(d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
+ if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollUp, true, true);
else
d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
@@ -3095,7 +3115,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
case Qt::Key_PageDown:
key_consumed = true;
if (d->currentAction && d->scroll) {
- if(d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
+ if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollDown, true, true);
else
d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollBottom, true);
@@ -3107,8 +3127,8 @@ void QMenu::keyPressEvent(QKeyEvent *e)
QAction *nextAction = nullptr;
QMenuPrivate::QMenuScroller::ScrollLocation scroll_loc = QMenuPrivate::QMenuScroller::ScrollStay;
if (!d->currentAction) {
- if(key == Qt::Key_Down) {
- for(int i = 0; i < d->actions.count(); ++i) {
+ if (key == Qt::Key_Down) {
+ for(int i = 0; i < d->actions.size(); ++i) {
QAction *act = d->actions.at(i);
if (d->actionRects.at(i).isNull())
continue;
@@ -3120,7 +3140,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
}
}
} else {
- for(int i = d->actions.count()-1; i >= 0; --i) {
+ for(int i = d->actions.size()-1; i >= 0; --i) {
QAction *act = d->actions.at(i);
if (d->actionRects.at(i).isNull())
continue;
@@ -3133,7 +3153,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
}
}
} else {
- for(int i = 0, y = 0; !nextAction && i < d->actions.count(); i++) {
+ for(int i = 0, y = 0; !nextAction && i < d->actions.size(); i++) {
QAction *act = d->actions.at(i);
if (act == d->currentAction) {
if (key == Qt::Key_Up) {
@@ -3143,7 +3163,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
break;
if (d->scroll)
scroll_loc = QMenuPrivate::QMenuScroller::ScrollBottom;
- next_i = d->actionRects.count()-1;
+ next_i = d->actionRects.size()-1;
}
QAction *next = d->actions.at(next_i);
if (next == d->currentAction)
@@ -3169,7 +3189,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
} else {
y += d->actionRects.at(i).height();
for(int next_i = i+1; true; next_i++) {
- if (next_i == d->actionRects.count()) {
+ if (next_i == d->actionRects.size()) {
if (!style()->styleHint(QStyle::SH_Menu_SelectionWrap, nullptr, this))
break;
if (d->scroll)
@@ -3326,7 +3346,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
if (!key_consumed) { // send to menu bar
if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) &&
- e->text().length()==1) {
+ e->text().size()==1) {
bool activateAction = false;
QAction *nextAction = nullptr;
if (style()->styleHint(QStyle::SH_Menu_KeyboardSearch, nullptr, this) && !e->modifiers()) {
@@ -3340,10 +3360,10 @@ void QMenu::keyPressEvent(QKeyEvent *e)
QAction *act = d->actions.at(i);
const QString act_text = act->text();
for(int c = 0; c < d->searchBuffer.size(); ++c) {
- if(act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
+ if (act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
++match_count;
}
- if(match_count > best_match_count) {
+ if (match_count > best_match_count) {
best_match_count = match_count;
nextAction = act;
}
@@ -3359,7 +3379,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
continue;
QAction *act = d->actions.at(i);
QKeySequence sequence = QKeySequence::mnemonic(act->text());
- int key = sequence[0] & 0xffff;
+ int key = sequence[0].toCombined() & 0xffff; // suspicious
if (key == c.unicode()) {
clashCount++;
if (!first)
@@ -3382,7 +3402,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
#endif
if (nextAction) {
key_consumed = true;
- if(d->scroll)
+ if (d->scroll)
d->scrollMenu(nextAction, QMenuPrivate::QMenuScroller::ScrollCenter, false);
d->setCurrentAction(nextAction, 0, QMenuPrivate::SelectedFromElsewhere, true);
if (!nextAction->menu() && activateAction) {
@@ -3423,12 +3443,12 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
return;
d->motions++;
- if (d->motions == 0)
+ if (!d->hasMouseMoved(e->globalPosition().toPoint()))
return;
- d->hasHadMouse = d->hasHadMouse || rect().contains(e->pos());
+ d->hasHadMouse = d->hasHadMouse || rect().contains(e->position().toPoint());
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
if ((!action || action->isSeparator()) && !d->sloppyState.enabled()) {
if (d->hasHadMouse
|| (!d->currentAction || !d->currentAction->menu() || !d->currentAction->menu()->isVisible())) {
@@ -3443,7 +3463,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
if (d->activeMenu)
d->activeMenu->d_func()->setCurrentAction(nullptr);
- QMenuSloppyState::MouseEventResult sloppyEventResult = d->sloppyState.processMouseEvent(e->localPos(), action, d->currentAction);
+ QMenuSloppyState::MouseEventResult sloppyEventResult = d->sloppyState.processMouseEvent(e->position(), action, d->currentAction);
if (sloppyEventResult == QMenuSloppyState::EventShouldBePropagated) {
d->setCurrentAction(action, d->mousePopupDelay);
} else if (sloppyEventResult == QMenuSloppyState::EventDiscardsSloppyState) {
@@ -3455,7 +3475,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
/*!
\reimp
*/
-void QMenu::enterEvent(QEvent *)
+void QMenu::enterEvent(QEnterEvent *)
{
Q_D(QMenu);
d->hasReceievedEnter = true;
@@ -3493,7 +3513,7 @@ QMenu::timerEvent(QTimerEvent *e)
internalDelayedPopup();
} else if (d->sloppyState.isTimerId(e->timerId())) {
d->sloppyState.timeout();
- } else if(d->searchBufferTimer.timerId() == e->timerId()) {
+ } else if (d->searchBufferTimer.timerId() == e->timerId()) {
d->searchBuffer.clear();
}
}
@@ -3511,7 +3531,10 @@ void QMenu::actionEvent(QActionEvent *e)
if (e->type() == QEvent::ActionAdded) {
if (!d->tornoff
- && !qobject_cast<QMenuBar*>(e->action()->parent())) {
+#if QT_CONFIG(menubar)
+ && !qobject_cast<QMenuBar*>(e->action()->parent())
+#endif
+ ) {
// Only connect if the action was not directly added by QMenuBar::addAction(const QString &text)
// to avoid the signal being emitted twice
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()), Qt::UniqueConnection);
@@ -3536,19 +3559,8 @@ void QMenu::actionEvent(QActionEvent *e)
if (e->action() == d->currentAction)
d->currentAction = nullptr;
if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
- if (QWidget *widget = d->widgetItems.value(wa)) {
-#ifdef Q_OS_OSX
- QWidget *p = widget->parentWidget();
- if (p != this && qobject_cast<QMacNativeWidget *>(p)) {
- // This widget was reparented into a native Mac view
- // (see QMenuPrivate::moveWidgetToPlatformItem).
- // Reset the parent and delete the native widget.
- widget->setParent(this);
- p->deleteLater();
- }
-#endif
+ if (QWidget *widget = d->widgetItems.value(wa))
wa->releaseWidget(widget);
- }
}
d->widgetItems.remove(static_cast<QAction *>(e->action()));
}
@@ -3609,13 +3621,13 @@ void QMenu::internalDelayedPopup()
screen = d->popupGeometry();
else
#endif
- screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(pos()));
+ screen = d->popupGeometry(QGuiApplication::screenAt(pos()));
int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, this);
const QRect actionRect(d->actionRect(d->currentAction));
QPoint subMenuPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
if (subMenuPos.x() > screen.right())
- subMenuPos.setX(QCursor::pos().x());
+ subMenuPos.setX(geometry().left());
const auto &subMenuActions = d->activeMenu->actions();
if (!subMenuActions.isEmpty()) {
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 35d5a865ff..33ebd79d1f 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMENU_H
#define QMENU_H
@@ -44,9 +8,9 @@
#include <QtWidgets/qwidget.h>
#include <QtCore/qstring.h>
#include <QtGui/qicon.h>
-#include <QtWidgets/qaction.h>
+#include <QtGui/qaction.h>
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
Q_FORWARD_DECLARE_OBJC_CLASS(NSMenu);
#endif
@@ -76,96 +40,75 @@ public:
~QMenu();
using QWidget::addAction;
+#if QT_WIDGETS_REMOVED_SINCE(6, 3)
QAction *addAction(const QString &text);
QAction *addAction(const QIcon &icon, const QString &text);
-
- QAction *addAction(const QString &text, const QObject *receiver, const char* member
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
+#if !QT_CONFIG(shortcut)
+ QAction *addAction(const QString &text, const QObject *receiver, const char* member);
+ QAction *addAction(const QIcon &icon, const QString &text,
+ const QObject *receiver, const char* member);
#endif
- );
- QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
#endif
- );
-#ifdef Q_CLANG_QDOC
+#if QT_CONFIG(shortcut)
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(text, shortcut, receiver, member) instead.")
+ QAction *addAction(const QString &text, const QObject *receiver, const char* member,
+ const QKeySequence &shortcut);
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(icon, text, shortcut, receiver, member) instead.")
+ QAction *addAction(const QIcon &icon, const QString &text,
+ const QObject *receiver, const char* member,
+ const QKeySequence &shortcut);
+
+#ifdef Q_QDOC
template<typename Functor>
- QAction *addAction(const QString &text, Functor functor, const QKeySequence &shortcut = 0);
+ QAction *addAction(const QString &text, Functor functor, const QKeySequence &shortcut);
template<typename Functor>
- QAction *addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut = 0);
+ QAction *addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut);
template<typename Functor>
- QAction *addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut = 0);
+ QAction *addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut);
template<typename Functor>
- QAction *addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut = 0);
+ QAction *addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut);
#else
// addAction(QString): Connect to a QObject slot / functor or function pointer (with context)
template<class Obj, typename Func1>
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(text, shortcut, object, slot) instead.")
inline typename std::enable_if<!std::is_same<const char*, Func1>::value
&& QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type
- addAction(const QString &text, const Obj *object, Func1 slot
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
-#endif
- )
+ addAction(const QString &text, const Obj *object, Func1 slot,
+ const QKeySequence &shortcut)
{
- QAction *result = addAction(text);
-#if QT_CONFIG(shortcut)
- result->setShortcut(shortcut);
-#endif
- connect(result, &QAction::triggered, object, std::move(slot));
- return result;
+ return addAction(text, shortcut, object, slot);
}
// addAction(QString): Connect to a functor or function pointer (without context)
template <typename Func1>
- inline QAction *addAction(const QString &text, Func1 slot
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
-#endif
- )
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(text, shortcut, slot) instead.")
+ inline QAction *addAction(const QString &text, Func1 slot, const QKeySequence &shortcut)
{
- QAction *result = addAction(text);
-#if QT_CONFIG(shortcut)
- result->setShortcut(shortcut);
-#endif
- connect(result, &QAction::triggered, std::move(slot));
- return result;
+ return addAction(text, shortcut, slot);
}
// addAction(QIcon, QString): Connect to a QObject slot / functor or function pointer (with context)
template<class Obj, typename Func1>
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(icon, text, shortcut, object, slot) instead.")
inline typename std::enable_if<!std::is_same<const char*, Func1>::value
&& QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type
- addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
-#endif
- )
+ addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot,
+ const QKeySequence &shortcut)
{
- QAction *result = addAction(actionIcon, text);
-#if QT_CONFIG(shortcut)
- result->setShortcut(shortcut);
-#endif
- connect(result, &QAction::triggered, object, std::move(slot));
- return result;
+ return addAction(actionIcon, text, shortcut, object, slot);
}
// addAction(QIcon, QString): Connect to a functor or function pointer (without context)
template <typename Func1>
- inline QAction *addAction(const QIcon &actionIcon, const QString &text, Func1 slot
-#if QT_CONFIG(shortcut)
- , const QKeySequence &shortcut = {}
-#endif
- )
+ QT_DEPRECATED_VERSION_X_6_4("Use addAction(icon, text, shortcut, slot) instead.")
+ inline QAction *addAction(const QIcon &actionIcon, const QString &text, Func1 slot,
+ const QKeySequence &shortcut)
{
- QAction *result = addAction(actionIcon, text);
-#if QT_CONFIG(shortcut)
- result->setShortcut(shortcut);
-#endif
- connect(result, &QAction::triggered, std::move(slot));
- return result;
+ return addAction(actionIcon, text, shortcut, slot);
}
-#endif // !Q_CLANG_QDOC
+#endif // !Q_QDOC
+#endif // QT_DEPRECATED_SINCE(6, 4)
+#endif // QT_CONFIG(shortcut)
QAction *addMenu(QMenu *menu);
QMenu *addMenu(const QString &title);
@@ -202,11 +145,7 @@ public:
QAction *exec();
QAction *exec(const QPoint &pos, QAction *at = nullptr);
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
static QAction *exec(const QList<QAction *> &actions, const QPoint &pos, QAction *at = nullptr, QWidget *parent = nullptr);
-#else
- static QAction *exec(QList<QAction*> actions, const QPoint &pos, QAction *at = nullptr, QWidget *parent = nullptr);
-#endif
QSize sizeHint() const override;
@@ -214,6 +153,8 @@ public:
QAction *actionAt(const QPoint &) const;
QAction *menuAction() const;
+ static QMenu *menuInAction(const QAction *action)
+ { return qobject_cast<QMenu *>(action->menuObject()); }
QString title() const;
void setTitle(const QString &title);
@@ -225,7 +166,7 @@ public:
QPlatformMenu *platformMenu();
void setPlatformMenu(QPlatformMenu *platformMenu);
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
NSMenu* toNSMenu();
void setAsDockMenu();
#endif
@@ -253,7 +194,7 @@ protected:
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *) override;
#endif
- void enterEvent(QEvent *) override;
+ void enterEvent(QEnterEvent *) override;
void leaveEvent(QEvent *) override;
void hideEvent(QHideEvent *) override;
void paintEvent(QPaintEvent *) override;
@@ -261,7 +202,7 @@ protected:
void timerEvent(QTimerEvent *) override;
bool event(QEvent *) override;
bool focusNextPrevChild(bool next) override;
- void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
+ virtual void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
private Q_SLOTS:
void internalDelayedPopup();
@@ -282,17 +223,12 @@ private:
friend class QMenuBarPrivate;
friend class QTornOffMenu;
friend class QComboBox;
- friend class QAction;
+ friend class QtWidgetsActionPrivate;
friend class QToolButtonPrivate;
friend void qt_mac_emit_menuSignals(QMenu *menu, bool show);
friend void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action);
};
-#ifdef Q_OS_OSX
-// ### Qt 4 compatibility; remove in Qt 6
-inline QT_DEPRECATED void qt_mac_set_dock_menu(QMenu *menu) { menu->setAsDockMenu(); }
-#endif
-
QT_END_NAMESPACE
#endif // QMENU_H
diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm
index 0872da803d..184386a731 100644
--- a/src/widgets/widgets/qmenu_mac.mm
+++ b/src/widgets/widgets/qmenu_mac.mm
@@ -1,77 +1,31 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
+#include <qtwidgetsglobal.h>
+
+QT_USE_NAMESPACE
+
#include "qmenu.h"
#if QT_CONFIG(menubar)
#include "qmenubar.h"
#include "qmenubar_p.h"
#endif
-#include "qmacnativewidget_mac.h"
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformmenu_p.h>
+
+using namespace QNativeInterface::Private;
QT_BEGIN_NAMESPACE
#if QT_CONFIG(menu)
-namespace {
-// TODO use QtMacExtras copy of this function when available.
-inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePlatformFunction(const QByteArray &functionName)
-{
- QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
- nativeInterface->nativeResourceFunctionForIntegration(functionName);
- if (Q_UNLIKELY(!function))
- qWarning("Qt could not resolve function %s from "
- "QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration()",
- functionName.constData());
- return function;
-}
-} //namespsace
-
-
/*!
\fn NSMenu *QMenu::toNSMenu()
\since 5.2
@@ -84,12 +38,9 @@ inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePla
NSMenu *QMenu::toNSMenu()
{
Q_D(QMenu);
- // Call into the cocoa platform plugin: qMenuToNSMenu(platformMenu())
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("qmenutonsmenu");
- if (function) {
- typedef void* (*QMenuToNSMenuFunction)(QPlatformMenu *platformMenu);
- return reinterpret_cast<NSMenu *>(reinterpret_cast<QMenuToNSMenuFunction>(function)(d->createPlatformMenu()));
- }
+ if (auto *cocoaPlatformMenu = dynamic_cast<QCocoaMenu *>(d->createPlatformMenu()))
+ return cocoaPlatformMenu->nsMenu();
+
return nil;
}
@@ -104,46 +55,46 @@ NSMenu *QMenu::toNSMenu()
void QMenu::setAsDockMenu()
{
Q_D(QMenu);
- // Call into the cocoa platform plugin: setDockMenu(platformMenu())
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("setdockmenu");
- if (function) {
- typedef void (*SetDockMenuFunction)(QPlatformMenu *platformMenu);
- reinterpret_cast<SetDockMenuFunction>(function)(d->createPlatformMenu());
- }
+ if (auto *cocoaPlatformMenu = dynamic_cast<QCocoaMenu *>(d->createPlatformMenu()))
+ cocoaPlatformMenu->setAsDockMenu();
}
-
-/*! \fn void qt_mac_set_dock_menu(QMenu *menu)
- \relates QMenu
- \deprecated
-
- Sets this \a menu to be the dock menu available by option-clicking
- on the application dock icon. Available on \macos only.
-
- Deprecated; use \l QMenu::setAsDockMenu() instead.
-*/
-
void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* item)
{
- QMacNativeWidget *container = new QMacNativeWidget;
- QObject::connect(platformMenu, SIGNAL(destroyed()), container, SLOT(deleteLater()));
- container->resize(widget->sizeHint());
- widget->setParent(container);
- widget->setVisible(true);
-
- NSView *containerView = container->nativeView();
- QWindow *containerWindow = container->windowHandle();
- Qt::WindowFlags wf = containerWindow->flags();
- containerWindow->setFlags(wf | Qt::SubWindow);
- [(NSView *)widget->winId() setAutoresizingMask:NSViewWidthSizable];
-
- if (QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("setEmbeddedInForeignView")) {
- typedef void (*SetEmbeddedInForeignViewFunction)(QPlatformWindow *window, bool embedded);
- reinterpret_cast<SetEmbeddedInForeignViewFunction>(function)(containerWindow->handle(), true);
- }
-
- item->setNativeContents((WId)containerView);
- container->show();
+ // Hide the widget before we mess with it
+ widget->hide();
+
+ // Move out of QMenu, since this widget will live in the native menu item
+ widget->setParent(nullptr);
+
+ // Make sure the widget doesn't prevent quitting the application,
+ // just because it's a parent-less (top level) window.
+ widget->setAttribute(Qt::WA_QuitOnClose, false);
+
+ // And that it blends nicely with the native menu background
+ widget->setAttribute(Qt::WA_TranslucentBackground);
+
+ // Trigger creation of the backing QWindow, the platform window, and its
+ // underlying NSView and NSWindow. At this point the widget is still hidden,
+ // so the corresponding NSWindow that is created is not shown.
+ widget->setAttribute(Qt::WA_NativeWindow);
+ QWindow *widgetWindow = widget->windowHandle();
+ widgetWindow->create();
+
+ // Inform the window that it's actually a sub-window. This
+ // ensures that we dispose of the NSWindow when the widget is
+ // finally shown. We need to do this on a QWindow level, as
+ // QWidget will ignore the flag if there is no parentWidget().
+ // And we need to do it after creating the platform window, as
+ // QWidget will overwrite the window flags during creation.
+ widgetWindow->setFlag(Qt::SubWindow);
+
+ // Finally, we can associate the underlying NSView with the menu item,
+ // and show it. This will dispose of the created NSWindow, due to
+ // the Qt::SubWindow flag above. The widget will not actually be
+ // visible until it's re-parented into the NSMenu hierarchy.
+ item->setNativeContents(WId(widgetWindow->winId()));
+ widget->show();
}
#endif // QT_CONFIG(menu)
@@ -161,12 +112,9 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem*
*/
NSMenu *QMenuBar::toNSMenu()
{
- // Call into the cocoa platform plugin: qMenuBarToNSMenu(platformMenuBar())
- QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("qmenubartonsmenu");
- if (function) {
- typedef void* (*QMenuBarToNSMenuFunction)(QPlatformMenuBar *platformMenuBar);
- return reinterpret_cast<NSMenu *>(reinterpret_cast<QMenuBarToNSMenuFunction>(function)(platformMenuBar()));
- }
+ if (auto *cocoaMenuBar = dynamic_cast<QCocoaMenuBar *>(platformMenuBar()))
+ return cocoaMenuBar->nsMenu();
+
return nil;
}
#endif // QT_CONFIG(menubar)
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index efbbc099a1..1e32fbcdfa 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMENU_P_H
#define QMENU_P_H
@@ -52,6 +16,7 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "QtWidgets/qmenu.h"
#if QT_CONFIG(menubar)
#include "QtWidgets/qmenubar.h"
#endif
@@ -64,6 +29,10 @@
#include <qpa/qplatformmenu.h>
+#include <QtCore/qpointer.h>
+
+#include <functional>
+
QT_REQUIRE_CONFIG(menu);
QT_BEGIN_NAMESPACE
@@ -302,6 +271,8 @@ class QMenuPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMenu)
public:
+ using PositionFunction = std::function<QPoint(const QSize &)>;
+
QMenuPrivate() :
itemsDirty(false),
hasCheckableItems(false),
@@ -331,7 +302,7 @@ public:
void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item);
QPlatformMenuItem *insertActionInPlatformMenu(const QAction *action, QPlatformMenuItem *beforeItem);
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
void moveWidgetToPlatformItem(QWidget *w, QPlatformMenuItem* item);
#endif
@@ -343,14 +314,15 @@ public:
//item calculations
QRect actionRect(QAction *) const;
- mutable QVector<QRect> actionRects;
+ mutable QList<QRect> actionRects;
mutable QHash<QAction *, QWidget *> widgetItems;
void updateActionRects() const;
void updateActionRects(const QRect &screen) const;
- QRect popupGeometry() const;
- QRect popupGeometry(int screen) const;
+ QRect popupGeometry(QScreen *screen = nullptr) const;
bool useFullScreenForPopup() const;
int getLastVisibleAction() const;
+ void popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction = {});
+ QAction *exec(const QPoint &p, QAction *action, PositionFunction positionFunction = {});
//selection
static QMenu *mouseDown;
@@ -430,10 +402,11 @@ public:
QPointer<QWidget> widget;
QPointer<QAction> action;
};
- virtual QVector<QPointer<QWidget> > calcCausedStack() const;
+ virtual QList<QPointer<QWidget>> calcCausedStack() const;
QMenuCaused causedPopup;
void hideUpToMenuBar();
void hideMenu(QMenu *menu);
+ QWindow *transientParentWindow() const;
//index mappings
inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
@@ -455,7 +428,8 @@ public:
//firing of events
void activateAction(QAction *, QAction::ActionEvent, bool self=true);
- void activateCausedStack(const QVector<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
+ void activateCausedStack(const QList<QPointer<QWidget>> &, QAction *, QAction::ActionEvent,
+ bool);
void _q_actionTriggered();
void _q_actionHovered();
@@ -499,6 +473,11 @@ public:
mutable quint8 ncols = 0; // "255cols ought to be enough for anybody."
+ // Contains the screen of the popup point during popup(QPoint).
+ // This is to make sure the screen is remembered,
+ // when the menu contains many items on multiple screens
+ QPointer<QScreen> popupScreen;
+
mutable bool itemsDirty : 1;
mutable bool hasCheckableItems : 1;
bool lastContextMenu : 1;
@@ -515,8 +494,6 @@ public:
bool tearoffHighlighted : 1;
//menu fading/scrolling effects
bool doChildEffects : 1;
-
- int popupScreen = -1;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 59c8af30b4..c9c9191c17 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1,49 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qmenubar.h>
#include <qstyle.h>
#include <qlayout.h>
#include <qapplication.h>
-#include <qdesktopwidget.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include <qaccessible.h>
#endif
#include <qpainter.h>
@@ -64,7 +27,6 @@
#include <qpa/qplatformtheme.h>
#include "private/qguiapplication_p.h"
#include "qpa/qplatformintegration.h"
-#include <private/qdesktopwidget_p.h>
#include "qmenu_p.h"
#include "qmenubar_p.h"
@@ -73,6 +35,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QMenuBarExtension : public QToolButton
{
public:
@@ -85,7 +49,7 @@ public:
QMenuBarExtension::QMenuBarExtension(QWidget *parent)
: QToolButton(parent)
{
- setObjectName(QLatin1String("qt_menubar_ext_button"));
+ setObjectName("qt_menubar_ext_button"_L1);
setAutoRaise(true);
#if QT_CONFIG(menu)
setPopupMode(QToolButton::InstantPopup);
@@ -117,7 +81,7 @@ QSize QMenuBarExtension::sizeHint() const
QAction *QMenuBarPrivate::actionAt(QPoint p) const
{
for(int i = 0; i < actions.size(); ++i) {
- if(actionRect(actions.at(i)).contains(p))
+ if (actionRect(actions.at(i)).contains(p))
return actions.at(i);
}
return nullptr;
@@ -165,11 +129,11 @@ bool QMenuBarPrivate::isVisible(QAction *action)
void QMenuBarPrivate::updateGeometries()
{
Q_Q(QMenuBar);
- if(!itemsDirty)
+ if (!itemsDirty)
return;
int q_width = q->width()-(q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, q)*2);
int q_start = -1;
- if(leftWidget || rightWidget) {
+ if (leftWidget || rightWidget) {
int vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, nullptr, q)
+ q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, q);
int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, nullptr, q)
@@ -192,7 +156,7 @@ void QMenuBarPrivate::updateGeometries()
}
#ifdef Q_OS_MAC
- if(q->isNativeMenuBar()) {//nothing to see here folks, move along..
+ if (q->isNativeMenuBar()) {//nothing to see here folks, move along..
itemsDirty = false;
return;
}
@@ -200,11 +164,11 @@ void QMenuBarPrivate::updateGeometries()
calcActionRects(q_width, q_start);
currentAction = nullptr;
#ifndef QT_NO_SHORTCUT
- if(itemsDirty) {
+ if (itemsDirty) {
for(int j = 0; j < shortcutIndexMap.size(); ++j)
q->releaseShortcut(shortcutIndexMap.value(j));
shortcutIndexMap.clear();
- const int actionsCount = actions.count();
+ const int actionsCount = actions.size();
shortcutIndexMap.reserve(actionsCount);
for (int i = 0; i < actionsCount; i++)
shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actions.at(i)->text())));
@@ -218,7 +182,7 @@ void QMenuBarPrivate::updateGeometries()
//we try to see if the actions will fit there
bool hasHiddenActions = false;
- for (int i = 0; i < actions.count(); ++i) {
+ for (int i = 0; i < actions.size(); ++i) {
const QRect &rect = actionRects.at(i);
if (rect.isValid() && !menuRect.contains(rect)) {
hasHiddenActions = true;
@@ -229,7 +193,7 @@ void QMenuBarPrivate::updateGeometries()
//...and if not, determine the ones that fit on the menu with the extension visible
if (hasHiddenActions) {
menuRect = this->menuRect(true);
- for (int i = 0; i < actions.count(); ++i) {
+ for (int i = 0; i < actions.size(); ++i) {
const QRect &rect = actionRects.at(i);
if (rect.isValid() && !menuRect.contains(rect)) {
hiddenActions.append(actions.at(i));
@@ -237,7 +201,7 @@ void QMenuBarPrivate::updateGeometries()
}
}
- if (hiddenActions.count() > 0) {
+ if (hiddenActions.size() > 0) {
QMenu *pop = extension->menu();
if (!pop) {
pop = new QMenu(q);
@@ -265,7 +229,7 @@ QRect QMenuBarPrivate::actionRect(QAction *act) const
//makes sure the geometries are up-to-date
const_cast<QMenuBarPrivate*>(this)->updateGeometries();
- if (index < 0 || index >= actionRects.count())
+ if (index < 0 || index >= actionRects.size())
return QRect(); // that can happen in case of native menubar
return actionRects.at(index);
@@ -273,11 +237,11 @@ QRect QMenuBarPrivate::actionRect(QAction *act) const
void QMenuBarPrivate::focusFirstAction()
{
- if(!currentAction) {
+ if (!currentAction) {
updateGeometries();
int index = 0;
- while (index < actions.count() && actionRects.at(index).isNull()) ++index;
- if (index < actions.count())
+ while (index < actions.size() && actionRects.at(index).isNull()) ++index;
+ if (index < actions.size())
setCurrentAction(actions.at(index));
}
}
@@ -290,16 +254,16 @@ void QMenuBarPrivate::setKeyboardMode(bool b)
return;
}
keyboardState = b;
- if(b) {
+ if (b) {
QWidget *fw = QApplication::focusWidget();
if (fw && fw != q && fw->window() != QApplication::activePopupWidget())
keyboardFocusWidget = fw;
focusFirstAction();
q->setFocus(Qt::MenuBarFocusReason);
} else {
- if(!popupState)
+ if (!popupState)
setCurrentAction(nullptr);
- if(keyboardFocusWidget) {
+ if (keyboardFocusWidget) {
if (QApplication::focusWidget() == q)
keyboardFocusWidget->setFocus(Qt::MenuBarFocusReason);
keyboardFocusWidget = nullptr;
@@ -311,23 +275,34 @@ void QMenuBarPrivate::setKeyboardMode(bool b)
void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
{
Q_Q(QMenuBar);
- if(!action || !action->menu() || closePopupMode)
+ if (!action || !action->menu() || closePopupMode)
return;
popupState = true;
if (action->isEnabled() && action->menu()->isEnabled()) {
closePopupMode = 0;
activeMenu = action->menu();
- activeMenu->d_func()->causedPopup.widget = q;
- activeMenu->d_func()->causedPopup.action = action;
+ auto *activeMenuPriv = activeMenu->d_func();
+ activeMenuPriv->causedPopup.widget = q;
+ activeMenuPriv->causedPopup.action = action;
QRect adjustedActionRect = actionRect(action);
- QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1)));
- QSize popup_size = activeMenu->sizeHint();
+ QPoint popupPos = adjustedActionRect.bottomLeft() + QPoint(0, 1);
+
//we put the popup menu on the screen containing the bottom-center of the action rect
QScreen *menubarScreen = q->window()->windowHandle()->screen();
- QScreen *popupScreen = menubarScreen->virtualSiblingAt(pos + QPoint(adjustedActionRect.width() / 2, 0));
+ QPoint screenTestPos = q->mapToGlobal(popupPos + QPoint(adjustedActionRect.width() / 2, 0));
+ QPointer<QScreen> popupScreen = menubarScreen->virtualSiblingAt(screenTestPos);
if (!popupScreen)
popupScreen = menubarScreen;
+ std::swap(popupScreen, activeMenuPriv->popupScreen);
+ const QSize popup_size = activeMenu->sizeHint();
+ std::swap(popupScreen, activeMenuPriv->popupScreen);
+
+ // Use screenTestPos.y() for the popup y position. This is the correct global y
+ // consistent with the selected screen in cases where the action rect spans
+ // multiple screens with different scale factors.
+ QPoint pos(q->mapToGlobal(popupPos).x(), screenTestPos.y());
+
QRect screenRect = popupScreen->geometry();
pos = QPoint(qMax(pos.x(), screenRect.x()), qMax(pos.y(), screenRect.y()));
const bool fitUp = (pos.y() - popup_size.height() >= screenRect.top());
@@ -353,11 +328,11 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
pos.rx() += actionWidth;
}
- if(!defaultPopDown || (fitUp && !fitDown))
+ if (!defaultPopDown || (fitUp && !fitDown))
pos.setY(qMax(screenRect.y(), q->mapToGlobal(QPoint(0, adjustedActionRect.top()-popup_size.height())).y()));
- QMenuPrivate::get(activeMenu)->topData()->initialScreenIndex = QGuiApplication::screens().indexOf(popupScreen);
+ QMenuPrivate::get(activeMenu)->topData()->initialScreen = popupScreen;
activeMenu->popup(pos);
- if(activateFirst)
+ if (activateFirst)
activeMenu->d_func()->setFirstActionActive();
}
q->update(actionRect(action));
@@ -365,7 +340,7 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activateFirst)
{
- if(currentAction == action && popup == popupState)
+ if (currentAction == action && popup == popupState)
return;
autoReleaseTimer.stop();
@@ -373,7 +348,7 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
doChildEffects = (popup && !activeMenu);
Q_Q(QMenuBar);
QWidget *fw = nullptr;
- if(QMenu *menu = activeMenu) {
+ if (QMenu *menu = activeMenu) {
activeMenu = nullptr;
if (popup) {
fw = q->window()->focusWidget();
@@ -382,7 +357,7 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
menu->hide();
}
- if(currentAction)
+ if (currentAction)
q->update(actionRect(currentAction));
popupState = popup;
@@ -392,7 +367,7 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
currentAction = action;
if (action && action->isEnabled()) {
activateAction(action, QAction::Hover);
- if(popup)
+ if (popup)
popupAction(action, activateFirst);
q->update(actionRect(action));
#if QT_CONFIG(statustip)
@@ -410,11 +385,11 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
{
Q_Q(const QMenuBar);
- if(!itemsDirty)
+ if (!itemsDirty)
return;
//let's reinitialize the buffer
- actionRects.resize(actions.count());
+ actionRects.resize(actions.size());
actionRects.fill(QRect());
const QStyle *style = q->style();
@@ -427,15 +402,15 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
const int hmargin = style->pixelMetric(QStyle::PM_MenuBarHMargin, nullptr, q),
vmargin = style->pixelMetric(QStyle::PM_MenuBarVMargin, nullptr, q),
icone = style->pixelMetric(QStyle::PM_SmallIconSize, nullptr, q);
- for(int i = 0; i < actions.count(); i++) {
+ for(int i = 0; i < actions.size(); i++) {
QAction *action = actions.at(i);
- if(!action->isVisible())
+ if (!action->isVisible())
continue;
QSize sz;
//calc what I think the size is..
- if(action->isSeparator()) {
+ if (action->isSeparator()) {
if (style->styleHint(QStyle::SH_DrawMenuBarSeparator, nullptr, q))
separator = i;
continue; //we don't really position these!
@@ -454,10 +429,10 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
q->initStyleOption(&opt, action);
sz = q->style()->sizeFromContents(QStyle::CT_MenuBarItem, &opt, sz, q);
- if(!sz.isEmpty()) {
+ if (!sz.isEmpty()) {
{ //update the separator state
int iWidth = sz.width() + itemSpacing;
- if(separator == -1)
+ if (separator == -1)
separator_start += iWidth;
else
separator_len += iWidth;
@@ -473,7 +448,7 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, q);
int x = fw + ((start == -1) ? hmargin : start) + itemSpacing;
int y = fw + vmargin;
- for(int i = 0; i < actions.count(); i++) {
+ for(int i = 0; i < actions.size(); i++) {
QRect &rect = actionRects[i];
if (rect.isNull())
continue;
@@ -482,9 +457,9 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const
rect.setHeight(max_item_height);
//move
- if(separator != -1 && i >= separator) { //after the separator
+ if (separator != -1 && i >= separator) { //after the separator
int left = (max_width - separator_len - hmargin - itemSpacing) + (x - separator_start - hmargin);
- if(left < separator_start) { //wrap
+ if (left < separator_start) { //wrap
separator_start = x = hmargin;
y += max_item_height;
}
@@ -511,9 +486,9 @@ void QMenuBarPrivate::activateAction(QAction *action, QAction::ActionEvent actio
if (action_e == QAction::Hover)
action->showStatusText(q);
-// if(action_e == QAction::Trigger)
+// if (action_e == QAction::Trigger)
// emit q->activated(action);
-// else if(action_e == QAction::Hover)
+// else if (action_e == QAction::Hover)
// emit q->highlighted(action);
}
@@ -531,14 +506,14 @@ void QMenuBarPrivate::_q_actionHovered()
Q_Q(QMenuBar);
if (QAction *action = qobject_cast<QAction *>(q->sender())) {
emit q->hovered(action);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
int actionIndex = actions.indexOf(action);
QAccessibleEvent focusEvent(q, QAccessible::Focus);
focusEvent.setChild(actionIndex);
QAccessible::updateAccessibility(&focusEvent);
}
-#endif //QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
}
}
@@ -583,7 +558,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
\inmodule QtWidgets
A menu bar consists of a list of pull-down menu items. You add
- menu items with addMenu(). For example, asuming that \c menubar
+ menu items with addMenu(). For example, assuming that \c menubar
is a pointer to a QMenuBar and \c fileMenu is a pointer to a
QMenu, the following statement inserts the menu into the menu bar:
\snippet code/src_gui_widgets_qmenubar.cpp 0
@@ -632,11 +607,13 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
Qt for \macos also provides a menu bar merging feature to make
QMenuBar conform more closely to accepted \macos menu bar layout.
- The merging functionality is based on string matching the title of
- a QMenu entry. These strings are translated (using QObject::tr())
- in the "QMenuBar" context. If an entry is moved its slots will still
- fire as if it was in the original place. The table below outlines
- the strings looked for and where the entry is placed if matched:
+ If an entry is moved its slots will still fire as if it was in the
+ original place.
+
+ The merging functionality is based on the QAction::menuRole() of
+ the menu entries. If an item has QAction::TextHeuristicRole,
+ the role is determined by string matching the title using the
+ following heuristics:
\table
\header \li String matches \li Placement \li Notes
@@ -654,8 +631,8 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
created to call QCoreApplication::quit()
\endtable
- You can override this behavior by using the QAction::menuRole()
- property.
+ You can override this behavior by setting the QAction::menuRole()
+ property to QAction::NoRole.
If you want all windows in a Mac application to share one menu
bar, you must create a menu bar that does not have a parent.
@@ -686,7 +663,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
\sa QMenu, QShortcut, QAction,
{http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html}{Introduction to Apple Human Interface Guidelines},
- {fowler}{GUI Design Handbook: Menu Bar}, {Menus Example}
+ {Menus Example}
*/
@@ -716,8 +693,8 @@ QAction *QMenuBarPrivate::getNextAction(const int _start, const int increment) c
Q_Q(const QMenuBar);
const_cast<QMenuBarPrivate*>(this)->updateGeometries();
bool allowActiveAndDisabled = q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q);
- const int start = (_start == -1 && increment == -1) ? actions.count() : _start;
- const int end = increment == -1 ? 0 : actions.count() - 1;
+ const int start = (_start == -1 && increment == -1) ? actions.size() : _start;
+ const int end = increment == -1 ? 0 : actions.size() - 1;
for (int i = start; i != end;) {
i += increment;
@@ -753,72 +730,6 @@ QMenuBar::~QMenuBar()
}
/*!
- This convenience function creates a new action with \a text.
- The function adds the newly created action to the menu's
- list of actions, and returns it.
-
- \sa QWidget::addAction(), QWidget::actions()
-*/
-QAction *QMenuBar::addAction(const QString &text)
-{
- QAction *ret = new QAction(text, this);
- addAction(ret);
- return ret;
-}
-
-/*!
- \overload
-
- This convenience function creates a new action with the given \a
- text. The action's triggered() signal is connected to the \a
- receiver's \a member slot. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- \sa QWidget::addAction(), QWidget::actions()
-*/
-QAction *QMenuBar::addAction(const QString &text, const QObject *receiver, const char* member)
-{
- QAction *ret = new QAction(text, this);
- QObject::connect(ret, SIGNAL(triggered(bool)), receiver, member);
- addAction(ret);
- return ret;
-}
-
-/*!
- \fn template<typename Obj, typename PointerToMemberFunctionOrFunctor> QAction *QMenuBar::addAction(const QString &text, const Obj *receiver, PointerToMemberFunctionOrFunctor method)
-
- \since 5.11
-
- \overload
-
- This convenience function creates a new action with the given \a
- text. The action's triggered() signal is connected to the
- \a method of the \a receiver. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenuBar takes ownership of the returned QAction.
-
- \sa QWidget::addAction(), QWidget::actions()
-*/
-
-/*!
- \fn template<typename Functor> QAction *QMenuBar::addAction(const QString &text, Functor functor)
-
- \since 5.11
-
- \overload
-
- This convenience function creates a new action with the given \a
- text. The action's triggered() signal is connected to the
- \a functor. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenuBar takes ownership of the returned QAction.
-
- \sa QWidget::addAction(), QWidget::actions()
-*/
-
-/*!
Appends a new QMenu with \a title to the menu bar. The menu bar
takes ownership of the menu. Returns the new menu.
@@ -986,12 +897,12 @@ void QMenuBar::paintEvent(QPaintEvent *e)
QRegion emptyArea(rect());
//draw the items
- for (int i = 0; i < d->actions.count(); ++i) {
+ for (int i = 0; i < d->actions.size(); ++i) {
QAction *action = d->actions.at(i);
QRect adjustedActionRect = d->actionRect(action);
if (adjustedActionRect.isEmpty() || !d->isVisible(action))
continue;
- if(!e->rect().intersects(adjustedActionRect))
+ if (!e->rect().intersects(adjustedActionRect))
continue;
emptyArea -= adjustedActionRect;
@@ -1014,7 +925,7 @@ void QMenuBar::paintEvent(QPaintEvent *e)
frame.rect = rect();
frame.palette = palette();
frame.state = QStyle::State_None;
- frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, &frame, this);
frame.midLineWidth = 0;
style()->drawPrimitive(QStyle::PE_PanelMenuBar, &frame, &p, this);
}
@@ -1048,23 +959,23 @@ void QMenuBar::setVisible(bool visible)
void QMenuBar::mousePressEvent(QMouseEvent *e)
{
Q_D(QMenuBar);
- if(e->button() != Qt::LeftButton)
+ if (e->button() != Qt::LeftButton)
return;
d->mouseDown = true;
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
if (!action || !d->isVisible(action) || !action->isEnabled()) {
d->setCurrentAction(nullptr);
#if QT_CONFIG(whatsthis)
if (QWhatsThis::inWhatsThisMode())
- QWhatsThis::showText(e->globalPos(), d->whatsThis, this);
+ QWhatsThis::showText(e->globalPosition().toPoint(), d->whatsThis, this);
#endif
return;
}
- if(d->currentAction == action && d->popupState) {
- if(QMenu *menu = d->activeMenu) {
+ if (d->currentAction == action && d->popupState) {
+ if (QMenu *menu = d->activeMenu) {
d->activeMenu = nullptr;
menu->setAttribute(Qt::WA_NoMouseReplay);
menu->hide();
@@ -1080,20 +991,20 @@ void QMenuBar::mousePressEvent(QMouseEvent *e)
void QMenuBar::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QMenuBar);
- if(e->button() != Qt::LeftButton || !d->mouseDown)
+ if (e->button() != Qt::LeftButton || !d->mouseDown)
return;
d->mouseDown = false;
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
// do noting if the action is hidden
if (!d->isVisible(action))
return;
- if((d->closePopupMode && action == d->currentAction) || !action || !action->menu()) {
+ if ((d->closePopupMode && action == d->currentAction) || !action || !action->menu()) {
//we set the current action before activating
//so that we let the leave event set the current back to 0
d->setCurrentAction(action, false);
- if(action)
+ if (action)
d->activateAction(action, QAction::Trigger);
}
d->closePopupMode = 0;
@@ -1107,15 +1018,15 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
Q_D(QMenuBar);
d->updateGeometries();
int key = e->key();
- if(isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
- if(key == Qt::Key_Left)
+ if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
+ if (key == Qt::Key_Left)
key = Qt::Key_Right;
- else if(key == Qt::Key_Right)
+ else if (key == Qt::Key_Right)
key = Qt::Key_Left;
}
- if(key == Qt::Key_Tab) //means right
+ if (key == Qt::Key_Tab) //means right
key = Qt::Key_Right;
- else if(key == Qt::Key_Backtab) //means left
+ else if (key == Qt::Key_Backtab) //means left
key = Qt::Key_Left;
bool key_consumed = false;
@@ -1127,9 +1038,9 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
case Qt::Key_Return: {
if (!style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, nullptr, this) || !d->currentAction)
break;
- if(d->currentAction->menu()) {
+ if (d->currentAction->menu()) {
d->popupAction(d->currentAction, true);
- } else if(key == Qt::Key_Enter || key == Qt::Key_Return || key == Qt::Key_Space) {
+ } else if (key == Qt::Key_Enter || key == Qt::Key_Return || key == Qt::Key_Space) {
d->activateAction(d->currentAction, QAction::Trigger);
d->setCurrentAction(d->currentAction, false);
d->setKeyboardMode(false);
@@ -1139,7 +1050,7 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
case Qt::Key_Right:
case Qt::Key_Left: {
- if(d->currentAction) {
+ if (d->currentAction) {
int index = d->actions.indexOf(d->currentAction);
if (QAction *nextAction = d->getNextAction(index, key == Qt::Key_Left ? -1 : +1)) {
d->setCurrentAction(nextAction, d->popupState, true);
@@ -1160,9 +1071,9 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
}
#endif
- if(!key_consumed &&
+ if (!key_consumed &&
(!e->modifiers() ||
- (e->modifiers()&(Qt::MetaModifier|Qt::AltModifier))) && e->text().length()==1 && !d->popupState) {
+ (e->modifiers()&(Qt::MetaModifier|Qt::AltModifier))) && e->text().size()==1 && !d->popupState) {
int clashCount = 0;
QAction *first = nullptr, *currentSelected = nullptr, *firstAfterCurrent = nullptr;
{
@@ -1172,14 +1083,14 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
continue;
QAction *act = d->actions.at(i);
QString s = act->text();
- if(!s.isEmpty()) {
- int ampersand = s.indexOf(QLatin1Char('&'));
- if(ampersand >= 0) {
- if(s[ampersand+1].toUpper() == c) {
+ if (!s.isEmpty()) {
+ qsizetype ampersand = s.indexOf(u'&');
+ if (ampersand >= 0) {
+ if (s[ampersand+1].toUpper() == c) {
clashCount++;
- if(!first)
+ if (!first)
first = act;
- if(act == d->currentAction)
+ if (act == d->currentAction)
currentSelected = act;
else if (!firstAfterCurrent && currentSelected)
firstAfterCurrent = act;
@@ -1189,18 +1100,18 @@ void QMenuBar::keyPressEvent(QKeyEvent *e)
}
}
QAction *next_action = nullptr;
- if(clashCount >= 1) {
- if(clashCount == 1 || !d->currentAction || (currentSelected && !firstAfterCurrent))
+ if (clashCount >= 1) {
+ if (clashCount == 1 || !d->currentAction || (currentSelected && !firstAfterCurrent))
next_action = first;
else
next_action = firstAfterCurrent;
}
- if(next_action) {
+ if (next_action) {
key_consumed = true;
d->setCurrentAction(next_action, true, true);
}
}
- if(key_consumed)
+ if (key_consumed)
e->accept();
else
e->ignore();
@@ -1222,7 +1133,7 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e)
}
bool popupState = d->popupState || d->mouseDown;
- QAction *action = d->actionAt(e->pos());
+ QAction *action = d->actionAt(e->position().toPoint());
if ((action && d->isVisible(action)) || !popupState)
d->setCurrentAction(action, popupState);
}
@@ -1233,7 +1144,7 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e)
void QMenuBar::leaveEvent(QEvent *)
{
Q_D(QMenuBar);
- if((!hasFocus() && !d->popupState) ||
+ if ((!hasFocus() && !d->popupState) ||
(d->currentAction && d->currentAction->menu() == nullptr))
d->setCurrentAction(nullptr);
}
@@ -1324,10 +1235,10 @@ void QMenuBar::actionEvent(QActionEvent *e)
}
}
- if(e->type() == QEvent::ActionAdded) {
+ if (e->type() == QEvent::ActionAdded) {
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
- } else if(e->type() == QEvent::ActionRemoved) {
+ } else if (e->type() == QEvent::ActionRemoved) {
e->action()->disconnect(this);
}
// updateGeometries() is also needed for native menu bars because
@@ -1344,7 +1255,7 @@ void QMenuBar::actionEvent(QActionEvent *e)
void QMenuBar::focusInEvent(QFocusEvent *)
{
Q_D(QMenuBar);
- if(d->keyboardState)
+ if (d->keyboardState)
d->focusFirstAction();
}
@@ -1354,7 +1265,7 @@ void QMenuBar::focusInEvent(QFocusEvent *)
void QMenuBar::focusOutEvent(QFocusEvent *)
{
Q_D(QMenuBar);
- if(!d->popupState) {
+ if (!d->popupState) {
d->setCurrentAction(nullptr);
d->setKeyboardMode(false);
}
@@ -1384,10 +1295,15 @@ void QMenuBarPrivate::handleReparent()
// also a window (for shortcuts)
QWidget *newWindow = newParent ? newParent->window() : nullptr;
- QVector<QPointer<QWidget> > newParents;
+ QList<QPointer<QWidget>> newParents;
// Remove event filters on ex-parents, keep them on still-parents
// The parents are always ordered in the vector
- foreach (const QPointer<QWidget> &w, oldParents) {
+ //
+ // Take a copy because this method is called from changeEvent() and eventFilter(),
+ // which might cause recursion into the class due to event processing, which might
+ // modify oldParents.
+ const auto copy = oldParents;
+ for (const QPointer<QWidget> &w : copy) {
if (w) {
if (newParent == w) {
newParents.append(w);
@@ -1433,10 +1349,10 @@ void QMenuBarPrivate::handleReparent()
void QMenuBar::changeEvent(QEvent *e)
{
Q_D(QMenuBar);
- if(e->type() == QEvent::StyleChange) {
+ if (e->type() == QEvent::StyleChange) {
d->itemsDirty = true;
setMouseTracking(style()->styleHint(QStyle::SH_MenuBar_MouseTracking, nullptr, this));
- if(parentWidget())
+ if (parentWidget())
resize(parentWidget()->width(), heightForWidth(parentWidget()->width()));
d->updateGeometries();
} else if (e->type() == QEvent::ParentChange) {
@@ -1458,14 +1374,14 @@ bool QMenuBar::event(QEvent *e)
Q_D(QMenuBar);
switch (e->type()) {
case QEvent::KeyPress: {
- QKeyEvent *ke = (QKeyEvent*)e;
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
#if 0
- if(!d->keyboardState) { //all keypresses..
+ if (!d->keyboardState) { //all keypresses..
d->setCurrentAction(0);
return ;
}
#endif
- if(ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
+ if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
keyPressEvent(ke);
return true;
}
@@ -1486,7 +1402,7 @@ bool QMenuBar::event(QEvent *e)
break;
#ifndef QT_NO_SHORTCUT
case QEvent::ShortcutOverride: {
- QKeyEvent *kev = static_cast<QKeyEvent*>(e);
+ QKeyEvent *kev = static_cast<QKeyEvent *>(e);
//we only filter out escape if there is a current action
if (kev->matches(QKeySequence::Cancel) && d->currentAction) {
e->accept();
@@ -1590,7 +1506,7 @@ bool QMenuBar::eventFilter(QObject *object, QEvent *event)
Returns the QAction at \a pt. Returns \nullptr if there is no action at \a pt or if
the location has a separator.
- \sa addAction(), addSeparator()
+ \sa QWidget::addAction(), addSeparator()
*/
QAction *QMenuBar::actionAt(const QPoint &pt) const
{
@@ -1624,29 +1540,29 @@ QSize QMenuBar::minimumSizeHint() const
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, nullptr, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, nullptr, this);
- if(as_gui_menubar) {
- int w = parentWidget() ? parentWidget()->width() : QDesktopWidgetPrivate::width();
+ if (as_gui_menubar) {
+ int w = parentWidget() ? parentWidget()->width() : QGuiApplication::primaryScreen()->virtualGeometry().width();
d->calcActionRects(w - (2 * fw), 0);
- for (int i = 0; ret.isNull() && i < d->actions.count(); ++i)
+ for (int i = 0; ret.isNull() && i < d->actions.size(); ++i)
ret = d->actionRects.at(i).size();
if (!d->extension->isHidden())
ret += QSize(d->extension->sizeHint().width(), 0);
ret += QSize(2*fw + hmargin, 2*fw + vmargin);
}
int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
- if(d->leftWidget) {
+ if (d->leftWidget) {
QSize sz = d->leftWidget->minimumSizeHint();
ret.setWidth(ret.width() + sz.width());
- if(sz.height() + margin > ret.height())
+ if (sz.height() + margin > ret.height())
ret.setHeight(sz.height() + margin);
}
- if(d->rightWidget) {
+ if (d->rightWidget) {
QSize sz = d->rightWidget->minimumSizeHint();
ret.setWidth(ret.width() + sz.width());
- if(sz.height() + margin > ret.height())
+ if (sz.height() + margin > ret.height())
ret.setHeight(sz.height() + margin);
}
- if(as_gui_menubar) {
+ if (as_gui_menubar) {
QStyleOptionMenuItem opt;
opt.rect = rect();
opt.menuRect = rect();
@@ -1654,9 +1570,7 @@ QSize QMenuBar::minimumSizeHint() const
opt.menuItemType = QStyleOptionMenuItem::Normal;
opt.checkType = QStyleOptionMenuItem::NotCheckable;
opt.palette = palette();
- return (style()->sizeFromContents(QStyle::CT_MenuBar, &opt,
- ret.expandedTo(QApplication::globalStrut()),
- this));
+ return style()->sizeFromContents(QStyle::CT_MenuBar, &opt, ret, this);
}
return ret;
}
@@ -1676,10 +1590,10 @@ QSize QMenuBar::sizeHint() const
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, nullptr, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, nullptr, this);
- if(as_gui_menubar) {
- const int w = parentWidget() ? parentWidget()->width() : QDesktopWidgetPrivate::width();
+ if (as_gui_menubar) {
+ const int w = parentWidget() ? parentWidget()->width() : QGuiApplication::primaryScreen()->virtualGeometry().width();
d->calcActionRects(w - (2 * fw), 0);
- for (int i = 0; i < d->actionRects.count(); ++i) {
+ for (int i = 0; i < d->actionRects.size(); ++i) {
const QRect &actionRect = d->actionRects.at(i);
ret = ret.expandedTo(QSize(actionRect.x() + actionRect.width(), actionRect.y() + actionRect.height()));
}
@@ -1688,18 +1602,18 @@ QSize QMenuBar::sizeHint() const
ret += QSize(fw + hmargin, fw + vmargin);
}
int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
- if(d->leftWidget) {
+ if (d->leftWidget) {
QSize sz = d->leftWidget->sizeHint();
sz.rheight() += margin;
ret = ret.expandedTo(sz);
}
- if(d->rightWidget) {
+ if (d->rightWidget) {
QSize sz = d->rightWidget->sizeHint();
ret.setWidth(ret.width() + sz.width());
- if(sz.height() + margin > ret.height())
+ if (sz.height() + margin > ret.height())
ret.setHeight(sz.height() + margin);
}
- if(as_gui_menubar) {
+ if (as_gui_menubar) {
QStyleOptionMenuItem opt;
opt.rect = rect();
opt.menuRect = rect();
@@ -1707,9 +1621,7 @@ QSize QMenuBar::sizeHint() const
opt.menuItemType = QStyleOptionMenuItem::Normal;
opt.checkType = QStyleOptionMenuItem::NotCheckable;
opt.palette = palette();
- return (style()->sizeFromContents(QStyle::CT_MenuBar, &opt,
- ret.expandedTo(QApplication::globalStrut()),
- this));
+ return style()->sizeFromContents(QStyle::CT_MenuBar, &opt, ret, this);
}
return ret;
}
@@ -1727,8 +1639,8 @@ int QMenuBar::heightForWidth(int) const
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, nullptr, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, nullptr, this);
int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, nullptr, this);
- if(as_gui_menubar) {
- for (int i = 0; i < d->actionRects.count(); ++i)
+ if (as_gui_menubar) {
+ for (int i = 0; i < d->actionRects.size(); ++i)
height = qMax(height, d->actionRects.at(i).height());
if (height) //there is at least one non-null item
height += spaceBelowMenuBar;
@@ -1736,13 +1648,13 @@ int QMenuBar::heightForWidth(int) const
height += 2*vmargin;
}
int margin = 2*vmargin + 2*fw + spaceBelowMenuBar;
- if(d->leftWidget)
+ if (d->leftWidget)
height = qMax(d->leftWidget->sizeHint().height() + margin, height);
- if(d->rightWidget)
+ if (d->rightWidget)
height = qMax(d->rightWidget->sizeHint().height() + margin, height);
- if(as_gui_menubar) {
+ if (as_gui_menubar) {
QStyleOptionMenuItem opt;
- opt.init(this);
+ opt.initFrom(this);
opt.menuRect = rect();
opt.state = QStyle::State_None;
opt.menuItemType = QStyleOptionMenuItem::Normal;
@@ -1878,6 +1790,7 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
if (!nativeMenuBar) {
delete d->platformMenuBar;
d->platformMenuBar = nullptr;
+ d->itemsDirty = true;
} else {
if (!d->platformMenuBar)
d->platformMenuBar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
diff --git a/src/widgets/widgets/qmenubar.h b/src/widgets/widgets/qmenubar.h
index cf6663f94a..dc0d1559bf 100644
--- a/src/widgets/widgets/qmenubar.h
+++ b/src/widgets/widgets/qmenubar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMENUBAR_H
#define QMENUBAR_H
@@ -64,34 +28,10 @@ public:
~QMenuBar();
using QWidget::addAction;
+#if QT_WIDGETS_REMOVED_SINCE(6, 3)
QAction *addAction(const QString &text);
QAction *addAction(const QString &text, const QObject *receiver, const char* member);
-
-#ifdef Q_CLANG_QDOC
- template<typename Obj, typename PointerToMemberFunctionOrFunctor>
- QAction *addAction(const QString &text, const Obj *receiver, PointerToMemberFunctionOrFunctor method);
- template<typename Functor>
- QAction *addAction(const QString &text, Functor functor);
-#else
- // addAction(QString): Connect to a QObject slot / functor or function pointer (with context)
- template<typename Obj, typename Func1>
- inline typename std::enable_if<!std::is_same<const char*, Func1>::value
- && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type
- addAction(const QString &text, const Obj *object, Func1 slot)
- {
- QAction *result = addAction(text);
- connect(result, &QAction::triggered, object, std::move(slot));
- return result;
- }
- // addAction(QString): Connect to a functor or function pointer (without context)
- template <typename Func1>
- inline QAction *addAction(const QString &text, Func1 slot)
- {
- QAction *result = addAction(text);
- connect(result, &QAction::triggered, std::move(slot));
- return result;
- }
-#endif // !Q_CLANG_QDOC
+#endif
QAction *addMenu(QMenu *menu);
QMenu *addMenu(const QString &title);
@@ -121,7 +61,7 @@ public:
void setCornerWidget(QWidget *w, Qt::Corner corner = Qt::TopRightCorner);
QWidget *cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
NSMenu* toNSMenu();
#endif
@@ -150,7 +90,7 @@ protected:
void timerEvent(QTimerEvent *) override;
bool eventFilter(QObject *, QEvent *) override;
bool event(QEvent *) override;
- void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
+ virtual void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
private:
Q_DECLARE_PRIVATE(QMenuBar)
diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h
index e3db16d190..549a4c7a1f 100644
--- a/src/widgets/widgets/qmenubar_p.h
+++ b/src/widgets/widgets/qmenubar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMENUBAR_P_H
#define QMENUBAR_P_H
@@ -56,6 +20,8 @@
#include <private/qmenu_p.h> // Mac needs what in this file!
#include <qpa/qplatformmenu.h>
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(menubar);
QT_BEGIN_NAMESPACE
@@ -81,8 +47,8 @@ public:
//item calculations
uint itemsDirty : 1;
- QVector<int> shortcutIndexMap;
- mutable QVector<QRect> actionRects;
+ QList<int> shortcutIndexMap;
+ mutable QList<QRect> actionRects;
void calcActionRects(int max_width, int start) const;
QRect actionRect(QAction *) const;
void updateGeometries();
@@ -124,7 +90,7 @@ public:
// reparenting
void handleReparent();
- QVector<QPointer<QWidget> > oldParents;
+ QList<QPointer<QWidget>> oldParents;
QList<QAction*> hiddenActions;
//default action
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index d54c0d0b20..8362c6c629 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplaintextedit_p.h"
@@ -71,9 +35,14 @@
QT_BEGIN_NAMESPACE
-static inline bool shouldEnableInputMethod(QPlainTextEdit *plaintextedit)
+static inline bool shouldEnableInputMethod(QPlainTextEdit *control)
{
- return !plaintextedit->isReadOnly();
+#if defined(Q_OS_ANDROID)
+ Q_UNUSED(control);
+ return !control->isReadOnly() || (control->textInteractionFlags() & Qt::TextSelectableByMouse);
+#else
+ return !control->isReadOnly();
+#endif
}
class QPlainTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate
@@ -449,22 +418,29 @@ QPlainTextEditControl::QPlainTextEditControl(QPlainTextEdit *parent)
setAcceptRichText(false);
}
-void QPlainTextEditPrivate::_q_cursorPositionChanged()
+void QPlainTextEditPrivate::cursorPositionChanged()
{
pageUpDownLastCursorYIsValid = false;
Q_Q(QPlainTextEdit);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextCursorEvent ev(q, q->textCursor().position());
QAccessible::updateAccessibility(&ev);
#endif
emit q->cursorPositionChanged();
}
-void QPlainTextEditPrivate::_q_verticalScrollbarActionTriggered(int action) {
- if (action == QAbstractSlider::SliderPageStepAdd) {
+void QPlainTextEditPrivate::verticalScrollbarActionTriggered(int action) {
+
+ const auto a = static_cast<QAbstractSlider::SliderAction>(action);
+ switch (a) {
+ case QAbstractSlider::SliderPageStepAdd:
pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor, false);
- } else if (action == QAbstractSlider::SliderPageStepSub) {
+ break;
+ case QAbstractSlider::SliderPageStepSub:
pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor, false);
+ break;
+ default:
+ break;
}
}
@@ -653,10 +629,7 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx)
lineNumber = maxTopLine - block.firstLineNumber();
}
- {
- const QSignalBlocker blocker(vbar);
- vbar->setValue(newTopLine);
- }
+ vbar->setValue(newTopLine);
if (!dx && blockNumber == control->topBlock && lineNumber == topLine)
return;
@@ -672,10 +645,7 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx)
control->topBlock = blockNumber;
topLine = lineNumber;
- {
- const QSignalBlocker blocker(vbar);
- vbar->setValue(block.firstLineNumber() + lineNumber);
- }
+ vbar->setValue(block.firstLineNumber() + lineNumber);
if (dx || dy) {
viewport->scroll(q->isRightToLeft() ? -dx : dx, dy);
@@ -755,21 +725,17 @@ void QPlainTextEditPrivate::updateViewport()
}
QPlainTextEditPrivate::QPlainTextEditPrivate()
- : control(nullptr),
- tabChangesFocus(false),
- lineWrap(QPlainTextEdit::WidgetWidth),
- wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere),
- clickCausedFocus(0), placeholderVisible(1),
- topLine(0), topLineFracture(0),
- pageUpDownLastCursorYIsValid(false)
+ : tabChangesFocus(false)
+ , showCursorOnInitialShow(false)
+ , backgroundVisible(false)
+ , centerOnScroll(false)
+ , inDrag(false)
+ , clickCausedFocus(false)
+ , pageUpDownLastCursorYIsValid(false)
+ , placeholderTextShown(false)
{
- showCursorOnInitialShow = true;
- backgroundVisible = false;
- centerOnScroll = false;
- inDrag = false;
}
-
void QPlainTextEditPrivate::init(const QString &txt)
{
Q_Q(QPlainTextEdit);
@@ -782,23 +748,28 @@ void QPlainTextEditPrivate::init(const QString &txt)
control->setPalette(q->palette());
- QObject::connect(vbar, SIGNAL(actionTriggered(int)), q, SLOT(_q_verticalScrollbarActionTriggered(int)));
-
- QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus()));
- QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars()));
- QObject::connect(control, SIGNAL(blockCountChanged(int)), q, SIGNAL(blockCountChanged(int)));
- QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF)));
- QObject::connect(control, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
-
- QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged()));
- QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
- QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
- QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool)));
- QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
- QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged()));
-
- QObject::connect(control, SIGNAL(textChanged()), q, SLOT(_q_textChanged()));
- QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus()));
+ QObjectPrivate::connect(vbar, &QAbstractSlider::actionTriggered,
+ this, &QPlainTextEditPrivate::verticalScrollbarActionTriggered);
+ QObject::connect(control, &QWidgetTextControl::microFocusChanged, q,
+ [q](){q->updateMicroFocus(); });
+ QObjectPrivate::connect(control, &QWidgetTextControl::documentSizeChanged,
+ this, &QPlainTextEditPrivate::adjustScrollbars);
+ QObject::connect(control, &QWidgetTextControl::blockCountChanged,
+ q, &QPlainTextEdit::blockCountChanged);
+ QObjectPrivate::connect(control, &QWidgetTextControl::updateRequest,
+ this, &QPlainTextEditPrivate::repaintContents);
+ QObject::connect(control, &QWidgetTextControl::modificationChanged,
+ q, &QPlainTextEdit::modificationChanged);
+ QObject::connect(control, &QWidgetTextControl::textChanged, q, &QPlainTextEdit::textChanged);
+ QObject::connect(control, &QWidgetTextControl::undoAvailable, q, &QPlainTextEdit::undoAvailable);
+ QObject::connect(control, &QWidgetTextControl::redoAvailable, q, &QPlainTextEdit::redoAvailable);
+ QObject::connect(control, &QWidgetTextControl::copyAvailable, q, &QPlainTextEdit::copyAvailable);
+ QObject::connect(control, &QWidgetTextControl::selectionChanged, q, &QPlainTextEdit::selectionChanged);
+ QObjectPrivate::connect(control, &QWidgetTextControl::cursorPositionChanged,
+ this, &QPlainTextEditPrivate::cursorPositionChanged);
+ QObjectPrivate::connect(control, &QWidgetTextControl::textChanged,
+ this, &QPlainTextEditPrivate::updatePlaceholderVisibility);
+ QObject::connect(control, &QWidgetTextControl::textChanged, q, [q](){q->updateMicroFocus(); });
// set a null page size initially to avoid any relayouting until the textedit
// is shown. relayoutDocument() will take care of setting the page size to the
@@ -824,29 +795,21 @@ void QPlainTextEditPrivate::init(const QString &txt)
#ifndef QT_NO_CURSOR
viewport->setCursor(Qt::IBeamCursor);
#endif
- originalOffsetY = 0;
}
-void QPlainTextEditPrivate::_q_textChanged()
+void QPlainTextEditPrivate::updatePlaceholderVisibility()
{
- Q_Q(QPlainTextEdit);
-
// We normally only repaint the part of view that contains text in the
- // document that has changed (in _q_repaintContents). But the placeholder
+ // document that has changed (in repaintContents). But the placeholder
// text is not a part of the document, but is drawn on separately. So whenever
// we either show or hide the placeholder text, we issue a full update.
- bool placeholderCurrentyVisible = placeholderVisible;
-
- placeholderVisible = !placeholderText.isEmpty()
- && q->document()->isEmpty()
- && (!q->firstVisibleBlock().isValid() ||
- q->firstVisibleBlock().layout()->preeditAreaText().isEmpty());
-
- if (placeholderCurrentyVisible != placeholderVisible)
+ if (placeholderTextShown != placeHolderTextToBeShown()) {
viewport->update();
+ placeholderTextShown = placeHolderTextToBeShown();
+ }
}
-void QPlainTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
+void QPlainTextEditPrivate::repaintContents(const QRectF &contentsRect)
{
Q_Q(QPlainTextEdit);
if (!contentsRect.isValid()) {
@@ -972,14 +935,14 @@ void QPlainTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCurso
}
if (moveCursor) {
- control->setTextCursor(cursor);
+ control->setTextCursor(cursor, moveMode == QTextCursor::KeepAnchor);
pageUpDownLastCursorYIsValid = true;
}
}
#if QT_CONFIG(scrollbar)
-void QPlainTextEditPrivate::_q_adjustScrollbars()
+void QPlainTextEditPrivate::adjustScrollbars()
{
Q_Q(QPlainTextEdit);
QTextDocument *doc = control->document();
@@ -1033,8 +996,6 @@ void QPlainTextEditPrivate::_q_adjustScrollbars()
vSliderLength = lineSpacing != 0 ? viewport->height() / lineSpacing : 0;
}
-
-
QSizeF documentSize = documentLayout->documentSize();
vbar->setRange(0, qMax(0, vmax));
vbar->setPageStep(vSliderLength);
@@ -1043,10 +1004,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars()
if (firstVisibleBlock.isValid())
visualTopLine = firstVisibleBlock.firstLineNumber() + topLine;
- {
- const QSignalBlocker blocker(vbar);
- vbar->setValue(visualTopLine);
- }
+ vbar->setValue(visualTopLine);
hbar->setRange(0, (int)documentSize.width() - viewport->width());
hbar->setPageStep(viewport->width());
@@ -1226,10 +1184,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
editor with line wrap enabled in real time. It also makes for a
fast log viewer (see setMaximumBlockCount()).
-
- \sa QTextDocument, QTextCursor, {Application Example},
- {Code Editor Example}, {Syntax Highlighter Example},
- {Rich Text Processing}
+ \sa QTextDocument, QTextCursor
+ {Syntax Highlighter Example}, {Rich Text Processing}
*/
@@ -1341,7 +1297,7 @@ void QPlainTextEdit::setDocument(QTextDocument *document)
d->documentLayoutPtr = documentLayout;
d->updateDefaultTextOption();
d->relayoutDocument();
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
}
/*!
@@ -1373,8 +1329,7 @@ void QPlainTextEdit::setPlaceholderText(const QString &placeholderText)
Q_D(QPlainTextEdit);
if (d->placeholderText != placeholderText) {
d->placeholderText = placeholderText;
- if (d->control->document()->isEmpty())
- d->viewport->update();
+ d->updatePlaceholderVisibility();
}
}
@@ -1430,7 +1385,7 @@ QString QPlainTextEdit::anchorAt(const QPoint &pos) const
if (cursorPos < 0)
return QString();
- QTextDocumentPrivate *pieceTable = document()->docHandle();
+ QTextDocumentPrivate *pieceTable = QTextDocumentPrivate::get(document());
QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos);
QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format);
return fmt.anchorHref();
@@ -1554,53 +1509,61 @@ bool QPlainTextEdit::event(QEvent *e)
{
Q_D(QPlainTextEdit);
+ switch (e->type()) {
#ifndef QT_NO_CONTEXTMENU
- if (e->type() == QEvent::ContextMenu
- && static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
- ensureCursorVisible();
- const QPoint cursorPos = cursorRect().center();
- QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
- ce.setAccepted(e->isAccepted());
- const bool result = QAbstractScrollArea::event(&ce);
- e->setAccepted(ce.isAccepted());
- return result;
- }
+ case QEvent::ContextMenu:
+ if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
+ ensureCursorVisible();
+ const QPoint cursorPos = cursorRect().center();
+ QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
+ ce.setAccepted(e->isAccepted());
+ const bool result = QAbstractScrollArea::event(&ce);
+ e->setAccepted(ce.isAccepted());
+ return result;
+ }
+ break;
#endif // QT_NO_CONTEXTMENU
- if (e->type() == QEvent::ShortcutOverride
- || e->type() == QEvent::ToolTip) {
+ case QEvent::ShortcutOverride:
+ case QEvent::ToolTip:
d->sendControlEvent(e);
- }
+ break;
#ifdef QT_KEYPAD_NAVIGATION
- else if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) {
+ case QEvent::EnterEditFocus:
+ case QEvent::LeaveEditFocus:
if (QApplicationPrivate::keypadNavigationEnabled())
d->sendControlEvent(e);
- }
+ break;
#endif
#ifndef QT_NO_GESTURES
- else if (e->type() == QEvent::Gesture) {
- QGestureEvent *ge = static_cast<QGestureEvent *>(e);
- QPanGesture *g = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture));
- if (g) {
+ case QEvent::Gesture:
+ if (auto *g = static_cast<QGestureEvent *>(e)->gesture(Qt::PanGesture)) {
+ QPanGesture *panGesture = static_cast<QPanGesture *>(g);
QScrollBar *hBar = horizontalScrollBar();
QScrollBar *vBar = verticalScrollBar();
- if (g->state() == Qt::GestureStarted)
+ if (panGesture->state() == Qt::GestureStarted)
d->originalOffsetY = vBar->value();
- QPointF offset = g->offset();
+ QPointF offset = panGesture->offset();
if (!offset.isNull()) {
if (QGuiApplication::isRightToLeft())
offset.rx() *= -1;
// QPlainTextEdit scrolls by lines only in vertical direction
QFontMetrics fm(document()->defaultFont());
int lineHeight = fm.height();
- int newX = hBar->value() - g->delta().x();
+ int newX = hBar->value() - panGesture->delta().x();
int newY = d->originalOffsetY - offset.y()/lineHeight;
hBar->setValue(newX);
vBar->setValue(newY);
}
}
return true;
- }
#endif // QT_NO_GESTURES
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ d->control->setPalette(palette());
+ break;
+ default:
+ break;
+ }
return QAbstractScrollArea::event(e);
}
@@ -1833,8 +1796,11 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e)
*/
void QPlainTextEdit::keyReleaseEvent(QKeyEvent *e)
{
-#ifdef QT_KEYPAD_NAVIGATION
Q_D(QPlainTextEdit);
+ if (!isReadOnly())
+ d->handleSoftwareInputPanel();
+
+#ifdef QT_KEYPAD_NAVIGATION
if (QApplicationPrivate::keypadNavigationEnabled()) {
if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
&& d->deleteAllTimer.isActive()) {
@@ -1880,7 +1846,7 @@ void QPlainTextEdit::resizeEvent(QResizeEvent *e)
Q_D(QPlainTextEdit);
if (e->oldSize().width() != e->size().width())
d->relayoutDocument();
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
}
void QPlainTextEditPrivate::relayoutDocument()
@@ -1942,11 +1908,11 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
// keep right margin clean from full-width selection
int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
- - document()->documentMargin();
+ - document()->documentMargin() + cursorWidth();
er.setRight(qMin(er.right(), maxX));
painter.setClipRect(er);
- if (d->placeholderVisible) {
+ if (d->placeHolderTextToBeShown()) {
const QColor col = d->control->palette().placeholderText().color();
painter.setPen(col);
painter.setClipRect(e->rect());
@@ -1980,8 +1946,7 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
fillBackground(&painter, contentsRect, bg);
}
-
- QVector<QTextLayout::FormatRange> selections;
+ QList<QTextLayout::FormatRange> selections;
int blpos = block.position();
int bllen = block.length();
for (int i = 0; i < context.selections.size(); ++i) {
@@ -2091,7 +2056,7 @@ void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QPlainTextEdit);
d->inDrag = false; // paranoia
- const QPoint pos = e->pos();
+ const QPoint pos = e->position().toPoint();
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
@@ -2115,7 +2080,7 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->ensureCursorVisible();
}
- if (!isReadOnly() && rect().contains(e->pos()))
+ if (!isReadOnly() && rect().contains(e->position().toPoint()))
d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
d->clickCausedFocus = 0;
}
@@ -2186,7 +2151,7 @@ void QPlainTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
void QPlainTextEdit::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QPlainTextEdit);
- d->autoScrollDragPos = e->pos();
+ d->autoScrollDragPos = e->position().toPoint();
if (!d->autoScrollTimer.isActive())
d->autoScrollTimer.start(100, this);
d->sendControlEvent(e);
@@ -2218,6 +2183,10 @@ void QPlainTextEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
d->sendControlEvent(e);
+ const bool emptyEvent = e->preeditString().isEmpty() && e->commitString().isEmpty()
+ && e->attributes().isEmpty();
+ if (emptyEvent)
+ return;
ensureCursorVisible();
}
@@ -2242,25 +2211,29 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant a
{
Q_D(const QPlainTextEdit);
switch (query) {
- case Qt::ImHints:
- case Qt::ImInputItemClipRectangle:
+ case Qt::ImEnabled:
+ return isEnabled() && !isReadOnly();
+ case Qt::ImHints:
+ case Qt::ImInputItemClipRectangle:
return QWidget::inputMethodQuery(query);
+ case Qt::ImReadOnly:
+ return isReadOnly();
default:
break;
}
const QPointF offset = contentOffset();
- switch (argument.type()) {
- case QVariant::RectF:
+ switch (argument.userType()) {
+ case QMetaType::QRectF:
argument = argument.toRectF().translated(-offset);
break;
- case QVariant::PointF:
+ case QMetaType::QPointF:
argument = argument.toPointF() - offset;
break;
- case QVariant::Rect:
+ case QMetaType::QRect:
argument = argument.toRect().translated(-offset.toPoint());
break;
- case QVariant::Point:
+ case QMetaType::QPoint:
argument = argument.toPoint() - offset;
break;
default:
@@ -2268,14 +2241,14 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant a
}
const QVariant v = d->control->inputMethodQuery(query, argument);
- switch (v.type()) {
- case QVariant::RectF:
+ switch (v.userType()) {
+ case QMetaType::QRectF:
return v.toRectF().translated(offset);
- case QVariant::PointF:
+ case QMetaType::QPointF:
return v.toPointF() + offset;
- case QVariant::Rect:
+ case QMetaType::QRect:
return v.toRect().translated(offset.toPoint());
- case QVariant::Point:
+ case QMetaType::QPoint:
return v.toPoint() + offset.toPoint();
default:
break;
@@ -2313,6 +2286,7 @@ void QPlainTextEdit::showEvent(QShowEvent *)
d->showCursorOnInitialShow = false;
ensureCursorVisible();
}
+ d->adjustScrollbars();
}
/*! \reimp
@@ -2321,20 +2295,29 @@ void QPlainTextEdit::changeEvent(QEvent *e)
{
Q_D(QPlainTextEdit);
QAbstractScrollArea::changeEvent(e);
- if (e->type() == QEvent::ApplicationFontChange
- || e->type() == QEvent::FontChange) {
+
+ switch (e->type()) {
+ case QEvent::ApplicationFontChange:
+ case QEvent::FontChange:
d->control->document()->setDefaultFont(font());
- } else if(e->type() == QEvent::ActivationChange) {
+ break;
+ case QEvent::ActivationChange:
if (!isActiveWindow())
d->autoScrollTimer.stop();
- } else if (e->type() == QEvent::EnabledChange) {
+ break;
+ case QEvent::EnabledChange:
e->setAccepted(isEnabled());
d->control->setPalette(palette());
d->sendControlEvent(e);
- } else if (e->type() == QEvent::PaletteChange) {
+ break;
+ case QEvent::PaletteChange:
d->control->setPalette(palette());
- } else if (e->type() == QEvent::LayoutDirectionChange) {
+ break;
+ case QEvent::LayoutDirectionChange:
d->sendControlEvent(e);
+ break;
+ default:
+ break;
}
}
@@ -2491,32 +2474,18 @@ void QPlainTextEdit::setOverwriteMode(bool overwrite)
d->control->setOverwriteMode(overwrite);
}
-#if QT_DEPRECATED_SINCE(5, 10)
-/*!
- \property QPlainTextEdit::tabStopWidth
- \brief the tab stop width in pixels
- \deprecated in Qt 5.10. Use tabStopDistance instead.
-
- By default, this property contains a value of 80.
-*/
-
-int QPlainTextEdit::tabStopWidth() const
-{
- return qRound(tabStopDistance());
-}
-
-void QPlainTextEdit::setTabStopWidth(int width)
-{
- setTabStopDistance(width);
-}
-#endif
-
/*!
\property QPlainTextEdit::tabStopDistance
\brief the tab stop distance in pixels
\since 5.10
- By default, this property contains a value of 80.
+ By default, this property contains a value of 80 pixels.
+
+ Do not set a value less than the \l {QFontMetrics::}{horizontalAdvance()}
+ of the QChar::VisualTabCharacter character, otherwise the tab-character
+ will be drawn incompletely.
+
+ \sa QTextOption::ShowTabsAndSpaces, QTextDocument::defaultTextOption
*/
qreal QPlainTextEdit::tabStopDistance() const
@@ -2634,7 +2603,7 @@ void QPlainTextEdit::insertFromMimeData(const QMimeData *source)
bool QPlainTextEdit::isReadOnly() const
{
Q_D(const QPlainTextEdit);
- return !(d->control->textInteractionFlags() & Qt::TextEditable);
+ return !d->control || !(d->control->textInteractionFlags() & Qt::TextEditable);
}
void QPlainTextEdit::setReadOnly(bool ro)
@@ -2819,7 +2788,7 @@ void QPlainTextEdit::setLineWrapMode(LineWrapMode wrap)
d->lineWrap = wrap;
d->updateDefaultTextOption();
d->relayoutDocument();
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
ensureCursorVisible();
}
@@ -2905,7 +2874,7 @@ void QPlainTextEdit::setCenterOnScroll(bool enabled)
if (enabled == d->centerOnScroll)
return;
d->centerOnScroll = enabled;
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
}
@@ -2922,38 +2891,20 @@ bool QPlainTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
}
/*!
- \fn bool QPlainTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
-
- \since 5.3
- \overload
-
- Finds the next occurrence, matching the regular expression, \a exp, using the given
- \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
- use QRegExp::caseSensitivity instead.
-
- Returns \c true if a match was found and changes the cursor to select the match;
- otherwise returns \c false.
-*/
-#ifndef QT_NO_REGEXP
-bool QPlainTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
-{
- Q_D(QPlainTextEdit);
- return d->control->find(exp, options);
-}
-#endif
-
-/*!
\fn bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
\since 5.13
\overload
Finds the next occurrence, matching the regular expression, \a exp, using the given
- \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
- use QRegularExpression::CaseInsensitiveOption instead.
+ \a options.
Returns \c true if a match was found and changes the cursor to select the match;
otherwise returns \c false.
+
+ \warning For historical reasons, the case sensitivity option set on
+ \a exp is ignored. Instead, the \a options are used to determine
+ if the search is case sensitive or not.
*/
#if QT_CONFIG(regularexpression)
bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
@@ -3054,12 +3005,17 @@ void QPlainTextEditPrivate::append(const QString &text, Qt::TextFormat format)
bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
documentLayout->priv()->blockDocumentSizeChanged = true;
- if (format == Qt::RichText)
+ switch (format) {
+ case Qt::RichText:
control->appendHtml(text);
- else if (format == Qt::PlainText)
+ break;
+ case Qt::PlainText:
control->appendPlainText(text);
- else
+ break;
+ default:
control->append(text);
+ break;
+ }
if (maximumBlockCount > 0) {
if (document->blockCount() > maximumBlockCount) {
@@ -3081,7 +3037,7 @@ void QPlainTextEditPrivate::append(const QString &text, Qt::TextFormat format)
}
documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
- _q_adjustScrollbars();
+ adjustScrollbars();
if (atBottom) {
diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h
index a5945d649a..89a4d3ab04 100644
--- a/src/widgets/widgets/qplaintextedit.h
+++ b/src/widgets/widgets/qplaintextedit.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLAINTEXTEDIT_H
#define QPLAINTEXTEDIT_H
@@ -74,12 +38,10 @@ class Q_WIDGETS_EXPORT QPlainTextEdit : public QAbstractScrollArea
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText NOTIFY textChanged USER true)
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
-#if QT_DEPRECATED_SINCE(5, 10)
- Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth)
-#endif
Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance)
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
- Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags
+ WRITE setTextInteractionFlags)
Q_PROPERTY(int blockCount READ blockCount)
Q_PROPERTY(int maximumBlockCount READ maximumBlockCount WRITE setMaximumBlockCount)
Q_PROPERTY(bool backgroundVisible READ backgroundVisible WRITE setBackgroundVisible)
@@ -147,9 +109,6 @@ public:
bool centerOnScroll() const;
bool find(const QString &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
-#ifndef QT_NO_REGEXP
- bool find(const QRegExp &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
-#endif
#if QT_CONFIG(regularexpression)
bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
#endif
@@ -174,11 +133,6 @@ public:
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
-#if QT_DEPRECATED_SINCE(5, 10)
- QT_DEPRECATED int tabStopWidth() const;
- QT_DEPRECATED void setTabStopWidth(int width);
-#endif
-
qreal tabStopDistance() const;
void setTabStopDistance(qreal distance);
@@ -286,11 +240,6 @@ protected:
private:
Q_DISABLE_COPY(QPlainTextEdit)
- Q_PRIVATE_SLOT(d_func(), void _q_repaintContents(const QRectF &r))
- Q_PRIVATE_SLOT(d_func(), void _q_textChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_adjustScrollbars())
- Q_PRIVATE_SLOT(d_func(), void _q_verticalScrollbarActionTriggered(int))
- Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
friend class QPlainTextEditControl;
};
diff --git a/src/widgets/widgets/qplaintextedit_p.h b/src/widgets/widgets/qplaintextedit_p.h
index 534f0d4681..9ca1cdcc67 100644
--- a/src/widgets/widgets/qplaintextedit_p.h
+++ b/src/widgets/widgets/qplaintextedit_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLAINTEXTEDIT_P_H
#define QPLAINTEXTEDIT_P_H
@@ -68,6 +32,8 @@
#include "private/qwidgettextcontrol_p.h"
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(textedit);
QT_BEGIN_NAMESPACE
@@ -120,14 +86,14 @@ public:
QPlainTextEditPrivate();
void init(const QString &txt = QString());
- void _q_repaintContents(const QRectF &contentsRect);
- void _q_textChanged();
+ void repaintContents(const QRectF &contentsRect);
+ void updatePlaceholderVisibility();
inline QPoint mapToContents(const QPoint &point) const
{ return QPoint(point.x() + horizontalOffset(), point.y() + verticalOffset()); }
- void _q_adjustScrollbars();
- void _q_verticalScrollbarActionTriggered(int action);
+ void adjustScrollbars();
+ void verticalScrollbarActionTriggered(int action);
void ensureViewportLayouted();
void relayoutDocument();
@@ -143,25 +109,29 @@ public:
void updateDefaultTextOption();
- QPlainTextEditControl *control;
-
- bool tabChangesFocus;
-
QBasicTimer autoScrollTimer;
+#ifdef QT_KEYPAD_NAVIGATION
+ QBasicTimer deleteAllTimer;
+#endif
QPoint autoScrollDragPos;
+ QString placeholderText;
- QPlainTextEdit::LineWrapMode lineWrap;
- QTextOption::WrapMode wordWrap;
+ QPlainTextEditControl *control = nullptr;
+ qreal topLineFracture = 0; // for non-int sized fonts
+ qreal pageUpDownLastCursorY = 0;
+ QPlainTextEdit::LineWrapMode lineWrap = QPlainTextEdit::WidgetWidth;
+ QTextOption::WrapMode wordWrap = QTextOption::WrapAtWordBoundaryOrAnywhere;
+ int originalOffsetY = 0;
+ int topLine = 0;
+ uint tabChangesFocus : 1;
uint showCursorOnInitialShow : 1;
uint backgroundVisible : 1;
uint centerOnScroll : 1;
uint inDrag : 1;
uint clickCausedFocus : 1;
- uint placeholderVisible : 1;
-
- int topLine;
- qreal topLineFracture; // for non-int sized fonts
+ uint pageUpDownLastCursorYIsValid : 1;
+ uint placeholderTextShown : 1;
void setTopLine(int visualTopLine, int dx = 0);
void setTopBlock(int newTopBlock, int newTopLine, int dx = 0);
@@ -174,19 +144,13 @@ public:
void append(const QString &text, Qt::TextFormat format = Qt::AutoText);
- qreal pageUpDownLastCursorY;
- bool pageUpDownLastCursorYIsValid;
-
-
-#ifdef QT_KEYPAD_NAVIGATION
- QBasicTimer deleteAllTimer;
-#endif
-
- void _q_cursorPositionChanged();
- void _q_modificationChanged(bool);
-
- int originalOffsetY;
- QString placeholderText;
+ void cursorPositionChanged();
+ void modificationChanged(bool);
+ inline bool placeHolderTextToBeShown() const
+ {
+ Q_Q(const QPlainTextEdit);
+ return q->document()->isEmpty() && !q->placeholderText().isEmpty();
+ }
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp
index 04241fda09..79cdecd22a 100644
--- a/src/widgets/widgets/qprogressbar.cpp
+++ b/src/widgets/widgets/qprogressbar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qprogressbar.h"
@@ -45,13 +9,15 @@
#include <qstylepainter.h>
#include <qstyleoption.h>
#include <private/qwidget_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <qaccessible.h>
#endif
#include <limits.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QProgressBarPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QProgressBar)
@@ -89,7 +55,7 @@ QProgressBarPrivate::QProgressBarPrivate()
void QProgressBarPrivate::initDefaultFormat()
{
if (defaultFormat)
- format = QLatin1String("%p") + locale.percent();
+ format = "%p"_L1 + locale.percent();
}
void QProgressBarPrivate::init()
@@ -107,6 +73,8 @@ void QProgressBarPrivate::resetLayoutItemMargins()
{
Q_Q(QProgressBar);
QStyleOptionProgressBar option;
+ // ### It seems like this can be called directly from the constructor which should be avoided
+ // ### if possible, since we will not call a possible re-implemented version
q->initStyleOption(&option);
setLayoutItemMargins(QStyle::SE_ProgressBarLayoutItem, &option);
}
@@ -133,7 +101,6 @@ void QProgressBar::initStyleOption(QStyleOptionProgressBar *option) const
option->textAlignment = d->alignment;
option->textVisible = d->textVisible;
option->text = text();
- option->orientation = d->orientation; // ### Qt 6: remove this member from QStyleOptionProgressBar
option->invertedAppearance = d->invertedAppearance;
option->bottomToTop = d->textDirection == QProgressBar::BottomToTop;
}
@@ -151,10 +118,9 @@ bool QProgressBarPrivate::repaintRequired() const
const auto totalSteps = qint64(maximum) - minimum;
if (textVisible) {
- if ((format.contains(QLatin1String("%v"))))
+ if (format.contains("%v"_L1))
return true;
- if ((format.contains(QLatin1String("%p"))
- && valueDifference >= qAbs(totalSteps / 100)))
+ if (format.contains("%p"_L1) && valueDifference >= qAbs(totalSteps / 100))
return true;
}
@@ -200,7 +166,7 @@ bool QProgressBarPrivate::repaintRequired() const
example, when using QNetworkAccessManager to download items when
they are unable to determine the size of the item being downloaded.
- \sa QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator}
+ \sa QProgressDialog
*/
/*!
@@ -317,7 +283,7 @@ void QProgressBar::setValue(int value)
return;
d->value = value;
emit valueChanged(value);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (isVisible()) {
QAccessibleValueChangeEvent event(this, value);
QAccessible::updateAccessibility(&event);
@@ -421,8 +387,8 @@ QSize QProgressBar::sizeHint() const
QStyleOptionProgressBar opt;
initStyleOption(&opt);
int cw = style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &opt, this);
- QSize size = QSize(qMax(9, cw) * 7 + fm.horizontalAdvance(QLatin1Char('0')) * 4, fm.height() + 8);
- if (opt.orientation == Qt::Vertical)
+ QSize size = QSize(qMax(9, cw) * 7 + fm.horizontalAdvance(u'0') * 4, fm.height() + 8);
+ if (!(opt.state & QStyle::State_Horizontal))
size = size.transposed();
return style()->sizeFromContents(QStyle::CT_ProgressBar, &opt, size, this);
}
@@ -467,19 +433,19 @@ QString QProgressBar::text() const
QString result = d->format;
QLocale locale = d->locale; // Omit group separators for compatibility with previous versions that were non-localized.
locale.setNumberOptions(locale.numberOptions() | QLocale::OmitGroupSeparator);
- result.replace(QLatin1String("%m"), locale.toString(totalSteps));
- result.replace(QLatin1String("%v"), locale.toString(d->value));
+ result.replace("%m"_L1, locale.toString(totalSteps));
+ result.replace("%v"_L1, locale.toString(d->value));
// If max and min are equal and we get this far, it means that the
// progress bar has one step and that we are on that step. Return
// 100% here in order to avoid division by zero further down.
if (totalSteps == 0) {
- result.replace(QLatin1String("%p"), locale.toString(100));
+ result.replace("%p"_L1, locale.toString(100));
return result;
}
const auto progress = static_cast<int>((qint64(d->value) - d->minimum) * 100.0 / totalSteps);
- result.replace(QLatin1String("%p"), locale.toString(progress));
+ result.replace("%p"_L1, locale.toString(progress));
return result;
}
diff --git a/src/widgets/widgets/qprogressbar.h b/src/widgets/widgets/qprogressbar.h
index ec9686068c..96b2993ec2 100644
--- a/src/widgets/widgets/qprogressbar.h
+++ b/src/widgets/widgets/qprogressbar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROGRESSBAR_H
#define QPROGRESSBAR_H
@@ -111,7 +75,7 @@ Q_SIGNALS:
protected:
bool event(QEvent *e) override;
void paintEvent(QPaintEvent *) override;
- void initStyleOption(QStyleOptionProgressBar *option) const;
+ virtual void initStyleOption(QStyleOptionProgressBar *option) const;
private:
Q_DECLARE_PRIVATE(QProgressBar)
diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp
index b0d3ba51f9..c180a08d62 100644
--- a/src/widgets/widgets/qpushbutton.cpp
+++ b/src/widgets/widgets/qpushbutton.cpp
@@ -1,46 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qbitmap.h"
-#include "qdesktopwidget.h"
-#include <private/qdesktopwidget_p.h>
#if QT_CONFIG(dialog)
#include <private/qdialog_p.h>
#endif
@@ -62,7 +24,7 @@
#include "qdialogbuttonbox.h"
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
@@ -173,7 +135,7 @@ QT_BEGIN_NAMESPACE
and other API, and QPushButton provides GUI logic.
See QAbstractButton for more information about the API.
- \sa QToolButton, QRadioButton, QCheckBox, {fowler}{GUI Design Handbook: Push Button}
+ \sa QToolButton, QRadioButton, QCheckBox
*/
/*!
@@ -332,6 +294,8 @@ void QPushButton::initStyleOption(QStyleOptionButton *option) const
option->state |= QStyle::State_On;
if (!d->flat && !d->down)
option->state |= QStyle::State_Raised;
+ if (underMouse() && hasMouseTracking())
+ option->state.setFlag(QStyle::State_MouseOver, d->hovering);
option->text = d->text;
option->icon = d->icon;
option->iconSize = iconSize();
@@ -352,7 +316,7 @@ void QPushButton::setAutoDefault(bool enable)
bool QPushButton::autoDefault() const
{
Q_D(const QPushButton);
- if(d->autoDefault == QPushButtonPrivate::Auto)
+ if (d->autoDefault == QPushButtonPrivate::Auto)
return ( d->dialogParent() != nullptr );
return d->autoDefault;
}
@@ -370,7 +334,7 @@ void QPushButton::setDefault(bool enable)
}
#endif
update();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State s;
s.defaultButton = true;
QAccessibleStateChangeEvent event(this, s);
@@ -418,17 +382,16 @@ QSize QPushButton::sizeHint() const
s = QStringLiteral("XXXX");
QFontMetrics fm = fontMetrics();
QSize sz = fm.size(Qt::TextShowMnemonic, s);
- if(!empty || !w)
+ if (!empty || !w)
w += sz.width();
- if(!empty || !h)
+ if (!empty || !h)
h = qMax(h, sz.height());
opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height
#if QT_CONFIG(menu)
if (menu())
w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
#endif
- d->sizeHint = (style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), this).
- expandedTo(QApplication::globalStrut()));
+ d->sizeHint = style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), this);
return d->sizeHint;
}
@@ -509,6 +472,38 @@ void QPushButton::focusOutEvent(QFocusEvent *e)
#endif
}
+/*!
+ \reimp
+*/
+void QPushButton::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(QPushButton);
+
+ if (testAttribute(Qt::WA_Hover)) {
+ bool hit = false;
+ if (underMouse())
+ hit = hitButton(e->position().toPoint());
+
+ if (hit != d->hovering) {
+ update(rect());
+ d->hovering = hit;
+ }
+ }
+
+ QAbstractButton::mouseMoveEvent(e);
+}
+
+/*!
+ \reimp
+*/
+bool QPushButton::hitButton(const QPoint &pos) const
+{
+ QStyleOptionButton option;
+ initStyleOption(&option);
+ const QRect bevel = style()->subElementRect(QStyle::SE_PushButtonBevel, &option, this);
+ return bevel.contains(pos);
+}
+
#if QT_CONFIG(menu)
/*!
Associates the popup menu \a menu with this push button. This
@@ -530,7 +525,8 @@ void QPushButton::setMenu(QMenu* menu)
return;
if (menu && !d->menu) {
- connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()), Qt::UniqueConnection);
+ QObjectPrivate::connect(this, &QPushButton::pressed,
+ d, &QPushButtonPrivate::popupPressed, Qt::UniqueConnection);
}
if (d->menu)
removeAction(d->menu->menuAction());
@@ -567,10 +563,10 @@ void QPushButton::showMenu()
if (!d || !d->menu)
return;
setDown(true);
- d->_q_popupPressed();
+ d->popupPressed();
}
-void QPushButtonPrivate::_q_popupPressed()
+void QPushButtonPrivate::popupPressed()
{
Q_Q(QPushButton);
if (!down || !menu)
@@ -580,17 +576,14 @@ void QPushButtonPrivate::_q_popupPressed()
QPoint menuPos = adjustedMenuPosition();
- QPointer<QPushButton> guard(q);
- QMenuPrivate::get(menu)->causedPopup.widget = guard;
+ QMenuPrivate::get(menu)->causedPopup.widget = q;
//Because of a delay in menu effects, we must keep track of the
//menu visibility to avoid flicker on button release
menuOpen = true;
- menu->exec(menuPos);
- if (guard) {
- menuOpen = false;
- q->setDown(false);
- }
+ QObject::connect(menu, &QMenu::aboutToHide,
+ q, [q, this]{ menuOpen = false; q->setDown(false); }, Qt::SingleShotConnection);
+ menu->popup(menuPos);
}
QPoint QPushButtonPrivate::adjustedMenuPosition()
@@ -612,7 +605,7 @@ QPoint QPushButtonPrivate::adjustedMenuPosition()
QPoint globalPos = q->mapToGlobal(rect.topLeft());
int x = globalPos.x();
int y = globalPos.y();
- const QRect availableGeometry = QDesktopWidgetPrivate::availableGeometry(q);
+ const QRect availableGeometry = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
if (horizontal) {
if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) {
y += rect.height();
@@ -634,6 +627,13 @@ QPoint QPushButtonPrivate::adjustedMenuPosition()
#endif // QT_CONFIG(menu)
+void QPushButtonPrivate::init()
+{
+ Q_Q(QPushButton);
+ q->setAttribute(Qt::WA_MacShowFocusRect);
+ resetLayoutItemMargins();
+}
+
void QPushButtonPrivate::resetLayoutItemMargins()
{
Q_Q(QPushButton);
diff --git a/src/widgets/widgets/qpushbutton.h b/src/widgets/widgets/qpushbutton.h
index b02ba63d07..3c420b5313 100644
--- a/src/widgets/widgets/qpushbutton.h
+++ b/src/widgets/widgets/qpushbutton.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPUSHBUTTON_H
#define QPUSHBUTTON_H
@@ -93,17 +57,14 @@ protected:
void keyPressEvent(QKeyEvent *) override;
void focusInEvent(QFocusEvent *) override;
void focusOutEvent(QFocusEvent *) override;
- void initStyleOption(QStyleOptionButton *option) const;
+ void mouseMoveEvent(QMouseEvent *) override;
+ virtual void initStyleOption(QStyleOptionButton *option) const;
+ bool hitButton(const QPoint &pos) const override;
QPushButton(QPushButtonPrivate &dd, QWidget* parent = nullptr);
-public:
-
private:
Q_DISABLE_COPY(QPushButton)
Q_DECLARE_PRIVATE(QPushButton)
-#if QT_CONFIG(menu)
- Q_PRIVATE_SLOT(d_func(), void _q_popupPressed())
-#endif
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qpushbutton_p.h b/src/widgets/widgets/qpushbutton_p.h
index 439b6e35d6..0817589baf 100644
--- a/src/widgets/widgets/qpushbutton_p.h
+++ b/src/widgets/widgets/qpushbutton_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPUSHBUTTON_P_H
#define QPUSHBUTTON_P_H
@@ -43,6 +7,8 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "private/qabstractbutton_p.h"
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(pushbutton);
//
@@ -69,19 +35,21 @@ public:
QPushButtonPrivate()
: QAbstractButtonPrivate(QSizePolicy::PushButton), autoDefault(Auto),
- defaultButton(false), flat(false), menuOpen(false), lastAutoDefault(false) {}
+ defaultButton(false), flat(false), menuOpen(false), hovering(false),
+ lastAutoDefault(false)
+ {}
- inline void init() { resetLayoutItemMargins(); }
+ void init();
static QPushButtonPrivate* get(QPushButton *b) { return b->d_func(); }
#if QT_CONFIG(menu)
QPoint adjustedMenuPosition();
#endif
void resetLayoutItemMargins();
- void _q_popupPressed();
+ void popupPressed();
#if QT_CONFIG(dialog)
QDialog *dialogParent() const;
#else
- QDialog *dialogParent() const { return 0; };
+ QDialog *dialogParent() const { return nullptr; }
#endif
QPointer<QMenu> menu;
@@ -89,6 +57,7 @@ public:
uint defaultButton : 1;
uint flat : 1;
uint menuOpen : 1;
+ uint hovering : 1;
mutable uint lastAutoDefault : 1;
};
diff --git a/src/widgets/widgets/qradiobutton.cpp b/src/widgets/widgets/qradiobutton.cpp
index fd8922ed28..af1bd3f649 100644
--- a/src/widgets/widgets/qradiobutton.cpp
+++ b/src/widgets/widgets/qradiobutton.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qradiobutton.h"
#include "qapplication.h"
@@ -118,8 +82,7 @@ void QRadioButtonPrivate::init()
setDown(), isDown(), autoRepeat(), group(), setAutoRepeat(),
toggle(), pressed(), released(), clicked(), and toggled().
- \sa QPushButton, QToolButton, QCheckBox, {fowler}{GUI Design Handbook: Radio Button},
- {Group Box Example}
+ \sa QPushButton, QToolButton, QCheckBox
*/
@@ -195,8 +158,7 @@ QSize QRadioButton::sizeHint() const
false, text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
- d->sizeHint = (style()->sizeFromContents(QStyle::CT_RadioButton, &opt, sz, this).
- expandedTo(QApplication::globalStrut()));
+ d->sizeHint = style()->sizeFromContents(QStyle::CT_RadioButton, &opt, sz, this);
return d->sizeHint;
}
@@ -227,7 +189,7 @@ void QRadioButton::mouseMoveEvent(QMouseEvent *e)
if (testAttribute(Qt::WA_Hover)) {
bool hit = false;
if (underMouse())
- hit = hitButton(e->pos());
+ hit = hitButton(e->position().toPoint());
if (hit != d->hovering) {
update();
diff --git a/src/widgets/widgets/qradiobutton.h b/src/widgets/widgets/qradiobutton.h
index c6b5ddce84..7a59b186d1 100644
--- a/src/widgets/widgets/qradiobutton.h
+++ b/src/widgets/widgets/qradiobutton.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRADIOBUTTON_H
#define QRADIOBUTTON_H
@@ -68,7 +32,7 @@ protected:
bool hitButton(const QPoint &) const override;
void paintEvent(QPaintEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
- void initStyleOption(QStyleOptionButton *button) const;
+ virtual void initStyleOption(QStyleOptionButton *button) const;
private:
diff --git a/src/widgets/widgets/qrubberband.cpp b/src/widgets/widgets/qrubberband.cpp
index af730f8023..e00f739ca7 100644
--- a/src/widgets/widgets/qrubberband.cpp
+++ b/src/widgets/widgets/qrubberband.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitmap.h"
#include "qevent.h"
diff --git a/src/widgets/widgets/qrubberband.h b/src/widgets/widgets/qrubberband.h
index c683c24a18..76d60b642b 100644
--- a/src/widgets/widgets/qrubberband.h
+++ b/src/widgets/widgets/qrubberband.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRUBBERBAND_H
#define QRUBBERBAND_H
@@ -79,7 +43,7 @@ protected:
void showEvent(QShowEvent *) override;
void resizeEvent(QResizeEvent *) override;
void moveEvent(QMoveEvent *) override;
- void initStyleOption(QStyleOptionRubberBand *option) const;
+ virtual void initStyleOption(QStyleOptionRubberBand *option) const;
private:
Q_DECLARE_PRIVATE(QRubberBand)
diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp
index ce08e3439a..efbf4da07f 100644
--- a/src/widgets/widgets/qscrollarea.cpp
+++ b/src/widgets/widgets/qscrollarea.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qscrollarea.h"
#include "private/qscrollarea_p.h"
@@ -127,11 +91,7 @@ QT_BEGIN_NAMESPACE
cause the size of the scroll area to be updated whenever the
contents of the layout changes.
- For a complete example using the QScrollArea class, see the \l
- {widgets/imageviewer}{Image Viewer} example. The example shows how
- to combine QLabel and QScrollArea to display an image.
-
- \sa QAbstractScrollArea, QScrollBar, {Image Viewer Example}
+ \sa QAbstractScrollArea, QScrollBar
*/
@@ -196,7 +156,23 @@ void QScrollAreaPrivate::updateScrollBars()
if (resizable) {
if ((widget->layout() ? widget->layout()->hasHeightForWidth() : widget->sizePolicy().hasHeightForWidth())) {
QSize p_hfw = p.expandedTo(min).boundedTo(max);
- int h = widget->heightForWidth( p_hfw.width() );
+ int h = widget->heightForWidth(p_hfw.width());
+ // If the height we calculated requires a vertical scrollbar,
+ // then we need to constrain the width and calculate the height again,
+ // otherwise we end up flipping the scrollbar on and off all the time.
+ if (vbarpolicy == Qt::ScrollBarAsNeeded) {
+ int vbarWidth = vbar->sizeHint().width();
+ QSize m_hfw = m.expandedTo(min).boundedTo(max);
+ // is there any point in searching?
+ if (widget->heightForWidth(m_hfw.width() - vbarWidth) <= m.height()) {
+ while (h > m.height() && vbarWidth) {
+ --vbarWidth;
+ --m_hfw.rwidth();
+ h = widget->heightForWidth(m_hfw.width());
+ }
+ }
+ max = QSize(m_hfw.width(), qMax(m_hfw.height(), h));
+ }
min = QSize(p_hfw.width(), qMax(p_hfw.height(), h));
}
}
@@ -490,14 +466,14 @@ void QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin, int yma
if (focusRect.width() > visibleRect.width())
d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2);
else if (focusRect.right() > visibleRect.right())
- d->hbar->setValue(focusRect.right() - d->viewport->width());
+ d->hbar->setValue(focusRect.right() - d->viewport->width() + 1);
else if (focusRect.left() < visibleRect.left())
d->hbar->setValue(focusRect.left());
if (focusRect.height() > visibleRect.height())
d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2);
else if (focusRect.bottom() > visibleRect.bottom())
- d->vbar->setValue(focusRect.bottom() - d->viewport->height());
+ d->vbar->setValue(focusRect.bottom() - d->viewport->height() + 1);
else if (focusRect.top() < visibleRect.top())
d->vbar->setValue(focusRect.top());
}
diff --git a/src/widgets/widgets/qscrollarea.h b/src/widgets/widgets/qscrollarea.h
index 6d252821c5..7486a121ea 100644
--- a/src/widgets/widgets/qscrollarea.h
+++ b/src/widgets/widgets/qscrollarea.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCROLLAREA_H
#define QSCROLLAREA_H
diff --git a/src/widgets/widgets/qscrollarea_p.h b/src/widgets/widgets/qscrollarea_p.h
index 26335285a4..a599fa8c36 100644
--- a/src/widgets/widgets/qscrollarea_p.h
+++ b/src/widgets/widgets/qscrollarea_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCROLLAREA_P_H
#define QSCROLLAREA_P_H
@@ -56,6 +20,8 @@
#include "private/qabstractscrollarea_p.h"
#include <QtWidgets/qscrollbar.h>
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(scrollarea);
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp
index 2ce1d50c86..789cffba99 100644
--- a/src/widgets/widgets/qscrollbar.cpp
+++ b/src/widgets/widgets/qscrollbar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qcursor.h"
@@ -44,12 +8,16 @@
#include "qscrollbar.h"
#include "qstyle.h"
#include "qstyleoption.h"
+#include "qstylepainter.h"
#if QT_CONFIG(menu)
#include "qmenu.h"
#endif
+
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qpointer.h>
+
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <limits.h>
@@ -175,7 +143,7 @@ QT_BEGIN_NAMESPACE
\li Up/Down move a vertical scroll bar by one single step.
\li PageUp moves up one page.
\li PageDown moves down one page.
- \li Home moves to the start (mininum).
+ \li Home moves to the start (minimum).
\li End moves to the end (maximum).
\endlist
@@ -187,7 +155,7 @@ QT_BEGIN_NAMESPACE
Most GUI styles use the pageStep() value to calculate the size of the
slider.
- \sa QScrollArea, QSlider, QDial, QSpinBox, {fowler}{GUI Design Handbook: Scroll Bar}, {Sliders Example}
+ \sa QScrollArea, QSlider, QDial, QSpinBox, {Sliders Example}
*/
bool QScrollBarPrivate::updateHoverControl(const QPoint &pos)
@@ -224,7 +192,9 @@ void QScrollBarPrivate::setTransient(bool value)
if (transient != value) {
transient = value;
if (q->isVisible()) {
- if (q->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, q))
+ QStyleOptionSlider opt;
+ q->initStyleOption(&opt);
+ if (q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q))
q->update();
} else if (!transient) {
q->show();
@@ -235,7 +205,9 @@ void QScrollBarPrivate::setTransient(bool value)
void QScrollBarPrivate::flash()
{
Q_Q(QScrollBar);
- if (!flashed && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, q)) {
+ QStyleOptionSlider opt;
+ q->initStyleOption(&opt);
+ if (!flashed && q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q)) {
flashed = true;
if (!q->isVisible())
q->show();
@@ -319,7 +291,7 @@ void QScrollBar::initStyleOption(QStyleOptionSlider *option) const
option->upsideDown = d->invertedAppearance;
if (d->orientation == Qt::Horizontal)
option->state |= QStyle::State_Horizontal;
- if ((d->flashed || !d->transient) && style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this))
+ if ((d->flashed || !d->transient) && style()->styleHint(QStyle::SH_ScrollBar_Transient, option, this))
option->state |= QStyle::State_On;
}
@@ -376,7 +348,9 @@ void QScrollBarPrivate::init()
invertedControls = true;
pressedControl = hoverControl = QStyle::SC_None;
pointerOutsidePressedControl = false;
- transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, q);
+ QStyleOption opt;
+ opt.initFrom(q);
+ transient = q->style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, q);
flashed = false;
flashTimer = 0;
q->setFocusPolicy(Qt::NoFocus);
@@ -448,8 +422,7 @@ QSize QScrollBar::sizeHint() const
else
size = QSize(scrollBarExtent, scrollBarExtent * 2 + scrollBarSliderMin);
- return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this)
- .expandedTo(QApplication::globalStrut());
+ return style()->sizeFromContents(QStyle::CT_ScrollBar, &opt, size, this);
}
/*!\reimp */
@@ -469,14 +442,19 @@ bool QScrollBar::event(QEvent *event)
case QEvent::HoverLeave:
case QEvent::HoverMove:
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
- d_func()->updateHoverControl(he->pos());
+ d_func()->updateHoverControl(he->position().toPoint());
break;
- case QEvent::StyleChange:
- d_func()->setTransient(style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this));
+ case QEvent::StyleChange: {
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ d_func()->setTransient(style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, this));
break;
+ }
case QEvent::Timer:
if (static_cast<QTimerEvent *>(event)->timerId() == d->flashTimer) {
- if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this)) {
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, &opt, this)) {
d->flashed = false;
update();
}
@@ -526,7 +504,7 @@ void QScrollBar::wheelEvent(QWheelEvent *event)
void QScrollBar::paintEvent(QPaintEvent *)
{
Q_D(QScrollBar);
- QPainter p(this);
+ QStylePainter p(this);
QStyleOptionSlider opt;
initStyleOption(&opt);
opt.subControls = QStyle::SC_All;
@@ -537,7 +515,7 @@ void QScrollBar::paintEvent(QPaintEvent *)
} else {
opt.activeSubControls = (QStyle::SubControl)d->hoverControl;
}
- style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this);
+ p.drawComplexControl(QStyle::CC_ScrollBar, opt);
}
/*!
@@ -554,18 +532,19 @@ void QScrollBar::mousePressEvent(QMouseEvent *e)
nullptr, this);
QStyleOptionSlider opt;
initStyleOption(&opt);
+ opt.keyboardModifiers = e->modifiers();
if (d->maximum == d->minimum // no range
|| (e->buttons() & (~e->button())) // another button was clicked before
- || !(e->button() == Qt::LeftButton || (midButtonAbsPos && e->button() == Qt::MidButton)))
+ || !(e->button() == Qt::LeftButton || (midButtonAbsPos && e->button() == Qt::MiddleButton)))
return;
- d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this);
+ d->pressedControl = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->position().toPoint(), this);
d->pointerOutsidePressedControl = false;
QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt,
QStyle::SC_ScrollBarSlider, this);
- QPoint click = e->pos();
+ QPoint click = e->position().toPoint();
QPoint pressValue = click - sr.center() + sr.topLeft();
d->pressValue = d->orientation == Qt::Horizontal ? d->pixelPosToRangeValue(pressValue.x()) :
d->pixelPosToRangeValue(pressValue.y());
@@ -576,12 +555,12 @@ void QScrollBar::mousePressEvent(QMouseEvent *e)
if ((d->pressedControl == QStyle::SC_ScrollBarAddPage
|| d->pressedControl == QStyle::SC_ScrollBarSubPage)
- && ((midButtonAbsPos && e->button() == Qt::MidButton)
+ && ((midButtonAbsPos && e->button() == Qt::MiddleButton)
|| (style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition, &opt, this)
&& e->button() == Qt::LeftButton))) {
int sliderLength = HORIZONTAL ? sr.width() : sr.height();
- setSliderPosition(d->pixelPosToRangeValue((HORIZONTAL ? e->pos().x()
- : e->pos().y()) - sliderLength / 2));
+ setSliderPosition(d->pixelPosToRangeValue((HORIZONTAL ? e->position().toPoint().x()
+ : e->position().toPoint().y()) - sliderLength / 2));
d->pressedControl = QStyle::SC_ScrollBarSlider;
d->clickOffset = sliderLength / 2;
}
@@ -632,18 +611,18 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e)
QStyleOptionSlider opt;
initStyleOption(&opt);
if (!(e->buttons() & Qt::LeftButton
- || ((e->buttons() & Qt::MidButton)
+ || ((e->buttons() & Qt::MiddleButton)
&& style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition, &opt, this))))
return;
if (d->pressedControl == QStyle::SC_ScrollBarSlider) {
- QPoint click = e->pos();
+ QPoint click = e->position().toPoint();
int newPosition = d->pixelPosToRangeValue((HORIZONTAL ? click.x() : click.y()) -d->clickOffset);
int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this);
if (m >= 0) {
QRect r = rect();
r.adjust(-m, -m, m, m);
- if (! r.contains(e->pos()))
+ if (! r.contains(e->position().toPoint()))
newPosition = d->snapBackPosition;
}
setSliderPosition(newPosition);
@@ -651,7 +630,7 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e)
if (style()->styleHint(QStyle::SH_ScrollBar_RollBetweenButtons, &opt, this)
&& d->pressedControl & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) {
- QStyle::SubControl newSc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->pos(), this);
+ QStyle::SubControl newSc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, e->position().toPoint(), this);
if (newSc == d->pressedControl && !d->pointerOutsidePressedControl)
return; // nothing to do
if (newSc & (QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine)) {
@@ -668,7 +647,7 @@ void QScrollBar::mouseMoveEvent(QMouseEvent *e)
// stop scrolling when the mouse pointer leaves a control
// similar to push buttons
QRect pr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this);
- if (pr.contains(e->pos()) == d->pointerOutsidePressedControl) {
+ if (pr.contains(e->position().toPoint()) == d->pointerOutsidePressedControl) {
if ((d->pointerOutsidePressedControl = !d->pointerOutsidePressedControl)) {
d->pointerOutsidePressedControl = true;
setRepeatAction(SliderNoAction);
diff --git a/src/widgets/widgets/qscrollbar.h b/src/widgets/widgets/qscrollbar.h
index 171195fd24..9fd8f617ab 100644
--- a/src/widgets/widgets/qscrollbar.h
+++ b/src/widgets/widgets/qscrollbar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCROLLBAR_H
#define QSCROLLBAR_H
@@ -76,7 +40,7 @@ protected:
#ifndef QT_NO_CONTEXTMENU
void contextMenuEvent(QContextMenuEvent *) override;
#endif
- void initStyleOption(QStyleOptionSlider *option) const;
+ virtual void initStyleOption(QStyleOptionSlider *option) const;
private:
diff --git a/src/widgets/widgets/qscrollbar_p.h b/src/widgets/widgets/qscrollbar_p.h
index 8693495c6f..1c8d07608d 100644
--- a/src/widgets/widgets/qscrollbar_p.h
+++ b/src/widgets/widgets/qscrollbar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCROLLBAR_P_H
#define QSCROLLBAR_P_H
diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp
index 2a4b4a0ad4..2500983450 100644
--- a/src/widgets/widgets/qsizegrip.cpp
+++ b/src/widgets/widgets/qsizegrip.cpp
@@ -1,59 +1,25 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsizegrip.h"
#include "qapplication.h"
#include "qevent.h"
-#include "qpainter.h"
+#include "qstylepainter.h"
#include "qwindow.h"
#include <qpa/qplatformwindow.h>
#include "qstyle.h"
#include "qstyleoption.h"
#include "qlayout.h"
#include "qdebug.h"
-#include <QDesktopWidget>
#include <private/qwidget_p.h>
-#include <private/qdesktopwidget_p.h>
+#include "private/qapplication_p.h"
+#include <qpa/qplatformtheme.h>
#include <QtWidgets/qabstractscrollarea.h>
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
static QWidget *qt_sizegrip_topLevelWidget(QWidget* w)
@@ -109,7 +75,7 @@ public:
void _q_showIfNotHidden()
{
Q_Q(QSizeGrip);
- bool showSizeGrip = !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ bool showSizeGrip = !isExplicitlyHidden();
updateTopLevelWidget();
if (tlw && showSizeGrip) {
Qt::WindowStates sizeGripNotVisibleState = Qt::WindowFullScreen;
@@ -173,6 +139,10 @@ Qt::Corner QSizeGripPrivate::corner() const
On some platforms the size grip automatically hides itself when the
window is shown full screen or maximised.
+ \note On macOS, size grips are no longer part of the human interface
+ guideline, and won't show unless used in a QMdiSubWindow. Set another
+ style on size grips that you want to be visible in main windows.
+
\table 50%
\row \li \inlineimage fusion-statusbar-sizegrip.png Screenshot of a Fusion style size grip
\li A size grip widget at the bottom-right corner of a main window, shown in the
@@ -229,9 +199,8 @@ QSizeGrip::~QSizeGrip()
QSize QSizeGrip::sizeHint() const
{
QStyleOption opt(0);
- opt.init(this);
- return (style()->sizeFromContents(QStyle::CT_SizeGrip, &opt, QSize(13, 13), this).
- expandedTo(QApplication::globalStrut()));
+ opt.initFrom(this);
+ return style()->sizeFromContents(QStyle::CT_SizeGrip, &opt, QSize(13, 13), this);
}
/*!
@@ -245,11 +214,11 @@ void QSizeGrip::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
Q_D(QSizeGrip);
- QPainter painter(this);
+ QStylePainter painter(this);
QStyleOptionSizeGrip opt;
- opt.init(this);
+ opt.initFrom(this);
opt.corner = d->m_corner;
- style()->drawControl(QStyle::CE_SizeGrip, &opt, &painter, this);
+ painter.drawControl(QStyle::CE_SizeGrip, opt);
}
/*!
@@ -260,6 +229,29 @@ void QSizeGrip::paintEvent(QPaintEvent *event)
parameter.
*/
+static Qt::Edges edgesFromCorner(Qt::Corner corner)
+{
+ switch (corner) {
+ case Qt::TopLeftCorner: return Qt::TopEdge | Qt::LeftEdge;
+ case Qt::TopRightCorner: return Qt::TopEdge | Qt::RightEdge;
+ case Qt::BottomLeftCorner: return Qt::BottomEdge | Qt::LeftEdge;
+ case Qt::BottomRightCorner: return Qt::BottomEdge | Qt::RightEdge;
+ }
+ return Qt::Edges{};
+}
+
+static bool usePlatformSizeGrip(const QWidget *tlw)
+{
+ const QString &platformName = QGuiApplication::platformName();
+ if (platformName.contains(u"xcb")) // ### FIXME QTBUG-69716
+ return false;
+ if (tlw->testAttribute(Qt::WA_TranslucentBackground)
+ && platformName == u"windows") {
+ return false; // QTBUG-90628, flicker when using translucency
+ }
+ return true;
+}
+
void QSizeGrip::mousePressEvent(QMouseEvent * e)
{
if (e->button() != Qt::LeftButton) {
@@ -269,7 +261,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
Q_D(QSizeGrip);
QWidget *tlw = qt_sizegrip_topLevelWidget(this);
- d->p = e->globalPos();
+ d->p = e->globalPosition().toPoint();
d->gotMousePress = true;
d->r = tlw->geometry();
@@ -279,10 +271,11 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
&& tlw->windowHandle()
&& !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen)
- && !tlw->hasHeightForWidth()) {
+ && !tlw->hasHeightForWidth()
+ && usePlatformSizeGrip(tlw)) {
QPlatformWindow *platformWindow = tlw->windowHandle()->handle();
- const QPoint topLevelPos = mapTo(tlw, e->pos());
- d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(topLevelPos, d->m_corner);
+ const Qt::Edges edges = edgesFromCorner(d->m_corner);
+ d->m_platformSizeGrip = platformWindow->startSystemResize(edges);
}
if (d->m_platformSizeGrip)
@@ -292,8 +285,12 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
QRect availableGeometry;
bool hasVerticalSizeConstraint = true;
bool hasHorizontalSizeConstraint = true;
- if (tlw->isWindow())
- availableGeometry = QDesktopWidgetPrivate::availableGeometry(tlw);
+ if (tlw->isWindow()) {
+ if (QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::InteractiveResizeAcrossScreens).toBool())
+ availableGeometry = tlw->screen()->availableVirtualGeometry();
+ else
+ availableGeometry = QWidgetPrivate::availableScreenGeometry(tlw);
+ }
else {
const QWidget *tlwParent = tlw->parentWidget();
// Check if tlw is inside QAbstractScrollArea/QScrollArea.
@@ -362,7 +359,7 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e)
if (!d->gotMousePress || tlw->testAttribute(Qt::WA_WState_ConfigPending))
return;
- QPoint np(e->globalPos());
+ QPoint np(e->globalPosition().toPoint());
// Don't extend beyond the available geometry; bound to dyMax and dxMax.
QSize ns;
@@ -454,7 +451,7 @@ void QSizeGrip::setVisible(bool visible)
bool QSizeGrip::eventFilter(QObject *o, QEvent *e)
{
Q_D(QSizeGrip);
- if ((isHidden() && testAttribute(Qt::WA_WState_ExplicitShowHide))
+ if (d->isExplicitlyHidden()
|| e->type() != QEvent::WindowStateChange
|| o != d->tlw) {
return QWidget::eventFilter(o, e);
diff --git a/src/widgets/widgets/qsizegrip.h b/src/widgets/widgets/qsizegrip.h
index 5285ffdfb8..c69b83e5d5 100644
--- a/src/widgets/widgets/qsizegrip.h
+++ b/src/widgets/widgets/qsizegrip.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIZEGRIP_H
#define QSIZEGRIP_H
diff --git a/src/widgets/widgets/qslider.cpp b/src/widgets/widgets/qslider.cpp
index 161e4ba27a..e39521a2e9 100644
--- a/src/widgets/widgets/qslider.cpp
+++ b/src/widgets/widgets/qslider.cpp
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qslider.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include "qapplication.h"
@@ -46,6 +10,7 @@
#include "qpainter.h"
#include "qstyle.h"
#include "qstyleoption.h"
+#include "qstylepainter.h"
#include "private/qapplication_p.h"
#include "private/qabstractslider_p.h"
#include "qdebug.h"
@@ -91,6 +56,8 @@ void QSliderPrivate::resetLayoutItemMargins()
{
Q_Q(QSlider);
QStyleOptionSlider opt;
+ // ### This is (also) reached from the ctor which is unfortunate since a possible
+ // ### re-implementation of initStyleOption is then not called.
q->initStyleOption(&opt);
setLayoutItemMargins(QStyle::SE_SliderLayoutItem, &opt);
}
@@ -153,6 +120,13 @@ void QSlider::initStyleOption(QStyleOptionSlider *option) const
option->pageStep = d->pageStep;
if (d->orientation == Qt::Horizontal)
option->state |= QStyle::State_Horizontal;
+
+ if (d->pressedControl) {
+ option->activeSubControls = d->pressedControl;
+ option->state |= QStyle::State_Sunken;
+ } else {
+ option->activeSubControls = d->hoverControl;
+ }
}
bool QSliderPrivate::updateHoverControl(const QPoint &pos)
@@ -250,11 +224,11 @@ QStyle::SubControl QSliderPrivate::newHoverControl(const QPoint &pos)
\li Up/Down move a vertical slider by one single step.
\li PageUp moves up one page.
\li PageDown moves down one page.
- \li Home moves to the start (mininum).
+ \li Home moves to the start (minimum).
\li End moves to the end (maximum).
\endlist
- \sa QScrollBar, QSpinBox, QDial, {fowler}{GUI Design Handbook: Slider}, {Sliders Example}
+ \sa QScrollBar, QSpinBox, QDial, {Sliders Example}
*/
@@ -308,21 +282,15 @@ QSlider::~QSlider()
void QSlider::paintEvent(QPaintEvent *)
{
Q_D(QSlider);
- QPainter p(this);
+ QStylePainter p(this);
QStyleOptionSlider opt;
initStyleOption(&opt);
opt.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
if (d->tickPosition != NoTicks)
opt.subControls |= QStyle::SC_SliderTickmarks;
- if (d->pressedControl) {
- opt.activeSubControls = d->pressedControl;
- opt.state |= QStyle::State_Sunken;
- } else {
- opt.activeSubControls = d->hoverControl;
- }
- style()->drawComplexControl(QStyle::CC_Slider, &opt, &p, this);
+ p.drawComplexControl(QStyle::CC_Slider, opt);
}
/*!
@@ -338,7 +306,7 @@ bool QSlider::event(QEvent *event)
case QEvent::HoverLeave:
case QEvent::HoverMove:
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
- d->updateHoverControl(he->pos());
+ d->updateHoverControl(he->position().toPoint());
break;
case QEvent::StyleChange:
case QEvent::MacSizeChange:
@@ -372,7 +340,7 @@ void QSlider::mousePressEvent(QMouseEvent *ev)
const QPoint center = sliderRect.center() - sliderRect.topLeft();
// to take half of the slider off for the setSliderPosition call we use the center - topLeft
- setSliderPosition(d->pixelPosToRangeValue(d->pick(ev->pos() - center)));
+ setSliderPosition(d->pixelPosToRangeValue(d->pick(ev->position().toPoint() - center)));
triggerAction(SliderMove);
setRepeatAction(SliderNoAction);
d->pressedControl = QStyle::SC_SliderHandle;
@@ -381,11 +349,11 @@ void QSlider::mousePressEvent(QMouseEvent *ev)
QStyleOptionSlider opt;
initStyleOption(&opt);
d->pressedControl = style()->hitTestComplexControl(QStyle::CC_Slider,
- &opt, ev->pos(), this);
+ &opt, ev->position().toPoint(), this);
SliderAction action = SliderNoAction;
if (d->pressedControl == QStyle::SC_SliderGroove) {
const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
- int pressValue = d->pixelPosToRangeValue(d->pick(ev->pos() - sliderRect.center() + sliderRect.topLeft()));
+ int pressValue = d->pixelPosToRangeValue(d->pick(ev->position().toPoint() - sliderRect.center() + sliderRect.topLeft()));
d->pressValue = pressValue;
if (pressValue > d->value)
action = SliderPageStepAdd;
@@ -406,7 +374,7 @@ void QSlider::mousePressEvent(QMouseEvent *ev)
initStyleOption(&opt);
setRepeatAction(SliderNoAction);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
- d->clickOffset = d->pick(ev->pos() - sr.topLeft());
+ d->clickOffset = d->pick(ev->position().toPoint() - sr.topLeft());
update(sr);
setSliderDown(true);
}
@@ -423,9 +391,7 @@ void QSlider::mouseMoveEvent(QMouseEvent *ev)
return;
}
ev->accept();
- int newPosition = d->pixelPosToRangeValue(d->pick(ev->pos()) - d->clickOffset);
- QStyleOptionSlider opt;
- initStyleOption(&opt);
+ int newPosition = d->pixelPosToRangeValue(d->pick(ev->position().toPoint()) - d->clickOffset);
setSliderPosition(newPosition);
}
@@ -472,7 +438,7 @@ QSize QSlider::sizeHint() const
w = SliderLength;
h = thick;
}
- return style()->sizeFromContents(QStyle::CT_Slider, &opt, QSize(w, h), this).expandedTo(QApplication::globalStrut());
+ return style()->sizeFromContents(QStyle::CT_Slider, &opt, QSize(w, h), this);
}
/*!
diff --git a/src/widgets/widgets/qslider.h b/src/widgets/widgets/qslider.h
index f74f9c8576..9e28928c14 100644
--- a/src/widgets/widgets/qslider.h
+++ b/src/widgets/widgets/qslider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSLIDER_H
#define QSLIDER_H
@@ -89,7 +53,7 @@ protected:
void mousePressEvent(QMouseEvent *ev) override;
void mouseReleaseEvent(QMouseEvent *ev) override;
void mouseMoveEvent(QMouseEvent *ev) override;
- void initStyleOption(QStyleOptionSlider *option) const;
+ virtual void initStyleOption(QStyleOptionSlider *option) const;
private:
diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp
index 61ea81c892..73946d54a9 100644
--- a/src/widgets/widgets/qspinbox.cpp
+++ b/src/widgets/widgets/qspinbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qabstractspinbox_p.h>
#include <qspinbox.h>
@@ -51,6 +15,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
//#define QSPINBOX_QSBDEBUG
#ifdef QSPINBOX_QSBDEBUG
# define QSBDEBUG qDebug
@@ -166,12 +132,9 @@ public:
for a custom spin box that allows the user to enter icon sizes
(e.g., "32 x 32"):
- \snippet widgets/icons/iconsizespinbox.cpp 1
+ \snippet code/src_gui_widgets_qspinbox.cpp 8
\codeline
- \snippet widgets/icons/iconsizespinbox.cpp 2
-
- See the \l{widgets/icons}{Icons} example for the full source
- code.
+ \snippet code/src_gui_widgets_qspinbox.cpp 9
\sa QDoubleSpinBox, QDateTimeEdit, QSlider, {Spin Boxes Example}
*/
@@ -191,17 +154,6 @@ public:
The new text is passed in \a text with prefix() and suffix().
*/
-#if QT_DEPRECATED_SINCE(5, 14)
-/*!
- \fn void QSpinBox::valueChanged(const QString &text)
-
- \overload
- \obsolete Use textChanged(QString) instead
-
- The new value is passed in \a text with prefix() and suffix().
-*/
-#endif
-
/*!
Constructs a spin box with 0 as minimum value and 99 as maximum value, a
step value of 1. The value is initially set to 0. It is parented to \a
@@ -529,7 +481,7 @@ QString QSpinBox::textFromValue(int value) const
QString str;
if (d->displayIntegerBase != 10) {
- const QLatin1String prefix = value < 0 ? QLatin1String("-") : QLatin1String();
+ const auto prefix = value < 0 ? "-"_L1 : ""_L1;
str = prefix + QString::number(qAbs(value), d->displayIntegerBase);
} else {
str = locale().toString(value);
@@ -663,17 +615,6 @@ void QSpinBox::fixup(QString &input) const
The new text is passed in \a text with prefix() and suffix().
*/
-#if QT_DEPRECATED_SINCE(5, 14)
-/*!
- \fn void QDoubleSpinBox::valueChanged(const QString &text);
-
- \overload
- \obsolete Use textChanged(QString) instead
-
- The new value is passed in \a text with prefix() and suffix().
-*/
-#endif
-
/*!
Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
a step value of 1.0 and a precision of 2 decimal places. The value is
@@ -999,9 +940,8 @@ void QDoubleSpinBox::setDecimals(int decimals)
This virtual function is used by the spin box whenever it needs to
display the given \a value. The default implementation returns a string
containing \a value printed using QWidget::locale().toString(\a value,
- QLatin1Char('f'), decimals()) and will remove the thousand
- separator unless setGroupSeparatorShown() is set. Reimplementations may
- return anything.
+ \c u'f', decimals()) and will remove the thousand separator unless
+ setGroupSeparatorShown() is set. Reimplementations may return anything.
Note: QDoubleSpinBox does not call this function for
specialValueText() and that neither prefix() nor suffix() should
@@ -1081,7 +1021,7 @@ QSpinBoxPrivate::QSpinBoxPrivate()
value = minimum;
displayIntegerBase = 10;
singleStep = QVariant((int)1);
- type = QVariant::Int;
+ type = QMetaType::Int;
}
/*!
@@ -1095,12 +1035,6 @@ void QSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
if (ep != NeverEmit) {
pendingEmit = false;
if (ep == AlwaysEmit || value != old) {
-#if QT_DEPRECATED_SINCE(5, 14)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- emit q->valueChanged(edit->displayText());
-QT_WARNING_POP
-#endif
emit q->textChanged(edit->displayText());
emit q->valueChanged(value.toInt());
}
@@ -1155,11 +1089,11 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
int num = min;
if (max != min && (copy.isEmpty()
- || (min < 0 && copy == QLatin1String("-"))
- || (max >= 0 && copy == QLatin1String("+")))) {
+ || (min < 0 && copy == "-"_L1)
+ || (max >= 0 && copy == "+"_L1))) {
state = QValidator::Intermediate;
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
- } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) {
+ } else if (copy.startsWith(u'-') && min >= 0) {
state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
} else {
bool ok = false;
@@ -1168,11 +1102,11 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
} else {
num = locale.toInt(copy, &ok);
if (!ok && (max >= 1000 || min <= -1000)) {
- const QChar sep = locale.groupSeparator();
- const QChar doubleSep[2] = {sep, sep};
- if (copy.contains(sep) && !copy.contains(QString(doubleSep, 2))) {
+ const QString sep(locale.groupSeparator());
+ const QString doubleSep = sep + sep;
+ if (copy.contains(sep) && !copy.contains(doubleSep)) {
QString copy2 = copy;
- copy2.remove(locale.groupSeparator());
+ copy2.remove(sep);
num = locale.toInt(copy2, &ok);
}
}
@@ -1238,7 +1172,7 @@ QDoubleSpinBoxPrivate::QDoubleSpinBoxPrivate()
value = minimum;
singleStep = QVariant(1.0);
decimals = 2;
- type = QVariant::Double;
+ type = QMetaType::Double;
}
/*!
@@ -1252,12 +1186,6 @@ void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
if (ep != NeverEmit) {
pendingEmit = false;
if (ep == AlwaysEmit || value != old) {
-#if QT_DEPRECATED_SINCE(5, 14)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- emit q->valueChanged(edit->displayText());
-QT_WARNING_POP
-#endif
emit q->textChanged(edit->displayText());
emit q->valueChanged(value.toDouble());
}
@@ -1314,21 +1242,26 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
const bool plus = max >= 0;
const bool minus = min <= 0;
+ const QString group(locale.groupSeparator());
+ const uint groupUcs = (group.isEmpty() ? 0 :
+ (group.size() > 1 && group.at(0).isHighSurrogate()
+ ? QChar::surrogateToUcs4(group.at(0), group.at(1))
+ : group.at(0).unicode()));
switch (len) {
case 0:
state = max != min ? QValidator::Intermediate : QValidator::Invalid;
goto end;
case 1:
if (copy.at(0) == locale.decimalPoint()
- || (plus && copy.at(0) == QLatin1Char('+'))
- || (minus && copy.at(0) == QLatin1Char('-'))) {
+ || (plus && copy.at(0) == u'+')
+ || (minus && copy.at(0) == u'-')) {
state = QValidator::Intermediate;
goto end;
}
break;
case 2:
if (copy.at(1) == locale.decimalPoint()
- && ((plus && copy.at(0) == QLatin1Char('+')) || (minus && copy.at(0) == QLatin1Char('-')))) {
+ && ((plus && copy.at(0) == u'+') || (minus && copy.at(0) == u'-'))) {
state = QValidator::Intermediate;
goto end;
}
@@ -1336,7 +1269,7 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
default: break;
}
- if (copy.at(0) == locale.groupSeparator()) {
+ if (groupUcs && copy.startsWith(group)) {
QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
state = QValidator::Invalid;
goto end;
@@ -1352,22 +1285,25 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
state = QValidator::Invalid;
goto end;
}
- for (int i=dec + 1; i<copy.size(); ++i) {
- if (copy.at(i).isSpace() || copy.at(i) == locale.groupSeparator()) {
+ for (int i = dec + 1; i < copy.size(); ++i) {
+ if (copy.at(i).isSpace()
+ || (groupUcs && QStringView{copy}.sliced(i).startsWith(group))) {
QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
state = QValidator::Invalid;
goto end;
}
}
} else {
- const QChar last = copy.at(len - 1);
- const QChar secondLast = copy.at(len - 2);
- if ((last == locale.groupSeparator() || last.isSpace())
- && (secondLast == locale.groupSeparator() || secondLast.isSpace())) {
+ const QChar last = copy.back();
+ const bool groupEnd = groupUcs && copy.endsWith(group);
+ const QStringView head(copy.constData(), groupEnd ? len - group.size() : len - 1);
+ const QChar secondLast = head.back();
+ if ((groupEnd || last.isSpace())
+ && ((groupUcs && head.endsWith(group)) || secondLast.isSpace())) {
state = QValidator::Invalid;
QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
goto end;
- } else if (last.isSpace() && (!locale.groupSeparator().isSpace() || secondLast.isSpace())) {
+ } else if (last.isSpace() && (!QChar::isSpace(groupUcs) || secondLast.isSpace())) {
state = QValidator::Invalid;
QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
goto end;
@@ -1381,26 +1317,32 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok;
if (!ok) {
- if (locale.groupSeparator().isPrint()) {
- if (max < 1000 && min > -1000 && copy.contains(locale.groupSeparator())) {
+ if (QChar::isPrint(groupUcs)) {
+ if (max < 1000 && min > -1000 && groupUcs && copy.contains(group)) {
state = QValidator::Invalid;
QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
goto end;
}
const int len = copy.size();
- for (int i=0; i<len- 1; ++i) {
- if (copy.at(i) == locale.groupSeparator() && copy.at(i + 1) == locale.groupSeparator()) {
- QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
- state = QValidator::Invalid;
- goto end;
+ for (int i = 0; i < len - 1;) {
+ if (groupUcs && QStringView{copy}.sliced(i).startsWith(group)) {
+ if (QStringView(copy).mid(i + group.size()).startsWith(group)) {
+ QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid";
+ state = QValidator::Invalid;
+ goto end;
+ }
+ i += group.size();
+ } else {
+ i++;
}
}
QString copy2 = copy;
- copy2.remove(locale.groupSeparator());
+ if (groupUcs)
+ copy2.remove(group);
num = locale.toDouble(copy2, &ok);
- QSBDEBUG() << locale.groupSeparator() << num << copy2 << ok;
+ QSBDEBUG() << group << num << copy2 << ok;
if (!ok) {
state = QValidator::Invalid;
diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h
index 762dd4a46a..38affecdbb 100644
--- a/src/widgets/widgets/qspinbox.h
+++ b/src/widgets/widgets/qspinbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSPINBOX_H
#define QSPINBOX_H
@@ -107,10 +71,6 @@ public Q_SLOTS:
Q_SIGNALS:
void valueChanged(int);
void textChanged(const QString &);
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_X("Use textChanged(QString) instead")
- void valueChanged(const QString &);
-#endif
private:
Q_DISABLE_COPY(QSpinBox)
@@ -173,10 +133,6 @@ public Q_SLOTS:
Q_SIGNALS:
void valueChanged(double);
void textChanged(const QString &);
-#if QT_DEPRECATED_SINCE(5, 14)
- QT_DEPRECATED_X("Use textChanged(QString) instead")
- void valueChanged(const QString &);
-#endif
private:
Q_DISABLE_COPY(QDoubleSpinBox)
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp
index 70f05033ea..fcd09908cd 100644
--- a/src/widgets/widgets/qsplashscreen.cpp
+++ b/src/widgets/widgets/qsplashscreen.cpp
@@ -1,47 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsplashscreen.h"
#include "qapplication.h"
-#include "qdesktopwidget.h"
-#include <private/qdesktopwidget_p.h>
#include "qpainter.h"
#include "qpixmap.h"
#include "qtextdocument.h"
@@ -71,9 +33,7 @@ public:
inline QSplashScreenPrivate();
- void setPixmap(const QPixmap &p, const QScreen *screen = nullptr);
-
- static const QScreen *screenFor(const QWidget *w);
+ void handlePaintEvent();
};
/*!
@@ -109,9 +69,9 @@ public:
\snippet qsplashscreen/main.cpp 1
The user can hide the splash screen by clicking on it with the
- mouse. Since the splash screen is typically displayed before the
- event loop has started running, it is necessary to periodically
- call QCoreApplication::processEvents() to receive the mouse clicks.
+ mouse. For mouse handling to work, call QApplication::processEvents()
+ periodically during startup.
+
It is sometimes useful to update the splash screen with messages,
for example, announcing connections established or modules loaded
@@ -154,27 +114,10 @@ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f)
QSplashScreen::QSplashScreen(QScreen *screen, const QPixmap &pixmap, Qt::WindowFlags f)
: QWidget(*(new QSplashScreenPrivate()), nullptr, Qt::SplashScreen | Qt::FramelessWindowHint | f)
{
- d_func()->setPixmap(pixmap, screen);
-}
-
-#if QT_DEPRECATED_SINCE(5, 15)
-/*!
- \overload
- \obsolete
-
- This function allows you to specify a parent for your splashscreen. The
- typical use for this constructor is if you have a multiple screens and
- prefer to have the splash screen on a different screen than your primary
- one. In that case pass the proper desktop() as the \a parent.
-*/
-QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f)
- : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f)
-{
- // Does an implicit repaint. Explicitly pass parent as QObject::parent()
- // is still 0 here due to QWidget's special handling.
- d_func()->setPixmap(pixmap, QSplashScreenPrivate::screenFor(parent));
+ Q_D(QSplashScreen);
+ d->setScreen(screen);
+ setPixmap(pixmap);
}
-#endif
/*!
Destructor.
@@ -260,28 +203,29 @@ void QSplashScreen::clearMessage()
repaint();
}
-// A copy of Qt Test's qWaitForWindowExposed() and qSleep().
-inline static bool waitForWindowExposed(QWindow *window, int timeout = 1000)
+static bool waitForWidgetMapped(QWidget *widget, int timeout = 1000)
{
enum { TimeOutMs = 10 };
+ auto isMapped = [widget](){
+ return widget->windowHandle() && widget->windowHandle()->isVisible();
+ };
+
QElapsedTimer timer;
timer.start();
- while (!window->isExposed()) {
+ while (!isMapped()) {
const int remaining = timeout - int(timer.elapsed());
if (remaining <= 0)
break;
QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
-#if defined(Q_OS_WINRT)
- WaitForSingleObjectEx(GetCurrentThread(), TimeOutMs, false);
-#elif defined(Q_OS_WIN)
+ QCoreApplication::sendPostedEvents();
+#if defined(Q_OS_WIN)
Sleep(uint(TimeOutMs));
#else
struct timespec ts = { TimeOutMs / 1000, (TimeOutMs % 1000) * 1000 * 1000 };
nanosleep(&ts, nullptr);
#endif
}
- return window->isExposed();
+ return isMapped();
}
/*!
@@ -294,7 +238,7 @@ void QSplashScreen::finish(QWidget *mainWin)
if (mainWin) {
if (!mainWin->windowHandle())
mainWin->createWinId();
- waitForWindowExposed(mainWin->windowHandle());
+ waitForWidgetMapped(mainWin);
}
close();
}
@@ -305,63 +249,16 @@ void QSplashScreen::finish(QWidget *mainWin)
*/
void QSplashScreen::setPixmap(const QPixmap &pixmap)
{
- d_func()->setPixmap(pixmap, QSplashScreenPrivate::screenFor(this));
-}
-
-// In setPixmap(), resize and try to position on a screen according to:
-// 1) If the screen for the given widget is available, use that
-// 2) If a QDesktopScreenWidget is found in the parent hierarchy, use that (see docs on
-// QSplashScreen(QWidget *, QPixmap).
-// 3) If a widget with associated QWindow is found, use that
-// 4) When nothing can be found, try to center it over the cursor
-
-#if QT_DEPRECATED_SINCE(5, 15)
-static inline int screenNumberOf(const QDesktopScreenWidget *dsw)
-{
- auto desktopWidgetPrivate =
- static_cast<QDesktopWidgetPrivate *>(qt_widget_private(QApplication::desktop()));
- return desktopWidgetPrivate->screens.indexOf(const_cast<QDesktopScreenWidget *>(dsw));
-}
-#endif
-
-const QScreen *QSplashScreenPrivate::screenFor(const QWidget *w)
-{
- if (w && w->screen())
- return w->screen();
-
- for (const QWidget *p = w; p !=nullptr ; p = p->parentWidget()) {
-#if QT_DEPRECATED_SINCE(5, 15)
- if (auto dsw = qobject_cast<const QDesktopScreenWidget *>(p))
- return QGuiApplication::screens().value(screenNumberOf(dsw));
-#endif
- if (QWindow *window = p->windowHandle())
- return window->screen();
- }
-
-#if QT_CONFIG(cursor)
- // Note: We could rely on QPlatformWindow::initialGeometry() to center it
- // over the cursor, but not all platforms (namely Android) use that.
- if (QGuiApplication::screens().size() > 1) {
- if (auto screenAtCursor = QGuiApplication::screenAt(QCursor::pos()))
- return screenAtCursor;
- }
-#endif // cursor
- return QGuiApplication::primaryScreen();
-}
-
-void QSplashScreenPrivate::setPixmap(const QPixmap &p, const QScreen *screen)
-{
- Q_Q(QSplashScreen);
+ Q_D(QSplashScreen);
+ d->pixmap = pixmap;
+ setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
- pixmap = p;
- q->setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
+ const QRect r(QPoint(), pixmap.deviceIndependentSize().toSize());
+ resize(r.size());
- QRect r(QPoint(), pixmap.size() / pixmap.devicePixelRatio());
- q->resize(r.size());
- if (screen)
- q->move(screen->geometry().center() - r.center());
- if (q->isVisible())
- q->repaint();
+ move(screen()->geometry().center() - r.center());
+ if (isVisible())
+ repaint();
}
/*!
@@ -419,17 +316,33 @@ void QSplashScreen::drawContents(QPainter *painter)
}
}
+void QSplashScreenPrivate::handlePaintEvent()
+{
+ Q_Q(QSplashScreen);
+ QPainter painter(q);
+ painter.setRenderHints(QPainter::SmoothPixmapTransform);
+ painter.setLayoutDirection(q->layoutDirection());
+ if (!pixmap.isNull())
+ painter.drawPixmap(QPoint(), pixmap);
+ q->drawContents(&painter);
+}
+
/*! \reimp */
bool QSplashScreen::event(QEvent *e)
{
- if (e->type() == QEvent::Paint) {
- Q_D(QSplashScreen);
- QPainter painter(this);
- painter.setLayoutDirection(layoutDirection());
- if (!d->pixmap.isNull())
- painter.drawPixmap(QPoint(), d->pixmap);
- drawContents(&painter);
+ Q_D(QSplashScreen);
+
+ switch (e->type()) {
+ case QEvent::Paint:
+ d->handlePaintEvent();
+ break;
+ case QEvent::Show:
+ waitForWidgetMapped(this);
+ break;
+ default:
+ break;
}
+
return QWidget::event(e);
}
diff --git a/src/widgets/widgets/qsplashscreen.h b/src/widgets/widgets/qsplashscreen.h
index 1877493fcf..2670e5c68b 100644
--- a/src/widgets/widgets/qsplashscreen.h
+++ b/src/widgets/widgets/qsplashscreen.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSPLASHSCREEN_H
#define QSPLASHSCREEN_H
@@ -56,10 +20,6 @@ class Q_WIDGETS_EXPORT QSplashScreen : public QWidget
public:
explicit QSplashScreen(const QPixmap &pixmap = QPixmap(), Qt::WindowFlags f = Qt::WindowFlags());
QSplashScreen(QScreen *screen, const QPixmap &pixmap = QPixmap(), Qt::WindowFlags f = Qt::WindowFlags());
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_VERSION_X_5_15("Use the constructor taking a QScreen *")
- QSplashScreen(QWidget *parent, const QPixmap &pixmap = QPixmap(), Qt::WindowFlags f = Qt::WindowFlags());
-#endif
virtual ~QSplashScreen();
void setPixmap(const QPixmap &pixmap);
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 090aa5cc8b..d0519a56a2 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsplitter.h"
@@ -53,7 +17,6 @@
#include "qstyleoption.h"
#include "qtextstream.h"
#include "qvarlengtharray.h"
-#include "qvector.h"
#include "private/qlayoutengine_p.h"
#include "private/qsplitter_p.h"
#include "qtimer.h"
@@ -63,6 +26,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
//#define QSPLITTER_DEBUG
QSplitterPrivate::~QSplitterPrivate()
@@ -228,10 +193,9 @@ QSize QSplitterHandle::sizeHint() const
Q_D(const QSplitterHandle);
int hw = d->s->handleWidth();
QStyleOption opt(0);
- opt.init(d->s);
+ opt.initFrom(d->s);
opt.state = QStyle::State_None;
- return parentWidget()->style()->sizeFromContents(QStyle::CT_Splitter, &opt, QSize(hw, hw), d->s)
- .expandedTo(QApplication::globalStrut());
+ return parentWidget()->style()->sizeFromContents(QStyle::CT_Splitter, &opt, QSize(hw, hw), d->s);
}
/*!
@@ -291,10 +255,11 @@ bool QSplitterHandle::event(QEvent *event)
void QSplitterHandle::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QSplitterHandle);
- if (!(e->buttons() & Qt::LeftButton))
+ if (!d->pressed)
return;
- int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPos()))
- - d->mouseOffset;
+
+ const int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPosition().toPoint()))
+ - d->mouseOffset;
if (opaqueResize()) {
moveSplitter(pos);
} else {
@@ -309,7 +274,7 @@ void QSplitterHandle::mousePressEvent(QMouseEvent *e)
{
Q_D(QSplitterHandle);
if (e->button() == Qt::LeftButton) {
- d->mouseOffset = d->pick(e->pos());
+ d->mouseOffset = d->pick(e->position().toPoint());
d->pressed = true;
update();
}
@@ -321,16 +286,18 @@ void QSplitterHandle::mousePressEvent(QMouseEvent *e)
void QSplitterHandle::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QSplitterHandle);
- if (!opaqueResize() && e->button() == Qt::LeftButton) {
- int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPos()))
- - d->mouseOffset;
+ if (!d->pressed)
+ return;
+
+ if (!opaqueResize()) {
+ const int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPosition().toPoint()))
+ - d->mouseOffset;
d->s->setRubberBand(-1);
moveSplitter(pos);
}
- if (e->button() == Qt::LeftButton) {
- d->pressed = false;
- update();
- }
+
+ d->pressed = false;
+ update();
}
/*!
@@ -394,7 +361,7 @@ void QSplitterPrivate::init()
void QSplitterPrivate::recalc(bool update)
{
Q_Q(QSplitter);
- int n = list.count();
+ int n = list.size();
/*
Splitter handles before the first visible widget or right
before a hidden widget must be hidden.
@@ -441,9 +408,9 @@ void QSplitterPrivate::recalc(bool update)
QSize minS = qSmartMinSize(s->widget);
minl += pick(minS);
- maxl += pick(s->widget->maximumSize());
+ maxl += pick(qSmartMaxSize(s->widget));
mint = qMax(mint, trans(minS));
- int tm = trans(s->widget->maximumSize());
+ int tm = trans(qSmartMaxSize(s->widget));
if (tm > 0)
maxt = qMin(maxt, tm);
}
@@ -484,8 +451,8 @@ void QSplitterPrivate::doResize()
{
Q_Q(QSplitter);
QRect r = q->contentsRect();
- int n = list.count();
- QVector<QLayoutStruct> a(n*2);
+ int n = list.size();
+ QList<QLayoutStruct> a(n * 2);
int i;
bool noStretchFactorsSet = true;
@@ -520,7 +487,7 @@ void QSplitterPrivate::doResize()
a[j].maximumSize = 0;
} else {
a[j].minimumSize = pick(qSmartMinSize(s->widget));
- a[j].maximumSize = pick(s->widget->maximumSize());
+ a[j].maximumSize = pick(qSmartMaxSize(s->widget));
a[j].empty = false;
bool stretch = noStretchFactorsSet;
@@ -582,7 +549,7 @@ void QSplitterPrivate::addContribution(int index, int *min, int *max, bool mayCo
if (mayCollapse || !s->collapsed)
*min += pick(qSmartMinSize(s->widget));
- *max += pick(s->widget->maximumSize());
+ *max += pick(qSmartMaxSize(s->widget));
}
}
@@ -598,7 +565,7 @@ int QSplitterPrivate::findWidgetJustBeforeOrJustAfter(int index, int delta, int
return index;
}
index += delta;
- } while (index >= 0 && index < list.count());
+ } while (index >= 0 && index < list.size());
return -1;
}
@@ -610,7 +577,7 @@ int QSplitterPrivate::findWidgetJustBeforeOrJustAfter(int index, int delta, int
void QSplitterPrivate::getRange(int index, int *farMin, int *min, int *max, int *farMax) const
{
Q_Q(const QSplitter);
- int n = list.count();
+ int n = list.size();
if (index <= 0 || index >= n)
return;
@@ -734,10 +701,15 @@ void QSplitterPrivate::setSizes_helper(const QList<int> &sizes, bool clampNegati
doResize();
}
+/*
+ Used by various methods inserting a widget to find out if we need to show the widget
+ explicitly, which we have to if the splitter is already visible, and if the widget hasn't
+ been explicitly hidden before inserting it.
+*/
bool QSplitterPrivate::shouldShowWidget(const QWidget *w) const
{
Q_Q(const QSplitter);
- return q->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ return q->isVisible() && !QWidgetPrivate::get(w)->isExplicitlyHidden();
}
void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool allowCollapse)
@@ -785,7 +757,7 @@ void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool all
void QSplitterPrivate::doMove(bool backwards, int hPos, int index, int delta, bool mayCollapse,
int *positions, int *widths)
{
- if (index < 0 || index >= list.count())
+ if (index < 0 || index >= list.size())
return;
#ifdef QSPLITTER_DEBUG
@@ -805,7 +777,7 @@ void QSplitterPrivate::doMove(bool backwards, int hPos, int index, int delta, bo
int ws = backwards ? hPos - pick(s->rect.topLeft())
: pick(s->rect.bottomRight()) - hPos -hs + 1;
if (ws > 0 || (!s->collapsed && !mayCollapse)) {
- ws = qMin(ws, pick(w->maximumSize()));
+ ws = qMin(ws, pick(qSmartMaxSize(w)));
ws = qMax(ws, pick(qSmartMinSize(w)));
} else {
ws = 0;
@@ -855,7 +827,7 @@ QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
Q_Q(QSplitter);
QSplitterLayoutStruct *sls = nullptr;
int i;
- int last = list.count();
+ int last = list.size();
for (i = 0; i < list.size(); ++i) {
QSplitterLayoutStruct *s = list.at(i);
if (s->widget == w) {
@@ -872,7 +844,7 @@ QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
} else {
sls = new QSplitterLayoutStruct;
QSplitterHandle *newHandle = q->createHandle();
- newHandle->setObjectName(QLatin1String("qt_splithandle_") + w->objectName());
+ newHandle->setObjectName("qt_splithandle_"_L1 + w->objectName());
sls->handle = newHandle;
sls->widget = w;
w->lower();
@@ -1107,7 +1079,7 @@ void QSplitter::resizeEvent(QResizeEvent *)
void QSplitter::addWidget(QWidget *widget)
{
Q_D(QSplitter);
- insertWidget(d->list.count(), widget);
+ insertWidget(d->list.size(), widget);
}
/*!
@@ -1157,7 +1129,7 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
return nullptr;
}
- if (index < 0 || index >= d->list.count()) {
+ if (index < 0 || index >= d->list.size()) {
qWarning("QSplitter::replaceWidget: Index %d out of range", index);
return nullptr;
}
@@ -1177,7 +1149,7 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
QBoolBlocker b(d->blockChildAdd);
const QRect geom = current->geometry();
- const bool shouldShow = d->shouldShowWidget(current);
+ const bool wasHidden = current->isHidden();
s->widget = widget;
current->setParent(nullptr);
@@ -1187,14 +1159,15 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
// should not change. Only set the geometry on the new widget
widget->setGeometry(geom);
widget->lower();
- widget->setVisible(shouldShow);
+ if (wasHidden)
+ widget->hide();
+ else if (d->shouldShowWidget(widget))
+ widget->show();
return current;
}
/*!
- \fn int QSplitter::indexOf(QWidget *widget) const
-
Returns the index in the splitter's layout of the specified \a widget,
or -1 if \a widget is not found. This also works for handles.
@@ -1204,12 +1177,12 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
\sa count(), widget()
*/
-int QSplitter::indexOf(QWidget *w) const
+int QSplitter::indexOf(QWidget *widget) const
{
Q_D(const QSplitter);
for (int i = 0; i < d->list.size(); ++i) {
QSplitterLayoutStruct *s = d->list.at(i);
- if (s->widget == w || s->handle == w)
+ if (s->widget == widget || s->handle == widget)
return i;
}
return -1;
@@ -1269,7 +1242,7 @@ QWidget *QSplitter::widget(int index) const
int QSplitter::count() const
{
Q_D(const QSplitter);
- return d->list.count();
+ return d->list.size();
}
/*!
@@ -1290,16 +1263,18 @@ int QSplitter::count() const
void QSplitter::childEvent(QChildEvent *c)
{
Q_D(QSplitter);
- if (!c->child()->isWidgetType()) {
- if (Q_UNLIKELY(c->type() == QEvent::ChildAdded && qobject_cast<QLayout *>(c->child())))
- qWarning("Adding a QLayout to a QSplitter is not supported.");
- return;
- }
if (c->added()) {
+ if (!c->child()->isWidgetType()) {
+ if (Q_UNLIKELY(qobject_cast<QLayout *>(c->child())))
+ qWarning("Adding a QLayout to a QSplitter is not supported.");
+ return;
+ }
QWidget *w = static_cast<QWidget*>(c->child());
if (!d->blockChildAdd && !w->isWindow() && !d->findWidget(w))
- d->insertWidget_helper(d->list.count(), w, false);
+ d->insertWidget_helper(d->list.size(), w, false);
} else if (c->polished()) {
+ if (!c->child()->isWidgetType())
+ return;
QWidget *w = static_cast<QWidget*>(c->child());
if (!d->blockChildAdd && !w->isWindow() && d->shouldShowWidget(w))
w->show();
@@ -1339,7 +1314,7 @@ void QSplitter::setRubberBand(int pos)
QBoolBlocker b(d->blockChildAdd);
d->rubberBand = new QRubberBand(QRubberBand::Line, this);
// For accessibility to identify this special widget.
- d->rubberBand->setObjectName(QLatin1String("qt_rubberband"));
+ d->rubberBand->setObjectName("qt_rubberband"_L1);
}
const QRect newGeom = d->orient == Qt::Horizontal ? QRect(QPoint(pos + hw / 2 - rBord, r.y()), QSize(2 * rBord, r.height()))
@@ -1381,7 +1356,7 @@ bool QSplitter::event(QEvent *e)
}
/*!
- \fn QSplitter::splitterMoved(int pos, int index)
+ \fn void QSplitter::splitterMoved(int pos, int index)
This signal is emitted when the splitter handle at a particular \a
index has been moved to position \a pos.
@@ -1408,10 +1383,10 @@ void QSplitter::moveSplitter(int pos, int index)
{
Q_D(QSplitter);
QSplitterLayoutStruct *s = d->list.at(index);
- int farMin;
- int min;
- int max;
- int farMax;
+ int farMin = 0;
+ int min = 0;
+ int max = 0;
+ int farMax = 0;
#ifdef QSPLITTER_DEBUG
int debugp = pos;
@@ -1423,15 +1398,15 @@ void QSplitter::moveSplitter(int pos, int index)
qDebug() << "QSplitter::moveSplitter" << debugp << index << "adjusted" << pos << "oldP" << oldP;
#endif
- QVarLengthArray<int, 32> poss(d->list.count());
- QVarLengthArray<int, 32> ws(d->list.count());
+ QVarLengthArray<int, 32> poss(d->list.size());
+ QVarLengthArray<int, 32> ws(d->list.size());
bool upLeft;
d->doMove(false, pos, index, +1, (d->collapsible(s) && (pos > max)), poss.data(), ws.data());
d->doMove(true, pos, index - 1, +1, (d->collapsible(index - 1) && (pos < min)), poss.data(), ws.data());
upLeft = (pos < oldP);
- int wid, delta, count = d->list.count();
+ int wid, delta, count = d->list.size();
if (upLeft) {
wid = 0;
delta = 1;
@@ -1475,7 +1450,10 @@ void QSplitter::getRange(int index, int *min, int *max) const
int QSplitter::closestLegalPosition(int pos, int index)
{
Q_D(QSplitter);
- int x, i, n, u;
+ int x = 0;
+ int i = 0;
+ int n = 0;
+ int u = 0;
return d->adjustPos(pos, index, &u, &n, &i, &x);
}
@@ -1656,7 +1634,7 @@ void QSplitter::setHandleWidth(int width)
void QSplitter::changeEvent(QEvent *ev)
{
Q_D(QSplitter);
- if(ev->type() == QEvent::StyleChange)
+ if (ev->type() == QEvent::StyleChange)
d->updateHandles();
QFrame::changeEvent(ev);
}
@@ -1680,6 +1658,7 @@ QByteArray QSplitter::saveState() const
int version = 1;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_5_0);
stream << qint32(SplitterMagic);
stream << qint32(version);
@@ -1721,6 +1700,7 @@ bool QSplitter::restoreState(const QByteArray &state)
int version = 1;
QByteArray sd = state;
QDataStream stream(&sd, QIODevice::ReadOnly);
+ stream.setVersion(QDataStream::Qt_5_0);
QList<int> list;
bool b;
qint32 i;
@@ -1771,7 +1751,7 @@ bool QSplitter::restoreState(const QByteArray &state)
void QSplitter::setStretchFactor(int index, int stretch)
{
Q_D(QSplitter);
- if (index <= -1 || index >= d->list.count())
+ if (index <= -1 || index >= d->list.size())
return;
QWidget *widget = d->list.at(index)->widget;
@@ -1781,40 +1761,6 @@ void QSplitter::setStretchFactor(int index, int stretch)
widget->setSizePolicy(sp);
}
-
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \relates QSplitter
- \obsolete
-
- Use \a ts << \a{splitter}.saveState() instead.
-*/
-
-QTextStream& operator<<(QTextStream& ts, const QSplitter& splitter)
-{
- ts << splitter.saveState() << Qt::endl;
- return ts;
-}
-
-/*!
- \relates QSplitter
- \obsolete
-
- Use \a ts >> \a{splitter}.restoreState() instead.
-*/
-
-QTextStream& operator>>(QTextStream& ts, QSplitter& splitter)
-{
- QString line = ts.readLine();
- line = line.simplified();
- line.replace(QLatin1Char(' '), QString());
- line = std::move(line).toUpper();
-
- splitter.restoreState(std::move(line).toLatin1());
- return ts;
-}
-#endif
-
QT_END_NAMESPACE
#include "moc_qsplitter.cpp"
diff --git a/src/widgets/widgets/qsplitter.h b/src/widgets/widgets/qsplitter.h
index 658914ae39..96c19be24d 100644
--- a/src/widgets/widgets/qsplitter.h
+++ b/src/widgets/widgets/qsplitter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSPLITTER_H
#define QSPLITTER_H
@@ -128,12 +92,6 @@ private:
friend class QSplitterHandle;
};
-#if QT_DEPRECATED_SINCE(5, 13)
-QT_DEPRECATED_X("Use QSplitter::saveState() instead")
-Q_WIDGETS_EXPORT QTextStream& operator<<(QTextStream&, const QSplitter&);
-QT_DEPRECATED_X("Use QSplitter::restoreState() instead")
-Q_WIDGETS_EXPORT QTextStream& operator>>(QTextStream&, QSplitter&);
-#endif
class QSplitterHandlePrivate;
class Q_WIDGETS_EXPORT QSplitterHandle : public QWidget
diff --git a/src/widgets/widgets/qsplitter_p.h b/src/widgets/widgets/qsplitter_p.h
index 871406a51d..5d5723a957 100644
--- a/src/widgets/widgets/qsplitter_p.h
+++ b/src/widgets/widgets/qsplitter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSPLITTER_P_H
#define QSPLITTER_P_H
@@ -54,6 +18,8 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "private/qframe_p.h"
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(splitter);
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp
index a565d4ab4c..9cecee2ef8 100644
--- a/src/widgets/widgets/qstackedwidget.cpp
+++ b/src/widgets/widgets/qstackedwidget.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstackedwidget.h"
@@ -51,7 +15,6 @@ class QStackedWidgetPrivate : public QFramePrivate
public:
QStackedWidgetPrivate():layout(nullptr){}
QStackedLayout *layout;
- bool blockChildAdd;
};
/*!
@@ -135,8 +98,10 @@ QStackedWidget::QStackedWidget(QWidget *parent)
{
Q_D(QStackedWidget);
d->layout = new QStackedLayout(this);
- connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int)));
- connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int)));
+ connect(d->layout, &QStackedLayout::widgetRemoved,
+ this, &QStackedWidget::widgetRemoved);
+ connect(d->layout, &QStackedLayout::currentChanged,
+ this, &QStackedWidget::currentChanged);
}
/*!
@@ -254,7 +219,7 @@ void QStackedWidget::setCurrentWidget(QWidget *widget)
\sa currentIndex(), widget()
*/
-int QStackedWidget::indexOf(QWidget *widget) const
+int QStackedWidget::indexOf(const QWidget *widget) const
{
return d_func()->layout->indexOf(widget);
}
diff --git a/src/widgets/widgets/qstackedwidget.h b/src/widgets/widgets/qstackedwidget.h
index 5508f905d4..49f2794ff4 100644
--- a/src/widgets/widgets/qstackedwidget.h
+++ b/src/widgets/widgets/qstackedwidget.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTACKEDWIDGET_H
#define QSTACKEDWIDGET_H
@@ -66,7 +30,7 @@ public:
QWidget *currentWidget() const;
int currentIndex() const;
- int indexOf(QWidget *) const;
+ int indexOf(const QWidget *) const;
QWidget *widget(int) const;
int count() const;
diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp
index 4a1fef8b65..e398f52ac4 100644
--- a/src/widgets/widgets/qstatusbar.cpp
+++ b/src/widgets/widgets/qstatusbar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstatusbar.h"
@@ -54,7 +18,7 @@
#include "qmainwindow.h"
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
@@ -69,22 +33,27 @@ class QStatusBarPrivate : public QWidgetPrivate
public:
QStatusBarPrivate() {}
+ enum ItemCategory
+ {
+ Normal,
+ Permanent
+ };
+
struct SBItem {
- SBItem(QWidget* widget, int stretch, bool permanent)
- : s(stretch), w(widget), p(permanent) {}
- int s;
- QWidget * w;
- bool p;
+ QWidget *widget = nullptr;
+ int stretch = 0;
+ ItemCategory category = Normal;
+ bool isPermanent() const { return category == Permanent; }
};
- QList<SBItem *> items;
+ QList<SBItem> items;
QString tempItem;
- QBoxLayout * box;
- QTimer * timer;
+ QBoxLayout *box;
+ QTimer *timer;
#if QT_CONFIG(sizegrip)
- QSizeGrip * resizer;
+ QSizeGrip *resizer;
bool showSizeGrip;
#endif
@@ -94,8 +63,8 @@ public:
{
int i = items.size() - 1;
for (; i >= 0; --i) {
- SBItem *item = items.at(i);
- if (!(item && item->p))
+ const SBItem &item = items.at(i);
+ if (!item.isPermanent())
break;
}
return i;
@@ -122,7 +91,7 @@ public:
QRect QStatusBarPrivate::messageRect() const
{
Q_Q(const QStatusBar);
- bool rtl = q->layoutDirection() == Qt::RightToLeft;
+ const bool rtl = q->layoutDirection() == Qt::RightToLeft;
int left = 6;
int right = q->width() - 12;
@@ -136,18 +105,13 @@ QRect QStatusBarPrivate::messageRect() const
}
#endif
- for (int i=0; i<items.size(); ++i) {
- QStatusBarPrivate::SBItem* item = items.at(i);
- if (!item)
+ for (const auto &item : items) {
+ if (item.isPermanent() && item.widget->isVisible()) {
+ if (rtl)
+ left = qMax(left, item.widget->x() + item.widget->width() + 2);
+ else
+ right = qMin(right, item.widget->x() - 2);
break;
- if (item->p && item->w->isVisible()) {
- if (item->p) {
- if (rtl)
- left = qMax(left, item->w->x() + item->w->width() + 2);
- else
- right = qMin(right, item->w->x() - 2);
- }
- break;
}
}
return QRect(left, 0, right-left, q->height());
@@ -187,12 +151,12 @@ QRect QStatusBarPrivate::messageRect() const
Use the showMessage() slot to display a \e temporary message:
- \snippet mainwindows/dockwidgets/mainwindow.cpp 8
+ \snippet code/src_gui_widgets_qstatusbar.cpp 1
To remove a temporary message, use the clearMessage() slot, or set
a time limit when calling showMessage(). For example:
- \snippet mainwindows/dockwidgets/mainwindow.cpp 3
+ \snippet code/src_gui_widgets_qstatusbar.cpp 2
Use the currentMessage() function to retrieve the temporary
message currently shown. The QStatusBar class also provide the
@@ -215,8 +179,7 @@ QRect QStatusBarPrivate::messageRect() const
\image fusion-statusbar-sizegrip.png A status bar shown in the Fusion widget style
- \sa QMainWindow, QStatusTipEvent, {fowler}{GUI Design Handbook:
- Status Bar}, {Application Example}
+ \sa QMainWindow, QStatusTipEvent
*/
@@ -246,9 +209,6 @@ QStatusBar::QStatusBar(QWidget * parent)
*/
QStatusBar::~QStatusBar()
{
- Q_D(QStatusBar);
- while (!d->items.isEmpty())
- delete d->items.takeFirst();
}
@@ -298,7 +258,7 @@ int QStatusBar::insertWidget(int index, QWidget *widget, int stretch)
return -1;
Q_D(QStatusBar);
- QStatusBarPrivate::SBItem* item = new QStatusBarPrivate::SBItem(widget, stretch, false);
+ QStatusBarPrivate::SBItem item{widget, stretch, QStatusBarPrivate::Normal};
int idx = d->indexToLastNonPermanentWidget();
if (Q_UNLIKELY(index < 0 || index > d->items.size() || (idx >= 0 && index > idx + 1))) {
@@ -311,7 +271,7 @@ int QStatusBar::insertWidget(int index, QWidget *widget, int stretch)
widget->hide();
reformat();
- if (!widget->isHidden() || !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ if (!QWidgetPrivate::get(widget)->isExplicitlyHidden())
widget->show();
return index;
@@ -326,7 +286,7 @@ int QStatusBar::insertWidget(int index, QWidget *widget, int stretch)
minimum of space.
Permanently means that the widget may not be obscured by temporary
- messages. It is is located at the far right of the status bar.
+ messages. It is located at the far right of the status bar.
\sa insertPermanentWidget(), removeWidget(), addWidget()
*/
@@ -338,7 +298,6 @@ void QStatusBar::addPermanentWidget(QWidget * widget, int stretch)
insertPermanentWidget(d_func()->items.size(), widget, stretch);
}
-
/*!
\since 4.2
@@ -353,7 +312,7 @@ void QStatusBar::addPermanentWidget(QWidget * widget, int stretch)
minimum of space.
Permanently means that the widget may not be obscured by temporary
- messages. It is is located at the far right of the status bar.
+ messages. It is located at the far right of the status bar.
\sa addPermanentWidget(), removeWidget(), addWidget()
*/
@@ -363,7 +322,7 @@ int QStatusBar::insertPermanentWidget(int index, QWidget *widget, int stretch)
return -1;
Q_D(QStatusBar);
- QStatusBarPrivate::SBItem* item = new QStatusBarPrivate::SBItem(widget, stretch, true);
+ QStatusBarPrivate::SBItem item{widget, stretch, QStatusBarPrivate::Permanent};
int idx = d->indexToLastNonPermanentWidget();
if (Q_UNLIKELY(index < 0 || index > d->items.size() || (idx >= 0 && index <= idx))) {
@@ -373,7 +332,7 @@ int QStatusBar::insertPermanentWidget(int index, QWidget *widget, int stretch)
d->items.insert(index, item);
reformat();
- if (!widget->isHidden() || !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ if (!QWidgetPrivate::get(widget)->isExplicitlyHidden())
widget->show();
return index;
@@ -395,23 +354,10 @@ void QStatusBar::removeWidget(QWidget *widget)
return;
Q_D(QStatusBar);
- bool found = false;
- QStatusBarPrivate::SBItem* item;
- for (int i=0; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item)
- break;
- if (item->w == widget) {
- d->items.removeAt(i);
- item->w->hide();
- delete item;
- found = true;
- break;
- }
- }
-
- if (found)
+ if (d->items.removeIf([widget](const auto &item) { return item.widget == widget; })) {
+ widget->hide();
reformat();
+ }
#if defined(QT_DEBUG)
else
qDebug("QStatusBar::removeWidget(): Widget not found.");
@@ -495,25 +441,22 @@ void QStatusBar::reformat()
int maxH = fontMetrics().height();
- int i;
- QStatusBarPrivate::SBItem* item;
- for (i=0,item=nullptr; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item || item->p)
+ qsizetype i;
+ for (i = 0; i < d->items.size(); ++i) {
+ const auto &item = d->items.at(i);
+ if (item.isPermanent())
break;
- l->addWidget(item->w, item->s);
- int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight());
+ l->addWidget(item.widget, item.stretch);
+ int itemH = qMin(qSmartMinSize(item.widget).height(), item.widget->maximumHeight());
maxH = qMax(maxH, itemH);
}
l->addStretch(0);
- for (item=nullptr; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item)
- break;
- l->addWidget(item->w, item->s);
- int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight());
+ for (; i < d->items.size(); ++i) {
+ const auto &item = d->items.at(i);
+ l->addWidget(item.widget, item.stretch);
+ int itemH = qMin(qSmartMinSize(item.widget).height(), item.widget->maximumHeight());
maxH = qMax(maxH, itemH);
}
#if QT_CONFIG(sizegrip)
@@ -551,7 +494,7 @@ void QStatusBar::showMessage(const QString &message, int timeout)
if (timeout > 0) {
if (!d->timer) {
d->timer = new QTimer(this);
- connect(d->timer, SIGNAL(timeout()), this, SLOT(clearMessage()));
+ connect(d->timer, &QTimer::timeout, this, &QStatusBar::clearMessage);
}
d->timer->start(timeout);
} else if (d->timer) {
@@ -577,7 +520,7 @@ void QStatusBar::clearMessage()
if (d->tempItem.isEmpty())
return;
if (d->timer) {
- qDeleteInEventHandler(d->timer);
+ delete d->timer;
d->timer = nullptr;
}
d->tempItem.clear();
@@ -617,22 +560,20 @@ void QStatusBar::hideOrShow()
Q_D(QStatusBar);
bool haveMessage = !d->tempItem.isEmpty();
- QStatusBarPrivate::SBItem* item = nullptr;
- for (int i=0; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item || item->p)
+ for (const auto &item : std::as_const(d->items)) {
+ if (item.isPermanent())
break;
- if (haveMessage && item->w->isVisible()) {
- item->w->hide();
- item->w->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
- } else if (!haveMessage && !item->w->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
- item->w->show();
+ if (haveMessage && item.widget->isVisible()) {
+ item.widget->hide();
+ item.widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ } else if (!haveMessage && !item.widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
+ item.widget->show();
}
}
emit messageChanged(d->tempItem);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
QAccessibleEvent event(this, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
@@ -671,16 +612,15 @@ void QStatusBar::paintEvent(QPaintEvent *event)
opt.initFrom(this);
style()->drawPrimitive(QStyle::PE_PanelStatusBar, &opt, &p, this);
- for (int i=0; i<d->items.size(); ++i) {
- QStatusBarPrivate::SBItem* item = d->items.at(i);
- if (item && item->w->isVisible() && (!haveMessage || item->p)) {
- QRect ir = item->w->geometry().adjusted(-2, -1, 2, 1);
+ for (const auto &item : std::as_const(d->items)) {
+ if (item.widget->isVisible() && (!haveMessage || item.isPermanent())) {
+ QRect ir = item.widget->geometry().adjusted(-2, -1, 2, 1);
if (event->rect().intersects(ir)) {
QStyleOption opt(0);
opt.rect = ir;
opt.palette = palette();
opt.state = QStyle::State_None;
- style()->drawPrimitive(QStyle::PE_FrameStatusBarItem, &opt, &p, item->w);
+ style()->drawPrimitive(QStyle::PE_FrameStatusBarItem, &opt, &p, item.widget);
}
}
}
@@ -706,17 +646,13 @@ bool QStatusBar::event(QEvent *e)
{
Q_D(QStatusBar);
- if (e->type() == QEvent::LayoutRequest
- ) {
+ switch (e->type()) {
+ case QEvent::LayoutRequest: {
// Calculate new strut height and call reformat() if it has changed
int maxH = fontMetrics().height();
- QStatusBarPrivate::SBItem* item = nullptr;
- for (int i=0; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item)
- break;
- int itemH = qMin(qSmartMinSize(item->w).height(), item->w->maximumHeight());
+ for (const auto &item : std::as_const(d->items)) {
+ const int itemH = qMin(qSmartMinSize(item.widget).height(), item.widget->maximumHeight());
maxH = qMax(maxH, itemH);
}
@@ -729,18 +665,17 @@ bool QStatusBar::event(QEvent *e)
reformat();
else
update();
+ break;
}
- if (e->type() == QEvent::ChildRemoved) {
- QStatusBarPrivate::SBItem* item = nullptr;
- for (int i=0; i<d->items.size(); ++i) {
- item = d->items.at(i);
- if (!item)
- break;
- if (item->w == ((QChildEvent*)e)->child()) {
+ case QEvent::ChildRemoved:
+ for (int i = 0; i < d->items.size(); ++i) {
+ const auto &item = d->items.at(i);
+ if (item.widget == static_cast<QChildEvent *>(e)->child())
d->items.removeAt(i);
- delete item;
- }
}
+ break;
+ default:
+ break;
}
return QWidget::event(e);
diff --git a/src/widgets/widgets/qstatusbar.h b/src/widgets/widgets/qstatusbar.h
index 2492e8487f..2bf8e0c632 100644
--- a/src/widgets/widgets/qstatusbar.h
+++ b/src/widgets/widgets/qstatusbar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTATUSBAR_H
#define QSTATUSBAR_H
@@ -83,7 +47,6 @@ protected:
void paintEvent(QPaintEvent *) override;
void resizeEvent(QResizeEvent *) override;
- // ### Qt 6: consider making reformat() and hideOrShow() private
void reformat();
void hideOrShow();
bool event(QEvent *) override;
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index a7b115a1bc..0b463840ae 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -1,49 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qlayoutengine_p.h"
#if QT_CONFIG(itemviews)
#include "qabstractitemdelegate.h"
#endif
#include "qapplication.h"
-#include "qbitmap.h"
-#include "qcursor.h"
#include "qevent.h"
#include "qpainter.h"
#include "qstyle.h"
@@ -52,15 +14,17 @@
#if QT_CONFIG(tabwidget)
#include "qtabwidget.h"
#endif
+#if QT_CONFIG(tooltip)
#include "qtooltip.h"
+#endif
#if QT_CONFIG(whatsthis)
#include "qwhatsthis.h"
#endif
#include "private/qtextengine_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
#include <qpa/qplatformnativeinterface.h>
#endif
@@ -70,6 +34,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
class CloseButton : public QAbstractButton
{
@@ -81,7 +47,7 @@ public:
QSize sizeHint() const override;
QSize minimumSizeHint() const override
{ return sizeHint(); }
- void enterEvent(QEvent *event) override;
+ void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
};
@@ -105,17 +71,9 @@ void QMovableTabWidget::paintEvent(QPaintEvent *e)
p.drawPixmap(0, 0, m_pixmap);
}
-inline static bool verticalTabs(QTabBar::Shape shape)
-{
- return shape == QTabBar::RoundedWest
- || shape == QTabBar::RoundedEast
- || shape == QTabBar::TriangularWest
- || shape == QTabBar::TriangularEast;
-}
-
void QTabBarPrivate::updateMacBorderMetrics()
{
-#if defined(Q_OS_OSX)
+#if defined(Q_OS_MACOS)
Q_Q(QTabBar);
// Extend the unified title and toolbar area to cover the tab bar iff
// 1) the tab bar is in document mode
@@ -137,6 +95,8 @@ void QTabBarPrivate::updateMacBorderMetrics()
}
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
+ if (!nativeInterface)
+ return;
quintptr identifier = reinterpret_cast<quintptr>(q);
// Set geometry
@@ -170,7 +130,7 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex)
if (!option || (tabIndex < 0 || tabIndex >= totalTabs))
return;
- const QTabBarPrivate::Tab &tab = tabList.at(tabIndex);
+ const QTabBarPrivate::Tab &tab = *tabList.at(tabIndex);
option->initFrom(q);
option->state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver);
option->rect = q->tabRect(tabIndex);
@@ -208,7 +168,7 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex)
option->selectedPosition = QStyleOptionTab::NotAdjacent;
const bool paintBeginning = (tabIndex == firstVisible) || (dragInProgress && tabIndex == pressedIndex + 1);
- const bool paintEnd = (tabIndex == lastVisible - 1) || (dragInProgress && tabIndex == pressedIndex - 1);
+ const bool paintEnd = (tabIndex == lastVisible) || (dragInProgress && tabIndex == pressedIndex - 1);
if (paintBeginning) {
if (paintEnd)
option->position = QStyleOptionTab::OnlyOneTab;
@@ -229,8 +189,7 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex)
option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
}
#endif
- if (QStyleOptionTabV4 *optv4 = qstyleoption_cast<QStyleOptionTabV4 *>(option))
- optv4->tabIndex = tabIndex;
+ option->tabIndex = tabIndex;
}
/*!
@@ -316,9 +275,9 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
returns the visual geometry of a single tab.
\table 100%
- \row \li \inlineimage fusion-tabbar.png Screenshot of a Fusion style tab bar
+ \row \li \inlineimage {fusion-tabbar.png} {Screenshot of a Fusion style tab bar}
\li A tab bar shown in the \l{Qt Widget Gallery}{Fusion widget style}.
- \row \li \inlineimage fusion-tabbar-truncated.png Screenshot of a truncated Fusion tab bar
+ \row \li \inlineimage {fusion-tabbar-truncated.png} {Screenshot of a truncated Fusion tab bar}
\li A truncated tab bar shown in the Fusion widget style.
\endtable
@@ -405,12 +364,16 @@ void QTabBarPrivate::init()
{
Q_Q(QTabBar);
leftB = new QToolButton(q);
+ leftB->setObjectName(u"ScrollLeftButton"_s);
leftB->setAutoRepeat(true);
- QObject::connect(leftB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs()));
+ QObjectPrivate::connect(leftB, &QToolButton::clicked,
+ this, &QTabBarPrivate::scrollTabs);
leftB->hide();
rightB = new QToolButton(q);
+ rightB->setObjectName(u"ScrollRightButton"_s);
rightB->setAutoRepeat(true);
- QObject::connect(rightB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs()));
+ QObjectPrivate::connect(rightB, &QToolButton::clicked,
+ this, &QTabBarPrivate::scrollTabs);
rightB->hide();
#ifdef QT_KEYPAD_NAVIGATION
if (QApplicationPrivate::keypadNavigationEnabled()) {
@@ -421,7 +384,7 @@ void QTabBarPrivate::init()
#endif
q->setFocusPolicy(Qt::TabFocus);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
leftB->setAccessibleName(QTabBar::tr("Scroll Left"));
rightB->setAccessibleName(QTabBar::tr("Scroll Right"));
#endif
@@ -430,23 +393,13 @@ void QTabBarPrivate::init()
useScrollButtons = !q->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, nullptr, q);
}
-QTabBarPrivate::Tab *QTabBarPrivate::at(int index)
-{
- return validIndex(index)?&tabList[index]:nullptr;
-}
-
-const QTabBarPrivate::Tab *QTabBarPrivate::at(int index) const
-{
- return validIndex(index)?&tabList[index]:nullptr;
-}
-
int QTabBarPrivate::indexAtPos(const QPoint &p) const
{
Q_Q(const QTabBar);
if (q->tabRect(currentIndex).contains(p))
return currentIndex;
- for (int i = 0; i < tabList.count(); ++i)
- if (tabList.at(i).enabled && q->tabRect(i).contains(p))
+ for (int i = 0; i < tabList.size(); ++i)
+ if (tabList.at(i)->enabled && q->tabRect(i).contains(p))
return i;
return -1;
}
@@ -458,13 +411,12 @@ void QTabBarPrivate::layoutTabs()
QSize size = q->size();
int last, available;
int maxExtent;
- int i;
bool vertTabs = verticalTabs(shape);
int tabChainIndex = 0;
int hiddenTabs = 0;
Qt::Alignment tabAlignment = Qt::Alignment(q->style()->styleHint(QStyle::SH_TabBar_Alignment, nullptr, q));
- QVector<QLayoutStruct> tabChain(tabList.count() + 2);
+ QList<QLayoutStruct> tabChain(tabList.size() + 2);
// We put an empty item at the front and back and set its expansive attribute
// depending on tabAlignment and expanding.
@@ -487,20 +439,21 @@ void QTabBarPrivate::layoutTabs()
int minx = 0;
int x = 0;
int maxHeight = 0;
- for (i = 0; i < tabList.count(); ++i) {
- if (!tabList.at(i).visible) {
+ for (int i = 0; i < tabList.size(); ++i) {
+ const auto tab = tabList.at(i);
+ if (!tab->visible) {
++hiddenTabs;
continue;
}
QSize sz = q->tabSizeHint(i);
- tabList[i].maxRect = QRect(x, 0, sz.width(), sz.height());
+ tab->maxRect = QRect(x, 0, sz.width(), sz.height());
x += sz.width();
maxHeight = qMax(maxHeight, sz.height());
sz = q->minimumTabSizeHint(i);
- tabList[i].minRect = QRect(minx, 0, sz.width(), sz.height());
+ tab->minRect = QRect(minx, 0, sz.width(), sz.height());
minx += sz.width();
tabChain[tabChainIndex].init();
- tabChain[tabChainIndex].sizeHint = tabList.at(i).maxRect.width();
+ tabChain[tabChainIndex].sizeHint = tab->maxRect.width();
tabChain[tabChainIndex].minimumSize = sz.width();
tabChain[tabChainIndex].empty = false;
tabChain[tabChainIndex].expansive = true;
@@ -517,20 +470,21 @@ void QTabBarPrivate::layoutTabs()
int miny = 0;
int y = 0;
int maxWidth = 0;
- for (i = 0; i < tabList.count(); ++i) {
- if (!tabList.at(i).visible) {
+ for (int i = 0; i < tabList.size(); ++i) {
+ auto tab = tabList.at(i);
+ if (!tab->visible) {
++hiddenTabs;
continue;
}
QSize sz = q->tabSizeHint(i);
- tabList[i].maxRect = QRect(0, y, sz.width(), sz.height());
+ tab->maxRect = QRect(0, y, sz.width(), sz.height());
y += sz.height();
maxWidth = qMax(maxWidth, sz.width());
sz = q->minimumTabSizeHint(i);
- tabList[i].minRect = QRect(0, miny, sz.width(), sz.height());
+ tab->minRect = QRect(0, miny, sz.width(), sz.height());
miny += sz.height();
tabChain[tabChainIndex].init();
- tabChain[tabChainIndex].sizeHint = tabList.at(i).maxRect.height();
+ tabChain[tabChainIndex].sizeHint = tab->maxRect.height();
tabChain[tabChainIndex].minimumSize = sz.height();
tabChain[tabChainIndex].empty = false;
tabChain[tabChainIndex].expansive = true;
@@ -551,33 +505,33 @@ void QTabBarPrivate::layoutTabs()
&& (tabAlignment != Qt::AlignRight)
&& (tabAlignment != Qt::AlignJustify);
tabChain[tabChainIndex].empty = true;
- Q_ASSERT(tabChainIndex == tabChain.count() - 1 - hiddenTabs); // add an assert just to make sure.
+ Q_ASSERT(tabChainIndex == tabChain.size() - 1 - hiddenTabs); // add an assert just to make sure.
// Do the calculation
- qGeomCalc(tabChain, 0, tabChain.count(), 0, qMax(available, last), 0);
+ qGeomCalc(tabChain, 0, tabChain.size(), 0, qMax(available, last), 0);
// Use the results
hiddenTabs = 0;
- for (i = 0; i < tabList.count(); ++i) {
- if (!tabList.at(i).visible) {
- tabList[i].rect = QRect();
+ for (int i = 0; i < tabList.size(); ++i) {
+ auto tab = tabList.at(i);
+ if (!tab->visible) {
+ tab->rect = QRect();
++hiddenTabs;
continue;
}
const QLayoutStruct &lstruct = tabChain.at(i + 1 - hiddenTabs);
if (!vertTabs)
- tabList[i].rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
+ tab->rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
else
- tabList[i].rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
+ tab->rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
}
- if (useScrollButtons && tabList.count() && last > available) {
+ if (useScrollButtons && tabList.size() && last > available) {
const QRect scrollRect = normalizedScrollRect(0);
- scrollOffset = -scrollRect.left();
Q_Q(QTabBar);
QStyleOption opt;
- opt.init(q);
+ opt.initFrom(q);
QRect scrollButtonLeftRect = q->style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, q);
QRect scrollButtonRightRect = q->style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, q);
int scrollButtonWidth = q->style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, &opt, q);
@@ -610,10 +564,9 @@ void QTabBarPrivate::layoutTabs()
leftB->show();
rightB->setGeometry(scrollButtonRightRect);
- rightB->setEnabled(last - scrollOffset > scrollRect.x() + scrollRect.width());
+ rightB->setEnabled(last + scrollRect.left() > scrollRect.x() + scrollRect.width());
rightB->show();
} else {
- scrollOffset = 0;
rightB->hide();
leftB->hide();
}
@@ -630,7 +583,12 @@ QRect QTabBarPrivate::normalizedScrollRect(int index)
// tab bar itself is in a different orientation.
Q_Q(QTabBar);
- QStyleOptionTabV4 opt;
+ // If scrollbuttons are not visible, then there's no tear either, and
+ // the entire widget is the scroll rect.
+ if (leftB->isHidden())
+ return verticalTabs(shape) ? q->rect().transposed() : q->rect();
+
+ QStyleOptionTab opt;
q->initStyleOption(&opt, currentIndex);
opt.rect = q->rect();
@@ -656,7 +614,7 @@ QRect QTabBarPrivate::normalizedScrollRect(int index)
}
bool tearTopVisible = index != 0 && topEdge != -scrollOffset;
- bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.constLast().rect.bottom() + 1 - scrollOffset;
+ bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.constLast()->rect.bottom() + 1 - scrollOffset;
if (tearTopVisible && !tearLeftRect.isNull())
topEdge = tearLeftRect.bottom() + 1;
if (tearBottomVisible && !tearRightRect.isNull())
@@ -687,7 +645,7 @@ QRect QTabBarPrivate::normalizedScrollRect(int index)
}
bool tearLeftVisible = index != 0 && leftEdge != -scrollOffset;
- bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.constLast().rect.right() + 1 - scrollOffset;
+ bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.constLast()->rect.right() + 1 - scrollOffset;
if (tearLeftVisible && !tearLeftRect.isNull())
leftEdge = tearLeftRect.right() + 1;
if (tearRightVisible && !tearRightRect.isNull())
@@ -709,25 +667,33 @@ int QTabBarPrivate::hoveredTabIndex() const
void QTabBarPrivate::makeVisible(int index)
{
Q_Q(QTabBar);
- if (!validIndex(index) || leftB->isHidden())
+ if (!validIndex(index))
return;
- const QRect tabRect = tabList.at(index).rect;
+ const QRect tabRect = tabList.at(index)->rect;
const int oldScrollOffset = scrollOffset;
const bool horiz = !verticalTabs(shape);
+ const int available = horiz ? q->width() : q->height();
const int tabStart = horiz ? tabRect.left() : tabRect.top();
const int tabEnd = horiz ? tabRect.right() : tabRect.bottom();
- const int lastTabEnd = horiz ? tabList.constLast().rect.right() : tabList.constLast().rect.bottom();
+ const int lastTabEnd = horiz ? tabList.constLast()->rect.right() : tabList.constLast()->rect.bottom();
const QRect scrollRect = normalizedScrollRect(index);
+ const QRect entireScrollRect = normalizedScrollRect(0); // ignore tears
const int scrolledTabBarStart = qMax(1, scrollRect.left() + scrollOffset);
const int scrolledTabBarEnd = qMin(lastTabEnd - 1, scrollRect.right() + scrollOffset);
- if (tabStart < scrolledTabBarStart) {
+ if (available >= lastTabEnd) {
+ // the entire tabbar fits, reset scroll
+ scrollOffset = 0;
+ } else if (tabStart < scrolledTabBarStart) {
// Tab is outside on the left, so scroll left.
scrollOffset = tabStart - scrollRect.left();
} else if (tabEnd > scrolledTabBarEnd) {
// Tab is outside on the right, so scroll right.
- scrollOffset = tabEnd - scrollRect.right();
+ scrollOffset = qMax(0, tabEnd - scrollRect.right());
+ } else if (scrollOffset + entireScrollRect.width() > lastTabEnd + 1) {
+ // fill any free space on the right without overshooting
+ scrollOffset = qMax(0, lastTabEnd - entireScrollRect.width() + 1);
}
leftB->setEnabled(scrollOffset > -scrollRect.left());
@@ -754,34 +720,34 @@ void QTabBarPrivate::layoutTab(int index)
Q_Q(QTabBar);
Q_ASSERT(index >= 0);
- Tab &tab = tabList[index];
+ const Tab *tab = tabList.at(index);
bool vertical = verticalTabs(shape);
- if (!(tab.leftWidget || tab.rightWidget))
+ if (!(tab->leftWidget || tab->rightWidget))
return;
- QStyleOptionTabV4 opt;
+ QStyleOptionTab opt;
q->initStyleOption(&opt, index);
- if (tab.leftWidget) {
+ if (tab->leftWidget) {
QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabLeftButton, &opt, q);
QPoint p = rect.topLeft();
if ((index == pressedIndex) || paintWithOffsets) {
if (vertical)
- p.setY(p.y() + tabList[index].dragOffset);
+ p.setY(p.y() + tab->dragOffset);
else
- p.setX(p.x() + tabList[index].dragOffset);
+ p.setX(p.x() + tab->dragOffset);
}
- tab.leftWidget->move(p);
+ tab->leftWidget->move(p);
}
- if (tab.rightWidget) {
+ if (tab->rightWidget) {
QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabRightButton, &opt, q);
QPoint p = rect.topLeft();
if ((index == pressedIndex) || paintWithOffsets) {
if (vertical)
- p.setY(p.y() + tab.dragOffset);
+ p.setY(p.y() + tab->dragOffset);
else
- p.setX(p.x() + tab.dragOffset);
+ p.setX(p.x() + tab->dragOffset);
}
- tab.rightWidget->move(p);
+ tab->rightWidget->move(p);
}
}
@@ -801,20 +767,20 @@ void QTabBarPrivate::autoHideTabs()
q->setVisible(q->count() > 1);
}
-void QTabBarPrivate::_q_closeTab()
+void QTabBarPrivate::closeTab()
{
Q_Q(QTabBar);
QObject *object = q->sender();
int tabToClose = -1;
QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition)q->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, q);
- for (int i = 0; i < tabList.count(); ++i) {
+ for (int i = 0; i < tabList.size(); ++i) {
if (closeSide == QTabBar::LeftSide) {
- if (tabList.at(i).leftWidget == object) {
+ if (tabList.at(i)->leftWidget == object) {
tabToClose = i;
break;
}
} else {
- if (tabList.at(i).rightWidget == object) {
+ if (tabList.at(i)->rightWidget == object) {
tabToClose = i;
break;
}
@@ -824,26 +790,29 @@ void QTabBarPrivate::_q_closeTab()
emit q->tabCloseRequested(tabToClose);
}
-void QTabBarPrivate::_q_scrollTabs()
+void QTabBarPrivate::scrollTabs()
{
Q_Q(QTabBar);
const QObject *sender = q->sender();
const bool horizontal = !verticalTabs(shape);
- const QRect scrollRect = normalizedScrollRect();
+ const QRect scrollRect = normalizedScrollRect().translated(scrollOffset, 0);
+
int i = -1;
if (sender == leftB) {
- for (i = tabList.count() - 1; i >= 0; --i) {
- int start = horizontal ? tabList.at(i).rect.left() : tabList.at(i).rect.top();
- if (start < scrollRect.left() + scrollOffset) {
+ for (i = tabList.size() - 1; i >= 0; --i) {
+ int start = horizontal ? tabList.at(i)->rect.left() : tabList.at(i)->rect.top();
+ if (start < scrollRect.left()) {
makeVisible(i);
return;
}
}
} else if (sender == rightB) {
- for (i = 0; i < tabList.count(); ++i) {
- int end = horizontal ? tabList.at(i).rect.right() : tabList.at(i).rect.bottom();
- if (end > scrollRect.right() + scrollOffset) {
+ for (i = 0; i < tabList.size(); ++i) {
+ const auto tabRect = tabList.at(i)->rect;
+ int start = horizontal ? tabRect.left() : tabRect.top();
+ int end = horizontal ? tabRect.right() : tabRect.bottom();
+ if (end > scrollRect.right() && start > scrollOffset) {
makeVisible(i);
return;
}
@@ -858,7 +827,7 @@ void QTabBarPrivate::refresh()
// be safe in case a subclass is also handling move with the tabs
if (pressedIndex != -1
&& movable
- && QGuiApplication::mouseButtons() == Qt::NoButton) {
+ && mouseButtons == Qt::NoButton) {
moveTabFinished(pressedIndex);
if (!validIndex(pressedIndex))
pressedIndex = -1;
@@ -919,7 +888,7 @@ void QTabBar::setShape(Shape shape)
\property QTabBar::drawBase
\brief defines whether or not tab bar should draw its base.
- If true then QTabBar draws a base in relation to the styles overlab.
+ If true then QTabBar draws a base in relation to the styles overlap.
Otherwise only the tabs are drawn.
\sa QStyle::pixelMetric(), QStyle::PM_TabBarBaseOverlap, QStyleOptionTabBarBase
@@ -962,7 +931,7 @@ int QTabBar::addTab(const QIcon& icon, const QString &text)
/*!
Inserts a new tab with text \a text at position \a index. If \a
- index is out of range, the new tab is appened. Returns the new
+ index is out of range, the new tab is appended. Returns the new
tab's index.
*/
int QTabBar::insertTab(int index, const QString &text)
@@ -986,36 +955,44 @@ int QTabBar::insertTab(int index, const QIcon& icon, const QString &text)
{
Q_D(QTabBar);
if (!d->validIndex(index)) {
- index = d->tabList.count();
- d->tabList.append(QTabBarPrivate::Tab(icon, text));
+ index = d->tabList.size();
+ d->tabList.append(new QTabBarPrivate::Tab(icon, text));
} else {
- d->tabList.insert(index, QTabBarPrivate::Tab(icon, text));
+ d->tabList.insert(index, new QTabBarPrivate::Tab(icon, text));
}
#ifndef QT_NO_SHORTCUT
- d->tabList[index].shortcutId = grabShortcut(QKeySequence::mnemonic(text));
+ d->tabList.at(index)->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
#endif
d->firstVisible = qMax(qMin(index, d->firstVisible), 0);
- d->lastVisible = qMax(index, d->lastVisible);
d->refresh();
- if (d->tabList.count() == 1)
+ if (d->tabList.size() == 1)
setCurrentIndex(index);
- else if (index <= d->currentIndex) {
+ else if (index <= d->currentIndex)
++d->currentIndex;
+
+ if (index <= d->lastVisible)
++d->lastVisible;
- }
+ else
+ d->lastVisible = index;
if (d->closeButtonOnTabs) {
- QStyleOptionTabV4 opt;
+ QStyleOptionTab opt;
initStyleOption(&opt, index);
ButtonPosition closeSide = (ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, this);
QAbstractButton *closeButton = new CloseButton(this);
- connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
+ QObjectPrivate::connect(closeButton, &CloseButton::clicked,
+ d, &QTabBarPrivate::closeTab);
setTabButton(index, closeSide, closeButton);
}
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (d->tabList[i].lastTab >= index)
- ++d->tabList[i].lastTab;
+ for (const auto tab : std::as_const(d->tabList)) {
+ if (tab->lastTab >= index)
+ ++tab->lastTab;
+ }
+
+ if (tabAt(d->mousePosition) == index) {
+ d->hoverIndex = index;
+ d->hoverRect = tabRect(index);
}
tabInserted(index);
@@ -1033,30 +1010,32 @@ void QTabBar::removeTab(int index)
{
Q_D(QTabBar);
if (d->validIndex(index)) {
+ auto removedTab = d->tabList.at(index);
if (d->dragInProgress)
d->moveTabFinished(d->pressedIndex);
#ifndef QT_NO_SHORTCUT
- releaseShortcut(d->tabList.at(index).shortcutId);
+ releaseShortcut(d->tabList.at(index)->shortcutId);
#endif
- if (d->tabList[index].leftWidget) {
- d->tabList[index].leftWidget->hide();
- d->tabList[index].leftWidget->deleteLater();
- d->tabList[index].leftWidget = nullptr;
+ if (removedTab->leftWidget) {
+ removedTab->leftWidget->hide();
+ removedTab->leftWidget->deleteLater();
+ removedTab->leftWidget = nullptr;
}
- if (d->tabList[index].rightWidget) {
- d->tabList[index].rightWidget->hide();
- d->tabList[index].rightWidget->deleteLater();
- d->tabList[index].rightWidget = nullptr;
+ if (removedTab->rightWidget) {
+ removedTab->rightWidget->hide();
+ removedTab->rightWidget->deleteLater();
+ removedTab->rightWidget = nullptr;
}
- int newIndex = d->tabList[index].lastTab;
+ int newIndex = removedTab->lastTab;
d->tabList.removeAt(index);
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (d->tabList[i].lastTab == index)
- d->tabList[i].lastTab = -1;
- if (d->tabList[i].lastTab > index)
- --d->tabList[i].lastTab;
+ delete removedTab;
+ for (auto tab : std::as_const(d->tabList)) {
+ if (tab->lastTab == index)
+ tab->lastTab = -1;
+ if (tab->lastTab > index)
+ --tab->lastTab;
}
d->calculateFirstLastVisible(index, false, true);
@@ -1071,7 +1050,7 @@ void QTabBar::removeTab(int index)
case SelectPreviousTab:
if (newIndex > index)
newIndex--;
- if (d->validIndex(newIndex) && d->tabList.at(newIndex).visible)
+ if (d->validIndex(newIndex) && d->tabList.at(newIndex)->visible)
break;
Q_FALLTHROUGH();
case SelectRightTab:
@@ -1079,8 +1058,6 @@ void QTabBar::removeTab(int index)
break;
case SelectLeftTab:
newIndex = qBound(d->firstVisible, index-1, d->lastVisible);
- if (newIndex < 0)
- newIndex = 0;
break;
default:
break;
@@ -1088,9 +1065,12 @@ void QTabBar::removeTab(int index)
if (d->validIndex(newIndex)) {
// don't loose newIndex's old through setCurrentIndex
- int bump = d->tabList[newIndex].lastTab;
+ int bump = d->tabList.at(newIndex)->lastTab;
setCurrentIndex(newIndex);
- d->tabList[newIndex].lastTab = bump;
+ d->tabList.at(newIndex)->lastTab = bump;
+ } else {
+ // we had a valid current index, but there are no visible tabs left
+ emit currentChanged(-1);
}
} else {
emit currentChanged(-1);
@@ -1100,16 +1080,15 @@ void QTabBar::removeTab(int index)
}
d->refresh();
d->autoHideTabs();
- if (!d->hoverRect.isEmpty()) {
- for (int i = 0; i < d->tabList.count(); ++i) {
- const QRect area = tabRect(i);
- if (area.contains(mapFromGlobal(QCursor::pos()))) {
- d->hoverIndex = i;
- d->hoverRect = area;
- break;
- }
- }
+ if (d->hoverRect.isValid()) {
update(d->hoverRect);
+ d->hoverIndex = tabAt(d->mousePosition);
+ if (d->validIndex(d->hoverIndex)) {
+ d->hoverRect = tabRect(d->hoverIndex);
+ update(d->hoverRect);
+ } else {
+ d->hoverRect = QRect();
+ }
}
tabRemoved(index);
}
@@ -1158,7 +1137,7 @@ bool QTabBar::isTabVisible(int index) const
{
Q_D(const QTabBar);
if (d->validIndex(index))
- return d->tabList.at(index).visible;
+ return d->tabList.at(index)->visible;
return false;
}
@@ -1280,7 +1259,7 @@ void QTabBar::setTabIcon(int index, const QIcon & icon)
}
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
/*!
Sets the tool tip of the tab at position \a index to \a tip.
*/
@@ -1302,7 +1281,7 @@ QString QTabBar::tabToolTip(int index) const
return tab->toolTip;
return QString();
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(whatsthis)
/*!
@@ -1423,17 +1402,30 @@ void QTabBar::setCurrentIndex(int index)
Q_D(QTabBar);
if (d->dragInProgress && d->pressedIndex != -1)
return;
+ if (d->currentIndex == index)
+ return;
int oldIndex = d->currentIndex;
- if (d->validIndex(index) && d->currentIndex != index) {
+ if (auto tab = d->at(index)) {
d->currentIndex = index;
+ // If the size hint depends on whether the tab is selected (for instance a style
+ // sheet rule that sets a bold font on the 'selected' tab) then we need to
+ // re-layout the entire tab bar. To minimize the cost, do that only if the
+ // size hint changes for the tab that becomes the current tab (the old current tab
+ // will most certainly do the same). QTBUG-6905
+ if (tabRect(index).size() != tabSizeHint(index))
+ d->layoutTabs();
update();
- d->makeVisible(index);
- d->tabList[index].lastTab = oldIndex;
- if (oldIndex >= 0 && oldIndex < count())
+ if (!isVisible())
+ d->layoutDirty = true;
+ else
+ d->makeVisible(index);
+ if (d->validIndex(oldIndex)) {
+ tab->lastTab = oldIndex;
d->layoutTab(oldIndex);
+ }
d->layoutTab(index);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
if (hasFocus()) {
QAccessibleEvent focusEvent(this, QAccessible::Focus);
@@ -1486,7 +1478,7 @@ void QTabBar::setIconSize(const QSize &size)
int QTabBar::count() const
{
Q_D(const QTabBar);
- return d->tabList.count();
+ return d->tabList.size();
}
@@ -1498,12 +1490,11 @@ QSize QTabBar::sizeHint() const
if (d->layoutDirty)
const_cast<QTabBarPrivate*>(d)->layoutTabs();
QRect r;
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (d->tabList.at(i).visible)
- r = r.united(d->tabList.at(i).maxRect);
+ for (const auto tab : d->tabList) {
+ if (tab->visible)
+ r = r.united(tab->maxRect);
}
- QSize sz = QApplication::globalStrut();
- return r.size().expandedTo(sz);
+ return r.size();
}
/*!\reimp
@@ -1515,11 +1506,11 @@ QSize QTabBar::minimumSizeHint() const
const_cast<QTabBarPrivate*>(d)->layoutTabs();
if (!d->useScrollButtons) {
QRect r;
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (d->tabList.at(i).visible)
- r = r.united(d->tabList.at(i).minRect);
+ for (const auto tab : d->tabList) {
+ if (tab->visible)
+ r = r.united(tab->minRect);
}
- return r.size().expandedTo(QApplication::globalStrut());
+ return r.size();
}
if (verticalTabs(d->shape))
return QSize(sizeHint().width(), d->rightB->sizeHint().height() * 2 + 75);
@@ -1530,20 +1521,20 @@ QSize QTabBar::minimumSizeHint() const
// Compute the most-elided possible text, for minimumSizeHint
static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
{
- if (text.length() <= 3)
+ if (text.size() <= 3)
return text;
- static const QLatin1String Ellipses("...");
+ static const auto Ellipses = "..."_L1;
QString ret;
switch (mode) {
case Qt::ElideRight:
- ret = text.leftRef(2) + Ellipses;
+ ret = QStringView{text}.left(2) + Ellipses;
break;
case Qt::ElideMiddle:
- ret = text.leftRef(1) + Ellipses + text.rightRef(1);
+ ret = QStringView{text}.left(1) + Ellipses + QStringView{text}.right(1);
break;
case Qt::ElideLeft:
- ret = Ellipses + text.rightRef(2);
+ ret = Ellipses + QStringView{text}.right(2);
break;
case Qt::ElideNone:
ret = text;
@@ -1560,11 +1551,11 @@ static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
QSize QTabBar::minimumTabSizeHint(int index) const
{
Q_D(const QTabBar);
- QTabBarPrivate::Tab &tab = const_cast<QTabBarPrivate::Tab&>(d->tabList[index]);
- QString oldText = tab.text;
- tab.text = computeElidedText(d->elideMode, oldText);
+ QTabBarPrivate::Tab *tab = d->tabList.at(index);
+ QString oldText = tab->text;
+ tab->text = computeElidedText(d->elideMode, oldText);
QSize size = tabSizeHint(index);
- tab.text = oldText;
+ tab->text = oldText;
return size;
}
@@ -1576,9 +1567,9 @@ QSize QTabBar::tabSizeHint(int index) const
//Note: this must match with the computations in QCommonStylePrivate::tabLayout
Q_D(const QTabBar);
if (const QTabBarPrivate::Tab *tab = d->at(index)) {
- QStyleOptionTabV4 opt;
+ QStyleOptionTab opt;
d->initBasicStyleOption(&opt, index);
- opt.text = d->tabList.at(index).text;
+ opt.text = tab->text;
QSize iconSize = tab->icon.isNull() ? QSize(0, 0) : opt.iconSize;
int hframe = style()->pixelMetric(QStyle::PM_TabBarTabHSpace, &opt, this);
int vframe = style()->pixelMetric(QStyle::PM_TabBarTabVSpace, &opt, this);
@@ -1630,7 +1621,7 @@ QSize QTabBar::tabSizeHint(int index) const
*/
void QTabBar::tabInserted(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*!
@@ -1641,7 +1632,7 @@ void QTabBar::tabInserted(int index)
*/
void QTabBar::tabRemoved(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*!
@@ -1663,6 +1654,8 @@ void QTabBar::showEvent(QShowEvent *)
d->refresh();
if (!d->validIndex(d->currentIndex))
setCurrentIndex(0);
+ else
+ d->makeVisible(d->currentIndex);
d->updateMacBorderMetrics();
}
@@ -1679,52 +1672,53 @@ void QTabBar::hideEvent(QHideEvent *)
bool QTabBar::event(QEvent *event)
{
Q_D(QTabBar);
- if (event->type() == QEvent::HoverMove
- || event->type() == QEvent::HoverEnter) {
+ switch (event->type()) {
+ case QEvent::HoverMove:
+ case QEvent::HoverEnter: {
QHoverEvent *he = static_cast<QHoverEvent *>(event);
- if (!d->hoverRect.contains(he->pos())) {
- QRect oldHoverRect = d->hoverRect;
- bool cursorOverTabs = false;
- for (int i = 0; i < d->tabList.count(); ++i) {
- QRect area = tabRect(i);
- if (area.contains(he->pos())) {
- d->hoverIndex = i;
- d->hoverRect = area;
- cursorOverTabs = true;
- break;
- }
- }
- if (!cursorOverTabs) {
- d->hoverIndex = -1;
+ d->mousePosition = he->position().toPoint();
+ if (!d->hoverRect.contains(d->mousePosition)) {
+ if (d->hoverRect.isValid())
+ update(d->hoverRect);
+ d->hoverIndex = tabAt(d->mousePosition);
+ if (d->validIndex(d->hoverIndex)) {
+ d->hoverRect = tabRect(d->hoverIndex);
+ update(d->hoverRect);
+ } else {
d->hoverRect = QRect();
}
- if (he->oldPos() != QPoint(-1, -1))
- update(oldHoverRect);
- update(d->hoverRect);
}
return true;
- } else if (event->type() == QEvent::HoverLeave) {
- QRect oldHoverRect = d->hoverRect;
+ }
+ case QEvent::HoverLeave: {
+ d->mousePosition = {-1, -1};
+ if (d->hoverRect.isValid())
+ update(d->hoverRect);
d->hoverIndex = -1;
d->hoverRect = QRect();
- update(oldHoverRect);
+#if QT_CONFIG(wheelevent)
+ d->accumulatedAngleDelta = QPoint();
+#endif
return true;
-#ifndef QT_NO_TOOLTIP
- } else if (event->type() == QEvent::ToolTip) {
+ }
+#if QT_CONFIG(tooltip)
+ case QEvent::ToolTip:
if (const QTabBarPrivate::Tab *tab = d->at(tabAt(static_cast<QHelpEvent*>(event)->pos()))) {
if (!tab->toolTip.isEmpty()) {
QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), tab->toolTip, this);
return true;
}
}
-#endif // QT_NO_TOOLTIP
+ break;
+#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(whatsthis)
- } else if (event->type() == QEvent::QueryWhatsThis) {
+ case QEvent::QEvent::QueryWhatsThis: {
const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()));
if (!tab || tab->whatsThis.isEmpty())
event->ignore();
return true;
- } else if (event->type() == QEvent::WhatsThis) {
+ }
+ case QEvent::WhatsThis:
if (const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()))) {
if (!tab->whatsThis.isEmpty()) {
QWhatsThis::showText(static_cast<QHelpEvent*>(event)->globalPos(),
@@ -1732,35 +1726,34 @@ bool QTabBar::event(QEvent *event)
return true;
}
}
+ break;
#endif // QT_CONFIG(whatsthis)
#ifndef QT_NO_SHORTCUT
- } else if (event->type() == QEvent::Shortcut) {
+
+ case QEvent::Shortcut: {
QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
- for (int i = 0; i < d->tabList.count(); ++i) {
- const QTabBarPrivate::Tab *tab = &d->tabList.at(i);
+ for (int i = 0; i < d->tabList.size(); ++i) {
+ const QTabBarPrivate::Tab *tab = d->tabList.at(i);
if (tab->shortcutId == se->shortcutId()) {
setCurrentIndex(i);
return true;
}
}
+ }
+ break;
#endif
- } else if (event->type() == QEvent::MouseButtonDblClick) { // ### fixme Qt 6: move to mouseDoubleClickEvent(), here for BC reasons.
- const QPoint pos = static_cast<const QMouseEvent *>(event)->pos();
- const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
- || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
- if (!isEventInCornerButtons)
- emit tabBarDoubleClicked(tabAt(pos));
- } else if (event->type() == QEvent::Move) {
+ case QEvent::Move:
d->updateMacBorderMetrics();
- return QWidget::event(event);
-
+ break;
#if QT_CONFIG(draganddrop)
- } else if (event->type() == QEvent::DragEnter) {
+
+ case QEvent::DragEnter:
if (d->changeCurrentOnDrag)
event->accept();
- } else if (event->type() == QEvent::DragMove) {
+ break;
+ case QEvent::DragMove:
if (d->changeCurrentOnDrag) {
- const int tabIndex = tabAt(static_cast<QDragMoveEvent *>(event)->pos());
+ const int tabIndex = tabAt(static_cast<QDragMoveEvent *>(event)->position().toPoint());
if (isTabEnabled(tabIndex) && d->switchTabCurrentIndex != tabIndex) {
d->switchTabCurrentIndex = tabIndex;
if (d->switchTabTimerId)
@@ -1769,11 +1762,23 @@ bool QTabBar::event(QEvent *event)
}
event->ignore();
}
- } else if (event->type() == QEvent::DragLeave || event->type() == QEvent::Drop) {
+ break;
+ case QEvent::DragLeave:
+ case QEvent::Drop:
d->killSwitchTabTimer();
event->ignore();
+ break;
#endif
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ d->mousePosition = static_cast<QMouseEvent *>(event)->position().toPoint();
+ d->mouseButtons = static_cast<QMouseEvent *>(event)->buttons();
+ break;
+ default:
+ break;
}
+
return QWidget::event(event);
}
@@ -1784,6 +1789,8 @@ void QTabBar::resizeEvent(QResizeEvent *)
Q_D(QTabBar);
if (d->layoutDirty)
updateGeometry();
+
+ // when resizing, we want to keep the scroll offset as much as possible
d->layoutTabs();
d->makeVisible(d->currentIndex);
@@ -1810,7 +1817,7 @@ void QTabBar::paintEvent(QPaintEvent *)
selected = d->pressedIndex;
const QRect scrollRect = d->normalizedScrollRect();
- for (int i = 0; i < d->tabList.count(); ++i)
+ for (int i = 0; i < d->tabList.size(); ++i)
optTabBase.tabBarRect |= tabRect(i);
optTabBase.selectedTabRect = tabRect(selected);
@@ -1818,66 +1825,91 @@ void QTabBar::paintEvent(QPaintEvent *)
if (d->drawBase)
p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase);
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (!d->at(i)->visible)
+ // the buttons might be semi-transparent or not fill their rect, but we don't
+ // want the tab underneath to shine through, so clip the button area; QTBUG-50866
+ if (d->leftB->isVisible() || d->rightB->isVisible()) {
+ QStyleOption opt;
+ opt.initFrom(this);
+ QRegion buttonRegion;
+ if (d->leftB->isVisible())
+ buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, this);
+ if (d->rightB->isVisible())
+ buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, this);
+ if (!buttonRegion.isEmpty())
+ p.setClipRegion(QRegion(rect()) - buttonRegion);
+ }
+
+ for (int i = 0; i < d->tabList.size(); ++i) {
+ const auto tab = d->tabList.at(i);
+ if (!tab->visible)
continue;
- QStyleOptionTabV4 tab;
- initStyleOption(&tab, i);
- if (d->paintWithOffsets && d->tabList[i].dragOffset != 0) {
+ QStyleOptionTab tabOption;
+ initStyleOption(&tabOption, i);
+ if (d->paintWithOffsets && tab->dragOffset != 0) {
if (vertical) {
- tab.rect.moveTop(tab.rect.y() + d->tabList[i].dragOffset);
+ tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
} else {
- tab.rect.moveLeft(tab.rect.x() + d->tabList[i].dragOffset);
+ tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
}
}
- if (!(tab.state & QStyle::State_Enabled)) {
- tab.palette.setCurrentColorGroup(QPalette::Disabled);
+ if (!(tabOption.state & QStyle::State_Enabled)) {
+ tabOption.palette.setCurrentColorGroup(QPalette::Disabled);
}
// If this tab is partially obscured, make a note of it so that we can pass the information
// along when we draw the tear.
- QRect tabRect = d->tabList[i].rect;
+ QRect tabRect = tab->rect;
int tabStart = vertical ? tabRect.top() : tabRect.left();
int tabEnd = vertical ? tabRect.bottom() : tabRect.right();
if (tabStart < scrollRect.left() + d->scrollOffset) {
cutLeft = i;
- cutTabLeft = tab;
+ cutTabLeft = tabOption;
} else if (tabEnd > scrollRect.right() + d->scrollOffset) {
cutRight = i;
- cutTabRight = tab;
+ cutTabRight = tabOption;
}
// Don't bother drawing a tab if the entire tab is outside of the visible tab bar.
- if ((!vertical && (tab.rect.right() < 0 || tab.rect.left() > width()))
- || (vertical && (tab.rect.bottom() < 0 || tab.rect.top() > height())))
+ if ((!vertical && (tabOption.rect.right() < 0 || tabOption.rect.left() > width()))
+ || (vertical && (tabOption.rect.bottom() < 0 || tabOption.rect.top() > height())))
continue;
- optTabBase.tabBarRect |= tab.rect;
+ optTabBase.tabBarRect |= tabOption.rect;
if (i == selected)
continue;
- p.drawControl(QStyle::CE_TabBarTab, tab);
+ p.drawControl(QStyle::CE_TabBarTab, tabOption);
}
// Draw the selected tab last to get it "on top"
if (selected >= 0) {
- QStyleOptionTabV4 tab;
- initStyleOption(&tab, selected);
- if (d->paintWithOffsets && d->tabList[selected].dragOffset != 0) {
+ QStyleOptionTab tabOption;
+ const auto tab = d->tabList.at(selected);
+ initStyleOption(&tabOption, selected);
+
+ if (d->paintWithOffsets && tab->dragOffset != 0) {
+ // if the drag offset is != 0, a move is in progress (drag or animation)
+ // => set the tab position to Moving to preserve the rect
+ tabOption.position = QStyleOptionTab::TabPosition::Moving;
+
if (vertical)
- tab.rect.moveTop(tab.rect.y() + d->tabList[selected].dragOffset);
+ tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
else
- tab.rect.moveLeft(tab.rect.x() + d->tabList[selected].dragOffset);
- }
- if (!d->dragInProgress)
- p.drawControl(QStyle::CE_TabBarTab, tab);
- else {
- int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this);
- if (verticalTabs(d->shape))
- d->movingTab->setGeometry(tab.rect.adjusted(0, -taboverlap, 0, taboverlap));
- else
- d->movingTab->setGeometry(tab.rect.adjusted(-taboverlap, 0, taboverlap, 0));
+ tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
}
+
+ // Calculate the rect of a moving tab
+ const int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this);
+ const QRect &movingRect = verticalTabs(d->shape)
+ ? tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap)
+ : tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0);
+
+ // If a drag is in process, set the moving tab's geometry here
+ // (in an animation, it is already set)
+ if (d->dragInProgress)
+ d->movingTab->setGeometry(movingRect);
+
+ p.drawControl(QStyle::CE_TabBarTab, tabOption);
}
// Only draw the tear indicator if necessary. Most of the time we don't need too.
@@ -1906,19 +1938,17 @@ void QTabBarPrivate::calculateFirstLastVisible(int index, bool visible, bool rem
} else {
if (remove || (index == firstVisible)) {
firstVisible = -1;
- for (int i = 0; i < tabList.count(); ++i) {
- if (tabList.at(i).visible) {
+ for (int i = 0; i < tabList.size(); ++i) {
+ if (tabList.at(i)->visible) {
firstVisible = i;
break;
}
}
- if (firstVisible < 0)
- firstVisible = 0;
}
if (remove || (index == lastVisible)) {
lastVisible = -1;
- for (int i = tabList.count() - 1; i >= 0; --i) {
- if (tabList.at(i).visible) {
+ for (int i = tabList.size() - 1; i >= 0; --i) {
+ if (tabList.at(i)->visible) {
lastVisible = i;
break;
}
@@ -1935,7 +1965,7 @@ void QTabBarPrivate::calculateFirstLastVisible(int index, bool visible, bool rem
int QTabBarPrivate::selectNewCurrentIndexFrom(int fromIndex)
{
int newindex = -1;
- for (int i = fromIndex; i < tabList.count(); ++i) {
+ for (int i = fromIndex; i < tabList.size(); ++i) {
if (at(i)->visible && at(i)->enabled) {
newindex = i;
break;
@@ -1982,53 +2012,57 @@ void QTabBar::moveTab(int from, int to)
|| !d->validIndex(to))
return;
+ auto &fromTab = *d->tabList.at(from);
+ auto &toTab = *d->tabList.at(to);
+
bool vertical = verticalTabs(d->shape);
int oldPressedPosition = 0;
if (d->pressedIndex != -1) {
// Record the position of the pressed tab before reordering the tabs.
- oldPressedPosition = vertical ? d->tabList[d->pressedIndex].rect.y()
- : d->tabList[d->pressedIndex].rect.x();
+ oldPressedPosition = vertical ? d->tabList.at(d->pressedIndex)->rect.y()
+ : d->tabList.at(d->pressedIndex)->rect.x();
}
// Update the locations of the tabs first
int start = qMin(from, to);
int end = qMax(from, to);
- int width = vertical ? d->tabList[from].rect.height() : d->tabList[from].rect.width();
+ int width = vertical ? fromTab.rect.height() : fromTab.rect.width();
if (from < to)
width *= -1;
bool rtl = isRightToLeft();
for (int i = start; i <= end; ++i) {
if (i == from)
continue;
+ auto &tab = *d->tabList.at(i);
if (vertical)
- d->tabList[i].rect.moveTop(d->tabList[i].rect.y() + width);
+ tab.rect.moveTop(tab.rect.y() + width);
else
- d->tabList[i].rect.moveLeft(d->tabList[i].rect.x() + width);
+ tab.rect.moveLeft(tab.rect.x() + width);
int direction = -1;
if (rtl && !vertical)
direction *= -1;
- if (d->tabList[i].dragOffset != 0)
- d->tabList[i].dragOffset += (direction * width);
+ if (tab.dragOffset != 0)
+ tab.dragOffset += (direction * width);
}
if (vertical) {
if (from < to)
- d->tabList[from].rect.moveTop(d->tabList[to].rect.bottom() + 1);
+ fromTab.rect.moveTop(toTab.rect.bottom() + 1);
else
- d->tabList[from].rect.moveTop(d->tabList[to].rect.top() - width);
+ fromTab.rect.moveTop(toTab.rect.top() - width);
} else {
if (from < to)
- d->tabList[from].rect.moveLeft(d->tabList[to].rect.right() + 1);
+ fromTab.rect.moveLeft(toTab.rect.right() + 1);
else
- d->tabList[from].rect.moveLeft(d->tabList[to].rect.left() - width);
+ fromTab.rect.moveLeft(toTab.rect.left() - width);
}
// Move the actual data structures
d->tabList.move(from, to);
// update lastTab locations
- for (int i = 0; i < d->tabList.count(); ++i)
- d->tabList[i].lastTab = d->calculateNewPosition(from, to, d->tabList[i].lastTab);
+ for (const auto tab : std::as_const(d->tabList))
+ tab->lastTab = d->calculateNewPosition(from, to, tab->lastTab);
// update external variables
int previousIndex = d->currentIndex;
@@ -2037,7 +2071,8 @@ void QTabBar::moveTab(int from, int to)
// If we are in the middle of a drag update the dragStartPosition
if (d->pressedIndex != -1) {
d->pressedIndex = d->calculateNewPosition(from, to, d->pressedIndex);
- int newPressedPosition = vertical ? d->tabList[d->pressedIndex].rect.top() : d->tabList[d->pressedIndex].rect.left();
+ const auto pressedTab = d->tabList.at(d->pressedIndex);
+ int newPressedPosition = vertical ? pressedTab->rect.top() : pressedTab->rect.left();
int diff = oldPressedPosition - newPressedPosition;
if (isRightToLeft() && !vertical)
diff *= -1;
@@ -2069,15 +2104,15 @@ void QTabBarPrivate::slide(int from, int to)
q->setUpdatesEnabled(true);
int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x();
int length = postLocation - preLocation;
- tabList[to].dragOffset -= length;
- tabList[to].startAnimation(this, ANIMATION_DURATION);
+ tabList.at(to)->dragOffset -= length;
+ tabList.at(to)->startAnimation(this, ANIMATION_DURATION);
}
void QTabBarPrivate::moveTab(int index, int offset)
{
if (!validIndex(index))
return;
- tabList[index].dragOffset = offset;
+ tabList.at(index)->dragOffset = offset;
layoutTab(index); // Make buttons follow tab
q_func()->update();
}
@@ -2088,7 +2123,7 @@ void QTabBar::mousePressEvent(QMouseEvent *event)
{
Q_D(QTabBar);
- const QPoint pos = event->pos();
+ const QPoint pos = event->position().toPoint();
const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
|| (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
if (!isEventInCornerButtons) {
@@ -2104,18 +2139,18 @@ void QTabBar::mousePressEvent(QMouseEvent *event)
if (d->pressedIndex != -1 && d->movable)
d->moveTabFinished(d->pressedIndex);
- d->pressedIndex = d->indexAtPos(event->pos());
+ d->pressedIndex = d->indexAtPos(event->position().toPoint());
if (d->validIndex(d->pressedIndex)) {
QStyleOptionTabBarBase optTabBase;
- optTabBase.init(this);
+ optTabBase.initFrom(this);
optTabBase.documentMode = d->documentMode;
if (event->type() == style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this))
setCurrentIndex(d->pressedIndex);
else
repaint(tabRect(d->pressedIndex));
if (d->movable) {
- d->dragStartPosition = event->pos();
+ d->dragStartPosition = event->position().toPoint();
}
}
}
@@ -2133,7 +2168,7 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event)
// Start drag
if (!d->dragInProgress && d->pressedIndex != -1) {
- if ((event->pos() - d->dragStartPosition).manhattanLength() > QApplication::startDragDistance()) {
+ if ((event->position().toPoint() - d->dragStartPosition).manhattanLength() > QApplication::startDragDistance()) {
d->dragInProgress = true;
d->setupMovableTab();
}
@@ -2145,11 +2180,11 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event)
bool vertical = verticalTabs(d->shape);
int dragDistance;
if (vertical) {
- dragDistance = (event->pos().y() - d->dragStartPosition.y());
+ dragDistance = (event->position().toPoint().y() - d->dragStartPosition.y());
} else {
- dragDistance = (event->pos().x() - d->dragStartPosition.x());
+ dragDistance = (event->position().toPoint().x() - d->dragStartPosition.x());
}
- d->tabList[d->pressedIndex].dragOffset = dragDistance;
+ d->tabList.at(d->pressedIndex)->dragOffset = dragDistance;
QRect startingRect = tabRect(d->pressedIndex);
if (vertical)
@@ -2181,7 +2216,8 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event)
}
}
// Buttons needs to follow the dragged tab
- d->layoutTab(d->pressedIndex);
+ if (d->pressedIndex != -1)
+ d->layoutTab(d->pressedIndex);
update();
}
@@ -2206,14 +2242,14 @@ void QTabBarPrivate::setupMovableTab()
else
grabRect.adjust(-taboverlap, 0, taboverlap, 0);
- QPixmap grabImage(grabRect.size() * q->devicePixelRatioF());
- grabImage.setDevicePixelRatio(q->devicePixelRatioF());
+ QPixmap grabImage(grabRect.size() * q->devicePixelRatio());
+ grabImage.setDevicePixelRatio(q->devicePixelRatio());
grabImage.fill(Qt::transparent);
QStylePainter p(&grabImage, q);
- QStyleOptionTabV4 tab;
+ QStyleOptionTab tab;
q->initStyleOption(&tab, pressedIndex);
- tab.position = QStyleOptionTab::OnlyOneTab;
+ tab.position = QStyleOptionTab::Moving;
if (verticalTabs(shape))
tab.rect.moveTopLeft(QPoint(0, taboverlap));
else
@@ -2226,10 +2262,11 @@ void QTabBarPrivate::setupMovableTab()
movingTab->raise();
// Re-arrange widget order to avoid overlaps
- if (tabList[pressedIndex].leftWidget)
- tabList[pressedIndex].leftWidget->raise();
- if (tabList[pressedIndex].rightWidget)
- tabList[pressedIndex].rightWidget->raise();
+ const auto &pressedTab = *tabList.at(pressedIndex);
+ if (pressedTab.leftWidget)
+ pressedTab.leftWidget->raise();
+ if (pressedTab.rightWidget)
+ pressedTab.rightWidget->raise();
if (leftB)
leftB->raise();
if (rightB)
@@ -2243,17 +2280,18 @@ void QTabBarPrivate::moveTabFinished(int index)
bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index);
bool allAnimationsFinished = true;
#if QT_CONFIG(animation)
- for(int i = 0; allAnimationsFinished && i < tabList.count(); ++i) {
- const Tab &t = tabList.at(i);
- if (t.animation && t.animation->state() == QAbstractAnimation::Running)
+ for (const auto tab : std::as_const(tabList)) {
+ if (tab->animation && tab->animation->state() == QAbstractAnimation::Running) {
allAnimationsFinished = false;
+ break;
+ }
}
#endif // animation
if (allAnimationsFinished && cleanup) {
- if(movingTab)
+ if (movingTab)
movingTab->setVisible(false); // We might not get a mouse release
- for (int i = 0; i < tabList.count(); ++i) {
- tabList[i].dragOffset = 0;
+ for (auto tab : std::as_const(tabList)) {
+ tab->dragOffset = 0;
}
if (pressedIndex != -1 && movable) {
pressedIndex = -1;
@@ -2264,7 +2302,7 @@ void QTabBarPrivate::moveTabFinished(int index)
} else {
if (!validIndex(index))
return;
- tabList[index].dragOffset = 0;
+ tabList.at(index)->dragOffset = 0;
}
q->update();
}
@@ -2280,19 +2318,21 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event)
}
if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) {
- int length = d->tabList[d->pressedIndex].dragOffset;
+ int length = d->tabList.at(d->pressedIndex)->dragOffset;
int width = verticalTabs(d->shape)
? tabRect(d->pressedIndex).height()
: tabRect(d->pressedIndex).width();
int duration = qMin(ANIMATION_DURATION,
(qAbs(length) * ANIMATION_DURATION) / width);
- d->tabList[d->pressedIndex].startAnimation(d, duration);
+ d->tabList.at(d->pressedIndex)->startAnimation(d, duration);
d->dragInProgress = false;
d->movingTab->setVisible(false);
d->dragStartPosition = QPoint();
}
- int i = d->indexAtPos(event->pos()) == d->pressedIndex ? d->pressedIndex : -1;
+ // mouse release event might happen outside the tab, so keep the pressed index
+ int oldPressedIndex = d->pressedIndex;
+ int i = d->indexAtPos(event->position().toPoint()) == d->pressedIndex ? d->pressedIndex : -1;
d->pressedIndex = -1;
QStyleOptionTabBarBase optTabBase;
optTabBase.initFrom(this);
@@ -2301,8 +2341,22 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event)
(style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this) == QEvent::MouseButtonRelease);
if (selectOnRelease)
setCurrentIndex(i);
- if (!selectOnRelease || !d->validIndex(i) || d->currentIndex == i)
- repaint(tabRect(i));
+ if (d->validIndex(oldPressedIndex))
+ update(tabRect(oldPressedIndex));
+}
+
+/*!\reimp
+ */
+void QTabBar::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QTabBar);
+ const QPoint pos = event->position().toPoint();
+ const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
+ || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
+ if (!isEventInCornerButtons)
+ emit tabBarDoubleClicked(tabAt(pos));
+
+ mousePressEvent(event);
}
/*!\reimp
@@ -2323,16 +2377,61 @@ void QTabBar::keyPressEvent(QKeyEvent *event)
#if QT_CONFIG(wheelevent)
void QTabBar::wheelEvent(QWheelEvent *event)
{
-#ifndef Q_OS_MAC
Q_D(QTabBar);
- int delta = (qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()) ?
- event->angleDelta().x() : event->angleDelta().y());
- int offset = delta > 0 ? -1 : 1;
- d->setCurrentNextEnabledIndex(offset);
- QWidget::wheelEvent(event);
-#else
- Q_UNUSED(event)
-#endif
+ if (style()->styleHint(QStyle::SH_TabBar_AllowWheelScrolling)) {
+ const bool wheelVertical = qAbs(event->angleDelta().y()) > qAbs(event->angleDelta().x());
+ const bool tabsVertical = verticalTabs(d->shape);
+ if (event->device()->capabilities().testFlag(QInputDevice::Capability::PixelScroll)) {
+ // For wheels/touch pads with pixel precision, scroll the tab bar if
+ // it has the right orientation.
+ int delta = 0;
+ if (tabsVertical == wheelVertical)
+ delta = wheelVertical ? event->pixelDelta().y() : event->pixelDelta().x();
+ if (layoutDirection() == Qt::RightToLeft)
+ delta = -delta;
+ if (delta && d->validIndex(d->lastVisible)) {
+ const int oldScrollOffset = d->scrollOffset;
+ const QRect lastTabRect = d->tabList.at(d->lastVisible)->rect;
+ const QRect scrollRect = d->normalizedScrollRect(d->lastVisible);
+ int scrollRectExtent = scrollRect.right();
+ if (!d->leftB->isVisible())
+ scrollRectExtent += tabsVertical ? d->leftB->height() : d->leftB->width();
+ if (!d->rightB->isVisible())
+ scrollRectExtent += tabsVertical ? d->rightB->height() : d->rightB->width();
+
+ const int maxScrollOffset = qMax((tabsVertical ?
+ lastTabRect.bottom() :
+ lastTabRect.right()) - scrollRectExtent, 0);
+ d->scrollOffset = qBound(0, d->scrollOffset - delta, maxScrollOffset);
+ d->leftB->setEnabled(d->scrollOffset > -scrollRect.left());
+ d->rightB->setEnabled(maxScrollOffset > d->scrollOffset);
+ if (oldScrollOffset != d->scrollOffset) {
+ event->accept();
+ update();
+ return;
+ }
+ }
+ } else {
+ d->accumulatedAngleDelta += event->angleDelta();
+ const int xSteps = d->accumulatedAngleDelta.x() / QWheelEvent::DefaultDeltasPerStep;
+ const int ySteps = d->accumulatedAngleDelta.y() / QWheelEvent::DefaultDeltasPerStep;
+ int offset = 0;
+ if (xSteps > 0 || ySteps > 0) {
+ offset = -1;
+ d->accumulatedAngleDelta = QPoint();
+ } else if (xSteps < 0 || ySteps < 0) {
+ offset = 1;
+ d->accumulatedAngleDelta = QPoint();
+ }
+ const int oldCurrentIndex = d->currentIndex;
+ d->setCurrentNextEnabledIndex(offset);
+ if (oldCurrentIndex != d->currentIndex) {
+ event->accept();
+ return;
+ }
+ }
+ QWidget::wheelEvent(event);
+ }
}
#endif // QT_CONFIG(wheelevent)
@@ -2340,7 +2439,7 @@ void QTabBarPrivate::setCurrentNextEnabledIndex(int offset)
{
Q_Q(QTabBar);
for (int index = currentIndex + offset; validIndex(index); index += offset) {
- if (tabList.at(index).enabled) {
+ if (tabList.at(index)->enabled && tabList.at(index)->visible) {
q->setCurrentIndex(index);
break;
}
@@ -2393,7 +2492,7 @@ void QTabBar::timerEvent(QTimerEvent *event)
This property controls how items are elided when there is not
enough space to show them for a given tab bar size.
- By default the value is style dependent.
+ By default the value is style-dependent.
\sa QTabWidget::elideMode, usesScrollButtons, QStyle::SH_TabBar_ElideMode
*/
@@ -2422,7 +2521,7 @@ void QTabBar::setElideMode(Qt::TextElideMode mode)
When there are too many tabs in a tab bar for its size, the tab bar can either choose
to expand its size or to add buttons that allow you to scroll through the tabs.
- By default the value is style dependant.
+ By default the value is style-dependent.
\sa elideMode, QTabWidget::usesScrollButtons, QStyle::SH_TabBar_PreferNoArrows
*/
@@ -2469,24 +2568,25 @@ void QTabBar::setTabsClosable(bool closable)
d->closeButtonOnTabs = closable;
ButtonPosition closeSide = (ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, this);
if (!closable) {
- for (int i = 0; i < d->tabList.count(); ++i) {
- if (closeSide == LeftSide && d->tabList[i].leftWidget) {
- d->tabList[i].leftWidget->deleteLater();
- d->tabList[i].leftWidget = nullptr;
+ for (auto tab : std::as_const(d->tabList)) {
+ if (closeSide == LeftSide && tab->leftWidget) {
+ tab->leftWidget->deleteLater();
+ tab->leftWidget = nullptr;
}
- if (closeSide == RightSide && d->tabList[i].rightWidget) {
- d->tabList[i].rightWidget->deleteLater();
- d->tabList[i].rightWidget = nullptr;
+ if (closeSide == RightSide && tab->rightWidget) {
+ tab->rightWidget->deleteLater();
+ tab->rightWidget = nullptr;
}
}
} else {
bool newButtons = false;
- for (int i = 0; i < d->tabList.count(); ++i) {
+ for (int i = 0; i < d->tabList.size(); ++i) {
if (tabButton(i, closeSide))
continue;
newButtons = true;
QAbstractButton *closeButton = new CloseButton(this);
- connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
+ QObjectPrivate::connect(closeButton, &CloseButton::clicked,
+ d, &QTabBarPrivate::closeTab);
setTabButton(i, closeSide, closeButton);
}
if (newButtons)
@@ -2676,10 +2776,11 @@ void QTabBar::setChangeCurrentOnDrag(bool change)
/*!
Sets \a widget on the tab \a index. The widget is placed
- on the left or right hand side depending upon the \a position.
+ on the left or right hand side depending on the \a position.
\since 4.5
- Any previously set widget in \a position is hidden.
+ Any previously set widget in \a position is hidden. Setting \a widget
+ to \nullptr will hide the current widget at \a position.
The tab bar will take ownership of the widget and so all widgets set here
will be deleted by the tab bar when it is destroyed unless you separately
@@ -2690,7 +2791,7 @@ void QTabBar::setChangeCurrentOnDrag(bool change)
void QTabBar::setTabButton(int index, ButtonPosition position, QWidget *widget)
{
Q_D(QTabBar);
- if (index < 0 || index >= d->tabList.count())
+ if (index < 0 || index >= d->tabList.size())
return;
if (widget) {
widget->setParent(this);
@@ -2698,14 +2799,15 @@ void QTabBar::setTabButton(int index, ButtonPosition position, QWidget *widget)
widget->lower();
widget->show();
}
+ auto &tab = *d->tabList.at(index);
if (position == LeftSide) {
- if (d->tabList[index].leftWidget)
- d->tabList[index].leftWidget->hide();
- d->tabList[index].leftWidget = widget;
+ if (tab.leftWidget)
+ tab.leftWidget->hide();
+ tab.leftWidget = widget;
} else {
- if (d->tabList[index].rightWidget)
- d->tabList[index].rightWidget->hide();
- d->tabList[index].rightWidget = widget;
+ if (tab.rightWidget)
+ tab.rightWidget->hide();
+ tab.rightWidget = widget;
}
d->layoutTabs();
d->refresh();
@@ -2719,15 +2821,14 @@ void QTabBar::setTabButton(int index, ButtonPosition position, QWidget *widget)
QWidget *QTabBar::tabButton(int index, ButtonPosition position) const
{
Q_D(const QTabBar);
- if (index < 0 || index >= d->tabList.count())
- return nullptr;
- if (position == LeftSide)
- return d->tabList.at(index).leftWidget;
- else
- return d->tabList.at(index).rightWidget;
+ if (const auto tab = d->at(index)) {
+ return position == LeftSide ? tab->leftWidget
+ : tab->rightWidget;
+ }
+ return nullptr;
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
/*!
Sets the accessibleName of the tab at position \a index to \a name.
*/
@@ -2753,7 +2854,7 @@ QString QTabBar::accessibleTabName(int index) const
return tab->accessibleName;
return QString();
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
CloseButton::CloseButton(QWidget *parent)
: QAbstractButton(parent)
@@ -2762,7 +2863,7 @@ CloseButton::CloseButton(QWidget *parent)
#ifndef QT_NO_CURSOR
setCursor(Qt::ArrowCursor);
#endif
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
setToolTip(tr("Close Tab"));
#endif
resize(sizeHint());
@@ -2776,7 +2877,7 @@ QSize CloseButton::sizeHint() const
return QSize(width, height);
}
-void CloseButton::enterEvent(QEvent *event)
+void CloseButton::enterEvent(QEnterEvent *event)
{
if (isEnabled())
update();
@@ -2794,7 +2895,7 @@ void CloseButton::paintEvent(QPaintEvent *)
{
QPainter p(this);
QStyleOption opt;
- opt.init(this);
+ opt.initFrom(this);
opt.state |= QStyle::State_AutoRaise;
if (isEnabled() && underMouse() && !isChecked() && !isDown())
opt.state |= QStyle::State_Raised;
@@ -2816,12 +2917,12 @@ void CloseButton::paintEvent(QPaintEvent *)
#if QT_CONFIG(animation)
void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(const QVariant &current)
{
- priv->moveTab(priv->tabList.indexOf(*tab), current.toInt());
+ priv->moveTab(priv->tabList.indexOf(tab), current.toInt());
}
void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State)
{
- if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab));
+ if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(tab));
}
#endif
diff --git a/src/widgets/widgets/qtabbar.h b/src/widgets/widgets/qtabbar.h
index c49c12f38c..2759d5a318 100644
--- a/src/widgets/widgets/qtabbar.h
+++ b/src/widgets/widgets/qtabbar.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTABBAR_H
#define QTABBAR_H
@@ -63,7 +27,8 @@ class Q_WIDGETS_EXPORT QTabBar: public QWidget
Q_PROPERTY(Qt::TextElideMode elideMode READ elideMode WRITE setElideMode)
Q_PROPERTY(bool usesScrollButtons READ usesScrollButtons WRITE setUsesScrollButtons)
Q_PROPERTY(bool tabsClosable READ tabsClosable WRITE setTabsClosable)
- Q_PROPERTY(SelectionBehavior selectionBehaviorOnRemove READ selectionBehaviorOnRemove WRITE setSelectionBehaviorOnRemove)
+ Q_PROPERTY(SelectionBehavior selectionBehaviorOnRemove READ selectionBehaviorOnRemove
+ WRITE setSelectionBehaviorOnRemove)
Q_PROPERTY(bool expanding READ expanding WRITE setExpanding)
Q_PROPERTY(bool movable READ isMovable WRITE setMovable)
Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode)
@@ -103,10 +68,10 @@ public:
void moveTab(int from, int to);
bool isTabEnabled(int index) const;
- void setTabEnabled(int index, bool);
+ void setTabEnabled(int index, bool enabled);
bool isTabVisible(int index) const;
- void setTabVisible(int index, bool);
+ void setTabVisible(int index, bool visible);
QString tabText(int index) const;
void setTabText(int index, const QString &text);
@@ -118,9 +83,9 @@ public:
void setTabIcon(int index, const QIcon &icon);
Qt::TextElideMode elideMode() const;
- void setElideMode(Qt::TextElideMode);
+ void setElideMode(Qt::TextElideMode mode);
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
void setTabToolTip(int index, const QString &tip);
QString tabToolTip(int index) const;
#endif
@@ -175,7 +140,7 @@ public:
bool changeCurrentOnDrag() const;
void setChangeCurrentOnDrag(bool change);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QString accessibleTabName(int index) const;
void setAccessibleTabName(int index, const QString &name);
#endif
@@ -202,25 +167,24 @@ protected:
void showEvent(QShowEvent *) override;
void hideEvent(QHideEvent *) override;
void paintEvent(QPaintEvent *) override;
- void mousePressEvent (QMouseEvent *) override;
- void mouseMoveEvent (QMouseEvent *) override;
- void mouseReleaseEvent (QMouseEvent *) override;
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseDoubleClickEvent(QMouseEvent *) override;
#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
#endif
void keyPressEvent(QKeyEvent *) override;
void changeEvent(QEvent *) override;
void timerEvent(QTimerEvent *event) override;
- void initStyleOption(QStyleOptionTab *option, int tabIndex) const;
+ virtual void initStyleOption(QStyleOptionTab *option, int tabIndex) const;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
friend class QAccessibleTabBar;
#endif
private:
Q_DISABLE_COPY(QTabBar)
Q_DECLARE_PRIVATE(QTabBar)
- Q_PRIVATE_SLOT(d_func(), void _q_scrollTabs())
- Q_PRIVATE_SLOT(d_func(), void _q_closeTab())
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index ac4cbd32a8..d76f439bd7 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTABBAR_P_H
#define QTABBAR_P_H
@@ -65,6 +29,7 @@
#define ANIMATION_DURATION 250
#include <qstyleoption.h>
+#include <utility>
QT_REQUIRE_CONFIG(tabbar);
@@ -88,41 +53,75 @@ class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate
Q_DECLARE_PUBLIC(QTabBar)
public:
QTabBarPrivate()
- :currentIndex(-1), pressedIndex(-1), firstVisible(0), lastVisible(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
- drawBase(true), scrollOffset(0), hoverIndex(-1), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
- selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
- dragInProgress(false), documentMode(false), autoHide(false), changeCurrentOnDrag(false),
- switchTabCurrentIndex(-1), switchTabTimerId(0), movingTab(nullptr)
- {}
-
- int currentIndex;
- int pressedIndex;
- int firstVisible;
- int lastVisible;
- QTabBar::Shape shape;
- bool layoutDirty;
- bool drawBase;
- int scrollOffset;
+ : layoutDirty(false), drawBase(true), elideModeSetByUser(false), useScrollButtons(false),
+ useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
+ paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false),
+ autoHide(false), changeCurrentOnDrag(false)
+ {}
+ ~QTabBarPrivate()
+ {
+ qDeleteAll(tabList);
+ }
+
+ QRect hoverRect;
+ QPoint dragStartPosition;
+ QPoint mousePosition = {-1, -1};
+#if QT_CONFIG(wheelevent)
+ QPoint accumulatedAngleDelta;
+#endif
+ QSize iconSize;
+ QToolButton* rightB = nullptr; // right or bottom
+ QToolButton* leftB = nullptr; // left or top
+ QMovableTabWidget *movingTab = nullptr;
+ int hoverIndex = -1;
+ int switchTabCurrentIndex = -1;
+ int switchTabTimerId = 0;
+ Qt::TextElideMode elideMode = Qt::ElideNone;
+ QTabBar::SelectionBehavior selectionBehaviorOnRemove = QTabBar::SelectRightTab;
+ QTabBar::Shape shape = QTabBar::RoundedNorth;
+ Qt::MouseButtons mouseButtons = Qt::NoButton;
+
+ int currentIndex = -1;
+ int pressedIndex = -1;
+ int firstVisible = 0;
+ int lastVisible = -1;
+ int scrollOffset = 0;
+
+ bool layoutDirty : 1;
+ bool drawBase : 1;
+ bool elideModeSetByUser : 1;
+ bool useScrollButtons : 1;
+ bool useScrollButtonsSetByUser : 1;
+ bool expanding : 1;
+ bool closeButtonOnTabs : 1;
+ bool paintWithOffsets : 1;
+ bool movable : 1;
+ bool dragInProgress : 1;
+ bool documentMode : 1;
+ bool autoHide : 1;
+ bool changeCurrentOnDrag : 1;
struct Tab {
inline Tab(const QIcon &ico, const QString &txt)
- : enabled(true) , visible(true), shortcutId(0), text(txt), icon(ico),
- leftWidget(nullptr), rightWidget(nullptr), lastTab(-1), dragOffset(0)
-#if QT_CONFIG(animation)
- , animation(nullptr)
-#endif // animation
- {}
- bool operator==(const Tab &other) const { return &other == this; }
- bool enabled;
- bool visible;
- int shortcutId;
+ : text(txt), icon(ico), enabled(true), visible(true)
+ {
+ }
+ /*
+ Tabs are managed by instance; they are not the same even
+ if all properties are the same.
+ */
+ Q_DISABLE_COPY_MOVE(Tab);
+
QString text;
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
QString toolTip;
#endif
#if QT_CONFIG(whatsthis)
QString whatsThis;
#endif
+#if QT_CONFIG(accessibility)
+ QString accessibleName;
+#endif
QIcon icon;
QRect rect;
QRect minRect;
@@ -130,16 +129,15 @@ public:
QColor textColor;
QVariant data;
- QWidget *leftWidget;
- QWidget *rightWidget;
- int lastTab;
- int dragOffset;
-#ifndef QT_NO_ACCESSIBILITY
- QString accessibleName;
-#endif
+ QWidget *leftWidget = nullptr;
+ QWidget *rightWidget = nullptr;
+ int shortcutId = 0;
+ int lastTab = -1;
+ int dragOffset = 0;
+ uint enabled : 1;
+ uint visible : 1;
#if QT_CONFIG(animation)
- ~Tab() { delete animation; }
struct TabBarAnimation : public QVariantAnimation {
TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv)
{ setEasingCurve(QEasingCurve::InOutQuad); }
@@ -151,15 +149,16 @@ public:
//these are needed for the callbacks
Tab *tab;
QTabBarPrivate *priv;
- } *animation;
+ };
+ std::unique_ptr<TabBarAnimation> animation;
void startAnimation(QTabBarPrivate *priv, int duration) {
if (!priv->isAnimated()) {
- priv->moveTabFinished(priv->tabList.indexOf(*this));
+ priv->moveTabFinished(priv->tabList.indexOf(this));
return;
}
if (!animation)
- animation = new TabBarAnimation(this, priv);
+ animation = std::make_unique<TabBarAnimation>(this, priv);
animation->setStartValue(dragOffset);
animation->setEndValue(0);
animation->setDuration(duration);
@@ -167,10 +166,10 @@ public:
}
#else
void startAnimation(QTabBarPrivate *priv, int duration)
- { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(*this)); }
+ { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(this)); }
#endif // animation
};
- QList<Tab> tabList;
+ QList<Tab*> tabList;
mutable QHash<QString, QSize> textSizes;
void calculateFirstLastVisible(int index, bool visible, bool remove);
@@ -179,24 +178,19 @@ public:
void slide(int from, int to);
void init();
- Tab *at(int index);
- const Tab *at(int index) const;
+ inline Tab *at(int index) { return tabList.value(index, nullptr); }
+ inline const Tab *at(int index) const { return tabList.value(index, nullptr); }
int indexAtPos(const QPoint &p) const;
inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, q) > 0; }
- inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); }
+ inline bool validIndex(int index) const { return index >= 0 && index < tabList.size(); }
void setCurrentNextEnabledIndex(int offset);
- QToolButton* rightB; // right or bottom
- QToolButton* leftB; // left or top
-
- void _q_scrollTabs();
- void _q_closeTab();
+ void scrollTabs();
+ void closeTab();
void moveTab(int index, int offset);
void moveTabFinished(int index);
- QRect hoverRect;
- int hoverIndex;
void refresh();
void layoutTabs();
@@ -212,28 +206,7 @@ public:
void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const;
void makeVisible(int index);
- QSize iconSize;
- Qt::TextElideMode elideMode;
- bool elideModeSetByUser;
- bool useScrollButtons;
- bool useScrollButtonsSetByUser;
- bool expanding;
- bool closeButtonOnTabs;
- QTabBar::SelectionBehavior selectionBehaviorOnRemove;
-
- QPoint dragStartPosition;
- bool paintWithOffsets;
- bool movable;
- bool dragInProgress;
- bool documentMode;
- bool autoHide;
- bool changeCurrentOnDrag;
-
- int switchTabCurrentIndex;
- int switchTabTimerId;
-
- QMovableTabWidget *movingTab;
// shared by tabwidget and qtabbar
static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
{
@@ -241,7 +214,7 @@ public:
tabOverlap.shape = tabbar->shape();
int overlap = tabbar->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap, tabbar);
QWidget *theParent = tabbar->parentWidget();
- optTabBase->init(tabbar);
+ optTabBase->initFrom(tabbar);
optTabBase->shape = tabbar->shape();
optTabBase->documentMode = tabbar->documentMode();
if (theParent && overlap > 0) {
@@ -272,6 +245,14 @@ public:
};
+constexpr inline bool verticalTabs(QTabBar::Shape shape) noexcept
+{
+ return shape == QTabBar::RoundedWest
+ || shape == QTabBar::RoundedEast
+ || shape == QTabBar::TriangularWest
+ || shape == QTabBar::TriangularEast;
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index f0bfe67e3a..5e7c266ef6 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtabwidget.h"
@@ -44,8 +8,6 @@
#include "private/qtabbar_p.h"
#include "qapplication.h"
#include "qbitmap.h"
-#include "qdesktopwidget.h"
-#include <private/qdesktopwidget_p.h>
#include "qevent.h"
#include "qlayout.h"
#include "qstackedwidget.h"
@@ -57,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QTabWidget
\brief The QTabWidget class provides a stack of tabbed widgets.
@@ -192,9 +156,9 @@ public:
QTabWidgetPrivate();
~QTabWidgetPrivate();
void updateTabBarPosition();
- void _q_showTab(int);
- void _q_removeTab(int);
- void _q_tabMoved(int from, int to);
+ void showTab(int);
+ void removeTab(int);
+ void tabMoved(int from, int to);
void init();
bool isAutoHidden() const
{
@@ -228,14 +192,14 @@ void QTabWidgetPrivate::init()
Q_Q(QTabWidget);
stack = new QStackedWidget(q);
- stack->setObjectName(QLatin1String("qt_tabwidget_stackedwidget"));
+ stack->setObjectName("qt_tabwidget_stackedwidget"_L1);
stack->setLineWidth(0);
// hack so that QMacStyle::layoutSpacing() can detect tab widget pages
stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::TabWidget));
- QObject::connect(stack, SIGNAL(widgetRemoved(int)), q, SLOT(_q_removeTab(int)));
+ QObjectPrivate::connect(stack, &QStackedWidget::widgetRemoved, this, &QTabWidgetPrivate::removeTab);
QTabBar *tabBar = new QTabBar(q);
- tabBar->setObjectName(QLatin1String("qt_tabwidget_tabbar"));
+ tabBar->setObjectName("qt_tabwidget_tabbar"_L1);
tabBar->setDrawBase(false);
q->setTabBar(tabBar);
@@ -471,7 +435,7 @@ int QTabWidget::insertTab(int index, QWidget *w, const QString &label)
int QTabWidget::insertTab(int index, QWidget *w, const QIcon& icon, const QString &label)
{
Q_D(QTabWidget);
- if(!w)
+ if (!w)
return -1;
index = d->stack->insertWidget(index, w);
d->tabs->insertTab(index, icon, label);
@@ -612,7 +576,7 @@ void QTabWidget::setTabVisible(int index, bool visible)
Only the horizontal element of the \a corner will be used.
- Passing 0 shows no widget in the corner.
+ Passing \nullptr shows no widget in the corner.
Any previously set corner widget is hidden.
@@ -721,7 +685,7 @@ void QTabWidget::setCurrentIndex(int index)
Returns the index position of the page occupied by the widget \a
w, or -1 if the widget cannot be found.
*/
-int QTabWidget::indexOf(QWidget* w) const
+int QTabWidget::indexOf(const QWidget *w) const
{
Q_D(const QTabWidget);
return d->stack->indexOf(w);
@@ -756,17 +720,17 @@ void QTabWidget::setTabBar(QTabBar* tb)
delete d->tabs;
d->tabs = tb;
setFocusProxy(d->tabs);
- connect(d->tabs, SIGNAL(currentChanged(int)),
- this, SLOT(_q_showTab(int)));
- connect(d->tabs, SIGNAL(tabMoved(int,int)),
- this, SLOT(_q_tabMoved(int,int)));
- connect(d->tabs, SIGNAL(tabBarClicked(int)),
- this, SIGNAL(tabBarClicked(int)));
- connect(d->tabs, SIGNAL(tabBarDoubleClicked(int)),
- this, SIGNAL(tabBarDoubleClicked(int)));
+ QObjectPrivate::connect(d->tabs, &QTabBar::currentChanged,
+ d, &QTabWidgetPrivate::showTab);
+ QObjectPrivate::connect(d->tabs, &QTabBar::tabMoved,
+ d, &QTabWidgetPrivate::tabMoved);
+ connect(d->tabs, &QTabBar::tabBarClicked,
+ this, &QTabWidget::tabBarClicked);
+ connect(d->tabs, &QTabBar::tabBarDoubleClicked,
+ this, &QTabWidget::tabBarDoubleClicked);
if (d->tabs->tabsClosable())
- connect(d->tabs, SIGNAL(tabCloseRequested(int)),
- this, SIGNAL(tabCloseRequested(int)));
+ connect(d->tabs, &QTabBar::tabCloseRequested,
+ this, &QTabWidget::tabCloseRequested);
tb->setExpanding(!documentMode());
setUpLayout();
}
@@ -788,7 +752,7 @@ QTabBar* QTabWidget::tabBar() const
sized.
*/
-void QTabWidgetPrivate::_q_showTab(int index)
+void QTabWidgetPrivate::showTab(int index)
{
Q_Q(QTabWidget);
if (index < stack->count() && index >= 0)
@@ -796,7 +760,7 @@ void QTabWidgetPrivate::_q_showTab(int index)
emit q->currentChanged(index);
}
-void QTabWidgetPrivate::_q_removeTab(int index)
+void QTabWidgetPrivate::removeTab(int index)
{
Q_Q(QTabWidget);
tabs->removeTab(index);
@@ -804,7 +768,7 @@ void QTabWidgetPrivate::_q_removeTab(int index)
q->tabRemoved(index);
}
-void QTabWidgetPrivate::_q_tabMoved(int from, int to)
+void QTabWidgetPrivate::tabMoved(int from, int to)
{
const QSignalBlocker blocker(stack);
QWidget *w = stack->widget(from);
@@ -880,7 +844,7 @@ QSize QTabWidget::sizeHint() const
if (d->leftCornerWidget)
lc = d->leftCornerWidget->sizeHint();
- if(d->rightCornerWidget)
+ if (d->rightCornerWidget)
rc = d->rightCornerWidget->sizeHint();
if (!d->dirty) {
QTabWidget *that = const_cast<QTabWidget*>(this);
@@ -899,13 +863,12 @@ QSize QTabWidget::sizeHint() const
if (usesScrollButtons())
t = t.boundedTo(QSize(200,200));
else
- t = t.boundedTo(QDesktopWidgetPrivate::size());
+ t = t.boundedTo(QGuiApplication::primaryScreen()->virtualGeometry().size());
}
QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
- return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
- .expandedTo(QApplication::globalStrut());
+ return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this);
}
@@ -919,9 +882,9 @@ QSize QTabWidget::minimumSizeHint() const
Q_D(const QTabWidget);
QSize lc(0, 0), rc(0, 0);
- if(d->leftCornerWidget)
+ if (d->leftCornerWidget)
lc = d->leftCornerWidget->minimumSizeHint();
- if(d->rightCornerWidget)
+ if (d->rightCornerWidget)
rc = d->rightCornerWidget->minimumSizeHint();
if (!d->dirty) {
QTabWidget *that = const_cast<QTabWidget*>(this);
@@ -938,8 +901,7 @@ QSize QTabWidget::minimumSizeHint() const
initStyleOption(&opt);
opt.palette = palette();
opt.state = QStyle::State_None;
- return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
- .expandedTo(QApplication::globalStrut());
+ return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this);
}
/*!
@@ -953,13 +915,12 @@ int QTabWidget::heightForWidth(int width) const
opt.state = QStyle::State_None;
QSize zero(0,0);
- const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this)
- .expandedTo(QApplication::globalStrut());
+ const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this);
QSize lc(0, 0), rc(0, 0);
if (d->leftCornerWidget)
lc = d->leftCornerWidget->sizeHint();
- if(d->rightCornerWidget)
+ if (d->rightCornerWidget)
rc = d->rightCornerWidget->sizeHint();
if (!d->dirty) {
QTabWidget *that = const_cast<QTabWidget*>(this);
@@ -971,7 +932,7 @@ int QTabWidget::heightForWidth(int width) const
if (usesScrollButtons())
t = t.boundedTo(QSize(200,200));
else
- t = t.boundedTo(QDesktopWidgetPrivate::size());
+ t = t.boundedTo(QGuiApplication::primaryScreen()->virtualSize());
}
const bool tabIsHorizontal = (d->pos == North || d->pos == South);
@@ -984,7 +945,7 @@ int QTabWidget::heightForWidth(int width) const
QSize s(stackWidth, stackHeight);
QSize contentSize = basicSize(tabIsHorizontal, lc, rc, s, t);
- return (contentSize + padding).expandedTo(QApplication::globalStrut()).height();
+ return (contentSize + padding).height();
}
@@ -1178,7 +1139,7 @@ void QTabWidget::keyPressEvent(QKeyEvent *e)
) {
page = 0;
}
- if (d->tabs->isTabEnabled(page)) {
+ if (d->tabs->isTabEnabled(page) && d->tabs->isTabVisible(page)) {
setCurrentIndex(page);
break;
}
@@ -1212,7 +1173,7 @@ int QTabWidget::count() const
return d->tabs->count();
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
/*!
Sets the tab tool tip for the page at position \a index to \a tip.
@@ -1235,7 +1196,7 @@ QString QTabWidget::tabToolTip(int index) const
Q_D(const QTabWidget);
return d->tabs->tabToolTip(index);
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(whatsthis)
/*!
@@ -1271,7 +1232,7 @@ QString QTabWidget::tabWhatsThis(int index) const
*/
void QTabWidget::tabInserted(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*!
@@ -1282,7 +1243,7 @@ void QTabWidget::tabInserted(int index)
*/
void QTabWidget::tabRemoved(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*!
@@ -1348,7 +1309,7 @@ void QTabWidget::setIconSize(const QSize &size)
This property controls how items are elided when there is not
enough space to show them for a given tab bar size.
- By default the value is style dependant.
+ By default the value is style dependent.
\sa QTabBar::elideMode, usesScrollButtons, QStyle::SH_TabBar_ElideMode
*/
@@ -1371,7 +1332,7 @@ void QTabWidget::setElideMode(Qt::TextElideMode mode)
When there are too many tabs in a tab bar for its size, the tab bar can either choose
to expand its size or to add buttons that allow you to scroll through the tabs.
- By default the value is style dependant.
+ By default the value is style dependent.
\sa elideMode, QTabBar::usesScrollButtons, QStyle::SH_TabBar_PreferNoArrows
*/
@@ -1446,6 +1407,20 @@ void QTabWidget::clear()
removeTab(0);
}
+QTabBar::Shape _q_tb_tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
+{
+ const bool rounded = (shape == QTabWidget::Rounded);
+ if (position == QTabWidget::North)
+ return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
+ if (position == QTabWidget::South)
+ return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
+ if (position == QTabWidget::East)
+ return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
+ if (position == QTabWidget::West)
+ return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
+ return QTabBar::RoundedNorth;
+}
+
QT_END_NAMESPACE
#include "moc_qtabwidget.cpp"
diff --git a/src/widgets/widgets/qtabwidget.h b/src/widgets/widgets/qtabwidget.h
index e6b3f93303..c813f8d921 100644
--- a/src/widgets/widgets/qtabwidget.h
+++ b/src/widgets/widgets/qtabwidget.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTABWIDGET_H
#define QTABWIDGET_H
@@ -80,18 +44,18 @@ public:
void removeTab(int index);
bool isTabEnabled(int index) const;
- void setTabEnabled(int index, bool);
+ void setTabEnabled(int index, bool enabled);
bool isTabVisible(int index) const;
- void setTabVisible(int index, bool);
+ void setTabVisible(int index, bool visible);
QString tabText(int index) const;
- void setTabText(int index, const QString &);
+ void setTabText(int index, const QString &text);
QIcon tabIcon(int index) const;
void setTabIcon(int index, const QIcon & icon);
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
void setTabToolTip(int index, const QString & tip);
QString tabToolTip(int index) const;
#endif
@@ -104,13 +68,13 @@ public:
int currentIndex() const;
QWidget *currentWidget() const;
QWidget *widget(int index) const;
- int indexOf(QWidget *widget) const;
+ int indexOf(const QWidget *widget) const;
int count() const;
enum TabPosition { North, South, West, East };
Q_ENUM(TabPosition)
TabPosition tabPosition() const;
- void setTabPosition(TabPosition);
+ void setTabPosition(TabPosition position);
bool tabsClosable() const;
void setTabsClosable(bool closeable);
@@ -132,7 +96,7 @@ public:
QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
Qt::TextElideMode elideMode() const;
- void setElideMode(Qt::TextElideMode);
+ void setElideMode(Qt::TextElideMode mode);
QSize iconSize() const;
void setIconSize(const QSize &size);
@@ -171,15 +135,12 @@ protected:
void setTabBar(QTabBar *);
void changeEvent(QEvent *) override;
bool event(QEvent *) override;
- void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
+ virtual void initStyleOption(QStyleOptionTabWidgetFrame *option) const;
private:
Q_DECLARE_PRIVATE(QTabWidget)
Q_DISABLE_COPY(QTabWidget)
- Q_PRIVATE_SLOT(d_func(), void _q_showTab(int))
- Q_PRIVATE_SLOT(d_func(), void _q_removeTab(int))
- Q_PRIVATE_SLOT(d_func(), void _q_tabMoved(int, int))
void setUpLayout(bool = false);
};
diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp
index d0ccd435b3..2c01ed2b26 100644
--- a/src/widgets/widgets/qtextbrowser.cpp
+++ b/src/widgets/widgets/qtextbrowser.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextbrowser.h"
#include "qtextedit_p.h"
@@ -44,13 +8,9 @@
#include <qapplication.h>
#include <private/qapplication_p.h>
#include <qevent.h>
-#include <qdesktopwidget.h>
#include <qdebug.h>
#include <qabstracttextdocumentlayout.h>
#include "private/qtextdocumentlayout_p.h"
-#if QT_CONFIG(textcodec)
-#include <qtextcodec.h>
-#endif
#include <qpainter.h>
#include <qdir.h>
#if QT_CONFIG(whatsthis)
@@ -58,9 +18,21 @@
#endif
#include <qtextobject.h>
#include <qdesktopservices.h>
+#include <qstringconverter.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+static inline bool shouldEnableInputMethod(QTextBrowser *texbrowser)
+{
+#if defined (Q_OS_ANDROID)
+ return !texbrowser->isReadOnly() || (texbrowser->textInteractionFlags() & Qt::TextSelectableByMouse);
+#else
+ return !texbrowser->isReadOnly();
+#endif
+}
+
Q_LOGGING_CATEGORY(lcBrowser, "qt.text.browser")
class QTextBrowserPrivate : public QTextEditPrivate
@@ -74,6 +46,11 @@ public:
, lastKeypadScrollValue(-1)
#endif
{}
+ ~QTextBrowserPrivate()
+ {
+ for (const QMetaObject::Connection &connection : connections)
+ QObject::disconnect(connection);
+ }
void init();
@@ -92,13 +69,13 @@ public:
HistoryEntry history(int i) const
{
if (i <= 0)
- if (-i < stack.count())
- return stack[stack.count()+i-1];
+ if (-i < stack.size())
+ return stack[stack.size()+i-1];
else
return HistoryEntry();
else
- if (i <= forwardStack.count())
- return forwardStack[forwardStack.count()-i];
+ if (i <= forwardStack.size())
+ return forwardStack[forwardStack.size()-i];
else
return HistoryEntry();
}
@@ -131,14 +108,14 @@ public:
QString findFile(const QUrl &name) const;
- inline void _q_documentModified()
+ inline void documentModified()
{
textOrSourceChanged = true;
forceLoadOnSourceChange = !currentURL.path().isEmpty();
}
- void _q_activateAnchor(const QString &href);
- void _q_highlightLink(const QString &href);
+ void activateAnchor(const QString &href);
+ void highlightLink(const QString &href);
void setSource(const QUrl &url, QTextDocument::ResourceType type);
@@ -152,20 +129,26 @@ public:
QTextCursor prevFocus;
int lastKeypadScrollValue;
#endif
+ void emitHighlighted(const QUrl &url)
+ {
+ Q_Q(QTextBrowser);
+ emit q->highlighted(url);
+ }
+ std::array<QMetaObject::Connection, 3> connections;
};
-Q_DECLARE_TYPEINFO(QTextBrowserPrivate::HistoryEntry, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QTextBrowserPrivate::HistoryEntry, Q_RELOCATABLE_TYPE);
QString QTextBrowserPrivate::findFile(const QUrl &name) const
{
QString fileName;
- if (name.scheme() == QLatin1String("qrc")) {
- fileName = QLatin1String(":/") + name.path();
+ if (name.scheme() == "qrc"_L1) {
+ fileName = ":/"_L1 + name.path();
} else if (name.scheme().isEmpty()) {
fileName = name.path();
} else {
#if defined(Q_OS_ANDROID)
- if (name.scheme() == QLatin1String("assets"))
- fileName = QLatin1String("assets:") + name.path();
+ if (name.scheme() == "assets"_L1)
+ fileName = "assets:"_L1 + name.path();
else
#endif
fileName = name.toLocalFile();
@@ -177,9 +160,9 @@ QString QTextBrowserPrivate::findFile(const QUrl &name) const
if (QFileInfo(fileName).isAbsolute())
return fileName;
- for (QString path : qAsConst(searchPaths)) {
- if (!path.endsWith(QLatin1Char('/')))
- path.append(QLatin1Char('/'));
+ for (QString path : std::as_const(searchPaths)) {
+ if (!path.endsWith(u'/'))
+ path.append(u'/');
path.append(fileName);
if (QFileInfo(path).isReadable())
return path;
@@ -196,7 +179,7 @@ QUrl QTextBrowserPrivate::resolveUrl(const QUrl &url) const
// For the second case QUrl can merge "#someanchor" with "foo.html"
// correctly to "foo.html#someanchor"
if (!(currentURL.isRelative()
- || (currentURL.scheme() == QLatin1String("file")
+ || (currentURL.scheme() == "file"_L1
&& !QFileInfo(currentURL.toLocalFile()).isAbsolute()))
|| (url.hasFragment() && url.path().isEmpty())) {
return currentURL.resolved(url);
@@ -213,7 +196,7 @@ QUrl QTextBrowserPrivate::resolveUrl(const QUrl &url) const
return url;
}
-void QTextBrowserPrivate::_q_activateAnchor(const QString &href)
+void QTextBrowserPrivate::activateAnchor(const QString &href)
{
if (href.isEmpty())
return;
@@ -234,11 +217,11 @@ void QTextBrowserPrivate::_q_activateAnchor(const QString &href)
#ifndef QT_NO_DESKTOPSERVICES
bool isFileScheme =
- url.scheme() == QLatin1String("file")
+ url.scheme() == "file"_L1
#if defined(Q_OS_ANDROID)
- || url.scheme() == QLatin1String("assets")
+ || url.scheme() == "assets"_L1
#endif
- || url.scheme() == QLatin1String("qrc");
+ || url.scheme() == "qrc"_L1;
if ((openExternalLinks && !isFileScheme && !url.isRelative())
|| (url.isRelative() && !currentURL.isRelative() && !isFileScheme)) {
QDesktopServices::openUrl(url);
@@ -254,26 +237,22 @@ void QTextBrowserPrivate::_q_activateAnchor(const QString &href)
q->setSource(url);
}
-void QTextBrowserPrivate::_q_highlightLink(const QString &anchor)
+void QTextBrowserPrivate::highlightLink(const QString &anchor)
{
- Q_Q(QTextBrowser);
if (anchor.isEmpty()) {
#ifndef QT_NO_CURSOR
if (viewport->cursor().shape() != Qt::PointingHandCursor)
oldCursor = viewport->cursor();
viewport->setCursor(oldCursor);
#endif
- emit q->highlighted(QUrl());
- emit q->highlighted(QString());
+ emitHighlighted(QUrl());
} else {
#ifndef QT_NO_CURSOR
viewport->setCursor(Qt::PointingHandCursor);
#endif
const QUrl url = resolveUrl(anchor);
- emit q->highlighted(url);
- // convenience to ease connecting to QStatusBar::showMessage(const QString &)
- emit q->highlighted(url.toString());
+ emitHighlighted(url);
}
}
@@ -297,9 +276,9 @@ void QTextBrowserPrivate::setSource(const QUrl &url, QTextDocument::ResourceType
QString fileName = url.fileName();
if (type == QTextDocument::UnknownResource) {
#if QT_CONFIG(textmarkdownreader)
- if (fileName.endsWith(QLatin1String(".md")) ||
- fileName.endsWith(QLatin1String(".mkd")) ||
- fileName.endsWith(QLatin1String(".markdown")))
+ if (fileName.endsWith(".md"_L1) ||
+ fileName.endsWith(".mkd"_L1) ||
+ fileName.endsWith(".markdown"_L1))
type = QTextDocument::MarkdownResource;
else
#endif
@@ -310,27 +289,26 @@ void QTextBrowserPrivate::setSource(const QUrl &url, QTextDocument::ResourceType
if (url.isValid()
&& (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) {
QVariant data = q->loadResource(type, resolveUrl(url));
- if (data.type() == QVariant::String) {
+ if (data.userType() == QMetaType::QString) {
txt = data.toString();
- } else if (data.type() == QVariant::ByteArray) {
+ } else if (data.userType() == QMetaType::QByteArray) {
+ QByteArray ba = data.toByteArray();
if (type == QTextDocument::HtmlResource) {
-#if QT_CONFIG(textcodec)
- QByteArray ba = data.toByteArray();
- QTextCodec *codec = Qt::codecForHtml(ba);
- txt = codec->toUnicode(ba);
-#else
- txt = data.toString();
-#endif
+ auto decoder = QStringDecoder::decoderForHtml(ba);
+ if (!decoder.isValid())
+ // fall back to utf8
+ decoder = QStringDecoder(QStringDecoder::Utf8);
+ txt = decoder(ba);
} else {
- txt = QString::fromUtf8(data.toByteArray());
+ txt = QString::fromUtf8(ba);
}
}
if (Q_UNLIKELY(txt.isEmpty()))
qWarning("QTextBrowser: No document for %s", url.toString().toLatin1().constData());
if (q->isVisible()) {
- const QStringRef firstTag = txt.leftRef(txt.indexOf(QLatin1Char('>')) + 1);
- if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
+ const QStringView firstTag = QStringView{txt}.left(txt.indexOf(u'>') + 1);
+ if (firstTag.startsWith("<qt"_L1) && firstTag.contains("type"_L1) && firstTag.contains("detail"_L1)) {
#ifndef QT_NO_CURSOR
QGuiApplication::restoreOverrideCursor();
#endif
@@ -383,8 +361,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url, QTextDocument::ResourceType
}
#ifdef QT_KEYPAD_NAVIGATION
lastKeypadScrollValue = vbar->value();
- emit q->highlighted(QUrl());
- emit q->highlighted(QString());
+ emitHighlighted(QUrl());
#endif
#ifndef QT_NO_CURSOR
@@ -506,7 +483,7 @@ void QTextBrowserPrivate::keypadMove(bool next)
// up e.g. 110%
// Obviously if a link is entirely visible, we still
// focus it.
- if(bothViewRects.contains(desiredRect)
+ if (bothViewRects.contains(desiredRect)
|| bothViewRects.adjusted(0, visibleLinkAmount, 0, -visibleLinkAmount).intersects(desiredRect)) {
focusIt = true;
@@ -535,7 +512,7 @@ void QTextBrowserPrivate::keypadMove(bool next)
if (!focusIt && prevFocus.hasSelection()) {
QRectF desiredRect = control->selectionRect(prevFocus);
// XXX this may be better off also using the visibleLinkAmount value
- if(newViewRect.intersects(desiredRect)) {
+ if (newViewRect.intersects(desiredRect)) {
focusedPos = scrollYOffset;
focusIt = true;
anchorToFocus = prevFocus;
@@ -559,8 +536,7 @@ void QTextBrowserPrivate::keypadMove(bool next)
// Ensure that the new selection is highlighted.
const QString href = control->anchorAtCursor();
QUrl url = resolveUrl(href);
- emit q->highlighted(url);
- emit q->highlighted(url.toString());
+ emitHighlighted(url);
} else {
// Scroll
vbar->setValue(scrollYOffset);
@@ -575,8 +551,7 @@ void QTextBrowserPrivate::keypadMove(bool next)
hbar->setValue(savedXOffset);
vbar->setValue(scrollYOffset);
- emit q->highlighted(QUrl());
- emit q->highlighted(QString());
+ emitHighlighted(QUrl());
}
}
#endif
@@ -619,8 +594,7 @@ void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry &entry)
Q_Q(QTextBrowser);
const QString href = prevFocus.charFormat().anchorHref();
QUrl url = resolveUrl(href);
- emit q->highlighted(url);
- emit q->highlighted(url.toString());
+ emitHighlighted(url);
#endif
}
@@ -699,14 +673,17 @@ void QTextBrowserPrivate::init()
#ifndef QT_NO_CURSOR
viewport->setCursor(oldCursor);
#endif
- q->setAttribute(Qt::WA_InputMethodEnabled, !q->isReadOnly());
+ q->setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(q));
q->setUndoRedoEnabled(false);
viewport->setMouseTracking(true);
- QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified()));
- QObject::connect(control, SIGNAL(linkActivated(QString)),
- q, SLOT(_q_activateAnchor(QString)));
- QObject::connect(control, SIGNAL(linkHovered(QString)),
- q, SLOT(_q_highlightLink(QString)));
+ connections = {
+ QObjectPrivate::connect(q->document(), &QTextDocument::contentsChanged,
+ this, &QTextBrowserPrivate::documentModified),
+ QObjectPrivate::connect(control, &QWidgetTextControl::linkActivated,
+ this, &QTextBrowserPrivate::activateAnchor),
+ QObjectPrivate::connect(control, &QWidgetTextControl::linkHovered,
+ this, &QTextBrowserPrivate::highlightLink),
+ };
}
/*!
@@ -813,13 +790,6 @@ void QTextBrowser::reload()
setSource(s, d->currentType);
}
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-void QTextBrowser::setSource(const QUrl &url)
-{
- setSource(url, QTextDocument::UnknownResource);
-}
-#endif
-
/*!
Attempts to load the document at the given \a url with the specified \a type.
@@ -835,14 +805,12 @@ void QTextBrowser::setSource(const QUrl &url, QTextDocument::ResourceType type)
doSetSource(url, type);
}
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
/*!
Attempts to load the document at the given \a url with the specified \a type.
setSource() calls doSetSource. In Qt 5, setSource(const QUrl &url) was virtual.
In Qt 6, doSetSource() is virtual instead, so that it can be overridden in subclasses.
*/
-#endif
void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type)
{
Q_D(QTextBrowser);
@@ -869,11 +837,11 @@ void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type
entry.vpos = 0;
d->stack.push(entry);
- emit backwardAvailable(d->stack.count() > 1);
+ emit backwardAvailable(d->stack.size() > 1);
if (!d->forwardStack.isEmpty() && d->forwardStack.top().url == url) {
d->forwardStack.pop();
- emit forwardAvailable(d->forwardStack.count() > 0);
+ emit forwardAvailable(d->forwardStack.size() > 0);
} else {
d->forwardStack.clear();
emit forwardAvailable(false);
@@ -914,7 +882,7 @@ void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type
being the new source.
Source changes happen both programmatically when calling
- setSource(), forward(), backword() or home() or when the user
+ setSource(), forward(), backward() or home() or when the user
clicks on links or presses the equivalent key sequences.
*/
@@ -925,15 +893,6 @@ void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type
anchor is passed in \a link.
*/
-/*! \fn void QTextBrowser::highlighted(const QString &link)
- \overload
-
- Convenience signal that allows connecting to a slot
- that takes just a QString, like for example QStatusBar's
- message().
-*/
-
-
/*!
\fn void QTextBrowser::anchorClicked(const QUrl &link)
@@ -956,14 +915,14 @@ void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type
void QTextBrowser::backward()
{
Q_D(QTextBrowser);
- if (d->stack.count() <= 1)
+ if (d->stack.size() <= 1)
return;
// Update the history entry
d->forwardStack.push(d->createHistoryEntry());
d->stack.pop(); // throw away the old version of the current entry
d->restoreHistoryEntry(d->stack.top()); // previous entry
- emit backwardAvailable(d->stack.count() > 1);
+ emit backwardAvailable(d->stack.size() > 1);
emit forwardAvailable(true);
emit historyChanged();
}
@@ -1127,8 +1086,7 @@ bool QTextBrowser::focusNextPrevChild(bool next)
if (d->prevFocus != d->control->textCursor() && d->control->textCursor().hasSelection()) {
const QString href = d->control->anchorAtCursor();
QUrl url = d->resolveUrl(href);
- emit highlighted(url);
- emit highlighted(url.toString());
+ emitHighlighted(url);
}
d->prevFocus = d->control->textCursor();
#endif
@@ -1136,8 +1094,7 @@ bool QTextBrowser::focusNextPrevChild(bool next)
} else {
#ifdef QT_KEYPAD_NAVIGATION
// We assume we have no highlight now.
- emit highlighted(QUrl());
- emit highlighted(QString());
+ emitHighlighted(QUrl());
#endif
}
return QTextEdit::focusNextPrevChild(next);
@@ -1171,7 +1128,7 @@ void QTextBrowser::paintEvent(QPaintEvent *e)
depending on the resource type:
\table
- \header \li ResourceType \li QVariant::Type
+ \header \li ResourceType \li QMetaType::Type
\row \li QTextDocument::HtmlResource \li QString or QByteArray
\row \li QTextDocument::ImageResource \li QImage, QPixmap or QByteArray
\row \li QTextDocument::StyleSheetResource \li QString or QByteArray
@@ -1208,7 +1165,7 @@ QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name)
bool QTextBrowser::isBackwardAvailable() const
{
Q_D(const QTextBrowser);
- return d->stack.count() > 1;
+ return d->stack.size() > 1;
}
/*!
@@ -1295,7 +1252,7 @@ QString QTextBrowser::historyTitle(int i) const
int QTextBrowser::forwardHistoryCount() const
{
Q_D(const QTextBrowser);
- return d->forwardStack.count();
+ return d->forwardStack.size();
}
/*!
@@ -1306,7 +1263,7 @@ int QTextBrowser::forwardHistoryCount() const
int QTextBrowser::backwardHistoryCount() const
{
Q_D(const QTextBrowser);
- return d->stack.count()-1;
+ return d->stack.size()-1;
}
/*!
diff --git a/src/widgets/widgets/qtextbrowser.h b/src/widgets/widgets/qtextbrowser.h
index 33e5b3980c..f8e9c0c301 100644
--- a/src/widgets/widgets/qtextbrowser.h
+++ b/src/widgets/widgets/qtextbrowser.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTBROWSER_H
#define QTEXTBROWSER_H
@@ -90,12 +54,7 @@ public:
void setOpenLinks(bool open);
public Q_SLOTS:
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- virtual void setSource(const QUrl &name);
- void setSource(const QUrl &name, QTextDocument::ResourceType type);
-#else
void setSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource);
-#endif
virtual void backward();
virtual void forward();
virtual void home();
@@ -107,7 +66,6 @@ Q_SIGNALS:
void historyChanged();
void sourceChanged(const QUrl &);
void highlighted(const QUrl &);
- void highlighted(const QString &);
void anchorClicked(const QUrl &);
protected:
@@ -119,17 +77,11 @@ protected:
virtual void focusOutEvent(QFocusEvent *ev) override;
virtual bool focusNextPrevChild(bool next) override;
virtual void paintEvent(QPaintEvent *e) override;
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
- virtual
-#endif
- void doSetSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource);
+ virtual void doSetSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource);
private:
Q_DISABLE_COPY(QTextBrowser)
Q_DECLARE_PRIVATE(QTextBrowser)
- Q_PRIVATE_SLOT(d_func(), void _q_documentModified())
- Q_PRIVATE_SLOT(d_func(), void _q_activateAnchor(const QString &))
- Q_PRIVATE_SLOT(d_func(), void _q_highlightLink(const QString &))
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 10de7d0b9e..90884dd438 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextedit_p.h"
#if QT_CONFIG(lineedit)
@@ -58,7 +22,7 @@
#endif
#include <qstyle.h>
#include <qtimer.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <qaccessible.h>
#endif
#include "private/qtextdocumentlayout_p.h"
@@ -79,7 +43,11 @@ QT_BEGIN_NAMESPACE
static inline bool shouldEnableInputMethod(QTextEdit *textedit)
{
+#if defined (Q_OS_ANDROID)
+ return !textedit->isReadOnly() || (textedit->textInteractionFlags() & Qt::TextSelectableByMouse);
+#else
return !textedit->isReadOnly();
+#endif
}
class QTextEditControl : public QWidgetTextControl
@@ -120,8 +88,7 @@ QTextEditPrivate::QTextEditPrivate()
: control(nullptr),
autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false),
lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0),
- wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0),
- textFormat(Qt::AutoText)
+ wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0)
{
ignoreAutomaticScrollbarAdjustment = false;
preferRichText = false;
@@ -129,6 +96,12 @@ QTextEditPrivate::QTextEditPrivate()
inDrag = false;
}
+QTextEditPrivate::~QTextEditPrivate()
+{
+ for (const QMetaObject::Connection &connection : connections)
+ QObject::disconnect(connection);
+}
+
void QTextEditPrivate::createAutoBulletList()
{
QTextCursor cursor = control->textCursor();
@@ -155,24 +128,34 @@ void QTextEditPrivate::init(const QString &html)
control = new QTextEditControl(q);
control->setPalette(q->palette());
- QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus()));
- QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars()));
- QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF)));
- QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), q, SLOT(_q_ensureVisible(QRectF)));
- QObject::connect(control, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
- q, SLOT(_q_currentCharFormatChanged(QTextCharFormat)));
-
- QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged()));
- QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
- QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
- QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool)));
- QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
- QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged()));
-#if QT_CONFIG(cursor)
- QObject::connect(control, SIGNAL(blockMarkerHovered(QTextBlock)), q, SLOT(_q_hoveredBlockWithMarkerChanged(QTextBlock)));
-#endif
-
- QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus()));
+ connections = {
+ QObjectPrivate::connect(control, &QTextEditControl::documentSizeChanged,
+ this, &QTextEditPrivate::adjustScrollbars),
+ QObjectPrivate::connect(control, &QTextEditControl::updateRequest,
+ this, &QTextEditPrivate::repaintContents),
+ QObjectPrivate::connect(control, &QTextEditControl::visibilityRequest,
+ this, &QTextEditPrivate::ensureVisible),
+ QObjectPrivate::connect(control, &QTextEditControl::blockMarkerHovered,
+ this, &QTextEditPrivate::hoveredBlockWithMarkerChanged),
+ QObjectPrivate::connect(control, &QTextEditControl::cursorPositionChanged,
+ this, &QTextEditPrivate::cursorPositionChanged),
+ QObject::connect(control, &QTextEditControl::microFocusChanged,
+ q, [q]() { q->updateMicroFocus(); }),
+ QObject::connect(control, &QTextEditControl::currentCharFormatChanged,
+ q, &QTextEdit::currentCharFormatChanged),
+ QObject::connect(control, &QTextEditControl::textChanged,
+ q, &QTextEdit::textChanged),
+ QObject::connect(control, &QTextEditControl::undoAvailable,
+ q, &QTextEdit::undoAvailable),
+ QObject::connect(control, &QTextEditControl::redoAvailable,
+ q, &QTextEdit::redoAvailable),
+ QObject::connect(control, &QTextEditControl::copyAvailable,
+ q, &QTextEdit::copyAvailable),
+ QObject::connect(control, &QTextEditControl::selectionChanged,
+ q, &QTextEdit::selectionChanged),
+ QObject::connect(control, &QTextEditControl::textChanged,
+ q, [q]() { q->updateMicroFocus(); }),
+ };
QTextDocument *doc = control->document();
// set a null page size initially to avoid any relayouting until the textedit
@@ -202,7 +185,7 @@ void QTextEditPrivate::init(const QString &html)
#endif
}
-void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
+void QTextEditPrivate::repaintContents(const QRectF &contentsRect)
{
if (!contentsRect.isValid()) {
viewport->update();
@@ -220,19 +203,19 @@ void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
viewport->update(r);
}
-void QTextEditPrivate::_q_cursorPositionChanged()
+void QTextEditPrivate::cursorPositionChanged()
{
Q_Q(QTextEdit);
emit q->cursorPositionChanged();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextCursorEvent event(q, q->textCursor().position());
QAccessible::updateAccessibility(&event);
#endif
}
-#if QT_CONFIG(cursor)
-void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block)
+void QTextEditPrivate::hoveredBlockWithMarkerChanged(const QTextBlock &block)
{
+#if QT_CONFIG(cursor)
Q_Q(QTextEdit);
Qt::CursorShape cursor = cursorToRestoreAfterHover;
if (block.isValid() && !q->isReadOnly()) {
@@ -244,8 +227,8 @@ void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block)
}
}
viewport->setCursor(cursor);
-}
#endif
+}
void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode)
{
@@ -270,7 +253,7 @@ void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::Mo
vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
}
}
- control->setTextCursor(cursor);
+ control->setTextCursor(cursor, moveMode == QTextCursor::KeepAnchor);
}
#if QT_CONFIG(scrollbar)
@@ -294,7 +277,7 @@ static QSize documentSize(QWidgetTextControl *control)
return docSize;
}
-void QTextEditPrivate::_q_adjustScrollbars()
+void QTextEditPrivate::adjustScrollbars()
{
if (ignoreAutomaticScrollbarAdjustment)
return;
@@ -344,12 +327,12 @@ void QTextEditPrivate::_q_adjustScrollbars()
#endif
// rect is in content coordinates
-void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
+void QTextEditPrivate::ensureVisible(const QRectF &_rect)
{
const QRect rect = _rect.toRect();
if ((vbar->isVisible() && vbar->maximum() < rect.bottom())
|| (hbar->isVisible() && hbar->maximum() < rect.right()))
- _q_adjustScrollbars();
+ adjustScrollbars();
const int visibleWidth = viewport->width();
const int visibleHeight = viewport->height();
const bool rtl = q_func()->isRightToLeft();
@@ -572,7 +555,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
of the movement keystrokes, for example, \e{Shift+Right}
will select the character to the right, and \e{Shift+Ctrl+Right} will select the word to the right, etc.
- \sa QTextDocument, QTextCursor, {Application Example},
+ \sa QTextDocument, QTextCursor,
{Syntax Highlighter Example}, {Rich Text Processing}
*/
@@ -580,8 +563,9 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
\property QTextEdit::plainText
\since 4.3
- This property gets and sets the text editor's contents as plain
- text. Previous contents are removed and undo/redo history is reset
+ \brief the text editor's contents as plain text.
+
+ Previous contents are removed and undo/redo history is reset
when the property is set. currentCharFormat() is also reset, unless
textCursor() is already at the beginning of the document.
@@ -598,7 +582,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
/*!
\property QTextEdit::undoRedoEnabled
- \brief whether undo and redo are enabled
+ \brief whether undo and redo are enabled.
Users are only able to undo or redo actions if this property is
true, and if there is an action that can be undone (or redone).
@@ -685,7 +669,7 @@ qreal QTextEdit::fontPointSize() const
QString QTextEdit::fontFamily() const
{
Q_D(const QTextEdit);
- return d->control->textCursor().charFormat().fontFamily();
+ return d->control->textCursor().charFormat().fontFamilies().toStringList().value(0, QString());
}
/*!
@@ -744,7 +728,8 @@ QColor QTextEdit::textColor() const
QColor QTextEdit::textBackgroundColor() const
{
Q_D(const QTextEdit);
- return d->control->textCursor().charFormat().background().color();
+ const QBrush &brush = d->control->textCursor().charFormat().background();
+ return brush.style() == Qt::NoBrush ? Qt::transparent : brush.color();
}
/*!
@@ -877,7 +862,7 @@ QTextCursor QTextEdit::textCursor() const
void QTextEdit::setFontFamily(const QString &fontFamily)
{
QTextCharFormat fmt;
- fmt.setFontFamily(fontFamily);
+ fmt.setFontFamilies({fontFamily});
mergeCurrentCharFormat(fmt);
}
@@ -1095,30 +1080,38 @@ void QTextEdit::selectAll()
bool QTextEdit::event(QEvent *e)
{
Q_D(QTextEdit);
-#ifndef QT_NO_CONTEXTMENU
- if (e->type() == QEvent::ContextMenu
- && static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
- Q_D(QTextEdit);
- ensureCursorVisible();
- const QPoint cursorPos = cursorRect().center();
- QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
- ce.setAccepted(e->isAccepted());
- const bool result = QAbstractScrollArea::event(&ce);
- e->setAccepted(ce.isAccepted());
- return result;
- } else if (e->type() == QEvent::ShortcutOverride
- || e->type() == QEvent::ToolTip) {
+ switch (e->type()) {
+ case QEvent::ShortcutOverride:
+ case QEvent::ToolTip:
d->sendControlEvent(e);
- }
-#else
- Q_UNUSED(d)
+ break;
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ d->control->setPalette(palette());
+ break;
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ if (static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
+ ensureCursorVisible();
+ const QPoint cursorPos = cursorRect().center();
+ QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
+ ce.setAccepted(e->isAccepted());
+ const bool result = QAbstractScrollArea::event(&ce);
+ e->setAccepted(ce.isAccepted());
+ return result;
+ }
+ break;
#endif // QT_NO_CONTEXTMENU
#ifdef QT_KEYPAD_NAVIGATION
- if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) {
+ case QEvent::EnterEditFocus:
+ case QEvent::LeaveEditFocus:
if (QApplicationPrivate::keypadNavigationEnabled())
d->sendControlEvent(e);
- }
+ break;
#endif
+ default:
+ break;
+ }
return QAbstractScrollArea::event(e);
}
@@ -1272,6 +1265,7 @@ QString QTextEdit::toHtml() const
The default is \c MarkdownDialectGitHub.
\sa plainText, html, QTextDocument::toMarkdown(), QTextDocument::setMarkdown()
+ \since 5.14
*/
#endif
@@ -1401,8 +1395,8 @@ void QTextEdit::keyPressEvent(QKeyEvent *e)
const QString text = e->text();
if (cursor.atBlockStart()
&& (d->autoFormatting & AutoBulletList)
- && (text.length() == 1)
- && (text.at(0) == QLatin1Char('-') || text.at(0) == QLatin1Char('*'))
+ && (text.size() == 1)
+ && (text.at(0) == u'-' || text.at(0) == u'*')
&& (!cursor.currentList())) {
d->createAutoBulletList();
@@ -1450,8 +1444,10 @@ void QTextEdit::keyPressEvent(QKeyEvent *e)
*/
void QTextEdit::keyReleaseEvent(QKeyEvent *e)
{
-#ifdef QT_KEYPAD_NAVIGATION
Q_D(QTextEdit);
+ if (!isReadOnly())
+ d->handleSoftwareInputPanel();
+#ifdef QT_KEYPAD_NAVIGATION
if (QApplicationPrivate::keypadNavigationEnabled()) {
if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
&& d->deleteAllTimer.isActive()) {
@@ -1502,10 +1498,10 @@ void QTextEdit::resizeEvent(QResizeEvent *e)
QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment");
if (!doc->pageSize().isNull()
- && alignmentProperty.type() == QVariant::Bool
+ && alignmentProperty.userType() == QMetaType::Bool
&& !alignmentProperty.toBool()) {
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
return;
}
}
@@ -1514,7 +1510,7 @@ void QTextEdit::resizeEvent(QResizeEvent *e)
&& e->oldSize().width() != e->size().width())
d->relayoutDocument();
else
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
}
void QTextEditPrivate::relayoutDocument()
@@ -1536,7 +1532,7 @@ void QTextEditPrivate::relayoutDocument()
else
lastUsedSize = layout->documentSize().toSize();
- // ignore calls to _q_adjustScrollbars caused by an emission of the
+ // ignore calls to adjustScrollbars caused by an emission of the
// usedSizeChanged() signal in the layout, as we're calling it
// later on our own anyway (or deliberately not) .
const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment;
@@ -1547,7 +1543,7 @@ void QTextEditPrivate::relayoutDocument()
width = lineWrapColumnOrWidth;
else if (lineWrap == QTextEdit::NoWrap) {
QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment");
- if (alignmentProperty.type() == QVariant::Bool && !alignmentProperty.toBool()) {
+ if (alignmentProperty.userType() == QMetaType::Bool && !alignmentProperty.toBool()) {
width = 0;
}
@@ -1575,7 +1571,7 @@ void QTextEditPrivate::relayoutDocument()
// its size. So a layout with less width _can_ take up less vertical space, too.
// If the wider case causes a vertical scroll bar to appear and the narrower one
// (narrower because the vertical scroll bar takes up horizontal space)) to disappear
- // again then we have an endless loop, as _q_adjustScrollBars sets new ranges on the
+ // again then we have an endless loop, as adjustScrollbars sets new ranges on the
// scroll bars, the QAbstractScrollArea will find out about it and try to show/hide
// the scroll bars again. That's why we try to detect this case here and break out.
//
@@ -1588,7 +1584,7 @@ void QTextEditPrivate::relayoutDocument()
&& usedSize.height() <= viewport->height())
return;
- _q_adjustScrollbars();
+ adjustScrollbars();
}
void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
@@ -1626,6 +1622,8 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
This event handler can be reimplemented in a subclass to receive paint events passed in \a event.
It is usually unnecessary to reimplement this function in a subclass of QTextEdit.
+\note If you create a QPainter, it must operate on the \l{QAbstractScrollArea::}{viewport()}.
+
\warning The underlying text document must not be modified from within a reimplementation
of this function.
*/
@@ -1636,12 +1634,6 @@ void QTextEdit::paintEvent(QPaintEvent *e)
d->paint(&p, e);
}
-void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt)
-{
- Q_Q(QTextEdit);
- emit q->currentCharFormatChanged(fmt);
-}
-
void QTextEditPrivate::updateDefaultTextOption()
{
QTextDocument *doc = control->document();
@@ -1676,7 +1668,7 @@ void QTextEdit::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QTextEdit);
d->inDrag = false; // paranoia
- const QPoint pos = e->pos();
+ const QPoint pos = e->position().toPoint();
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
@@ -1699,7 +1691,7 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->autoScrollTimer.stop();
ensureCursorVisible();
}
- if (!isReadOnly() && rect().contains(e->pos()))
+ if (!isReadOnly() && rect().contains(e->position().toPoint()))
d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
d->clickCausedFocus = 0;
}
@@ -1770,7 +1762,7 @@ void QTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
void QTextEdit::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QTextEdit);
- d->autoScrollDragPos = e->pos();
+ d->autoScrollDragPos = e->position().toPoint();
if (!d->autoScrollTimer.isActive())
d->autoScrollTimer.start(100, this);
d->sendControlEvent(e);
@@ -1800,6 +1792,10 @@ void QTextEdit::inputMethodEvent(QInputMethodEvent *e)
setEditFocus(true);
#endif
d->sendControlEvent(e);
+ const bool emptyEvent = e->preeditString().isEmpty() && e->commitString().isEmpty()
+ && e->attributes().isEmpty();
+ if (emptyEvent)
+ return;
ensureCursorVisible();
}
@@ -1827,25 +1823,29 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume
{
Q_D(const QTextEdit);
switch (query) {
- case Qt::ImHints:
- case Qt::ImInputItemClipRectangle:
+ case Qt::ImEnabled:
+ return isEnabled() && !isReadOnly();
+ case Qt::ImHints:
+ case Qt::ImInputItemClipRectangle:
return QWidget::inputMethodQuery(query);
+ case Qt::ImReadOnly:
+ return isReadOnly();
default:
break;
}
const QPointF offset(-d->horizontalOffset(), -d->verticalOffset());
- switch (argument.type()) {
- case QVariant::RectF:
+ switch (argument.userType()) {
+ case QMetaType::QRectF:
argument = argument.toRectF().translated(-offset);
break;
- case QVariant::PointF:
+ case QMetaType::QPointF:
argument = argument.toPointF() - offset;
break;
- case QVariant::Rect:
+ case QMetaType::QRect:
argument = argument.toRect().translated(-offset.toPoint());
break;
- case QVariant::Point:
+ case QMetaType::QPoint:
argument = argument.toPoint() - offset;
break;
default:
@@ -1853,14 +1853,14 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume
}
const QVariant v = d->control->inputMethodQuery(query, argument);
- switch (v.type()) {
- case QVariant::RectF:
+ switch (v.userType()) {
+ case QMetaType::QRectF:
return v.toRectF().translated(offset);
- case QVariant::PointF:
+ case QMetaType::QPointF:
return v.toPointF() + offset;
- case QVariant::Rect:
+ case QMetaType::QRect:
return v.toRect().translated(offset.toPoint());
- case QVariant::Point:
+ case QMetaType::QPoint:
return v.toPoint() + offset.toPoint();
default:
break;
@@ -1913,7 +1913,7 @@ void QTextEdit::changeEvent(QEvent *e)
if (e->type() == QEvent::ApplicationFontChange
|| e->type() == QEvent::FontChange) {
d->control->document()->setDefaultFont(font());
- } else if(e->type() == QEvent::ActivationChange) {
+ } else if (e->type() == QEvent::ActivationChange) {
if (!isActiveWindow())
d->autoScrollTimer.stop();
} else if (e->type() == QEvent::EnabledChange) {
@@ -2052,33 +2052,18 @@ void QTextEdit::setOverwriteMode(bool overwrite)
d->control->setOverwriteMode(overwrite);
}
-#if QT_DEPRECATED_SINCE(5, 10)
-/*!
- \property QTextEdit::tabStopWidth
- \brief the tab stop width in pixels
- \since 4.1
- \deprecated in Qt 5.10. Use tabStopDistance instead.
-
- By default, this property contains a value of 80 pixels.
-*/
-
-int QTextEdit::tabStopWidth() const
-{
- return qRound(tabStopDistance());
-}
-
-void QTextEdit::setTabStopWidth(int width)
-{
- setTabStopDistance(width);
-}
-#endif
-
/*!
\property QTextEdit::tabStopDistance
\brief the tab stop distance in pixels
\since 5.10
By default, this property contains a value of 80 pixels.
+
+ Do not set a value less than the \l {QFontMetrics::}{horizontalAdvance()}
+ of the QChar::VisualTabCharacter character, otherwise the tab-character
+ will be drawn incompletely.
+
+ \sa QTextOption::ShowTabsAndSpaces, QTextDocument::defaultTextOption
*/
qreal QTextEdit::tabStopDistance() const
@@ -2120,7 +2105,7 @@ void QTextEdit::setCursorWidth(int width)
\brief whether the text edit accepts rich text insertions by the user
\since 4.1
- When this propery is set to false text edit will accept only
+ When this property is set to false text edit will accept only
plain text input from the user. For example through clipboard or drag and drop.
This property's default is true.
@@ -2244,7 +2229,7 @@ void QTextEdit::insertFromMimeData(const QMimeData *source)
bool QTextEdit::isReadOnly() const
{
Q_D(const QTextEdit);
- return !(d->control->textInteractionFlags() & Qt::TextEditable);
+ return !d->control || !(d->control->textInteractionFlags() & Qt::TextEditable);
}
void QTextEdit::setReadOnly(bool ro)
@@ -2401,7 +2386,7 @@ void QTextEdit::scrollToAnchor(const QString &name)
QPointF p = d->control->anchorPosition(name);
const int newPosition = qRound(p.y());
if ( d->vbar->maximum() < newPosition )
- d->_q_adjustScrollbars();
+ d->adjustScrollbars();
d->vbar->setValue(newPosition);
}
@@ -2609,38 +2594,20 @@ bool QTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
}
/*!
- \fn bool QTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
-
- \since 5.3
- \overload
-
- Finds the next occurrence, matching the regular expression, \a exp, using the given
- \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
- use QRegExp::caseSensitivity instead.
-
- Returns \c true if a match was found and changes the cursor to select the match;
- otherwise returns \c false.
-*/
-#ifndef QT_NO_REGEXP
-bool QTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
-{
- Q_D(QTextEdit);
- return d->control->find(exp, options);
-}
-#endif
-
-/*!
\fn bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
\since 5.13
\overload
Finds the next occurrence, matching the regular expression, \a exp, using the given
- \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
- use QRegularExpression::CaseInsensitiveOption instead.
+ \a options.
Returns \c true if a match was found and changes the cursor to select the match;
otherwise returns \c false.
+
+ \warning For historical reasons, the case sensitivity option set on
+ \a exp is ignored. Instead, the \a options are used to determine
+ if the search is case sensitive or not.
*/
#if QT_CONFIG(regularexpression)
bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
@@ -2704,10 +2671,7 @@ bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags opt
*/
void QTextEdit::setText(const QString &text)
{
- Q_D(QTextEdit);
- Qt::TextFormat format = d->textFormat;
- if (d->textFormat == Qt::AutoText)
- format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText;
+ Qt::TextFormat format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText;
#ifndef QT_NO_TEXTHTMLPARSER
if (format == Qt::RichText)
setHtml(text);
diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h
index 5c8a3c7793..421eb9136b 100644
--- a/src/widgets/widgets/qtextedit.h
+++ b/src/widgets/widgets/qtextedit.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTEDIT_H
#define QTEXTEDIT_H
@@ -79,13 +43,11 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
#endif
Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText DESIGNABLE false)
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
-#if QT_DEPRECATED_SINCE(5, 10)
- Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth)
-#endif
Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance)
Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText)
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
- Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags
+ WRITE setTextInteractionFlags)
Q_PROPERTY(QTextDocument *document READ document WRITE setDocument DESIGNABLE false)
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
public:
@@ -166,9 +128,6 @@ public:
void setWordWrapMode(QTextOption::WrapMode policy);
bool find(const QString &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
-#ifndef QT_NO_REGEXP
- bool find(const QRegExp &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
-#endif
#if QT_CONFIG(regularexpression)
bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
#endif
@@ -198,11 +157,6 @@ public:
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
-#if QT_DEPRECATED_SINCE(5, 10)
- QT_DEPRECATED int tabStopWidth() const;
- QT_DEPRECATED void setTabStopWidth(int width);
-#endif
-
qreal tabStopDistance() const;
void setTabStopDistance(qreal distance);
@@ -326,14 +280,6 @@ protected:
private:
Q_DISABLE_COPY(QTextEdit)
- Q_PRIVATE_SLOT(d_func(), void _q_repaintContents(const QRectF &r))
- Q_PRIVATE_SLOT(d_func(), void _q_currentCharFormatChanged(const QTextCharFormat &))
- Q_PRIVATE_SLOT(d_func(), void _q_adjustScrollbars())
- Q_PRIVATE_SLOT(d_func(), void _q_ensureVisible(const QRectF &))
- Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
-#if QT_CONFIG(cursor)
- Q_PRIVATE_SLOT(d_func(), void _q_hoveredBlockWithMarkerChanged(const QTextBlock &))
-#endif
friend class QTextEditControl;
friend class QTextDocument;
friend class QWidgetTextControl;
diff --git a/src/widgets/widgets/qtextedit_p.h b/src/widgets/widgets/qtextedit_p.h
index f7b4d15318..7dd7d9c107 100644
--- a/src/widgets/widgets/qtextedit_p.h
+++ b/src/widgets/widgets/qtextedit_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTEDIT_P_H
#define QTEXTEDIT_P_H
@@ -69,6 +33,8 @@
#include "private/qwidgettextcontrol_p.h"
+#include <array>
+
QT_REQUIRE_CONFIG(textedit);
QT_BEGIN_NAMESPACE
@@ -79,16 +45,17 @@ class QTextEditPrivate : public QAbstractScrollAreaPrivate
Q_DECLARE_PUBLIC(QTextEdit)
public:
QTextEditPrivate();
+ ~QTextEditPrivate();
void init(const QString &html = QString());
void paint(QPainter *p, QPaintEvent *e);
- void _q_repaintContents(const QRectF &contentsRect);
+ void repaintContents(const QRectF &contentsRect);
inline QPoint mapToContents(const QPoint &point) const
{ return QPoint(point.x() + horizontalOffset(), point.y() + verticalOffset()); }
- void _q_adjustScrollbars();
- void _q_ensureVisible(const QRectF &rect);
+ void adjustScrollbars();
+ void ensureVisible(const QRectF &rect);
void relayoutDocument();
void createAutoBulletList();
@@ -102,9 +69,8 @@ public:
inline void sendControlEvent(QEvent *e)
{ control->processEvent(e, QPointF(horizontalOffset(), verticalOffset()), viewport); }
- void _q_currentCharFormatChanged(const QTextCharFormat &format);
- void _q_cursorPositionChanged();
- void _q_hoveredBlockWithMarkerChanged(const QTextBlock &block);
+ void cursorPositionChanged();
+ void hoveredBlockWithMarkerChanged(const QTextBlock &block);
void updateDefaultTextOption();
@@ -130,15 +96,14 @@ public:
uint inDrag : 1;
uint clickCausedFocus : 1;
- // Qt3 COMPAT only, for setText
- Qt::TextFormat textFormat;
-
QString anchorToScrollToWhenVisible;
QString placeholderText;
Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor;
+ std::array<QMetaObject::Connection, 13> connections;
+
#ifdef QT_KEYPAD_NAVIGATION
QBasicTimer deleteAllTimer;
#endif
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index f35c02f2fb..5e5ef8e8d5 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtoolbar.h"
@@ -43,6 +7,9 @@
#if QT_CONFIG(combobox)
#include <qcombobox.h>
#endif
+#if QT_CONFIG(draganddrop)
+#include <qdrag.h>
+#endif
#include <qevent.h>
#include <qlayout.h>
#include <qmainwindow.h>
@@ -50,6 +17,7 @@
#if QT_CONFIG(menubar)
#include <qmenubar.h>
#endif
+#include <qmimedata.h>
#if QT_CONFIG(rubberband)
#include <qrubberband.h>
#endif
@@ -60,8 +28,9 @@
#include <qtimer.h>
#include <private/qwidgetaction_p.h>
#include <private/qmainwindowlayout_p.h>
+#include <private/qhighdpiscaling_p.h>
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
#include <qpa/qplatformnativeinterface.h>
#endif
@@ -75,6 +44,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// qmainwindow.cpp
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
@@ -140,8 +111,12 @@ void QToolBarPrivate::updateWindowFlags(bool floating, bool unplug)
flags |= Qt::FramelessWindowHint;
- if (unplug)
+#if QT_CONFIG(draganddrop)
+ // If we are performing a platform drag the flag is not needed and we want to avoid recreating
+ // the platform window when it would be removed later
+ if (unplug && !QMainWindowLayout::needsPlatformDrag())
flags |= Qt::X11BypassWindowManagerHint;
+#endif
q->setWindowFlags(flags);
}
@@ -152,8 +127,6 @@ void QToolBarPrivate::setWindowState(bool floating, bool unplug, const QRect &re
bool visible = !q->isHidden();
bool wasFloating = q->isFloating(); // ...is also currently using popup menus
- q->hide();
-
updateWindowFlags(floating, unplug);
if (floating != wasFloating)
@@ -207,12 +180,29 @@ void QToolBarPrivate::startDrag(bool moving)
QMainWindowLayout *layout = qt_mainwindow_layout(win);
Q_ASSERT(layout != nullptr);
+#if QT_CONFIG(draganddrop)
+ const bool wasFloating = q->isFloating();
+#endif
+
if (!moving) {
- state->widgetItem = layout->unplug(q);
+ state->widgetItem = layout->unplug(q, QDockWidgetPrivate::DragScope::Group);
Q_ASSERT(state->widgetItem != nullptr);
}
state->dragging = !moving;
state->moving = moving;
+
+#if QT_CONFIG(draganddrop)
+ if (QMainWindowLayout::needsPlatformDrag() && state->dragging) {
+ auto result = layout->performPlatformWidgetDrag(state->widgetItem, state->pressPos);
+ if (result == Qt::IgnoreAction && !wasFloating) {
+ layout->revert(state->widgetItem);
+ delete state;
+ state = nullptr;
+ } else {
+ endDrag();
+ }
+ }
+#endif
}
void QToolBarPrivate::endDrag()
@@ -247,8 +237,8 @@ bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
Q_Q(QToolBar);
QStyleOptionToolBar opt;
q->initStyleOption(&opt);
- if (q->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, q).contains(event->pos()) == false) {
-#ifdef Q_OS_OSX
+ if (q->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, q).contains(event->position().toPoint()) == false) {
+#ifdef Q_OS_MACOS
// When using the unified toolbar on OS X, the user can click and
// drag between toolbar contents to move the window. Make this work by
// implementing the standard mouse-dragging code and then call
@@ -272,17 +262,24 @@ bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
if (!layout->movable())
return true;
- initDrag(event->pos());
+ initDrag(event->position().toPoint());
return true;
}
bool QToolBarPrivate::mouseReleaseEvent(QMouseEvent*)
{
+#if QT_CONFIG(draganddrop)
+ // if we are peforming a platform drag ignore the release here and end the drag when the actual
+ // drag ends.
+ if (QMainWindowLayout::needsPlatformDrag())
+ return false;
+#endif
+
if (state != nullptr) {
endDrag();
return true;
} else {
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
if (!macWindowDragging)
return false;
macWindowDragging = false;
@@ -298,7 +295,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
Q_Q(QToolBar);
if (!state) {
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
if (!macWindowDragging)
return false;
QWidget *w = q->window();
@@ -317,19 +314,24 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
Q_ASSERT(layout != nullptr);
if (layout->pluggingWidget == nullptr
- && (event->pos() - state->pressPos).manhattanLength() > QApplication::startDragDistance()) {
+ && (event->position().toPoint() - state->pressPos).manhattanLength() > QApplication::startDragDistance()) {
const bool wasDragging = state->dragging;
const bool moving = !q->isWindow() && (orientation == Qt::Vertical ?
- event->x() >= 0 && event->x() < q->width() :
- event->y() >= 0 && event->y() < q->height());
+ event->position().toPoint().x() >= 0 && event->position().toPoint().x() < q->width() :
+ event->position().toPoint().y() >= 0 && event->position().toPoint().y() < q->height());
startDrag(moving);
if (!moving && !wasDragging)
q->grabMouse();
}
+ if (!state) {
+ q->releaseMouse();
+ return true;
+ }
+
if (state->dragging) {
- QPoint pos = event->globalPos();
+ QPoint pos = event->globalPosition().toPoint();
// if we are right-to-left, we move so as to keep the right edge the same distance
// from the mouse
if (q->isLeftToRight())
@@ -338,14 +340,19 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
pos += QPoint(state->pressPos.x() - q->width(), -state->pressPos.y());
q->move(pos);
- layout->hover(state->widgetItem, event->globalPos());
+ layout->hover(state->widgetItem, event->globalPosition().toPoint());
} else if (state->moving) {
const QPoint rtl(q->width() - state->pressPos.x(), state->pressPos.y()); //for RTL
const QPoint globalPressPos = q->mapToGlobal(q->isRightToLeft() ? rtl : state->pressPos);
int pos = 0;
- QPoint delta = event->globalPos() - globalPressPos;
+ const QWindow *handle = q->window() ? q->window()->windowHandle() : nullptr;
+ const QPoint delta = handle
+ ? QHighDpi::fromNativePixels(event->globalPosition(), handle).toPoint()
+ - QHighDpi::fromNativePixels(globalPressPos, handle)
+ : event->globalPosition().toPoint() - globalPressPos;
+
if (orientation == Qt::Vertical) {
pos = q->y() + delta.y();
} else {
@@ -388,6 +395,10 @@ void QToolBarPrivate::plug(const QRect &r)
\ingroup mainwindow-classes
\inmodule QtWidgets
+ A toolbar is typically created by calling
+ \l QMainWindow::addToolBar(const QString &title), but it can also
+ be added as the first widget in a QVBoxLayout, for example.
+
Toolbar buttons are added by adding \e actions, using addAction()
or insertAction(). Groups of buttons can be separated using
addSeparator() or insertSeparator(). If a toolbar button is not
@@ -411,7 +422,7 @@ void QToolBarPrivate::plug(const QRect &r)
addWidget(). Please use widget actions created by inheriting QWidgetAction
and implementing QWidgetAction::createWidget() instead.
- \sa QToolButton, QMenu, QAction, {Application Example}
+ \sa QToolButton, QMenu, QAction
*/
/*!
@@ -737,117 +748,6 @@ void QToolBar::clear()
}
/*!
- Creates a new action with the given \a text. This action is added to
- the end of the toolbar.
-*/
-QAction *QToolBar::addAction(const QString &text)
-{
- QAction *action = new QAction(text, this);
- addAction(action);
- return action;
-}
-
-/*!
- \overload
-
- Creates a new action with the given \a icon and \a text. This
- action is added to the end of the toolbar.
-*/
-QAction *QToolBar::addAction(const QIcon &icon, const QString &text)
-{
- QAction *action = new QAction(icon, text, this);
- addAction(action);
- return action;
-}
-
-/*!
- \overload
-
- Creates a new action with the given \a text. This action is added to
- the end of the toolbar. The action's \l{QAction::triggered()}{triggered()}
- signal is connected to \a member in \a receiver.
-*/
-QAction *QToolBar::addAction(const QString &text,
- const QObject *receiver, const char* member)
-{
- QAction *action = new QAction(text, this);
- QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
- addAction(action);
- return action;
-}
-
-/*!
- \overload
-
- Creates a new action with the given \a icon and \a text. This
- action is added to the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to \a
- member in \a receiver.
-*/
-QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
- const QObject *receiver, const char* member)
-{
- QAction *action = new QAction(icon, text, this);
- QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
- addAction(action);
- return action;
-}
-
-/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QString &text, Functor functor)
-
- \since 5.6
-
- \overload
-
- Creates a new action with the given \a text. This action is added to
- the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor.
-*/
-
-/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QString &text, const QObject *context, Functor functor)
-
- \since 5.6
-
- \overload
-
- Creates a new action with the given \a text. This action is added
- to the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The \a functor can be a pointer to a member function
- in the \a context object.
-
- If the \a context object is destroyed, the \a functor will not be called.
-*/
-
-/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QIcon &icon, const QString &text, Functor functor)
-
- \since 5.6
-
- \overload
-
- Creates a new action with the given \a icon and \a text. This
- action is added to the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor.
-*/
-
-/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor)
-
- \since 5.6
-
- \overload
-
- Creates a new action with the given \a icon and \a text. This
- action is added to the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The \a functor can be a pointer to a member function
- of the \a context object.
-
- If the \a context object is destroyed, the \a functor will not be called.
-*/
-
-/*!
Adds a separator to the end of the toolbar.
\sa insertSeparator()
@@ -1073,17 +973,18 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup)
if (menu == nullptr)
return false;
- QAction *action = menu->menuAction();
- QList<QWidget*> widgets = action->associatedWidgets();
- for (int i = 0; i < widgets.count(); ++i) {
- if (waitForPopup(tb, widgets.at(i)))
- return true;
+ const QAction *action = menu->menuAction();
+ for (auto object : action->associatedObjects()) {
+ if (QWidget *widget = qobject_cast<QWidget*>(object)) {
+ if (waitForPopup(tb, widget))
+ return true;
+ }
}
return false;
}
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
static void enableMacToolBar(QToolBar *toolbar, bool enable)
{
QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
@@ -1122,7 +1023,7 @@ bool QToolBar::event(QEvent *event)
Q_FALLTHROUGH();
case QEvent::Show:
d->toggleViewAction->setChecked(event->type() == QEvent::Show);
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
enableMacToolBar(this, event->type() == QEvent::Show);
#endif
emit visibilityChanged(event->type() == QEvent::Show);
@@ -1149,7 +1050,7 @@ bool QToolBar::event(QEvent *event)
QHoverEvent *e = static_cast<QHoverEvent*>(event);
QStyleOptionToolBar opt;
initStyleOption(&opt);
- if (style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, this).contains(e->pos()))
+ if (style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, this).contains(e->position().toPoint()))
setCursor(Qt::SizeAllCursor);
else
unsetCursor();
@@ -1163,7 +1064,7 @@ bool QToolBar::event(QEvent *event)
case QEvent::Leave:
if (d->state != nullptr && d->state->dragging) {
#ifdef Q_OS_WIN
- // This is a workaround for loosing the mouse on Vista.
+ // This is a workaround for losing the mouse on Vista.
QPoint pos = QCursor::pos();
QMouseEvent fake(QEvent::MouseMove, mapFromGlobal(pos), pos, Qt::NoButton,
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
@@ -1183,6 +1084,7 @@ bool QToolBar::event(QEvent *event)
d->layout->setExpanded(false);
break;
}
+ break;
default:
break;
}
diff --git a/src/widgets/widgets/qtoolbar.h b/src/widgets/widgets/qtoolbar.h
index 6aaf59cafd..fbad25c7c9 100644
--- a/src/widgets/widgets/qtoolbar.h
+++ b/src/widgets/widgets/qtoolbar.h
@@ -1,47 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICTOOLBAR_H
#define QDYNAMICTOOLBAR_H
#include <QtWidgets/qtwidgetsglobal.h>
-#include <QtWidgets/qaction.h>
+#include <QtGui/qaction.h>
#include <QtWidgets/qwidget.h>
QT_REQUIRE_CONFIG(toolbar);
@@ -60,8 +24,10 @@ class Q_WIDGETS_EXPORT QToolBar : public QWidget
Q_OBJECT
Q_PROPERTY(bool movable READ isMovable WRITE setMovable NOTIFY movableChanged)
- Q_PROPERTY(Qt::ToolBarAreas allowedAreas READ allowedAreas WRITE setAllowedAreas NOTIFY allowedAreasChanged)
- Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(Qt::ToolBarAreas allowedAreas READ allowedAreas WRITE setAllowedAreas
+ NOTIFY allowedAreasChanged)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation
+ NOTIFY orientationChanged)
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize NOTIFY iconSizeChanged)
Q_PROPERTY(Qt::ToolButtonStyle toolButtonStyle READ toolButtonStyle WRITE setToolButtonStyle
NOTIFY toolButtonStyleChanged)
@@ -88,58 +54,13 @@ public:
void clear();
using QWidget::addAction;
+#if QT_WIDGETS_REMOVED_SINCE(6, 3)
QAction *addAction(const QString &text);
QAction *addAction(const QIcon &icon, const QString &text);
QAction *addAction(const QString &text, const QObject *receiver, const char* member);
QAction *addAction(const QIcon &icon, const QString &text,
const QObject *receiver, const char* member);
-#ifdef Q_CLANG_QDOC
- template<typename Functor>
- QAction *addAction(const QString &text, Functor functor);
- template<typename Functor>
- QAction *addAction(const QString &text, const QObject *context, Functor functor);
- template<typename Functor>
- QAction *addAction(const QIcon &icon, const QString &text, Functor functor);
- template<typename Functor>
- QAction *addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor);
-#else
- // addAction(QString): Connect to a QObject slot / functor or function pointer (with context)
- template<class Obj, typename Func1>
- inline typename std::enable_if<!std::is_same<const char*, Func1>::value
- && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type
- addAction(const QString &text, const Obj *object, Func1 slot)
- {
- QAction *result = addAction(text);
- connect(result, &QAction::triggered, object, std::move(slot));
- return result;
- }
- // addAction(QString): Connect to a functor or function pointer (without context)
- template <typename Func1>
- inline QAction *addAction(const QString &text, Func1 slot)
- {
- QAction *result = addAction(text);
- connect(result, &QAction::triggered, slot);
- return result;
- }
- // addAction(QString): Connect to a QObject slot / functor or function pointer (with context)
- template<class Obj, typename Func1>
- inline typename std::enable_if<!std::is_same<const char*, Func1>::value
- && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value, QAction *>::type
- addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot)
- {
- QAction *result = addAction(actionIcon, text);
- connect(result, &QAction::triggered, object, std::move(slot));
- return result;
- }
- // addAction(QIcon, QString): Connect to a functor or function pointer (without context)
- template <typename Func1>
- inline QAction *addAction(const QIcon &actionIcon, const QString &text, Func1 slot)
- {
- QAction *result = addAction(actionIcon, text);
- connect(result, &QAction::triggered, slot);
- return result;
- }
-#endif // !Q_CLANG_QDOC
+#endif
QAction *addSeparator();
QAction *insertSeparator(QAction *before);
@@ -181,7 +102,7 @@ protected:
void changeEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
bool event(QEvent *event) override;
- void initStyleOption(QStyleOptionToolBar *option) const;
+ virtual void initStyleOption(QStyleOptionToolBar *option) const;
private:
diff --git a/src/widgets/widgets/qtoolbar_p.h b/src/widgets/widgets/qtoolbar_p.h
index 8cb5850903..2561cd8f64 100644
--- a/src/widgets/widgets/qtoolbar_p.h
+++ b/src/widgets/widgets/qtoolbar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICTOOLBAR_P_H
#define QDYNAMICTOOLBAR_P_H
@@ -53,7 +17,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "qtoolbar.h"
-#include "QtWidgets/qaction.h"
+#include "QtGui/qaction.h"
#include "private/qwidget_p.h"
#include <QtCore/qbasictimer.h>
@@ -74,7 +38,7 @@ public:
allowedAreas(Qt::AllToolBarAreas), orientation(Qt::Horizontal),
toolButtonStyle(Qt::ToolButtonIconOnly),
layout(nullptr), state(nullptr)
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
, macWindowDragging(false)
#endif
{ }
@@ -106,7 +70,7 @@ public:
};
DragState *state;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
bool macWindowDragging;
QPoint macWindowDragPressPosition;
#endif
diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp
index 493c094cc1..54c21b6038 100644
--- a/src/widgets/widgets/qtoolbararealayout.cpp
+++ b/src/widgets/widgets/qtoolbararealayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QWidgetItem>
#include <QToolBar>
@@ -106,7 +70,7 @@ QToolBarAreaLayoutLine::QToolBarAreaLayoutLine(Qt::Orientation orientation)
QSize QToolBarAreaLayoutLine::sizeHint() const
{
int a = 0, b = 0;
- for (int i = 0; i < toolBarItems.count(); ++i) {
+ for (int i = 0; i < toolBarItems.size(); ++i) {
const QToolBarAreaLayoutItem &item = toolBarItems.at(i);
if (item.skip())
continue;
@@ -126,7 +90,7 @@ QSize QToolBarAreaLayoutLine::sizeHint() const
QSize QToolBarAreaLayoutLine::minimumSize() const
{
int a = 0, b = 0;
- for (int i = 0; i < toolBarItems.count(); ++i) {
+ for (int i = 0; i < toolBarItems.size(); ++i) {
const QToolBarAreaLayoutItem &item = toolBarItems[i];
if (item.skip())
continue;
@@ -150,7 +114,7 @@ void QToolBarAreaLayoutLine::fitLayout()
int space = pick(o, rect.size());
int extra = qMax(0, space - min);
- for (int i = 0; i < toolBarItems.count(); ++i) {
+ for (int i = 0; i < toolBarItems.size(); ++i) {
QToolBarAreaLayoutItem &item = toolBarItems[i];
if (item.skip())
continue;
@@ -173,7 +137,7 @@ void QToolBarAreaLayoutLine::fitLayout()
// calculate the positions from the sizes
int pos = 0;
- for (int i = 0; i < toolBarItems.count(); ++i) {
+ for (int i = 0; i < toolBarItems.size(); ++i) {
QToolBarAreaLayoutItem &item = toolBarItems[i];
if (item.skip())
continue;
@@ -187,7 +151,7 @@ void QToolBarAreaLayoutLine::fitLayout()
bool QToolBarAreaLayoutLine::skip() const
{
- for (int i = 0; i < toolBarItems.count(); ++i) {
+ for (int i = 0; i < toolBarItems.size(); ++i) {
if (!toolBarItems.at(i).skip())
return false;
}
@@ -219,7 +183,7 @@ QToolBarAreaLayoutInfo::QToolBarAreaLayoutInfo(QInternal::DockPosition pos)
QSize QToolBarAreaLayoutInfo::sizeHint() const
{
int a = 0, b = 0;
- for (int i = 0; i < lines.count(); ++i) {
+ for (int i = 0; i < lines.size(); ++i) {
const QToolBarAreaLayoutLine &l = lines.at(i);
if (l.skip())
continue;
@@ -239,7 +203,7 @@ QSize QToolBarAreaLayoutInfo::sizeHint() const
QSize QToolBarAreaLayoutInfo::minimumSize() const
{
int a = 0, b = 0;
- for (int i = 0; i < lines.count(); ++i) {
+ for (int i = 0; i < lines.size(); ++i) {
const QToolBarAreaLayoutLine &l = lines.at(i);
if (l.skip())
continue;
@@ -264,9 +228,9 @@ void QToolBarAreaLayoutInfo::fitLayout()
bool reverse = dockPos == QInternal::RightDock || dockPos == QInternal::BottomDock;
- int i = reverse ? lines.count() - 1 : 0;
+ int i = reverse ? lines.size() - 1 : 0;
for (;;) {
- if ((reverse && i < 0) || (!reverse && i == lines.count()))
+ if ((reverse && i < 0) || (!reverse && i == lines.size()))
break;
QToolBarAreaLayoutLine &l = lines[i];
@@ -309,10 +273,10 @@ void QToolBarAreaLayoutInfo::insertItem(QToolBar *before, QLayoutItem *item)
return;
}
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == before) {
line.toolBarItems.insert(k, item);
return;
@@ -323,17 +287,17 @@ void QToolBarAreaLayoutInfo::insertItem(QToolBar *before, QLayoutItem *item)
void QToolBarAreaLayoutInfo::removeToolBar(QToolBar *toolBar)
{
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
QToolBarAreaLayoutItem &item = line.toolBarItems[k];
if (item.widgetItem->widget() == toolBar) {
delete item.widgetItem;
item.widgetItem = nullptr;
line.toolBarItems.removeAt(k);
- if (line.toolBarItems.isEmpty() && j < lines.count() - 1)
+ if (line.toolBarItems.isEmpty() && j < lines.size() - 1)
lines.removeAt(j);
return;
@@ -351,10 +315,10 @@ void QToolBarAreaLayoutInfo::insertToolBarBreak(QToolBar *before)
return;
}
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == before) {
if (k == 0)
return;
@@ -372,10 +336,10 @@ void QToolBarAreaLayoutInfo::insertToolBarBreak(QToolBar *before)
void QToolBarAreaLayoutInfo::removeToolBarBreak(QToolBar *before)
{
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == before) {
if (k != 0)
return;
@@ -402,12 +366,12 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
pos -= rect.top();
//here we actually update the preferredSize for the line containing the toolbar so that we move it
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
int previousIndex = -1;
int minPos = 0;
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
QToolBarAreaLayoutItem &current = line.toolBarItems[k];
if (current.widgetItem->widget() == toolbar) {
int newPos = current.pos;
@@ -419,7 +383,7 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
} else {
//we check the max value for the position (until everything at the right is "compressed")
int maxPos = pick(o, rect.size());
- for(int l = k; l < line.toolBarItems.count(); ++l) {
+ for(int l = k; l < line.toolBarItems.size(); ++l) {
const QToolBarAreaLayoutItem &item = line.toolBarItems.at(l);
if (!item.skip()) {
maxPos -= pick(o, item.minimumSize());
@@ -487,7 +451,7 @@ QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos, int *minDistance)
// Since we're comparing p with item.pos, we put them in the same coordinate system.
const int p = pick(o, pos - rect.topLeft());
- for (int j = 0; j < lines.count(); ++j) {
+ for (int j = 0; j < lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = lines.at(j);
if (line.skip())
continue;
@@ -495,7 +459,7 @@ QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos, int *minDistance)
continue;
int k = 0;
- for (; k < line.toolBarItems.count(); ++k) {
+ for (; k < line.toolBarItems.size(); ++k) {
const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
if (item.skip())
continue;
@@ -521,7 +485,7 @@ QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos, int *minDistance)
*minDistance = dist;
QList<int> result;
- result << lines.count() << 0;
+ result << lines.size() << 0;
return result;
}
}
@@ -531,9 +495,9 @@ QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos, int *minDistance)
bool QToolBarAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *item)
{
- Q_ASSERT(path.count() == 2);
+ Q_ASSERT(path.size() == 2);
int j = path.first();
- if (j == lines.count())
+ if (j == lines.size())
lines.append(QToolBarAreaLayoutLine(o));
QToolBarAreaLayoutLine &line = lines[j];
@@ -576,7 +540,7 @@ void QToolBarAreaLayoutInfo::clear()
QRect QToolBarAreaLayoutInfo::itemRect(const QList<int> &path) const
{
- Q_ASSERT(path.count() == 2);
+ Q_ASSERT(path.size() == 2);
int j = path.at(0);
int k = path.at(1);
@@ -734,10 +698,10 @@ QLayoutItem *QToolBarAreaLayout::itemAt(int *x, int index) const
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if ((*x)++ == index)
return line.toolBarItems.at(k).widgetItem;
}
@@ -754,10 +718,10 @@ QLayoutItem *QToolBarAreaLayout::takeAt(int *x, int index)
for (int i = 0; i < QInternal::DockCount; ++i) {
QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
QToolBarAreaLayoutLine &line = dock.lines[j];
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if ((*x)++ == index) {
QLayoutItem *result = line.toolBarItems.takeAt(k).widgetItem;
if (line.toolBarItems.isEmpty())
@@ -776,10 +740,10 @@ void QToolBarAreaLayout::deleteAllLayoutItems()
for (int i = 0; i < QInternal::DockCount; ++i) {
QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
QToolBarAreaLayoutLine &line = dock.lines[j];
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
QToolBarAreaLayoutItem &item = line.toolBarItems[k];
if (!item.gap)
delete item.widgetItem;
@@ -794,10 +758,10 @@ QInternal::DockPosition QToolBarAreaLayout::findToolBar(const QToolBar *toolBar)
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
return static_cast<QInternal::DockPosition>(i);
}
@@ -885,12 +849,12 @@ void QToolBarAreaLayout::apply(bool animate)
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
if (line.skip())
continue;
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
if (item.skip() || item.gap)
continue;
@@ -943,10 +907,10 @@ bool QToolBarAreaLayout::toolBarBreak(QToolBar *toolBar) const
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
return j > 0 && k == 0;
}
@@ -961,25 +925,25 @@ void QToolBarAreaLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBa
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
if (line.toolBarItems.at(k).widgetItem->widget() == toolBar) {
- if (line.toolBarItems.count() == 1)
+ if (line.toolBarItems.size() == 1)
option->positionWithinLine = QStyleOptionToolBar::OnlyOne;
else if (k == 0)
option->positionWithinLine = QStyleOptionToolBar::Beginning;
- else if (k == line.toolBarItems.count() - 1)
+ else if (k == line.toolBarItems.size() - 1)
option->positionWithinLine = QStyleOptionToolBar::End;
else
option->positionWithinLine = QStyleOptionToolBar::Middle;
- if (dock.lines.count() == 1)
+ if (dock.lines.size() == 1)
option->positionOfLine = QStyleOptionToolBar::OnlyOne;
else if (j == 0)
option->positionOfLine = QStyleOptionToolBar::Beginning;
- else if (j == dock.lines.count() - 1)
+ else if (j == dock.lines.size() - 1)
option->positionOfLine = QStyleOptionToolBar::End;
else
option->positionOfLine = QStyleOptionToolBar::Middle;
@@ -1000,10 +964,10 @@ QList<int> QToolBarAreaLayout::indexOf(QWidget *toolBar) const
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
if (!item.gap && item.widgetItem->widget() == toolBar) {
found = true;
@@ -1052,10 +1016,10 @@ QList<int> QToolBarAreaLayout::currentGapIndex() const
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines[j];
- for (int k = 0; k < line.toolBarItems.count(); k++) {
+ for (int k = 0; k < line.toolBarItems.size(); k++) {
if (line.toolBarItems[k].gap) {
QList<int> result;
result << i << j << k;
@@ -1069,7 +1033,7 @@ QList<int> QToolBarAreaLayout::currentGapIndex() const
bool QToolBarAreaLayout::insertGap(const QList<int> &path, QLayoutItem *item)
{
- Q_ASSERT(path.count() == 3);
+ Q_ASSERT(path.size() == 3);
const int i = path.first();
Q_ASSERT(i >= 0 && i < QInternal::DockCount);
return docks[i].insertGap(path.mid(1), item);
@@ -1077,7 +1041,7 @@ bool QToolBarAreaLayout::insertGap(const QList<int> &path, QLayoutItem *item)
void QToolBarAreaLayout::remove(const QList<int> &path)
{
- Q_ASSERT(path.count() == 3);
+ Q_ASSERT(path.size() == 3);
QToolBarAreaLayoutInfo &dock = docks[path.at(0)];
QToolBarAreaLayoutLine &line = dock.lines[path.at(1)];
line.toolBarItems.removeAt(path.at(2));
@@ -1090,10 +1054,10 @@ void QToolBarAreaLayout::remove(QLayoutItem *item)
for (int i = 0; i < QInternal::DockCount; ++i) {
QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
QToolBarAreaLayoutLine &line = dock.lines[j];
- for (int k = 0; k < line.toolBarItems.count(); k++) {
+ for (int k = 0; k < line.toolBarItems.size(); k++) {
if (line.toolBarItems[k].widgetItem == item) {
line.toolBarItems.removeAt(k);
if (line.toolBarItems.isEmpty())
@@ -1114,15 +1078,15 @@ void QToolBarAreaLayout::clear()
QToolBarAreaLayoutItem *QToolBarAreaLayout::item(const QList<int> &path)
{
- Q_ASSERT(path.count() == 3);
+ Q_ASSERT(path.size() == 3);
if (path.at(0) < 0 || path.at(0) >= QInternal::DockCount)
return nullptr;
QToolBarAreaLayoutInfo &info = docks[path.at(0)];
- if (path.at(1) < 0 || path.at(1) >= info.lines.count())
+ if (path.at(1) < 0 || path.at(1) >= info.lines.size())
return nullptr;
QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
- if (path.at(2) < 0 || path.at(2) >= line.toolBarItems.count())
+ if (path.at(2) < 0 || path.at(2) >= line.toolBarItems.size())
return nullptr;
return &(line.toolBarItems[path.at(2)]);
}
@@ -1154,7 +1118,7 @@ QLayoutItem *QToolBarAreaLayout::plug(const QList<int> &path)
QLayoutItem *QToolBarAreaLayout::unplug(const QList<int> &path, QToolBarAreaLayout *other)
{
//other needs to be update as well
- Q_ASSERT(path.count() == 3);
+ Q_ASSERT(path.size() == 3);
QToolBarAreaLayoutItem *item = this->item(path);
Q_ASSERT(item);
@@ -1172,7 +1136,7 @@ QLayoutItem *QToolBarAreaLayout::unplug(const QList<int> &path, QToolBarAreaLayo
if (!previous.skip()) {
//we need to check if it has a previous element and a next one
//the previous will get its size changed
- for (int j = path.at(2) + 1; j < line.toolBarItems.count(); ++j) {
+ for (int j = path.at(2) + 1; j < line.toolBarItems.size(); ++j) {
const QToolBarAreaLayoutItem &next = line.toolBarItems.at(j);
if (!next.skip()) {
newExtraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
@@ -1257,19 +1221,19 @@ void QToolBarAreaLayout::saveState(QDataStream &stream) const
int lineCount = 0;
for (int i = 0; i < QInternal::DockCount; ++i)
- lineCount += docks[i].lines.count();
+ lineCount += docks[i].lines.size();
stream << lineCount;
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
- for (int j = 0; j < dock.lines.count(); ++j) {
+ for (int j = 0; j < dock.lines.size(); ++j) {
const QToolBarAreaLayoutLine &line = dock.lines.at(j);
- stream << i << line.toolBarItems.count();
+ stream << i << int(line.toolBarItems.size());
- for (int k = 0; k < line.toolBarItems.count(); ++k) {
+ for (int k = 0; k < line.toolBarItems.size(); ++k) {
const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
QWidget *widget = const_cast<QLayoutItem*>(item.widgetItem)->widget();
QString objectName = widget->objectName();
@@ -1353,7 +1317,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*
}
QToolBar *toolBar = nullptr;
- for (int x = 0; x < toolBars.count(); ++x) {
+ for (int x = 0; x < toolBars.size(); ++x) {
if (toolBars.at(x)->objectName() == objectName) {
toolBar = toolBars.takeAt(x);
break;
@@ -1364,10 +1328,14 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*
}
if (applyingLayout) {
+ // Clear the previous widgetItem for the toolBar, so that it's
+ // assigned correctly in QWidgetItemV2 constructor.
+ auto *toolBarPrivate = QWidgetPrivate::get(toolBar);
+ toolBarPrivate->widgetItem = nullptr;
item.widgetItem = new QWidgetItemV2(toolBar);
toolBar->setOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
toolBar->setVisible(shown & 1);
- toolBar->d_func()->setWindowState(floating, true, rect);
+ toolBar->d_func()->setWindowState(floating, false, rect);
item.preferredSize = item.size;
line.toolBarItems.append(item);
diff --git a/src/widgets/widgets/qtoolbararealayout_p.h b/src/widgets/widgets/qtoolbararealayout_p.h
index 5df95a3038..4318f206f3 100644
--- a/src/widgets/widgets/qtoolbararealayout_p.h
+++ b/src/widgets/widgets/qtoolbararealayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLBARAREALAYOUT_P_H
#define QTOOLBARAREALAYOUT_P_H
@@ -112,7 +76,7 @@ Q_DECLARE_TYPEINFO(QToolBarAreaLayoutItem, Q_PRIMITIVE_TYPE);
class QToolBarAreaLayoutLine
{
public:
- QToolBarAreaLayoutLine() {} // for QVector, don't use
+ QToolBarAreaLayoutLine() { } // for QList, don't use
QToolBarAreaLayoutLine(Qt::Orientation orientation);
QSize sizeHint() const;
@@ -124,9 +88,9 @@ public:
QRect rect;
Qt::Orientation o;
- QVector<QToolBarAreaLayoutItem> toolBarItems;
+ QList<QToolBarAreaLayoutItem> toolBarItems;
};
-Q_DECLARE_TYPEINFO(QToolBarAreaLayoutLine, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QToolBarAreaLayoutLine, Q_RELOCATABLE_TYPE);
class QToolBarAreaLayoutInfo
{
@@ -151,13 +115,13 @@ public:
QRect itemRect(const QList<int> &path) const;
int distance(const QPoint &pos) const;
- QVector<QToolBarAreaLayoutLine> lines;
+ QList<QToolBarAreaLayoutLine> lines;
QRect rect;
Qt::Orientation o;
QInternal::DockPosition dockPos;
bool dirty;
};
-Q_DECLARE_TYPEINFO(QToolBarAreaLayoutInfo, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QToolBarAreaLayoutInfo, Q_RELOCATABLE_TYPE);
class QToolBarAreaLayout
{
diff --git a/src/widgets/widgets/qtoolbarextension.cpp b/src/widgets/widgets/qtoolbarextension.cpp
index bbe7eddaa4..350a900457 100644
--- a/src/widgets/widgets/qtoolbarextension.cpp
+++ b/src/widgets/widgets/qtoolbarextension.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtoolbarextension_p.h"
#include <qevent.h>
@@ -45,11 +9,13 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QToolBarExtension::QToolBarExtension(QWidget *parent)
: QToolButton(parent)
, m_orientation(Qt::Horizontal)
{
- setObjectName(QLatin1String("qt_toolbar_ext_button"));
+ setObjectName("qt_toolbar_ext_button"_L1);
setAutoRaise(true);
setOrientation(m_orientation);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
@@ -59,11 +25,11 @@ QToolBarExtension::QToolBarExtension(QWidget *parent)
void QToolBarExtension::setOrientation(Qt::Orientation o)
{
QStyleOption opt;
- opt.init(this);
+ opt.initFrom(this);
if (o == Qt::Horizontal) {
- setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton, &opt));
+ setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton, &opt, this));
} else {
- setIcon(style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton, &opt));
+ setIcon(style()->standardIcon(QStyle::SP_ToolBarVerticalExtensionButton, &opt, this));
}
m_orientation = o;
}
@@ -81,7 +47,9 @@ void QToolBarExtension::paintEvent(QPaintEvent *)
QSize QToolBarExtension::sizeHint() const
{
- int ext = style()->pixelMetric(QStyle::PM_ToolBarExtensionExtent);
+ QStyleOption opt;
+ opt.initFrom(this);
+ const int ext = style()->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, this);
return QSize(ext, ext);
}
diff --git a/src/widgets/widgets/qtoolbarextension_p.h b/src/widgets/widgets/qtoolbarextension_p.h
index 146e0e58c1..c2afd3fc62 100644
--- a/src/widgets/widgets/qtoolbarextension_p.h
+++ b/src/widgets/widgets/qtoolbarextension_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICTOOLBAREXTENSION_P_H
#define QDYNAMICTOOLBAREXTENSION_P_H
diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp
index 93aded6876..cc842e2657 100644
--- a/src/widgets/widgets/qtoolbarlayout.cpp
+++ b/src/widgets/widgets/qtoolbarlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qapplication.h>
#include <qaction.h>
@@ -48,7 +12,7 @@
#include <qmenu.h>
#include <qdebug.h>
#include <qmath.h>
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
#include <qpa/qplatformnativeinterface.h>
#endif
@@ -168,14 +132,14 @@ void QToolBarLayout::addItem(QLayoutItem*)
QLayoutItem *QToolBarLayout::itemAt(int index) const
{
- if (index < 0 || index >= items.count())
+ if (index < 0 || index >= items.size())
return nullptr;
return items.at(index);
}
QLayoutItem *QToolBarLayout::takeAt(int index)
{
- if (index < 0 || index >= items.count())
+ if (index < 0 || index >= items.size())
return nullptr;
QToolBarItem *item = items.takeAt(index);
@@ -198,7 +162,7 @@ QLayoutItem *QToolBarLayout::takeAt(int index)
void QToolBarLayout::insertAction(int index, QAction *action)
{
index = qMax(0, index);
- index = qMin(items.count(), index);
+ index = qMin(items.size(), index);
QToolBarItem *item = createItem(action);
if (item) {
@@ -207,9 +171,9 @@ void QToolBarLayout::insertAction(int index, QAction *action)
}
}
-int QToolBarLayout::indexOf(const QGuiAction *action) const
+int QToolBarLayout::indexOf(const QAction *action) const
{
- for (int i = 0; i < items.count(); ++i) {
+ for (int i = 0; i < items.size(); ++i) {
if (items.at(i)->action == action)
return i;
}
@@ -218,7 +182,7 @@ int QToolBarLayout::indexOf(const QGuiAction *action) const
int QToolBarLayout::count() const
{
- return items.count();
+ return items.size();
}
bool QToolBarLayout::isEmpty() const
@@ -282,10 +246,10 @@ void QToolBarLayout::updateGeomArray() const
that->expanding = false;
that->empty = false;
- QVector<QLayoutStruct> a(items.count() + 1); // + 1 for the stretch
+ QList<QLayoutStruct> a(items.size() + 1); // + 1 for the stretch
int count = 0;
- for (int i = 0; i < items.count(); ++i) {
+ for (int i = 0; i < items.size(); ++i) {
QToolBarItem *item = items.at(i);
QSize max = item->maximumSize();
@@ -332,7 +296,7 @@ void QToolBarLayout::updateGeomArray() const
rpick(o, that->minSize) += handleExtent;
that->minSize += QSize(pick(Qt::Horizontal, margins), pick(Qt::Vertical, margins));
- if (items.count() > 1)
+ if (items.size() > 1)
rpick(o, that->minSize) += spacing + extensionExtent;
rpick(o, that->hint) += handleExtent;
@@ -348,7 +312,7 @@ static bool defaultWidgetAction(QToolBarItem *item)
void QToolBarLayout::updateMacBorderMetrics()
{
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
if (!tb)
return;
@@ -460,15 +424,15 @@ bool QToolBarLayout::layoutActions(const QSize &size)
if (space <= 0)
return false; // nothing to do.
- if(popupMenu)
+ if (popupMenu)
popupMenu->clear();
bool ranOutOfSpace = false;
int rows = 0;
int rowPos = perp(o, rect.topLeft()) + perp(o, QSize(margins.top(), margins.left()));
int i = 0;
- while (i < items.count()) {
- QVector<QLayoutStruct> a = geomArray;
+ while (i < items.size()) {
+ QList<QLayoutStruct> a = geomArray;
int start = i;
int size = 0;
@@ -477,7 +441,7 @@ bool QToolBarLayout::layoutActions(const QSize &size)
int count = 0;
int maximumSize = 0;
bool expansiveRow = false;
- for (; i < items.count(); ++i) {
+ for (; i < items.size(); ++i) {
if (a[i].empty)
continue;
@@ -548,7 +512,7 @@ bool QToolBarLayout::layoutActions(const QSize &size)
}
if (!expanded) {
- for (int j = i; j < items.count(); ++j) {
+ for (int j = i; j < items.size(); ++j) {
QToolBarItem *item = items.at(j);
if (!item->widget()->isHidden())
hideWidgets << item->widget();
@@ -573,9 +537,9 @@ bool QToolBarLayout::layoutActions(const QSize &size)
extension->setEnabled(popupMenu == nullptr || !extensionMenuContainsOnlyWidgetActions);
// we have to do the show/hide here, because it triggers more calls to setGeometry :(
- for (int i = 0; i < showWidgets.count(); ++i)
+ for (int i = 0; i < showWidgets.size(); ++i)
showWidgets.at(i)->show();
- for (int i = 0; i < hideWidgets.count(); ++i)
+ for (int i = 0; i < hideWidgets.size(); ++i)
hideWidgets.at(i)->hide();
return ranOutOfSpace;
@@ -602,7 +566,7 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
int total_w = 0;
int count = 0;
- for (int x = 0; x < items.count(); ++x) {
+ for (int x = 0; x < items.size(); ++x) {
if (!geomArray[x].empty) {
total_w += (count == 0 ? 0 : spacing) + geomArray[x].minimumSize;
++count;
@@ -623,12 +587,12 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
int w = 0;
int h = 0;
int i = 0;
- while (i < items.count()) {
+ while (i < items.size()) {
int count = 0;
int size = 0;
int prev = -1;
int rowHeight = 0;
- for (; i < items.count(); ++i) {
+ for (; i < items.size(); ++i) {
if (geomArray[i].empty)
continue;
diff --git a/src/widgets/widgets/qtoolbarlayout_p.h b/src/widgets/widgets/qtoolbarlayout_p.h
index 1a406a3d29..a7d3810d61 100644
--- a/src/widgets/widgets/qtoolbarlayout_p.h
+++ b/src/widgets/widgets/qtoolbarlayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLBARLAYOUT_P_H
#define QTOOLBARLAYOUT_P_H
@@ -54,7 +18,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtWidgets/qlayout.h>
#include <private/qlayoutengine_p.h>
-#include <QVector>
+#include <QList>
QT_REQUIRE_CONFIG(toolbar);
@@ -96,7 +60,7 @@ public:
QSize sizeHint() const override;
void insertAction(int index, QAction *action);
- int indexOf(const QGuiAction *action) const;
+ int indexOf(const QAction *action) const;
using QLayout::indexOf; // bring back the hidden members
bool layoutActions(const QSize &size);
@@ -118,7 +82,7 @@ private:
QList<QToolBarItem*> items;
QSize hint, minSize;
bool dirty, expanding, empty, expandFlag;
- QVector<QLayoutStruct> geomArray;
+ QList<QLayoutStruct> geomArray;
QRect handRect;
QToolBarExtension *extension;
diff --git a/src/widgets/widgets/qtoolbarseparator.cpp b/src/widgets/widgets/qtoolbarseparator.cpp
index 92cd08317a..0e70c21361 100644
--- a/src/widgets/widgets/qtoolbarseparator.cpp
+++ b/src/widgets/widgets/qtoolbarseparator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtoolbarseparator_p.h"
diff --git a/src/widgets/widgets/qtoolbarseparator_p.h b/src/widgets/widgets/qtoolbarseparator_p.h
index 60b51a28cb..d43c241015 100644
--- a/src/widgets/widgets/qtoolbarseparator_p.h
+++ b/src/widgets/widgets/qtoolbarseparator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDYNAMICTOOLBARSEPARATOR_P_H
#define QDYNAMICTOOLBARSEPARATOR_P_H
diff --git a/src/widgets/widgets/qtoolbox.cpp b/src/widgets/widgets/qtoolbox.cpp
index 4767394842..e0fac9be0f 100644
--- a/src/widgets/widgets/qtoolbox.cpp
+++ b/src/widgets/widgets/qtoolbox.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtoolbox.h"
@@ -47,15 +11,17 @@
#include <qscrollarea.h>
#include <qstyle.h>
#include <qstyleoption.h>
+#if QT_CONFIG(tooltip)
#include <qtooltip.h>
+#endif
#include <qabstractbutton.h>
-#include <private/qmemory_p.h>
-
#include "qframe_p.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QToolBoxButton : public QAbstractButton
{
Q_OBJECT
@@ -96,7 +62,7 @@ public:
inline void setText(const QString &text) { button->setText(text); }
inline void setIcon(const QIcon &is) { button->setIcon(is); }
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
inline void setToolTip(const QString &tip) { button->setToolTip(tip); }
inline QString toolTip() const { return button->toolTip(); }
#endif
@@ -189,8 +155,7 @@ QSize QToolBoxButton::sizeHint() const
}
QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text()) + QSize(0, 8);
- QSize total(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height()));
- return total.expandedTo(QApplication::globalStrut());
+ return QSize(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height()));
}
QSize QToolBoxButton::minimumSizeHint() const
@@ -348,11 +313,11 @@ int QToolBox::insertItem(int index, QWidget *widget, const QIcon &icon, const QS
Q_D(QToolBox);
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(_q_widgetDestroyed(QObject*)));
- auto newPage = qt_make_unique<QToolBoxPrivate::Page>();
+ auto newPage = std::make_unique<QToolBoxPrivate::Page>();
auto &c = *newPage;
c.widget = widget;
c.button = new QToolBoxButton(this);
- c.button->setObjectName(QLatin1String("qt_toolbox_toolboxbutton"));
+ c.button->setObjectName("qt_toolbox_toolboxbutton"_L1);
connect(c.button, SIGNAL(clicked()), this, SLOT(_q_buttonClicked()));
c.sv = new QScrollArea(this);
@@ -559,7 +524,7 @@ QWidget *QToolBox::widget(int index) const
exist.
*/
-int QToolBox::indexOf(QWidget *widget) const
+int QToolBox::indexOf(const QWidget *widget) const
{
Q_D(const QToolBox);
const QToolBoxPrivate::Page *c = (widget ? d->page(widget) : nullptr);
@@ -639,7 +604,7 @@ void QToolBox::setItemIcon(int index, const QIcon &icon)
c->setIcon(icon);
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
/*!
Sets the tooltip of the item at position \a index to \a toolTip.
*/
@@ -651,7 +616,7 @@ void QToolBox::setItemToolTip(int index, const QString &toolTip)
if (c)
c->setToolTip(toolTip);
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
/*!
Returns \c true if the item at position \a index is enabled; otherwise returns \c false.
@@ -688,7 +653,7 @@ QIcon QToolBox::itemIcon(int index) const
return (c ? c->icon() : QIcon());
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
/*!
Returns the tooltip of the item at position \a index, or an
empty string if \a index is out of range.
@@ -700,7 +665,7 @@ QString QToolBox::itemToolTip(int index) const
const QToolBoxPrivate::Page *c = d->page(index);
return (c ? c->toolTip() : QString());
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
/*! \reimp */
void QToolBox::showEvent(QShowEvent *e)
@@ -712,7 +677,7 @@ void QToolBox::showEvent(QShowEvent *e)
void QToolBox::changeEvent(QEvent *ev)
{
Q_D(QToolBox);
- if(ev->type() == QEvent::StyleChange)
+ if (ev->type() == QEvent::StyleChange)
d->updateTabs();
QFrame::changeEvent(ev);
}
@@ -725,7 +690,7 @@ void QToolBox::changeEvent(QEvent *ev)
*/
void QToolBox::itemInserted(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*!
@@ -736,7 +701,7 @@ void QToolBox::itemInserted(int index)
*/
void QToolBox::itemRemoved(int index)
{
- Q_UNUSED(index)
+ Q_UNUSED(index);
}
/*! \reimp */
diff --git a/src/widgets/widgets/qtoolbox.h b/src/widgets/widgets/qtoolbox.h
index 2796631b94..a295dad2fd 100644
--- a/src/widgets/widgets/qtoolbox.h
+++ b/src/widgets/widgets/qtoolbox.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLBOX_H
#define QTOOLBOX_H
@@ -76,7 +40,7 @@ public:
void setItemIcon(int index, const QIcon &icon);
QIcon itemIcon(int index) const;
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
void setItemToolTip(int index, const QString &toolTip);
QString itemToolTip(int index) const;
#endif
@@ -84,7 +48,7 @@ public:
int currentIndex() const;
QWidget *currentWidget() const;
QWidget *widget(int index) const;
- int indexOf(QWidget *widget) const;
+ int indexOf(const QWidget *widget) const;
int count() const;
public Q_SLOTS:
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 127960b23c..e0775afd26 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -1,47 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtoolbutton.h"
#include <qapplication.h>
-#include <qdesktopwidget.h>
-#include <private/qdesktopwidget_p.h>
#include <qdrawutil.h>
#include <qevent.h>
#include <qicon.h>
@@ -49,7 +11,9 @@
#include <qpointer.h>
#include <qstyle.h>
#include <qstyleoption.h>
+#if QT_CONFIG(tooltip)
#include <qtooltip.h>
+#endif
#if QT_CONFIG(mainwindow)
#include <qmainwindow.h>
#endif
@@ -67,20 +31,22 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QToolButtonPrivate : public QAbstractButtonPrivate
{
Q_DECLARE_PUBLIC(QToolButton)
public:
void init();
#if QT_CONFIG(menu)
- void _q_buttonPressed();
- void _q_buttonReleased();
+ void onButtonPressed();
+ void onButtonReleased();
void popupTimerDone();
- void _q_updateButtonDown();
- void _q_menuTriggered(QAction *);
+ void updateButtonDown();
+ void onMenuTriggered(QAction *);
#endif
bool updateHoverControl(const QPoint &pos);
- void _q_actionTriggered();
+ void onActionTriggered();
QStyle::SubControl newHoverControl(const QPoint &pos);
QStyle::SubControl hoverControl;
QRect hoverRect;
@@ -169,8 +135,7 @@ bool QToolButtonPrivate::hasMenu() const
with actions used in other parts of the main window.
\endtable
- \sa QPushButton, QToolBar, QMainWindow, QAction,
- {fowler}{GUI Design Handbook: Push Button}
+ \sa QPushButton, QToolBar, QMainWindow, QAction
*/
/*!
@@ -222,8 +187,10 @@ void QToolButtonPrivate::init()
QSizePolicy::ToolButton));
#if QT_CONFIG(menu)
- QObject::connect(q, SIGNAL(pressed()), q, SLOT(_q_buttonPressed()));
- QObject::connect(q, SIGNAL(released()), q, SLOT(_q_buttonReleased()));
+ QObjectPrivate::connect(q, &QAbstractButton::pressed,
+ this, &QToolButtonPrivate::onButtonPressed);
+ QObjectPrivate::connect(q, &QAbstractButton::released,
+ this, &QToolButtonPrivate::onButtonReleased);
#endif
setLayoutItemMargins(QStyle::SE_ToolButtonLayoutItem);
@@ -244,7 +211,6 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
Q_D(const QToolButton);
option->initFrom(this);
- bool forceNoText = false;
option->iconSize = iconSize(); //default value
#if QT_CONFIG(toolbar)
@@ -255,8 +221,7 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
}
#endif // QT_CONFIG(toolbar)
- if (!forceNoText)
- option->text = d->text;
+ option->text = d->text;
option->icon = d->icon;
option->arrowType = d->arrowType;
if (d->down)
@@ -308,7 +273,7 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
option->toolButtonStyle = Qt::ToolButtonIconOnly;
}
- if (d->icon.isNull() && d->arrowType == Qt::NoArrow && !forceNoText) {
+ if (d->icon.isNull() && d->arrowType == Qt::NoArrow) {
if (!d->text.isEmpty())
option->toolButtonStyle = Qt::ToolButtonTextOnly;
else if (option->toolButtonStyle != Qt::ToolButtonTextOnly)
@@ -350,7 +315,7 @@ QSize QToolButton::sizeHint() const
if (opt.toolButtonStyle != Qt::ToolButtonIconOnly) {
QSize textSize = fm.size(Qt::TextShowMnemonic, text());
- textSize.setWidth(textSize.width() + fm.horizontalAdvance(QLatin1Char(' '))*2);
+ textSize.setWidth(textSize.width() + fm.horizontalAdvance(u' ') * 2);
if (opt.toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
h += 4 + textSize.height();
if (textSize.width() > w)
@@ -369,8 +334,7 @@ QSize QToolButton::sizeHint() const
if (d->popupMode == MenuButtonPopup)
w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
- d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this).
- expandedTo(QApplication::globalStrut());
+ d->sizeHint = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this);
return d->sizeHint;
}
@@ -473,7 +437,8 @@ void QToolButton::actionEvent(QActionEvent *event)
setDefaultAction(action); // update button state
break;
case QEvent::ActionAdded:
- connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+ QObjectPrivate::connect(action, &QAction::triggered, d,
+ &QToolButtonPrivate::onActionTriggered);
break;
case QEvent::ActionRemoved:
if (d->defaultAction == action)
@@ -518,7 +483,7 @@ bool QToolButtonPrivate::updateHoverControl(const QPoint &pos)
return !doesHover;
}
-void QToolButtonPrivate::_q_actionTriggered()
+void QToolButtonPrivate::onActionTriggered()
{
Q_Q(QToolButton);
if (QAction *action = qobject_cast<QAction *>(q->sender()))
@@ -528,7 +493,7 @@ void QToolButtonPrivate::_q_actionTriggered()
/*!
\reimp
*/
-void QToolButton::enterEvent(QEvent * e)
+void QToolButton::enterEvent(QEnterEvent * e)
{
Q_D(QToolButton);
if (d->autoRaise)
@@ -602,7 +567,7 @@ void QToolButton::mousePressEvent(QMouseEvent *e)
if (e->button() == Qt::LeftButton && (d->popupMode == MenuButtonPopup)) {
QRect popupr = style()->subControlRect(QStyle::CC_ToolButton, &opt,
QStyle::SC_ToolButtonMenu, this);
- if (popupr.isValid() && popupr.contains(e->pos())) {
+ if (popupr.isValid() && popupr.contains(e->position().toPoint())) {
d->buttonPressed = QToolButtonPrivate::MenuButtonPressed;
showMenu();
return;
@@ -619,8 +584,10 @@ void QToolButton::mousePressEvent(QMouseEvent *e)
void QToolButton::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QToolButton);
+ QPointer<QAbstractButton> guard(this);
QAbstractButton::mouseReleaseEvent(e);
- d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
+ if (guard)
+ d->buttonPressed = QToolButtonPrivate::NoButtonPressed;
}
/*!
@@ -629,7 +596,7 @@ void QToolButton::mouseReleaseEvent(QMouseEvent *e)
bool QToolButton::hitButton(const QPoint &pos) const
{
Q_D(const QToolButton);
- if(QAbstractButton::hitButton(pos))
+ if (QAbstractButton::hitButton(pos))
return (d->buttonPressed != QToolButtonPrivate::MenuButtonPressed);
return false;
}
@@ -705,7 +672,7 @@ void QToolButton::showMenu()
d->popupTimerDone();
}
-void QToolButtonPrivate::_q_buttonPressed()
+void QToolButtonPrivate::onButtonPressed()
{
Q_Q(QToolButton);
if (!hasMenu())
@@ -718,43 +685,17 @@ void QToolButtonPrivate::_q_buttonPressed()
q->showMenu();
}
-void QToolButtonPrivate::_q_buttonReleased()
+void QToolButtonPrivate::onButtonReleased()
{
popupTimer.stop();
}
-void QToolButtonPrivate::popupTimerDone()
+static QPoint positionMenu(const QToolButton *q, bool horizontal,
+ const QSize &sh)
{
- Q_Q(QToolButton);
- popupTimer.stop();
- if (!menuButtonDown && !down)
- return;
-
- menuButtonDown = true;
- QPointer<QMenu> actualMenu;
- bool mustDeleteActualMenu = false;
- if(menuAction) {
- actualMenu = menuAction->menu();
- } else if (defaultAction && defaultAction->menu()) {
- actualMenu = defaultAction->menu();
- } else {
- actualMenu = new QMenu(q);
- mustDeleteActualMenu = true;
- for(int i = 0; i < actions.size(); i++)
- actualMenu->addAction(actions.at(i));
- }
- repeat = q->autoRepeat();
- q->setAutoRepeat(false);
- bool horizontal = true;
-#if QT_CONFIG(toolbar)
- QToolBar *tb = qobject_cast<QToolBar*>(parent);
- if (tb && tb->orientation() == Qt::Vertical)
- horizontal = false;
-#endif
QPoint p;
const QRect rect = q->rect(); // Find screen via point in case of QGraphicsProxyWidget.
- QRect screen = QDesktopWidgetPrivate::availableGeometry(q->mapToGlobal(rect.center()));
- QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
+ const QRect screen = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
if (horizontal) {
if (q->isRightToLeft()) {
if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.bottom()) {
@@ -786,26 +727,73 @@ void QToolButtonPrivate::popupTimerDone()
}
}
}
+
+ // QTBUG-118695 Force point inside the current screen. If the returned point
+ // is not found inside any screen, QMenu's positioning logic kicks in without
+ // taking the QToolButton's screen into account. This can cause the menu to
+ // end up on primary monitor, even if the QToolButton is on a non-primary monitor.
p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width()));
- p.ry() += 1;
+ p.ry() = qMax(screen.top(), qMin(p.y() + 1, screen.bottom()));
+ return p;
+}
+
+void QToolButtonPrivate::popupTimerDone()
+{
+ Q_Q(QToolButton);
+ popupTimer.stop();
+ if (!menuButtonDown && !down)
+ return;
+
+ menuButtonDown = true;
+ QPointer<QMenu> actualMenu;
+ bool mustDeleteActualMenu = false;
+ if (menuAction) {
+ actualMenu = menuAction->menu();
+ } else if (defaultAction && defaultAction->menu()) {
+ actualMenu = defaultAction->menu();
+ } else {
+ actualMenu = new QMenu(q);
+ mustDeleteActualMenu = true;
+ for (int i = 0; i < actions.size(); i++)
+ actualMenu->addAction(actions.at(i));
+ }
+ repeat = q->autoRepeat();
+ q->setAutoRepeat(false);
+ bool horizontal = true;
+#if QT_CONFIG(toolbar)
+ QToolBar *tb = qobject_cast<QToolBar*>(parent);
+ if (tb && tb->orientation() == Qt::Vertical)
+ horizontal = false;
+#endif
QPointer<QToolButton> that = q;
actualMenu->setNoReplayFor(q);
- if (!mustDeleteActualMenu) //only if action are not in this widget
- QObject::connect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
- QObject::connect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
+ if (!mustDeleteActualMenu) { //only if action are not in this widget
+ QObjectPrivate::connect(actualMenu, &QMenu::triggered,
+ this, &QToolButtonPrivate::onMenuTriggered);
+ }
+ QObjectPrivate::connect(actualMenu, &QMenu::aboutToHide,
+ this, &QToolButtonPrivate::updateButtonDown);
actualMenu->d_func()->causedPopup.widget = q;
actualMenu->d_func()->causedPopup.action = defaultAction;
actionsCopy = q->actions(); //(the list of action may be modified in slots)
- actualMenu->exec(p);
+
+ // QTBUG-78966, Delay positioning until after aboutToShow().
+ auto positionFunction = [q, horizontal](const QSize &sizeHint) {
+ return positionMenu(q, horizontal, sizeHint); };
+ const auto initialPos = positionFunction(actualMenu->sizeHint());
+ actualMenu->d_func()->exec(initialPos, nullptr, positionFunction);
if (!that)
return;
- QObject::disconnect(actualMenu, SIGNAL(aboutToHide()), q, SLOT(_q_updateButtonDown()));
- if (mustDeleteActualMenu)
+ QObjectPrivate::disconnect(actualMenu, &QMenu::aboutToHide,
+ this, &QToolButtonPrivate::updateButtonDown);
+ if (mustDeleteActualMenu) {
delete actualMenu;
- else
- QObject::disconnect(actualMenu, SIGNAL(triggered(QAction*)), q, SLOT(_q_menuTriggered(QAction*)));
+ } else {
+ QObjectPrivate::disconnect(actualMenu, &QMenu::triggered,
+ this, &QToolButtonPrivate::onMenuTriggered);
+ }
actionsCopy.clear();
@@ -813,7 +801,7 @@ void QToolButtonPrivate::popupTimerDone()
q->setAutoRepeat(true);
}
-void QToolButtonPrivate::_q_updateButtonDown()
+void QToolButtonPrivate::updateButtonDown()
{
Q_Q(QToolButton);
menuButtonDown = false;
@@ -823,7 +811,7 @@ void QToolButtonPrivate::_q_updateButtonDown()
q->repaint();
}
-void QToolButtonPrivate::_q_menuTriggered(QAction *action)
+void QToolButtonPrivate::onMenuTriggered(QAction *action)
{
Q_Q(QToolButton);
if (action && !actionsCopy.contains(action))
@@ -933,10 +921,10 @@ void QToolButton::setDefaultAction(QAction *action)
// If iconText() is generated from text(), we need to escape any '&'s so they
// don't turn into shortcuts
if (QActionPrivate::get(action)->iconText.isEmpty())
- buttonText.replace(QLatin1String("&"), QLatin1String("&&"));
+ buttonText.replace("&"_L1, "&&"_L1);
setText(buttonText);
setIcon(action->icon());
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
setToolTip(action->toolTip());
#endif
#if QT_CONFIG(statustip)
@@ -972,7 +960,15 @@ QAction *QToolButton::defaultAction() const
return d->defaultAction;
}
-
+/*!
+ \reimp
+ */
+void QToolButton::checkStateSet()
+{
+ Q_D(QToolButton);
+ if (d->defaultAction && d->defaultAction->isCheckable())
+ d->defaultAction->setChecked(isChecked());
+}
/*!
\reimp
@@ -994,7 +990,7 @@ bool QToolButton::event(QEvent *event)
case QEvent::HoverLeave:
case QEvent::HoverMove:
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
- d_func()->updateHoverControl(he->pos());
+ d_func()->updateHoverControl(he->position().toPoint());
break;
default:
break;
diff --git a/src/widgets/widgets/qtoolbutton.h b/src/widgets/widgets/qtoolbutton.h
index 52bd2d5f7a..72429620ad 100644
--- a/src/widgets/widgets/qtoolbutton.h
+++ b/src/widgets/widgets/qtoolbutton.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLBUTTON_H
#define QTOOLBUTTON_H
@@ -112,26 +76,19 @@ protected:
void paintEvent(QPaintEvent *) override;
void actionEvent(QActionEvent *) override;
- void enterEvent(QEvent *) override;
+ void enterEvent(QEnterEvent *) override;
void leaveEvent(QEvent *) override;
void timerEvent(QTimerEvent *) override;
void changeEvent(QEvent *) override;
bool hitButton(const QPoint &pos) const override;
+ void checkStateSet() override;
void nextCheckState() override;
- void initStyleOption(QStyleOptionToolButton *option) const;
+ virtual void initStyleOption(QStyleOptionToolButton *option) const;
private:
Q_DISABLE_COPY(QToolButton)
Q_DECLARE_PRIVATE(QToolButton)
-#if QT_CONFIG(menu)
- Q_PRIVATE_SLOT(d_func(), void _q_buttonPressed())
- Q_PRIVATE_SLOT(d_func(), void _q_buttonReleased())
- Q_PRIVATE_SLOT(d_func(), void _q_updateButtonDown())
- Q_PRIVATE_SLOT(d_func(), void _q_menuTriggered(QAction*))
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
-
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qwidgetanimator.cpp b/src/widgets/widgets/qwidgetanimator.cpp
index cec6ba1dea..d45215dee3 100644
--- a/src/widgets/widgets/qwidgetanimator.cpp
+++ b/src/widgets/widgets/qwidgetanimator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwidgetanimator_p.h"
@@ -55,7 +19,7 @@ QWidgetAnimator::QWidgetAnimator(QMainWindowLayout *layout)
: m_mainWindowLayout(layout)
#endif
{
- Q_UNUSED(layout)
+ Q_UNUSED(layout);
}
void QWidgetAnimator::abort(QWidget *w)
@@ -93,7 +57,7 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
animate = animate && !r.isNull() && !_final_geometry.isNull();
- // might make the wigdet go away by sending it to negative space
+ // might make the widget go away by sending it to negative space
const QRect final_geometry = _final_geometry.isValid() || widget->isWindow() ? _final_geometry :
QRect(QPoint(-500 - widget->width(), -500 - widget->height()), widget->size());
@@ -109,7 +73,8 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->setEndValue(final_geometry);
m_animation_map[widget] = anim;
- connect(anim, SIGNAL(finished()), SLOT(animationFinished()));
+ connect(anim, &QPropertyAnimation::finished,
+ this, &QWidgetAnimator::animationFinished);
anim->start(QPropertyAnimation::DeleteWhenStopped);
} else
#endif // animation
diff --git a/src/widgets/widgets/qwidgetanimator_p.h b/src/widgets/widgets/qwidgetanimator_p.h
index 9d08d03593..c7af3855b0 100644
--- a/src/widgets/widgets/qwidgetanimator_p.h
+++ b/src/widgets/widgets/qwidgetanimator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGET_ANIMATOR_P_H
#define QWIDGET_ANIMATOR_P_H
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 9dd61c2c6a..ce1b8706ae 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwidgetlinecontrol_p.h"
@@ -49,7 +13,7 @@
#endif
#include <qpa/qplatformtheme.h>
#include <qstylehints.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
@@ -98,7 +62,7 @@ void QWidgetLineControl::updateDisplayText(bool forceUpdate)
if (m_echoMode == QLineEdit::Password) {
str.fill(m_passwordCharacter);
- if (m_passwordEchoTimer != 0 && m_cursor > 0 && m_cursor <= m_text.length()) {
+ if (m_passwordEchoTimer != 0 && m_cursor > 0 && m_cursor <= m_text.size()) {
int cursor = m_cursor - 1;
QChar uc = m_text.at(cursor);
str[cursor] = uc;
@@ -118,11 +82,10 @@ void QWidgetLineControl::updateDisplayText(bool forceUpdate)
// drawing boxes when using fonts that don't have glyphs for such
// characters)
QChar* uc = str.data();
- for (int i = 0; i < (int)str.length(); ++i) {
+ for (int i = 0; i < (int)str.size(); ++i) {
if ((uc[i].unicode() < 0x20 && uc[i].unicode() != 0x09)
|| uc[i] == QChar::LineSeparator
- || uc[i] == QChar::ParagraphSeparator
- || uc[i] == QChar::ObjectReplacementCharacter)
+ || uc[i] == QChar::ParagraphSeparator)
uc[i] = QChar(0x0020);
}
@@ -278,7 +241,7 @@ void QWidgetLineControl::clear()
{
int priorState = m_undoState;
m_selstart = 0;
- m_selend = m_text.length();
+ m_selend = m_text.size();
removeSelectedText();
separate();
finishChange(priorState, /*update*/false, /*edited*/false);
@@ -322,7 +285,7 @@ void QWidgetLineControl::setSelection(int start, int length)
if (start == m_selstart && start + length == m_selend && m_cursor == m_selend)
return;
m_selstart = start;
- m_selend = qMin(start + length, (int)m_text.length());
+ m_selend = qMin(start + length, (int)m_text.size());
m_cursor = m_selend;
} else if (length < 0){
if (start == m_selend && start + length == m_selstart && m_cursor == m_selstart)
@@ -365,7 +328,7 @@ void QWidgetLineControl::init(const QString &txt)
m_textLayout.setCacheEnabled(true);
m_text = txt;
updateDisplayText();
- m_cursor = m_text.length();
+ m_cursor = m_text.size();
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
m_keyboardScheme = theme->themeHint(QPlatformTheme::KeyboardScheme).toInt();
m_passwordMaskDelay = theme->themeHint(QPlatformTheme::PasswordMaskDelay).toInt();
@@ -419,7 +382,7 @@ QRect QWidgetLineControl::rectForPos(int pos) const
int w = m_cursorWidth;
int ch = l.height() + 1;
- return QRect(cix-5, 0, w+9, ch);
+ return QRect(cix - 5, 0, w + 9, ch);
}
/*!
@@ -527,14 +490,14 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing()) {
updatePasswordEchoEditing(true);
m_selstart = 0;
- m_selend = m_text.length();
+ m_selend = m_text.size();
}
removeSelectedText();
}
int c = m_cursor; // cursor position after insertion of commit string
if (event->replacementStart() <= 0)
- c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength());
+ c += event->commitString().size() - qMin(-event->replacementStart(), event->replacementLength());
m_cursor += event->replacementStart();
if (m_cursor < 0)
@@ -550,15 +513,15 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
internalInsert(event->commitString());
cursorPositionChanged = true;
} else {
- m_cursor = qBound(0, c, m_text.length());
+ m_cursor = qBound(0, c, m_text.size());
}
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
if (a.type == QInputMethodEvent::Selection) {
- m_cursor = qBound(0, a.start + a.length, m_text.length());
+ m_cursor = qBound(0, a.start + a.length, m_text.size());
if (a.length) {
- m_selstart = qMax(0, qMin(a.start, m_text.length()));
+ m_selstart = qMax(0, qMin(a.start, m_text.size()));
m_selend = m_cursor;
if (m_selend < m_selstart) {
qSwap(m_selstart, m_selend);
@@ -573,12 +536,26 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
}
}
#ifndef QT_NO_IM
- setPreeditArea(m_cursor, event->preeditString());
+ // in NoEcho mode, the cursor is always at the beginning of the lineedit
+ switch (m_echoMode) {
+ case QLineEdit::NoEcho:
+ setPreeditArea(0, QString());
+ break;
+ case QLineEdit::Password: {
+ QString preeditString = event->preeditString();
+ preeditString.fill(m_passwordCharacter);
+ setPreeditArea(m_cursor, preeditString);
+ break;
+ }
+ default:
+ setPreeditArea(m_cursor, event->preeditString());
+ break;
+ }
#endif //QT_NO_IM
const int oldPreeditCursor = m_preeditCursor;
- m_preeditCursor = event->preeditString().length();
+ m_preeditCursor = event->preeditString().size();
m_hideCursor = false;
- QVector<QTextLayout::FormatRange> formats;
+ QList<QTextLayout::FormatRange> formats;
formats.reserve(event->attributes().size());
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
@@ -627,7 +604,7 @@ void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
*/
void QWidgetLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags)
{
- QVector<QTextLayout::FormatRange> selections;
+ QList<QTextLayout::FormatRange> selections;
if (flags & DrawSelections) {
QTextLayout::FormatRange o;
if (m_selstart < m_selend) {
@@ -669,7 +646,7 @@ void QWidgetLineControl::draw(QPainter *painter, const QPoint &offset, const QRe
void QWidgetLineControl::selectWordAtPos(int cursor)
{
int next = cursor + 1;
- if(next > end())
+ if (next > end())
--next;
int c = textLayout()->previousCursorPosition(next, QTextLayout::SkipWords);
moveCursor(c, false);
@@ -694,7 +671,7 @@ void QWidgetLineControl::selectWordAtPos(int cursor)
*/
bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool edited)
{
- Q_UNUSED(update)
+ Q_UNUSED(update);
if (m_textDirty) {
// do validation
@@ -717,7 +694,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e
}
#endif
if (validateFromState >= 0 && wasValidInput && !m_validInput) {
- if (m_transactions.count())
+ if (m_transactions.size())
return false;
internalUndo(validateFromState);
m_history.erase(m_history.begin() + m_undoState, m_history.end());
@@ -741,7 +718,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e
emit selectionChanged();
}
if (m_cursor == m_lastCursorPos)
- updateMicroFocus();
+ emit updateMicroFocus();
emitCursorPositionChanged();
return true;
}
@@ -759,7 +736,7 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
QString oldText = m_text;
if (m_maskData) {
m_text = maskString(0, txt, true);
- m_text += clearString(m_text.length(), m_maxLength - m_text.length());
+ m_text += clearString(m_text.size(), m_maxLength - m_text.size());
if (edited && oldText == m_text)
emit inputRejected();
} else {
@@ -767,11 +744,11 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
}
m_history.clear();
m_modifiedState = m_undoState = 0;
- m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
+ m_cursor = (pos < 0 || pos > m_text.size()) ? m_text.size() : pos;
m_textDirty = (oldText != m_text);
const bool changed = finishChange(-1, true, edited);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (changed) {
if (oldText.isEmpty()) {
QAccessibleTextInsertEvent event(accessibleObject(), 0, txt);
@@ -788,7 +765,7 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
}
}
#else
- Q_UNUSED(changed)
+ Q_UNUSED(changed);
#endif
}
@@ -804,7 +781,7 @@ void QWidgetLineControl::addCommand(const Command &cmd)
m_history.erase(m_history.begin() + m_undoState, m_history.end());
if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator)
- m_history.push_back(Command(Separator, m_cursor, 0, m_selstart, m_selend));
+ m_history.push_back(Command(Separator, m_cursor, u'\0', m_selstart, m_selend));
m_separator = false;
m_history.push_back(cmd);
@@ -836,40 +813,40 @@ void QWidgetLineControl::internalInsert(const QString &s)
m_passwordEchoTimer = startTimer(delay);
}
if (hasSelectedText())
- addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ addCommand(Command(SetSelection, m_cursor, u'\0', m_selstart, m_selend));
if (m_maskData) {
QString ms = maskString(m_cursor, s);
if (ms.isEmpty() && !s.isEmpty())
emit inputRejected();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextInsertEvent insertEvent(accessibleObject(), m_cursor, ms);
QAccessible::updateAccessibility(&insertEvent);
#endif
- for (int i = 0; i < (int) ms.length(); ++i) {
+ for (int i = 0; i < (int) ms.size(); ++i) {
addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
}
- m_text.replace(m_cursor, ms.length(), ms);
- m_cursor += ms.length();
+ m_text.replace(m_cursor, ms.size(), ms);
+ m_cursor += ms.size();
m_cursor = nextMaskBlank(m_cursor);
m_textDirty = true;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextCursorEvent event(accessibleObject(), m_cursor);
QAccessible::updateAccessibility(&event);
#endif
} else {
- int remaining = m_maxLength - m_text.length();
+ int remaining = m_maxLength - m_text.size();
if (remaining != 0) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextInsertEvent insertEvent(accessibleObject(), m_cursor, s);
QAccessible::updateAccessibility(&insertEvent);
#endif
m_text.insert(m_cursor, s.left(remaining));
- for (int i = 0; i < (int) s.left(remaining).length(); ++i)
+ for (int i = 0; i < (int) s.left(remaining).size(); ++i)
addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
m_textDirty = true;
}
- if (s.length() > remaining)
+ if (s.size() > remaining)
emit inputRejected();
}
}
@@ -887,13 +864,13 @@ void QWidgetLineControl::internalInsert(const QString &s)
*/
void QWidgetLineControl::internalDelete(bool wasBackspace)
{
- if (m_cursor < (int) m_text.length()) {
+ if (m_cursor < (int) m_text.size()) {
cancelPasswordEchoTimer();
if (hasSelectedText())
- addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ addCommand(Command(SetSelection, m_cursor, u'\0', m_selstart, m_selend));
addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
m_cursor, m_text.at(m_cursor), -1, -1));
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextRemoveEvent event(accessibleObject(), m_cursor, m_text.at(m_cursor));
QAccessible::updateAccessibility(&event);
#endif
@@ -918,11 +895,11 @@ void QWidgetLineControl::internalDelete(bool wasBackspace)
*/
void QWidgetLineControl::removeSelectedText()
{
- if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
+ if (m_selstart < m_selend && m_selend <= (int) m_text.size()) {
cancelPasswordEchoTimer();
separate();
int i ;
- addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
+ addCommand(Command(SetSelection, m_cursor, u'\0', m_selstart, m_selend));
if (m_selstart <= m_cursor && m_cursor < m_selend) {
// cursor is within the selection. Split up the commands
// to be able to restore the correct cursor position
@@ -934,7 +911,7 @@ void QWidgetLineControl::removeSelectedText()
for (i = m_selend-1; i >= m_selstart; --i)
addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleTextRemoveEvent event(accessibleObject(), m_selstart, m_text.mid(m_selstart, m_selend - m_selstart));
QAccessible::updateAccessibility(&event);
#endif
@@ -960,11 +937,10 @@ void QWidgetLineControl::removeSelectedText()
*/
void QWidgetLineControl::parseInputMask(const QString &maskFields)
{
- int delimiter = maskFields.indexOf(QLatin1Char(';'));
+ qsizetype delimiter = maskFields.indexOf(u';');
if (maskFields.isEmpty() || delimiter == 0) {
if (m_maskData) {
- delete [] m_maskData;
- m_maskData = nullptr;
+ m_maskData.reset();
m_maxLength = 32767;
internalSetText(QString(), -1, false);
}
@@ -972,47 +948,42 @@ void QWidgetLineControl::parseInputMask(const QString &maskFields)
}
if (delimiter == -1) {
- m_blank = QLatin1Char(' ');
+ m_blank = u' ';
m_inputMask = maskFields;
} else {
m_inputMask = maskFields.left(delimiter);
- m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
+ m_blank = (delimiter + 1 < maskFields.size()) ? maskFields[delimiter + 1] : u' ';
}
// calculate m_maxLength / m_maskData length
m_maxLength = 0;
- QChar c = 0;
bool escaped = false;
- for (int i=0; i<m_inputMask.length(); i++) {
- c = m_inputMask.at(i);
+ for (int i=0; i<m_inputMask.size(); i++) {
+ const auto c = m_inputMask.at(i);
if (escaped) {
++m_maxLength;
escaped = false;
continue;
}
- if (c == '\\') {
+ if (c == u'\\') {
escaped = true;
continue;
}
- if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
- c != QLatin1Char('<') && c != QLatin1Char('>') &&
- c != QLatin1Char('{') && c != QLatin1Char('}') &&
- c != QLatin1Char('[') && c != QLatin1Char(']'))
+ if (c != u'\\' && c != u'!' && c != u'<' && c != u'>' &&
+ c != u'{' && c != u'}' && c != u'[' && c != u']')
m_maxLength++;
}
- delete [] m_maskData;
- m_maskData = new MaskInputData[m_maxLength];
+ m_maskData = std::make_unique<MaskInputData[]>(m_maxLength);
MaskInputData::Casemode m = MaskInputData::NoCaseMode;
- c = 0;
bool s;
bool escape = false;
int index = 0;
- for (int i = 0; i < m_inputMask.length(); i++) {
- c = m_inputMask.at(i);
+ for (int i = 0; i < m_inputMask.size(); i++) {
+ const auto c = m_inputMask.at(i);
if (escape) {
s = true;
m_maskData[index].maskChar = c;
@@ -1020,13 +991,13 @@ void QWidgetLineControl::parseInputMask(const QString &maskFields)
m_maskData[index].caseMode = m;
index++;
escape = false;
- } else if (c == QLatin1Char('<')) {
- m = MaskInputData::Lower;
- } else if (c == QLatin1Char('>')) {
+ } else if (c == u'<') {
+ m = MaskInputData::Lower;
+ } else if (c == u'>') {
m = MaskInputData::Upper;
- } else if (c == QLatin1Char('!')) {
+ } else if (c == u'!') {
m = MaskInputData::NoCaseMode;
- } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
+ } else if (c != u'{' && c != u'}' && c != u'[' && c != u']') {
switch (c.unicode()) {
case 'A':
case 'a':
@@ -1114,23 +1085,23 @@ bool QWidgetLineControl::isValidInput(QChar key, QChar mask) const
return true;
break;
case '#':
- if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
+ if (key.isNumber() || key == u'+' || key == u'-' || key == m_blank)
return true;
break;
case 'B':
- if (key == QLatin1Char('0') || key == QLatin1Char('1'))
+ if (key == u'0' || key == u'1')
return true;
break;
case 'b':
- if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
+ if (key == u'0' || key == u'1' || key == m_blank)
return true;
break;
case 'H':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
+ if (key.isNumber() || (key >= u'a' && key <= u'f') || (key >= u'A' && key <= u'F'))
return true;
break;
case 'h':
- if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
+ if (key.isNumber() || (key >= u'a' && key <= u'f') || (key >= u'A' && key <= u'F') || key == m_blank)
return true;
break;
default:
@@ -1160,7 +1131,7 @@ bool QWidgetLineControl::hasAcceptableInput(const QString &str) const
if (!m_maskData)
return true;
- if (str.length() != m_maxLength)
+ if (str.size() != m_maxLength)
return false;
for (int i=0; i < m_maxLength; ++i) {
@@ -1195,47 +1166,47 @@ QString QWidgetLineControl::maskString(int pos, const QString &str, bool clear)
QString s = QString::fromLatin1("");
int i = pos;
while (i < m_maxLength) {
- if (strIndex < str.length()) {
+ if (strIndex < str.size()) {
if (m_maskData[i].separator) {
s += m_maskData[i].maskChar;
- if (str[(int)strIndex] == m_maskData[i].maskChar)
+ if (str[strIndex] == m_maskData[i].maskChar)
strIndex++;
++i;
} else {
- if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
+ if (isValidInput(str[strIndex], m_maskData[i].maskChar)) {
switch (m_maskData[i].caseMode) {
case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
+ s += str[strIndex].toUpper();
break;
case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
+ s += str[strIndex].toLower();
break;
default:
- s += str[(int)strIndex];
+ s += str[strIndex];
}
++i;
} else {
// search for separator first
- int n = findInMask(i, true, true, str[(int)strIndex]);
+ int n = findInMask(i, true, true, str[strIndex]);
if (n != -1) {
- if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
- s += fill.midRef(i, n - i + 1);
+ if (str.size() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[strIndex]))) {
+ s += QStringView{fill}.mid(i, n - i + 1);
i = n + 1; // update i to find + 1
}
} else {
// search for valid m_blank if not
- n = findInMask(i, true, false, str[(int)strIndex]);
+ n = findInMask(i, true, false, str[strIndex]);
if (n != -1) {
- s += fill.midRef(i, n - i);
+ s += QStringView{fill}.mid(i, n - i);
switch (m_maskData[n].caseMode) {
case MaskInputData::Upper:
- s += str[(int)strIndex].toUpper();
+ s += str[strIndex].toUpper();
break;
case MaskInputData::Lower:
- s += str[(int)strIndex].toLower();
+ s += str[strIndex].toLower();
break;
default:
- s += str[(int)strIndex];
+ s += str[strIndex];
}
i = n + 1; // updates i to find + 1
}
@@ -1286,7 +1257,7 @@ QString QWidgetLineControl::stripString(const QString &str) const
return str;
QString s;
- int end = qMin(m_maxLength, (int)str.length());
+ int end = qMin(m_maxLength, (int)str.size());
for (int i = 0; i < end; ++i)
if (m_maskData[i].separator)
s += m_maskData[i].maskChar;
@@ -1424,8 +1395,8 @@ void QWidgetLineControl::emitCursorPositionChanged()
if (m_cursor != m_lastCursorPos) {
const int oldLast = m_lastCursorPos;
m_lastCursorPos = m_cursor;
- cursorPositionChanged(oldLast, m_cursor);
-#ifndef QT_NO_ACCESSIBILITY
+ emit cursorPositionChanged(oldLast, m_cursor);
+#if QT_CONFIG(accessibility)
// otherwise we send a selection update which includes the cursor
if (!hasSelectedText()) {
QAccessibleTextCursorEvent event(accessibleObject(), m_cursor);
@@ -1473,7 +1444,7 @@ void QWidgetLineControl::complete(int key)
return;
int n = 0;
if (key == Qt::Key_Up || key == Qt::Key_Down) {
- if (textAfterSelection().length())
+ if (textAfterSelection().size())
return;
QString prefix = hasSelectedText() ? textBeforeSelection()
: text;
@@ -1662,10 +1633,12 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
break;
#endif
if (!m_completer->currentCompletion().isEmpty() && hasSelectedText()
+ && !m_completer->completionPrefix().isEmpty()
&& textAfterSelection().isEmpty()) {
setText(m_completer->currentCompletion());
inlineCompletionAccepted = true;
}
+ break;
default:
break; // normal key processing
}
@@ -1837,13 +1810,18 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
}
else if (event == QKeySequence::DeleteEndOfWord) {
if (!isReadOnly()) {
- cursorWordForward(true);
- del();
+ if (!hasSelectedText())
+ cursorWordForward(true);
+
+ if (hasSelectedText())
+ del();
}
}
else if (event == QKeySequence::DeleteStartOfWord) {
if (!isReadOnly()) {
- cursorWordBackward(true);
+ if (!hasSelectedText())
+ cursorWordBackward(true);
+
if (hasSelectedText())
del();
}
@@ -1948,10 +1926,15 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
return;
}
- if (unknown)
+ if (unknown) {
event->ignore();
- else
+ } else {
+#ifndef QT_NO_CLIPBOARD
+ if (QApplication::clipboard()->supportsSelection())
+ copy(QClipboard::Selection);
+#endif
event->accept();
+ }
}
bool QWidgetLineControl::isUndoAvailable() const
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index a8fffd23dc..2ce0fe7d94 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETLINECONTROL_P_H
#define QWIDGETLINECONTROL_P_H
@@ -70,7 +34,11 @@
#include "qplatformdefs.h"
#include <vector>
+#include <memory>
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
#ifdef DrawText
# undef DrawText
#endif
@@ -110,9 +78,7 @@ public:
// password data to stay in the process memory, therefore we need
// to zero it out
if (m_echoMode != QLineEdit::Normal)
- m_text.fill('\0');
-
- delete [] m_maskData;
+ m_text.fill(u'\0');
}
void setAccessibleObject(QObject *object)
@@ -149,7 +115,7 @@ public:
bool isModified() const { return m_modifiedState != m_undoState; }
void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; }
- bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
+ bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.size(); }
bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
int width() const { return qRound(m_textLayout.lineAt(0).width()) + 1; }
@@ -165,6 +131,9 @@ public:
int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
+#if defined (Q_OS_ANDROID)
+ bool isSelectableByMouse() const { return true; }
+#endif
bool inSelection(int x) const
{
if (m_selstart >= m_selend)
@@ -181,7 +150,7 @@ public:
}
int start() const { return 0; }
- int end() const { return m_text.length(); }
+ int end() const { return m_text.size(); }
#ifndef QT_NO_CLIPBOARD
void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
@@ -217,7 +186,7 @@ public:
void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
void home(bool mark) { moveCursor(0, mark); }
- void end(bool mark) { moveCursor(m_text.length(), mark); }
+ void end(bool mark) { moveCursor(m_text.size(), mark); }
int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
QRect rectForPos(int pos) const;
@@ -262,7 +231,7 @@ public:
void backspace();
void del();
void deselect() { internalDeselect(); finishChange(); }
- void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
+ void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.size(), true); }
void insert(const QString &);
void clear();
@@ -308,7 +277,7 @@ public:
#endif
int cursorPosition() const { return m_cursor; }
- void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
+ void setCursorPosition(int pos) { if (pos <= m_text.size()) moveCursor(qMax(0, pos)); }
bool hasAcceptableInput() const { return hasAcceptableInput(m_text); }
bool fixup();
@@ -318,8 +287,8 @@ public:
QString mask;
if (m_maskData) {
mask = m_inputMask;
- if (m_blank != QLatin1Char(' ')) {
- mask += QLatin1Char(';');
+ if (m_blank != u' ') {
+ mask += u';';
mask += m_blank;
}
}
@@ -354,11 +323,8 @@ public:
void setPasswordMaskDelay(int delay) { m_passwordMaskDelay = delay; }
Qt::LayoutDirection layoutDirection() const {
- if (m_layoutDirection == Qt::LayoutDirectionAuto) {
- if (m_text.isEmpty())
- return QGuiApplication::inputMethod()->inputDirection();
+ if (m_layoutDirection == Qt::LayoutDirectionAuto && !m_text.isEmpty())
return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
- }
return m_layoutDirection;
}
void setLayoutDirection(Qt::LayoutDirection direction)
@@ -468,7 +434,7 @@ private:
};
QString m_inputMask;
QChar m_blank;
- MaskInputData *m_maskData;
+ std::unique_ptr<MaskInputData[]> m_maskData;
// undo/redo handling
enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
@@ -550,6 +516,8 @@ private:
// accessibility events are sent for this object
QObject *m_accessibleObject;
+
+ friend class QLineEdit;
};
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp
index 9dbba12aba..b7ee494e99 100644
--- a/src/widgets/widgets/qwidgetresizehandler.cpp
+++ b/src/widgets/widgets/qwidgetresizehandler.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwidgetresizehandler_p.h"
#include "qframe.h"
#include "qapplication.h"
-#include "qdesktopwidget.h"
-#include <private/qdesktopwidget_p.h>
+#include "private/qwidget_p.h"
#include "qcursor.h"
#if QT_CONFIG(sizegrip)
#include "qsizegrip.h"
@@ -53,51 +16,44 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#define RANGE 4
static bool resizeHorizontalDirectionFixed = false;
static bool resizeVerticalDirectionFixed = false;
-// ### fixme: Qt 6: No longer export QWidgetResizeHandler and remove "Move"
-// functionality. Currently, only the resize functionality is used by QDockWidget.
-// Historically, the class was used in Qt 3's QWorkspace (predecessor to QMdiArea).
-
QWidgetResizeHandler::QWidgetResizeHandler(QWidget *parent, QWidget *cw)
: QObject(parent), widget(parent), childWidget(cw ? cw : parent),
- fw(0), extrahei(0), buttonDown(false), moveResizeMode(false), sizeprotect(true), movingEnabled(true)
+ fw(0), extrahei(0), buttonDown(false), active(false)
{
mode = Nowhere;
widget->setMouseTracking(true);
QFrame *frame = qobject_cast<QFrame*>(widget);
range = frame ? frame->frameWidth() : RANGE;
range = qMax(RANGE, range);
- activeForMove = activeForResize = true;
+ enabled = true;
widget->installEventFilter(this);
}
-void QWidgetResizeHandler::setActive(Action ac, bool b)
+void QWidgetResizeHandler::setEnabled(bool b)
{
- if (ac & Move)
- activeForMove = b;
- if (ac & Resize)
- activeForResize = b;
+ if (b == enabled)
+ return;
- if (!isActive())
+ enabled = b;
+ if (!enabled)
setMouseCursor(Nowhere);
}
-bool QWidgetResizeHandler::isActive(Action ac) const
+bool QWidgetResizeHandler::isEnabled() const
{
- bool b = false;
- if (ac & Move) b = activeForMove;
- if (ac & Resize) b |= activeForResize;
-
- return b;
+ return enabled;
}
bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee)
{
- if (!isActive()
+ if (!isEnabled()
|| (ee->type() != QEvent::MouseButtonPress
&& ee->type() != QEvent::MouseButtonRelease
&& ee->type() != QEvent::MouseMove
@@ -120,41 +76,30 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee)
if (w->isMaximized())
break;
const QRect widgetRect = widget->rect().marginsAdded(QMargins(range, range, range, range));
- const QPoint cursorPoint = widget->mapFromGlobal(e->globalPos());
+ const QPoint cursorPoint = widget->mapFromGlobal(e->globalPosition().toPoint());
if (!widgetRect.contains(cursorPoint))
return false;
if (e->button() == Qt::LeftButton) {
buttonDown = false;
emit activate();
- bool me = movingEnabled;
- movingEnabled = (me && o == widget);
mouseMoveEvent(e);
- movingEnabled = me;
buttonDown = true;
- moveOffset = widget->mapFromGlobal(e->globalPos());
+ moveOffset = widget->mapFromGlobal(e->globalPosition().toPoint());
invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
- if (mode == Center) {
- if (movingEnabled)
- return true;
- } else {
+ if (mode != Center)
return true;
- }
}
} break;
case QEvent::MouseButtonRelease:
if (w->isMaximized())
break;
if (static_cast<QMouseEvent *>(ee)->button() == Qt::LeftButton) {
- moveResizeMode = false;
+ active = false;
buttonDown = false;
widget->releaseMouse();
widget->releaseKeyboard();
- if (mode == Center) {
- if (movingEnabled)
- return true;
- } else {
+ if (mode != Center)
return true;
- }
}
break;
case QEvent::MouseMove: {
@@ -162,16 +107,9 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee)
break;
QMouseEvent *e = static_cast<QMouseEvent *>(ee);
buttonDown = buttonDown && (e->buttons() & Qt::LeftButton); // safety, state machine broken!
- bool me = movingEnabled;
- movingEnabled = (me && o == widget && (buttonDown || moveResizeMode));
mouseMoveEvent(e);
- movingEnabled = me;
- if (mode == Center) {
- if (movingEnabled)
- return true;
- } else {
+ if (mode != Center)
return true;
- }
} break;
case QEvent::KeyPress:
keyPressEvent(static_cast<QKeyEvent *>(ee));
@@ -192,8 +130,8 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee)
void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
{
- QPoint pos = widget->mapFromGlobal(e->globalPos());
- if (!moveResizeMode && !buttonDown) {
+ QPoint pos = widget->mapFromGlobal(e->globalPosition().toPoint());
+ if (!active && !buttonDown) {
if (pos.y() <= range && pos.x() <= range)
mode = TopLeft;
else if (pos.y() >= widget->height()-range && pos.x() >= widget->width()-range)
@@ -215,7 +153,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
else
mode = Nowhere;
- if (widget->isMinimized() || !isActive(Resize))
+ if (widget->isMinimized() || !isEnabled())
mode = Center;
#ifndef QT_NO_CURSOR
setMouseCursor(mode);
@@ -223,7 +161,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
return;
}
- if (mode == Center && !movingEnabled)
+ if (mode == Center)
return;
if (widget->testAttribute(Qt::WA_WState_ConfigPending))
@@ -231,15 +169,15 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
QPoint globalPos = (!widget->isWindow() && widget->parentWidget()) ?
- widget->parentWidget()->mapFromGlobal(e->globalPos()) : e->globalPos();
+ widget->parentWidget()->mapFromGlobal(e->globalPosition().toPoint()) : e->globalPosition().toPoint();
if (!widget->isWindow() && !widget->parentWidget()->rect().contains(globalPos)) {
if (globalPos.x() < 0)
globalPos.rx() = 0;
if (globalPos.y() < 0)
globalPos.ry() = 0;
- if (sizeprotect && globalPos.x() > widget->parentWidget()->width())
+ if (globalPos.x() > widget->parentWidget()->width())
globalPos.rx() = widget->parentWidget()->width();
- if (sizeprotect && globalPos.y() > widget->parentWidget()->height())
+ if (globalPos.y() > widget->parentWidget()->height())
globalPos.ry() = widget->parentWidget()->height();
}
@@ -247,8 +185,8 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
QPoint pp = globalPos - moveOffset;
// Workaround for window managers which refuse to move a tool window partially offscreen.
- if (QGuiApplication::platformName() == QLatin1String("xcb")) {
- const QRect desktop = QDesktopWidgetPrivate::availableGeometry(widget);
+ if (QGuiApplication::platformName() == "xcb"_L1) {
+ const QRect desktop = QWidgetPrivate::availableScreenGeometry(widget);
pp.rx() = qMax(pp.x(), desktop.left());
pp.ry() = qMax(pp.y(), desktop.top());
p.rx() = qMin(p.x(), desktop.right());
@@ -300,9 +238,6 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
case Right:
geom = QRect(widget->geometry().topLeft(), QPoint(p.x(), widget->geometry().bottom())) ;
break;
- case Center:
- geom.moveTopLeft(pp);
- break;
default:
break;
}
@@ -314,10 +249,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
if (geom != widget->geometry() &&
(widget->isWindow() || widget->parentWidget()->rect().intersects(geom))) {
- if (mode == Center)
- widget->move(geom.topLeft());
- else
- widget->setGeometry(geom);
+ widget->setGeometry(geom);
}
}
@@ -361,7 +293,7 @@ void QWidgetResizeHandler::setMouseCursor(MousePosition m)
void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
{
- if (!isMove() && !isResize())
+ if (!isResizing())
return;
bool is_control = e->modifiers() & Qt::ControlModifier;
int delta = is_control?1:8;
@@ -369,7 +301,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
switch (e->key()) {
case Qt::Key_Left:
pos.rx() -= delta;
- if (pos.x() <= QDesktopWidgetPrivate::geometry().left()) {
+ if (pos.x() <= QGuiApplication::primaryScreen()->virtualGeometry().left()) {
if (mode == TopLeft || mode == BottomLeft) {
moveOffset.rx() += delta;
invertedMoveOffset.rx() += delta;
@@ -378,7 +310,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
invertedMoveOffset.rx() -= delta;
}
}
- if (isResize() && !resizeHorizontalDirectionFixed) {
+ if (isResizing() && !resizeHorizontalDirectionFixed) {
resizeHorizontalDirectionFixed = true;
if (mode == BottomRight)
mode = BottomLeft;
@@ -394,7 +326,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
break;
case Qt::Key_Right:
pos.rx() += delta;
- if (pos.x() >= QDesktopWidgetPrivate::geometry().right()) {
+ if (pos.x() >= QGuiApplication::primaryScreen()->virtualGeometry().right()) {
if (mode == TopRight || mode == BottomRight) {
moveOffset.rx() += delta;
invertedMoveOffset.rx() += delta;
@@ -403,7 +335,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
invertedMoveOffset.rx() -= delta;
}
}
- if (isResize() && !resizeHorizontalDirectionFixed) {
+ if (isResizing() && !resizeHorizontalDirectionFixed) {
resizeHorizontalDirectionFixed = true;
if (mode == BottomLeft)
mode = BottomRight;
@@ -419,7 +351,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
break;
case Qt::Key_Up:
pos.ry() -= delta;
- if (pos.y() <= QDesktopWidgetPrivate::geometry().top()) {
+ if (pos.y() <= QGuiApplication::primaryScreen()->virtualGeometry().top()) {
if (mode == TopLeft || mode == TopRight) {
moveOffset.ry() += delta;
invertedMoveOffset.ry() += delta;
@@ -428,7 +360,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
invertedMoveOffset.ry() -= delta;
}
}
- if (isResize() && !resizeVerticalDirectionFixed) {
+ if (isResizing() && !resizeVerticalDirectionFixed) {
resizeVerticalDirectionFixed = true;
if (mode == BottomLeft)
mode = TopLeft;
@@ -444,7 +376,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
break;
case Qt::Key_Down:
pos.ry() += delta;
- if (pos.y() >= QDesktopWidgetPrivate::geometry().bottom()) {
+ if (pos.y() >= QGuiApplication::primaryScreen()->virtualGeometry().bottom()) {
if (mode == BottomLeft || mode == BottomRight) {
moveOffset.ry() += delta;
invertedMoveOffset.ry() += delta;
@@ -453,7 +385,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
invertedMoveOffset.ry() -= delta;
}
}
- if (isResize() && !resizeVerticalDirectionFixed) {
+ if (isResizing() && !resizeVerticalDirectionFixed) {
resizeVerticalDirectionFixed = true;
if (mode == TopLeft)
mode = BottomLeft;
@@ -471,7 +403,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Escape:
- moveResizeMode = false;
+ active = false;
widget->releaseMouse();
widget->releaseKeyboard();
buttonDown = false;
@@ -485,10 +417,10 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e)
void QWidgetResizeHandler::doResize()
{
- if (!activeForResize)
+ if (!enabled)
return;
- moveResizeMode = true;
+ active = true;
moveOffset = widget->mapFromGlobal(QCursor::pos());
if (moveOffset.x() < widget->width()/2) {
if (moveOffset.y() < widget->height()/2)
@@ -513,23 +445,6 @@ void QWidgetResizeHandler::doResize()
resizeVerticalDirectionFixed = false;
}
-void QWidgetResizeHandler::doMove()
-{
- if (!activeForMove)
- return;
-
- mode = Center;
- moveResizeMode = true;
- moveOffset = widget->mapFromGlobal(QCursor::pos());
- invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
-#ifndef QT_NO_CURSOR
- widget->grabMouse(Qt::SizeAllCursor);
-#else
- widget->grabMouse();
-#endif
- widget->grabKeyboard();
-}
-
QT_END_NAMESPACE
#include "moc_qwidgetresizehandler_p.cpp"
diff --git a/src/widgets/widgets/qwidgetresizehandler_p.h b/src/widgets/widgets/qwidgetresizehandler_p.h
index df3ac7cb8a..d7780a55e6 100644
--- a/src/widgets/widgets/qwidgetresizehandler_p.h
+++ b/src/widgets/widgets/qwidgetresizehandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETRESIZEHANDLER_P_H
#define QWIDGETRESIZEHANDLER_P_H
@@ -62,34 +26,22 @@ QT_BEGIN_NAMESPACE
class QMouseEvent;
class QKeyEvent;
-class Q_WIDGETS_EXPORT QWidgetResizeHandler : public QObject
+class QWidgetResizeHandler : public QObject
{
Q_OBJECT
public:
- enum Action {
- Move = 0x01,
- Resize = 0x02,
- Any = Move|Resize
- };
-
explicit QWidgetResizeHandler(QWidget *parent, QWidget *cw = nullptr);
- void setActive(bool b) { setActive(Any, b); }
- void setActive(Action ac, bool b);
- bool isActive() const { return isActive(Any); }
- bool isActive(Action ac) const;
- void setMovingEnabled(bool b) { movingEnabled = b; }
- bool isMovingEnabled() const { return movingEnabled; }
+ void setEnabled(bool b);
+ bool isEnabled() const;
bool isButtonDown() const { return buttonDown; }
void setExtraHeight(int h) { extrahei = h; }
- void setSizeProtection(bool b) { sizeprotect = b; }
void setFrameWidth(int w) { fw = w; }
void doResize();
- void doMove();
Q_SIGNALS:
void activate();
@@ -117,19 +69,13 @@ private:
int fw;
int extrahei;
int range;
- uint buttonDown :1;
- uint moveResizeMode :1;
- uint activeForResize :1;
- uint sizeprotect :1;
- uint movingEnabled :1;
- uint activeForMove :1;
+ uint buttonDown :1;
+ uint active :1;
+ uint enabled :1;
void setMouseCursor(MousePosition m);
- bool isMove() const {
- return moveResizeMode && mode == Center;
- }
- bool isResize() const {
- return moveResizeMode && !isMove();
+ bool isResizing() const {
+ return active && mode != Center;
}
};
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 49a1a02867..6dcaeee0c8 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwidgettextcontrol_p.h"
#include "qwidgettextcontrol_p_p.h"
@@ -50,16 +14,17 @@
#include <qdrag.h>
#endif
#include <qclipboard.h>
-#if QT_CONFIG(menu)
-#include <qmenu.h>
-#endif
#include <qstyle.h>
#include <qtimer.h>
#include "private/qapplication_p.h"
#include "private/qtextdocumentlayout_p.h"
#include "private/qabstracttextdocumentlayout_p.h"
+#if QT_CONFIG(menu)
+#include "private/qmenu_p.h"
+#endif
#include "qtextdocument.h"
#include "private/qtextdocument_p.h"
+#include "private/qtextdocumentfragment_p.h"
#include "qtextlist.h"
#include "private/qwidgettextcontrol_p.h"
#if QT_CONFIG(style_stylesheet)
@@ -84,7 +49,9 @@
#include <qurl.h>
#include <qdesktopservices.h>
#include <qinputmethod.h>
+#if QT_CONFIG(tooltip)
#include <qtooltip.h>
+#endif
#include <qstyleoption.h>
#if QT_CONFIG(lineedit)
#include <QtWidgets/qlineedit.h>
@@ -96,10 +63,9 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include <qkeysequence.h>
-#define ACCEL_KEY(k) ((!QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) \
- && QGuiApplication::styleHints()->showShortcutsInContextMenus()) \
+#define ACCEL_KEY(k) (!QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) \
&& !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(k) ? \
- QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
+ u'\t' + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
#else
#define ACCEL_KEY(k) QString()
@@ -109,6 +75,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// could go into QTextCursor...
static QTextLine currentTextLine(const QTextCursor &cursor)
{
@@ -445,25 +413,30 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
if (!doc) {
if (document) {
doc = document;
- clearDocument = false;
} else {
palette = QApplication::palette("QWidgetTextControl");
doc = new QTextDocument(q);
}
+ clearDocument = false;
_q_documentLayoutChanged();
cursor = QTextCursor(doc);
// #### doc->documentLayout()->setPaintDevice(viewport);
- QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection()));
- QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor)));
- QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
+ QObjectPrivate::connect(doc, &QTextDocument::contentsChanged, this,
+ &QWidgetTextControlPrivate::_q_updateCurrentCharFormatAndSelection);
+ QObjectPrivate::connect(doc, &QTextDocument::cursorPositionChanged, this,
+ &QWidgetTextControlPrivate::_q_emitCursorPosChanged);
+ QObjectPrivate::connect(doc, &QTextDocument::documentLayoutChanged, this,
+ &QWidgetTextControlPrivate::_q_documentLayoutChanged);
// convenience signal forwards
- QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
- QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
- QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
- QObject::connect(doc, SIGNAL(blockCountChanged(int)), q, SIGNAL(blockCountChanged(int)));
+ QObject::connect(doc, &QTextDocument::undoAvailable, q, &QWidgetTextControl::undoAvailable);
+ QObject::connect(doc, &QTextDocument::redoAvailable, q, &QWidgetTextControl::redoAvailable);
+ QObject::connect(doc, &QTextDocument::modificationChanged, q,
+ &QWidgetTextControl::modificationChanged);
+ QObject::connect(doc, &QTextDocument::blockCountChanged, q,
+ &QWidgetTextControl::blockCountChanged);
}
bool previousUndoRedoState = doc->isUndoRedoEnabled();
@@ -525,7 +498,8 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
q->ensureCursorVisible();
emit q->cursorPositionChanged();
- QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)), Qt::UniqueConnection);
+ QObjectPrivate::connect(doc, &QTextDocument::contentsChange, this,
+ &QWidgetTextControlPrivate::_q_contentsChanged, Qt::UniqueConnection);
}
void QWidgetTextControlPrivate::startDrag()
@@ -605,7 +579,7 @@ void QWidgetTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged
Q_Q(QWidgetTextControl);
if (forceEmitSelectionChanged) {
emit q->selectionChanged();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (q->parent() && q->parent()->isWidgetType()) {
QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
QAccessible::updateAccessibility(&ev);
@@ -628,7 +602,7 @@ void QWidgetTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged
&& (cursor.position() != lastSelectionPosition
|| cursor.anchor() != lastSelectionAnchor)))) {
emit q->selectionChanged();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (q->parent() && q->parent()->isWidgetType()) {
QAccessibleTextSelectionEvent ev(q->parent(), cursor.anchor(), cursor.position());
QAccessible::updateAccessibility(&ev);
@@ -669,7 +643,7 @@ void QWidgetTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someC
void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, int charsAdded)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_Q(QWidgetTextControl);
if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) {
@@ -681,7 +655,7 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
QString newText = tmp.selectedText();
// always report the right number of removed chars, but in lack of the real string use spaces
- QString oldText = QString(charsRemoved, QLatin1Char(' '));
+ QString oldText = QString(charsRemoved, u' ');
QAccessibleEvent *ev = nullptr;
if (charsRemoved == 0) {
@@ -695,9 +669,9 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
delete ev;
}
#else
- Q_UNUSED(from)
- Q_UNUSED(charsRemoved)
- Q_UNUSED(charsAdded)
+ Q_UNUSED(from);
+ Q_UNUSED(charsRemoved);
+ Q_UNUSED(charsAdded);
#endif
}
@@ -705,10 +679,12 @@ void QWidgetTextControlPrivate::_q_documentLayoutChanged()
{
Q_Q(QWidgetTextControl);
QAbstractTextDocumentLayout *layout = doc->documentLayout();
- QObject::connect(layout, SIGNAL(update(QRectF)), q, SIGNAL(updateRequest(QRectF)));
- QObject::connect(layout, SIGNAL(updateBlock(QTextBlock)), q, SLOT(_q_updateBlock(QTextBlock)));
- QObject::connect(layout, SIGNAL(documentSizeChanged(QSizeF)), q, SIGNAL(documentSizeChanged(QSizeF)));
-
+ QObject::connect(layout, &QAbstractTextDocumentLayout::update, q,
+ &QWidgetTextControl::updateRequest);
+ QObjectPrivate::connect(layout, &QAbstractTextDocumentLayout::updateBlock, this,
+ &QWidgetTextControlPrivate::_q_updateBlock);
+ QObject::connect(layout, &QAbstractTextDocumentLayout::documentSizeChanged, q,
+ &QWidgetTextControl::documentSizeChanged);
}
void QWidgetTextControlPrivate::setCursorVisible(bool visible)
@@ -921,7 +897,7 @@ QTextDocument *QWidgetTextControl::document() const
return d->doc;
}
-void QWidgetTextControl::setTextCursor(const QTextCursor &cursor)
+void QWidgetTextControl::setTextCursor(const QTextCursor &cursor, bool selectionClipboard)
{
Q_D(QWidgetTextControl);
d->cursorIsFocusIndicator = false;
@@ -935,6 +911,13 @@ void QWidgetTextControl::setTextCursor(const QTextCursor &cursor)
d->repaintOldAndNewSelection(oldSelection);
if (posChanged)
emit cursorPositionChanged();
+
+#ifndef QT_NO_CLIPBOARD
+ if (selectionClipboard)
+ d->setClipboardSelection();
+#else
+ Q_UNUSED(selectionClipboard);
+#endif
}
QTextCursor QWidgetTextControl::textCursor() const
@@ -984,20 +967,23 @@ void QWidgetTextControl::selectAll()
{
Q_D(QWidgetTextControl);
const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor());
+ const int oldCursorPos = d->cursor.position();
d->cursor.select(QTextCursor::Document);
d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor()));
d->cursorIsFocusIndicator = false;
+ if (d->cursor.position() != oldCursorPos)
+ emit cursorPositionChanged();
emit updateRequest();
}
void QWidgetTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset, QWidget *contextWidget)
{
- QMatrix m;
- m.translate(coordinateOffset.x(), coordinateOffset.y());
- processEvent(e, m, contextWidget);
+ QTransform t;
+ t.translate(coordinateOffset.x(), coordinateOffset.y());
+ processEvent(e, t, contextWidget);
}
-void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget)
+void QWidgetTextControl::processEvent(QEvent *e, const QTransform &transform, QWidget *contextWidget)
{
Q_D(QWidgetTextControl);
if (d->interactionFlags == Qt::NoTextInteraction) {
@@ -1038,23 +1024,23 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
break;
case QEvent::MouseButtonPress: {
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
- d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(),
- ev->buttons(), ev->globalPos());
+ d->mousePressEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
+ ev->buttons(), ev->globalPosition().toPoint());
break; }
case QEvent::MouseMove: {
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
- d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(),
- ev->buttons(), ev->globalPos());
+ d->mouseMoveEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
+ ev->buttons(), ev->globalPosition().toPoint());
break; }
case QEvent::MouseButtonRelease: {
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
- d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(),
- ev->buttons(), ev->globalPos());
+ d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
+ ev->buttons(), ev->globalPosition().toPoint());
break; }
case QEvent::MouseButtonDblClick: {
QMouseEvent *ev = static_cast<QMouseEvent *>(e);
- d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(),
- ev->buttons(), ev->globalPos());
+ d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->position().toPoint()), ev->modifiers(),
+ ev->buttons(), ev->globalPosition().toPoint());
break; }
case QEvent::InputMethod:
d->inputMethodEvent(static_cast<QInputMethodEvent *>(e));
@@ -1062,7 +1048,7 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
#ifndef QT_NO_CONTEXTMENU
case QEvent::ContextMenu: {
QContextMenuEvent *ev = static_cast<QContextMenuEvent *>(e);
- d->contextMenuEvent(ev->globalPos(), matrix.map(ev->pos()), contextWidget);
+ d->contextMenuEvent(ev->globalPos(), transform.map(ev->pos()), contextWidget);
break; }
#endif // QT_NO_CONTEXTMENU
case QEvent::FocusIn:
@@ -1074,13 +1060,13 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
d->isEnabled = e->isAccepted();
break;
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
case QEvent::ToolTip: {
QHelpEvent *ev = static_cast<QHelpEvent *>(e);
- d->showToolTip(ev->globalPos(), matrix.map(ev->pos()), contextWidget);
+ d->showToolTip(ev->globalPos(), transform.map(ev->pos()), contextWidget);
break;
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(draganddrop)
case QEvent::DragEnter: {
@@ -1094,13 +1080,13 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
break;
case QEvent::DragMove: {
QDragMoveEvent *ev = static_cast<QDragMoveEvent *>(e);
- if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos())))
+ if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->position().toPoint())))
ev->acceptProposedAction();
break;
}
case QEvent::Drop: {
QDropEvent *ev = static_cast<QDropEvent *>(e);
- if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source()))
+ if (d->dropEvent(ev->mimeData(), transform.map(ev->position().toPoint()), ev->dropAction(), ev->source()))
ev->acceptProposedAction();
break;
}
@@ -1109,32 +1095,32 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
#if QT_CONFIG(graphicsview)
case QEvent::GraphicsSceneMousePress: {
QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e);
- d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
+ d->mousePressEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
ev->screenPos());
break; }
case QEvent::GraphicsSceneMouseMove: {
QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e);
- d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
+ d->mouseMoveEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
ev->screenPos());
break; }
case QEvent::GraphicsSceneMouseRelease: {
QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e);
- d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
+ d->mouseReleaseEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
ev->screenPos());
break; }
case QEvent::GraphicsSceneMouseDoubleClick: {
QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e);
- d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(),
+ d->mouseDoubleClickEvent(ev, ev->button(), transform.map(ev->pos()), ev->modifiers(), ev->buttons(),
ev->screenPos());
break; }
case QEvent::GraphicsSceneContextMenu: {
QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e);
- d->contextMenuEvent(ev->screenPos(), matrix.map(ev->pos()), contextWidget);
+ d->contextMenuEvent(ev->screenPos(), transform.map(ev->pos()), contextWidget);
break; }
case QEvent::GraphicsSceneHoverMove: {
QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e);
- d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton,
+ d->mouseMoveEvent(ev, Qt::NoButton, transform.map(ev->pos()), ev->modifiers(),Qt::NoButton,
ev->screenPos());
break; }
@@ -1148,12 +1134,12 @@ void QWidgetTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget
break;
case QEvent::GraphicsSceneDragMove: {
QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e);
- if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos())))
+ if (d->dragMoveEvent(e, ev->mimeData(), transform.map(ev->pos())))
ev->acceptProposedAction();
break; }
case QEvent::GraphicsSceneDrop: {
QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e);
- if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source()))
+ if (d->dropEvent(ev->mimeData(), transform.map(ev->pos()), ev->dropAction(), ev->source()))
ev->accept();
break; }
#endif // QT_CONFIG(graphicsview)
@@ -1224,6 +1210,9 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
if (e == QKeySequence::SelectAll) {
e->accept();
q->selectAll();
+#ifndef QT_NO_CLIPBOARD
+ setClipboardSelection();
+#endif
return;
}
#ifndef QT_NO_CLIPBOARD
@@ -1272,7 +1261,7 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
// example)
repaintSelection();
- if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) {
+ if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~(Qt::ShiftModifier | Qt::GroupSwitchModifier))) {
QTextBlockFormat blockFmt = cursor.blockFormat();
QTextList *list = cursor.currentList();
if (list && cursor.atBlockStart() && !cursor.hasSelection()) {
@@ -1290,7 +1279,7 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
}
#ifndef QT_NO_SHORTCUT
else if (e == QKeySequence::InsertParagraphSeparator) {
- cursor.insertBlock();
+ insertParagraphSeparator();
e->accept();
goto accept;
} else if (e == QKeySequence::InsertLineSeparator) {
@@ -1375,6 +1364,10 @@ process:
accept:
+#ifndef QT_NO_CLIPBOARD
+ setClipboardSelection();
+#endif
+
e->accept();
cursorOn = true;
@@ -1413,16 +1406,14 @@ QRectF QWidgetTextControlPrivate::rectForPosition(int position) const
if (relativePos == preeditPos)
relativePos += preeditCursor;
else if (relativePos > preeditPos)
- relativePos += layout->preeditAreaText().length();
+ relativePos += layout->preeditAreaText().size();
}
QTextLine line = layout->lineForTextPosition(relativePos);
int cursorWidth;
{
bool ok = false;
-#ifndef QT_NO_PROPERTIES
cursorWidth = docLayout->property("cursorWidth").toInt(&ok);
-#endif
if (!ok)
cursorWidth = 1;
}
@@ -1436,7 +1427,7 @@ QRectF QWidgetTextControlPrivate::rectForPosition(int position) const
if (relativePos < line.textLength() - line.textStart())
w = line.cursorToX(relativePos + 1) - x;
else
- w = QFontMetrics(block.layout()->font()).horizontalAdvance(QLatin1Char(' ')); // in sync with QTextLine::draw()
+ w = QFontMetrics(block.layout()->font()).horizontalAdvance(u' '); // in sync with QTextLine::draw()
}
r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(),
cursorWidth + w, line.height());
@@ -1792,7 +1783,7 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but
#ifndef QT_NO_CLIPBOARD
setClipboardSelection();
selectionChanged(true);
- } else if (button == Qt::MidButton
+ } else if (button == Qt::MiddleButton
&& (interactionFlags & Qt::TextEditable)
&& QGuiApplication::clipboard()->supportsSelection()) {
setCursorPosition(pos);
@@ -1830,25 +1821,36 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but
}
if (interactionFlags & Qt::LinksAccessibleByMouse) {
- if (!(button & Qt::LeftButton))
+
+ // Ignore event unless left button has been pressed
+ if (!(button & Qt::LeftButton)) {
+ e->ignore();
return;
+ }
const QString anchor = q->anchorAt(pos);
- if (anchor.isEmpty())
+ // Ignore event without selection anchor
+ if (anchor.isEmpty()) {
+ e->ignore();
return;
+ }
if (!cursor.hasSelection()
|| (anchor == anchorOnMousePress && hadSelectionOnMousePress)) {
const int anchorPos = q->hitTest(pos, Qt::ExactHit);
- if (anchorPos != -1) {
- cursor.setPosition(anchorPos);
- QString anchor = anchorOnMousePress;
- anchorOnMousePress = QString();
- activateLinkUnderCursor(anchor);
+ // Ignore event without valid anchor position
+ if (anchorPos < 0) {
+ e->ignore();
+ return;
}
+
+ cursor.setPosition(anchorPos);
+ QString anchor = anchorOnMousePress;
+ anchorOnMousePress = QString();
+ activateLinkUnderCursor(anchor);
}
}
}
@@ -1912,7 +1914,7 @@ bool QWidgetTextControlPrivate::sendMouseEventToInputContext(
QTextLayout *layout = cursor.block().layout();
int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position();
- if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length())
+ if (cursorPos < 0 || cursorPos > layout->preeditAreaText().size())
cursorPos = -1;
if (cursorPos >= 0) {
@@ -1941,6 +1943,12 @@ void QWidgetTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const
if (!menu)
return;
menu->setAttribute(Qt::WA_DeleteOnClose);
+
+ if (auto *widget = qobject_cast<QWidget *>(parent)) {
+ if (auto *window = widget->window()->windowHandle())
+ QMenuPrivate::get(menu)->topData()->initialScreen = window->screen();
+ }
+
menu->popup(screenPos);
#endif
}
@@ -2019,7 +2027,7 @@ bool QWidgetTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPoin
void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
{
Q_Q(QWidgetTextControl);
- if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) {
+ if (!(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByMouse)) || cursor.isNull()) {
e->ignore();
return;
}
@@ -2027,6 +2035,11 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
|| e->preeditString() != cursor.block().layout()->preeditAreaText()
|| e->replacementLength() > 0;
+ if (!isGettingInput && e->attributes().isEmpty()) {
+ e->ignore();
+ return;
+ }
+
int oldCursorPos = cursor.position();
cursor.beginEditBlock();
@@ -2063,10 +2076,10 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QTextLayout *layout = block.layout();
if (isGettingInput)
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
- QVector<QTextLayout::FormatRange> overrides;
+ QList<QTextLayout::FormatRange> overrides;
overrides.reserve(e->attributes().size());
const int oldPreeditCursor = preeditCursor;
- preeditCursor = e->preeditString().length();
+ preeditCursor = e->preeditString().size();
hideCursor = false;
for (int i = 0; i < e->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = e->attributes().at(i);
@@ -2083,9 +2096,9 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
o.format = f;
// Make sure list is sorted by start index
- QVector<QTextLayout::FormatRange>::iterator it = overrides.end();
+ QList<QTextLayout::FormatRange>::iterator it = overrides.end();
while (it != overrides.begin()) {
- QVector<QTextLayout::FormatRange>::iterator previous = it - 1;
+ QList<QTextLayout::FormatRange>::iterator previous = it - 1;
if (o.start >= previous->start) {
overrides.insert(it, o);
break;
@@ -2101,9 +2114,9 @@ void QWidgetTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
if (cursor.charFormat().isValid()) {
int start = cursor.position() - block.position();
- int end = start + e->preeditString().length();
+ int end = start + e->preeditString().size();
- QVector<QTextLayout::FormatRange>::iterator it = overrides.begin();
+ QList<QTextLayout::FormatRange>::iterator it = overrides.begin();
while (it != overrides.end()) {
QTextLayout::FormatRange range = *it;
int rangeStart = range.start;
@@ -2174,12 +2187,12 @@ QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVa
QTextCursor tmpCursor = d->cursor;
int localPos = d->cursor.position() - block.position();
QString result = block.text().mid(localPos);
- while (result.length() < maxLength) {
+ while (result.size() < maxLength) {
int currentBlock = tmpCursor.blockNumber();
tmpCursor.movePosition(QTextCursor::NextBlock);
if (tmpCursor.blockNumber() == currentBlock)
break;
- result += QLatin1Char('\n') + tmpCursor.block().text();
+ result += u'\n' + tmpCursor.block().text();
}
return QVariant(result);
}
@@ -2200,11 +2213,11 @@ QVariant QWidgetTextControl::inputMethodQuery(Qt::InputMethodQuery property, QVa
}
QString result;
while (numBlocks) {
- result += tmpCursor.block().text() + QLatin1Char('\n');
+ result += tmpCursor.block().text() + u'\n';
tmpCursor.movePosition(QTextCursor::NextBlock);
--numBlocks;
}
- result += block.text().midRef(0, localPos);
+ result += QStringView{block.text()}.mid(0, localPos);
return QVariant(result);
}
default:
@@ -2236,6 +2249,7 @@ void QWidgetTextControlPrivate::focusEvent(QFocusEvent *e)
#endif
} else {
setCursorVisible(false);
+ cursorOn = false;
if (cursorIsFocusIndicator
&& e->reason() != Qt::ActiveWindowFocusReason
@@ -2290,7 +2304,7 @@ void QWidgetTextControlPrivate::editFocusEvent(QEvent *e)
#endif
#ifndef QT_NO_CONTEXTMENU
-static inline void setActionIcon(QAction *action, const QString &name)
+void setActionIcon(QAction *action, const QString &name)
{
const QIcon icon = QIcon::fromTheme(name);
if (!icon.isNull())
@@ -2448,24 +2462,16 @@ void QWidgetTextControl::setOverwriteMode(bool overwrite)
int QWidgetTextControl::cursorWidth() const
{
-#ifndef QT_NO_PROPERTIES
Q_D(const QWidgetTextControl);
return d->doc->documentLayout()->property("cursorWidth").toInt();
-#else
- return 1;
-#endif
}
void QWidgetTextControl::setCursorWidth(int width)
{
Q_D(QWidgetTextControl);
-#ifdef QT_NO_PROPERTIES
- Q_UNUSED(width);
-#else
if (width == -1)
- width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth);
+ width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth, nullptr, qobject_cast<QWidget *>(parent()));
d->doc->documentLayout()->setProperty("cursorWidth", width);
-#endif
d->repaintCursor();
}
@@ -2488,12 +2494,12 @@ void QWidgetTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelectio
Q_D(QWidgetTextControl);
QMultiHash<int, int> hash;
- for (int i = 0; i < d->extraSelections.count(); ++i) {
+ for (int i = 0; i < d->extraSelections.size(); ++i) {
const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(i);
hash.insert(esel.cursor.anchor(), i);
}
- for (int i = 0; i < selections.count(); ++i) {
+ for (int i = 0; i < selections.size(); ++i) {
const QTextEdit::ExtraSelection &sel = selections.at(i);
const auto it = hash.constFind(sel.cursor.anchor());
if (it != hash.cend()) {
@@ -2512,7 +2518,7 @@ void QWidgetTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelectio
emit updateRequest(r);
}
- for (QHash<int, int>::iterator it = hash.begin(); it != hash.end(); ++it) {
+ for (auto it = hash.cbegin(); it != hash.cend(); ++it) {
const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(it.value());
QRectF r = selectionRect(esel.cursor);
if (esel.format.boolProperty(QTextFormat::FullWidthSelection)) {
@@ -2522,8 +2528,8 @@ void QWidgetTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelectio
emit updateRequest(r);
}
- d->extraSelections.resize(selections.count());
- for (int i = 0; i < selections.count(); ++i) {
+ d->extraSelections.resize(selections.size());
+ for (int i = 0; i < selections.size(); ++i) {
d->extraSelections[i].cursor = selections.at(i).cursor;
d->extraSelections[i].format = selections.at(i).format;
}
@@ -2533,7 +2539,7 @@ QList<QTextEdit::ExtraSelection> QWidgetTextControl::extraSelections() const
{
Q_D(const QWidgetTextControl);
QList<QTextEdit::ExtraSelection> selections;
- const int numExtraSelections = d->extraSelections.count();
+ const int numExtraSelections = d->extraSelections.size();
selections.reserve(numExtraSelections);
for (int i = 0; i < numExtraSelections; ++i) {
QTextEdit::ExtraSelection sel;
@@ -2668,6 +2674,7 @@ void QWidgetTextControl::print(QPagedPaintDevice *printer) const
if (!d->cursor.hasSelection())
return;
tempDoc = new QTextDocument(const_cast<QTextDocument *>(doc));
+ tempDoc->setResourceProvider(doc->resourceProvider());
tempDoc->setMetaInformation(QTextDocument::DocumentTitle, doc->metaInformation(QTextDocument::DocumentTitle));
tempDoc->setPageSize(doc->pageSize());
tempDoc->setDefaultFont(doc->defaultFont());
@@ -2696,8 +2703,8 @@ bool QWidgetTextControl::canInsertFromMimeData(const QMimeData *source) const
if (d->acceptRichText)
return (source->hasText() && !source->text().isEmpty())
|| source->hasHtml()
- || source->hasFormat(QLatin1String("application/x-qrichtext"))
- || source->hasFormat(QLatin1String("application/x-qt-richtext"));
+ || source->hasFormat("application/x-qrichtext"_L1)
+ || source->hasFormat("application/x-qt-richtext"_L1);
else
return source->hasText() && !source->text().isEmpty();
}
@@ -2710,26 +2717,33 @@ void QWidgetTextControl::insertFromMimeData(const QMimeData *source)
bool hasData = false;
QTextDocumentFragment fragment;
+#if QT_CONFIG(textmarkdownreader)
+ const auto formats = source->formats();
+ if (formats.size() && formats.first() == "text/markdown"_L1) {
+ auto s = QString::fromUtf8(source->data("text/markdown"_L1));
+ fragment = QTextDocumentFragment::fromMarkdown(s);
+ hasData = true;
+ } else
+#endif
#ifndef QT_NO_TEXTHTMLPARSER
- if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) {
+ if (source->hasFormat("application/x-qrichtext"_L1) && d->acceptRichText) {
// x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore).
- const QString richtext = QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")
- + QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext")));
+ const QString richtext = "<meta name=\"qrichtext\" content=\"1\" />"_L1
+ + QString::fromUtf8(source->data("application/x-qrichtext"_L1));
fragment = QTextDocumentFragment::fromHtml(richtext, d->doc);
hasData = true;
} else if (source->hasHtml() && d->acceptRichText) {
fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc);
hasData = true;
- } else {
- QString text = source->text();
+ }
+#endif // QT_NO_TEXTHTMLPARSER
+ if (!hasData) {
+ const QString text = source->text();
if (!text.isNull()) {
fragment = QTextDocumentFragment::fromPlainText(text);
hasData = true;
}
}
-#else
- fragment = QTextDocumentFragment::fromPlainText(source->text());
-#endif // QT_NO_TEXTHTMLPARSER
if (hasData)
d->cursor.insertFragment(fragment);
@@ -2947,7 +2961,7 @@ void QWidgetTextControlPrivate::activateLinkUnderCursor(QString href)
emit q_func()->linkActivated(href);
}
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
void QWidgetTextControlPrivate::showToolTip(const QPoint &globalPos, const QPointF &pos, QWidget *contextWidget)
{
const QString toolTip = q_func()->cursorForPosition(pos).charFormat().toolTip();
@@ -2955,7 +2969,7 @@ void QWidgetTextControlPrivate::showToolTip(const QPoint &globalPos, const QPoin
return;
QToolTip::showText(globalPos, toolTip, contextWidget);
}
-#endif // QT_NO_TOOLTIP
+#endif // QT_CONFIG(tooltip)
bool QWidgetTextControlPrivate::isPreediting() const
{
@@ -3145,19 +3159,6 @@ bool QWidgetTextControl::find(const QString &exp, QTextDocument::FindFlags optio
return true;
}
-#ifndef QT_NO_REGEXP
-bool QWidgetTextControl::find(const QRegExp &exp, QTextDocument::FindFlags options)
-{
- Q_D(QWidgetTextControl);
- QTextCursor search = d->doc->find(exp, d->cursor, options);
- if (search.isNull())
- return false;
-
- setTextCursor(search);
- return true;
-}
-#endif
-
#if QT_CONFIG(regularexpression)
bool QWidgetTextControl::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
{
@@ -3190,6 +3191,49 @@ QString QWidgetTextControl::toMarkdown(QTextDocument::MarkdownFeatures features)
}
#endif
+void QWidgetTextControlPrivate::insertParagraphSeparator()
+{
+ // clear blockFormat properties that the user is unlikely to want duplicated:
+ // - don't insert <hr/> automatically
+ // - the next paragraph after a heading should be a normal paragraph
+ // - remove the bottom margin from the last list item before appending
+ // - the next checklist item after a checked item should be unchecked
+ auto blockFmt = cursor.blockFormat();
+ auto charFmt = cursor.charFormat();
+ blockFmt.clearProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
+ if (blockFmt.hasProperty(QTextFormat::HeadingLevel)) {
+ blockFmt.clearProperty(QTextFormat::HeadingLevel);
+ charFmt = QTextCharFormat();
+ }
+ if (cursor.currentList()) {
+ auto existingFmt = cursor.blockFormat();
+ existingFmt.clearProperty(QTextBlockFormat::BlockBottomMargin);
+ cursor.setBlockFormat(existingFmt);
+ if (blockFmt.marker() == QTextBlockFormat::MarkerType::Checked)
+ blockFmt.setMarker(QTextBlockFormat::MarkerType::Unchecked);
+ }
+
+ // After a blank line, reset block and char formats. I.e. you can end a list,
+ // block quote, etc. by hitting enter twice, and get back to normal paragraph style.
+ if (cursor.block().text().isEmpty() &&
+ !cursor.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) &&
+ !cursor.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
+ blockFmt = QTextBlockFormat();
+ const bool blockFmtChanged = (cursor.blockFormat() != blockFmt);
+ charFmt = QTextCharFormat();
+ cursor.setBlockFormat(blockFmt);
+ cursor.setCharFormat(charFmt);
+ // If the user hit enter twice just to get back to default format,
+ // don't actually insert a new block. But if the user then hits enter
+ // yet again, the block format will not change, so we will insert a block.
+ // This is what many word processors do.
+ if (blockFmtChanged)
+ return;
+ }
+
+ cursor.insertBlock(blockFmt, charFmt);
+}
+
void QWidgetTextControlPrivate::append(const QString &text, Qt::TextFormat format)
{
QTextCursor tmp(doc);
@@ -3416,16 +3460,19 @@ void QUnicodeControlCharacterMenu::menuActionTriggered()
QStringList QTextEditMimeData::formats() const
{
if (!fragment.isEmpty())
- return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html")
+ return QStringList() << u"text/plain"_s << u"text/html"_s
+#if QT_CONFIG(textmarkdownwriter)
+ << u"text/markdown"_s
+#endif
#ifndef QT_NO_TEXTODFWRITER
- << QString::fromLatin1("application/vnd.oasis.opendocument.text")
+ << u"application/vnd.oasis.opendocument.text"_s
#endif
;
else
return QMimeData::formats();
}
-QVariant QTextEditMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+QVariant QTextEditMimeData::retrieveData(const QString &mimeType, QMetaType type) const
{
if (!fragment.isEmpty())
setup();
@@ -3436,7 +3483,10 @@ void QTextEditMimeData::setup() const
{
QTextEditMimeData *that = const_cast<QTextEditMimeData *>(this);
#ifndef QT_NO_TEXTHTMLPARSER
- that->setData(QLatin1String("text/html"), fragment.toHtml("utf-8").toUtf8());
+ that->setData("text/html"_L1, fragment.toHtml().toUtf8());
+#endif
+#if QT_CONFIG(textmarkdownwriter)
+ that->setData("text/markdown"_L1, fragment.toMarkdown().toUtf8());
#endif
#ifndef QT_NO_TEXTODFWRITER
{
@@ -3444,7 +3494,7 @@ void QTextEditMimeData::setup() const
QTextDocumentWriter writer(&buffer, "ODF");
writer.write(fragment);
buffer.close();
- that->setData(QLatin1String("application/vnd.oasis.opendocument.text"), buffer.data());
+ that->setData("application/vnd.oasis.opendocument.text"_L1, buffer.data());
}
#endif
that->setText(fragment.toPlainText());
diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h
index 1f06aa0b97..9df4c0c810 100644
--- a/src/widgets/widgets/qwidgettextcontrol_p.h
+++ b/src/widgets/widgets/qwidgettextcontrol_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETTEXTCONTROL_P_H
#define QWIDGETTEXTCONTROL_P_H
@@ -93,9 +57,11 @@ class Q_WIDGETS_EXPORT QWidgetTextControl : public QInputControl
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText)
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
- Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags
+ WRITE setTextInteractionFlags)
Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
- Q_PROPERTY(bool ignoreUnusedNavigationEvents READ ignoreUnusedNavigationEvents WRITE setIgnoreUnusedNavigationEvents)
+ Q_PROPERTY(bool ignoreUnusedNavigationEvents READ ignoreUnusedNavigationEvents
+ WRITE setIgnoreUnusedNavigationEvents)
public:
explicit QWidgetTextControl(QObject *parent = nullptr);
explicit QWidgetTextControl(const QString &text, QObject *parent = nullptr);
@@ -105,7 +71,7 @@ public:
void setDocument(QTextDocument *document);
QTextDocument *document() const;
- void setTextCursor(const QTextCursor &cursor);
+ void setTextCursor(const QTextCursor &cursor, bool selectionClipboard = false);
QTextCursor textCursor() const;
void setTextInteractionFlags(Qt::TextInteractionFlags flags);
@@ -117,9 +83,6 @@ public:
QTextCharFormat currentCharFormat() const;
bool find(const QString &exp, QTextDocument::FindFlags options = { });
-#ifndef QT_NO_REGEXP
- bool find(const QRegExp &exp, QTextDocument::FindFlags options = { });
-#endif
#if QT_CONFIG(regularexpression)
bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = { });
#endif
@@ -252,7 +215,7 @@ public:
QPalette palette() const;
void setPalette(const QPalette &pal);
- virtual void processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget = nullptr);
+ virtual void processEvent(QEvent *e, const QTransform &transform, QWidget *contextWidget = nullptr);
void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF(), QWidget *contextWidget = nullptr);
// control methods
@@ -277,13 +240,8 @@ protected:
private:
Q_DISABLE_COPY_MOVE(QWidgetTextControl)
- Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection())
- Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &))
Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected())
Q_PRIVATE_SLOT(d_func(), void _q_copyLink())
- Q_PRIVATE_SLOT(d_func(), void _q_updateBlock(const QTextBlock &))
- Q_PRIVATE_SLOT(d_func(), void _q_documentLayoutChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_contentsChanged(int, int, int))
};
@@ -311,13 +269,18 @@ public:
virtual QStringList formats() const override;
protected:
- virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const override;
+ virtual QVariant retrieveData(const QString &mimeType, QMetaType type) const override;
private:
void setup() const;
mutable QTextDocumentFragment fragment;
};
+#ifndef QT_NO_CONTEXTMENU
+// also used by QLineEdit
+void setActionIcon(QAction *action, const QString &name);
+#endif // QT_NO_CONTEXTMENU
+
QT_END_NAMESPACE
#endif // QWidgetTextControl_H
diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h
index c77a31bedf..955a70ecad 100644
--- a/src/widgets/widgets/qwidgettextcontrol_p_p.h
+++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETTEXTCONTROL_P_P_H
#define QWIDGETTEXTCONTROL_P_P_H
@@ -73,8 +37,9 @@ class QAbstractScrollArea;
class QWidgetTextControlPrivate : public QObjectPrivate
{
- Q_DECLARE_PUBLIC(QWidgetTextControl)
public:
+ Q_DECLARE_PUBLIC(QWidgetTextControl)
+
QWidgetTextControlPrivate();
bool cursorMoveKeyEvent(QKeyEvent *e);
@@ -171,13 +136,14 @@ public:
void activateLinkUnderCursor(QString href = QString());
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
void showToolTip(const QPoint &globalPos, const QPointF &pos, QWidget *contextWidget);
#endif
bool isPreediting() const;
void commitPreedit();
+ void insertParagraphSeparator();
void append(const QString &text, Qt::TextFormat format = Qt::AutoText);
QTextDocument *doc;
@@ -217,7 +183,7 @@ public:
int preeditCursor;
bool hideCursor; // used to hide the cursor in the preedit area
- QVector<QAbstractTextDocumentLayout::Selection> extraSelections;
+ QList<QAbstractTextDocumentLayout::Selection> extraSelections;
QPalette palette;
bool hasFocus;
diff --git a/src/widgets/widgets/widgets.pri b/src/widgets/widgets/widgets.pri
deleted file mode 100644
index 55804c5aaf..0000000000
--- a/src/widgets/widgets/widgets.pri
+++ /dev/null
@@ -1,371 +0,0 @@
-# Qt widgets module
-
-HEADERS += \
- widgets/qframe.h \
- widgets/qframe_p.h \
- widgets/qabstractscrollarea.h \
- widgets/qabstractscrollarea_p.h \
- widgets/qfocusframe.h \
- widgets/qwidgetanimator_p.h
-
-SOURCES += \
- widgets/qframe.cpp \
- widgets/qabstractscrollarea.cpp \
- widgets/qfocusframe.cpp \
- widgets/qwidgetanimator.cpp
-
-qtConfig(abstractbutton) {
- HEADERS += \
- widgets/qabstractbutton.h \
- widgets/qabstractbutton_p.h
-
- SOURCES += \
- widgets/qabstractbutton.cpp
-}
-
-qtConfig(abstractslider) {
- HEADERS += \
- widgets/qabstractslider.h \
- widgets/qabstractslider_p.h
-
- SOURCES += \
- widgets/qabstractslider.cpp
-}
-
-qtConfig(buttongroup) {
- HEADERS += \
- widgets/qbuttongroup.h \
- widgets/qbuttongroup_p.h
-
- SOURCES += widgets/qbuttongroup.cpp
-}
-
-qtConfig(calendarwidget) {
- HEADERS += widgets/qcalendarwidget.h
- SOURCES += widgets/qcalendarwidget.cpp
-}
-
-qtConfig(checkbox) {
- HEADERS += \
- widgets/qcheckbox.h
-
- SOURCES += \
- widgets/qcheckbox.cpp
-}
-
-qtConfig(combobox) {
- HEADERS += \
- widgets/qcombobox.h \
- widgets/qcombobox_p.h
-
- SOURCES += widgets/qcombobox.cpp
-}
-
-qtConfig(commandlinkbutton) {
- HEADERS += \
- widgets/qcommandlinkbutton.h
-
- SOURCES += \
- widgets/qcommandlinkbutton.cpp
-}
-
-qtConfig(datetimeedit) {
- HEADERS += \
- widgets/qdatetimeedit.h \
- widgets/qdatetimeedit_p.h
-
- SOURCES += \
- widgets/qdatetimeedit.cpp
-}
-
-qtConfig(dial) {
- HEADERS += widgets/qdial.h
- SOURCES += widgets/qdial.cpp
-}
-
-qtConfig(dockwidget) {
- HEADERS += \
- widgets/qdockwidget.h \
- widgets/qdockwidget_p.h \
- widgets/qdockarealayout_p.h
-
- SOURCES += \
- widgets/qdockwidget.cpp \
- widgets/qdockarealayout.cpp
-}
-
-qtConfig(effects) {
- HEADERS += widgets/qeffects_p.h
- SOURCES += widgets/qeffects.cpp
-}
-
-qtConfig(fontcombobox) {
- HEADERS += widgets/qfontcombobox.h
- SOURCES += widgets/qfontcombobox.cpp
-}
-
-qtConfig(groupbox) {
- HEADERS += widgets/qgroupbox.h
- SOURCES += widgets/qgroupbox.cpp
-}
-
-qtConfig(keysequenceedit) {
- HEADERS += \
- widgets/qkeysequenceedit.h \
- widgets/qkeysequenceedit_p.h
-
- SOURCES += widgets/qkeysequenceedit.cpp
-}
-
-qtConfig(label) {
- HEADERS += \
- widgets/qlabel.h \
- widgets/qlabel_p.h
-
- SOURCES += \
- widgets/qlabel.cpp
-}
-
-qtConfig(lcdnumber) {
- HEADERS += \
- widgets/qlcdnumber.h
-
- SOURCES += \
- widgets/qlcdnumber.cpp
-}
-
-qtConfig(lineedit) {
- HEADERS += \
- widgets/qlineedit.h \
- widgets/qlineedit_p.h \
- widgets/qwidgetlinecontrol_p.h
-
- SOURCES += \
- widgets/qlineedit_p.cpp \
- widgets/qlineedit.cpp \
- widgets/qwidgetlinecontrol.cpp
-}
-
-qtConfig(mainwindow) {
- HEADERS += \
- widgets/qmainwindow.h \
- widgets/qmainwindowlayout_p.h
-
- SOURCES += \
- widgets/qmainwindow.cpp \
- widgets/qmainwindowlayout.cpp
-}
-
-qtConfig(mdiarea) {
- HEADERS += \
- widgets/qmdiarea.h \
- widgets/qmdiarea_p.h \
- widgets/qmdisubwindow.h \
- widgets/qmdisubwindow_p.h
-
- SOURCES += \
- widgets/qmdiarea.cpp \
- widgets/qmdisubwindow.cpp
-}
-
-qtConfig(menu) {
- HEADERS += \
- widgets/qmenu.h \
- widgets/qmenu_p.h
-
- SOURCES += widgets/qmenu.cpp
-}
-
-qtConfig(menubar) {
- HEADERS += \
- widgets/qmenubar.h \
- widgets/qmenubar_p.h
-
- SOURCES += widgets/qmenubar.cpp
-}
-
-qtConfig(progressbar) {
- HEADERS += widgets/qprogressbar.h
- SOURCES += widgets/qprogressbar.cpp
-}
-
-qtConfig(pushbutton) {
- HEADERS += \
- widgets/qpushbutton.h \
- widgets/qpushbutton_p.h
-
- SOURCES += \
- widgets/qpushbutton.cpp
-}
-
-qtConfig(radiobutton) {
- HEADERS += \
- widgets/qradiobutton.h
-
- SOURCES += \
- widgets/qradiobutton.cpp
-}
-
-qtConfig(resizehandler) {
- HEADERS += widgets/qwidgetresizehandler_p.h
- SOURCES += widgets/qwidgetresizehandler.cpp
-}
-
-qtConfig(dialogbuttonbox) {
- HEADERS += \
- widgets/qdialogbuttonbox.h
-
- SOURCES += \
- widgets/qdialogbuttonbox.cpp
-}
-
-qtConfig(rubberband) {
- HEADERS += widgets/qrubberband.h
- SOURCES += widgets/qrubberband.cpp
-}
-
-qtConfig(scrollarea) {
- HEADERS += \
- widgets/qscrollarea.h \
- widgets/qscrollarea_p.h
-
- SOURCES += widgets/qscrollarea.cpp
-}
-
-qtConfig(scrollbar) {
- HEADERS += \
- widgets/qscrollbar.h \
- widgets/qscrollbar_p.h
-
- SOURCES += widgets/qscrollbar.cpp
-}
-
-qtConfig(sizegrip) {
- HEADERS += widgets/qsizegrip.h
- SOURCES += widgets/qsizegrip.cpp
-}
-
-qtConfig(slider) {
- HEADERS += widgets/qslider.h
- SOURCES += widgets/qslider.cpp
-}
-
-qtConfig(spinbox) {
- HEADERS += \
- widgets/qabstractspinbox.h \
- widgets/qabstractspinbox_p.h \
- widgets/qspinbox.h
-
- SOURCES += \
- widgets/qabstractspinbox.cpp \
- widgets/qspinbox.cpp
-}
-
-qtConfig(splashscreen) {
- HEADERS += \
- widgets/qsplashscreen.h
-
- SOURCES += \
- widgets/qsplashscreen.cpp
-}
-
-qtConfig(splitter) {
- HEADERS += \
- widgets/qsplitter.h \
- widgets/qsplitter_p.h
-
- SOURCES += widgets/qsplitter.cpp
-}
-
-qtConfig(stackedwidget) {
- HEADERS += widgets/qstackedwidget.h
- SOURCES += widgets/qstackedwidget.cpp
-}
-
-qtConfig(statusbar) {
- HEADERS += widgets/qstatusbar.h
- SOURCES += widgets/qstatusbar.cpp
-}
-
-qtConfig(tabbar) {
- HEADERS += \
- widgets/qtabbar.h \
- widgets/qtabbar_p.h
-
- SOURCES += widgets/qtabbar.cpp
-}
-
-qtConfig(textedit) {
- HEADERS += \
- widgets/qplaintextedit.h \
- widgets/qplaintextedit_p.h \
- widgets/qtextedit.h \
- widgets/qtextedit_p.h
-
- SOURCES += \
- widgets/qplaintextedit.cpp \
- widgets/qtextedit.cpp
-}
-
-qtConfig(textbrowser) {
- HEADERS += widgets/qtextbrowser.h
- SOURCES += widgets/qtextbrowser.cpp
-}
-
-qtConfig(tabwidget) {
- HEADERS += widgets/qtabwidget.h
- SOURCES += widgets/qtabwidget.cpp
-}
-
-qtConfig(toolbar) {
- HEADERS += \
- widgets/qtoolbar.h \
- widgets/qtoolbar_p.h \
- widgets/qtoolbararealayout_p.h \
- widgets/qtoolbarlayout_p.h \
- widgets/qtoolbarseparator_p.h
-
- SOURCES += \
- widgets/qtoolbar.cpp \
- widgets/qtoolbarlayout.cpp \
- widgets/qtoolbararealayout.cpp \
- widgets/qtoolbarseparator.cpp
-}
-
-qtConfig(toolbox) {
- HEADERS += widgets/qtoolbox.h
- SOURCES += widgets/qtoolbox.cpp
-}
-
-qtConfig(toolbutton) {
- HEADERS += \
- widgets/qtoolbutton.h \
- widgets/qtoolbarextension_p.h
-
- SOURCES += \
- widgets/qtoolbutton.cpp \
- widgets/qtoolbarextension.cpp
-}
-
-qtConfig(widgettextcontrol) {
- HEADERS += \
- widgets/qwidgettextcontrol_p.h \
- widgets/qwidgettextcontrol_p_p.h
-
- SOURCES += \
- widgets/qwidgettextcontrol.cpp
-}
-
-macx {
- HEADERS += \
- widgets/qmacnativewidget_mac.h \
- widgets/qmaccocoaviewcontainer_mac.h
-
- OBJECTIVE_SOURCES += \
- widgets/qmacnativewidget_mac.mm \
- widgets/qmaccocoaviewcontainer_mac.mm
-
- qtConfig(menu)|qtConfig(menubar) {
- SOURCES += widgets/qmenu_mac.mm
- }
-}