File indexing completed on 2024-03-24 15:27:45
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org> 0003 Copyright (C) 2006 Hamish Rodda <rodda@kde.org> 0004 Copyright (C) 2006 Andreas Hartmetz <ahartmetz@gmail.com> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "kshortcut.h" 0023 0024 #include <QActionEvent> 0025 #include <QKeySequence> 0026 #include <QCharRef> 0027 #include <QMutableStringListIterator> 0028 0029 #include "kdebug.h" 0030 #include "klocalizedstring.h" 0031 0032 class KShortcutPrivate 0033 { 0034 public: 0035 KShortcutPrivate() {} 0036 0037 QKeySequence primary; 0038 QKeySequence alternate; 0039 }; 0040 0041 KShortcut::KShortcut() 0042 : d(new KShortcutPrivate) 0043 { 0044 qRegisterMetaType<KShortcut>(); 0045 } 0046 0047 KShortcut::KShortcut(const QKeySequence &primary) 0048 : d(new KShortcutPrivate) 0049 { 0050 qRegisterMetaType<KShortcut>(); 0051 d->primary = primary; 0052 } 0053 0054 KShortcut::KShortcut(const QKeySequence &primary, const QKeySequence &alternate) 0055 : d(new KShortcutPrivate) 0056 { 0057 qRegisterMetaType<KShortcut>(); 0058 d->primary = primary; 0059 d->alternate = alternate; 0060 } 0061 0062 KShortcut::KShortcut(int keyQtPri, int keyQtAlt) 0063 : d(new KShortcutPrivate) 0064 { 0065 qRegisterMetaType<KShortcut>(); 0066 d->primary = keyQtPri; 0067 d->alternate = keyQtAlt; 0068 } 0069 0070 KShortcut::KShortcut(const KShortcut &other) 0071 : d(new KShortcutPrivate) 0072 { 0073 d->primary = other.d->primary; 0074 d->alternate = other.d->alternate; 0075 } 0076 0077 KShortcut::KShortcut(const QList<QKeySequence> &seqs) 0078 : d(new KShortcutPrivate) 0079 { 0080 qRegisterMetaType<KShortcut>(); 0081 if (seqs.count() >= 1) { 0082 d->primary = seqs.at(0); 0083 } 0084 if (seqs.count() >= 2) { 0085 d->alternate = seqs.at(1); 0086 } 0087 } 0088 0089 KShortcut::KShortcut(const QString &s) 0090 : d(new KShortcutPrivate) 0091 { 0092 qRegisterMetaType<KShortcut>(); 0093 if (s == QLatin1String("none")) { 0094 return; 0095 } 0096 0097 QStringList sCuts = s.split("; "); 0098 if (sCuts.count() > 2) { 0099 kWarning() << "asked to store more than two key sequences but can only hold two."; 0100 } 0101 0102 //TODO: what is the "(default)" thingie used for? 0103 for (int i = 0; i < sCuts.count(); i++) 0104 if (sCuts[i].startsWith(QLatin1String("default("))) { 0105 sCuts[i] = sCuts[i].mid(8, sCuts[i].length() - 9); 0106 } 0107 0108 if (sCuts.count() >= 1) { 0109 QString k = sCuts.at(0); 0110 k.replace("Win+", "Meta+"); // workaround for KDE3-style shortcuts 0111 k.replace("Plus", "+"); // workaround for KDE3-style "Alt+Plus" 0112 k.replace("Minus", "-"); // workaround for KDE3-style "Alt+Plus" 0113 d->primary = QKeySequence::fromString(k); 0114 // Complain about a unusable shortcuts sequence only if we have got 0115 // something. 0116 if (d->primary.isEmpty() && !k.isEmpty()) { 0117 qDebug() << "unusable primary shortcut sequence " << sCuts[0]; 0118 } 0119 } 0120 0121 if (sCuts.count() >= 2) { 0122 QString k = sCuts.at(1); 0123 k.replace("Win+", "Meta+"); // workaround for KDE3-style shortcuts 0124 d->alternate = QKeySequence::fromString(k); 0125 if (d->alternate.isEmpty()) { 0126 qDebug() << "unusable alternate shortcut sequence " << sCuts[1]; 0127 } 0128 } 0129 } 0130 0131 KShortcut::~KShortcut() 0132 { 0133 delete d; 0134 } 0135 0136 QKeySequence KShortcut::primary() const 0137 { 0138 return d->primary; 0139 } 0140 0141 QKeySequence KShortcut::alternate() const 0142 { 0143 return d->alternate; 0144 } 0145 0146 bool KShortcut::isEmpty() const 0147 { 0148 return d->primary.isEmpty() && d->alternate.isEmpty(); 0149 } 0150 0151 bool KShortcut::contains(const QKeySequence &needle) const 0152 { 0153 if (needle.isEmpty()) { 0154 return false; 0155 } 0156 return d->primary == needle || d->alternate == needle; 0157 } 0158 0159 bool KShortcut::conflictsWith(const QKeySequence &needle) const 0160 { 0161 if (needle.isEmpty()) { 0162 return false; 0163 } 0164 0165 bool primaryConflicts = false; 0166 bool alternateConflicts = false; 0167 0168 if (!d->primary.isEmpty()) { 0169 primaryConflicts = 0170 (d->primary.matches(needle) == QKeySequence::NoMatch 0171 && needle.matches(d->primary) == QKeySequence::NoMatch) 0172 ? false 0173 : true; 0174 } 0175 0176 if (!d->alternate.isEmpty()) { 0177 alternateConflicts = 0178 (d->alternate.matches(needle) == QKeySequence::NoMatch 0179 && needle.matches(d->alternate) == QKeySequence::NoMatch) 0180 ? false 0181 : true; 0182 } 0183 0184 return primaryConflicts || alternateConflicts; 0185 } 0186 0187 void KShortcut::setPrimary(const QKeySequence &newPrimary) 0188 { 0189 d->primary = newPrimary; 0190 } 0191 0192 void KShortcut::setAlternate(const QKeySequence &newAlternate) 0193 { 0194 d->alternate = newAlternate; 0195 } 0196 0197 void KShortcut::remove(const QKeySequence &keySeq, enum EmptyHandling handleEmpty) 0198 { 0199 if (keySeq.isEmpty()) { 0200 return; 0201 } 0202 0203 if (d->primary == keySeq) { 0204 if (handleEmpty == KeepEmpty) { 0205 d->primary = QKeySequence(); 0206 } else { 0207 d->primary = d->alternate; 0208 d->alternate = QKeySequence(); 0209 } 0210 } 0211 if (d->alternate == keySeq) { 0212 d->alternate = QKeySequence(); 0213 } 0214 } 0215 0216 KShortcut &KShortcut::operator=(const KShortcut &other) 0217 { 0218 d->primary = other.d->primary; 0219 d->alternate = other.d->alternate; 0220 return (*this); 0221 } 0222 0223 bool KShortcut::operator==(const KShortcut &other) const 0224 { 0225 return (d->primary == other.d->primary && d->alternate == other.d->alternate); 0226 } 0227 0228 bool KShortcut::operator!=(const KShortcut &other) const 0229 { 0230 return !operator==(other); 0231 } 0232 0233 KShortcut::operator QList<QKeySequence>() const 0234 { 0235 return toList(RemoveEmpty); 0236 } 0237 0238 QList<QKeySequence> KShortcut::toList(enum EmptyHandling handleEmpty) const 0239 { 0240 QList<QKeySequence> ret; 0241 if (handleEmpty == RemoveEmpty) { 0242 if (!d->primary.isEmpty()) { 0243 ret.append(d->primary); 0244 } 0245 if (!d->alternate.isEmpty()) { 0246 ret.append(d->alternate); 0247 } 0248 } else { 0249 ret.append(d->primary); 0250 ret.append(d->alternate); 0251 } 0252 0253 return ret; 0254 } 0255 0256 QString KShortcut::toString() const 0257 { 0258 return toString(QKeySequence::PortableText); 0259 } 0260 0261 QString KShortcut::toString(QKeySequence::SequenceFormat format) const 0262 { 0263 QString ret; 0264 foreach (const QKeySequence &seq, toList()) { 0265 ret.append(seq.toString(format)); 0266 ret.append("; "); 0267 } 0268 ret.chop(2); 0269 return ret; 0270 } 0271 0272 KShortcut::operator QVariant() const 0273 { 0274 return QVariant::fromValue(*this); 0275 }