File indexing completed on 2025-02-09 04:30:15
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Alexander Dymo <adymo@kdevelop.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 #include "kshortcutsdialog_p.h" 0008 0009 #include <QComboBox> 0010 #include <QDir> 0011 #include <QDomDocument> 0012 #include <QFile> 0013 #include <QFileDialog> 0014 #include <QInputDialog> 0015 #include <QLabel> 0016 #include <QMenu> 0017 #include <QPushButton> 0018 #include <QStandardPaths> 0019 #include <QTextStream> 0020 0021 #include <KConfigGroup> 0022 #include <KMessageBox> 0023 #include <KSharedConfig> 0024 0025 #include "kactioncollection.h" 0026 #include "kshortcutschemeshelper_p.h" 0027 #include "kshortcutsdialog.h" 0028 #include "kxmlguiclient.h" 0029 #include <debug.h> 0030 0031 KShortcutSchemesEditor::KShortcutSchemesEditor(KShortcutsDialog *parent) 0032 : QGroupBox(i18nc("@title:group", "Shortcut Schemes"), parent) 0033 , m_dialog(parent) 0034 { 0035 QHBoxLayout *l = new QHBoxLayout(this); 0036 0037 QLabel *schemesLabel = new QLabel(i18n("Current scheme:"), this); 0038 l->addWidget(schemesLabel); 0039 0040 m_schemesList = new QComboBox(this); 0041 m_schemesList->setEditable(false); 0042 refreshSchemes(); 0043 m_schemesList->setSizeAdjustPolicy(QComboBox::AdjustToContents); 0044 schemesLabel->setBuddy(m_schemesList); 0045 l->addWidget(m_schemesList); 0046 0047 m_newScheme = new QPushButton(QIcon::fromTheme(QStringLiteral("document-new")), i18nc("@action:button", "New...")); 0048 l->addWidget(m_newScheme); 0049 0050 m_deleteScheme = new QPushButton(QIcon::fromTheme(QStringLiteral("edit-delete")), i18nc("@action:button", "Delete")); 0051 l->addWidget(m_deleteScheme); 0052 0053 QPushButton *moreActions = new QPushButton(QIcon::fromTheme(QStringLiteral("view-more-symbolic")), i18nc("@action:button", "More Actions")); 0054 l->addWidget(moreActions); 0055 0056 m_moreActionsMenu = new QMenu(this); 0057 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), 0058 i18nc("@action:inmenu", "Save shortcuts to scheme"), 0059 this, 0060 &KShortcutSchemesEditor::saveAsDefaultsForScheme); 0061 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-export")), 0062 i18nc("@action:inmenu", "Export Scheme..."), 0063 this, 0064 &KShortcutSchemesEditor::exportShortcutsScheme); 0065 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-import")), 0066 i18nc("@action:inmenu", "Import Scheme..."), 0067 this, 0068 &KShortcutSchemesEditor::importShortcutsScheme); 0069 moreActions->setMenu(m_moreActionsMenu); 0070 0071 l->addStretch(1); 0072 0073 connect(m_schemesList, &QComboBox::textActivated, this, &KShortcutSchemesEditor::shortcutsSchemeChanged); 0074 connect(m_newScheme, &QPushButton::clicked, this, &KShortcutSchemesEditor::newScheme); 0075 connect(m_deleteScheme, &QPushButton::clicked, this, &KShortcutSchemesEditor::deleteScheme); 0076 updateDeleteButton(); 0077 } 0078 0079 void KShortcutSchemesEditor::refreshSchemes() 0080 { 0081 QStringList schemes; 0082 schemes << QStringLiteral("Default"); 0083 // List files in the shortcuts subdir, each one is a scheme. See KShortcutSchemesHelper::{shortcutSchemeFileName,exportActionCollection} 0084 const QStringList shortcutsDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, 0085 QCoreApplication::applicationName() + QLatin1String("/shortcuts"), 0086 QStandardPaths::LocateDirectory); 0087 qCDebug(DEBUG_KXMLGUI) << "shortcut scheme dirs:" << shortcutsDirs; 0088 for (const QString &dir : shortcutsDirs) { 0089 const auto files = QDir(dir).entryList(QDir::Files | QDir::NoDotAndDotDot); 0090 for (const QString &file : files) { 0091 qCDebug(DEBUG_KXMLGUI) << "shortcut scheme file:" << file; 0092 schemes << file; 0093 } 0094 } 0095 0096 m_schemesList->clear(); 0097 m_schemesList->addItems(schemes); 0098 0099 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("Shortcut Schemes")); 0100 const QString currentScheme = group.readEntry("Current Scheme", "Default"); 0101 qCDebug(DEBUG_KXMLGUI) << "Current Scheme" << currentScheme; 0102 0103 const int schemeIdx = m_schemesList->findText(currentScheme); 0104 if (schemeIdx > -1) { 0105 m_schemesList->setCurrentIndex(schemeIdx); 0106 } else { 0107 qCWarning(DEBUG_KXMLGUI) << "Current scheme" << currentScheme << "not found in" << shortcutsDirs; 0108 } 0109 } 0110 0111 void KShortcutSchemesEditor::newScheme() 0112 { 0113 bool ok; 0114 const QString newName = 0115 QInputDialog::getText(this, i18nc("@title:window", "Name for New Scheme"), i18n("Name for new scheme:"), QLineEdit::Normal, i18n("New Scheme"), &ok); 0116 if (!ok) { 0117 return; 0118 } 0119 0120 if (m_schemesList->findText(newName) != -1) { 0121 KMessageBox::error(this, i18n("A scheme with this name already exists.")); 0122 return; 0123 } 0124 0125 const QString newSchemeFileName = KShortcutSchemesHelper::writableApplicationShortcutSchemeFileName(newName); 0126 QDir().mkpath(QFileInfo(newSchemeFileName).absolutePath()); 0127 QFile schemeFile(newSchemeFileName); 0128 if (!schemeFile.open(QFile::WriteOnly | QFile::Truncate)) { 0129 qCWarning(DEBUG_KXMLGUI) << "Couldn't write to" << newSchemeFileName; 0130 return; 0131 } 0132 0133 QDomDocument doc; 0134 QDomElement docElem = doc.createElement(QStringLiteral("gui")); 0135 doc.appendChild(docElem); 0136 QDomElement elem = doc.createElement(QStringLiteral("ActionProperties")); 0137 docElem.appendChild(elem); 0138 0139 QTextStream out(&schemeFile); 0140 out << doc.toString(4); 0141 0142 m_schemesList->addItem(newName); 0143 m_schemesList->setCurrentIndex(m_schemesList->findText(newName)); 0144 updateDeleteButton(); 0145 Q_EMIT shortcutsSchemeChanged(newName); 0146 } 0147 0148 void KShortcutSchemesEditor::deleteScheme() 0149 { 0150 if (KMessageBox::questionTwoActions(this, 0151 i18n("Do you really want to delete the scheme %1?\n\ 0152 Note that this will not remove any system wide shortcut schemes.", 0153 currentScheme()), 0154 QString(), 0155 KStandardGuiItem::del(), 0156 KStandardGuiItem::cancel()) 0157 == KMessageBox::SecondaryAction) { 0158 return; 0159 } 0160 0161 // delete the scheme for the app itself 0162 QFile::remove(KShortcutSchemesHelper::writableApplicationShortcutSchemeFileName(currentScheme())); 0163 0164 // delete all scheme files we can find for xmlguiclients in the user directories 0165 const auto dialogCollections = m_dialog->actionCollections(); 0166 for (KActionCollection *collection : dialogCollections) { 0167 const KXMLGUIClient *client = collection->parentGUIClient(); 0168 if (!client) { 0169 continue; 0170 } 0171 QFile::remove(KShortcutSchemesHelper::writableShortcutSchemeFileName(client->componentName(), currentScheme())); 0172 } 0173 0174 m_schemesList->removeItem(m_schemesList->findText(currentScheme())); 0175 updateDeleteButton(); 0176 Q_EMIT shortcutsSchemeChanged(currentScheme()); 0177 } 0178 0179 QString KShortcutSchemesEditor::currentScheme() 0180 { 0181 return m_schemesList->currentText(); 0182 } 0183 0184 void KShortcutSchemesEditor::exportShortcutsScheme() 0185 { 0186 // ask user about dir 0187 QString path = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Export Shortcuts"), QDir::currentPath(), i18n("Shortcuts (*.shortcuts)")); 0188 if (path.isEmpty()) { 0189 return; 0190 } 0191 0192 m_dialog->exportConfiguration(path); 0193 } 0194 0195 void KShortcutSchemesEditor::importShortcutsScheme() 0196 { 0197 // ask user about dir 0198 QString path = QFileDialog::getOpenFileName(this, i18nc("@title:window", "Import Shortcuts"), QDir::currentPath(), i18n("Shortcuts (*.shortcuts)")); 0199 if (path.isEmpty()) { 0200 return; 0201 } 0202 0203 m_dialog->importConfiguration(path); 0204 } 0205 0206 void KShortcutSchemesEditor::saveAsDefaultsForScheme() 0207 { 0208 if (KShortcutSchemesHelper::saveShortcutScheme(m_dialog->actionCollections(), currentScheme())) { 0209 KMessageBox::information(this, i18n("Shortcut scheme successfully saved.")); 0210 } else { 0211 // We'd need to return to return more than a bool, to show more details here. 0212 KMessageBox::error(this, i18n("Error saving the shortcut scheme.")); 0213 } 0214 } 0215 0216 void KShortcutSchemesEditor::updateDeleteButton() 0217 { 0218 m_deleteScheme->setEnabled(m_schemesList->count() >= 1); 0219 } 0220 0221 void KShortcutSchemesEditor::addMoreMenuAction(QAction *action) 0222 { 0223 m_moreActionsMenu->addAction(action); 0224 }