1 /**
2  * SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org>
3  * SPDX-FileCopyrightText: 2009 Michael Jansen <kde@michael-jansen.biz>
4  *
5  * SPDX-License-Identifier: LGPL-2.0-or-later
6  **/
7 
8 #include "settings_writer.h"
9 
10 #include "action_data/action_data.h"
11 #include "action_data/action_data_group.h"
12 #include "action_data/generic_action_data.h"
13 #include "action_data/menuentry_shortcut_action_data.h"
14 #include "action_data/simple_action_data.h"
15 
16 #include "conditions/conditions_list.h"
17 
18 #include "windows_helper/window_selection_list.h"
19 
20 #include <KConfig>
21 #include <KConfigGroup>
22 #include <QDebug>
23 
24 namespace KHotKeys
25 {
26 const int CurrentFileVersion = 2;
27 
SettingsWriter(const Settings * settings,ActionState state,const QString & id,bool allowMerging)28 SettingsWriter::SettingsWriter(const Settings *settings, ActionState state, const QString &id, bool allowMerging)
29     : _settings(settings)
30     , _state(state)
31     , _importId(id)
32     , _allowMerging(allowMerging)
33     , _export(false)
34 {
35 }
36 
exportTo(const ActionDataBase * element,KConfigBase & config)37 void SettingsWriter::exportTo(const ActionDataBase *element, KConfigBase &config)
38 {
39     _export = true;
40 
41     if (!element) {
42         Q_ASSERT(element);
43         return;
44     }
45 
46     // Clean the file
47     QStringList groups = config.groupList();
48     Q_FOREACH (const QString &name, config.groupList()) {
49         config.deleteGroup(name);
50     }
51 
52     KConfigGroup mainGroup(&config, "Main");
53     mainGroup.writeEntry("Version", CurrentFileVersion);
54     mainGroup.writeEntry("AllowMerge", _allowMerging);
55 
56     if (!_importId.isEmpty())
57         mainGroup.writeEntry("ImportId", _importId);
58 
59     // The root group contains nothing but the datacount!
60     KConfigGroup dataGroup(&config, "Data");
61     dataGroup.writeEntry("DataCount", 1);
62 
63     // The group for the element to export
64     KConfigGroup data1Group(&config, "Data_1");
65     _stack.push(&data1Group);
66     element->accept(this);
67     _stack.pop();
68 
69     _export = false;
70 }
71 
visitActionData(const ActionData * data)72 void SettingsWriter::visitActionData(const ActionData *data)
73 {
74     visitActionDataBase(data);
75 
76     KConfigGroup *config = _stack.top();
77 
78     // Write triggers if available
79     if (data->triggers()) {
80         KConfigGroup triggersGroup(config->config(), config->name() + "Triggers");
81         data->triggers()->cfg_write(triggersGroup);
82     }
83 
84     // Write actions if available
85     if (data->actions()) {
86         KConfigGroup actionsGroup(config->config(), config->name() + "Actions");
87         data->actions()->cfg_write(actionsGroup);
88     }
89 }
90 
visitActionDataBase(const ActionDataBase * base)91 void SettingsWriter::visitActionDataBase(const ActionDataBase *base)
92 {
93     KConfigGroup *config = _stack.top();
94 
95     config->writeEntry("Type", "ERROR"); // derived classes should call with their type
96     config->writeEntry("Name", base->name());
97     config->writeEntry("Comment", base->comment());
98 
99     switch (_state) {
100     case KHotKeys::Retain:
101         config->writeEntry("Enabled", base->isEnabled(ActionDataBase::Ignore));
102         break;
103 
104     case KHotKeys::Enabled:
105         config->writeEntry("Enabled", true);
106         break;
107 
108     case KHotKeys::Disabled:
109         config->writeEntry("Enabled", false);
110         break;
111 
112     default:
113         Q_ASSERT(false);
114         config->writeEntry("Enabled", false);
115     }
116 
117     if (base->conditions()) {
118         KConfigGroup conditionsConfig(config->config(), config->name() + "Conditions");
119         base->conditions()->cfg_write(conditionsConfig);
120     } else {
121         qDebug() << "No conditions";
122     }
123 }
124 
visitActionDataGroup(const ActionDataGroup * group)125 void SettingsWriter::visitActionDataGroup(const ActionDataGroup *group)
126 {
127     visitActionDataBase(group);
128 
129     KConfigGroup *config = _stack.top();
130 
131     config->writeEntry("SystemGroup", int(group->system_group()));
132     config->writeEntry("Type", "ACTION_DATA_GROUP");
133 
134     int cnt = 0;
135     Q_FOREACH (ActionDataBase *child, group->children()) {
136         ++cnt;
137         KConfigGroup childConfig(config->config(), config->name() + QString("_") + QString::number(cnt));
138         _stack.push(&childConfig);
139         child->accept(this);
140         _stack.pop();
141     }
142     config->writeEntry("DataCount", cnt);
143 
144     // We only write those two back if we do not export the settings
145     if (!_export) {
146         // ImportId only if set
147         if (!group->importId().isEmpty())
148             config->writeEntry("ImportId", group->importId());
149         if (group->allowMerging())
150             config->writeEntry("AllowMerge", group->allowMerging());
151     }
152 }
153 
visitGenericActionData(const Generic_action_data * data)154 void SettingsWriter::visitGenericActionData(const Generic_action_data *data)
155 {
156     visitActionData(data);
157 
158     KConfigGroup *config = _stack.top();
159     config->writeEntry("Type", "GENERIC_ACTION_DATA");
160 }
161 
visitMenuentryShortcutActionData(const MenuEntryShortcutActionData * data)162 void SettingsWriter::visitMenuentryShortcutActionData(const MenuEntryShortcutActionData *data)
163 {
164     visitActionData(data);
165 
166     KConfigGroup *config = _stack.top();
167     config->writeEntry("Type", "MENUENTRY_SHORTCUT_ACTION_DATA");
168 }
169 
visitSimpleActionData(const SimpleActionData * data)170 void SettingsWriter::visitSimpleActionData(const SimpleActionData *data)
171 {
172     visitActionData(data);
173 
174     KConfigGroup *config = _stack.top();
175     config->writeEntry("Type", "SIMPLE_ACTION_DATA");
176 }
177 
writeTo(KConfigBase & config)178 void SettingsWriter::writeTo(KConfigBase &config)
179 {
180     QStringList groups = config.groupList();
181     for (QStringList::ConstIterator it = groups.constBegin(); it != groups.constEnd(); ++it)
182         config.deleteGroup(*it);
183 
184     // Write the global settings
185     KConfigGroup mainGroup(&config, "Main");
186     mainGroup.writeEntry("Version", 2);
187     mainGroup.writeEntry("AlreadyImported", _settings->already_imported);
188     mainGroup.writeEntry("Disabled", _settings->isDaemonDisabled());
189 
190     // Write the actions
191     KConfigGroup dataGroup(&config, "Data");
192     _stack.push(&dataGroup);
193 
194     int cnt = 0;
195     if (_settings->actions()) {
196         Q_FOREACH (ActionDataBase *child, _settings->actions()->children()) {
197             ++cnt;
198             KConfigGroup childConfig(dataGroup.config(), QString("Data_") + QString::number(cnt));
199             _stack.push(&childConfig);
200             child->accept(this);
201             _stack.pop();
202         }
203     }
204     dataGroup.writeEntry("DataCount", cnt);
205     _stack.pop();
206 
207     // CHECKME Count still needed????
208     // int cnt = write_actions( dataGroup, _settings->actions(), true );
209     // mainGroup.writeEntry( "Autostart", cnt != 0 && !_settings->isDaemonDisabled() );
210 
211     // Write the gestures configuration
212     KConfigGroup gesturesConfig(&config, "Gestures");
213     gesturesConfig.writeEntry("Disabled", _settings->areGesturesDisabled());
214     gesturesConfig.writeEntry("MouseButton", _settings->gestureMouseButton());
215     gesturesConfig.writeEntry("Timeout", _settings->gestureTimeOut());
216     if (_settings->gesturesExclude() != nullptr) {
217         KConfigGroup gesturesExcludeConfig(&config, "GesturesExclude");
218         _settings->gesturesExclude()->cfg_write(gesturesExcludeConfig);
219     } else
220         config.deleteGroup("GesturesExclude");
221     KConfigGroup voiceConfig(&config, "Voice");
222     voiceConfig.writeEntry("Shortcut", _settings->voice_shortcut.toString());
223 }
224 
225 } // namespace KHotKeys
226