📄 qshortcutmap.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qshortcutmap_p.h"#include "private/qobject_p.h"#include "qkeysequence.h"#include "qdebug.h"#include "qevent.h"#include "qwidget.h"#include "qapplication.h"#include "qvector.h"#include "qmenu.h"#include "qshortcut.h"#include "qapplication_p.h"#include <private/qaction_p.h>#include <private/qkeymapper_p.h>#ifndef QT_NO_SHORTCUT// To enable verbose output uncomment below//#define DEBUG_QSHORTCUTMAP/* \internal Entry data for QShortcutMap Contains: Keysequence for entry Pointer to parent owning the sequence*/struct QShortcutEntry{ QShortcutEntry() : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0) {} QShortcutEntry(const QKeySequence &k) : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0) {} QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i) : keyseq(k), context(c), enabled(true), autorepeat(1), id(i), owner(o) {} QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a) : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o) {} bool operator<(const QShortcutEntry &f) const { return keyseq < f.keyseq; } QKeySequence keyseq; Qt::ShortcutContext context; bool enabled : 1; bool autorepeat : 1; signed int id; QObject *owner;};#ifndef QT_NO_DEBUG_STREAM/*! \internal QDebug operator<< for easy debug output of the shortcut entries.*/QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { if (!se) return dbg << "QShortcutEntry(0x0)"; dbg.nospace() << "QShortcutEntry(" << se->keyseq << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat << "), owner(" << se->owner << ")"; return dbg.space();}#endif // QT_NO_DEBUGSTREAM/* \internal Private data for QShortcutMap*/class QShortcutMapPrivate{ Q_DECLARE_PUBLIC(QShortcutMap)public: QShortcutMapPrivate(QShortcutMap* parent) : q_ptr(parent), currentId(0), ambigCount(0), currentState(QKeySequence::NoMatch) { identicals.reserve(10); currentSequences.reserve(10); } QShortcutMap *q_ptr; // Private's parent QList<QShortcutEntry> sequences; // All sequences! int currentId; // Global shortcut ID number int ambigCount; // Index of last enabled ambiguous dispatch QKeySequence::SequenceMatch currentState; QVector<QKeySequence> currentSequences; // Sequence for the current state QVector<QKeySequence> newEntries; QKeySequence prevSequence; // Sequence for the previous identical match QVector<const QShortcutEntry*> identicals; // Last identical matches};/*! \internal QShortcutMap constructor.*/QShortcutMap::QShortcutMap(){ d_ptr = new QShortcutMapPrivate(this); Q_ASSERT(d_ptr != 0); resetState();}/*! \internal QShortcutMap destructor.*/QShortcutMap::~QShortcutMap(){ delete d_ptr; d_ptr = 0;}/*! \internal Adds a shortcut to the global map. Returns the id of the newly added shortcut.*/int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context){ Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner"); Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map"); Q_D(QShortcutMap); QShortcutEntry newEntry(owner, key, context, --(d->currentId), true); QList<QShortcutEntry>::iterator it = qUpperBound(d->sequences.begin(), d->sequences.end(), newEntry); d->sequences.insert(it, newEntry); // Insert sorted#if defined(DEBUG_QSHORTCUTMAP) qDebug().nospace() << "QShortcutMap::addShortcut(" << owner << ", " << key << ", " << context << ") = " << d->currentId;#endif return d->currentId;}/*! \internal Removes a shortcut from the global map. If \a owner is 0, all entries in the map with the key sequence specified is removed. If \a key is null, all sequences for \a owner is removed from the map. If \a id is 0, any identical \a key sequences owned by \a owner are removed. Returns the number of sequences removed from the map.*/int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key){ Q_D(QShortcutMap); int itemsRemoved = 0; bool allOwners = (owner == 0); bool allKeys = key.isEmpty(); bool allIds = id == 0; // Special case, remove everything if (allOwners && allKeys && id == 0) { itemsRemoved = d->sequences.size(); d->sequences.clear(); return itemsRemoved; } int i = d->sequences.size()-1; while (i>=0) { const QShortcutEntry &entry = d->sequences.at(i); int entryId = entry.id; if ((allOwners || entry.owner == owner) && (allIds || entry.id == id) && (allKeys || entry.keyseq == key)) { d->sequences.removeAt(i); ++itemsRemoved; } if (id == entryId) return itemsRemoved; --i; }#if defined(DEBUG_QSHORTCUTMAP) qDebug().nospace() << "QShortcutMap::removeShortcut(" << id << ", " << owner << ", " << key << ") = " << itemsRemoved;#endif return itemsRemoved;}/*! \internal Changes the enable state of a shortcut to \a enable. If \a owner is 0, all entries in the map with the key sequence specified is removed. If \a key is null, all sequences for \a owner is removed from the map. If \a id is 0, any identical \a key sequences owned by \a owner are changed. Returns the number of sequences which are matched in the map.*/int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key){ Q_D(QShortcutMap); int itemsChanged = 0; bool allOwners = (owner == 0); bool allKeys = key.isEmpty(); bool allIds = id == 0; int i = d->sequences.size()-1; while (i>=0) { QShortcutEntry entry = d->sequences.at(i); if ((allOwners || entry.owner == owner) && (allIds || entry.id == id) && (allKeys || entry.keyseq == key)) { d->sequences[i].enabled = enable; ++itemsChanged; } if (id == entry.id) return itemsChanged; --i; }#if defined(DEBUG_QSHORTCUTMAP) qDebug().nospace() << "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", " << owner << ", " << key << ") = " << itemsChanged;#endif return itemsChanged;}/*! \internal Changes the auto repeat state of a shortcut to \a enable. If \a owner is 0, all entries in the map with the key sequence specified is removed. If \a key is null, all sequences for \a owner is removed from the map. If \a id is 0, any identical \a key sequences owned by \a owner are changed. Returns the number of sequences which are matched in the map.*/int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key){ Q_D(QShortcutMap); int itemsChanged = 0; bool allOwners = (owner == 0); bool allKeys = key.isEmpty(); bool allIds = id == 0; int i = d->sequences.size()-1; while (i>=0) { QShortcutEntry entry = d->sequences.at(i); if ((allOwners || entry.owner == owner) && (allIds || entry.id == id) && (allKeys || entry.keyseq == key)) { d->sequences[i].autorepeat = on; ++itemsChanged; } if (id == entry.id) return itemsChanged; --i; }#if defined(DEBUG_QSHORTCUTMAP) qDebug().nospace() << "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", " << owner << ", " << key << ") = " << itemsChanged;#endif return itemsChanged;}/*! \internal Resets the state of the statemachine to NoMatch*/void QShortcutMap::resetState(){ Q_D(QShortcutMap); d->currentState = QKeySequence::NoMatch; clearSequence(d->currentSequences);}/*! \internal Returns the current state of the statemachine*/QKeySequence::SequenceMatch QShortcutMap::state(){ Q_D(QShortcutMap); return d->currentState;}/*! \internal Uses ShortcutOverride event to see if any widgets want to override the event. If not, uses nextState(QKeyEvent) to check for a grabbed Shortcut, and dispatchEvent() is found an identical. \sa nextState dispatchEvent*/bool QShortcutMap::tryShortcutEvent(QWidget *w, QKeyEvent *e){ Q_D(QShortcutMap); bool wasAccepted = e->isAccepted(); if (d->currentState == QKeySequence::NoMatch) { ushort orgType = e->t; e->t = QEvent::ShortcutOverride; e->ignore(); QApplication::sendSpontaneousEvent(w, e); e->t = orgType; if (e->isAccepted()) { if (!wasAccepted) e->ignore(); return false; } } QKeySequence::SequenceMatch result = nextState(e); bool stateWasAccepted = e->isAccepted(); if (wasAccepted) e->accept(); else e->ignore(); int identicalMatches = d->identicals.count(); switch(result) { case QKeySequence::NoMatch: return stateWasAccepted; case QKeySequence::ExactMatch: resetState(); dispatchEvent(e); default: break; } // If nextState is QKeySequence::ExactMatch && identicals.count == 0 // we've only found disabled shortcuts return identicalMatches > 0 || result == QKeySequence::PartialMatch;}/*! \internal Returns the next state of the statemachine If return value is SequenceMatch::ExactMatch, then a call to matches() will return a QObjects* list of all matching objects for the last matching sequence.*/QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e){ Q_D(QShortcutMap); // Modifiers can NOT be shortcuts... if (e->key() >= Qt::Key_Shift && e->key() <= Qt::Key_Alt) return d->currentState; QKeySequence::SequenceMatch result = QKeySequence::NoMatch; // We start fresh each time.. d->identicals.resize(0); result = find(e); if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) { // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -