File indexing completed on 2024-11-10 10:53:33
0001 /** 0002 * SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org> 0003 * SPDX-FileCopyrightText: 2009 Michael Jansen <kde@michael-jansen.biz> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 **/ 0007 0008 #include "settings_reader_v2.h" 0009 0010 #include "action_data/action_data_group.h" 0011 #include "action_data/generic_action_data.h" 0012 #include "action_data/menuentry_shortcut_action_data.h" 0013 #include "action_data/simple_action_data.h" 0014 0015 #include "conditions/conditions_list.h" 0016 0017 #include "windows_helper/window_selection_list.h" 0018 0019 #include <KConfig> 0020 #include <KConfigBase> 0021 #include <KConfigGroup> 0022 #include <QDebug> 0023 0024 SettingsReaderV2::SettingsReaderV2(KHotKeys::Settings *settings, bool loadAll, KHotKeys::ActionState stateStrategy, const QString &importId) 0025 : _settings(settings) 0026 , _loadAll(loadAll) 0027 , _stateStrategy(stateStrategy) 0028 , _importId(importId) 0029 { 0030 #ifdef KHOTKEYS_TRACE 0031 qDebug() << "Created SettingsReader with disableActions(" << _stateStrategy << ")"; 0032 #endif 0033 } 0034 0035 SettingsReaderV2::~SettingsReaderV2() 0036 { 0037 } 0038 0039 void SettingsReaderV2::read(const KConfigBase &config, KHotKeys::ActionDataGroup *parent) 0040 { 0041 KConfigGroup data(&config, "Data"); 0042 0043 // We have to skip the top level group. 0044 QString configName = data.name(); 0045 int cnt = data.readEntry("DataCount", 0); 0046 for (int i = 1; i <= cnt; ++i) { 0047 KConfigGroup childConfig(data.config(), configName + '_' + QString::number(i)); 0048 if (_loadAll || KHotKeys::ActionDataBase::cfg_is_enabled(childConfig)) { 0049 KHotKeys::ActionDataBase *elem = readActionData(childConfig, parent); 0050 if (!_importId.isEmpty()) 0051 elem->setImportId(_importId); 0052 } 0053 } 0054 } 0055 0056 KHotKeys::ActionDataGroup *SettingsReaderV2::readGroup(const KConfigGroup &config, KHotKeys::ActionDataGroup *parent) 0057 { 0058 #ifdef KHOTKEYS_TRACE 0059 qDebug() << "Reading group" << config.readEntry("Name"); 0060 #endif 0061 KHotKeys::ActionDataGroup *group = nullptr; 0062 0063 // Check if it is allowed to merge the group. If yes check for a group 0064 // with the desired name 0065 if (config.readEntry("AllowMerge", false)) { 0066 Q_FOREACH (KHotKeys::ActionDataBase *child, parent->children()) { 0067 if (KHotKeys::ActionDataGroup *existing = dynamic_cast<KHotKeys::ActionDataGroup *>(child)) { 0068 if (config.readEntry("Name") == existing->name()) { 0069 group = existing; 0070 break; 0071 } 0072 } 0073 } 0074 } 0075 0076 // Do not allow loading a system group if there is already one. 0077 unsigned int system_group_tmp = config.readEntry("SystemGroup", 0); 0078 if ((system_group_tmp != 0) && (system_group_tmp < KHotKeys::ActionDataGroup::SYSTEM_MAX)) { 0079 // It's a valid value. Get the system group and load into it 0080 group = _settings->get_system_group(static_cast<KHotKeys::ActionDataGroup::system_group_t>(system_group_tmp)); 0081 } 0082 0083 // if no group was found or merging is disabled create a new group 0084 if (!group) { 0085 group = new KHotKeys::ActionDataGroup(parent); 0086 _config = &config; 0087 group->accept(this); 0088 } 0089 0090 Q_ASSERT(group); 0091 0092 // Now load the children 0093 QString configName = config.name(); 0094 int cnt = config.readEntry("DataCount", 0); 0095 for (int i = 1; i <= cnt; ++i) { 0096 KConfigGroup childConfig(config.config(), configName + '_' + QString::number(i)); 0097 if (_loadAll || KHotKeys::ActionDataBase::cfg_is_enabled(childConfig)) { 0098 readActionData(childConfig, group); 0099 } 0100 } 0101 0102 // The object is complete. Activate it if needed 0103 switch (_stateStrategy) { 0104 case KHotKeys::Retain: 0105 config.readEntry("Enabled", false) ? group->enable() : group->disable(); 0106 break; 0107 0108 case KHotKeys::Disabled: 0109 // Its disabled by default 0110 break; 0111 0112 case KHotKeys::Enabled: 0113 group->enable(); 0114 break; 0115 0116 default: 0117 qWarning() << "Unknown stateStrategy"; 0118 Q_ASSERT(false); 0119 break; 0120 }; 0121 0122 return group; 0123 } 0124 0125 KHotKeys::ActionDataBase *SettingsReaderV2::readActionData(const KConfigGroup &config, KHotKeys::ActionDataGroup *parent) 0126 { 0127 QString type = config.readEntry("Type"); 0128 0129 if (type == "ACTION_DATA_GROUP") { 0130 return readGroup(config, parent); 0131 } 0132 0133 KHotKeys::ActionData *newObject = nullptr; 0134 0135 if (type == "GENERIC_ACTION_DATA") { 0136 newObject = new KHotKeys::Generic_action_data(parent); 0137 } else if (type == "MENUENTRY_SHORTCUT_ACTION_DATA") { 0138 // We collect all of those in the system group 0139 newObject = new KHotKeys::MenuEntryShortcutActionData(_settings->get_system_group(KHotKeys::ActionDataGroup::SYSTEM_MENUENTRIES)); 0140 } else if (type == "SIMPLE_ACTION_DATA" || type == "COMMAND_URL_SHORTCUT_ACTION_DATA" || type == "DCOP_SHORTCUT_ACTION_DATA" 0141 || type == "DBUS_SHORTCUT_ACTION_DATA" || type == "KEYBOARD_INPUT_GESTURE_ACTION_DATA" || type == "KEYBOARD_INPUT_SHORTCUT_ACTION_DATA" 0142 || type == "ACTIVATE_WINDOW_SHORTCUT_ACTION_DATA") { 0143 newObject = new KHotKeys::SimpleActionData(parent); 0144 } else { 0145 qWarning() << "Unknown ActionDataBase type read from cfg file\n"; 0146 return nullptr; 0147 } 0148 0149 _config = &config; 0150 newObject->accept(this); 0151 0152 // And the actions 0153 readActionList(config, newObject); 0154 0155 // Now load the triggers 0156 readTriggerList(config, newObject); 0157 0158 // The object is complete. Activate it if needed 0159 switch (_stateStrategy) { 0160 case KHotKeys::Retain: 0161 config.readEntry("Enabled", false) ? newObject->enable() : newObject->disable(); 0162 break; 0163 0164 case KHotKeys::Disabled: 0165 // Its disabled by default 0166 break; 0167 0168 case KHotKeys::Enabled: 0169 newObject->enable(); 0170 break; 0171 0172 default: 0173 qWarning() << "Unknown stateStrategy"; 0174 Q_ASSERT(false); 0175 break; 0176 }; 0177 0178 #ifdef KHOTKEYS_TRACE 0179 qDebug() << newObject->name() << "loaded into" << newObject->isEnabled(KHotKeys::ActionDataBase::Ignore) << "state"; 0180 #endif 0181 0182 return newObject; 0183 } 0184 0185 KHotKeys::ActionList *SettingsReaderV2::readActionList(const KConfigGroup &config, KHotKeys::ActionData *parent) 0186 { 0187 KConfigGroup actionsGroup(config.config(), config.name() + "Actions"); 0188 0189 int cnt = actionsGroup.readEntry("ActionsCount", 0); 0190 QString save_cfg_group = actionsGroup.name(); 0191 for (int i = 0; i < cnt; ++i) { 0192 KConfigGroup group(actionsGroup.config(), save_cfg_group + QString::number(i)); 0193 KHotKeys::Action *action; 0194 0195 QString type = group.readEntry("Type"); 0196 0197 if (type == "COMMAND_URL") 0198 action = new KHotKeys::CommandUrlAction(parent); 0199 else if (type == "MENUENTRY") 0200 action = new KHotKeys::MenuEntryAction(parent); 0201 else if (type == "DCOP" || type == "DBUS") 0202 action = new KHotKeys::DBusAction(parent); 0203 else if (type == "KEYBOARD_INPUT") 0204 action = new KHotKeys::KeyboardInputAction(parent); 0205 else if (type == "ACTIVATE_WINDOW") 0206 action = new KHotKeys::ActivateWindowAction(parent); 0207 else { 0208 qWarning() << "Unknown Action type read from cfg file\n"; 0209 return nullptr; 0210 } 0211 0212 _config = &group; 0213 action->accept(*this); 0214 0215 parent->add_action(action); 0216 } 0217 0218 return nullptr; 0219 } 0220 0221 KHotKeys::Trigger_list *SettingsReaderV2::readTriggerList(const KConfigGroup &config, KHotKeys::ActionData *parent) 0222 { 0223 KConfigGroup triggersGroup(config.config(), config.name() + "Triggers"); 0224 KHotKeys::Trigger_list *list = parent->triggers(); 0225 0226 if (!triggersGroup.exists()) 0227 return list; 0228 Q_ASSERT(list); 0229 0230 list->set_comment(triggersGroup.readEntry("Comment")); 0231 0232 KHotKeys::Trigger *trigger = nullptr; 0233 0234 int cnt = triggersGroup.readEntry("TriggersCount", 0); 0235 for (int i = 0; i < cnt; ++i) { 0236 KConfigGroup triggerConfig(triggersGroup.config(), triggersGroup.name() + QString::number(i)); 0237 QString type = triggerConfig.readEntry("Type"); 0238 QUuid uuid = triggerConfig.readEntry("Uuid"); 0239 if (uuid.isNull()) 0240 uuid = QUuid::createUuid(); 0241 0242 if (type == "SHORTCUT" || type == "SINGLE_SHORTCUT") 0243 trigger = new KHotKeys::ShortcutTrigger(parent, QKeySequence(), uuid); 0244 else if (type == "WINDOW") 0245 trigger = new KHotKeys::WindowTrigger(parent); 0246 else if (type == "GESTURE") 0247 trigger = new KHotKeys::GestureTrigger(parent); 0248 else { 0249 qWarning() << "khotkeys: Unknown trigger type" << type; 0250 return nullptr; 0251 } 0252 0253 _config = &triggerConfig; 0254 trigger->accept(*this); 0255 0256 if (trigger) 0257 parent->add_trigger(trigger); 0258 } 0259 0260 return list; 0261 } 0262 0263 void SettingsReaderV2::visit(KHotKeys::ActivateWindowAction &action) 0264 { 0265 QString save_cfg_group = _config->name(); 0266 KConfigGroup windowGroup(_config->config(), save_cfg_group + "Window"); 0267 action.set_window_list(new KHotKeys::Windowdef_list(windowGroup)); 0268 } 0269 0270 void SettingsReaderV2::visit(KHotKeys::CommandUrlAction &action) 0271 { 0272 action.set_command_url(_config->readEntry("CommandURL")); 0273 } 0274 0275 void SettingsReaderV2::visit(KHotKeys::DBusAction &action) 0276 { 0277 action.set_remote_application(_config->readEntry("RemoteApp")); 0278 action.set_remote_object(_config->readEntry("RemoteObj")); 0279 action.set_called_function(_config->readEntry("Call")); 0280 action.set_arguments(_config->readEntry("Arguments")); 0281 } 0282 0283 void SettingsReaderV2::visit(KHotKeys::GestureTrigger &trigger) 0284 { 0285 if (_config->hasKey("Gesture")) 0286 trigger.setKDE3Gesture(_config->readEntry("Gesture")); 0287 else 0288 trigger.setPointData(_config->readEntry("GesturePointData", QStringList())); 0289 } 0290 0291 void SettingsReaderV2::visit(KHotKeys::KeyboardInputAction &action) 0292 { 0293 action.setInput(_config->readEntry("Input")); 0294 0295 KHotKeys::Windowdef_list *window_list = nullptr; 0296 KHotKeys::KeyboardInputAction::DestinationWindow destWindow; 0297 0298 // Try the new format with DestinationWindow 0299 int destination = _config->readEntry("DestinationWindow", -1); 0300 0301 switch (destination) { 0302 case KHotKeys::KeyboardInputAction::SpecificWindow: { 0303 KConfigGroup windowGroup(_config->config(), _config->name() + "DestinationWindow"); 0304 window_list = new KHotKeys::Windowdef_list(windowGroup); 0305 destWindow = KHotKeys::KeyboardInputAction::SpecificWindow; 0306 } break; 0307 0308 case KHotKeys::KeyboardInputAction::ActionWindow: 0309 destWindow = KHotKeys::KeyboardInputAction::ActionWindow; 0310 break; 0311 0312 case KHotKeys::KeyboardInputAction::ActiveWindow: 0313 destWindow = KHotKeys::KeyboardInputAction::ActiveWindow; 0314 break; 0315 0316 case -1: { 0317 // Old format 0318 if (_config->readEntry("IsDestinationWindow", false)) { 0319 KConfigGroup windowGroup(_config->config(), _config->name() + "DestinationWindow"); 0320 window_list = new KHotKeys::Windowdef_list(windowGroup); 0321 destWindow = KHotKeys::KeyboardInputAction::SpecificWindow; 0322 } else { 0323 if (_config->readEntry("ActiveWindow", false)) 0324 destWindow = KHotKeys::KeyboardInputAction::ActiveWindow; 0325 else 0326 destWindow = KHotKeys::KeyboardInputAction::ActionWindow; 0327 } 0328 } break; 0329 0330 default: 0331 Q_ASSERT(false); 0332 destWindow = KHotKeys::KeyboardInputAction::ActionWindow; 0333 } 0334 0335 if (!window_list) 0336 window_list = new KHotKeys::Windowdef_list; 0337 0338 action.setDestination(destWindow); 0339 action.setDestinationWindowRules(window_list); 0340 } 0341 0342 void SettingsReaderV2::visit(KHotKeys::MenuEntryAction &action) 0343 { 0344 visit(*static_cast<KHotKeys::CommandUrlAction *>(&action)); 0345 } 0346 0347 void SettingsReaderV2::visit(KHotKeys::ShortcutTrigger &trigger) 0348 { 0349 QString shortcutString = _config->readEntry("Key"); 0350 0351 // TODO: Check if this is still necessary 0352 shortcutString.replace("Win+", "Meta+"); // Qt4 doesn't parse Win+, avoid a shortcut without modifier 0353 0354 trigger.set_key_sequence(shortcutString); 0355 } 0356 0357 void SettingsReaderV2::visit(KHotKeys::WindowTrigger &trigger) 0358 { 0359 KConfigGroup windowsConfig(_config->config(), _config->name() + "Windows"); 0360 trigger.set_window_rules(new KHotKeys::Windowdef_list(windowsConfig)); 0361 trigger.setOnWindowEvents(KHotKeys::WindowTrigger::WindowEvents(_config->readEntry("WindowActions", 0))); 0362 } 0363 0364 void SettingsReaderV2::visitActionDataBase(KHotKeys::ActionDataBase *object) 0365 { 0366 object->set_name(_config->readEntry("Name")); 0367 object->set_comment(_config->readEntry("Comment")); 0368 object->setImportId(_config->readEntry("ImportId")); 0369 object->setAllowMerging(_config->readEntry("AllowMerge", false)); 0370 0371 KConfigGroup conditionsConfig(_config->config(), _config->name() + "Conditions"); 0372 0373 // Load the conditions if they exist 0374 if (conditionsConfig.exists()) { 0375 object->set_conditions(new KHotKeys::Condition_list(conditionsConfig, object)); 0376 } else { 0377 object->set_conditions(new KHotKeys::Condition_list(QString(), object)); 0378 } 0379 } 0380 0381 void SettingsReaderV2::visitActionData(KHotKeys::ActionData *object) 0382 { 0383 visitActionDataBase(object); 0384 } 0385 0386 void SettingsReaderV2::visitActionDataGroup(KHotKeys::ActionDataGroup *object) 0387 { 0388 unsigned int system_group_tmp = _config->readEntry("SystemGroup", 0); 0389 0390 // Correct wrong values 0391 if (system_group_tmp >= KHotKeys::ActionDataGroup::SYSTEM_MAX) { 0392 system_group_tmp = 0; 0393 } 0394 0395 object->set_system_group(static_cast<KHotKeys::ActionDataGroup::system_group_t>(system_group_tmp)); 0396 0397 visitActionDataBase(object); 0398 } 0399 0400 void SettingsReaderV2::visitGenericActionData(KHotKeys::Generic_action_data *object) 0401 { 0402 visitActionData(object); 0403 } 0404 0405 void SettingsReaderV2::visitMenuentryShortcutActionData(KHotKeys::MenuEntryShortcutActionData *object) 0406 { 0407 visitSimpleActionData(object); 0408 } 0409 0410 void SettingsReaderV2::visitSimpleActionData(KHotKeys::SimpleActionData *object) 0411 { 0412 visitActionData(object); 0413 }