VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPool.cpp@ 43138

Last change on this file since 43138 was 42853, checked in by vboxsync, 12 years ago

FE/Qt: 6234: Support for VM groups: Show Log action will now only be available for single selected VM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 18.8 KB
Line 
1/* $Id: UIActionPool.cpp 42853 2012-08-16 18:08:14Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UIActionPool class implementation
6 */
7
8/*
9 * Copyright (C) 2010-2012 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Global includes: */
21#include <QHelpEvent>
22#include <QToolTip>
23
24/* Local includes: */
25#include "UIActionPool.h"
26#include "UIIconPool.h"
27#include "VBoxGlobal.h"
28#include "UISelectorShortcuts.h"
29#include "UIMachineShortcuts.h"
30
31/* Action activation event: */
32class ActivateActionEvent : public QEvent
33{
34public:
35
36 ActivateActionEvent(QAction *pAction)
37 : QEvent((QEvent::Type)ActivateActionEventType)
38 , m_pAction(pAction) {}
39 QAction* action() const { return m_pAction; }
40
41private:
42
43 QAction *m_pAction;
44};
45
46/* UIAction stuff: */
47UIAction::UIAction(QObject *pParent, UIActionType type)
48 : QIWithRetranslateUI3<QAction>(pParent)
49 , m_type(type)
50{
51 /* By default there is no specific menu role.
52 * It will be set explicitly later. */
53 setMenuRole(QAction::NoRole);
54}
55
56void UIAction::setShortcut(const QKeySequence &shortcut)
57{
58 /* Call to base-class: */
59 QAction::setShortcut(shortcut);
60 /* Remember shortcut: */
61 m_shortcut = shortcut;
62}
63
64void UIAction::showShortcut()
65{
66 if (!m_shortcut.isEmpty())
67 QAction::setShortcut(m_shortcut);
68}
69
70void UIAction::hideShortcut()
71{
72 if (!shortcut().isEmpty())
73 QAction::setShortcut(QKeySequence());
74}
75
76QString UIAction::menuText(const QString &strText)
77{
78 return vboxGlobal().isVMConsoleProcess() ? VBoxGlobal::removeAccelMark(strText) : strText;
79}
80
81/* UIMenu stuff: */
82UIMenu::UIMenu()
83 : m_fShowToolTips(false)
84{
85}
86
87bool UIMenu::event(QEvent *pEvent)
88{
89 /* Handle particular event-types: */
90 switch (pEvent->type())
91 {
92 /* Tool-tip request handler: */
93 case QEvent::ToolTip:
94 {
95 /* Get current help-event: */
96 QHelpEvent *pHelpEvent = static_cast<QHelpEvent*>(pEvent);
97 /* Get action which caused help-event: */
98 QAction *pAction = actionAt(pHelpEvent->pos());
99 /* If action present => show action's tool-tip if needed: */
100 if (pAction && m_fShowToolTips)
101 QToolTip::showText(pHelpEvent->globalPos(), pAction->toolTip());
102 break;
103 }
104 default:
105 break;
106 }
107 /* Base-class event-handler: */
108 return QMenu::event(pEvent);
109}
110
111/* UIActionSimple stuff: */
112UIActionSimple::UIActionSimple(QObject *pParent, const QString &strIcon, const QString &strIconDis)
113 : UIAction(pParent, UIActionType_Simple)
114{
115 if (!strIcon.isNull())
116 setIcon(UIIconPool::iconSet(strIcon, strIconDis));
117}
118
119UIActionSimple::UIActionSimple(QObject *pParent,
120 const QSize &normalSize, const QSize &smallSize,
121 const QString &strNormalIcon, const QString &strSmallIcon,
122 const QString &strNormalIconDis, const QString &strSmallIconDis)
123 : UIAction(pParent, UIActionType_Simple)
124{
125 setIcon(UIIconPool::iconSetFull(normalSize, smallSize, strNormalIcon, strSmallIcon, strNormalIconDis, strSmallIconDis));
126}
127
128UIActionSimple::UIActionSimple(QObject *pParent, const QIcon& icon)
129 : UIAction(pParent, UIActionType_Simple)
130{
131 if (!icon.isNull())
132 setIcon(icon);
133}
134
135/* UIActionState stuff: */
136UIActionState::UIActionState(QObject *pParent, const QString &strIcon, const QString &strIconDis)
137 : UIAction(pParent, UIActionType_State)
138 , m_iState(0)
139{
140 if (!strIcon.isNull())
141 setIcon(UIIconPool::iconSet(strIcon, strIconDis));
142}
143
144UIActionState::UIActionState(QObject *pParent,
145 const QSize &normalSize, const QSize &smallSize,
146 const QString &strNormalIcon, const QString &strSmallIcon,
147 const QString &strNormalIconDis, const QString &strSmallIconDis)
148 : UIAction(pParent, UIActionType_State)
149 , m_iState(0)
150{
151 setIcon(UIIconPool::iconSetFull(normalSize, smallSize, strNormalIcon, strSmallIcon, strNormalIconDis, strSmallIconDis));
152}
153
154UIActionState::UIActionState(QObject *pParent, const QIcon& icon)
155 : UIAction(pParent, UIActionType_State)
156 , m_iState(0)
157{
158 if (!icon.isNull())
159 setIcon(icon);
160}
161
162/* UIActionToggle stuff: */
163UIActionToggle::UIActionToggle(QObject *pParent, const QString &strIcon, const QString &strIconDis)
164 : UIAction(pParent, UIActionType_Toggle)
165{
166 if (!strIcon.isNull())
167 setIcon(UIIconPool::iconSet(strIcon, strIconDis));
168 init();
169}
170
171UIActionToggle::UIActionToggle(QObject *pParent,
172 const QSize &normalSize, const QSize &smallSize,
173 const QString &strNormalIcon, const QString &strSmallIcon,
174 const QString &strNormalIconDis, const QString &strSmallIconDis)
175 : UIAction(pParent, UIActionType_Toggle)
176{
177 setIcon(UIIconPool::iconSetFull(normalSize, smallSize, strNormalIcon, strSmallIcon, strNormalIconDis, strSmallIconDis));
178 init();
179}
180
181UIActionToggle::UIActionToggle(QObject *pParent,
182 const QString &strIconOn, const QString &strIconOff,
183 const QString &strIconOnDis, const QString &strIconOffDis)
184 : UIAction(pParent, UIActionType_Toggle)
185{
186 setIcon(UIIconPool::iconSetOnOff(strIconOn, strIconOff, strIconOnDis, strIconOffDis));
187 init();
188}
189
190UIActionToggle::UIActionToggle(QObject *pParent, const QIcon &icon)
191 : UIAction(pParent, UIActionType_Toggle)
192{
193 if (!icon.isNull())
194 setIcon(icon);
195 init();
196}
197
198void UIActionToggle::sltUpdateAppearance()
199{
200 retranslateUi();
201}
202
203void UIActionToggle::init()
204{
205 setCheckable(true);
206 connect(this, SIGNAL(toggled(bool)), this, SLOT(sltUpdateAppearance()));
207}
208
209/* UIActionMenu stuff: */
210UIActionMenu::UIActionMenu(QObject *pParent, const QString &strIcon, const QString &strIconDis)
211 : UIAction(pParent, UIActionType_Menu)
212{
213 if (!strIcon.isNull())
214 setIcon(UIIconPool::iconSet(strIcon, strIconDis));
215 setMenu(new UIMenu);
216}
217
218UIActionMenu::UIActionMenu(QObject *pParent, const QIcon &icon)
219 : UIAction(pParent, UIActionType_Menu)
220{
221 if (!icon.isNull())
222 setIcon(icon);
223 setMenu(new UIMenu);
224}
225
226
227class UIActionSimpleLogDialog : public UIActionSimple
228{
229 Q_OBJECT;
230
231public:
232
233 UIActionSimpleLogDialog(QObject *pParent)
234 : UIActionSimple(pParent, QSize(32, 32), QSize(16, 16),
235 ":/vm_show_logs_32px.png", ":/show_logs_16px.png",
236 ":/vm_show_logs_disabled_32px.png", ":/show_logs_disabled_16px.png")
237 {
238 switch (gActionPool->type())
239 {
240 case UIActionPoolType_Selector:
241 setShortcut(gSS->keySequence(UISelectorShortcuts::ShowVMLogShortcut));
242 break;
243 case UIActionPoolType_Runtime:
244 break;
245 }
246 retranslateUi();
247 }
248
249protected:
250
251 void retranslateUi()
252 {
253 setText(QApplication::translate("UIActionPool", "Show &Log..."));
254 setStatusTip(QApplication::translate("UIActionPool", "Show the log files of the selected virtual machine"));
255 }
256};
257
258class UIActionMenuHelp : public UIActionMenu
259{
260 Q_OBJECT;
261
262public:
263
264 UIActionMenuHelp(QObject *pParent)
265 : UIActionMenu(pParent)
266 {
267 retranslateUi();
268 }
269
270protected:
271
272 void retranslateUi()
273 {
274 setText(menuText(QApplication::translate("UIActionPool", "&Help")));
275 }
276};
277
278class UIActionSimpleContents : public UIActionSimple
279{
280 Q_OBJECT;
281
282public:
283
284 UIActionSimpleContents(QObject *pParent)
285 : UIActionSimple(pParent, UIIconPool::defaultIcon(UIIconPool::DialogHelpIcon))
286 {
287 switch (gActionPool->type())
288 {
289 case UIActionPoolType_Selector:
290 setShortcut(gSS->keySequence(UISelectorShortcuts::HelpShortcut));
291 break;
292 case UIActionPoolType_Runtime:
293 setShortcut(gMS->keySequence(UIMachineShortcuts::HelpShortcut));
294 break;
295 }
296 retranslateUi();
297 }
298
299protected:
300
301 void retranslateUi()
302 {
303 setText(menuText(QApplication::translate("UIActionPool", "&Contents...")));
304 setStatusTip(QApplication::translate("UIActionPool", "Show help contents"));
305 }
306};
307
308class UIActionSimpleWebSite : public UIActionSimple
309{
310 Q_OBJECT;
311
312public:
313
314 UIActionSimpleWebSite(QObject *pParent)
315 : UIActionSimple(pParent, ":/site_16px.png")
316 {
317 switch (gActionPool->type())
318 {
319 case UIActionPoolType_Selector:
320 setShortcut(gSS->keySequence(UISelectorShortcuts::WebShortcut));
321 break;
322 case UIActionPoolType_Runtime:
323 setShortcut(gMS->keySequence(UIMachineShortcuts::WebShortcut));
324 break;
325 }
326 retranslateUi();
327 }
328
329protected:
330
331 void retranslateUi()
332 {
333 setText(vboxGlobal().insertKeyToActionText(menuText(QApplication::translate("UIActionPool", "&VirtualBox Web Site...")), gMS->shortcut(UIMachineShortcuts::WebShortcut)));
334 setStatusTip(QApplication::translate("UIActionPool", "Open the browser and go to the VirtualBox product web site"));
335 }
336};
337
338class UIActionSimpleResetWarnings : public UIActionSimple
339{
340 Q_OBJECT;
341
342public:
343
344 UIActionSimpleResetWarnings(QObject *pParent)
345 : UIActionSimple(pParent, ":/reset_16px.png")
346 {
347 switch (gActionPool->type())
348 {
349 case UIActionPoolType_Selector:
350 setShortcut(gSS->keySequence(UISelectorShortcuts::ResetWarningsShortcut));
351 break;
352 case UIActionPoolType_Runtime:
353 setShortcut(gMS->keySequence(UIMachineShortcuts::ResetWarningsShortcut));
354 break;
355 }
356 retranslateUi();
357 }
358
359protected:
360
361 void retranslateUi()
362 {
363 setText(vboxGlobal().insertKeyToActionText(menuText(QApplication::translate("UIActionPool", "&Reset All Warnings")), gMS->shortcut(UIMachineShortcuts::ResetWarningsShortcut)));
364 setStatusTip(QApplication::translate("UIActionPool", "Go back to showing all suppressed warnings and messages"));
365 }
366};
367
368class UIActionSimpleNetworkAccessManager : public UIActionSimple
369{
370 Q_OBJECT;
371
372public:
373
374 UIActionSimpleNetworkAccessManager(QObject *pParent)
375 : UIActionSimple(pParent, ":/nw_16px.png", ":/nw_disabled_16px.png")
376 {
377 switch (gActionPool->type())
378 {
379 case UIActionPoolType_Selector:
380 setShortcut(gSS->keySequence(UISelectorShortcuts::NetworkAccessManager));
381 break;
382 case UIActionPoolType_Runtime:
383 setShortcut(gMS->keySequence(UIMachineShortcuts::NetworkAccessManager));
384 break;
385 }
386 retranslateUi();
387 }
388
389protected:
390
391 void retranslateUi()
392 {
393 setText(vboxGlobal().insertKeyToActionText(menuText(QApplication::translate("UIActionPool", "&Network Operations Manager...")), gMS->shortcut(UIMachineShortcuts::NetworkAccessManager)));
394 setStatusTip(QApplication::translate("UIActionPool", "Show Network Operations Manager"));
395 }
396};
397
398class UIActionSimpleCheckForUpdates : public UIActionSimple
399{
400 Q_OBJECT;
401
402public:
403
404 UIActionSimpleCheckForUpdates(QObject *pParent)
405 : UIActionSimple(pParent, ":/refresh_16px.png", ":/refresh_disabled_16px.png")
406 {
407 setMenuRole(QAction::ApplicationSpecificRole);
408 switch (gActionPool->type())
409 {
410 case UIActionPoolType_Selector:
411 setShortcut(gSS->keySequence(UISelectorShortcuts::UpdateShortcut));
412 break;
413 case UIActionPoolType_Runtime:
414 setShortcut(gMS->keySequence(UIMachineShortcuts::UpdateShortcut));
415 break;
416 }
417 retranslateUi();
418 }
419
420protected:
421
422 void retranslateUi()
423 {
424 setText(vboxGlobal().insertKeyToActionText(menuText(QApplication::translate("UIActionPool", "C&heck for Updates...")), gMS->shortcut(UIMachineShortcuts::UpdateShortcut)));
425 setStatusTip(QApplication::translate("UIActionPool", "Check for a new VirtualBox version"));
426 }
427};
428
429class UIActionSimpleAbout : public UIActionSimple
430{
431 Q_OBJECT;
432
433public:
434
435 UIActionSimpleAbout(QObject *pParent)
436 : UIActionSimple(pParent, ":/about_16px.png")
437 {
438 setMenuRole(QAction::AboutRole);
439 switch (gActionPool->type())
440 {
441 case UIActionPoolType_Selector:
442 setShortcut(gSS->keySequence(UISelectorShortcuts::AboutShortcut));
443 break;
444 case UIActionPoolType_Runtime:
445 setShortcut(gMS->keySequence(UIMachineShortcuts::AboutShortcut));
446 break;
447 }
448 retranslateUi();
449 }
450
451protected:
452
453 void retranslateUi()
454 {
455 setText(vboxGlobal().insertKeyToActionText(menuText(QApplication::translate("UIActionPool", "&About VirtualBox...")), gMS->shortcut(UIMachineShortcuts::AboutShortcut)));
456 setStatusTip(QApplication::translate("UIActionPool", "Show a dialog with product information"));
457 }
458};
459
460
461/* UIActionPool stuff: */
462UIActionPool* UIActionPool::m_pInstance = 0;
463
464/* static */
465UIActionPool* UIActionPool::instance()
466{
467 return m_pInstance;
468}
469
470UIActionPool::UIActionPool(UIActionPoolType type)
471 : m_type(type)
472{
473 /* Prepare instance: */
474 if (!m_pInstance)
475 m_pInstance = this;
476}
477
478UIActionPool::~UIActionPool()
479{
480 /* Cleanup instance: */
481 if (m_pInstance == this)
482 m_pInstance = 0;
483}
484
485void UIActionPool::prepare()
486{
487 /* Create actions: */
488 createActions();
489 /* Create menus: */
490 createMenus();
491}
492
493void UIActionPool::cleanup()
494{
495 /* Destroy pool: */
496 destroyPool();
497}
498
499bool UIActionPool::processHotKey(const QKeySequence &key)
500{
501 /* Get the list of keys: */
502 QList<int> keys = m_pool.keys();
503 /* Iterate through the whole list of keys: */
504 for (int i = 0; i < keys.size(); ++i)
505 {
506 /* Get current action: */
507 UIAction *pAction = m_pool[keys[i]];
508 /* Skip menus/separators: */
509 if (pAction->type() == UIActionType_Menu)
510 continue;
511 /* Get the hot key of the current action: */
512 QString strHotKey = VBoxGlobal::extractKeyFromActionText(pAction->text());
513 if (pAction->isEnabled() && pAction->isVisible() && !strHotKey.isEmpty())
514 {
515 if (key.matches(QKeySequence(strHotKey)) == QKeySequence::ExactMatch)
516 {
517 /* We asynchronously post a special event instead of calling
518 * pAction->trigger() directly, to let key presses and
519 * releases be processed correctly by Qt first.
520 * Note: we assume that nobody will delete the menu item
521 * corresponding to the key sequence, so that the pointer to
522 * menu data posted along with the event will remain valid in
523 * the event handler, at least until the main window is closed. */
524 QApplication::postEvent(this, new ActivateActionEvent(pAction));
525 return true;
526 }
527 }
528 }
529 return false;
530}
531
532void UIActionPool::createActions()
533{
534 /* Various dialog actions: */
535 m_pool[UIActionIndex_Simple_LogDialog] = new UIActionSimpleLogDialog(this);
536 /* 'Help' actions: */
537 m_pool[UIActionIndex_Simple_Contents] = new UIActionSimpleContents(this);
538 m_pool[UIActionIndex_Simple_WebSite] = new UIActionSimpleWebSite(this);
539 m_pool[UIActionIndex_Simple_ResetWarnings] = new UIActionSimpleResetWarnings(this);
540 m_pool[UIActionIndex_Simple_NetworkAccessManager] = new UIActionSimpleNetworkAccessManager(this);
541 m_pool[UIActionIndex_Simple_CheckForUpdates] = new UIActionSimpleCheckForUpdates(this);
542 m_pool[UIActionIndex_Simple_About] = new UIActionSimpleAbout(this);
543}
544
545void UIActionPool::createMenus()
546{
547 /* On Mac OS X, all QMenu's are consumed by Qt after they are added to another QMenu or a QMenuBar.
548 * This means we have to recreate all QMenus when creating a new QMenuBar.
549 * For simplicity we doing this on all platforms right now. */
550
551 /* Recreate 'help' menu items as well.
552 * This makes sure they are removed also from the Application menu: */
553 if (m_pool[UIActionIndex_Simple_Contents])
554 delete m_pool[UIActionIndex_Simple_Contents];
555 m_pool[UIActionIndex_Simple_Contents] = new UIActionSimpleContents(this);
556 if (m_pool[UIActionIndex_Simple_WebSite])
557 delete m_pool[UIActionIndex_Simple_WebSite];
558 m_pool[UIActionIndex_Simple_WebSite] = new UIActionSimpleWebSite(this);
559 if (m_pool[UIActionIndex_Simple_ResetWarnings])
560 delete m_pool[UIActionIndex_Simple_ResetWarnings];
561 m_pool[UIActionIndex_Simple_ResetWarnings] = new UIActionSimpleResetWarnings(this);
562 if (m_pool[UIActionIndex_Simple_NetworkAccessManager])
563 delete m_pool[UIActionIndex_Simple_NetworkAccessManager];
564 m_pool[UIActionIndex_Simple_NetworkAccessManager] = new UIActionSimpleNetworkAccessManager(this);
565#if defined(Q_WS_MAC) && (QT_VERSION >= 0x040700)
566 /* For whatever reason, Qt doesn't fully remove items with a
567 * ApplicationSpecificRole from the application menu. Although the QAction
568 * itself is deleted, a dummy entry is leaved back in the menu.
569 * Hiding before deletion helps. */
570 m_pool[UIActionIndex_Simple_CheckForUpdates]->setVisible(false);
571#endif
572#if !(defined(Q_WS_MAC) && (QT_VERSION < 0x040700))
573 if (m_pool[UIActionIndex_Simple_CheckForUpdates])
574 delete m_pool[UIActionIndex_Simple_CheckForUpdates];
575 m_pool[UIActionIndex_Simple_CheckForUpdates] = new UIActionSimpleCheckForUpdates(this);
576 if (m_pool[UIActionIndex_Simple_About])
577 delete m_pool[UIActionIndex_Simple_About];
578 m_pool[UIActionIndex_Simple_About] = new UIActionSimpleAbout(this);
579#endif
580
581 /* 'Help' menu itself: */
582 if (m_pool[UIActionIndex_Menu_Help])
583 delete m_pool[UIActionIndex_Menu_Help];
584 m_pool[UIActionIndex_Menu_Help] = new UIActionMenuHelp(this);
585}
586
587void UIActionPool::destroyPool()
588{
589 /* Get the list of keys: */
590 QList<int> keys = m_pool.keys();
591 /* Delete all the items of the map: */
592 for (int i = 0; i < keys.size(); ++i)
593 delete m_pool[keys[i]];
594}
595
596bool UIActionPool::event(QEvent *pEvent)
597{
598 /* Depending on event-type: */
599 switch (pEvent->type())
600 {
601 case ActivateActionEventType:
602 {
603 /* Process specific event: */
604 ActivateActionEvent *pActionEvent = static_cast<ActivateActionEvent*>(pEvent);
605 pActionEvent->action()->trigger();
606 pEvent->accept();
607 return true;
608 }
609 default:
610 break;
611 }
612 /* Pass to the base-class: */
613 return QObject::event(pEvent);
614}
615
616#include "UIActionPool.moc"
617
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use