File indexing completed on 2024-09-01 03:49:49
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1998 Mark Donohoe <donohoe@kde.org> 0004 SPDX-FileCopyrightText: 1997 Nicolas Hadacek <hadacek@kde.org> 0005 SPDX-FileCopyrightText: 1998 Matthias Ettrich <ettrich@kde.org> 0006 SPDX-FileCopyrightText: 2001 Ellis Whitehead <ellis@kde.org> 0007 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0008 SPDX-FileCopyrightText: 2007 Roberto Raggi <roberto@kdevelop.org> 0009 SPDX-FileCopyrightText: 2007 Andreas Hartmetz <ahartmetz@gmail.com> 0010 SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz> 0011 SPDX-FileCopyrightText: 2008 Alexander Dymo <adymo@kdevelop.org> 0012 SPDX-FileCopyrightText: 2009 Chani Armitage <chani@kde.org> 0013 0014 SPDX-License-Identifier: LGPL-2.0-or-later 0015 */ 0016 0017 #include "kshortcutsdialog.h" 0018 #include "kshortcutschemeshelper_p.h" 0019 #include "kshortcutsdialog_p.h" 0020 0021 #include <QApplication> 0022 #include <QDialogButtonBox> 0023 #include <QDomDocument> 0024 0025 #include <KConfigGroup> 0026 #include <KLocalizedString> 0027 #include <KMessageBox> 0028 #include <KSharedConfig> 0029 0030 #include "kactioncollection.h" 0031 #include "kxmlguiclient.h" 0032 #include "kxmlguifactory.h" 0033 0034 /************************************************************************/ 0035 /* KShortcutsDialog */ 0036 /* */ 0037 /* Originally by Nicolas Hadacek <hadacek@via.ecp.fr> */ 0038 /* */ 0039 /* Substantially revised by Mark Donohoe <donohoe@kde.org> */ 0040 /* */ 0041 /* And by Espen Sand <espen@kde.org> 1999-10-19 */ 0042 /* (by using KDialog there is almost no code left ;) */ 0043 /* */ 0044 /************************************************************************/ 0045 0046 QKeySequence primarySequence(const QList<QKeySequence> &sequences) 0047 { 0048 return sequences.isEmpty() ? QKeySequence() : sequences.at(0); 0049 } 0050 0051 QKeySequence alternateSequence(const QList<QKeySequence> &sequences) 0052 { 0053 return sequences.size() <= 1 ? QKeySequence() : sequences.at(1); 0054 } 0055 0056 class KShortcutsDialogPrivate 0057 { 0058 public: 0059 KShortcutsDialogPrivate(KShortcutsDialog *qq) 0060 : q(qq) 0061 { 0062 } 0063 0064 QList<KActionCollection *> m_collections; 0065 0066 void changeShortcutScheme(const QString &scheme) 0067 { 0068 if (m_keyChooser->isModified() 0069 && KMessageBox::questionTwoActions(q, 0070 i18n("The current shortcut scheme is modified. Save before switching to the new one?"), 0071 QString(), 0072 KStandardGuiItem::save(), 0073 KStandardGuiItem::discard()) 0074 == KMessageBox::PrimaryAction) { 0075 m_keyChooser->save(); 0076 } else { 0077 m_keyChooser->undo(); 0078 } 0079 0080 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 0081 m_keyChooser->clearCollections(); 0082 0083 for (KActionCollection *collection : std::as_const(m_collections)) { 0084 // passing an empty stream forces the clients to reread the XML 0085 KXMLGUIClient *client = const_cast<KXMLGUIClient *>(collection->parentGUIClient()); 0086 if (client) { 0087 client->setXMLGUIBuildDocument(QDomDocument()); 0088 } 0089 } 0090 0091 // get xmlguifactory 0092 if (!m_collections.isEmpty()) { 0093 const KXMLGUIClient *client = m_collections.first()->parentGUIClient(); 0094 if (client) { 0095 KXMLGUIFactory *factory = client->factory(); 0096 if (factory) { 0097 factory->changeShortcutScheme(scheme); 0098 } 0099 } 0100 } 0101 0102 for (KActionCollection *collection : std::as_const(m_collections)) { 0103 m_keyChooser->addCollection(collection); 0104 } 0105 0106 QApplication::restoreOverrideCursor(); 0107 } 0108 0109 void undo() 0110 { 0111 m_keyChooser->undo(); 0112 } 0113 0114 void toggleDetails() 0115 { 0116 const bool isVisible = m_schemeEditor->isVisible(); 0117 0118 m_schemeEditor->setVisible(!isVisible); 0119 m_detailsButton->setText(detailsButtonText() + (isVisible ? QStringLiteral(" >>") : QStringLiteral(" <<"))); 0120 } 0121 0122 static QString detailsButtonText() 0123 { 0124 return i18n("Manage &Schemes"); 0125 } 0126 0127 void save() 0128 { 0129 m_keyChooser->save(); 0130 Q_EMIT q->saved(); 0131 } 0132 0133 KShortcutsDialog *const q; 0134 KShortcutsEditor *m_keyChooser = nullptr; // ### move 0135 KShortcutSchemesEditor *m_schemeEditor = nullptr; 0136 QPushButton *m_detailsButton = nullptr; 0137 bool m_saveSettings = false; 0138 }; 0139 0140 KShortcutsDialog::KShortcutsDialog(QWidget *parent) 0141 : KShortcutsDialog(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, parent) 0142 { 0143 } 0144 0145 KShortcutsDialog::KShortcutsDialog(KShortcutsEditor::ActionTypes types, KShortcutsEditor::LetterShortcuts allowLetterShortcuts, QWidget *parent) 0146 : QDialog(parent) 0147 , d(new KShortcutsDialogPrivate(this)) 0148 { 0149 setWindowTitle(i18nc("@title:window", "Configure Keyboard Shortcuts")); 0150 setModal(true); 0151 0152 QVBoxLayout *layout = new QVBoxLayout(this); 0153 0154 d->m_keyChooser = new KShortcutsEditor(this, types, allowLetterShortcuts); 0155 layout->addWidget(d->m_keyChooser); 0156 0157 d->m_schemeEditor = new KShortcutSchemesEditor(this); 0158 connect(d->m_schemeEditor, &KShortcutSchemesEditor::shortcutsSchemeChanged, this, [this](const QString &scheme) { 0159 d->changeShortcutScheme(scheme); 0160 }); 0161 d->m_schemeEditor->hide(); 0162 layout->addWidget(d->m_schemeEditor); 0163 0164 d->m_detailsButton = new QPushButton; 0165 d->m_detailsButton->setText(KShortcutsDialogPrivate::detailsButtonText() + QLatin1String(" >>")); 0166 0167 QPushButton *printButton = new QPushButton; 0168 KGuiItem::assign(printButton, KStandardGuiItem::print()); 0169 0170 QDialogButtonBox *buttonBox = new QDialogButtonBox(this); 0171 buttonBox->addButton(d->m_detailsButton, QDialogButtonBox::ActionRole); 0172 buttonBox->addButton(printButton, QDialogButtonBox::ActionRole); 0173 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); 0174 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); 0175 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); 0176 KGuiItem::assign(buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults()); 0177 layout->addWidget(buttonBox); 0178 0179 connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, d->m_keyChooser, &KShortcutsEditor::allDefault); 0180 connect(d->m_detailsButton, &QPushButton::clicked, this, [this]() { 0181 d->toggleDetails(); 0182 }); 0183 connect(printButton, &QPushButton::clicked, d->m_keyChooser, &KShortcutsEditor::printShortcuts); 0184 connect(buttonBox, &QDialogButtonBox::rejected, this, [this]() { 0185 d->undo(); 0186 }); 0187 0188 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0189 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0190 0191 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("KShortcutsDialog Settings")); 0192 resize(group.readEntry("Dialog Size", sizeHint())); 0193 } 0194 0195 KShortcutsDialog::~KShortcutsDialog() 0196 { 0197 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("KShortcutsDialog Settings")); 0198 group.writeEntry("Dialog Size", size(), KConfigGroup::Persistent | KConfigGroup::Global); 0199 } 0200 0201 void KShortcutsDialog::addCollection(KActionCollection *collection, const QString &title) 0202 { 0203 d->m_keyChooser->addCollection(collection, title); 0204 d->m_collections << collection; 0205 } 0206 0207 QList<KActionCollection *> KShortcutsDialog::actionCollections() const 0208 { 0209 return d->m_collections; 0210 } 0211 0212 // TODO KF6: remove this method, always save settings, and open the 0213 // dialog with show() not exec() 0214 bool KShortcutsDialog::configure(bool saveSettings) 0215 { 0216 d->m_saveSettings = saveSettings; 0217 if (isModal()) { 0218 int retcode = exec(); 0219 return retcode; 0220 } else { 0221 show(); 0222 return false; 0223 } 0224 } 0225 0226 void KShortcutsDialog::accept() 0227 { 0228 if (d->m_saveSettings) { 0229 d->save(); 0230 } 0231 QDialog::accept(); 0232 } 0233 0234 QSize KShortcutsDialog::sizeHint() const 0235 { 0236 return QSize(600, 480); 0237 } 0238 0239 // static 0240 void KShortcutsDialog::showDialog(KActionCollection *collection, KShortcutsEditor::LetterShortcuts allowLetterShortcuts, QWidget *parent) 0241 { 0242 auto *dlg = new KShortcutsDialog(KShortcutsEditor::AllActions, allowLetterShortcuts, parent); 0243 dlg->setAttribute(Qt::WA_DeleteOnClose); 0244 0245 dlg->d->m_saveSettings = true; // Always save settings if the dialog is accepted 0246 0247 dlg->addCollection(collection); 0248 dlg->show(); 0249 } 0250 0251 void KShortcutsDialog::importConfiguration(const QString &path) 0252 { 0253 KConfig config(path); 0254 d->m_keyChooser->importConfiguration(static_cast<KConfigBase *>(&config)); 0255 } 0256 0257 void KShortcutsDialog::exportConfiguration(const QString &path) const 0258 { 0259 KConfig config(path); 0260 d->m_keyChooser->exportConfiguration(static_cast<KConfigBase *>(&config)); 0261 } 0262 0263 void KShortcutsDialog::refreshSchemes() 0264 { 0265 d->m_schemeEditor->refreshSchemes(); 0266 } 0267 0268 void KShortcutsDialog::addActionToSchemesMoreButton(QAction *action) 0269 { 0270 d->m_schemeEditor->addMoreMenuAction(action); 0271 } 0272 0273 #include "moc_kshortcutsdialog.cpp" 0274 #include "moc_kshortcutsdialog_p.cpp"