Add QKeySequenceEdit

Change-Id: I497309d3e6cbf38b298afb5ff3cb1ed6a0e82000
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
bb10
Ivan Komissarov 2012-07-07 01:19:46 +04:00 committed by The Qt Project
parent 75abfa8982
commit f3a723f2ec
10 changed files with 627 additions and 0 deletions

View File

@ -115,6 +115,9 @@
// Image Text
//#define QT_NO_IMAGE_TEXT
// QKeySequenceEdit
//#define QT_NO_KEYSEQUENCEEDIT
// QLCDNumber
//#define QT_NO_LCDNUMBER
@ -306,6 +309,11 @@
#define QT_NO_IMAGEFORMATPLUGIN
#endif
// QKeySequenceEdit
#if !defined(QT_NO_KEYSEQUENCEEDIT) && (defined(QT_NO_SHORTCUT))
#define QT_NO_KEYSEQUENCEEDIT
#endif
// QLocalServer
#if !defined(QT_NO_LOCALSERVER) && (defined(QT_NO_TEMPORARYFILE))
#define QT_NO_LOCALSERVER

View File

@ -931,6 +931,7 @@ QT_CLASS_LIB(QFocusFrame, QtWidgets, qfocusframe.h)
QT_CLASS_LIB(QFontComboBox, QtWidgets, qfontcombobox.h)
QT_CLASS_LIB(QFrame, QtWidgets, qframe.h)
QT_CLASS_LIB(QGroupBox, QtWidgets, qgroupbox.h)
QT_CLASS_LIB(QKeySequenceEdit, QtWidgets, qkeysequenceedit.h)
QT_CLASS_LIB(QLabel, QtWidgets, qlabel.h)
QT_CLASS_LIB(QLCDNumber, QtWidgets, qlcdnumber.h)
QT_CLASS_LIB(QLineEdit, QtWidgets, qlineedit.h)

View File

