KXmlGui

kshortcutschemeseditor.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2008 Alexander Dymo <adymo@kdevelop.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7#include "kshortcutsdialog_p.h"
8
9#include <QComboBox>
10#include <QDir>
11#include <QDomDocument>
12#include <QFile>
13#include <QFileDialog>
14#include <QInputDialog>
15#include <QLabel>
16#include <QMenu>
17#include <QPushButton>
18#include <QStandardPaths>
19#include <QTextStream>
20
21#include <KConfigGroup>
22#include <KMessageBox>
23#include <KSharedConfig>
24
25#include "kactioncollection.h"
26#include "kshortcutschemeshelper_p.h"
27#include "kshortcutsdialog.h"
28#include "kxmlguiclient.h"
29#include <debug.h>
30
31KShortcutSchemesEditor::KShortcutSchemesEditor(KShortcutsDialog *parent)
32 : QGroupBox(i18nc("@title:group", "Shortcut Schemes"), parent)
33 , m_dialog(parent)
34{
35 QHBoxLayout *l = new QHBoxLayout(this);
36
37 QLabel *schemesLabel = new QLabel(i18n("Current scheme:"), this);
38 l->addWidget(schemesLabel);
39
40 m_schemesList = new QComboBox(this);
41 m_schemesList->setEditable(false);
42 refreshSchemes();
43 m_schemesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
44 schemesLabel->setBuddy(m_schemesList);
45 l->addWidget(m_schemesList);
46
47 m_newScheme = new QPushButton(QIcon::fromTheme(QStringLiteral("document-new")), i18nc("@action:button", "New..."));
48 l->addWidget(m_newScheme);
49
50 m_deleteScheme = new QPushButton(QIcon::fromTheme(QStringLiteral("edit-delete")), i18nc("@action:button", "Delete"));
51 l->addWidget(m_deleteScheme);
52
53 QPushButton *moreActions = new QPushButton(QIcon::fromTheme(QStringLiteral("view-more-symbolic")), i18nc("@action:button", "More Actions"));
54 l->addWidget(moreActions);
55
56 m_moreActionsMenu = new QMenu(this);
57 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-save")),
58 i18nc("@action:inmenu", "Save shortcuts to scheme"),
59 this,
60 &KShortcutSchemesEditor::saveAsDefaultsForScheme);
61 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-export")),
62 i18nc("@action:inmenu", "Export Scheme..."),
63 this,
64 &KShortcutSchemesEditor::exportShortcutsScheme);
65 m_moreActionsMenu->addAction(QIcon::fromTheme(QStringLiteral("document-import")),
66 i18nc("@action:inmenu", "Import Scheme..."),
67 this,
68 &KShortcutSchemesEditor::importShortcutsScheme);
69 moreActions->setMenu(m_moreActionsMenu);
70
71 l->addStretch(1);
72
73 connect(m_schemesList, &QComboBox::textActivated, this, &KShortcutSchemesEditor::shortcutsSchemeChanged);
74 connect(m_newScheme, &QPushButton::clicked, this, &KShortcutSchemesEditor::newScheme);
75 connect(m_deleteScheme, &QPushButton::clicked, this, &KShortcutSchemesEditor::deleteScheme);
76 updateDeleteButton();
77}
78
79void KShortcutSchemesEditor::refreshSchemes()
80{
81 QStringList schemes;
82 schemes << QStringLiteral("Default");
83 // List files in the shortcuts subdir, each one is a scheme. See KShortcutSchemesHelper::{shortcutSchemeFileName,exportActionCollection}
87 qCDebug(DEBUG_KXMLGUI) << "shortcut scheme dirs:" << shortcutsDirs;
88 for (const QString &dir : shortcutsDirs) {
89 const auto files = QDir(dir).entryList(QDir::Files | QDir::NoDotAndDotDot);
90 for (const QString &file : files) {
91 qCDebug(DEBUG_KXMLGUI) << "shortcut scheme file:" << file;
92 schemes << file;
93 }
94 }
95
96 m_schemesList->clear();
97 m_schemesList->addItems(schemes);
98
99 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("Shortcut Schemes"));
100 const QString currentScheme = group.readEntry("Current Scheme", "Default");
101 qCDebug(DEBUG_KXMLGUI) << "Current Scheme" << currentScheme;
102
103 const int schemeIdx = m_schemesList->findText(currentScheme);
104 if (schemeIdx > -1) {
105 m_schemesList->setCurrentIndex(schemeIdx);
106 } else {
107 qCWarning(DEBUG_KXMLGUI) << "Current scheme" << currentScheme << "not found in" << shortcutsDirs;
108 }
109}
110
111void KShortcutSchemesEditor::newScheme()
112{
113 bool ok;
114 const QString newName =
115 QInputDialog::getText(this, i18nc("@title:window", "Name for New Scheme"), i18n("Name for new scheme:"), QLineEdit::Normal, i18n("New Scheme"), &ok);
116 if (!ok) {
117 return;
118 }
119
120 if (m_schemesList->findText(newName) != -1) {
121 KMessageBox::error(this, i18n("A scheme with this name already exists."));
122 return;
123 }
124
125 const QString newSchemeFileName = KShortcutSchemesHelper::writableApplicationShortcutSchemeFileName(newName);
126 QDir().mkpath(QFileInfo(newSchemeFileName).absolutePath());
127 QFile schemeFile(newSchemeFileName);
128 if (!schemeFile.open(QFile::WriteOnly | QFile::Truncate)) {
129 qCWarning(DEBUG_KXMLGUI) << "Couldn't write to" << newSchemeFileName;
130 return;
131 }
132
133 QDomDocument doc;
134 QDomElement docElem = doc.createElement(QStringLiteral("gui"));
135 doc.appendChild(docElem);
136 QDomElement elem = doc.createElement(QStringLiteral("ActionProperties"));
137 docElem.appendChild(elem);
138
139 QTextStream out(&schemeFile);
140 out << doc.toString(4);
141
142 m_schemesList->addItem(newName);
143 m_schemesList->setCurrentIndex(m_schemesList->findText(newName));
144 updateDeleteButton();
145 Q_EMIT shortcutsSchemeChanged(newName);
146}
147
148void KShortcutSchemesEditor::deleteScheme()
149{
151 i18n("Do you really want to delete the scheme %1?\n\
152Note that this will not remove any system wide shortcut schemes.",
153 currentScheme()),
154 QString(),
158 return;
159 }
160
161 // delete the scheme for the app itself
162 QFile::remove(KShortcutSchemesHelper::writableApplicationShortcutSchemeFileName(currentScheme()));
163
164 // delete all scheme files we can find for xmlguiclients in the user directories
165 const auto dialogCollections = m_dialog->actionCollections();
166 for (KActionCollection *collection : dialogCollections) {
167 const KXMLGUIClient *client = collection->parentGUIClient();
168 if (!client) {
169 continue;
170 }
171 QFile::remove(KShortcutSchemesHelper::writableShortcutSchemeFileName(client->componentName(), currentScheme()));
172 }
173
174 m_schemesList->removeItem(m_schemesList->findText(currentScheme()));
175 updateDeleteButton();
176 Q_EMIT shortcutsSchemeChanged(currentScheme());
177}
178
179QString KShortcutSchemesEditor::currentScheme()
180{
181 return m_schemesList->currentText();
182}
183
184void KShortcutSchemesEditor::exportShortcutsScheme()
185{
186 // ask user about dir
187 QString path = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Export Shortcuts"), QDir::currentPath(), i18n("Shortcuts (*.shortcuts)"));
188 if (path.isEmpty()) {
189 return;
190 }
191
192 m_dialog->exportConfiguration(path);
193}
194
195void KShortcutSchemesEditor::importShortcutsScheme()
196{
197 // ask user about dir
198 QString path = QFileDialog::getOpenFileName(this, i18nc("@title:window", "Import Shortcuts"), QDir::currentPath(), i18n("Shortcuts (*.shortcuts)"));
199 if (path.isEmpty()) {
200 return;
201 }
202
203 m_dialog->importConfiguration(path);
204}
205
206void KShortcutSchemesEditor::saveAsDefaultsForScheme()
207{
208 if (KShortcutSchemesHelper::saveShortcutScheme(m_dialog->actionCollections(), currentScheme())) {
209 KMessageBox::information(this, i18n("Shortcut scheme successfully saved."));
210 } else {
211 // We'd need to return to return more than a bool, to show more details here.
212 KMessageBox::error(this, i18n("Error saving the shortcut scheme."));
213 }
214}
215
216void KShortcutSchemesEditor::updateDeleteButton()
217{
218 m_deleteScheme->setEnabled(m_schemesList->count() >= 1);
219}
220
221void KShortcutSchemesEditor::addMoreMenuAction(QAction *action)
222{
223 m_moreActionsMenu->addAction(action);
224}
A container for a set of QAction objects.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Dialog for configuration of KActionCollection and KGlobalAccel.
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document,...
virtual QString componentName() const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString path(const QString &relativePath)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
KGuiItem cancel()
KGuiItem del()
void clicked(bool checked)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void textActivated(const QString &text)
QString currentPath()
QStringList entryList(Filters filters, SortFlags sort) const const
bool mkpath(const QString &dirPath) const const
QDomElement createElement(const QString &tagName)
QString toString(int indent) const const
QDomNode appendChild(const QDomNode &newChild)
bool remove()
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
QIcon fromTheme(const QString &name)
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
void setBuddy(QWidget *buddy)
void clear()
void setMenu(QMenu *menu)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
bool isEmpty() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:52:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.