VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp@ 43138

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

FE/Qt: 6234: Support for VM groups: Save VM groups order on-the-fly in parallel thread (extra-data).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.8 KB
Line 
1/** @file
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * UISelectorWindow class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2012 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#ifdef VBOX_WITH_PRECOMPILED_HEADERS
20# include "precomp.h"
21#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
22
23/* Qt includes: */
24#include <QDesktopWidget>
25#include <QDesktopServices>
26#include <QMenuBar>
27#include <QResizeEvent>
28#include <QStackedWidget>
29
30/* Local includes: */
31#include "QISplitter.h"
32#include "QIFileDialog.h"
33#include "UIBar.h"
34#include "UINetworkManager.h"
35#include "UINetworkManagerIndicator.h"
36#include "UIUpdateManager.h"
37#include "UIDownloaderUserManual.h"
38#include "UIDownloaderExtensionPack.h"
39#include "UIIconPool.h"
40#include "UIWizardCloneVM.h"
41#include "UIWizardExportApp.h"
42#include "UIWizardImportApp.h"
43#include "UIVMDesktop.h"
44#include "UIVirtualBoxEventHandler.h"
45#include "UIMediumManager.h"
46#include "UIMessageCenter.h"
47#include "UISelectorWindow.h"
48#include "UISettingsDialogSpecific.h"
49#include "UIToolBar.h"
50#include "UIVMLogViewer.h"
51#include "UISelectorShortcuts.h"
52#include "UIDesktopServices.h"
53#include "UIGlobalSettingsExtension.h"
54#include "UIActionPoolSelector.h"
55#include "UIGChooser.h"
56#include "UIGDetails.h"
57#include "UIVMItem.h"
58#include "VBoxGlobal.h"
59
60#ifdef Q_WS_MAC
61# include "VBoxUtils.h"
62# include "UIWindowMenuManager.h"
63# include "UIImageTools.h"
64#endif /* Q_WS_MAC */
65
66/* Other VBox stuff: */
67#include <iprt/buildconfig.h>
68#include <VBox/version.h>
69#ifdef Q_WS_X11
70# include <iprt/env.h>
71#endif /* Q_WS_X11 */
72
73#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
74
75UISelectorWindow::UISelectorWindow(UISelectorWindow **ppSelf, QWidget *pParent,
76 Qt::WindowFlags flags /* = Qt::Window */)
77 : QIWithRetranslateUI2<QMainWindow>(pParent, flags)
78 , m_pSplitter(0)
79#ifndef Q_WS_MAC
80 , m_pBar(0)
81#endif /* !Q_WS_MAC */
82 , mVMToolBar(0)
83 , m_pContainer(0)
84 , m_pChooser(0)
85 , m_pDetails(0)
86 , m_pVMDesktop(0)
87 , m_fDoneInaccessibleWarningOnce(false)
88{
89 /* Remember self: */
90 if (ppSelf)
91 *ppSelf = this;
92
93 /* Prepare: */
94 prepareIcon();
95 prepareMenuBar();
96 prepareStatusBar();
97 prepareWidgets();
98 prepareConnections();
99
100 /* Load settings: */
101 loadSettings();
102
103 /* Translate UI: */
104 retranslateUi();
105
106#ifdef Q_WS_MAC
107# if MAC_LEOPARD_STYLE
108 /* Enable unified toolbars on Mac OS X. Available on Qt >= 4.3.
109 * We do this after setting the window pos/size, cause Qt sometimes
110 * includes the toolbar height in the content height. */
111 mVMToolBar->setMacToolbar();
112# endif /* MAC_LEOPARD_STYLE */
113
114 UIWindowMenuManager::instance()->addWindow(this);
115 /* Beta label? */
116 if (vboxGlobal().isBeta())
117 {
118 QPixmap betaLabel = ::betaLabelSleeve(QSize(107, 16));
119 ::darwinLabelWindow(this, &betaLabel, false);
120 }
121
122 /* General event filter: */
123 qApp->installEventFilter(this);
124#endif /* Q_WS_MAC */
125}
126
127UISelectorWindow::~UISelectorWindow()
128{
129 /* Destroy event handlers: */
130 UIVirtualBoxEventHandler::destroy();
131
132 /* Save settings: */
133 saveSettings();
134}
135
136void UISelectorWindow::sltStateChanged(QString)
137{
138 /* Get current item: */
139 UIVMItem *pItem = currentItem();
140
141 /* Make sure current item present: */
142 if (!pItem)
143 return;
144
145 /* Update actions: */
146 updateActionsAppearance();
147}
148
149void UISelectorWindow::sltSnapshotChanged(QString strId)
150{
151 /* Get current item: */
152 UIVMItem *pItem = currentItem();
153
154 /* Make sure current item present: */
155 if (!pItem)
156 return;
157
158 /* If signal is for the current item: */
159 if (pItem->id() == strId)
160 m_pVMDesktop->updateSnapshots(pItem, pItem->machine());
161}
162
163void UISelectorWindow::sltDetailsViewIndexChanged(int iWidgetIndex)
164{
165 if (iWidgetIndex)
166 m_pContainer->setCurrentWidget(m_pVMDesktop);
167 else
168 m_pContainer->setCurrentWidget(m_pDetails);
169}
170
171void UISelectorWindow::sltMediumEnumFinished(const VBoxMediaList &list)
172{
173 /* We warn about inaccessible media only once
174 * (after media emumeration started from main() at startup),
175 * to avoid annoying the user: */
176 if (m_fDoneInaccessibleWarningOnce)
177 return;
178 m_fDoneInaccessibleWarningOnce = true;
179
180 /* Ignore the signal if a modal widget is currently active
181 * (we won't be able to properly show the modeless VDI manager window in this case): */
182 // TODO: Not sure that is required at all...
183 if (QApplication::activeModalWidget())
184 return;
185
186 /* Ignore the signal if a UIMediumManager window is active: */
187 // TODO: Thats a very dirty way, rework required!
188 if (qApp->activeWindow() &&
189 !strcmp(qApp->activeWindow()->metaObject()->className(), "UIMediumManager"))
190 return;
191
192 /* Look for at least one inaccessible media: */
193 VBoxMediaList::const_iterator it;
194 for (it = list.begin(); it != list.end(); ++it)
195 if ((*it).state() == KMediumState_Inaccessible)
196 break;
197 /* Ask the user about: */
198 if (it != list.end() && msgCenter().remindAboutInaccessibleMedia())
199 {
200 /* Show the VMM dialog without refresh: */
201 UIMediumManager::showModeless(this, false /* refresh? */);
202 }
203}
204
205void UISelectorWindow::sltShowSelectorContextMenu(const QPoint &pos)
206{
207 /* Load toolbar/statusbar availability settings: */
208 CVirtualBox vbox = vboxGlobal().virtualBox();
209 QString strToolbar = vbox.GetExtraData(GUI_Toolbar);
210 QString strStatusbar = vbox.GetExtraData(GUI_Statusbar);
211 bool fToolbar = strToolbar.isEmpty() || strToolbar == "true";
212 bool fStatusbar = strStatusbar.isEmpty() || strStatusbar == "true";
213
214 /* Populate toolbar/statusbar acctions: */
215 QList<QAction*> actions;
216 QAction *pShowToolBar = new QAction(tr("Show Toolbar"), 0);
217 pShowToolBar->setCheckable(true);
218 pShowToolBar->setChecked(fToolbar);
219 actions << pShowToolBar;
220 QAction *pShowStatusBar = new QAction(tr("Show Statusbar"), 0);
221 pShowStatusBar->setCheckable(true);
222 pShowStatusBar->setChecked(fStatusbar);
223 actions << pShowStatusBar;
224
225 QPoint gpos = pos;
226 QWidget *pSender = static_cast<QWidget*>(sender());
227 if (pSender)
228 gpos = pSender->mapToGlobal(pos);
229 QAction *pResult = QMenu::exec(actions, gpos);
230 if (pResult == pShowToolBar)
231 {
232 if (pResult->isChecked())
233 {
234#ifdef Q_WS_MAC
235 mVMToolBar->show();
236#else /* Q_WS_MAC */
237 m_pBar->show();
238#endif /* !Q_WS_MAC */
239 vbox.SetExtraData(GUI_Toolbar, "true");
240 }
241 else
242 {
243#ifdef Q_WS_MAC
244 mVMToolBar->hide();
245#else /* Q_WS_MAC */
246 m_pBar->hide();
247#endif /* !Q_WS_MAC */
248 vbox.SetExtraData(GUI_Toolbar, "false");
249 }
250 }
251 else if (pResult == pShowStatusBar)
252 {
253 if (pResult->isChecked())
254 {
255 statusBar()->show();
256 vbox.SetExtraData(GUI_Statusbar, "true");
257 }
258 else
259 {
260 statusBar()->hide();
261 vbox.SetExtraData(GUI_Statusbar, "false");
262 }
263 }
264}
265
266void UISelectorWindow::sltShowMediumManager()
267{
268 /* Show modeless Virtual Medium Manager: */
269 UIMediumManager::showModeless(this);
270}
271
272void UISelectorWindow::sltShowImportApplianceWizard(const QString &strFileName /* = QString() */)
273{
274 /* Show Import Appliance wizard: */
275#ifdef Q_WS_MAC
276 QString strTmpFile = ::darwinResolveAlias(strFileName);
277#else /* Q_WS_MAC */
278 QString strTmpFile = strFileName;
279#endif /* !Q_WS_MAC */
280 UIWizardImportApp wizard(this, strTmpFile);
281 if (strFileName.isEmpty() || wizard.isValid())
282 wizard.exec();
283}
284
285void UISelectorWindow::sltShowExportApplianceWizard()
286{
287 /* Get selected items: */
288 QList<UIVMItem*> items = currentItems();
289 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
290
291 /* Populate the list of VM names: */
292 QStringList names;
293 for (int i = 0; i < items.size(); ++i)
294 names << items[i]->name();
295 /* Show Export Appliance wizard: */
296 UIWizardExportApp wizard(this, names);
297 wizard.exec();
298}
299
300void UISelectorWindow::sltShowPreferencesDialog()
301{
302 /* Check that we do NOT handling that already: */
303 if (m_pPreferencesDialogAction->data().toBool())
304 return;
305 /* Remember that we handling that already: */
306 m_pPreferencesDialogAction->setData(true);
307
308 /* Create and execute global settings dialog: */
309 UISettingsDialogGlobal dialog(this);
310 dialog.execute();
311
312 /* Remember that we do NOT handling that already: */
313 m_pPreferencesDialogAction->setData(false);
314}
315
316void UISelectorWindow::sltPerformExit()
317{
318 close();
319}
320
321void UISelectorWindow::sltShowAddMachineDialog(const QString &strFileName /* = QString() */)
322{
323 /* Initialize variables: */
324#ifdef Q_WS_MAC
325 QString strTmpFile = ::darwinResolveAlias(strFileName);
326#else /* Q_WS_MAC */
327 QString strTmpFile = strFileName;
328#endif /* !Q_WS_MAC */
329 CVirtualBox vbox = vboxGlobal().virtualBox();
330 if (strTmpFile.isEmpty())
331 {
332 QString strBaseFolder = vbox.GetSystemProperties().GetDefaultMachineFolder();
333 QString strTitle = tr("Select a virtual machine file");
334 QStringList extensions;
335 for (int i = 0; i < VBoxFileExts.size(); ++i)
336 extensions << QString("*.%1").arg(VBoxFileExts[i]);
337 QString strFilter = tr("Virtual machine files (%1)").arg(extensions.join(" "));
338 /* Create open file dialog: */
339 QStringList fileNames = QIFileDialog::getOpenFileNames(strBaseFolder, strFilter, this, strTitle, 0, true, true);
340 if (!fileNames.isEmpty())
341 strTmpFile = fileNames.at(0);
342 }
343 /* Nothing was chosen? */
344 if (strTmpFile.isEmpty())
345 return;
346
347 /* Make sure this machine can be opened: */
348 CMachine newMachine = vbox.OpenMachine(strTmpFile);
349 if (!vbox.isOk() || newMachine.isNull())
350 {
351 msgCenter().cannotOpenMachine(this, strTmpFile, vbox);
352 return;
353 }
354
355 /* Make sure this machine was NOT registered already: */
356 CMachine oldMachine = vbox.FindMachine(newMachine.GetId());
357 if (!oldMachine.isNull())
358 {
359 msgCenter().cannotReregisterMachine(this, strTmpFile, oldMachine.GetName());
360 return;
361 }
362
363 /* Register that machine: */
364 vbox.RegisterMachine(newMachine);
365}
366
367void UISelectorWindow::sltShowMachineSettingsDialog(const QString &strCategoryRef /* = QString() */,
368 const QString &strControlRef /* = QString() */,
369 const QString &strId /* = QString() */)
370{
371 /* Check that we do NOT handling that already: */
372 if (m_pAction_Machine_Settings->data().toBool())
373 return;
374 /* Remember that we handling that already: */
375 m_pAction_Machine_Settings->setData(true);
376
377 /* Process href from VM details / description: */
378 if (!strCategoryRef.isEmpty() && strCategoryRef[0] != '#')
379 {
380 vboxGlobal().openURL(strCategoryRef);
381 return;
382 }
383
384 /* Get category and control: */
385 QString strCategory = strCategoryRef;
386 QString strControl = strControlRef;
387 /* Check if control is coded into the URL by %%: */
388 if (strControl.isEmpty())
389 {
390 QStringList parts = strCategory.split("%%");
391 if (parts.size() == 2)
392 {
393 strCategory = parts.at(0);
394 strControl = parts.at(1);
395 }
396 }
397
398 /* Don't show the inaccessible warning if the user tries to open VM settings: */
399 m_fDoneInaccessibleWarningOnce = true;
400
401 /* Create and execute corresponding VM settings dialog: */
402 UISettingsDialogMachine dialog(this,
403 strId.isEmpty() ? currentItem()->id() : strId,
404 strCategory, strControl);
405 dialog.execute();
406
407 /* Remember that we do NOT handling that already: */
408 m_pAction_Machine_Settings->setData(false);
409}
410
411void UISelectorWindow::sltShowCloneMachineWizard()
412{
413 /* Get current item: */
414 UIVMItem *pItem = currentItem();
415 AssertMsgReturnVoid(pItem, ("Current item should be selected!\n"));
416
417 /* Show Clone VM wizard: */
418 UIWizardCloneVM wizard(this, pItem->machine());
419 wizard.exec();
420}
421
422void UISelectorWindow::sltPerformStartOrShowAction()
423{
424 /* Get selected items: */
425 QList<UIVMItem*> items = currentItems();
426 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
427
428 /* For every selected item: */
429 foreach (UIVMItem *pItem, items)
430 {
431 /* Check if current item could be started/showed: */
432 if (!isActionEnabled(UIActionIndexSelector_State_Common_StartOrShow, QList<UIVMItem*>() << pItem))
433 continue;
434
435 /* Launch/show current VM: */
436 CMachine machine = pItem->machine();
437 vboxGlobal().launchMachine(machine, qApp->keyboardModifiers() == Qt::ShiftModifier);
438 }
439}
440
441void UISelectorWindow::sltPerformDiscardAction()
442{
443 /* Get selected items: */
444 QList<UIVMItem*> items = currentItems();
445 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
446
447 /* Prepare the list of the machines to be discarded: */
448 QStringList machineNames;
449 QList<UIVMItem*> itemsToDiscard;
450 foreach (UIVMItem *pItem, items)
451 if (isActionEnabled(UIActionIndexSelector_Simple_Common_Discard, QList<UIVMItem*>() << pItem))
452 {
453 machineNames << pItem->name();
454 itemsToDiscard << pItem;
455 }
456 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
457
458 /* Confirm discarding saved VM state: */
459 if (!msgCenter().confirmDiscardSavedState(machineNames.join(", ")))
460 return;
461
462 /* For every confirmed item: */
463 foreach (UIVMItem *pItem, itemsToDiscard)
464 {
465 /* Open a session to modify VM: */
466 CSession session = vboxGlobal().openSession(pItem->id());
467 if (session.isNull())
468 {
469 msgCenter().cannotOpenSession(session);
470 return;
471 }
472
473 /* Get session console: */
474 CConsole console = session.GetConsole();
475 console.DiscardSavedState(true);
476 if (!console.isOk())
477 msgCenter().cannotDiscardSavedState(console);
478
479 /* Unlock machine finally: */
480 session.UnlockMachine();
481 }
482}
483
484void UISelectorWindow::sltPerformPauseResumeAction(bool fPause)
485{
486 /* Get selected items: */
487 QList<UIVMItem*> items = currentItems();
488 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
489
490 /* For every selected item: */
491 foreach (UIVMItem *pItem, items)
492 {
493 /* Get item state: */
494 KMachineState state = pItem->machineState();
495
496 /* Check if current item could be paused/resumed: */
497 if (!isActionEnabled(UIActionIndexSelector_Toggle_Common_PauseAndResume, QList<UIVMItem*>() << pItem))
498 continue;
499
500 /* Check if current item already paused: */
501 if (fPause &&
502 (state == KMachineState_Paused ||
503 state == KMachineState_TeleportingPausedVM))
504 continue;
505
506 /* Check if current item already resumed: */
507 if (!fPause &&
508 (state == KMachineState_Running ||
509 state == KMachineState_Teleporting ||
510 state == KMachineState_LiveSnapshotting))
511 continue;
512
513 /* Open a session to modify VM state: */
514 CSession session = vboxGlobal().openExistingSession(pItem->id());
515 if (session.isNull())
516 {
517 msgCenter().cannotOpenSession(session);
518 return;
519 }
520
521 /* Get session console: */
522 CConsole console = session.GetConsole();
523 /* Pause/resume VM: */
524 if (fPause)
525 console.Pause();
526 else
527 console.Resume();
528 bool ok = console.isOk();
529 if (!ok)
530 {
531 if (fPause)
532 msgCenter().cannotPauseMachine(console);
533 else
534 msgCenter().cannotResumeMachine(console);
535 }
536
537 /* Unlock machine finally: */
538 session.UnlockMachine();
539 }
540}
541
542void UISelectorWindow::sltPerformResetAction()
543{
544 /* Get selected items: */
545 QList<UIVMItem*> items = currentItems();
546 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
547
548 /* Prepare the list of the machines to be reseted: */
549 QStringList machineNames;
550 QList<UIVMItem*> itemsToReset;
551 foreach (UIVMItem *pItem, items)
552 if (isActionEnabled(UIActionIndexSelector_Simple_Common_Reset, QList<UIVMItem*>() << pItem))
553 {
554 machineNames << pItem->name();
555 itemsToReset << pItem;
556 }
557 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
558
559 /* Confirm reseting VM: */
560 if (!msgCenter().confirmVMReset(machineNames.join(", ")))
561 return;
562
563 /* For each selected item: */
564 foreach (UIVMItem *pItem, itemsToReset)
565 {
566 /* Open a session to modify VM state: */
567 CSession session = vboxGlobal().openExistingSession(pItem->id());
568 if (session.isNull())
569 {
570 msgCenter().cannotOpenSession(session);
571 return;
572 }
573
574 /* Get session console: */
575 CConsole console = session.GetConsole();
576 /* Reset VM: */
577 console.Reset();
578
579 /* Unlock machine finally: */
580 session.UnlockMachine();
581 }
582}
583
584void UISelectorWindow::sltPerformSaveAction()
585{
586 /* Get selected items: */
587 QList<UIVMItem*> items = currentItems();
588 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
589
590 /* For each selected item: */
591 foreach (UIVMItem *pItem, items)
592 {
593 /* Check if current item could be saved: */
594 if (!isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_Save, QList<UIVMItem*>() << pItem))
595 continue;
596
597 /* Open a session to modify VM state: */
598 CSession session = vboxGlobal().openExistingSession(pItem->id());
599 if (session.isNull())
600 {
601 msgCenter().cannotOpenSession(session);
602 return;
603 }
604
605 /* Get session console: */
606 CConsole console = session.GetConsole();
607 /* Save machine state: */
608 CProgress progress = console.SaveState();
609 if (!console.isOk())
610 msgCenter().cannotSaveMachineState(console);
611 else
612 {
613 /* Show the "VM saving" progress dialog: */
614 CMachine machine = session.GetMachine();
615 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_save_90px.png", 0, true);
616 if (progress.GetResultCode() != 0)
617 msgCenter().cannotSaveMachineState(progress);
618 }
619
620 /* Unlock machine finally: */
621 session.UnlockMachine();
622 }
623}
624
625void UISelectorWindow::sltPerformACPIShutdownAction()
626{
627 /* Get selected items: */
628 QList<UIVMItem*> items = currentItems();
629 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
630
631 /* Prepare the list of the machines to be shutdowned: */
632 QStringList machineNames;
633 QList<UIVMItem*> itemsToShutdown;
634 foreach (UIVMItem *pItem, items)
635 if (isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_ACPIShutdown, QList<UIVMItem*>() << pItem))
636 {
637 machineNames << pItem->name();
638 itemsToShutdown << pItem;
639 }
640 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
641
642 /* Confirm ACPI shutdown current VM: */
643 if (!msgCenter().confirmVMACPIShutdown(machineNames.join(", ")))
644 return;
645
646 /* For each selected item: */
647 foreach (UIVMItem *pItem, itemsToShutdown)
648 {
649 /* Open a session to modify VM state: */
650 CSession session = vboxGlobal().openExistingSession(pItem->id());
651 if (session.isNull())
652 {
653 msgCenter().cannotOpenSession(session);
654 return;
655 }
656
657 /* Get session console: */
658 CConsole console = session.GetConsole();
659 /* ACPI Shutdown: */
660 console.PowerButton();
661
662 /* Unlock machine finally: */
663 session.UnlockMachine();
664 }
665}
666
667void UISelectorWindow::sltPerformPowerOffAction()
668{
669 /* Get selected items: */
670 QList<UIVMItem*> items = currentItems();
671 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
672
673 /* Prepare the list of the machines to be powered off: */
674 QStringList machineNames;
675 QList<UIVMItem*> itemsToPowerOff;
676 foreach (UIVMItem *pItem, items)
677 if (isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_PowerOff, QList<UIVMItem*>() << pItem))
678 {
679 machineNames << pItem->name();
680 itemsToPowerOff << pItem;
681 }
682 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
683
684 /* Confirm Power Off current VM: */
685 if (!msgCenter().confirmVMPowerOff(machineNames.join(", ")))
686 return;
687
688 /* For each selected item: */
689 foreach (UIVMItem *pItem, itemsToPowerOff)
690 {
691 /* Open a session to modify VM state: */
692 CSession session = vboxGlobal().openExistingSession(pItem->id());
693 if (session.isNull())
694 {
695 msgCenter().cannotOpenSession(session);
696 return;
697 }
698
699 /* Get session console: */
700 CConsole console = session.GetConsole();
701 /* Power Off: */
702 console.PowerDown();
703
704 /* Unlock machine finally: */
705 session.UnlockMachine();
706 }
707}
708
709void UISelectorWindow::sltPerformRefreshAction()
710{
711 /* Get selected items: */
712 QList<UIVMItem*> items = currentItems();
713 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
714
715 // TODO: Notify selector-model to refresh selected items!
716
717 /* Refresh details: */
718 sltCurrentVMItemChanged();
719}
720
721void UISelectorWindow::sltShowLogDialog()
722{
723 /* Get selected items: */
724 QList<UIVMItem*> items = currentItems();
725 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
726
727 /* For each selected item: */
728 foreach (UIVMItem *pItem, items)
729 {
730 /* Check if log could be show for the current item: */
731 if (!isActionEnabled(UIActionIndex_Simple_LogDialog, QList<UIVMItem*>() << pItem))
732 continue;
733
734 /* Show VM Log Viewer: */
735 UIVMLogViewer::showLogViewerFor(this, pItem->machine());
736 }
737}
738
739void UISelectorWindow::sltShowMachineInFileManager()
740{
741 /* Get selected items: */
742 QList<UIVMItem*> items = currentItems();
743 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
744
745 /* For each selected item: */
746 foreach (UIVMItem *pItem, items)
747 {
748 /* Check if that item could be shown in file-browser: */
749 if (!isActionEnabled(UIActionIndexSelector_Simple_Common_ShowInFileManager, QList<UIVMItem*>() << pItem))
750 continue;
751
752 /* Show VM in filebrowser: */
753 UIDesktopServices::openInFileManager(pItem->machine().GetSettingsFilePath());
754 }
755}
756
757void UISelectorWindow::sltPerformCreateShortcutAction()
758{
759 /* Get selected items: */
760 QList<UIVMItem*> items = currentItems();
761 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
762
763 /* For each selected item: */
764 foreach (UIVMItem *pItem, items)
765 {
766 /* Check if shortcuts could be created for this item: */
767 if (!isActionEnabled(UIActionIndexSelector_Simple_Common_CreateShortcut, QList<UIVMItem*>() << pItem))
768 continue;
769
770 /* Create shortcut for this VM: */
771 const CMachine &machine = pItem->machine();
772 UIDesktopServices::createMachineShortcut(machine.GetSettingsFilePath(),
773 QDesktopServices::storageLocation(QDesktopServices::DesktopLocation),
774 machine.GetName(), machine.GetId());
775 }
776}
777
778void UISelectorWindow::sltGroupCloseMenuAboutToShow()
779{
780 /* Get selected items: */
781 QList<UIVMItem*> items = currentItems();
782 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
783
784 m_pGroupACPIShutdownAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Close_ACPIShutdown, items));
785}
786void UISelectorWindow::sltMachineCloseMenuAboutToShow()
787{
788 /* Get selected items: */
789 QList<UIVMItem*> items = currentItems();
790 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
791
792 m_pMachineACPIShutdownAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_ACPIShutdown, items));
793}
794
795void UISelectorWindow::sltCurrentVMItemChanged(bool fRefreshDetails, bool fRefreshSnapshots, bool)
796{
797 /* Get current item: */
798 UIVMItem *pItem = currentItem();
799
800 /* Determine which menu to show: */
801 m_pGroupMenuAction->setVisible(m_pChooser->singleGroupSelected());
802 m_pMachineMenuAction->setVisible(!m_pChooser->singleGroupSelected());
803 if (m_pGroupMenuAction->isVisible())
804 {
805 foreach (UIAction *pAction, m_machineActions)
806 pAction->hideShortcut();
807 foreach (UIAction *pAction, m_groupActions)
808 pAction->showShortcut();
809 }
810 else if (m_pMachineMenuAction->isVisible())
811 {
812 foreach (UIAction *pAction, m_groupActions)
813 pAction->hideShortcut();
814 foreach (UIAction *pAction, m_machineActions)
815 pAction->showShortcut();
816 }
817
818 /* Update action appearance: */
819 updateActionsAppearance();
820
821 /* If currently selected VM item is accessible: */
822 if (pItem && pItem->accessible())
823 {
824 /* Make sure valid widget raised: */
825 if (m_pVMDesktop->widgetIndex())
826 m_pContainer->setCurrentWidget(m_pVMDesktop);
827 else
828 m_pContainer->setCurrentWidget(m_pDetails);
829
830 if (fRefreshDetails)
831 m_pDetails->setItems(currentItems());
832 if (fRefreshSnapshots)
833 {
834 m_pVMDesktop->updateSnapshots(pItem, pItem->machine());
835 /* Always hide snapshots-view if
836 * single group or more than one machine is selected: */
837 if (currentItems().size() > 1 || m_pChooser->singleGroupSelected())
838 m_pVMDesktop->lockSnapshots();
839 }
840 }
841 /* If currently selected VM item is NOT accessible: */
842 else
843 {
844 /* Make sure valid widget raised: */
845 m_pContainer->setCurrentWidget(m_pVMDesktop);
846
847 /* Note that the machine becomes inaccessible (or if the last VM gets
848 * deleted), we have to update all fields, ignoring input arguments. */
849 if (pItem)
850 {
851 /* The VM is inaccessible: */
852 m_pVMDesktop->updateDetailsErrorText(UIMessageCenter::formatErrorInfo(pItem->accessError()));
853 }
854 else
855 {
856 /* Default HTML support in Qt is terrible so just try to get something really simple: */
857 m_pVMDesktop->updateDetailsText(
858 tr("<h3>Welcome to VirtualBox!</h3>"
859 "<p>The left part of this window is "
860 "a list of all virtual machines on your computer. "
861 "The list is empty now because you haven't created any virtual "
862 "machines yet."
863 "<img src=:/welcome.png align=right/></p>"
864 "<p>In order to create a new virtual machine, press the "
865 "<b>New</b> button in the main tool bar located "
866 "at the top of the window.</p>"
867 "<p>You can press the <b>%1</b> key to get instant help, "
868 "or visit "
869 "<a href=http://www.virtualbox.org>www.virtualbox.org</a> "
870 "for the latest information and news.</p>")
871 .arg(QKeySequence(QKeySequence::HelpContents).toString(QKeySequence::NativeText)));
872 }
873
874 /* Empty and disable other tabs: */
875 m_pVMDesktop->updateSnapshots(0, CMachine());
876 }
877}
878
879void UISelectorWindow::sltOpenUrls(QList<QUrl> list /* = QList<QUrl>() */)
880{
881 /* Make sure any pending D&D events are consumed. */
882 // TODO: What? So dangerous method for so cheap purpose?
883 qApp->processEvents();
884
885 if (list.isEmpty())
886 {
887 list = vboxGlobal().argUrlList();
888 vboxGlobal().argUrlList().clear();
889 }
890 /* Check if we are can handle the dropped urls. */
891 for (int i = 0; i < list.size(); ++i)
892 {
893#ifdef Q_WS_MAC
894 QString strFile = ::darwinResolveAlias(list.at(i).toLocalFile());
895#else /* Q_WS_MAC */
896 QString strFile = list.at(i).toLocalFile();
897#endif /* !Q_WS_MAC */
898 if (!strFile.isEmpty() && QFile::exists(strFile))
899 {
900 if (VBoxGlobal::hasAllowedExtension(strFile, VBoxFileExts))
901 {
902 /* VBox config files. */
903 CVirtualBox vbox = vboxGlobal().virtualBox();
904 CMachine machine = vbox.FindMachine(strFile);
905 if (!machine.isNull())
906 {
907 CVirtualBox vbox = vboxGlobal().virtualBox();
908 CMachine machine = vbox.FindMachine(strFile);
909 if (!machine.isNull())
910 vboxGlobal().launchMachine(machine);
911 }
912 else
913 sltShowAddMachineDialog(strFile);
914 }
915 else if (VBoxGlobal::hasAllowedExtension(strFile, OVFFileExts))
916 {
917 /* OVF/OVA. Only one file at the time. */
918 sltShowImportApplianceWizard(strFile);
919 break;
920 }
921 else if (VBoxGlobal::hasAllowedExtension(strFile, VBoxExtPackFileExts))
922 {
923 UIGlobalSettingsExtension::doInstallation(strFile, QString(), this, NULL);
924 }
925 }
926 }
927}
928
929void UISelectorWindow::sltGroupSavingUpdate()
930{
931 updateActionsAppearance();
932}
933
934void UISelectorWindow::retranslateUi()
935{
936 /* Set window title: */
937 QString strTitle(VBOX_PRODUCT);
938 strTitle += " " + tr("Manager", "Note: main window title which is pretended by the product name.");
939#ifdef VBOX_BLEEDING_EDGE
940 strTitle += QString(" EXPERIMENTAL build ")
941 + QString(RTBldCfgVersion())
942 + QString(" r")
943 + QString(RTBldCfgRevisionStr())
944 + QString(" - "VBOX_BLEEDING_EDGE);
945#endif /* VBOX_BLEEDING_EDGE */
946 setWindowTitle(strTitle);
947
948 /* Ensure the details and screenshot view are updated: */
949 sltCurrentVMItemChanged();
950
951#ifdef VBOX_GUI_WITH_SYSTRAY
952 if (vboxGlobal().isTrayMenu())
953 {
954 m_pTrayIcon->retranslateUi();
955 m_pTrayIcon->refresh();
956 }
957#endif /* VBOX_GUI_WITH_SYSTRAY */
958
959#ifdef QT_MAC_USE_COCOA
960 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when
961 the necessary size of the toolbar is increased. Also for some languages
962 the with doesn't match if the text increase. So manually adjust the size
963 after changing the text. */
964 mVMToolBar->updateLayout();
965#endif /* QT_MAC_USE_COCOA */
966}
967
968bool UISelectorWindow::event(QEvent *pEvent)
969{
970 /* Which event do we have? */
971 switch (pEvent->type())
972 {
973 /* By handling every Resize and Move we keep track of the normal
974 * (non-minimized and non-maximized) window geometry. Shame on Qt
975 * that it doesn't provide this geometry in its public APIs. */
976 case QEvent::Resize:
977 {
978 QResizeEvent *pResizeEvent = (QResizeEvent*) pEvent;
979 if ((windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)) == 0)
980 m_normalGeo.setSize(pResizeEvent->size());
981 break;
982 }
983 case QEvent::Move:
984 {
985 if ((windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)) == 0)
986 m_normalGeo.moveTo(geometry().x(), geometry().y());
987 break;
988 }
989 case QEvent::WindowDeactivate:
990 {
991 /* Make sure every status bar hint is cleared when the window lost focus. */
992 statusBar()->clearMessage();
993 break;
994 }
995#ifdef Q_WS_MAC
996 case QEvent::ContextMenu:
997 {
998 /* This is the unified context menu event. Lets show the context menu. */
999 QContextMenuEvent *pContextMenuEvent = static_cast<QContextMenuEvent*>(pEvent);
1000 sltShowSelectorContextMenu(pContextMenuEvent->globalPos());
1001 /* Accept it to interrupt the chain. */
1002 pContextMenuEvent->accept();
1003 return false;
1004 break;
1005 }
1006 case QEvent::ToolBarChange:
1007 {
1008 CVirtualBox vbox = vboxGlobal().virtualBox();
1009 /* We have to invert the isVisible check one time, cause this event
1010 * is sent *before* the real toggle is done. Really intuitive Trolls. */
1011 vbox.SetExtraData(GUI_Toolbar, !::darwinIsToolbarVisible(mVMToolBar) ? "true" : "false");
1012 break;
1013 }
1014#endif /* Q_WS_MAC */
1015 default:
1016 break;
1017 }
1018 /* Call to base-class: */
1019 return QMainWindow::event(pEvent);
1020}
1021
1022void UISelectorWindow::closeEvent(QCloseEvent *pEvent)
1023{
1024 // TODO: Such things are obsolete, rework required!
1025 emit closing();
1026 QMainWindow::closeEvent(pEvent);
1027}
1028
1029#ifdef Q_WS_MAC
1030bool UISelectorWindow::eventFilter(QObject *pObject, QEvent *pEvent)
1031{
1032 /* Ignore for non-active window: */
1033 if (!isActiveWindow())
1034 return QIWithRetranslateUI2<QMainWindow>::eventFilter(pObject, pEvent);
1035
1036 /* Ignore for other objects: */
1037 if (qobject_cast<QWidget*>(pObject) &&
1038 qobject_cast<QWidget*>(pObject)->window() != this)
1039 return QIWithRetranslateUI2<QMainWindow>::eventFilter(pObject, pEvent);
1040
1041 /* Which event do we have? */
1042 switch (pEvent->type())
1043 {
1044 case QEvent::FileOpen:
1045 {
1046 sltOpenUrls(QList<QUrl>() << static_cast<QFileOpenEvent*>(pEvent)->file());
1047 pEvent->accept();
1048 return true;
1049 break;
1050 }
1051# if (QT_VERSION < 0x040402)
1052 case QEvent::KeyPress:
1053 {
1054 /* Bug in Qt below 4.4.2. The key events are send to the current
1055 * window even if a menu is shown & has the focus. See
1056 * http://trolltech.com/developer/task-tracker/index_html?method=entry&id=214681. */
1057 if (::darwinIsMenuOpen())
1058 return true;
1059 break;
1060 }
1061# endif
1062 default:
1063 break;
1064 }
1065 /* Call to base-class: */
1066 return QIWithRetranslateUI2<QMainWindow>::eventFilter(pObject, pEvent);
1067}
1068#endif /* Q_WS_MAC */
1069
1070void UISelectorWindow::prepareIcon()
1071{
1072 /* Prepare application icon: */
1073#if !(defined (Q_WS_WIN) || defined (Q_WS_MAC))
1074 /* On Win32, it's built-in to the executable.
1075 * On Mac OS X the icon referenced in info.plist is used. */
1076 setWindowIcon(QIcon(":/VirtualBox_48px.png"));
1077#endif
1078}
1079
1080void UISelectorWindow::prepareMenuBar()
1081{
1082 /* Prepare File-menu: */
1083 m_pFileMenu = gActionPool->action(UIActionIndexSelector_Menu_File)->menu();
1084 prepareMenuFile(m_pFileMenu);
1085 menuBar()->addMenu(m_pFileMenu);
1086
1087 /* Prepare 'Group' / 'Close' menu: */
1088 m_pGroupCloseMenuAction = gActionPool->action(UIActionIndexSelector_Menu_Group_Close);
1089 m_pGroupCloseMenu = m_pGroupCloseMenuAction->menu();
1090 prepareMenuGroupClose(m_pGroupCloseMenu);
1091
1092 /* Prepare 'Machine' / 'Close' menu: */
1093 m_pMachineCloseMenuAction = gActionPool->action(UIActionIndexSelector_Menu_Machine_Close);
1094 m_pMachineCloseMenu = m_pMachineCloseMenuAction->menu();
1095 prepareMenuMachineClose(m_pMachineCloseMenu);
1096
1097 /* Create actions for 'Group' and 'Machine' menus: */
1098 prepareCommonActions();
1099 prepareGroupActions();
1100 prepareMachineActions();
1101
1102 /* Prepare Group-menu: */
1103 m_pGroupMenu = gActionPool->action(UIActionIndexSelector_Menu_Group)->menu();
1104 prepareMenuGroup(m_pGroupMenu);
1105 m_pGroupMenuAction = menuBar()->addMenu(m_pGroupMenu);
1106
1107 /* Prepare Machine-menu: */
1108 m_pMachineMenu = gActionPool->action(UIActionIndexSelector_Menu_Machine)->menu();
1109 prepareMenuMachine(m_pMachineMenu);
1110 m_pMachineMenuAction = menuBar()->addMenu(m_pMachineMenu);
1111
1112#ifdef Q_WS_MAC
1113 menuBar()->addMenu(UIWindowMenuManager::instance(this)->createMenu(this));
1114#endif /* Q_WS_MAC */
1115
1116 /* Prepare Help-menu: */
1117 m_pHelpMenu = gActionPool->action(UIActionIndex_Menu_Help)->menu();
1118 prepareMenuHelp(m_pHelpMenu);
1119 menuBar()->addMenu(m_pHelpMenu);
1120
1121 /* Setup menubar policy: */
1122 menuBar()->setContextMenuPolicy(Qt::CustomContextMenu);
1123}
1124
1125void UISelectorWindow::prepareMenuFile(QMenu *pMenu)
1126{
1127 /* Do not touch if filled already: */
1128 if (!pMenu->isEmpty())
1129 return;
1130
1131 /* Populate File-menu: */
1132 m_pMediumManagerDialogAction = gActionPool->action(UIActionIndexSelector_Simple_File_MediumManagerDialog);
1133 pMenu->addAction(m_pMediumManagerDialogAction);
1134 m_pImportApplianceWizardAction = gActionPool->action(UIActionIndexSelector_Simple_File_ImportApplianceWizard);
1135 pMenu->addAction(m_pImportApplianceWizardAction);
1136 m_pExportApplianceWizardAction = gActionPool->action(UIActionIndexSelector_Simple_File_ExportApplianceWizard);
1137 pMenu->addAction(m_pExportApplianceWizardAction);
1138#ifndef Q_WS_MAC
1139 pMenu->addSeparator();
1140#endif /* Q_WS_MAC */
1141 m_pPreferencesDialogAction = gActionPool->action(UIActionIndexSelector_Simple_File_PreferencesDialog);
1142 pMenu->addAction(m_pPreferencesDialogAction);
1143#ifndef Q_WS_MAC
1144 pMenu->addSeparator();
1145#endif /* Q_WS_MAC */
1146 m_pExitAction = gActionPool->action(UIActionIndexSelector_Simple_File_Exit);
1147 pMenu->addAction(m_pExitAction);
1148}
1149
1150void UISelectorWindow::prepareCommonActions()
1151{
1152 m_pAction_Common_StartOrShow = gActionPool->action(UIActionIndexSelector_State_Common_StartOrShow);
1153 m_pAction_Common_PauseAndResume = gActionPool->action(UIActionIndexSelector_Toggle_Common_PauseAndResume);
1154 m_pAction_Common_Reset = gActionPool->action(UIActionIndexSelector_Simple_Common_Reset);
1155 m_pAction_Common_Discard = gActionPool->action(UIActionIndexSelector_Simple_Common_Discard);
1156 m_pAction_Common_Refresh = gActionPool->action(UIActionIndexSelector_Simple_Common_Refresh);
1157 m_pAction_Common_ShowInFileManager = gActionPool->action(UIActionIndexSelector_Simple_Common_ShowInFileManager);
1158 m_pAction_Common_CreateShortcut = gActionPool->action(UIActionIndexSelector_Simple_Common_CreateShortcut);
1159}
1160
1161void UISelectorWindow::prepareGroupActions()
1162{
1163 m_pAction_Group_New = gActionPool->action(UIActionIndexSelector_Simple_Group_New);
1164 m_pAction_Group_Add = gActionPool->action(UIActionIndexSelector_Simple_Group_Add);
1165 m_pAction_Group_Rename = gActionPool->action(UIActionIndexSelector_Simple_Group_Rename);
1166 m_pAction_Group_Remove = gActionPool->action(UIActionIndexSelector_Simple_Group_Remove);
1167 m_pAction_Group_Sort = gActionPool->action(UIActionIndexSelector_Simple_Group_Sort);
1168}
1169
1170void UISelectorWindow::prepareMachineActions()
1171{
1172 m_pAction_Machine_New = gActionPool->action(UIActionIndexSelector_Simple_Machine_New);
1173 m_pAction_Machine_Add = gActionPool->action(UIActionIndexSelector_Simple_Machine_Add);
1174 m_pAction_Machine_Settings = gActionPool->action(UIActionIndexSelector_Simple_Machine_Settings);
1175 m_pAction_Machine_Clone = gActionPool->action(UIActionIndexSelector_Simple_Machine_Clone);
1176 m_pAction_Machine_Remove = gActionPool->action(UIActionIndexSelector_Simple_Machine_Remove);
1177 m_pAction_Machine_AddGroup = gActionPool->action(UIActionIndexSelector_Simple_Machine_AddGroup);
1178 m_pAction_Machine_LogDialog = gActionPool->action(UIActionIndex_Simple_LogDialog);
1179 m_pAction_Machine_SortParent = gActionPool->action(UIActionIndexSelector_Simple_Machine_SortParent);
1180}
1181
1182void UISelectorWindow::prepareMenuGroup(QMenu *pMenu)
1183{
1184 /* Do not touch if filled already: */
1185 if (!pMenu->isEmpty())
1186 return;
1187
1188 /* Populate Machine-menu: */
1189 pMenu->addAction(m_pAction_Group_New);
1190 pMenu->addAction(m_pAction_Group_Add);
1191 pMenu->addSeparator();
1192 pMenu->addAction(m_pAction_Group_Rename);
1193 pMenu->addAction(m_pAction_Group_Remove);
1194 pMenu->addSeparator();
1195 pMenu->addAction(m_pAction_Common_StartOrShow);
1196 pMenu->addAction(m_pAction_Common_PauseAndResume);
1197 pMenu->addAction(m_pAction_Common_Reset);
1198 pMenu->addMenu(m_pGroupCloseMenu);
1199 pMenu->addSeparator();
1200 pMenu->addAction(m_pAction_Common_Discard);
1201 pMenu->addAction(m_pAction_Common_Refresh);
1202 pMenu->addSeparator();
1203 pMenu->addAction(m_pAction_Common_ShowInFileManager);
1204 pMenu->addAction(m_pAction_Common_CreateShortcut);
1205 pMenu->addSeparator();
1206 pMenu->addAction(m_pAction_Group_Sort);
1207
1208 /* Remember action list: */
1209 m_groupActions << m_pAction_Group_New
1210 << m_pAction_Group_Add
1211 << m_pAction_Group_Rename
1212 << m_pAction_Group_Remove
1213 << m_pAction_Group_Sort;
1214}
1215
1216void UISelectorWindow::prepareMenuMachine(QMenu *pMenu)
1217{
1218 /* Do not touch if filled already: */
1219 if (!pMenu->isEmpty())
1220 return;
1221
1222 /* Populate Machine-menu: */
1223 pMenu->addAction(m_pAction_Machine_New);
1224 pMenu->addAction(m_pAction_Machine_Add);
1225 pMenu->addAction(m_pAction_Machine_Settings);
1226 pMenu->addAction(m_pAction_Machine_Clone);
1227 pMenu->addAction(m_pAction_Machine_Remove);
1228 pMenu->addAction(m_pAction_Machine_AddGroup);
1229 pMenu->addSeparator();
1230 pMenu->addAction(m_pAction_Common_StartOrShow);
1231 pMenu->addAction(m_pAction_Common_PauseAndResume);
1232 pMenu->addAction(m_pAction_Common_Reset);
1233 pMenu->addMenu(m_pMachineCloseMenu);
1234 pMenu->addSeparator();
1235 pMenu->addAction(m_pAction_Common_Discard);
1236 pMenu->addAction(m_pAction_Machine_LogDialog);
1237 pMenu->addAction(m_pAction_Common_Refresh);
1238 pMenu->addSeparator();
1239 pMenu->addAction(m_pAction_Common_ShowInFileManager);
1240 pMenu->addAction(m_pAction_Common_CreateShortcut);
1241 pMenu->addSeparator();
1242 pMenu->addAction(m_pAction_Machine_SortParent);
1243
1244 /* Remember action list: */
1245 m_machineActions << m_pAction_Machine_New
1246 << m_pAction_Machine_Add
1247 << m_pAction_Machine_Settings
1248 << m_pAction_Machine_Clone
1249 << m_pAction_Machine_Remove
1250 << m_pAction_Machine_AddGroup
1251 << m_pAction_Machine_LogDialog
1252 << m_pAction_Machine_SortParent;
1253}
1254
1255void UISelectorWindow::prepareMenuGroupClose(QMenu *pMenu)
1256{
1257 /* Do not touch if filled already: */
1258 if (!pMenu->isEmpty())
1259 return;
1260
1261 /* Populate 'Group' / 'Close' menu: */
1262 m_pGroupSaveAction = gActionPool->action(UIActionIndexSelector_Simple_Group_Close_Save);
1263 pMenu->addAction(m_pGroupSaveAction);
1264 m_pGroupACPIShutdownAction = gActionPool->action(UIActionIndexSelector_Simple_Group_Close_ACPIShutdown);
1265 pMenu->addAction(m_pGroupACPIShutdownAction);
1266 m_pGroupPowerOffAction = gActionPool->action(UIActionIndexSelector_Simple_Group_Close_PowerOff);
1267 pMenu->addAction(m_pGroupPowerOffAction);
1268}
1269
1270void UISelectorWindow::prepareMenuMachineClose(QMenu *pMenu)
1271{
1272 /* Do not touch if filled already: */
1273 if (!pMenu->isEmpty())
1274 return;
1275
1276 /* Populate 'Machine' / 'Close' menu: */
1277 m_pMachineSaveAction = gActionPool->action(UIActionIndexSelector_Simple_Machine_Close_Save);
1278 pMenu->addAction(m_pMachineSaveAction);
1279 m_pMachineACPIShutdownAction = gActionPool->action(UIActionIndexSelector_Simple_Machine_Close_ACPIShutdown);
1280 pMenu->addAction(m_pMachineACPIShutdownAction);
1281 m_pMachinePowerOffAction = gActionPool->action(UIActionIndexSelector_Simple_Machine_Close_PowerOff);
1282 pMenu->addAction(m_pMachinePowerOffAction);
1283}
1284
1285void UISelectorWindow::prepareMenuHelp(QMenu *pMenu)
1286{
1287 /* Do not touch if filled already: */
1288 if (!pMenu->isEmpty())
1289 return;
1290
1291 /* Populate Help-menu: */
1292 m_pHelpAction = gActionPool->action(UIActionIndex_Simple_Contents);
1293 pMenu->addAction(m_pHelpAction);
1294 m_pWebAction = gActionPool->action(UIActionIndex_Simple_WebSite);
1295 pMenu->addAction(m_pWebAction);
1296 pMenu->addSeparator();
1297 m_pResetWarningsAction = gActionPool->action(UIActionIndex_Simple_ResetWarnings);
1298 pMenu->addAction(m_pResetWarningsAction);
1299 pMenu->addSeparator();
1300 m_pNetworkAccessManager = gActionPool->action(UIActionIndex_Simple_NetworkAccessManager);
1301 pMenu->addAction(m_pNetworkAccessManager);
1302#ifdef VBOX_WITH_REGISTRATION
1303 m_pRegisterAction = gActionPool->action(UIActionIndex_Simple_Register);
1304 pMenu->addAction(m_pRegisterAction);
1305#endif /* VBOX_WITH_REGISTRATION */
1306 m_pUpdateAction = gActionPool->action(UIActionIndex_Simple_CheckForUpdates);
1307 pMenu->addAction(m_pUpdateAction);
1308#ifndef Q_WS_MAC
1309 pMenu->addSeparator();
1310#endif /* !Q_WS_MAC */
1311 m_pAboutAction = gActionPool->action(UIActionIndex_Simple_About);
1312 pMenu->addAction(m_pAboutAction);
1313}
1314
1315void UISelectorWindow::prepareStatusBar()
1316{
1317 /* Setup statusbar policy: */
1318 statusBar()->setContextMenuPolicy(Qt::CustomContextMenu);
1319
1320 /* Add network-manager indicator: */
1321 QIStateIndicator *pIndicator = gNetworkManager->indicator();
1322 statusBar()->addPermanentWidget(pIndicator);
1323 pIndicator->updateAppearance();
1324}
1325
1326void UISelectorWindow::prepareWidgets()
1327{
1328 /* Prepare splitter: */
1329 m_pSplitter = new QISplitter(this);
1330#ifdef Q_WS_X11
1331 m_pSplitter->setHandleType(QISplitter::Native);
1332#endif /* Q_WS_X11 */
1333
1334 /* Prepare tool-bar: */
1335 mVMToolBar = new UIToolBar(this);
1336 mVMToolBar->setContextMenuPolicy(Qt::CustomContextMenu);
1337 mVMToolBar->setIconSize(QSize(32, 32));
1338 mVMToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
1339 mVMToolBar->addAction(m_pAction_Machine_New);
1340 mVMToolBar->addAction(m_pAction_Machine_Settings);
1341 mVMToolBar->addAction(m_pAction_Common_StartOrShow);
1342 mVMToolBar->addAction(m_pAction_Common_Discard);
1343
1344 /* Prepare graphics VM list: */
1345 m_pChooser = new UIGChooser(this);
1346 m_pChooser->setStatusBar(statusBar());
1347
1348 /* Prepare graphics details: */
1349 m_pDetails = new UIGDetails(this);
1350
1351 /* Prepare details and snapshots tabs: */
1352 m_pVMDesktop = new UIVMDesktop(mVMToolBar, m_pAction_Common_Refresh, this);
1353
1354 /* Crate container: */
1355 m_pContainer = new QStackedWidget(this);
1356 m_pContainer->addWidget(m_pDetails);
1357 m_pContainer->addWidget(m_pVMDesktop);
1358
1359 /* Layout all the widgets: */
1360#if MAC_LEOPARD_STYLE
1361 addToolBar(mVMToolBar);
1362 /* Central widget @ horizontal layout: */
1363 setCentralWidget(m_pSplitter);
1364 m_pSplitter->addWidget(m_pChooser);
1365#else /* MAC_LEOPARD_STYLE */
1366 QWidget *pCentralWidget = new QWidget(this);
1367 setCentralWidget(pCentralWidget);
1368 QVBoxLayout *pCentralLayout = new QVBoxLayout(pCentralWidget);
1369 pCentralLayout->setContentsMargins(0, 0, 0, 0);
1370 pCentralLayout->setSpacing(0);
1371 m_pBar = new UIMainBar(this);
1372 m_pBar->setContentWidget(mVMToolBar);
1373 pCentralLayout->addWidget(m_pBar);
1374 pCentralLayout->addWidget(m_pSplitter);
1375 m_pSplitter->addWidget(m_pChooser);
1376#endif /* !MAC_LEOPARD_STYLE */
1377 m_pSplitter->addWidget(m_pContainer);
1378
1379 /* Set the initial distribution. The right site is bigger. */
1380 m_pSplitter->setStretchFactor(0, 2);
1381 m_pSplitter->setStretchFactor(1, 3);
1382
1383 /* Bring the VM list to the focus: */
1384 m_pChooser->setFocus();
1385}
1386
1387void UISelectorWindow::prepareConnections()
1388{
1389 /* Medium enumeration connections: */
1390 connect(&vboxGlobal(), SIGNAL(mediumEnumFinished(const VBoxMediaList &)), this, SLOT(sltMediumEnumFinished(const VBoxMediaList &)));
1391
1392 /* Menu-bar connections: */
1393 connect(menuBar(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltShowSelectorContextMenu(const QPoint&)));
1394
1395 /* 'File' menu connections: */
1396 connect(m_pMediumManagerDialogAction, SIGNAL(triggered()), this, SLOT(sltShowMediumManager()));
1397 connect(m_pImportApplianceWizardAction, SIGNAL(triggered()), this, SLOT(sltShowImportApplianceWizard()));
1398 connect(m_pExportApplianceWizardAction, SIGNAL(triggered()), this, SLOT(sltShowExportApplianceWizard()));
1399 connect(m_pPreferencesDialogAction, SIGNAL(triggered()), this, SLOT(sltShowPreferencesDialog()));
1400 connect(m_pExitAction, SIGNAL(triggered()), this, SLOT(sltPerformExit()));
1401
1402 /* 'Group'/'Machine' menu common connections: */
1403 connect(m_pAction_Common_StartOrShow, SIGNAL(triggered()), this, SLOT(sltPerformStartOrShowAction()));
1404 connect(m_pAction_Common_PauseAndResume, SIGNAL(toggled(bool)), this, SLOT(sltPerformPauseResumeAction(bool)));
1405 connect(m_pAction_Common_Reset, SIGNAL(triggered()), this, SLOT(sltPerformResetAction()));
1406 connect(m_pAction_Common_Discard, SIGNAL(triggered()), this, SLOT(sltPerformDiscardAction()));
1407 connect(m_pAction_Common_Refresh, SIGNAL(triggered()), this, SLOT(sltPerformRefreshAction()));
1408 connect(m_pAction_Common_ShowInFileManager, SIGNAL(triggered()), this, SLOT(sltShowMachineInFileManager()));
1409 connect(m_pAction_Common_CreateShortcut, SIGNAL(triggered()), this, SLOT(sltPerformCreateShortcutAction()));
1410
1411 /* 'Group' menu connections: */
1412 connect(m_pAction_Group_Add, SIGNAL(triggered()), this, SLOT(sltShowAddMachineDialog()));
1413
1414 /* 'Machine' menu connections: */
1415 connect(m_pAction_Machine_Add, SIGNAL(triggered()), this, SLOT(sltShowAddMachineDialog()));
1416 connect(m_pAction_Machine_Settings, SIGNAL(triggered()), this, SLOT(sltShowMachineSettingsDialog()));
1417 connect(m_pAction_Machine_Clone, SIGNAL(triggered()), this, SLOT(sltShowCloneMachineWizard()));
1418 connect(m_pAction_Machine_LogDialog, SIGNAL(triggered()), this, SLOT(sltShowLogDialog()));
1419
1420 /* 'Group/Close' menu connections: */
1421 connect(m_pGroupCloseMenu, SIGNAL(aboutToShow()), this, SLOT(sltGroupCloseMenuAboutToShow()));
1422 connect(m_pGroupSaveAction, SIGNAL(triggered()), this, SLOT(sltPerformSaveAction()));
1423 connect(m_pGroupACPIShutdownAction, SIGNAL(triggered()), this, SLOT(sltPerformACPIShutdownAction()));
1424 connect(m_pGroupPowerOffAction, SIGNAL(triggered()), this, SLOT(sltPerformPowerOffAction()));
1425
1426 /* 'Machine/Close' menu connections: */
1427 connect(m_pMachineCloseMenu, SIGNAL(aboutToShow()), this, SLOT(sltMachineCloseMenuAboutToShow()));
1428 connect(m_pMachineSaveAction, SIGNAL(triggered()), this, SLOT(sltPerformSaveAction()));
1429 connect(m_pMachineACPIShutdownAction, SIGNAL(triggered()), this, SLOT(sltPerformACPIShutdownAction()));
1430 connect(m_pMachinePowerOffAction, SIGNAL(triggered()), this, SLOT(sltPerformPowerOffAction()));
1431
1432 /* 'Help' menu connections: */
1433 connect(m_pHelpAction, SIGNAL(triggered()), &msgCenter(), SLOT(sltShowHelpHelpDialog()));
1434 connect(m_pWebAction, SIGNAL(triggered()), &msgCenter(), SLOT(sltShowHelpWebDialog()));
1435 connect(m_pResetWarningsAction, SIGNAL(triggered()), &msgCenter(), SLOT(sltResetSuppressedMessages()));
1436 connect(m_pNetworkAccessManager, SIGNAL(triggered()), gNetworkManager, SLOT(show()));
1437#ifdef VBOX_WITH_REGISTRATION
1438 connect(m_pRegisterAction, SIGNAL(triggered()), &vboxGlobal(), SLOT(showRegistrationDialog()));
1439 connect(gEDataEvents, SIGNAL(sigCanShowRegistrationDlg(bool)), m_pRegisterAction, SLOT(setEnabled(bool)));
1440#endif /* VBOX_WITH_REGISTRATION */
1441 connect(m_pUpdateAction, SIGNAL(triggered()), gUpdateManager, SLOT(sltForceCheck()));
1442 connect(m_pAboutAction, SIGNAL(triggered()), &msgCenter(), SLOT(sltShowHelpAboutDialog()));
1443
1444 /* Status-bar connections: */
1445 connect(statusBar(), SIGNAL(customContextMenuRequested(const QPoint&)),
1446 this, SLOT(sltShowSelectorContextMenu(const QPoint&)));
1447
1448 /* Graphics VM chooser connections: */
1449 connect(m_pChooser, SIGNAL(sigSelectionChanged()), this, SLOT(sltCurrentVMItemChanged()), Qt::QueuedConnection);
1450 connect(m_pChooser, SIGNAL(sigSlidingStarted()), m_pDetails, SIGNAL(sigSlidingStarted()));
1451 connect(m_pChooser, SIGNAL(sigToggleStarted()), m_pDetails, SIGNAL(sigToggleStarted()));
1452 connect(m_pChooser, SIGNAL(sigToggleFinished()), m_pDetails, SIGNAL(sigToggleFinished()));
1453 connect(m_pChooser, SIGNAL(sigGroupSavingStateChanged()), this, SLOT(sltGroupSavingUpdate()));
1454
1455 /* Tool-bar connections: */
1456#ifndef Q_WS_MAC
1457 connect(mVMToolBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltShowSelectorContextMenu(const QPoint&)));
1458#else /* !Q_WS_MAC */
1459 /* A simple connect doesn't work on the Mac, also we want receive right
1460 * click notifications on the title bar. So register our own handler. */
1461 ::darwinRegisterForUnifiedToolbarContextMenuEvents(this);
1462#endif /* Q_WS_MAC */
1463
1464 /* VM desktop connections: */
1465 connect(m_pVMDesktop, SIGNAL(sigCurrentChanged(int)), this, SLOT(sltDetailsViewIndexChanged(int)));
1466 connect(m_pDetails, SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)),
1467 this, SLOT(sltShowMachineSettingsDialog(const QString&, const QString&, const QString&)));
1468
1469#ifdef VBOX_GUI_WITH_SYSTRAY
1470 /* Tray icon connections: */
1471 connect(m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1472 this, SLOT(sltTrayIconActivated(QSystemTrayIcon::ActivationReason)));
1473 connect(gEDataEvents, SIGNAL(sigMainWindowCountChange(int)), this, SLOT(sltMainWindowCountChanged(int)));
1474 connect(gEDataEvents, SIGNAL(sigCanShowTrayIcon(bool)), this, SLOT(sltTrayIconCanShow(bool)));
1475 connect(gEDataEvents, SIGNAL(sigTrayIconChange(bool)), this, SLOT(sltTrayIconChanged(bool)));
1476 connect(&vboxGlobal(), SIGNAL(sigTrayIconShow(bool)), this, SLOT(sltTrayIconShow(bool)));
1477#endif /* VBOX_GUI_WITH_SYSTRAY */
1478
1479 /* Global event handlers: */
1480 connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)), this, SLOT(sltStateChanged(QString)));
1481 connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)), this, SLOT(sltStateChanged(QString)));
1482 connect(gVBoxEvents, SIGNAL(sigSnapshotChange(QString, QString)), this, SLOT(sltSnapshotChanged(QString)));
1483}
1484
1485void UISelectorWindow::loadSettings()
1486{
1487 /* Get VBox object: */
1488 CVirtualBox vbox = vboxGlobal().virtualBox();
1489
1490 /* Restore window position: */
1491 {
1492 QString strWinPos = vbox.GetExtraData(GUI_LastSelectorWindowPosition);
1493
1494 bool ok = false, max = false;
1495 int x = 0, y = 0, w = 0, h = 0;
1496 x = strWinPos.section(',', 0, 0).toInt(&ok);
1497 if (ok)
1498 y = strWinPos.section(',', 1, 1).toInt(&ok);
1499 if (ok)
1500 w = strWinPos.section(',', 2, 2).toInt(&ok);
1501 if (ok)
1502 h = strWinPos.section(',', 3, 3).toInt(&ok);
1503 if (ok)
1504 max = strWinPos.section(',', 4, 4) == GUI_LastWindowState_Max;
1505
1506 QRect ar = ok ? QApplication::desktop()->availableGeometry(QPoint(x, y)) :
1507 QApplication::desktop()->availableGeometry(this);
1508
1509 if (ok /* previous parameters were read correctly */
1510 && (y > 0) && (y < ar.bottom()) /* check vertical bounds */
1511 && (x + w > ar.left()) && (x < ar.right()) /* & horizontal bounds */)
1512 {
1513 m_normalGeo.moveTo(x, y);
1514 m_normalGeo.setSize(QSize(w, h).expandedTo(minimumSizeHint()).boundedTo(ar.size()));
1515#if defined(Q_WS_MAC) && (QT_VERSION >= 0x040700)
1516 move(m_normalGeo.topLeft());
1517 resize(m_normalGeo.size());
1518 m_normalGeo = normalGeometry();
1519#else /* defined(Q_WS_MAC) && (QT_VERSION >= 0x040700) */
1520 setGeometry(m_normalGeo);
1521#endif /* !(defined(Q_WS_MAC) && (QT_VERSION >= 0x040700)) */
1522 if (max) /* maximize if needed */
1523 showMaximized();
1524 }
1525 else
1526 {
1527 m_normalGeo.setSize(QSize(770, 550).expandedTo(minimumSizeHint()).boundedTo(ar.size()));
1528 m_normalGeo.moveCenter(ar.center());
1529 setGeometry(m_normalGeo);
1530 }
1531 }
1532
1533 /* Restore splitter handle position: */
1534 {
1535 QList<int> sizes = vbox.GetExtraDataIntList(GUI_SplitterSizes);
1536
1537 if (sizes.size() == 2)
1538 m_pSplitter->setSizes(sizes);
1539 }
1540
1541 /* Restore toolbar and statusbar visibility: */
1542 {
1543 QString strToolbar = vbox.GetExtraData(GUI_Toolbar);
1544 QString strStatusbar = vbox.GetExtraData(GUI_Statusbar);
1545
1546#ifdef Q_WS_MAC
1547 mVMToolBar->setVisible(strToolbar.isEmpty() || strToolbar == "true");
1548#else /* Q_WS_MAC */
1549 m_pBar->setVisible(strToolbar.isEmpty() || strToolbar == "true");
1550#endif /* !Q_WS_MAC */
1551 statusBar()->setVisible(strStatusbar.isEmpty() || strStatusbar == "true");
1552 }
1553}
1554
1555void UISelectorWindow::saveSettings()
1556{
1557 /* Get VBox object: */
1558 CVirtualBox vbox = vboxGlobal().virtualBox();
1559
1560 /* Save window position: */
1561 {
1562#if defined(Q_WS_MAC) && (QT_VERSION >= 0x040700)
1563 QRect frameGeo = frameGeometry();
1564 QRect save(frameGeo.x(), frameGeo.y(), m_normalGeo.width(), m_normalGeo.height());
1565#else /* defined(Q_WS_MAC) && (QT_VERSION >= 0x040700) */
1566 QRect save(m_normalGeo);
1567#endif /* !(defined(Q_WS_MAC) && (QT_VERSION >= 0x040700)) */
1568 QString strWinPos = QString("%1,%2,%3,%4").arg(save.x()).arg(save.y()).arg(save.width()).arg(save.height());
1569#ifdef Q_WS_MAC
1570 UIWindowMenuManager::destroy();
1571 ::darwinUnregisterForUnifiedToolbarContextMenuEvents(this);
1572 if (::darwinIsWindowMaximized(this))
1573#else /* Q_WS_MAC */
1574 if (isMaximized())
1575#endif /* !Q_WS_MAC */
1576 strWinPos += QString(",%1").arg(GUI_LastWindowState_Max);
1577
1578 vbox.SetExtraData(GUI_LastSelectorWindowPosition, strWinPos);
1579 }
1580
1581 /* Save splitter handle position: */
1582 {
1583 vbox.SetExtraDataIntList(GUI_SplitterSizes, m_pSplitter->sizes());
1584 }
1585}
1586
1587UIVMItem* UISelectorWindow::currentItem() const
1588{
1589 return m_pChooser->currentItem();
1590}
1591
1592QList<UIVMItem*> UISelectorWindow::currentItems() const
1593{
1594 return m_pChooser->currentItems();
1595}
1596
1597void UISelectorWindow::updateActionsAppearance()
1598{
1599 /* Get current item(s): */
1600 UIVMItem *pItem = currentItem();
1601 QList<UIVMItem*> items = currentItems();
1602
1603 /* Enable/disable group actions: */
1604 m_pAction_Group_Rename->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Rename, items));
1605 m_pAction_Group_Remove->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Remove, items));
1606 m_pAction_Group_Sort->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Sort, items));
1607
1608 /* Enable/disable machine actions: */
1609 m_pAction_Machine_Settings->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Settings, items));
1610 m_pAction_Machine_Clone->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Clone, items));
1611 m_pAction_Machine_Remove->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Remove, items));
1612 m_pAction_Machine_AddGroup->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_AddGroup, items));
1613 m_pAction_Machine_LogDialog->setEnabled(isActionEnabled(UIActionIndex_Simple_LogDialog, items));
1614 m_pAction_Machine_SortParent->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_SortParent, items));
1615
1616 /* Enable/disable common actions: */
1617 m_pAction_Common_StartOrShow->setEnabled(isActionEnabled(UIActionIndexSelector_State_Common_StartOrShow, items));
1618 m_pAction_Common_PauseAndResume->setEnabled(isActionEnabled(UIActionIndexSelector_Toggle_Common_PauseAndResume, items));
1619 m_pAction_Common_Reset->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Common_Reset, items));
1620 m_pAction_Common_Discard->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Common_Discard, items));
1621 m_pAction_Common_Refresh->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Common_Refresh, items));
1622 m_pAction_Common_ShowInFileManager->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Common_ShowInFileManager, items));
1623 m_pAction_Common_CreateShortcut->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Common_CreateShortcut, items));
1624
1625 /* Enable/disable group-close actions: */
1626 m_pGroupCloseMenuAction->setEnabled(isActionEnabled(UIActionIndexSelector_Menu_Group_Close, items));
1627 m_pGroupSaveAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Close_Save, items));
1628 m_pGroupACPIShutdownAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Close_ACPIShutdown, items));
1629 m_pGroupPowerOffAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Group_Close_PowerOff, items));
1630
1631 /* Enable/disable machine-close actions: */
1632 m_pMachineCloseMenuAction->setEnabled(isActionEnabled(UIActionIndexSelector_Menu_Machine_Close, items));
1633 m_pMachineSaveAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_Save, items));
1634 m_pMachineACPIShutdownAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_ACPIShutdown, items));
1635 m_pMachinePowerOffAction->setEnabled(isActionEnabled(UIActionIndexSelector_Simple_Machine_Close_PowerOff, items));
1636
1637 /* Start/Show action is deremined by 1st item: */
1638 if (pItem && pItem->accessible())
1639 m_pAction_Common_StartOrShow->setState(isItemPoweredOff(pItem) ? 1 : 2);
1640 else
1641 m_pAction_Common_StartOrShow->setState(1);
1642
1643 /* Pause/Resume action is deremined by 1st started item: */
1644 UIVMItem *pFirstStartedAction = 0;
1645 foreach (UIVMItem *pSelectedItem, items)
1646 if (isItemStarted(pSelectedItem))
1647 pFirstStartedAction = pSelectedItem;
1648 /* Update the Pause/Resume action appearance: */
1649 m_pAction_Common_PauseAndResume->blockSignals(true);
1650 m_pAction_Common_PauseAndResume->setChecked(pFirstStartedAction && isItemPaused(pFirstStartedAction));
1651 m_pAction_Common_PauseAndResume->updateAppearance();
1652 m_pAction_Common_PauseAndResume->blockSignals(false);
1653
1654#ifdef QT_MAC_USE_COCOA
1655 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when
1656 the necessary size of the toolbar is increased. Also for some languages
1657 the with doesn't match if the text increase. So manually adjust the size
1658 after changing the text. */
1659 mVMToolBar->updateLayout();
1660#endif /* QT_MAC_USE_COCOA */
1661}
1662
1663bool UISelectorWindow::isActionEnabled(int iActionIndex, const QList<UIVMItem*> &items)
1664{
1665 /* No actions enabled for empty item list: */
1666 if (items.isEmpty())
1667 return false;
1668
1669 /* Get first item: */
1670 UIVMItem *pItem = items.first();
1671
1672 /* For known action types: */
1673 switch (iActionIndex)
1674 {
1675 case UIActionIndexSelector_Simple_Group_Rename:
1676 case UIActionIndexSelector_Simple_Group_Remove:
1677 {
1678 return !m_pChooser->isGroupSavingInProgress() &&
1679 isItemsPoweredOff(items);
1680 }
1681 case UIActionIndexSelector_Simple_Group_Sort:
1682 {
1683 return !m_pChooser->isGroupSavingInProgress() &&
1684 m_pChooser->singleGroupSelected();
1685 }
1686 case UIActionIndexSelector_Simple_Machine_Settings:
1687 {
1688 return !m_pChooser->isGroupSavingInProgress() &&
1689 items.size() == 1 &&
1690 pItem->accessible() &&
1691 !isItemStuck(pItem);
1692 }
1693 case UIActionIndexSelector_Simple_Machine_Clone:
1694 {
1695 return !m_pChooser->isGroupSavingInProgress() &&
1696 items.size() == 1 &&
1697 isItemEditable(pItem);
1698 }
1699 case UIActionIndexSelector_Simple_Machine_Remove:
1700 {
1701 return !m_pChooser->isGroupSavingInProgress() &&
1702 isAtLeastOneItemRemovable(items);
1703 }
1704 case UIActionIndexSelector_Simple_Machine_AddGroup:
1705 {
1706 return !m_pChooser->isGroupSavingInProgress() &&
1707 isItemsPoweredOff(items);
1708 }
1709 case UIActionIndexSelector_State_Common_StartOrShow:
1710 {
1711 return !m_pChooser->isGroupSavingInProgress() &&
1712 isAtLeastOneItemCanBeStartedOrShowed(items);
1713 }
1714 case UIActionIndexSelector_Simple_Common_Discard:
1715 {
1716 return !m_pChooser->isGroupSavingInProgress() &&
1717 isAtLeastOneItemDiscardable(items);
1718 }
1719 case UIActionIndexSelector_Toggle_Common_PauseAndResume:
1720 {
1721 return isAtLeastOneItemStarted(items);
1722 }
1723 case UIActionIndexSelector_Simple_Common_Reset:
1724 {
1725 return isAtLeastOneItemRunning(items);
1726 }
1727 case UIActionIndexSelector_Simple_Common_Refresh:
1728 {
1729 return isAtLeastOneItemInaccessible(items);
1730 }
1731 case UIActionIndex_Simple_LogDialog:
1732 {
1733 return items.size() == 1 && pItem->accessible();
1734 }
1735 case UIActionIndexSelector_Simple_Common_ShowInFileManager:
1736 {
1737 return isAtLeastOneItemAccessible(items);
1738 }
1739 case UIActionIndexSelector_Simple_Machine_SortParent:
1740 {
1741 return !m_pChooser->isGroupSavingInProgress();
1742 }
1743 case UIActionIndexSelector_Simple_Common_CreateShortcut:
1744 {
1745 return isAtLeastOneItemSupportsShortcuts(items);
1746 }
1747 case UIActionIndexSelector_Menu_Group_Close:
1748 case UIActionIndexSelector_Menu_Machine_Close:
1749 {
1750 return isAtLeastOneItemStarted(items);
1751 }
1752 case UIActionIndexSelector_Simple_Group_Close_Save:
1753 case UIActionIndexSelector_Simple_Machine_Close_Save:
1754 {
1755 return isActionEnabled(UIActionIndexSelector_Menu_Machine_Close, items);
1756 }
1757 case UIActionIndexSelector_Simple_Group_Close_ACPIShutdown:
1758 case UIActionIndexSelector_Simple_Machine_Close_ACPIShutdown:
1759 {
1760 return isActionEnabled(UIActionIndexSelector_Menu_Machine_Close, items) &&
1761 isAtLeastOneItemAbleToShutdown(items);
1762 }
1763 case UIActionIndexSelector_Simple_Group_Close_PowerOff:
1764 case UIActionIndexSelector_Simple_Machine_Close_PowerOff:
1765 {
1766 return isActionEnabled(UIActionIndexSelector_Menu_Machine_Close, items);
1767 }
1768 default:
1769 break;
1770 }
1771
1772 /* Unknown actions are disabled: */
1773 return false;
1774}
1775
1776/* static */
1777bool UISelectorWindow::isItemsPoweredOff(const QList<UIVMItem*> &items)
1778{
1779 foreach (UIVMItem *pItem, items)
1780 if (!isItemPoweredOff(pItem))
1781 return false;
1782 return true;
1783}
1784
1785/* static */
1786bool UISelectorWindow::isAtLeastOneItemAbleToShutdown(const QList<UIVMItem*> &items)
1787{
1788 foreach (UIVMItem *pItem, items)
1789 {
1790 if (!isItemRunning(pItem))
1791 continue;
1792
1793 CSession session = vboxGlobal().openExistingSession(pItem->id());
1794 if (session.isNull())
1795 {
1796 msgCenter().cannotOpenSession(session);
1797 return false;
1798 }
1799 CConsole console = session.GetConsole();
1800 if (console.isNull())
1801 {
1802 session.UnlockMachine();
1803 return false;
1804 }
1805 session.UnlockMachine();
1806
1807 return console.GetGuestEnteredACPIMode();
1808 }
1809 return false;
1810}
1811
1812/* static */
1813bool UISelectorWindow::isAtLeastOneItemSupportsShortcuts(const QList<UIVMItem*> &items)
1814{
1815 foreach (UIVMItem *pItem, items)
1816 if (pItem->accessible()
1817#ifdef Q_WS_MAC
1818 /* On Mac OS X this are real alias files, which don't work with the old
1819 * legacy xml files. On the other OS's some kind of start up script is used. */
1820 && !pItem->settingsFile().endsWith(".vbox", Qt::CaseInsensitive)
1821#endif /* Q_WS_MAC */
1822 )
1823 return true;
1824 return false;
1825}
1826
1827/* static */
1828bool UISelectorWindow::isAtLeastOneItemAccessible(const QList<UIVMItem*> &items)
1829{
1830 foreach (UIVMItem *pItem, items)
1831 if (pItem->accessible())
1832 return true;
1833 return false;
1834}
1835
1836/* static */
1837bool UISelectorWindow::isAtLeastOneItemInaccessible(const QList<UIVMItem*> &items)
1838{
1839 foreach (UIVMItem *pItem, items)
1840 if (!pItem->accessible())
1841 return true;
1842 return false;
1843}
1844
1845/* static */
1846bool UISelectorWindow::isAtLeastOneItemRemovable(const QList<UIVMItem*> &items)
1847{
1848 foreach (UIVMItem *pItem, items)
1849 if (!pItem->accessible() || isItemEditable(pItem))
1850 return true;
1851 return false;
1852}
1853
1854/* static */
1855bool UISelectorWindow::isAtLeastOneItemCanBeStartedOrShowed(const QList<UIVMItem*> &items)
1856{
1857 foreach (UIVMItem *pItem, items)
1858 {
1859 if ((isItemPoweredOff(pItem) && isItemEditable(pItem)) ||
1860 (isItemStarted(pItem) && pItem->canSwitchTo()))
1861 return true;
1862 }
1863 return false;
1864}
1865
1866/* static */
1867bool UISelectorWindow::isAtLeastOneItemDiscardable(const QList<UIVMItem*> &items)
1868{
1869 foreach (UIVMItem *pItem, items)
1870 if (isItemSaved(pItem) && isItemEditable(pItem))
1871 return true;
1872 return false;
1873}
1874
1875/* static */
1876bool UISelectorWindow::isAtLeastOneItemStarted(const QList<UIVMItem*> &items)
1877{
1878 foreach (UIVMItem *pItem, items)
1879 if (isItemStarted(pItem))
1880 return true;
1881 return false;
1882}
1883
1884/* static */
1885bool UISelectorWindow::isAtLeastOneItemRunning(const QList<UIVMItem*> &items)
1886{
1887 foreach (UIVMItem *pItem, items)
1888 if (isItemRunning(pItem))
1889 return true;
1890 return false;
1891}
1892
1893/* static */
1894bool UISelectorWindow::isItemEditable(UIVMItem *pItem)
1895{
1896 return pItem->accessible() &&
1897 pItem->sessionState() == KSessionState_Unlocked;
1898}
1899
1900/* static */
1901bool UISelectorWindow::isItemSaved(UIVMItem *pItem)
1902{
1903 if (pItem->accessible() &&
1904 pItem->machineState() == KMachineState_Saved)
1905 return true;
1906 return false;
1907}
1908
1909/* static */
1910bool UISelectorWindow::isItemPoweredOff(UIVMItem *pItem)
1911{
1912 if (pItem->accessible() &&
1913 (pItem->machineState() == KMachineState_PoweredOff ||
1914 pItem->machineState() == KMachineState_Saved ||
1915 pItem->machineState() == KMachineState_Teleported ||
1916 pItem->machineState() == KMachineState_Aborted))
1917 return true;
1918 return false;
1919}
1920
1921/* static */
1922bool UISelectorWindow::isItemStarted(UIVMItem *pItem)
1923{
1924 return isItemRunning(pItem) || isItemPaused(pItem);
1925}
1926
1927/* static */
1928bool UISelectorWindow::isItemRunning(UIVMItem *pItem)
1929{
1930 if (pItem->accessible() &&
1931 (pItem->machineState() == KMachineState_Running ||
1932 pItem->machineState() == KMachineState_Teleporting ||
1933 pItem->machineState() == KMachineState_LiveSnapshotting))
1934 return true;
1935 return false;
1936}
1937
1938/* static */
1939bool UISelectorWindow::isItemPaused(UIVMItem *pItem)
1940{
1941 if (pItem->accessible() &&
1942 (pItem->machineState() == KMachineState_Paused ||
1943 pItem->machineState() == KMachineState_TeleportingPausedVM))
1944 return true;
1945 return false;
1946
1947}
1948
1949/* static */
1950bool UISelectorWindow::isItemStuck(UIVMItem *pItem)
1951{
1952 if (pItem->accessible() &&
1953 pItem->machineState() == KMachineState_Stuck)
1954 return true;
1955 return false;
1956}
1957
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use