@ -0,0 +1,333 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Ivan Komissarov.
** Contact: http://www.qt-project.org/legal
**
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 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 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qkeysequenceedit.h"
#include "qkeysequenceedit_p.h"
#include "qboxlayout.h"
#include "qlineedit.h"
QT_BEGIN_NAMESPACE
#ifndef QT_NO_KEYSEQUENCEEDIT
void QKeySequenceEditPrivate::init()
{
Q_Q(QKeySequenceEdit);
lineEdit = new QLineEdit(q);
keyNum = 0;
prevKey = -1;
releaseTimer = 0;
layout = new QVBoxLayout(q);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(lineEdit);
key[0] = key[1] = key[2] = key[3] = 0;
lineEdit->setFocusProxy(q);
lineEdit->installEventFilter(q);
resetState();
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
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)
{
int result = 0;
// The shift modifier only counts when it is not used to type a symbol
// that is only reachable using the shift key anyway
if ((state & Qt::ShiftModifier) && (text.isEmpty() ||
!text.at(0).isPrint() ||
text.at(0).isLetterOrNumber() ||
text.at(0).isSpace()))
result |= Qt::SHIFT;
if (state & Qt::ControlModifier)
result |= Qt::CTRL;
if (state & Qt::MetaModifier)
result |= Qt::META;
if (state & Qt::AltModifier)
result |= Qt::ALT;
return result;
}
void QKeySequenceEditPrivate::resetState()
{
Q_Q(QKeySequenceEdit);
if (releaseTimer) {
q->killTimer(releaseTimer);
releaseTimer = 0;
}
prevKey = -1;
lineEdit->setText(keySequence.toString(QKeySequence::NativeText));
lineEdit->setPlaceholderText(QKeySequenceEdit::tr("Press shortcut"));
}
void QKeySequenceEditPrivate::finishEditing()
{
Q_Q(QKeySequenceEdit);
resetState();
emit q->keySequenceChanged(keySequence);
emit q->editingFinished();
}
/*!
\class QKeySequenceEdit
\brief The QKeySequenceEdit widget allows to input a QKeySequence.
\inmodule QtWidgets
\since 5.2
This widget lets the user choose a QKeySequence, which is usually used as
a shortcut. The recording is initiated when the widget receives the focus
and ends one second after the user releases the last key.
\sa QKeySequenceEdit::keySequence
*/
/*!
Constructs a QKeySequenceEdit widget with the given \a parent.
*/
QKeySequenceEdit::QKeySequenceEdit(QWidget *parent) :
QWidget(*new QKeySequenceEditPrivate, parent, 0)
{
Q_D(QKeySequenceEdit);
d->init();
}
/*!
Constructs a QKeySequenceEdit widget with the given \a keySequence and \a parent.
*/
QKeySequenceEdit::QKeySequenceEdit(const QKeySequence &keySequence, QWidget *parent) :
QWidget(*new QKeySequenceEditPrivate, parent, 0)
{
Q_D(QKeySequenceEdit);
d->init();
setKeySequence(keySequence);
}
/*!
\internal
*/
QKeySequenceEdit::QKeySequenceEdit(QKeySequenceEditPrivate &dd, QWidget *parent, Qt::WindowFlags f) :
QWidget(dd, parent, f)
{
Q_D(QKeySequenceEdit);
d->init();
}
/*!
Destroys the QKeySequenceEdit object.
*/
QKeySequenceEdit::~QKeySequenceEdit()
{
}
/*!
\property QKeySequenceEdit::keySequence
\brief This property contains the currently chosen key sequence.
The shortcut can be changed by the user or via setter function.
*/
QKeySequence QKeySequenceEdit::keySequence() const
{
Q_D(const QKeySequenceEdit);
return d->keySequence;
}
void QKeySequenceEdit::setKeySequence(const QKeySequence &keySequence)
{
Q_D(QKeySequenceEdit);
d->resetState();
if (d->keySequence == keySequence)
return;
d->keySequence = keySequence;
d->key[0] = d->key[1] = d->key[2] = d->key[3] = 0;
d->keyNum = keySequence.count();
for (int i = 0; i < d->keyNum; ++i)
d->key[i] = keySequence[i];
d->lineEdit->setText(keySequence.toString(QKeySequence::NativeText));
emit keySequenceChanged(keySequence);
}
/*!
\fn void QKeySequenceEdit::editingFinished()
This signal is emitted when the user finishes entering the shortcut.
\note there is a one second delay before releasing the last key and
emitting this signal.
*/
/*!
\brief Clears the current key sequence.
*/
void QKeySequenceEdit::clear()
{
Q_D(QKeySequenceEdit);
d->resetState();
d->lineEdit->clear();
d->keySequence = QKeySequence();
d->keyNum = d->key[0] = d->key[1] = d->key[2] = d->key[3] = 0;
d->prevKey = -1;
emit keySequenceChanged(d->keySequence);
}
/*!
\reimp
*/
bool QKeySequenceEdit::event(QEvent *e)
{
switch (e->type()) {
case QEvent::Shortcut:
return true;
case QEvent::ShortcutOverride:
e->accept();
return true;
default :
break;
}
return QWidget::event(e);
}
/*!
\reimp
*/
void QKeySequenceEdit::keyPressEvent(QKeyEvent *e)
{
Q_D(QKeySequenceEdit);
int nextKey = e->key();
if (d->prevKey == -1) {
clear();
d->prevKey = nextKey;
}
d->lineEdit->setPlaceholderText(QString());
if (nextKey == Qt::Key_Control
|| nextKey == Qt::Key_Shift
|| nextKey == Qt::Key_Meta
|| nextKey == Qt::Key_Alt) {
return;
}
QString selectedText = d->lineEdit->selectedText();
if (!selectedText.isEmpty() && selectedText == d->lineEdit->text()) {
clear();
if (nextKey == Qt::Key_Backspace)
return;
}
if (d->keyNum >= QKeySequenceEditPrivate::MaxKeyCount)
return;
nextKey |= d->translateModifiers(e->modifiers(), e->text());
d->key[d->keyNum] = 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 < QKeySequenceEditPrivate::MaxKeyCount) {
//: This text is an "unfinished" shortcut, expands like "Ctrl+A, ..."
text = tr("%1, ...").arg(text);
}
d->lineEdit->setText(text);
e->accept();
}
/*!
\reimp
*/
void QKeySequenceEdit::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QKeySequenceEdit);
if (d->prevKey == e->key()) {
if (d->keyNum < QKeySequenceEditPrivate::MaxKeyCount)
d->releaseTimer = startTimer(1000);
else
d->finishEditing();
}
e->accept();
}
/*!
\reimp
*/
void QKeySequenceEdit::timerEvent(QTimerEvent *e)
{
Q_D(QKeySequenceEdit);
if (e->timerId() == d->releaseTimer) {
d->finishEditing();
return;
}
QWidget::timerEvent(e);
}
#endif // QT_NO_KEYSEQUENCEEDIT
QT_END_NAMESPACE

View File

@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Ivan Komissarov.
** Contact: http://www.qt-project.org/legal
**
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 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 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QKEYSEQUENCEEDIT_H
#define QKEYSEQUENCEEDIT_H
#include <QtWidgets/qwidget.h>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_KEYSEQUENCEEDIT
class QKeySequenceEditPrivate;
class Q_WIDGETS_EXPORT QKeySequenceEdit : public QWidget
{
Q_OBJECT
Q_PROPERTY(QKeySequence keySequence READ keySequence WRITE setKeySequence RESET clear NOTIFY keySequenceChanged USER true)
public:
explicit QKeySequenceEdit(QWidget *parent = 0);
explicit QKeySequenceEdit(const QKeySequence &keySequence, QWidget *parent = 0);
~QKeySequenceEdit();
QKeySequence keySequence() const;
void setKeySequence(const QKeySequence &keySequence);
public Q_SLOTS:
void clear();
Q_SIGNALS:
void editingFinished();
void keySequenceChanged(const QKeySequence &keySequence);
protected:
QKeySequenceEdit(QKeySequenceEditPrivate &d, QWidget *parent, Qt::WindowFlags f);
bool event(QEvent *) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE;
void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QKeySequenceEdit)
Q_DECLARE_PRIVATE(QKeySequenceEdit)
};
#endif // QT_NO_KEYSEQUENCEEDIT
QT_END_NAMESPACE
#endif // QKEYSEQUENCEEDIT_H

