1 | /** @file
|
---|
2 | *
|
---|
3 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
4 | * UIShortcutPool class implementation
|
---|
5 | */
|
---|
6 |
|
---|
7 | /*
|
---|
8 | * Copyright (C) 2011-2013 Oracle Corporation
|
---|
9 | *
|
---|
10 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
11 | * available from http://www.virtualbox.org. This file is free software;
|
---|
12 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
13 | * General Public License (GPL) as published by the Free Software
|
---|
14 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
15 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
16 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
17 | */
|
---|
18 |
|
---|
19 | /* GUI includes: */
|
---|
20 | #include "UIShortcutPool.h"
|
---|
21 | #include "UIActionPool.h"
|
---|
22 | #include "UIExtraDataEventHandler.h"
|
---|
23 |
|
---|
24 | void UIShortcut::setDescription(const QString &strDescription)
|
---|
25 | {
|
---|
26 | m_strDescription = strDescription;
|
---|
27 | }
|
---|
28 |
|
---|
29 | const QString& UIShortcut::description() const
|
---|
30 | {
|
---|
31 | return m_strDescription;
|
---|
32 | }
|
---|
33 |
|
---|
34 | void UIShortcut::setSequence(const QKeySequence &sequence)
|
---|
35 | {
|
---|
36 | m_sequence = sequence;
|
---|
37 | }
|
---|
38 |
|
---|
39 | const QKeySequence& UIShortcut::sequence() const
|
---|
40 | {
|
---|
41 | return m_sequence;
|
---|
42 | }
|
---|
43 |
|
---|
44 | QString UIShortcut::toString() const
|
---|
45 | {
|
---|
46 | return m_sequence.toString();
|
---|
47 | }
|
---|
48 |
|
---|
49 | UIShortcutPool* UIShortcutPool::m_pInstance = 0;
|
---|
50 |
|
---|
51 | const QString UIShortcutPool::m_strShortcutKeyTemplate = QString("%1/%2");
|
---|
52 |
|
---|
53 | UIShortcutPool* UIShortcutPool::instance()
|
---|
54 | {
|
---|
55 | return m_pInstance;
|
---|
56 | }
|
---|
57 |
|
---|
58 | void UIShortcutPool::create()
|
---|
59 | {
|
---|
60 | /* Check that instance do NOT exists: */
|
---|
61 | if (m_pInstance)
|
---|
62 | return;
|
---|
63 |
|
---|
64 | /* Create instance: */
|
---|
65 | new UIShortcutPool;
|
---|
66 |
|
---|
67 | /* Prepare instance: */
|
---|
68 | m_pInstance->prepare();
|
---|
69 | }
|
---|
70 |
|
---|
71 | void UIShortcutPool::destroy()
|
---|
72 | {
|
---|
73 | /* Check that instance exists: */
|
---|
74 | if (!m_pInstance)
|
---|
75 | return;
|
---|
76 |
|
---|
77 | /* Cleanup instance: */
|
---|
78 | m_pInstance->cleanup();
|
---|
79 |
|
---|
80 | /* Delete instance: */
|
---|
81 | delete m_pInstance;
|
---|
82 | }
|
---|
83 |
|
---|
84 | UIShortcut& UIShortcutPool::shortcut(UIActionPool *pActionPool, UIAction *pAction)
|
---|
85 | {
|
---|
86 | /* Compose shortcut key: */
|
---|
87 | QString strShortcutKey(m_strShortcutKeyTemplate.arg(pActionPool->shortcutsExtraDataID(),
|
---|
88 | pAction->shortcutExtraDataID()));
|
---|
89 | /* Return existing if any: */
|
---|
90 | if (m_shortcuts.contains(strShortcutKey))
|
---|
91 | return shortcut(strShortcutKey);
|
---|
92 | /* Create and return new one: */
|
---|
93 | UIShortcut &newShortcut = m_shortcuts[strShortcutKey];
|
---|
94 | newShortcut.setDescription(pAction->name());
|
---|
95 | newShortcut.setSequence(pAction->defaultShortcut(pActionPool->type()));
|
---|
96 | return newShortcut;
|
---|
97 | }
|
---|
98 |
|
---|
99 | UIShortcut& UIShortcutPool::shortcut(const QString &strPoolID, const QString &strActionID)
|
---|
100 | {
|
---|
101 | /* Return if present, autocreate if necessary: */
|
---|
102 | return shortcut(m_strShortcutKeyTemplate.arg(strPoolID, strActionID));
|
---|
103 | }
|
---|
104 |
|
---|
105 | void UIShortcutPool::applyShortcuts(UIActionPool *pActionPool)
|
---|
106 | {
|
---|
107 | /* For each the action of the passed action-pool: */
|
---|
108 | foreach (UIAction *pAction, pActionPool->actions())
|
---|
109 | {
|
---|
110 | /* Compose full shortcut key: */
|
---|
111 | QString strShortcutKey = m_strShortcutKeyTemplate.arg(pActionPool->shortcutsExtraDataID(),
|
---|
112 | pAction->shortcutExtraDataID());
|
---|
113 | /* If shortcut key is already known: */
|
---|
114 | if (m_shortcuts.contains(strShortcutKey))
|
---|
115 | {
|
---|
116 | /* Get corresponding shortcut: */
|
---|
117 | UIShortcut &existingShortcut = m_shortcuts[strShortcutKey];
|
---|
118 | /* Copy the sequence from the shortcut to the action: */
|
---|
119 | pAction->setShortcut(existingShortcut.sequence());
|
---|
120 | /* Copy the description from the action to the shortcut if necessary: */
|
---|
121 | if (existingShortcut.description().isNull())
|
---|
122 | existingShortcut.setDescription(pAction->name());
|
---|
123 | }
|
---|
124 | /* If shortcut key is NOT known yet: */
|
---|
125 | else
|
---|
126 | {
|
---|
127 | /* Create corresponding shortcut: */
|
---|
128 | UIShortcut &newShortcut = m_shortcuts[strShortcutKey];
|
---|
129 | /* Copy the action's default to both the shortcut & the action: */
|
---|
130 | newShortcut.setSequence(pAction->defaultShortcut(pActionPool->type()));
|
---|
131 | pAction->setShortcut(newShortcut.sequence());
|
---|
132 | /* Copy the description from the action to the shortcut: */
|
---|
133 | newShortcut.setDescription(pAction->name());
|
---|
134 | }
|
---|
135 | }
|
---|
136 | }
|
---|
137 |
|
---|
138 | void UIShortcutPool::sltReloadSelectorShortcuts()
|
---|
139 | {
|
---|
140 | /* Clear selector shortcuts first: */
|
---|
141 | QList<QString> shortcutKeyList = m_shortcuts.keys();
|
---|
142 | foreach (const QString &strShortcutKey, shortcutKeyList)
|
---|
143 | if (strShortcutKey.startsWith(GUI_Input_SelectorShortcuts))
|
---|
144 | m_shortcuts.remove(strShortcutKey);
|
---|
145 | /* Load selector overrides: */
|
---|
146 | loadOverridesFor(GUI_Input_SelectorShortcuts);
|
---|
147 | /* Notify selector shortcuts reloaded: */
|
---|
148 | emit sigSelectorShortcutsReloaded();
|
---|
149 | }
|
---|
150 |
|
---|
151 | void UIShortcutPool::sltReloadMachineShortcuts()
|
---|
152 | {
|
---|
153 | /* Clear machine shortcuts first: */
|
---|
154 | QList<QString> shortcutKeyList = m_shortcuts.keys();
|
---|
155 | foreach (const QString &strShortcutKey, shortcutKeyList)
|
---|
156 | if (strShortcutKey.startsWith(GUI_Input_MachineShortcuts))
|
---|
157 | m_shortcuts.remove(strShortcutKey);
|
---|
158 | /* Load machine overrides: */
|
---|
159 | loadOverridesFor(GUI_Input_MachineShortcuts);
|
---|
160 | /* Notify machine shortcuts reloaded: */
|
---|
161 | emit sigMachineShortcutsReloaded();
|
---|
162 | }
|
---|
163 |
|
---|
164 | UIShortcutPool::UIShortcutPool()
|
---|
165 | {
|
---|
166 | /* Prepare instance: */
|
---|
167 | if (!m_pInstance)
|
---|
168 | m_pInstance = this;
|
---|
169 | }
|
---|
170 |
|
---|
171 | UIShortcutPool::~UIShortcutPool()
|
---|
172 | {
|
---|
173 | /* Cleanup instance: */
|
---|
174 | if (m_pInstance == this)
|
---|
175 | m_pInstance = 0;
|
---|
176 | }
|
---|
177 |
|
---|
178 | void UIShortcutPool::prepare()
|
---|
179 | {
|
---|
180 | /* Load defaults: */
|
---|
181 | loadDefaults();
|
---|
182 | /* Load overrides: */
|
---|
183 | loadOverrides();
|
---|
184 | /* Prepare connections: */
|
---|
185 | prepareConnections();
|
---|
186 | }
|
---|
187 |
|
---|
188 | void UIShortcutPool::prepareConnections()
|
---|
189 | {
|
---|
190 | /* Connect to extra-data signals: */
|
---|
191 | connect(gEDataEvents, SIGNAL(sigSelectorShortcutsChanged()), this, SLOT(sltReloadSelectorShortcuts()));
|
---|
192 | connect(gEDataEvents, SIGNAL(sigMachineShortcutsChanged()), this, SLOT(sltReloadMachineShortcuts()));
|
---|
193 | }
|
---|
194 |
|
---|
195 | void UIShortcutPool::loadDefaults()
|
---|
196 | {
|
---|
197 | /* Runtime shortcut key template: */
|
---|
198 | QString strRuntimeShortcutKeyTemplate(m_strShortcutKeyTemplate.arg(GUI_Input_MachineShortcuts));
|
---|
199 | /* Default shortcut for the Runtime Popup Menu invokation: */
|
---|
200 | m_shortcuts.insert(strRuntimeShortcutKeyTemplate.arg("PopupMenu"),
|
---|
201 | UIShortcut(QApplication::translate("UIActonPool", "Invoke popup menu"), QString("Home")));
|
---|
202 | }
|
---|
203 |
|
---|
204 | void UIShortcutPool::loadOverrides()
|
---|
205 | {
|
---|
206 | /* Load selector overrides: */
|
---|
207 | loadOverridesFor(GUI_Input_SelectorShortcuts);
|
---|
208 | /* Load machine overrides: */
|
---|
209 | loadOverridesFor(GUI_Input_MachineShortcuts);
|
---|
210 | }
|
---|
211 |
|
---|
212 | void UIShortcutPool::loadOverridesFor(const QString &strExtraDataID)
|
---|
213 | {
|
---|
214 | /* Shortcut prefix: */
|
---|
215 | QString strShortcutPrefix(strExtraDataID);
|
---|
216 | /* Shortcut key template: */
|
---|
217 | QString strShortcutKeyTemplate(m_strShortcutKeyTemplate.arg(strShortcutPrefix));
|
---|
218 | /* Iterate over all the records: */
|
---|
219 | parseOverrides(vboxGlobal().virtualBox().GetExtraDataStringList(strShortcutPrefix), strShortcutKeyTemplate);
|
---|
220 | }
|
---|
221 |
|
---|
222 | void UIShortcutPool::parseOverrides(const QStringList &overrides, const QString &strTemplate)
|
---|
223 | {
|
---|
224 | /* Iterate over all the selector records: */
|
---|
225 | foreach (const QString &strKeyValuePair, overrides)
|
---|
226 | {
|
---|
227 | /* Make sure record structure is valid: */
|
---|
228 | int iDelimiterPosition = strKeyValuePair.indexOf('=');
|
---|
229 | if (iDelimiterPosition < 0)
|
---|
230 | continue;
|
---|
231 |
|
---|
232 | /* Get shortcut ID/value: */
|
---|
233 | QString strShortcutID = strKeyValuePair.left(iDelimiterPosition);
|
---|
234 | QString strShortcutValue = strKeyValuePair.right(strKeyValuePair.length() - iDelimiterPosition - 1);
|
---|
235 |
|
---|
236 | /* Compose corresponding shortcut key: */
|
---|
237 | QString strShortcutKey(strTemplate.arg(strShortcutID));
|
---|
238 | /* Modify map with composed key/value: */
|
---|
239 | if (!m_shortcuts.contains(strShortcutKey))
|
---|
240 | m_shortcuts.insert(strShortcutKey, UIShortcut(QString(), strShortcutValue));
|
---|
241 | else
|
---|
242 | {
|
---|
243 | /* Get corresponding value: */
|
---|
244 | UIShortcut &shortcut = m_shortcuts[strShortcutKey];
|
---|
245 | /* Check if corresponding shortcut overriden by value: */
|
---|
246 | if (shortcut.toString().compare(strShortcutValue, Qt::CaseInsensitive) != 0)
|
---|
247 | {
|
---|
248 | /* Shortcut unassigned? */
|
---|
249 | if (strShortcutValue.compare("None", Qt::CaseInsensitive) == 0)
|
---|
250 | shortcut.setSequence(QKeySequence());
|
---|
251 | /* Or reassigned? */
|
---|
252 | else
|
---|
253 | shortcut.setSequence(QKeySequence(strShortcutValue));
|
---|
254 | }
|
---|
255 | }
|
---|
256 | }
|
---|
257 | }
|
---|
258 |
|
---|
259 | UIShortcut& UIShortcutPool::shortcut(const QString &strShortcutKey)
|
---|
260 | {
|
---|
261 | return m_shortcuts[strShortcutKey];
|
---|
262 | }
|
---|
263 |
|
---|