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 }