View File

@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Ivan Komissarov.
** Contact: http://www.qt-project.org/legal
**
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 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 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QKEYSEQUENCEEDIT_P_H
#define QKEYSEQUENCEEDIT_P_H
#include "qkeysequenceedit.h"
#include <private/qwidget_p.h>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_KEYSEQUENCEEDIT
class QLineEdit;
class QVBoxLayout;
class QKeySequenceEditPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QKeySequenceEdit)
public:
enum { MaxKeyCount = 4 };
void init();
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
void resetState();
void finishEditing();
QLineEdit *lineEdit;
QVBoxLayout *layout;
QKeySequence keySequence;
int keyNum;
int key[MaxKeyCount];
int prevKey;
int releaseTimer;
};
#endif // QT_NO_KEYSEQUENCEEDIT
QT_END_NAMESPACE
#endif // QKEYSEQUENCEEDIT_P_H

View File

@ -25,6 +25,8 @@ HEADERS += \
widgets/qframe.h \
widgets/qframe_p.h \
widgets/qgroupbox.h \
widgets/qkeysequenceedit.h \
widgets/qkeysequenceedit_p.h \
widgets/qlabel.h \
widgets/qlabel_p.h \
widgets/qlcdnumber.h \
@ -99,6 +101,7 @@ SOURCES += \
widgets/qfontcombobox.cpp \
widgets/qframe.cpp \
widgets/qgroupbox.cpp \
widgets/qkeysequenceedit.cpp \
widgets/qlabel.cpp \
widgets/qlcdnumber.cpp \
widgets/qlineedit_p.cpp \

View File

@ -0,0 +1 @@
tst_qshortcutedit

View File

@ -0,0 +1,5 @@
CONFIG += testcase
CONFIG += parallel_test
TARGET = tst_qkeysequenceedit
QT += widgets testlib
SOURCES += tst_qkeysequenceedit.cpp

View File

@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 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 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QKeySequenceEdit>
Q_DECLARE_METATYPE(Qt::Key)
Q_DECLARE_METATYPE(Qt::KeyboardModifiers)
class tst_QKeySequenceEdit : public QObject
{
Q_OBJECT
private slots:
void testSetters();
void testKeys_data();
void testKeys();
};
void tst_QKeySequenceEdit::testSetters()
{
QKeySequenceEdit edit;
QSignalSpy spy(&edit, SIGNAL(keySequenceChanged(QKeySequence)));
QCOMPARE(edit.keySequence(), QKeySequence());
edit.setKeySequence(QKeySequence::New);
QCOMPARE(edit.keySequence(), QKeySequence(QKeySequence::New));
edit.clear();
QCOMPARE(edit.keySequence(), QKeySequence());
QCOMPARE(spy.count(), 2);
}
void tst_QKeySequenceEdit::testKeys_data()
{
QTest::addColumn<Qt::Key>("key");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<QKeySequence>("keySequence");
QTest::newRow("1") << Qt::Key_N << Qt::KeyboardModifiers(Qt::ControlModifier) << QKeySequence("Ctrl+N");
QTest::newRow("2") << Qt::Key_N << Qt::KeyboardModifiers(Qt::AltModifier) << QKeySequence("Alt+N");
QTest::newRow("3") << Qt::Key_N << Qt::KeyboardModifiers(Qt::ShiftModifier) << QKeySequence("Shift+N");
QTest::newRow("4") << Qt::Key_N << Qt::KeyboardModifiers(Qt::ControlModifier | Qt::ShiftModifier) << QKeySequence("Ctrl+Shift+N");
}
void tst_QKeySequenceEdit::testKeys()
{
QFETCH(Qt::Key, key);
QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(QKeySequence, keySequence);
QKeySequenceEdit edit;
QSignalSpy spy(&edit, SIGNAL(editingFinished()));
QTest::keyPress(&edit, key, modifiers);
QTest::keyRelease(&edit, key, modifiers);
QCOMPARE(spy.count(), 0);
QCOMPARE(edit.keySequence(), keySequence);
QTRY_COMPARE(spy.count(), 1);
}
QTEST_MAIN(tst_QKeySequenceEdit)
#include "tst_qkeysequenceedit.moc"

View File

@ -17,6 +17,7 @@ SUBDIRS=\
qfocusframe \
qfontcombobox \
qgroupbox \
qkeysequenceedit \
qlabel \
qlcdnumber \
qlineedit \