VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManager.cpp@ 82781

Last change on this file since 82781 was 81261, checked in by vboxsync, 5 years ago

FE/Qt: Reapplying r133952 with build-fixes for macOS (s.a. r133953).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 83.5 KB
Line 
1/* $Id: UIVirtualBoxManager.cpp 81261 2019-10-14 14:38:47Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIVirtualBoxManager class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QMenuBar>
20#include <QStandardPaths>
21#include <QStatusBar>
22//# include <QToolButton>
23
24/* GUI includes: */
25#include "QIFileDialog.h"
26#include "UIActionPoolManager.h"
27#include "UICloudProfileManager.h"
28#include "UIDesktopServices.h"
29#include "UIExtraDataManager.h"
30#include "UIHostNetworkManager.h"
31#include "UIMedium.h"
32#include "UIMediumManager.h"
33#include "UIMessageCenter.h"
34#include "UIModalWindowManager.h"
35#include "UIVirtualBoxManager.h"
36#include "UIVirtualBoxManagerWidget.h"
37#include "UISettingsDialogSpecific.h"
38#include "UIVMLogViewerDialog.h"
39#include "UIVirtualMachineItem.h"
40#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
41# include "UIUpdateManager.h"
42#endif
43#include "UIVirtualBoxEventHandler.h"
44#include "UIWizardCloneVM.h"
45#include "UIWizardExportApp.h"
46#include "UIWizardImportApp.h"
47#include "UIWizardNewCloudVM.h"
48#ifdef VBOX_WS_MAC
49# include "UIImageTools.h"
50# include "UIWindowMenuManager.h"
51# include "VBoxUtils.h"
52#endif
53#ifdef VBOX_WS_X11
54# include "UIDesktopWidgetWatchdog.h"
55#endif
56#ifndef VBOX_WS_MAC
57# include "UIMenuBar.h"
58#endif
59
60/* COM includes: */
61#include "CSystemProperties.h"
62
63/* Other VBox stuff: */
64#include <iprt/buildconfig.h>
65#include <VBox/version.h>
66#ifdef VBOX_WS_X11
67# include <iprt/env.h>
68#endif /* VBOX_WS_X11 */
69
70
71/* static */
72UIVirtualBoxManager *UIVirtualBoxManager::s_pInstance = 0;
73
74/* static */
75void UIVirtualBoxManager::create()
76{
77 /* Make sure VirtualBox Manager isn't created: */
78 AssertReturnVoid(s_pInstance == 0);
79
80 /* Create VirtualBox Manager: */
81 new UIVirtualBoxManager;
82 /* Prepare VirtualBox Manager: */
83 s_pInstance->prepare();
84 /* Show VirtualBox Manager: */
85 s_pInstance->show();
86 /* Register in the modal window manager: */
87 windowManager().setMainWindowShown(s_pInstance);
88}
89
90/* static */
91void UIVirtualBoxManager::destroy()
92{
93 /* Make sure VirtualBox Manager is created: */
94 AssertPtrReturnVoid(s_pInstance);
95
96 /* Unregister in the modal window manager: */
97 windowManager().setMainWindowShown(0);
98 /* Cleanup VirtualBox Manager: */
99 s_pInstance->cleanup();
100 /* Destroy machine UI: */
101 delete s_pInstance;
102}
103
104UIVirtualBoxManager::UIVirtualBoxManager()
105 : m_fPolished(false)
106 , m_fFirstMediumEnumerationHandled(false)
107 , m_pActionPool(0)
108 , m_pManagerVirtualMedia(0)
109 , m_pManagerHostNetwork(0)
110 , m_pManagerCloudProfile(0)
111{
112 s_pInstance = this;
113}
114
115UIVirtualBoxManager::~UIVirtualBoxManager()
116{
117 s_pInstance = 0;
118}
119
120bool UIVirtualBoxManager::shouldBeMaximized() const
121{
122 return gEDataManager->selectorWindowShouldBeMaximized();
123}
124
125#ifdef VBOX_WS_MAC
126bool UIVirtualBoxManager::eventFilter(QObject *pObject, QEvent *pEvent)
127{
128 /* Ignore for non-active window except for FileOpen event which should be always processed: */
129 if (!isActiveWindow() && pEvent->type() != QEvent::FileOpen)
130 return QMainWindowWithRestorableGeometryAndRetranslateUi::eventFilter(pObject, pEvent);
131
132 /* Ignore for other objects: */
133 if (qobject_cast<QWidget*>(pObject) &&
134 qobject_cast<QWidget*>(pObject)->window() != this)
135 return QMainWindowWithRestorableGeometryAndRetranslateUi::eventFilter(pObject, pEvent);
136
137 /* Which event do we have? */
138 switch (pEvent->type())
139 {
140 case QEvent::FileOpen:
141 {
142 sltHandleOpenUrlCall(QList<QUrl>() << static_cast<QFileOpenEvent*>(pEvent)->url());
143 pEvent->accept();
144 return true;
145 break;
146 }
147 default:
148 break;
149 }
150
151 /* Call to base-class: */
152 return QMainWindowWithRestorableGeometryAndRetranslateUi::eventFilter(pObject, pEvent);
153}
154#endif /* VBOX_WS_MAC */
155
156void UIVirtualBoxManager::retranslateUi()
157{
158 /* Set window title: */
159 QString strTitle(VBOX_PRODUCT);
160 strTitle += " " + tr("Manager", "Note: main window title which is prepended by the product name.");
161#ifdef VBOX_BLEEDING_EDGE
162 strTitle += QString(" EXPERIMENTAL build ")
163 + QString(RTBldCfgVersion())
164 + QString(" r")
165 + QString(RTBldCfgRevisionStr())
166 + QString(" - " VBOX_BLEEDING_EDGE);
167#endif /* VBOX_BLEEDING_EDGE */
168 setWindowTitle(strTitle);
169}
170
171bool UIVirtualBoxManager::event(QEvent *pEvent)
172{
173 /* Which event do we have? */
174 switch (pEvent->type())
175 {
176 /* Handle every ScreenChangeInternal event to notify listeners: */
177 case QEvent::ScreenChangeInternal:
178 {
179 emit sigWindowRemapped();
180 break;
181 }
182 default:
183 break;
184 }
185 /* Call to base-class: */
186 return QMainWindowWithRestorableGeometryAndRetranslateUi::event(pEvent);
187}
188
189void UIVirtualBoxManager::showEvent(QShowEvent *pEvent)
190{
191 /* Call to base-class: */
192 QMainWindowWithRestorableGeometryAndRetranslateUi::showEvent(pEvent);
193
194 /* Is polishing required? */
195 if (!m_fPolished)
196 {
197 /* Pass the show-event to polish-event: */
198 polishEvent(pEvent);
199 /* Mark as polished: */
200 m_fPolished = true;
201 }
202}
203
204void UIVirtualBoxManager::polishEvent(QShowEvent *)
205{
206 /* Make sure user warned about inaccessible media: */
207 QMetaObject::invokeMethod(this, "sltHandleMediumEnumerationFinish", Qt::QueuedConnection);
208}
209
210void UIVirtualBoxManager::closeEvent(QCloseEvent *pEvent)
211{
212 /* Call to base-class: */
213 QMainWindowWithRestorableGeometryAndRetranslateUi::closeEvent(pEvent);
214
215 /* Quit application: */
216 QApplication::quit();
217}
218
219#ifdef VBOX_WS_X11
220void UIVirtualBoxManager::sltHandleHostScreenAvailableAreaChange()
221{
222 /* Prevent handling if fake screen detected: */
223 if (gpDesktop->isFakeScreenDetected())
224 return;
225
226 /* Restore the geometry cached by the window: */
227 const QRect geo = currentGeometry();
228 resize(geo.size());
229 move(geo.topLeft());
230}
231#endif /* VBOX_WS_X11 */
232
233void UIVirtualBoxManager::sltHandleMediumEnumerationFinish()
234{
235#if 0 // ohh, come on!
236 /* To avoid annoying the user, we check for inaccessible media just once, after
237 * the first media emumeration [started from main() at startup] is complete. */
238 if (m_fFirstMediumEnumerationHandled)
239 return;
240 m_fFirstMediumEnumerationHandled = true;
241
242 /* Make sure MM window/tool is not opened,
243 * otherwise user sees everything himself: */
244 if ( m_pManagerVirtualMedia
245 || m_pWidget->isGlobalToolOpened(UIToolType_Media))
246 return;
247
248 /* Look for at least one inaccessible medium: */
249 bool fIsThereAnyInaccessibleMedium = false;
250 foreach (const QUuid &uMediumID, uiCommon().mediumIDs())
251 {
252 if (uiCommon().medium(uMediumID).state() == KMediumState_Inaccessible)
253 {
254 fIsThereAnyInaccessibleMedium = true;
255 break;
256 }
257 }
258 /* Warn the user about inaccessible medium, propose to open MM window/tool: */
259 if (fIsThereAnyInaccessibleMedium && msgCenter().warnAboutInaccessibleMedia())
260 {
261 /* Open the MM window: */
262 sltOpenVirtualMediumManagerWindow();
263 }
264#endif
265}
266
267void UIVirtualBoxManager::sltHandleOpenUrlCall(QList<QUrl> list /* = QList<QUrl>() */)
268{
269 /* If passed list is empty, we take the one from UICommon: */
270 if (list.isEmpty())
271 list = uiCommon().takeArgumentUrls();
272
273 /* Check if we are can handle the dropped urls: */
274 for (int i = 0; i < list.size(); ++i)
275 {
276#ifdef VBOX_WS_MAC
277 const QString strFile = ::darwinResolveAlias(list.at(i).toLocalFile());
278#else
279 const QString strFile = list.at(i).toLocalFile();
280#endif
281 /* If there is such file exists: */
282 if (!strFile.isEmpty() && QFile::exists(strFile))
283 {
284 /* And has allowed VBox config file extension: */
285 if (UICommon::hasAllowedExtension(strFile, VBoxFileExts))
286 {
287 /* Handle VBox config file: */
288 CVirtualBox comVBox = uiCommon().virtualBox();
289 CMachine comMachine = comVBox.FindMachine(strFile);
290 if (comVBox.isOk() && comMachine.isNotNull())
291 uiCommon().launchMachine(comMachine);
292 else
293 sltOpenAddMachineDialog(strFile);
294 }
295 /* And has allowed VBox OVF file extension: */
296 else if (UICommon::hasAllowedExtension(strFile, OVFFileExts))
297 {
298 /* Allow only one file at the time: */
299 sltOpenImportApplianceWizard(strFile);
300 break;
301 }
302 /* And has allowed VBox extension pack file extension: */
303 else if (UICommon::hasAllowedExtension(strFile, VBoxExtPackFileExts))
304 {
305#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
306 /* Prevent update manager from proposing us to update EP: */
307 gUpdateManager->setEPInstallationRequested(true);
308#endif
309 /* Propose the user to install EP described by the arguments @a list. */
310 uiCommon().doExtPackInstallation(strFile, QString(), this, NULL);
311#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
312 /* Allow update manager to propose us to update EP: */
313 gUpdateManager->setEPInstallationRequested(false);
314#endif
315 }
316 }
317 }
318}
319
320void UIVirtualBoxManager::sltHandleChooserPaneIndexChange()
321{
322 updateActionsVisibility();
323 updateActionsAppearance();
324}
325
326void UIVirtualBoxManager::sltHandleGroupSavingProgressChange()
327{
328 updateActionsAppearance();
329}
330
331void UIVirtualBoxManager::sltHandleToolTypeChange()
332{
333 updateActionsVisibility();
334 updateActionsAppearance();
335
336 /* Make sure separate dialogs are closed when corresponding tools are opened: */
337 switch (m_pWidget->toolsType())
338 {
339 case UIToolType_Media: sltCloseVirtualMediumManagerWindow(); break;
340 case UIToolType_Network: sltCloseHostNetworkManagerWindow(); break;
341 case UIToolType_Cloud: sltCloseCloudProfileManagerWindow(); break;
342 case UIToolType_Logs: sltCloseLogViewerWindow(); break;
343 default: break;
344 }
345}
346
347void UIVirtualBoxManager::sltCurrentSnapshotItemChange()
348{
349 updateActionsAppearance();
350}
351
352void UIVirtualBoxManager::sltHandleStateChange(const QUuid &)
353{
354 updateActionsAppearance();
355}
356
357void UIVirtualBoxManager::sltOpenVirtualMediumManagerWindow()
358{
359 /* First check if instance of widget opened the embedded way: */
360 if (m_pWidget->isGlobalToolOpened(UIToolType_Media))
361 {
362 m_pWidget->setToolsType(UIToolType_Welcome);
363 m_pWidget->closeGlobalTool(UIToolType_Media);
364 }
365
366 /* Create instance if not yet created: */
367 if (!m_pManagerVirtualMedia)
368 {
369 UIMediumManagerFactory(m_pActionPool).prepare(m_pManagerVirtualMedia, this);
370 connect(m_pManagerVirtualMedia, &QIManagerDialog::sigClose,
371 this, &UIVirtualBoxManager::sltCloseVirtualMediumManagerWindow);
372 }
373
374 /* Show instance: */
375 m_pManagerVirtualMedia->show();
376 m_pManagerVirtualMedia->setWindowState(m_pManagerVirtualMedia->windowState() & ~Qt::WindowMinimized);
377 m_pManagerVirtualMedia->activateWindow();
378}
379
380void UIVirtualBoxManager::sltCloseVirtualMediumManagerWindow()
381{
382 /* Destroy instance if still exists: */
383 if (m_pManagerVirtualMedia)
384 UIMediumManagerFactory().cleanup(m_pManagerVirtualMedia);
385}
386
387void UIVirtualBoxManager::sltOpenHostNetworkManagerWindow()
388{
389 /* First check if instance of widget opened the embedded way: */
390 if (m_pWidget->isGlobalToolOpened(UIToolType_Network))
391 {
392 m_pWidget->setToolsType(UIToolType_Welcome);
393 m_pWidget->closeGlobalTool(UIToolType_Network);
394 }
395
396 /* Create instance if not yet created: */
397 if (!m_pManagerHostNetwork)
398 {
399 UIHostNetworkManagerFactory(m_pActionPool).prepare(m_pManagerHostNetwork, this);
400 connect(m_pManagerHostNetwork, &QIManagerDialog::sigClose,
401 this, &UIVirtualBoxManager::sltCloseHostNetworkManagerWindow);
402 }
403
404 /* Show instance: */
405 m_pManagerHostNetwork->show();
406 m_pManagerHostNetwork->setWindowState(m_pManagerHostNetwork->windowState() & ~Qt::WindowMinimized);
407 m_pManagerHostNetwork->activateWindow();
408}
409
410void UIVirtualBoxManager::sltCloseHostNetworkManagerWindow()
411{
412 /* Destroy instance if still exists: */
413 if (m_pManagerHostNetwork)
414 UIHostNetworkManagerFactory().cleanup(m_pManagerHostNetwork);
415}
416
417void UIVirtualBoxManager::sltOpenCloudProfileManagerWindow()
418{
419 /* First check if instance of widget opened the embedded way: */
420 if (m_pWidget->isGlobalToolOpened(UIToolType_Cloud))
421 {
422 m_pWidget->setToolsType(UIToolType_Welcome);
423 m_pWidget->closeGlobalTool(UIToolType_Cloud);
424 }
425
426 /* Create instance if not yet created: */
427 if (!m_pManagerCloudProfile)
428 {
429 UICloudProfileManagerFactory(m_pActionPool).prepare(m_pManagerCloudProfile, this);
430 connect(m_pManagerCloudProfile, &QIManagerDialog::sigClose,
431 this, &UIVirtualBoxManager::sltCloseCloudProfileManagerWindow);
432 connect(m_pManagerCloudProfile, &QIManagerDialog::sigChange,
433 this, &UIVirtualBoxManager::sigCloudProfileManagerChange);
434 }
435
436 /* Show instance: */
437 m_pManagerCloudProfile->show();
438 m_pManagerCloudProfile->setWindowState(m_pManagerCloudProfile->windowState() & ~Qt::WindowMinimized);
439 m_pManagerCloudProfile->activateWindow();
440}
441
442void UIVirtualBoxManager::sltCloseCloudProfileManagerWindow()
443{
444 /* Destroy instance if still exists: */
445 if (m_pManagerCloudProfile)
446 UIHostNetworkManagerFactory().cleanup(m_pManagerCloudProfile);
447}
448
449void UIVirtualBoxManager::sltOpenImportApplianceWizard(const QString &strFileName /* = QString() */)
450{
451 /* Initialize variables: */
452#ifdef VBOX_WS_MAC
453 const QString strTmpFile = ::darwinResolveAlias(strFileName);
454#else
455 const QString strTmpFile = strFileName;
456#endif
457
458 /* Lock the action preventing cascade calls: */
459 actionPool()->action(UIActionIndexST_M_File_S_ImportAppliance)->setProperty("opened", true);
460 updateActionsAppearance();
461
462 /* Use the "safe way" to open stack of Mac OS X Sheets: */
463 QWidget *pWizardParent = windowManager().realParentWindow(this);
464 UISafePointerWizardImportApp pWizard = new UIWizardImportApp(pWizardParent, false /* OCI by default? */, strTmpFile);
465 windowManager().registerNewParent(pWizard, pWizardParent);
466 pWizard->prepare();
467 if (strFileName.isEmpty() || pWizard->isValid())
468 pWizard->exec();
469 delete pWizard;
470
471 /* Unlock the action allowing further calls: */
472 if (actionPool())
473 {
474 actionPool()->action(UIActionIndexST_M_File_S_ImportAppliance)->setProperty("opened", QVariant());
475 updateActionsAppearance();
476 }
477}
478
479void UIVirtualBoxManager::sltOpenExportApplianceWizard()
480{
481 /* Get selected items: */
482 QList<UIVirtualMachineItem*> items = currentItems();
483
484 /* Populate the list of VM names: */
485 QStringList names;
486 for (int i = 0; i < items.size(); ++i)
487 names << items.at(i)->name();
488
489 /* Lock the action preventing cascade calls: */
490 actionPool()->action(UIActionIndexST_M_File_S_ExportAppliance)->setProperty("opened", true);
491 actionPool()->action(UIActionIndexST_M_Machine_S_ExportToOCI)->setProperty("opened", true);
492 updateActionsAppearance();
493
494 /* Check what was the action invoked us: */
495 UIAction *pAction = qobject_cast<UIAction*>(sender());
496
497 /* Use the "safe way" to open stack of Mac OS X Sheets: */
498 QWidget *pWizardParent = windowManager().realParentWindow(this);
499 UISafePointerWizard pWizard = new UIWizardExportApp(pWizardParent, names,
500 pAction &&
501 pAction == actionPool()->action(UIActionIndexST_M_Machine_S_ExportToOCI));
502 windowManager().registerNewParent(pWizard, pWizardParent);
503 pWizard->prepare();
504 pWizard->exec();
505 delete pWizard;
506
507 /* Unlock the action allowing further calls: */
508 if (actionPool())
509 {
510 actionPool()->action(UIActionIndexST_M_File_S_ExportAppliance)->setProperty("opened", QVariant());
511 actionPool()->action(UIActionIndexST_M_Machine_S_ExportToOCI)->setProperty("opened", QVariant());
512 updateActionsAppearance();
513 }
514}
515
516void UIVirtualBoxManager::sltOpenNewCloudVMWizard()
517{
518 /* Lock the action preventing cascade calls: */
519 actionPool()->action(UIActionIndexST_M_File_S_NewCloudVM)->setProperty("opened", true);
520 updateActionsAppearance();
521
522 /* Use the "safe way" to open stack of Mac OS X Sheets: */
523 QWidget *pWizardParent = windowManager().realParentWindow(this);
524 UISafePointerWizardNewCloudVM pWizard = new UIWizardNewCloudVM(pWizardParent);
525 windowManager().registerNewParent(pWizard, pWizardParent);
526 pWizard->prepare();
527 pWizard->exec();
528 delete pWizard;
529
530 /* Unlock the action allowing further calls: */
531 if (actionPool())
532 {
533 actionPool()->action(UIActionIndexST_M_File_S_NewCloudVM)->setProperty("opened", QVariant());
534 updateActionsAppearance();
535 }
536}
537
538#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
539void UIVirtualBoxManager::sltOpenExtraDataManagerWindow()
540{
541 gEDataManager->openWindow(this);
542}
543#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
544
545void UIVirtualBoxManager::sltOpenPreferencesDialog()
546{
547 /* Don't show the inaccessible warning
548 * if the user tries to open global settings: */
549 m_fFirstMediumEnumerationHandled = true;
550
551 /* Lock the action preventing cascade calls: */
552 actionPool()->action(UIActionIndex_M_Application_S_Preferences)->setProperty("opened", true);
553 updateActionsAppearance();
554
555 /* Create and execute global settings window: */
556 QPointer<UISettingsDialogGlobal> pDlg = new UISettingsDialogGlobal(this);
557 pDlg->execute();
558 delete pDlg;
559
560 /* Unlock the action allowing further calls: */
561 if (actionPool())
562 {
563 actionPool()->action(UIActionIndex_M_Application_S_Preferences)->setProperty("opened", QVariant());
564 updateActionsAppearance();
565 }
566}
567
568void UIVirtualBoxManager::sltPerformExit()
569{
570 close();
571}
572
573void UIVirtualBoxManager::sltOpenAddMachineDialog(const QString &strFileName /* = QString() */)
574{
575 /* Initialize variables: */
576#ifdef VBOX_WS_MAC
577 QString strTmpFile = ::darwinResolveAlias(strFileName);
578#else
579 QString strTmpFile = strFileName;
580#endif
581 CVirtualBox comVBox = uiCommon().virtualBox();
582
583 /* Lock the action preventing cascade calls: */
584 actionPool()->action(UIActionIndexST_M_Welcome_S_Add)->setProperty("opened", true);
585 updateActionsAppearance();
586
587 /* No file specified: */
588 if (strTmpFile.isEmpty())
589 {
590 QString strBaseFolder = comVBox.GetSystemProperties().GetDefaultMachineFolder();
591 QString strTitle = tr("Select a virtual machine file");
592 QStringList extensions;
593 for (int i = 0; i < VBoxFileExts.size(); ++i)
594 extensions << QString("*.%1").arg(VBoxFileExts[i]);
595 QString strFilter = tr("Virtual machine files (%1)").arg(extensions.join(" "));
596 /* Create open file dialog: */
597 QStringList fileNames = QIFileDialog::getOpenFileNames(strBaseFolder, strFilter, this, strTitle, 0, true, true);
598 if (!fileNames.isEmpty())
599 strTmpFile = fileNames.at(0);
600 }
601
602 /* Unlock the action allowing further calls: */
603 if (actionPool())
604 {
605 actionPool()->action(UIActionIndexST_M_Welcome_S_Add)->setProperty("opened", QVariant());
606 updateActionsAppearance();
607 }
608
609 /* Nothing was chosen? */
610 if (strTmpFile.isEmpty())
611 return;
612
613 /* Make sure this machine can be opened: */
614 CMachine comMachineNew = comVBox.OpenMachine(strTmpFile);
615 if (!comVBox.isOk())
616 {
617 msgCenter().cannotOpenMachine(comVBox, strTmpFile);
618 return;
619 }
620
621 /* Make sure this machine was NOT registered already: */
622 CMachine comMachineOld = comVBox.FindMachine(comMachineNew.GetId().toString());
623 if (!comMachineOld.isNull())
624 {
625 msgCenter().cannotReregisterExistingMachine(strTmpFile, comMachineOld.GetName());
626 return;
627 }
628
629 /* Register that machine: */
630 comVBox.RegisterMachine(comMachineNew);
631}
632
633void UIVirtualBoxManager::sltOpenMachineSettingsDialog(QString strCategory /* = QString() */,
634 QString strControl /* = QString() */,
635 const QUuid &uID /* = QString() */)
636{
637 /* Get current item: */
638 UIVirtualMachineItem *pItem = currentItem();
639 AssertMsgReturnVoid(pItem, ("Current item should be selected!\n"));
640
641 /* Lock the action preventing cascade calls: */
642 actionPool()->action(UIActionIndexST_M_Machine_S_Settings)->setProperty("opened", true);
643 updateActionsAppearance();
644
645 /* Process href from VM details / description: */
646 if (!strCategory.isEmpty() && strCategory[0] != '#')
647 {
648 uiCommon().openURL(strCategory);
649 }
650 else
651 {
652 /* Check if control is coded into the URL by %%: */
653 if (strControl.isEmpty())
654 {
655 QStringList parts = strCategory.split("%%");
656 if (parts.size() == 2)
657 {
658 strCategory = parts.at(0);
659 strControl = parts.at(1);
660 }
661 }
662
663 /* Don't show the inaccessible warning
664 * if the user tries to open VM settings: */
665 m_fFirstMediumEnumerationHandled = true;
666
667 /* Create and execute corresponding VM settings window: */
668 QPointer<UISettingsDialogMachine> pDlg = new UISettingsDialogMachine(this,
669 uID.isNull() ? pItem->id() : uID,
670 strCategory, strControl);
671 pDlg->execute();
672 delete pDlg;
673 }
674
675 /* Unlock the action allowing further calls: */
676 if (actionPool())
677 {
678 actionPool()->action(UIActionIndexST_M_Machine_S_Settings)->setProperty("opened", QVariant());
679 updateActionsAppearance();
680 }
681}
682
683void UIVirtualBoxManager::sltOpenCloneMachineWizard()
684{
685 /* Get current item: */
686 UIVirtualMachineItem *pItem = currentItem();
687 AssertMsgReturnVoid(pItem, ("Current item should be selected!\n"));
688
689 /* Use the "safe way" to open stack of Mac OS X Sheets: */
690 QWidget *pWizardParent = windowManager().realParentWindow(this);
691 const QStringList &machineGroupNames = pItem->groups();
692 const QString strGroup = !machineGroupNames.isEmpty() ? machineGroupNames.at(0) : QString();
693 UISafePointerWizard pWizard = new UIWizardCloneVM(pWizardParent, pItem->machine(), strGroup);
694 windowManager().registerNewParent(pWizard, pWizardParent);
695 pWizard->prepare();
696 pWizard->exec();
697 delete pWizard;
698}
699
700void UIVirtualBoxManager::sltPerformMachineMove()
701{
702 /* Get current item: */
703 UIVirtualMachineItem *pItem = currentItem();
704 AssertMsgReturnVoid(pItem, ("Current item should be selected!\n"));
705
706 /* Open a session thru which we will modify the machine: */
707 CSession comSession = uiCommon().openSession(pItem->id(), KLockType_Write);
708 if (comSession.isNull())
709 return;
710
711 /* Get session machine: */
712 CMachine comMachine = comSession.GetMachine();
713 AssertMsgReturnVoid(comSession.isOk() && comMachine.isNotNull(), ("Unable to acquire machine!\n"));
714
715 /* Open a file dialog for the user to select a destination folder. Start with the default machine folder: */
716 CVirtualBox comVBox = uiCommon().virtualBox();
717 QString strBaseFolder = comVBox.GetSystemProperties().GetDefaultMachineFolder();
718 QString strTitle = tr("Select a destination folder to move the selected virtual machine");
719 QString strDestinationFolder = QIFileDialog::getExistingDirectory(strBaseFolder, this, strTitle);
720 if (!strDestinationFolder.isEmpty())
721 {
722 /* Prepare machine move progress: */
723 CProgress comProgress = comMachine.MoveTo(strDestinationFolder, "basic");
724 if (comMachine.isOk() && comProgress.isNotNull())
725 {
726 /* Show machine move progress: */
727 msgCenter().showModalProgressDialog(comProgress, comMachine.GetName(), ":/progress_clone_90px.png");
728 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
729 msgCenter().cannotMoveMachine(comProgress, comMachine.GetName());
730 }
731 else
732 msgCenter().cannotMoveMachine(comMachine);
733 }
734 comSession.UnlockMachine();
735}
736
737void UIVirtualBoxManager::sltPerformStartOrShowMachine()
738{
739 /* Start selected VMs in corresponding mode: */
740 QList<UIVirtualMachineItem*> items = currentItems();
741 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
742 performStartOrShowVirtualMachines(items, UICommon::LaunchMode_Invalid);
743}
744
745void UIVirtualBoxManager::sltPerformStartMachineNormal()
746{
747 /* Start selected VMs in corresponding mode: */
748 QList<UIVirtualMachineItem*> items = currentItems();
749 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
750 performStartOrShowVirtualMachines(items, UICommon::LaunchMode_Default);
751}
752
753void UIVirtualBoxManager::sltPerformStartMachineHeadless()
754{
755 /* Start selected VMs in corresponding mode: */
756 QList<UIVirtualMachineItem*> items = currentItems();
757 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
758 performStartOrShowVirtualMachines(items, UICommon::LaunchMode_Headless);
759}
760
761void UIVirtualBoxManager::sltPerformStartMachineDetachable()
762{
763 /* Start selected VMs in corresponding mode: */
764 QList<UIVirtualMachineItem*> items = currentItems();
765 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
766 performStartOrShowVirtualMachines(items, UICommon::LaunchMode_Separate);
767}
768
769void UIVirtualBoxManager::sltPerformDiscardMachineState()
770{
771 /* Get selected items: */
772 QList<UIVirtualMachineItem*> items = currentItems();
773 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
774
775 /* Prepare the list of the machines to be discarded: */
776 QStringList machineNames;
777 QList<UIVirtualMachineItem*> itemsToDiscard;
778 foreach (UIVirtualMachineItem *pItem, items)
779 {
780 if (isActionEnabled(UIActionIndexST_M_Group_S_Discard, QList<UIVirtualMachineItem*>() << pItem))
781 {
782 machineNames << pItem->name();
783 itemsToDiscard << pItem;
784 }
785 }
786 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
787
788 /* Confirm discarding saved VM state: */
789 if (!msgCenter().confirmDiscardSavedState(machineNames.join(", ")))
790 return;
791
792 /* For every confirmed item: */
793 foreach (UIVirtualMachineItem *pItem, itemsToDiscard)
794 {
795 /* Open a session to modify VM: */
796 CSession comSession = uiCommon().openSession(pItem->id());
797 if (comSession.isNull())
798 return;
799
800 /* Get session machine: */
801 CMachine comMachine = comSession.GetMachine();
802 comMachine.DiscardSavedState(true);
803 if (!comMachine.isOk())
804 msgCenter().cannotDiscardSavedState(comMachine);
805
806 /* Unlock machine finally: */
807 comSession.UnlockMachine();
808 }
809}
810
811void UIVirtualBoxManager::sltPerformPauseOrResumeMachine(bool fPause)
812{
813 /* Get selected items: */
814 QList<UIVirtualMachineItem*> items = currentItems();
815 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
816
817 /* For every selected item: */
818 foreach (UIVirtualMachineItem *pItem, items)
819 {
820 /* Get item state: */
821 const KMachineState enmState = pItem->machineState();
822
823 /* Check if current item could be paused/resumed: */
824 if (!isActionEnabled(UIActionIndexST_M_Group_T_Pause, QList<UIVirtualMachineItem*>() << pItem))
825 continue;
826
827 /* Check if current item already paused: */
828 if (fPause &&
829 (enmState == KMachineState_Paused ||
830 enmState == KMachineState_TeleportingPausedVM))
831 continue;
832
833 /* Check if current item already resumed: */
834 if (!fPause &&
835 (enmState == KMachineState_Running ||
836 enmState == KMachineState_Teleporting ||
837 enmState == KMachineState_LiveSnapshotting))
838 continue;
839
840 /* Open a session to modify VM state: */
841 CSession comSession = uiCommon().openExistingSession(pItem->id());
842 if (comSession.isNull())
843 return;
844
845 /* Get session console: */
846 CConsole comConsole = comSession.GetConsole();
847 /* Pause/resume VM: */
848 if (fPause)
849 comConsole.Pause();
850 else
851 comConsole.Resume();
852 if (!comConsole.isOk())
853 {
854 if (fPause)
855 msgCenter().cannotPauseMachine(comConsole);
856 else
857 msgCenter().cannotResumeMachine(comConsole);
858 }
859
860 /* Unlock machine finally: */
861 comSession.UnlockMachine();
862 }
863}
864
865void UIVirtualBoxManager::sltPerformResetMachine()
866{
867 /* Get selected items: */
868 QList<UIVirtualMachineItem*> items = currentItems();
869 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
870
871 /* Prepare the list of the machines to be reseted: */
872 QStringList machineNames;
873 QList<UIVirtualMachineItem*> itemsToReset;
874 foreach (UIVirtualMachineItem *pItem, items)
875 {
876 if (isActionEnabled(UIActionIndexST_M_Group_S_Reset, QList<UIVirtualMachineItem*>() << pItem))
877 {
878 machineNames << pItem->name();
879 itemsToReset << pItem;
880 }
881 }
882 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
883
884 /* Confirm reseting VM: */
885 if (!msgCenter().confirmResetMachine(machineNames.join(", ")))
886 return;
887
888 /* For each selected item: */
889 foreach (UIVirtualMachineItem *pItem, itemsToReset)
890 {
891 /* Open a session to modify VM state: */
892 CSession comSession = uiCommon().openExistingSession(pItem->id());
893 if (comSession.isNull())
894 return;
895
896 /* Get session console: */
897 CConsole comConsole = comSession.GetConsole();
898 /* Reset VM: */
899 comConsole.Reset();
900
901 /* Unlock machine finally: */
902 comSession.UnlockMachine();
903 }
904}
905
906void UIVirtualBoxManager::sltPerformDetachMachineUI()
907{
908 /* Get selected items: */
909 QList<UIVirtualMachineItem*> items = currentItems();
910 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
911
912 /* For each selected item: */
913 foreach (UIVirtualMachineItem *pItem, items)
914 {
915 /* Check if current item could be detached: */
916 if (!isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_Detach, QList<UIVirtualMachineItem*>() << pItem))
917 continue;
918
919 /// @todo Detach separate UI process..
920 AssertFailed();
921 }
922}
923
924void UIVirtualBoxManager::sltPerformSaveMachineState()
925{
926 /* Get selected items: */
927 QList<UIVirtualMachineItem*> items = currentItems();
928 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
929
930 /* For each selected item: */
931 foreach (UIVirtualMachineItem *pItem, items)
932 {
933 /* Check if current item could be saved: */
934 if (!isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_SaveState, QList<UIVirtualMachineItem*>() << pItem))
935 continue;
936
937 /* Open a session to modify VM state: */
938 CSession comSession = uiCommon().openExistingSession(pItem->id());
939 if (comSession.isNull())
940 return;
941
942 /* Get session console: */
943 CConsole comConsole = comSession.GetConsole();
944 /* Get session machine: */
945 CMachine comMachine = comSession.GetMachine();
946 /* Pause VM first if necessary: */
947 if (pItem->machineState() != KMachineState_Paused)
948 comConsole.Pause();
949 if (comConsole.isOk())
950 {
951 /* Prepare machine state saving progress: */
952 CProgress comProgress = comMachine.SaveState();
953 if (comMachine.isOk())
954 {
955 /* Show machine state saving progress: */
956 msgCenter().showModalProgressDialog(comProgress, comMachine.GetName(), ":/progress_state_save_90px.png");
957 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
958 msgCenter().cannotSaveMachineState(comProgress, comMachine.GetName());
959 }
960 else
961 msgCenter().cannotSaveMachineState(comMachine);
962 }
963 else
964 msgCenter().cannotPauseMachine(comConsole);
965
966 /* Unlock machine finally: */
967 comSession.UnlockMachine();
968 }
969}
970
971void UIVirtualBoxManager::sltPerformShutdownMachine()
972{
973 /* Get selected items: */
974 QList<UIVirtualMachineItem*> items = currentItems();
975 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
976
977 /* Prepare the list of the machines to be shutdowned: */
978 QStringList machineNames;
979 QList<UIVirtualMachineItem*> itemsToShutdown;
980 foreach (UIVirtualMachineItem *pItem, items)
981 {
982 if (isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_Shutdown, QList<UIVirtualMachineItem*>() << pItem))
983 {
984 machineNames << pItem->name();
985 itemsToShutdown << pItem;
986 }
987 }
988 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
989
990 /* Confirm ACPI shutdown current VM: */
991 if (!msgCenter().confirmACPIShutdownMachine(machineNames.join(", ")))
992 return;
993
994 /* For each selected item: */
995 foreach (UIVirtualMachineItem *pItem, itemsToShutdown)
996 {
997 /* Open a session to modify VM state: */
998 CSession comSession = uiCommon().openExistingSession(pItem->id());
999 if (comSession.isNull())
1000 return;
1001
1002 /* Get session console: */
1003 CConsole comConsole = comSession.GetConsole();
1004 /* ACPI Shutdown: */
1005 comConsole.PowerButton();
1006 if (!comConsole.isOk())
1007 msgCenter().cannotACPIShutdownMachine(comConsole);
1008
1009 /* Unlock machine finally: */
1010 comSession.UnlockMachine();
1011 }
1012}
1013
1014void UIVirtualBoxManager::sltPerformPowerOffMachine()
1015{
1016 /* Get selected items: */
1017 QList<UIVirtualMachineItem*> items = currentItems();
1018 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1019
1020 /* Prepare the list of the machines to be powered off: */
1021 QStringList machineNames;
1022 QList<UIVirtualMachineItem*> itemsToPowerOff;
1023 foreach (UIVirtualMachineItem *pItem, items)
1024 {
1025 if (isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_PowerOff, QList<UIVirtualMachineItem*>() << pItem))
1026 {
1027 machineNames << pItem->name();
1028 itemsToPowerOff << pItem;
1029 }
1030 }
1031 AssertMsg(!machineNames.isEmpty(), ("This action should not be allowed!"));
1032
1033 /* Confirm Power Off current VM: */
1034 if (!msgCenter().confirmPowerOffMachine(machineNames.join(", ")))
1035 return;
1036
1037 /* For each selected item: */
1038 foreach (UIVirtualMachineItem *pItem, itemsToPowerOff)
1039 {
1040 /* Open a session to modify VM state: */
1041 CSession comSession = uiCommon().openExistingSession(pItem->id());
1042 if (comSession.isNull())
1043 return;
1044
1045 /* Get session console: */
1046 CConsole comConsole = comSession.GetConsole();
1047 /* Prepare machine power down: */
1048 CProgress comProgress = comConsole.PowerDown();
1049 if (comConsole.isOk())
1050 {
1051 /* Show machine power down progress: */
1052 CMachine machine = comSession.GetMachine();
1053 msgCenter().showModalProgressDialog(comProgress, machine.GetName(), ":/progress_poweroff_90px.png");
1054 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
1055 msgCenter().cannotPowerDownMachine(comProgress, machine.GetName());
1056 }
1057 else
1058 msgCenter().cannotPowerDownMachine(comConsole);
1059
1060 /* Unlock machine finally: */
1061 comSession.UnlockMachine();
1062 }
1063}
1064
1065void UIVirtualBoxManager::sltPerformShowMachineTool(QAction *pAction)
1066{
1067 AssertPtrReturnVoid(pAction);
1068 AssertPtrReturnVoid(m_pWidget);
1069 m_pWidget->setToolsType(pAction->property("UIToolType").value<UIToolType>());
1070}
1071
1072void UIVirtualBoxManager::sltOpenLogViewerWindow()
1073{
1074 /* Get selected items: */
1075 QList<UIVirtualMachineItem*> items = currentItems();
1076 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1077
1078 /* First check if instance of widget opened the embedded way: */
1079 if (m_pWidget->isMachineToolOpened(UIToolType_Logs))
1080 {
1081 m_pWidget->setToolsType(UIToolType_Details);
1082 m_pWidget->closeMachineTool(UIToolType_Logs);
1083 }
1084
1085 /* For each selected item: */
1086 foreach (UIVirtualMachineItem *pItem, items)
1087 {
1088 /* Check if log could be show for the current item: */
1089 if (!isActionEnabled(UIActionIndexST_M_Group_S_ShowLogDialog, QList<UIVirtualMachineItem*>() << pItem))
1090 continue;
1091
1092 QIManagerDialog *pLogViewerDialog = 0;
1093 /* Create and Show VM Log Viewer: */
1094 if (!m_logViewers[pItem->machine().GetHardwareUUID().toString()])
1095 {
1096 UIVMLogViewerDialogFactory dialogFactory(actionPool(), pItem->machine());
1097 dialogFactory.prepare(pLogViewerDialog, this);
1098 if (pLogViewerDialog)
1099 {
1100 m_logViewers[pItem->machine().GetHardwareUUID().toString()] = pLogViewerDialog;
1101 connect(pLogViewerDialog, &QIManagerDialog::sigClose,
1102 this, &UIVirtualBoxManager::sltCloseLogViewerWindow);
1103 }
1104 }
1105 else
1106 {
1107 pLogViewerDialog = m_logViewers[pItem->machine().GetHardwareUUID().toString()];
1108 }
1109 if (pLogViewerDialog)
1110 {
1111 /* Show instance: */
1112 pLogViewerDialog->show();
1113 pLogViewerDialog->setWindowState(pLogViewerDialog->windowState() & ~Qt::WindowMinimized);
1114 pLogViewerDialog->activateWindow();
1115 }
1116 }
1117}
1118
1119void UIVirtualBoxManager::sltCloseLogViewerWindow()
1120{
1121 /* If there is a proper sender: */
1122 if (qobject_cast<QIManagerDialog*>(sender()))
1123 {
1124 /* Search for the sender of the signal within the m_logViewers map: */
1125 QMap<QString, QIManagerDialog*>::iterator sendersIterator = m_logViewers.begin();
1126 while (sendersIterator != m_logViewers.end() && sendersIterator.value() != sender())
1127 ++sendersIterator;
1128 /* Do nothing if we cannot find it with the map: */
1129 if (sendersIterator == m_logViewers.end())
1130 return;
1131
1132 /* Check whether we have found the proper dialog: */
1133 QIManagerDialog *pDialog = qobject_cast<QIManagerDialog*>(sendersIterator.value());
1134 if (!pDialog)
1135 return;
1136
1137 /* First remove this log-viewer dialog from the map.
1138 * This should be done before closing the dialog which will incur
1139 * a second call to this function and result in double delete!!! */
1140 m_logViewers.erase(sendersIterator);
1141 UIVMLogViewerDialogFactory().cleanup(pDialog);
1142 }
1143 /* Otherwise: */
1144 else
1145 {
1146 /* Just wipe out everything: */
1147 foreach (const QString &strKey, m_logViewers.keys())
1148 {
1149 /* First remove each log-viewer dialog from the map.
1150 * This should be done before closing the dialog which will incur
1151 * a second call to this function and result in double delete!!! */
1152 QIManagerDialog *pDialog = m_logViewers.value(strKey);
1153 m_logViewers.remove(strKey);
1154 UIVMLogViewerDialogFactory().cleanup(pDialog);
1155 }
1156 }
1157}
1158
1159void UIVirtualBoxManager::sltShowMachineInFileManager()
1160{
1161 /* Get selected items: */
1162 QList<UIVirtualMachineItem*> items = currentItems();
1163 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1164
1165 /* For each selected item: */
1166 foreach (UIVirtualMachineItem *pItem, items)
1167 {
1168 /* Check if that item could be shown in file-browser: */
1169 if (!isActionEnabled(UIActionIndexST_M_Group_S_ShowInFileManager, QList<UIVirtualMachineItem*>() << pItem))
1170 continue;
1171
1172 /* Show VM in filebrowser: */
1173 UIDesktopServices::openInFileManager(pItem->machine().GetSettingsFilePath());
1174 }
1175}
1176
1177void UIVirtualBoxManager::sltPerformCreateMachineShortcut()
1178{
1179 /* Get selected items: */
1180 QList<UIVirtualMachineItem*> items = currentItems();
1181 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1182
1183 /* For each selected item: */
1184 foreach (UIVirtualMachineItem *pItem, items)
1185 {
1186 /* Check if shortcuts could be created for this item: */
1187 if (!isActionEnabled(UIActionIndexST_M_Group_S_CreateShortcut, QList<UIVirtualMachineItem*>() << pItem))
1188 continue;
1189
1190 /* Create shortcut for this VM: */
1191 const CMachine &comMachine = pItem->machine();
1192 UIDesktopServices::createMachineShortcut(comMachine.GetSettingsFilePath(),
1193 QStandardPaths::writableLocation(QStandardPaths::DesktopLocation),
1194 comMachine.GetName(), comMachine.GetId());
1195 }
1196}
1197
1198void UIVirtualBoxManager::sltGroupCloseMenuAboutToShow()
1199{
1200 /* Get selected items: */
1201 QList<UIVirtualMachineItem*> items = currentItems();
1202 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1203
1204 actionPool()->action(UIActionIndexST_M_Group_M_Close_S_Shutdown)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close_S_Shutdown, items));
1205}
1206
1207void UIVirtualBoxManager::sltMachineCloseMenuAboutToShow()
1208{
1209 /* Get selected items: */
1210 QList<UIVirtualMachineItem*> items = currentItems();
1211 AssertMsgReturnVoid(!items.isEmpty(), ("At least one item should be selected!\n"));
1212
1213 actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_Shutdown)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_Shutdown, items));
1214}
1215
1216void UIVirtualBoxManager::prepare()
1217{
1218#ifdef VBOX_WS_X11
1219 /* Assign same name to both WM_CLASS name & class for now: */
1220 UICommon::setWMClass(this, "VirtualBox Manager", "VirtualBox Manager");
1221#endif
1222
1223#ifdef VBOX_WS_MAC
1224 /* We have to make sure that we are getting the front most process: */
1225 ::darwinSetFrontMostProcess();
1226 /* Install global event-filter, since vmstarter.app can send us FileOpen events,
1227 * see UIVirtualBoxManager::eventFilter for handler implementation. */
1228 qApp->installEventFilter(this);
1229#endif
1230
1231 /* Cache media data early if necessary: */
1232 if (uiCommon().agressiveCaching())
1233 uiCommon().enumerateMedia();
1234
1235 /* Prepare: */
1236 prepareIcon();
1237 prepareMenuBar();
1238 prepareStatusBar();
1239 prepareWidgets();
1240 prepareConnections();
1241
1242 /* Update actions initially: */
1243 updateActionsVisibility();
1244 updateActionsAppearance();
1245
1246 /* Load settings: */
1247 loadSettings();
1248
1249 /* Translate UI: */
1250 retranslateUi();
1251
1252#ifdef VBOX_WS_MAC
1253 /* Beta label? */
1254 if (uiCommon().isBeta())
1255 {
1256 QPixmap betaLabel = ::betaLabel(QSize(100, 16));
1257 ::darwinLabelWindow(this, &betaLabel, true);
1258 }
1259#endif /* VBOX_WS_MAC */
1260
1261 /* If there are unhandled URLs we should handle them after manager is shown: */
1262 if (uiCommon().argumentUrlsPresent())
1263 QMetaObject::invokeMethod(this, "sltHandleOpenUrlCall", Qt::QueuedConnection);
1264}
1265
1266void UIVirtualBoxManager::prepareIcon()
1267{
1268 /* Prepare application icon.
1269 * On Win host it's built-in to the executable.
1270 * On Mac OS X the icon referenced in info.plist is used.
1271 * On X11 we will provide as much icons as we can. */
1272#if !defined(VBOX_WS_WIN) && !defined(VBOX_WS_MAC)
1273 QIcon icon(":/VirtualBox.svg");
1274 icon.addFile(":/VirtualBox_48px.png");
1275 icon.addFile(":/VirtualBox_64px.png");
1276 setWindowIcon(icon);
1277#endif /* !VBOX_WS_WIN && !VBOX_WS_MAC */
1278}
1279
1280void UIVirtualBoxManager::prepareMenuBar()
1281{
1282#ifndef VBOX_WS_MAC
1283 /* Create menu-bar: */
1284 setMenuBar(new UIMenuBar);
1285 if (menuBar())
1286 {
1287 /* Make sure menu-bar fills own solid background: */
1288 menuBar()->setAutoFillBackground(true);
1289 QPalette pal = menuBar()->palette();
1290 const QColor color = pal.color(QPalette::Active, QPalette::Mid).lighter(160);
1291 pal.setColor(QPalette::Active, QPalette::Button, color);
1292 menuBar()->setPalette(pal);
1293 }
1294#endif
1295
1296 /* Create action-pool: */
1297 m_pActionPool = UIActionPool::create(UIActionPoolType_Manager);
1298
1299 /* Build menu-bar: */
1300 foreach (QMenu *pMenu, actionPool()->menus())
1301 {
1302#ifdef VBOX_WS_MAC
1303 /* Before 'Help' menu we should: */
1304 if (pMenu == actionPool()->action(UIActionIndex_Menu_Help)->menu())
1305 {
1306 /* Insert 'Window' menu: */
1307 UIWindowMenuManager::create();
1308 menuBar()->addMenu(gpWindowMenuManager->createMenu(this));
1309 gpWindowMenuManager->addWindow(this);
1310 }
1311#endif
1312 menuBar()->addMenu(pMenu);
1313 }
1314
1315 /* Setup menu-bar policy: */
1316 menuBar()->setContextMenuPolicy(Qt::CustomContextMenu);
1317}
1318
1319void UIVirtualBoxManager::prepareStatusBar()
1320{
1321 /* We are not using status-bar anymore: */
1322 statusBar()->setHidden(true);
1323}
1324
1325void UIVirtualBoxManager::prepareWidgets()
1326{
1327 /* Create central-widget: */
1328 m_pWidget = new UIVirtualBoxManagerWidget(this);
1329 if (m_pWidget)
1330 {
1331 /* Configure central-widget: */
1332 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigCloudProfileManagerChange,
1333 this, &UIVirtualBoxManager::sigCloudProfileManagerChange);
1334 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigCurrentSnapshotItemChange,
1335 this, &UIVirtualBoxManager::sltCurrentSnapshotItemChange);
1336 setCentralWidget(m_pWidget);
1337 }
1338}
1339
1340void UIVirtualBoxManager::prepareConnections()
1341{
1342#ifdef VBOX_WS_X11
1343 /* Desktop event handlers: */
1344 connect(gpDesktop, &UIDesktopWidgetWatchdog::sigHostScreenWorkAreaResized,
1345 this, &UIVirtualBoxManager::sltHandleHostScreenAvailableAreaChange);
1346#endif
1347
1348 /* Medium enumeration connections: */
1349 connect(&uiCommon(), &UICommon::sigMediumEnumerationFinished,
1350 this, &UIVirtualBoxManager::sltHandleMediumEnumerationFinish);
1351
1352 /* Widget connections: */
1353 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigChooserPaneIndexChange,
1354 this, &UIVirtualBoxManager::sltHandleChooserPaneIndexChange);
1355 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigGroupSavingStateChanged,
1356 this, &UIVirtualBoxManager::sltHandleGroupSavingProgressChange);
1357 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigMachineSettingsLinkClicked,
1358 this, &UIVirtualBoxManager::sltOpenMachineSettingsDialog);
1359 connect(m_pWidget, &UIVirtualBoxManagerWidget::sigToolTypeChange,
1360 this, &UIVirtualBoxManager::sltHandleToolTypeChange);
1361 connect(menuBar(), &QMenuBar::customContextMenuRequested,
1362 m_pWidget, &UIVirtualBoxManagerWidget::sltHandleContextMenuRequest);
1363
1364 /* Global VBox event handlers: */
1365 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
1366 this, &UIVirtualBoxManager::sltHandleStateChange);
1367 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSessionStateChange,
1368 this, &UIVirtualBoxManager::sltHandleStateChange);
1369
1370 /* 'File' menu connections: */
1371 connect(actionPool()->action(UIActionIndexST_M_File_S_ShowVirtualMediumManager), &UIAction::triggered,
1372 this, &UIVirtualBoxManager::sltOpenVirtualMediumManagerWindow);
1373 connect(actionPool()->action(UIActionIndexST_M_File_S_ShowHostNetworkManager), &UIAction::triggered,
1374 this, &UIVirtualBoxManager::sltOpenHostNetworkManagerWindow);
1375 connect(actionPool()->action(UIActionIndexST_M_File_S_ShowCloudProfileManager), &UIAction::triggered,
1376 this, &UIVirtualBoxManager::sltOpenCloudProfileManagerWindow);
1377 connect(actionPool()->action(UIActionIndexST_M_File_S_ImportAppliance), &UIAction::triggered,
1378 this, &UIVirtualBoxManager::sltOpenImportApplianceWizardDefault);
1379 connect(actionPool()->action(UIActionIndexST_M_File_S_ExportAppliance), &UIAction::triggered,
1380 this, &UIVirtualBoxManager::sltOpenExportApplianceWizard);
1381 connect(actionPool()->action(UIActionIndexST_M_File_S_NewCloudVM), &UIAction::triggered,
1382 this, &UIVirtualBoxManager::sltOpenNewCloudVMWizard);
1383#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
1384 connect(actionPool()->action(UIActionIndexST_M_File_S_ShowExtraDataManager), &UIAction::triggered,
1385 this, &UIVirtualBoxManager::sltOpenExtraDataManagerWindow);
1386#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
1387 connect(actionPool()->action(UIActionIndex_M_Application_S_Preferences), &UIAction::triggered,
1388 this, &UIVirtualBoxManager::sltOpenPreferencesDialog);
1389 connect(actionPool()->action(UIActionIndexST_M_File_S_Close), &UIAction::triggered,
1390 this, &UIVirtualBoxManager::sltPerformExit);
1391
1392 /* 'Welcome' menu connections: */
1393 connect(actionPool()->action(UIActionIndexST_M_Welcome_S_Add), &UIAction::triggered,
1394 this, &UIVirtualBoxManager::sltOpenAddMachineDialogDefault);
1395
1396 /* 'Group' menu connections: */
1397 connect(actionPool()->action(UIActionIndexST_M_Group_S_Add), &UIAction::triggered,
1398 this, &UIVirtualBoxManager::sltOpenAddMachineDialogDefault);
1399 connect(actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow), &UIAction::triggered,
1400 this, &UIVirtualBoxManager::sltPerformStartOrShowMachine);
1401 connect(actionPool()->action(UIActionIndexST_M_Group_T_Pause), &UIAction::toggled,
1402 this, &UIVirtualBoxManager::sltPerformPauseOrResumeMachine);
1403 connect(actionPool()->action(UIActionIndexST_M_Group_S_Reset), &UIAction::triggered,
1404 this, &UIVirtualBoxManager::sltPerformResetMachine);
1405 connect(actionPool()->action(UIActionIndexST_M_Group_S_Discard), &UIAction::triggered,
1406 this, &UIVirtualBoxManager::sltPerformDiscardMachineState);
1407 connect(actionPool()->action(UIActionIndexST_M_Group_S_ShowLogDialog), &UIAction::triggered,
1408 this, &UIVirtualBoxManager::sltOpenLogViewerWindow);
1409 connect(actionPool()->action(UIActionIndexST_M_Group_S_ShowInFileManager), &UIAction::triggered,
1410 this, &UIVirtualBoxManager::sltShowMachineInFileManager);
1411 connect(actionPool()->action(UIActionIndexST_M_Group_S_CreateShortcut), &UIAction::triggered,
1412 this, &UIVirtualBoxManager::sltPerformCreateMachineShortcut);
1413
1414 /* 'Machine' menu connections: */
1415 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Add), &UIAction::triggered,
1416 this, &UIVirtualBoxManager::sltOpenAddMachineDialogDefault);
1417 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Settings), &UIAction::triggered,
1418 this, &UIVirtualBoxManager::sltOpenMachineSettingsDialogDefault);
1419 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Clone), &UIAction::triggered,
1420 this, &UIVirtualBoxManager::sltOpenCloneMachineWizard);
1421 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Move), &UIAction::triggered,
1422 this, &UIVirtualBoxManager::sltPerformMachineMove);
1423 connect(actionPool()->action(UIActionIndexST_M_Machine_S_ExportToOCI), &UIAction::triggered,
1424 this, &UIVirtualBoxManager::sltOpenExportApplianceWizard);
1425 connect(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow), &UIAction::triggered,
1426 this, &UIVirtualBoxManager::sltPerformStartOrShowMachine);
1427 connect(actionPool()->action(UIActionIndexST_M_Machine_T_Pause), &UIAction::toggled,
1428 this, &UIVirtualBoxManager::sltPerformPauseOrResumeMachine);
1429 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Reset), &UIAction::triggered,
1430 this, &UIVirtualBoxManager::sltPerformResetMachine);
1431 connect(actionPool()->action(UIActionIndexST_M_Machine_S_Discard), &UIAction::triggered,
1432 this, &UIVirtualBoxManager::sltPerformDiscardMachineState);
1433 connect(actionPool()->action(UIActionIndexST_M_Machine_S_ShowLogDialog), &UIAction::triggered,
1434 this, &UIVirtualBoxManager::sltOpenLogViewerWindow);
1435 connect(actionPool()->action(UIActionIndexST_M_Machine_S_ShowInFileManager), &UIAction::triggered,
1436 this, &UIVirtualBoxManager::sltShowMachineInFileManager);
1437 connect(actionPool()->action(UIActionIndexST_M_Machine_S_CreateShortcut), &UIAction::triggered,
1438 this, &UIVirtualBoxManager::sltPerformCreateMachineShortcut);
1439
1440 /* 'Group/Start or Show' menu connections: */
1441 connect(actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartNormal), &UIAction::triggered,
1442 this, &UIVirtualBoxManager::sltPerformStartMachineNormal);
1443 connect(actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartHeadless), &UIAction::triggered,
1444 this, &UIVirtualBoxManager::sltPerformStartMachineHeadless);
1445 connect(actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartDetachable), &UIAction::triggered,
1446 this, &UIVirtualBoxManager::sltPerformStartMachineDetachable);
1447
1448 /* 'Machine/Start or Show' menu connections: */
1449 connect(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartNormal), &UIAction::triggered,
1450 this, &UIVirtualBoxManager::sltPerformStartMachineNormal);
1451 connect(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartHeadless), &UIAction::triggered,
1452 this, &UIVirtualBoxManager::sltPerformStartMachineHeadless);
1453 connect(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartDetachable), &UIAction::triggered,
1454 this, &UIVirtualBoxManager::sltPerformStartMachineDetachable);
1455
1456 /* 'Group/Close' menu connections: */
1457 connect(actionPool()->action(UIActionIndexST_M_Group_M_Close)->menu(), &UIMenu::aboutToShow,
1458 this, &UIVirtualBoxManager::sltGroupCloseMenuAboutToShow);
1459 connect(actionPool()->action(UIActionIndexST_M_Group_M_Close_S_Detach), &UIAction::triggered,
1460 this, &UIVirtualBoxManager::sltPerformDetachMachineUI);
1461 connect(actionPool()->action(UIActionIndexST_M_Group_M_Close_S_SaveState), &UIAction::triggered,
1462 this, &UIVirtualBoxManager::sltPerformSaveMachineState);
1463 connect(actionPool()->action(UIActionIndexST_M_Group_M_Close_S_Shutdown), &UIAction::triggered,
1464 this, &UIVirtualBoxManager::sltPerformShutdownMachine);
1465 connect(actionPool()->action(UIActionIndexST_M_Group_M_Close_S_PowerOff), &UIAction::triggered,
1466 this, &UIVirtualBoxManager::sltPerformPowerOffMachine);
1467
1468 /* 'Machine/Close' menu connections: */
1469 connect(actionPool()->action(UIActionIndexST_M_Machine_M_Close)->menu(), &UIMenu::aboutToShow,
1470 this, &UIVirtualBoxManager::sltMachineCloseMenuAboutToShow);
1471 connect(actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_Detach), &UIAction::triggered,
1472 this, &UIVirtualBoxManager::sltPerformDetachMachineUI);
1473 connect(actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_SaveState), &UIAction::triggered,
1474 this, &UIVirtualBoxManager::sltPerformSaveMachineState);
1475 connect(actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_Shutdown), &UIAction::triggered,
1476 this, &UIVirtualBoxManager::sltPerformShutdownMachine);
1477 connect(actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_PowerOff), &UIAction::triggered,
1478 this, &UIVirtualBoxManager::sltPerformPowerOffMachine);
1479
1480 /* 'Group/Tools' menu connections: */
1481 connect(actionPool()->actionGroup(UIActionIndexST_M_Group_M_Tools), &QActionGroup::triggered,
1482 this, &UIVirtualBoxManager::sltPerformShowMachineTool);
1483
1484 /* 'Machine/Tools' menu connections: */
1485 connect(actionPool()->actionGroup(UIActionIndexST_M_Machine_M_Tools), &QActionGroup::triggered,
1486 this, &UIVirtualBoxManager::sltPerformShowMachineTool);
1487}
1488
1489void UIVirtualBoxManager::loadSettings()
1490{
1491 /* Load window geometry: */
1492 {
1493 const QRect geo = gEDataManager->selectorWindowGeometry(this);
1494 LogRel2(("GUI: UIVirtualBoxManager: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
1495 geo.x(), geo.y(), geo.width(), geo.height()));
1496 restoreGeometry(geo);
1497 }
1498}
1499
1500void UIVirtualBoxManager::saveSettings()
1501{
1502 /* Save window geometry: */
1503 {
1504 const QRect geo = currentGeometry();
1505 LogRel2(("GUI: UIVirtualBoxManager: Saving geometry as: Origin=%dx%d, Size=%dx%d\n",
1506 geo.x(), geo.y(), geo.width(), geo.height()));
1507 gEDataManager->setSelectorWindowGeometry(geo, isCurrentlyMaximized());
1508 }
1509}
1510
1511void UIVirtualBoxManager::cleanupConnections()
1512{
1513 /* Honestly we should disconnect everything here,
1514 * but for now it's enough to disconnect the most critical. */
1515 m_pWidget->disconnect(this);
1516}
1517
1518void UIVirtualBoxManager::cleanupWidgets()
1519{
1520 /* Deconfigure central-widget: */
1521 setCentralWidget(0);
1522 /* Destroy central-widget: */
1523 delete m_pWidget;
1524 m_pWidget = 0;
1525}
1526
1527void UIVirtualBoxManager::cleanupMenuBar()
1528{
1529#ifdef VBOX_WS_MAC
1530 /* Cleanup 'Window' menu: */
1531 UIWindowMenuManager::destroy();
1532#endif
1533
1534 /* Destroy action-pool: */
1535 UIActionPool::destroy(m_pActionPool);
1536 m_pActionPool = 0;
1537}
1538
1539void UIVirtualBoxManager::cleanup()
1540{
1541 /* Close the sub-dialogs first: */
1542 sltCloseVirtualMediumManagerWindow();
1543 sltCloseHostNetworkManagerWindow();
1544 sltCloseCloudProfileManagerWindow();
1545
1546 /* Save settings: */
1547 saveSettings();
1548
1549 /* Cleanup: */
1550 cleanupConnections();
1551 cleanupWidgets();
1552 cleanupMenuBar();
1553}
1554
1555UIVirtualMachineItem *UIVirtualBoxManager::currentItem() const
1556{
1557 return m_pWidget->currentItem();
1558}
1559
1560QList<UIVirtualMachineItem*> UIVirtualBoxManager::currentItems() const
1561{
1562 return m_pWidget->currentItems();
1563}
1564
1565bool UIVirtualBoxManager::isGroupSavingInProgress() const
1566{
1567 return m_pWidget->isGroupSavingInProgress();
1568}
1569
1570bool UIVirtualBoxManager::isAllItemsOfOneGroupSelected() const
1571{
1572 return m_pWidget->isAllItemsOfOneGroupSelected();
1573}
1574
1575bool UIVirtualBoxManager::isSingleGroupSelected() const
1576{
1577 return m_pWidget->isSingleGroupSelected();
1578}
1579
1580void UIVirtualBoxManager::performStartOrShowVirtualMachines(const QList<UIVirtualMachineItem*> &items, UICommon::LaunchMode enmLaunchMode)
1581{
1582 /* Do nothing while group saving is in progress: */
1583 if (isGroupSavingInProgress())
1584 return;
1585
1586 /* Compose the list of startable items: */
1587 QStringList startableMachineNames;
1588 QList<UIVirtualMachineItem*> startableItems;
1589 foreach (UIVirtualMachineItem *pItem, items)
1590 {
1591 if (isAtLeastOneItemCanBeStarted(QList<UIVirtualMachineItem*>() << pItem))
1592 {
1593 startableItems << pItem;
1594 startableMachineNames << pItem->name();
1595 }
1596 }
1597
1598 /* Initially we have start auto-confirmed: */
1599 bool fStartConfirmed = true;
1600 /* But if we have more than one item to start =>
1601 * We should still ask user for a confirmation: */
1602 if (startableItems.size() > 1)
1603 fStartConfirmed = msgCenter().confirmStartMultipleMachines(startableMachineNames.join(", "));
1604
1605 /* For every item => check if it could be launched: */
1606 foreach (UIVirtualMachineItem *pItem, items)
1607 {
1608 if ( isAtLeastOneItemCanBeShown(QList<UIVirtualMachineItem*>() << pItem)
1609 || ( isAtLeastOneItemCanBeStarted(QList<UIVirtualMachineItem*>() << pItem)
1610 && fStartConfirmed))
1611 {
1612 /* Fetch item launch mode: */
1613 UICommon::LaunchMode enmItemLaunchMode = enmLaunchMode;
1614 if (enmItemLaunchMode == UICommon::LaunchMode_Invalid)
1615 enmItemLaunchMode = UIVirtualMachineItem::isItemRunningHeadless(pItem) ? UICommon::LaunchMode_Separate :
1616 qApp->keyboardModifiers() == Qt::ShiftModifier ? UICommon::LaunchMode_Headless :
1617 UICommon::LaunchMode_Default;
1618
1619 /* Launch current VM: */
1620 CMachine machine = pItem->machine();
1621 uiCommon().launchMachine(machine, enmItemLaunchMode);
1622 }
1623 }
1624}
1625
1626void UIVirtualBoxManager::updateActionsVisibility()
1627{
1628 /* Determine whether Machine or Group menu should be shown at all: */
1629 const bool fGlobalMenuShown = m_pWidget->isGlobalItemSelected();
1630 const bool fGroupMenuShown = m_pWidget->isGroupItemSelected() && isSingleGroupSelected();
1631 const bool fMachineMenuShown = m_pWidget->isMachineItemSelected() && !isSingleGroupSelected();
1632 actionPool()->action(UIActionIndexST_M_Welcome)->setVisible(fGlobalMenuShown);
1633 actionPool()->action(UIActionIndexST_M_Group)->setVisible(fGroupMenuShown);
1634 actionPool()->action(UIActionIndexST_M_Machine)->setVisible(fMachineMenuShown);
1635
1636 /* Determine whether Media menu should be visible: */
1637 const bool fMediumMenuShown = fGlobalMenuShown && m_pWidget->currentGlobalTool() == UIToolType_Media;
1638 actionPool()->action(UIActionIndexST_M_Medium)->setVisible(fMediumMenuShown);
1639 /* Determine whether Network menu should be visible: */
1640 const bool fNetworkMenuShown = fGlobalMenuShown && m_pWidget->currentGlobalTool() == UIToolType_Network;
1641 actionPool()->action(UIActionIndexST_M_Network)->setVisible(fNetworkMenuShown);
1642 /* Determine whether Cloud menu should be visible: */
1643 const bool fCloudMenuShown = fGlobalMenuShown && m_pWidget->currentGlobalTool() == UIToolType_Cloud;
1644 actionPool()->action(UIActionIndexST_M_Cloud)->setVisible(fCloudMenuShown);
1645
1646 /* Determine whether Snapshots menu should be visible: */
1647 const bool fSnapshotMenuShown = (fMachineMenuShown || fGroupMenuShown) &&
1648 m_pWidget->currentMachineTool() == UIToolType_Snapshots;
1649 actionPool()->action(UIActionIndexST_M_Snapshot)->setVisible(fSnapshotMenuShown);
1650 /* Determine whether Logs menu should be visible: */
1651 const bool fLogViewerMenuShown = (fMachineMenuShown || fGroupMenuShown) &&
1652 m_pWidget->currentMachineTool() == UIToolType_Logs;
1653 actionPool()->action(UIActionIndex_M_Log)->setVisible(fLogViewerMenuShown);
1654
1655 /* Hide action shortcuts: */
1656 if (!fGlobalMenuShown)
1657 actionPool()->setShortcutsVisible(UIActionIndexST_M_Welcome, false);
1658 if (!fGroupMenuShown)
1659 actionPool()->setShortcutsVisible(UIActionIndexST_M_Group, false);
1660 if (!fMachineMenuShown)
1661 actionPool()->setShortcutsVisible(UIActionIndexST_M_Machine, false);
1662
1663 /* Show action shortcuts: */
1664 if (fGlobalMenuShown)
1665 actionPool()->setShortcutsVisible(UIActionIndexST_M_Welcome, true);
1666 if (fGroupMenuShown)
1667 actionPool()->setShortcutsVisible(UIActionIndexST_M_Group, true);
1668 if (fMachineMenuShown)
1669 actionPool()->setShortcutsVisible(UIActionIndexST_M_Machine, true);
1670}
1671
1672void UIVirtualBoxManager::updateActionsAppearance()
1673{
1674 /* Get current items: */
1675 QList<UIVirtualMachineItem*> items = currentItems();
1676
1677 /* Enable/disable File/Application actions: */
1678 actionPool()->action(UIActionIndex_M_Application_S_Preferences)->setEnabled(isActionEnabled(UIActionIndex_M_Application_S_Preferences, items));
1679 actionPool()->action(UIActionIndexST_M_File_S_ExportAppliance)->setEnabled(isActionEnabled(UIActionIndexST_M_File_S_ExportAppliance, items));
1680 actionPool()->action(UIActionIndexST_M_File_S_ImportAppliance)->setEnabled(isActionEnabled(UIActionIndexST_M_File_S_ImportAppliance, items));
1681 actionPool()->action(UIActionIndexST_M_File_S_NewCloudVM)->setEnabled(isActionEnabled(UIActionIndexST_M_File_S_NewCloudVM, items));
1682
1683 /* Enable/disable welcome actions: */
1684 actionPool()->action(UIActionIndexST_M_Welcome_S_Add)->setEnabled(isActionEnabled(UIActionIndexST_M_Welcome_S_Add, items));
1685
1686 /* Enable/disable group actions: */
1687 actionPool()->action(UIActionIndexST_M_Group_S_Rename)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Rename, items));
1688 actionPool()->action(UIActionIndexST_M_Group_S_Remove)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Remove, items));
1689 actionPool()->action(UIActionIndexST_M_Group_T_Pause)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_T_Pause, items));
1690 actionPool()->action(UIActionIndexST_M_Group_S_Reset)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Reset, items));
1691 actionPool()->action(UIActionIndexST_M_Group_S_Discard)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Discard, items));
1692 actionPool()->action(UIActionIndexST_M_Group_S_ShowLogDialog)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_ShowLogDialog, items));
1693 actionPool()->action(UIActionIndexST_M_Group_S_Refresh)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Refresh, items));
1694 actionPool()->action(UIActionIndexST_M_Group_S_ShowInFileManager)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_ShowInFileManager, items));
1695 actionPool()->action(UIActionIndexST_M_Group_S_CreateShortcut)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_CreateShortcut, items));
1696 actionPool()->action(UIActionIndexST_M_Group_S_Sort)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_S_Sort, items));
1697
1698 /* Enable/disable machine actions: */
1699 actionPool()->action(UIActionIndexST_M_Machine_S_Settings)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Settings, items));
1700 actionPool()->action(UIActionIndexST_M_Machine_S_Clone)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Clone, items));
1701 actionPool()->action(UIActionIndexST_M_Machine_S_Move)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Move, items));
1702 actionPool()->action(UIActionIndexST_M_Machine_S_ExportToOCI)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_ExportToOCI, items));
1703 actionPool()->action(UIActionIndexST_M_Machine_S_Remove)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Remove, items));
1704 actionPool()->action(UIActionIndexST_M_Machine_S_AddGroup)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_AddGroup, items));
1705 actionPool()->action(UIActionIndexST_M_Machine_T_Pause)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_T_Pause, items));
1706 actionPool()->action(UIActionIndexST_M_Machine_S_Reset)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Reset, items));
1707 actionPool()->action(UIActionIndexST_M_Machine_S_Discard)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Discard, items));
1708 actionPool()->action(UIActionIndexST_M_Machine_S_ShowLogDialog)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_ShowLogDialog, items));
1709 actionPool()->action(UIActionIndexST_M_Machine_S_Refresh)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_Refresh, items));
1710 actionPool()->action(UIActionIndexST_M_Machine_S_ShowInFileManager)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_ShowInFileManager, items));
1711 actionPool()->action(UIActionIndexST_M_Machine_S_CreateShortcut)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_CreateShortcut, items));
1712 actionPool()->action(UIActionIndexST_M_Machine_S_SortParent)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_S_SortParent, items));
1713
1714 /* Enable/disable group-start-or-show actions: */
1715 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_StartOrShow, items));
1716 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartNormal)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_StartOrShow_S_StartNormal, items));
1717 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartHeadless)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_StartOrShow_S_StartHeadless, items));
1718 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow_S_StartDetachable)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_StartOrShow_S_StartDetachable, items));
1719
1720 /* Enable/disable machine-start-or-show actions: */
1721 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_StartOrShow, items));
1722 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartNormal)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_StartOrShow_S_StartNormal, items));
1723 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartHeadless)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_StartOrShow_S_StartHeadless, items));
1724 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow_S_StartDetachable)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_StartOrShow_S_StartDetachable, items));
1725
1726 /* Enable/disable group-close actions: */
1727 actionPool()->action(UIActionIndexST_M_Group_M_Close)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close, items));
1728 actionPool()->action(UIActionIndexST_M_Group_M_Close_S_Detach)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close_S_Detach, items));
1729 actionPool()->action(UIActionIndexST_M_Group_M_Close_S_SaveState)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close_S_SaveState, items));
1730 actionPool()->action(UIActionIndexST_M_Group_M_Close_S_Shutdown)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close_S_Shutdown, items));
1731 actionPool()->action(UIActionIndexST_M_Group_M_Close_S_PowerOff)->setEnabled(isActionEnabled(UIActionIndexST_M_Group_M_Close_S_PowerOff, items));
1732
1733 /* Enable/disable machine-close actions: */
1734 actionPool()->action(UIActionIndexST_M_Machine_M_Close)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close, items));
1735 actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_Detach)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_Detach, items));
1736 actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_SaveState)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_SaveState, items));
1737 actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_Shutdown)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_Shutdown, items));
1738 actionPool()->action(UIActionIndexST_M_Machine_M_Close_S_PowerOff)->setEnabled(isActionEnabled(UIActionIndexST_M_Machine_M_Close_S_PowerOff, items));
1739
1740 /* Get current item: */
1741 UIVirtualMachineItem *pItem = currentItem();
1742
1743 /* Start/Show action is deremined by 1st item: */
1744 if (pItem && pItem->accessible())
1745 {
1746 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow)->toActionPolymorphicMenu()->setState(UIVirtualMachineItem::isItemPoweredOff(pItem) ? 0 : 1);
1747 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow)->toActionPolymorphicMenu()->setState(UIVirtualMachineItem::isItemPoweredOff(pItem) ? 0 : 1);
1748 /// @todo Hmm, fix it?
1749// QToolButton *pButton = qobject_cast<QToolButton*>(m_pToolBar->widgetForAction(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow)));
1750// if (pButton)
1751// pButton->setPopupMode(UIVirtualMachineItem::isItemPoweredOff(pItem) ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup);
1752 }
1753 else
1754 {
1755 actionPool()->action(UIActionIndexST_M_Group_M_StartOrShow)->toActionPolymorphicMenu()->setState(0);
1756 actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow)->toActionPolymorphicMenu()->setState(0);
1757 /// @todo Hmm, fix it?
1758// QToolButton *pButton = qobject_cast<QToolButton*>(m_pToolBar->widgetForAction(actionPool()->action(UIActionIndexST_M_Machine_M_StartOrShow)));
1759// if (pButton)
1760// pButton->setPopupMode(UIVirtualMachineItem::isItemPoweredOff(pItem) ? QToolButton::MenuButtonPopup : QToolButton::DelayedPopup);
1761 }
1762
1763 /* Pause/Resume action is deremined by 1st started item: */
1764 UIVirtualMachineItem *pFirstStartedAction = 0;
1765 foreach (UIVirtualMachineItem *pSelectedItem, items)
1766 {
1767 if (UIVirtualMachineItem::isItemStarted(pSelectedItem))
1768 {
1769 pFirstStartedAction = pSelectedItem;
1770 break;
1771 }
1772 }
1773 /* Update the group Pause/Resume action appearance: */
1774 actionPool()->action(UIActionIndexST_M_Group_T_Pause)->blockSignals(true);
1775 actionPool()->action(UIActionIndexST_M_Group_T_Pause)->setChecked(pFirstStartedAction && UIVirtualMachineItem::isItemPaused(pFirstStartedAction));
1776 actionPool()->action(UIActionIndexST_M_Group_T_Pause)->retranslateUi();
1777 actionPool()->action(UIActionIndexST_M_Group_T_Pause)->blockSignals(false);
1778 /* Update the machine Pause/Resume action appearance: */
1779 actionPool()->action(UIActionIndexST_M_Machine_T_Pause)->blockSignals(true);
1780 actionPool()->action(UIActionIndexST_M_Machine_T_Pause)->setChecked(pFirstStartedAction && UIVirtualMachineItem::isItemPaused(pFirstStartedAction));
1781 actionPool()->action(UIActionIndexST_M_Machine_T_Pause)->retranslateUi();
1782 actionPool()->action(UIActionIndexST_M_Machine_T_Pause)->blockSignals(false);
1783
1784 /* Update action toggle states: */
1785 if (m_pWidget)
1786 {
1787 switch (m_pWidget->currentMachineTool())
1788 {
1789 case UIToolType_Details:
1790 {
1791 actionPool()->action(UIActionIndexST_M_Group_M_Tools_T_Details)->setChecked(true);
1792 actionPool()->action(UIActionIndexST_M_Machine_M_Tools_T_Details)->setChecked(true);
1793 break;
1794 }
1795 case UIToolType_Snapshots:
1796 {
1797 actionPool()->action(UIActionIndexST_M_Group_M_Tools_T_Snapshots)->setChecked(true);
1798 actionPool()->action(UIActionIndexST_M_Machine_M_Tools_T_Snapshots)->setChecked(true);
1799 break;
1800 }
1801 case UIToolType_Logs:
1802 {
1803 actionPool()->action(UIActionIndexST_M_Group_M_Tools_T_Logs)->setChecked(true);
1804 actionPool()->action(UIActionIndexST_M_Machine_M_Tools_T_Logs)->setChecked(true);
1805 break;
1806 }
1807 default:
1808 break;
1809 }
1810 }
1811}
1812
1813bool UIVirtualBoxManager::isActionEnabled(int iActionIndex, const QList<UIVirtualMachineItem*> &items)
1814{
1815 /* For known *global* action types: */
1816 switch (iActionIndex)
1817 {
1818 case UIActionIndex_M_Application_S_Preferences:
1819 case UIActionIndexST_M_File_S_ExportAppliance:
1820 case UIActionIndexST_M_File_S_ImportAppliance:
1821 case UIActionIndexST_M_File_S_NewCloudVM:
1822 case UIActionIndexST_M_Welcome_S_Add:
1823 {
1824 return !actionPool()->action(iActionIndex)->property("opened").toBool();
1825 }
1826 default:
1827 break;
1828 }
1829
1830 /* No *machine* actions enabled for empty item list: */
1831 if (items.isEmpty())
1832 return false;
1833
1834 /* Get first item: */
1835 UIVirtualMachineItem *pItem = items.first();
1836
1837 /* For known *machine* action types: */
1838 switch (iActionIndex)
1839 {
1840 case UIActionIndexST_M_Group_S_Rename:
1841 case UIActionIndexST_M_Group_S_Remove:
1842 {
1843 return !isGroupSavingInProgress() &&
1844 isItemsPoweredOff(items);
1845 }
1846 case UIActionIndexST_M_Group_S_Sort:
1847 {
1848 return !isGroupSavingInProgress() &&
1849 isSingleGroupSelected();
1850 }
1851 case UIActionIndexST_M_Machine_S_Settings:
1852 {
1853 return !actionPool()->action(iActionIndex)->property("opened").toBool() &&
1854 !isGroupSavingInProgress() &&
1855 items.size() == 1 &&
1856 pItem->configurationAccessLevel() != ConfigurationAccessLevel_Null &&
1857 (m_pWidget->currentMachineTool() != UIToolType_Snapshots ||
1858 m_pWidget->isCurrentStateItemSelected());
1859 }
1860 case UIActionIndexST_M_Machine_S_Clone:
1861 case UIActionIndexST_M_Machine_S_Move:
1862 {
1863 return !isGroupSavingInProgress() &&
1864 items.size() == 1 &&
1865 UIVirtualMachineItem::isItemEditable(pItem);
1866 }
1867 case UIActionIndexST_M_Machine_S_ExportToOCI:
1868 {
1869 return !actionPool()->action(iActionIndex)->property("opened").toBool() &&
1870 items.size() == 1;
1871 }
1872 case UIActionIndexST_M_Machine_S_Remove:
1873 {
1874 return !isGroupSavingInProgress() &&
1875 isAtLeastOneItemRemovable(items);
1876 }
1877 case UIActionIndexST_M_Machine_S_AddGroup:
1878 {
1879 return !isGroupSavingInProgress() &&
1880 !isAllItemsOfOneGroupSelected() &&
1881 isItemsPoweredOff(items);
1882 }
1883 case UIActionIndexST_M_Group_M_StartOrShow:
1884 case UIActionIndexST_M_Group_M_StartOrShow_S_StartNormal:
1885 case UIActionIndexST_M_Group_M_StartOrShow_S_StartHeadless:
1886 case UIActionIndexST_M_Group_M_StartOrShow_S_StartDetachable:
1887 case UIActionIndexST_M_Machine_M_StartOrShow:
1888 case UIActionIndexST_M_Machine_M_StartOrShow_S_StartNormal:
1889 case UIActionIndexST_M_Machine_M_StartOrShow_S_StartHeadless:
1890 case UIActionIndexST_M_Machine_M_StartOrShow_S_StartDetachable:
1891 {
1892 return !isGroupSavingInProgress() &&
1893 isAtLeastOneItemCanBeStartedOrShown(items) &&
1894 (m_pWidget->currentMachineTool() != UIToolType_Snapshots ||
1895 m_pWidget->isCurrentStateItemSelected());
1896 }
1897 case UIActionIndexST_M_Group_S_Discard:
1898 case UIActionIndexST_M_Machine_S_Discard:
1899 {
1900 return !isGroupSavingInProgress() &&
1901 isAtLeastOneItemDiscardable(items) &&
1902 (m_pWidget->currentMachineTool() != UIToolType_Snapshots ||
1903 m_pWidget->isCurrentStateItemSelected());
1904 }
1905 case UIActionIndexST_M_Group_S_ShowLogDialog:
1906 case UIActionIndexST_M_Machine_S_ShowLogDialog:
1907 {
1908 return isAtLeastOneItemAccessible(items);
1909 }
1910 case UIActionIndexST_M_Group_T_Pause:
1911 case UIActionIndexST_M_Machine_T_Pause:
1912 {
1913 return isAtLeastOneItemStarted(items);
1914 }
1915 case UIActionIndexST_M_Group_S_Reset:
1916 case UIActionIndexST_M_Machine_S_Reset:
1917 {
1918 return isAtLeastOneItemRunning(items);
1919 }
1920 case UIActionIndexST_M_Group_S_Refresh:
1921 case UIActionIndexST_M_Machine_S_Refresh:
1922 {
1923 return isAtLeastOneItemInaccessible(items);
1924 }
1925 case UIActionIndexST_M_Group_S_ShowInFileManager:
1926 case UIActionIndexST_M_Machine_S_ShowInFileManager:
1927 {
1928 return isAtLeastOneItemAccessible(items);
1929 }
1930 case UIActionIndexST_M_Machine_S_SortParent:
1931 {
1932 return !isGroupSavingInProgress();
1933 }
1934 case UIActionIndexST_M_Group_S_CreateShortcut:
1935 case UIActionIndexST_M_Machine_S_CreateShortcut:
1936 {
1937 return isAtLeastOneItemSupportsShortcuts(items);
1938 }
1939 case UIActionIndexST_M_Group_M_Close:
1940 case UIActionIndexST_M_Machine_M_Close:
1941 {
1942 return isAtLeastOneItemStarted(items);
1943 }
1944 case UIActionIndexST_M_Group_M_Close_S_Detach:
1945 case UIActionIndexST_M_Machine_M_Close_S_Detach:
1946 {
1947 return isActionEnabled(UIActionIndexST_M_Machine_M_Close, items);
1948 }
1949 case UIActionIndexST_M_Group_M_Close_S_SaveState:
1950 case UIActionIndexST_M_Machine_M_Close_S_SaveState:
1951 {
1952 return isActionEnabled(UIActionIndexST_M_Machine_M_Close, items);
1953 }
1954 case UIActionIndexST_M_Group_M_Close_S_Shutdown:
1955 case UIActionIndexST_M_Machine_M_Close_S_Shutdown:
1956 {
1957 return isActionEnabled(UIActionIndexST_M_Machine_M_Close, items) &&
1958 isAtLeastOneItemAbleToShutdown(items);
1959 }
1960 case UIActionIndexST_M_Group_M_Close_S_PowerOff:
1961 case UIActionIndexST_M_Machine_M_Close_S_PowerOff:
1962 {
1963 return isActionEnabled(UIActionIndexST_M_Machine_M_Close, items);
1964 }
1965 default:
1966 break;
1967 }
1968
1969 /* Unknown actions are disabled: */
1970 return false;
1971}
1972
1973/* static */
1974bool UIVirtualBoxManager::isItemsPoweredOff(const QList<UIVirtualMachineItem*> &items)
1975{
1976 foreach (UIVirtualMachineItem *pItem, items)
1977 if (!UIVirtualMachineItem::isItemPoweredOff(pItem))
1978 return false;
1979 return true;
1980}
1981
1982/* static */
1983bool UIVirtualBoxManager::isAtLeastOneItemAbleToShutdown(const QList<UIVirtualMachineItem*> &items)
1984{
1985 /* Enumerate all the passed items: */
1986 foreach (UIVirtualMachineItem *pItem, items)
1987 {
1988 /* Skip non-running machines: */
1989 if (!UIVirtualMachineItem::isItemRunning(pItem))
1990 continue;
1991 /* Skip session failures: */
1992 CSession session = uiCommon().openExistingSession(pItem->id());
1993 if (session.isNull())
1994 continue;
1995 /* Skip console failures: */
1996 CConsole console = session.GetConsole();
1997 if (console.isNull())
1998 {
1999 /* Do not forget to release machine: */
2000 session.UnlockMachine();
2001 continue;
2002 }
2003 /* Is the guest entered ACPI mode? */
2004 bool fGuestEnteredACPIMode = console.GetGuestEnteredACPIMode();
2005 /* Do not forget to release machine: */
2006 session.UnlockMachine();
2007 /* True if the guest entered ACPI mode: */
2008 if (fGuestEnteredACPIMode)
2009 return true;
2010 }
2011 /* False by default: */
2012 return false;
2013}
2014
2015/* static */
2016bool UIVirtualBoxManager::isAtLeastOneItemSupportsShortcuts(const QList<UIVirtualMachineItem*> &items)
2017{
2018 foreach (UIVirtualMachineItem *pItem, items)
2019 {
2020 if ( pItem->accessible()
2021#ifdef VBOX_WS_MAC
2022 /* On Mac OS X this are real alias files, which don't work with the old legacy xml files. */
2023 && pItem->settingsFile().endsWith(".vbox", Qt::CaseInsensitive)
2024#endif
2025 )
2026 return true;
2027 }
2028 return false;
2029}
2030
2031/* static */
2032bool UIVirtualBoxManager::isAtLeastOneItemAccessible(const QList<UIVirtualMachineItem*> &items)
2033{
2034 foreach (UIVirtualMachineItem *pItem, items)
2035 if (pItem->accessible())
2036 return true;
2037 return false;
2038}
2039
2040/* static */
2041bool UIVirtualBoxManager::isAtLeastOneItemInaccessible(const QList<UIVirtualMachineItem*> &items)
2042{
2043 foreach (UIVirtualMachineItem *pItem, items)
2044 if (!pItem->accessible())
2045 return true;
2046 return false;
2047}
2048
2049/* static */
2050bool UIVirtualBoxManager::isAtLeastOneItemRemovable(const QList<UIVirtualMachineItem*> &items)
2051{
2052 foreach (UIVirtualMachineItem *pItem, items)
2053 if (!pItem->accessible() || UIVirtualMachineItem::isItemEditable(pItem))
2054 return true;
2055 return false;
2056}
2057
2058/* static */
2059bool UIVirtualBoxManager::isAtLeastOneItemCanBeStarted(const QList<UIVirtualMachineItem*> &items)
2060{
2061 foreach (UIVirtualMachineItem *pItem, items)
2062 {
2063 if (UIVirtualMachineItem::isItemPoweredOff(pItem) && UIVirtualMachineItem::isItemEditable(pItem))
2064 return true;
2065 }
2066 return false;
2067}
2068
2069/* static */
2070bool UIVirtualBoxManager::isAtLeastOneItemCanBeShown(const QList<UIVirtualMachineItem*> &items)
2071{
2072 foreach (UIVirtualMachineItem *pItem, items)
2073 {
2074 if (UIVirtualMachineItem::isItemStarted(pItem) && (pItem->canSwitchTo() || UIVirtualMachineItem::isItemRunningHeadless(pItem)))
2075 return true;
2076 }
2077 return false;
2078}
2079
2080/* static */
2081bool UIVirtualBoxManager::isAtLeastOneItemCanBeStartedOrShown(const QList<UIVirtualMachineItem*> &items)
2082{
2083 foreach (UIVirtualMachineItem *pItem, items)
2084 {
2085 if ((UIVirtualMachineItem::isItemPoweredOff(pItem) && UIVirtualMachineItem::isItemEditable(pItem)) ||
2086 (UIVirtualMachineItem::isItemStarted(pItem) && (pItem->canSwitchTo() || UIVirtualMachineItem::isItemRunningHeadless(pItem))))
2087 return true;
2088 }
2089 return false;
2090}
2091
2092/* static */
2093bool UIVirtualBoxManager::isAtLeastOneItemDiscardable(const QList<UIVirtualMachineItem*> &items)
2094{
2095 foreach (UIVirtualMachineItem *pItem, items)
2096 if (UIVirtualMachineItem::isItemSaved(pItem) && UIVirtualMachineItem::isItemEditable(pItem))
2097 return true;
2098 return false;
2099}
2100
2101/* static */
2102bool UIVirtualBoxManager::isAtLeastOneItemStarted(const QList<UIVirtualMachineItem*> &items)
2103{
2104 foreach (UIVirtualMachineItem *pItem, items)
2105 if (UIVirtualMachineItem::isItemStarted(pItem))
2106 return true;
2107 return false;
2108}
2109
2110/* static */
2111bool UIVirtualBoxManager::isAtLeastOneItemRunning(const QList<UIVirtualMachineItem*> &items)
2112{
2113 foreach (UIVirtualMachineItem *pItem, items)
2114 if (UIVirtualMachineItem::isItemRunning(pItem))
2115 return true;
2116 return false;
2117}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use