QKeySequence: use QKeySequencePrivate::MaxKeyCount everywhere

The MaxKeyCount symbolic constant was introduced for use by QKeySequenceEdit,
but never applied to QKeySequence itself. To prevent the two from getting
out of sync, use it in the QKeySequence implementation itself, too.

This required re-writing most expressions involving QKeySequenceEditPrivate::keys
with algorithms, but we already determined in the discussion around 1cf9a139
that GCC generates the same code as the loops unrolled by hand, and if Clang
doesn't, it's its own fault.

Where using MaxKeysCount was not possible, e.g. in documentation,
static_asserts were used to indicate the need for manual changes.

Change-Id: I559fffdfd552d488448ba4a5a1ac10708c16a2ae
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2014-08-27 11:53:47 +02:00
parent 05bcc9d2fc
commit 91ab18c0c9
2 changed files with 15 additions and 24 deletions

View File

@ -819,6 +819,7 @@ QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat form
assign(key, format);
}
Q_STATIC_ASSERT_X(QKeySequencePrivate::MaxKeyCount == 4, "Change docs and ctor impl below");
/*!
Constructs a key sequence with up to 4 keys \a k1, \a k2,
\a k3 and \a k4.
@ -877,26 +878,19 @@ QKeySequence::~QKeySequence()
void QKeySequence::setKey(int key, int index)
{
Q_ASSERT_X(index >= 0 && index < 4, "QKeySequence::setKey", "index out of range");
Q_ASSERT_X(index >= 0 && index < QKeySequencePrivate::MaxKeyCount, "QKeySequence::setKey", "index out of range");
qAtomicDetach(d);
d->key[index] = key;
}
Q_STATIC_ASSERT_X(QKeySequencePrivate::MaxKeyCount == 4, "Change docs below");
/*!
Returns the number of keys in the key sequence.
The maximum is 4.
*/
int QKeySequence::count() const
{
if (!d->key[0])
return 0;
if (!d->key[1])
return 1;
if (!d->key[2])
return 2;
if (!d->key[3])
return 3;
return 4;
return int(std::distance(d->key, std::find(d->key, d->key + QKeySequencePrivate::MaxKeyCount, 0)));
}
@ -988,8 +982,8 @@ int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
int p = 0, diff = 0;
// Run through the whole string, but stop
// if we have 4 keys before the end.
while (keyseq.length() && n < 4) {
// if we have MaxKeyCount keys before the end.
while (keyseq.length() && n < QKeySequencePrivate::MaxKeyCount) {
// We MUST use something to separate each sequence, and space
// does not cut it, since some of the key names have space
// in them.. (Let's hope no one translate with a comma in it:)
@ -1367,7 +1361,7 @@ QKeySequence::operator QVariant() const
*/
int QKeySequence::operator[](uint index) const
{
Q_ASSERT_X(index < 4, "QKeySequence::operator[]", "index out of range");
Q_ASSERT_X(index < QKeySequencePrivate::MaxKeyCount, "QKeySequence::operator[]", "index out of range");
return d->key[index];
}
@ -1435,10 +1429,8 @@ uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW
*/
bool QKeySequence::operator< (const QKeySequence &other) const
{
for (int i = 0; i < 4; ++i)
if (d->key[i] != other.d->key[i])
return d->key[i] < other.d->key[i];
return false;
return std::lexicographical_compare(d->key, d->key + QKeySequencePrivate::MaxKeyCount,
other.d->key, other.d->key + QKeySequencePrivate::MaxKeyCount);
}
/*!

View File

@ -47,6 +47,8 @@
#include "qkeysequence.h"
#include <algorithm>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_SHORTCUT
@ -61,20 +63,17 @@ struct Q_AUTOTEST_EXPORT QKeyBinding
class Q_AUTOTEST_EXPORT QKeySequencePrivate
{
public:
enum { MaxKeyCount = 4 }; // used in QKeySequenceEdit
enum { MaxKeyCount = 4 }; // also used in QKeySequenceEdit
inline QKeySequencePrivate() : ref(1)
{
key[0] = key[1] = key[2] = key[3] = 0;
std::fill_n(key, uint(MaxKeyCount), 0);
}
inline QKeySequencePrivate(const QKeySequencePrivate &copy) : ref(1)
{
key[0] = copy.key[0];
key[1] = copy.key[1];
key[2] = copy.key[2];
key[3] = copy.key[3];
std::copy(copy.key, copy.key + MaxKeyCount, key);
}
QAtomicInt ref;
int key[4];
int key[MaxKeyCount];
static QString encodeString(int key, QKeySequence::SequenceFormat format);
static int decodeString(const QString &keyStr, QKeySequence::SequenceFormat format);
};