File indexing completed on 2024-06-16 04:15:39

0001 /* This file is part of the KDE libraries SPDX-FileCopyrightText: 1998 Mark Donohoe <donohoe@kde.org>
0002     SPDX-FileCopyrightText: 1997 Nicolas Hadacek <hadacek@kde.org>
0003     SPDX-FileCopyrightText: 1998 Matthias Ettrich <ettrich@kde.org>
0004     SPDX-FileCopyrightText: 2001 Ellis Whitehead <ellis@kde.org>
0005     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0006     SPDX-FileCopyrightText: 2007 Roberto Raggi <roberto@kdevelop.org>
0007     SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com>
0008     SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz>
0009 
0010     SPDX-License-Identifier: LGPL-2.0-or-later
0011 */
0012 
0013 #include "KisShortcutsDialog_p.h"
0014 #include "KisShortcutsEditor_p.h"
0015 
0016 #include <QAction>
0017 #include <QTreeWidgetItem>
0018 #include <kis_debug.h>
0019 
0020 
0021 KisShortcutsEditorItem::KisShortcutsEditorItem(QTreeWidgetItem *parent, QAction *action)
0022     : QTreeWidgetItem(parent, ActionItem)
0023     , m_action(action)
0024 {
0025     // Filtering message requested by translators (scripting).
0026     m_id = m_action->objectName();
0027     m_actionNameInTable = i18nc("@item:intable Action name in shortcuts configuration",
0028                                 "%1", KLocalizedString::removeAcceleratorMarker(m_action->text()));
0029     if (m_actionNameInTable.isEmpty()) {
0030         warnKrita << "Action without text!" << m_action->objectName();
0031         m_actionNameInTable = m_id;
0032     }
0033 
0034     m_collator.setNumericMode(true);
0035     m_collator.setCaseSensitivity(Qt::CaseSensitive);
0036 
0037     // qDebug() << "Adding new action" << m_id << "with shortcut" << keySequence(LocalPrimary).toString();
0038 }
0039 
0040 KisShortcutsEditorItem::~KisShortcutsEditorItem()
0041 {
0042     delete m_oldLocalShortcut;
0043 }
0044 
0045 bool KisShortcutsEditorItem::isModified() const
0046 {
0047     return m_oldLocalShortcut;
0048 }
0049 
0050 QVariant KisShortcutsEditorItem::data(int column, int role) const
0051 {
0052     switch (role) {
0053     case Qt::DisplayRole:
0054         switch (column) {
0055         case Name:
0056             return m_actionNameInTable;
0057         case Id:
0058             return m_id;
0059         case LocalPrimary:
0060         case LocalAlternate:
0061             return QVariant::fromValue(keySequence(column));
0062         default:
0063             break;
0064         }
0065         break;
0066     case Qt::DecorationRole:
0067         if (column == Name) {
0068             return m_action->icon();
0069         } else {
0070             return QIcon();
0071         }
0072         break;
0073     case Qt::WhatsThisRole:
0074         return m_action->whatsThis();
0075     case Qt::ToolTipRole:
0076         // TODO: show command descriptions/tooltips in the shortcut editor
0077         return QVariant();
0078     case Qt::FontRole:
0079         if (column == Name && m_isNameBold) {
0080             QFont modifiedFont = treeWidget()->font();
0081             modifiedFont.setBold(true);
0082             return modifiedFont;
0083         }
0084         break;
0085     case KExtendableItemDelegate::ShowExtensionIndicatorRole:
0086         switch (column) {
0087         case Name:
0088             return false;
0089         case LocalPrimary:
0090         case LocalAlternate:
0091             return !m_action->property("isShortcutConfigurable").isValid()
0092                    || m_action->property("isShortcutConfigurable").toBool();
0093         default:
0094             return false;
0095         }
0096     //the following are custom roles, defined in this source file only
0097     case ShortcutRole:
0098         switch (column) {
0099         case LocalPrimary:
0100         case LocalAlternate:
0101             return QVariant::fromValue(keySequence(column));
0102         default:
0103             // Column not valid for this role
0104             Q_ASSERT(false);
0105             return QVariant();
0106         }
0107 
0108     case DefaultShortcutRole: {
0109 
0110         // Note: we are using the QMetaObject system to store this property.
0111         QList<QKeySequence> defaultShortcuts = m_action->property("defaultShortcuts").value<QList<QKeySequence> >();
0112 
0113         switch (column) {
0114         case LocalPrimary:
0115             return QVariant::fromValue(primarySequence(defaultShortcuts));
0116         case LocalAlternate:
0117             return QVariant::fromValue(alternateSequence(defaultShortcuts));
0118         default:
0119             // Column not valid for this role
0120             Q_ASSERT(false);
0121             return QVariant();
0122         }
0123     }
0124     case ObjectRole:
0125         return QVariant::fromValue((QObject *)m_action);
0126 
0127     default:
0128         break;
0129     }
0130 
0131     return QVariant();
0132 }
0133 
0134 bool KisShortcutsEditorItem::operator<(const QTreeWidgetItem &other) const
0135 {
0136     const int column = treeWidget() ? treeWidget()->sortColumn() : 0;
0137     return m_collator.compare(text(column), other.text(column)) < 0;
0138 }
0139 
0140 QKeySequence KisShortcutsEditorItem::keySequence(uint column) const
0141 {
0142     QList<QKeySequence> shortcuts = m_action->shortcuts();
0143 
0144     switch (column) {
0145     case LocalPrimary:
0146         return primarySequence(shortcuts);
0147     case LocalAlternate:
0148         return alternateSequence(shortcuts);
0149     default:
0150         return QKeySequence();
0151     }
0152 }
0153 
0154 void KisShortcutsEditorItem::setKeySequence(uint column, const QKeySequence &seq)
0155 {
0156     QList<QKeySequence> ks;
0157     ks = m_action->shortcuts();
0158     if (!m_oldLocalShortcut) {
0159         m_oldLocalShortcut = new QList<QKeySequence>(ks);
0160     }
0161 
0162     if (column == LocalAlternate) {
0163         if (ks.isEmpty()) {
0164             ks << QKeySequence();
0165         }
0166 
0167         if (ks.size() <= 1) {
0168             ks << seq;
0169         } else {
0170             ks[1] = seq;
0171         }
0172     } else {
0173         if (ks.isEmpty()) {
0174             ks << seq;
0175         } else {
0176             ks[0] = seq;
0177         }
0178     }
0179 
0180     m_action->setShortcuts(ks);
0181 
0182     updateModified();
0183 }
0184 
0185 //our definition of modified is "modified since the chooser was shown".
0186 void KisShortcutsEditorItem::updateModified()
0187 {
0188     if (m_oldLocalShortcut && *m_oldLocalShortcut == m_action->shortcuts()) {
0189         delete m_oldLocalShortcut;
0190         m_oldLocalShortcut = 0;
0191     }
0192 }
0193 
0194 bool KisShortcutsEditorItem::isModified(uint column) const
0195 {
0196     switch (column) {
0197     case Name:
0198         return false;
0199     case LocalPrimary:
0200     case LocalAlternate:
0201         if (!m_oldLocalShortcut) {
0202             return false;
0203         }
0204         if (column == LocalPrimary) {
0205             return primarySequence(*m_oldLocalShortcut) != primarySequence(m_action->shortcuts());
0206         } else {
0207             return alternateSequence(*m_oldLocalShortcut) != alternateSequence(m_action->shortcuts());
0208         }
0209     default:
0210         return false;
0211     }
0212 }
0213 
0214 void KisShortcutsEditorItem::undo()
0215 {
0216     //dbgKrita << "Undoing changes for " << data(Name, Qt::DisplayRole).toString();
0217 
0218     if (m_oldLocalShortcut) {
0219         // We only ever reset the active Shortcut
0220         m_action->setShortcuts(*m_oldLocalShortcut);
0221     }
0222 
0223     updateModified();
0224 }
0225 
0226 void KisShortcutsEditorItem::commit()
0227 {
0228     if (m_oldLocalShortcut) { // || m_oldShapeGesture || m_oldRockerGesture) {
0229        dbgUI << "Committing changes for " << data(Name, Qt::DisplayRole).toString();
0230     }
0231 
0232     delete m_oldLocalShortcut;
0233     m_oldLocalShortcut = 0;
0234 }