aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-06-14 16:40:50 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2017-11-02 13:12:28 +0000
commit7ae55889805bc1d62c0268938eeca20bec9b773c (patch)
treeeda6308c079d08ba2cc6f8e4ca514c3982bf9adf
parent287411a3923f5fc1cf10aff7eeec66d834810790 (diff)
Visualize mnemonics
Unfortunately this comes a bit late in the 5.10 cycle, but this should be released together with the rest of the mnemonics stuff going out in 5.10, because it affects the value of AbstractButton/Menu(Bar)Item::text. As the removed TODO comments and altered tests indicate, previously the ampersand was blatantly stripped out. It would be worse to change it later once people have already started using mnemonics and rely on the behavior in custom styles. The necessary modifications to QQuickText were added in qtdeclarative commit 65ef4ba. Task-number: QTBUG-61422 Change-Id: Iaa73da8c012e9a6019743cf98f5bdc02527064e5 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-menubar.qml24
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp2
-rw-r--r--src/quickcontrols2/qquickiconlabel.cpp3
-rw-r--r--src/quickcontrols2/qquickiconlabel_p_p.h4
-rw-r--r--src/quickcontrols2/qquickmnemoniclabel.cpp133
-rw-r--r--src/quickcontrols2/qquickmnemoniclabel_p.h82
-rw-r--r--src/quickcontrols2/quickcontrols2.pri2
-rw-r--r--src/quicktemplates2/qquickabstractbutton.cpp2
-rw-r--r--tests/auto/controls/data/tst_abstractbutton.qml4
9 files changed, 238 insertions, 18 deletions
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-menubar.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-menubar.qml
index 2c0b6c8e..550680f6 100644
--- a/src/imports/controls/doc/snippets/qtquickcontrols2-menubar.qml
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-menubar.qml
@@ -44,23 +44,23 @@ ApplicationWindow {
menuBar: MenuBar {
Menu {
- title: qsTr("File")
- Action { text: qsTr("New...") }
- Action { text: qsTr("Open...") }
- Action { text: qsTr("Save") }
- Action { text: qsTr("Save As...") }
+ title: qsTr("&File")
+ Action { text: qsTr("&New...") }
+ Action { text: qsTr("&Open...") }
+ Action { text: qsTr("&Save") }
+ Action { text: qsTr("Save &As...") }
MenuSeparator { }
- Action { text: qsTr("Quit") }
+ Action { text: qsTr("&Quit") }
}
Menu {
- title: qsTr("Edit")
- Action { text: qsTr("Cut") }
- Action { text: qsTr("Copy") }
- Action { text: qsTr("Paste") }
+ title: qsTr("&Edit")
+ Action { text: qsTr("Cu&t") }
+ Action { text: qsTr("&Copy") }
+ Action { text: qsTr("&Paste") }
}
Menu {
- title: qsTr("Help")
- Action { text: qsTr("About") }
+ title: qsTr("&Help")
+ Action { text: qsTr("&About") }
}
}
}
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index 5f019a4e..4ac5b7e0 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -40,6 +40,7 @@
#include <QtQuickControls2/private/qquickcolor_p.h>
#include <QtQuickControls2/private/qquickcolorimage_p.h>
#include <QtQuickControls2/private/qquickiconimage_p.h>
+#include <QtQuickControls2/private/qquickmnemoniclabel_p.h>
#include <QtQuickControls2/private/qquickpaddedrectangle_p.h>
#include <QtQuickControls2/private/qquickplaceholdertext_p.h>
#include <QtQuickControls2/private/qquickiconlabel_p.h>
@@ -200,6 +201,7 @@ void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *ur
qmlRegisterSingletonType<QQuickColor>(import, 2, 3, "Color", colorSingleton);
qmlRegisterType<QQuickIconLabel>(import, 2, 3, "IconLabel");
qmlRegisterType<QQuickCheckLabel>(import, 2, 3, "CheckLabel");
+ qmlRegisterType<QQuickMnemonicLabel>(import, 2, 3, "MnemonicLabel");
qmlRegisterRevision<QQuickText, 6>(import, 2, 3);
}
diff --git a/src/quickcontrols2/qquickiconlabel.cpp b/src/quickcontrols2/qquickiconlabel.cpp
index 06d74d43..266d30d7 100644
--- a/src/quickcontrols2/qquickiconlabel.cpp
+++ b/src/quickcontrols2/qquickiconlabel.cpp
@@ -37,6 +37,7 @@
#include "qquickiconlabel_p.h"
#include "qquickiconlabel_p_p.h"
#include "qquickiconimage_p.h"
+#include "qquickmnemoniclabel_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/private/qquickitem_p.h>
@@ -147,7 +148,7 @@ bool QQuickIconLabelPrivate::createLabel()
if (label)
return false;
- label = new QQuickText(q);
+ label = new QQuickMnemonicLabel(q);
watchChanges(label);
beginClass(label);
label->setObjectName(QStringLiteral("label"));
diff --git a/src/quickcontrols2/qquickiconlabel_p_p.h b/src/quickcontrols2/qquickiconlabel_p_p.h
index 5762187c..f0f4df4c 100644
--- a/src/quickcontrols2/qquickiconlabel_p_p.h
+++ b/src/quickcontrols2/qquickiconlabel_p_p.h
@@ -54,8 +54,8 @@
QT_BEGIN_NAMESPACE
-class QQuickText;
class QQuickIconImage;
+class QQuickMnemonicLabel;
class QQuickIconLabelPrivate : public QQuickItemPrivate, public QQuickItemChangeListener
{
@@ -105,7 +105,7 @@ public:
QString text;
QQuickIcon icon;
QQuickIconImage *image;
- QQuickText *label;
+ QQuickMnemonicLabel *label;
};
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickmnemoniclabel.cpp b/src/quickcontrols2/qquickmnemoniclabel.cpp
new file mode 100644
index 00000000..9c8e9ab1
--- /dev/null
+++ b/src/quickcontrols2/qquickmnemoniclabel.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmnemoniclabel_p.h"
+
+#include <QtQuick/private/qquicktext_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickMnemonicLabel::QQuickMnemonicLabel(QQuickItem *parent)
+ : QQuickText(parent),
+ m_mnemonicVisible(true)
+{
+}
+
+QString QQuickMnemonicLabel::text() const
+{
+ return m_fullText;
+}
+
+void QQuickMnemonicLabel::setText(const QString &text)
+{
+ if (m_fullText == text)
+ return;
+
+ m_fullText = text;
+ updateMnemonic();
+}
+
+bool QQuickMnemonicLabel::isMnemonicVisible() const
+{
+ return m_mnemonicVisible;
+}
+
+void QQuickMnemonicLabel::setMnemonicVisible(bool visible)
+{
+ if (m_mnemonicVisible == visible)
+ return;
+
+ m_mnemonicVisible = visible;
+ updateMnemonic();
+
+ if (isComponentComplete())
+ forceLayout();
+}
+
+static QTextLayout::FormatRange underlineRange(int start, int length = 1)
+{
+ QTextLayout::FormatRange range;
+ range.start = start;
+ range.length = length;
+ range.format.setFontUnderline(true);
+ return range;
+}
+
+// based on QPlatformTheme::removeMnemonics()
+void QQuickMnemonicLabel::updateMnemonic()
+{
+ QString text(m_fullText.size(), 0);
+ int idx = 0;
+ int pos = 0;
+ int len = m_fullText.length();
+ QVector<QTextLayout::FormatRange> formats;
+ while (len) {
+ if (m_fullText.at(pos) == QLatin1Char('&') && (len == 1 || m_fullText.at(pos + 1) != QLatin1Char('&'))) {
+ if (m_mnemonicVisible && (pos == 0 || m_fullText.at(pos - 1) != QLatin1Char('&')))
+ formats += underlineRange(pos);
+ ++pos;
+ --len;
+ if (len == 0)
+ break;
+ } else if (m_fullText.at(pos) == QLatin1Char('(') && len >= 4 &&
+ m_fullText.at(pos + 1) == QLatin1Char('&') &&
+ m_fullText.at(pos + 2) != QLatin1Char('&') &&
+ m_fullText.at(pos + 3) == QLatin1Char(')')) {
+ // a mnemonic with format "\s*(&X)"
+ if (m_mnemonicVisible) {
+ formats += underlineRange(pos + 1);
+ } else {
+ int n = 0;
+ while (idx > n && text.at(idx - n - 1).isSpace())
+ ++n;
+ idx -= n;
+ pos += 4;
+ len -= 4;
+ continue;
+ }
+ }
+ text[idx] = m_fullText.at(pos);
+ ++pos;
+ ++idx;
+ --len;
+ }
+ text.truncate(idx);
+
+ QQuickTextPrivate::get(this)->layout.setFormats(formats);
+ QQuickText::setText(text);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickmnemoniclabel_p.h b/src/quickcontrols2/qquickmnemoniclabel_p.h
new file mode 100644
index 00000000..33bc1e08
--- /dev/null
+++ b/src/quickcontrols2/qquickmnemoniclabel_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMNEMONICLABEL_P_H
+#define QQUICKMNEMONICLABEL_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 <QtQuick/private/qquicktext_p.h>
+#include <QtQuickControls2/private/qtquickcontrols2global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickMnemonicLabel : public QQuickText
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText FINAL)
+ Q_PROPERTY(bool mnemonicVisible READ isMnemonicVisible WRITE setMnemonicVisible FINAL)
+
+public:
+ explicit QQuickMnemonicLabel(QQuickItem *parent = nullptr);
+
+ QString text() const;
+ void setText(const QString &text);
+
+ bool isMnemonicVisible() const;
+ void setMnemonicVisible(bool visible);
+
+private:
+ void updateMnemonic();
+
+ bool m_mnemonicVisible;
+ QString m_fullText;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickMnemonicLabel)
+
+#endif // QQUICKMNEMONICLABEL_P_H
diff --git a/src/quickcontrols2/quickcontrols2.pri b/src/quickcontrols2/quickcontrols2.pri
index 66a109f5..6537a599 100644
--- a/src/quickcontrols2/quickcontrols2.pri
+++ b/src/quickcontrols2/quickcontrols2.pri
@@ -8,6 +8,7 @@ HEADERS += \
$$PWD/qquickiconimage_p_p.h \
$$PWD/qquickiconlabel_p.h \
$$PWD/qquickiconlabel_p_p.h \
+ $$PWD/qquickmnemoniclabel_p.h \
$$PWD/qquickpaddedrectangle_p.h \
$$PWD/qquickplaceholdertext_p.h \
$$PWD/qquickproxytheme_p.h \
@@ -26,6 +27,7 @@ SOURCES += \
$$PWD/qquickcolorimage.cpp \
$$PWD/qquickiconimage.cpp \
$$PWD/qquickiconlabel.cpp \
+ $$PWD/qquickmnemoniclabel.cpp \
$$PWD/qquickpaddedrectangle.cpp \
$$PWD/qquickplaceholdertext.cpp \
$$PWD/qquickproxytheme.cpp \
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index 2c77d941..03f525f0 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -409,7 +409,7 @@ void QQuickAbstractButton::setText(const QString &text)
setShortcut(QKeySequence::mnemonic(text));
#endif
- d->text = QPlatformTheme::removeMnemonics(text); // ### TODO: visualize mnemonics
+ d->text = text;
setAccessibleName(d->text);
buttonChange(ButtonTextChange);
emit textChanged();
diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml
index 168844a0..90c6567f 100644
--- a/tests/auto/controls/data/tst_abstractbutton.qml
+++ b/tests/auto/controls/data/tst_abstractbutton.qml
@@ -303,7 +303,7 @@ TestCase {
verify(control)
control.text = "&Hello"
- compare(control.text, "Hello") // ### TODO: visualize mnemonics
+ compare(control.text, "&Hello")
var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
verify(clickSpy.valid)
@@ -320,7 +320,7 @@ TestCase {
compare(clickSpy.count, 2)
control.text = "Te&st"
- compare(control.text, "Test") // ### TODO: visualize mnemonics
+ compare(control.text, "Te&st")
keyClick(Qt.Key_H, Qt.AltModifier)
compare(clickSpy.count, 2)