VirtualBox

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

Last change on this file since 44453 was 44449, checked in by vboxsync, 11 years ago

FE/Qt: Fixing little typo in r83440.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use