1
/* $Id: UISettingsDialogSpecific.cpp $ */
4
* VBox frontends: Qt GUI ("VirtualBox"):
5
* UISettingsDialogSpecific class implementation
9
* Copyright (C) 2006-2012 Oracle Corporation
11
* This file is part of VirtualBox Open Source Edition (OSE), as
12
* available from http://www.virtualbox.org. This file is free software;
13
* you can redistribute it and/or modify it under the terms of the GNU
14
* General Public License (GPL) as published by the Free Software
15
* Foundation, in version 2 as it comes in the "COPYING" file of the
16
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
21
#include <QStackedWidget>
24
#include <QWaitCondition>
28
#include "UISettingsDialogSpecific.h"
29
#include "UISettingsDefs.h"
30
#include "VBoxGlobal.h"
31
#include "UIMessageCenter.h"
32
#include "QIWidgetValidator.h"
33
#include "VBoxSettingsSelector.h"
34
#include "UIVirtualBoxEventHandler.h"
36
#include "UIGlobalSettingsGeneral.h"
37
#include "UIGlobalSettingsInput.h"
38
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
39
# include "UIGlobalSettingsUpdate.h"
40
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
41
#include "UIGlobalSettingsLanguage.h"
42
#include "UIGlobalSettingsDisplay.h"
43
#include "UIGlobalSettingsNetwork.h"
44
#include "UIGlobalSettingsExtension.h"
45
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
46
# include "UIGlobalSettingsProxy.h"
47
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
49
#include "UIMachineSettingsGeneral.h"
50
#include "UIMachineSettingsSystem.h"
51
#include "UIMachineSettingsDisplay.h"
52
#include "UIMachineSettingsStorage.h"
53
#include "UIMachineSettingsAudio.h"
54
#include "UIMachineSettingsNetwork.h"
55
#include "UIMachineSettingsSerial.h"
56
#include "UIMachineSettingsParallel.h"
57
#include "UIMachineSettingsUSB.h"
58
#include "UIMachineSettingsSF.h"
61
#include "CUSBController.h"
63
#if 0 /* Global USB filters are DISABLED now: */
64
# define ENABLE_GLOBAL_USB
65
#endif /* Global USB filters are DISABLED now: */
67
/* Settings page list: */
68
typedef QList<UISettingsPage*> UISettingsPageList;
69
typedef QMap<int, UISettingsPage*> UISettingsPageMap;
71
/* Serializer direction: */
72
enum UISettingsSerializeDirection
74
UISettingsSerializeDirection_Load,
75
UISettingsSerializeDirection_Save
78
/* QThread reimplementation for loading/saving settings in async mode: */
79
class UISettingsSerializer : public QThread
85
/* Signal to notify main GUI thread about process has been started: */
86
void sigNotifyAboutProcessStarted();
88
/* Signal to notify main GUI thread about some page was processed: */
89
void sigNotifyAboutPageProcessed(int iPageId);
91
/* Signal to notify main GUI thread about all pages were processed: */
92
void sigNotifyAboutPagesProcessed();
96
/* Settings serializer instance: */
97
static UISettingsSerializer* instance() { return m_pInstance; }
99
/* Settings serializer constructor: */
100
UISettingsSerializer(QObject *pParent, const QVariant &data, UISettingsSerializeDirection direction)
102
, m_direction(direction)
104
, m_fSavingComplete(m_direction == UISettingsSerializeDirection_Load)
105
, m_fAllowToDestroySerializer(m_direction == UISettingsSerializeDirection_Load)
106
, m_iIdOfHighPriorityPage(-1)
111
/* Connecting this signals: */
112
connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection);
113
connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection);
114
connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection);
115
/* Connecting parent signals: */
116
connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection);
117
connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection);
120
/* Settings serializer destructor: */
121
~UISettingsSerializer()
123
/* If serializer is being destructed by it's parent,
124
* thread could still be running, we have to wait
125
* for it to be finished! */
129
/* Clear instance: */
133
/* Set pages list: */
134
void setPageList(const UISettingsPageList &pageList)
136
for (int iPageIndex = 0; iPageIndex < pageList.size(); ++iPageIndex)
138
UISettingsPage *pPage = pageList[iPageIndex];
139
m_pages.insert(pPage->id(), pPage);
143
/* Raise priority of page: */
144
void raisePriorityOfPage(int iPageId)
146
/* If that page is not present or was processed already: */
147
if (!m_pages.contains(iPageId) || m_pages[iPageId]->processed())
149
/* We just ignoring that request: */
154
/* Else remember which page we should be processed next: */
155
m_iIdOfHighPriorityPage = iPageId;
159
/* Return current m_data content: */
160
QVariant& data() { return m_data; }
164
void start(Priority priority = InheritPriority)
166
/* Notify listeners about we are starting: */
167
emit sigNotifyAboutProcessStarted();
169
/* If serializer saves settings: */
170
if (m_direction == UISettingsSerializeDirection_Save)
172
/* We should update internal page cache first: */
173
for (int iPageIndex = 0; iPageIndex < m_pages.values().size(); ++iPageIndex)
174
m_pages.values()[iPageIndex]->putToCache();
177
/* Start async serializing thread: */
178
QThread::start(priority);
180
/* If serializer saves settings: */
181
if (m_direction == UISettingsSerializeDirection_Save)
183
/* We should block calling thread until all pages will be saved: */
184
while (!m_fSavingComplete)
186
/* Lock mutex initially: */
188
/* Perform idle-processing every 100ms,
189
* and waiting for direct wake up signal: */
190
m_condition.wait(&m_mutex, 100);
191
/* Process queued signals posted to GUI thread: */
192
qApp->processEvents();
193
/* Unlock mutex finally: */
196
m_fAllowToDestroySerializer = true;
202
/* Slot to handle the fact of some page was processed: */
203
void sltHandleProcessedPage(int iPageId)
205
/* If serializer loads settings: */
206
if (m_direction == UISettingsSerializeDirection_Load)
208
/* If such page present we should fetch internal page cache: */
209
if (m_pages.contains(iPageId))
211
UISettingsPage *pSettingsPage = m_pages[iPageId];
212
pSettingsPage->setValidatorBlocked(true);
213
pSettingsPage->getFromCache();
214
pSettingsPage->setValidatorBlocked(false);
219
/* Slot to handle the fact of all pages were processed: */
220
void sltHandleProcessedPages()
222
/* If serializer saves settings: */
223
if (m_direction == UISettingsSerializeDirection_Save)
225
/* We should flag GUI thread to unlock itself: */
226
if (!m_fSavingComplete)
227
m_fSavingComplete = true;
229
/* If serializer loads settings: */
232
/* We have to do initial validation finally: */
233
foreach (UISettingsPage *pPage, m_pages.values())
238
/* Slot to destroy serializer: */
239
void sltDestroySerializer()
241
/* If not yet all events were processed,
242
* we should postpone destruction for now: */
243
if (!m_fAllowToDestroySerializer)
244
QTimer::singleShot(0, this, SLOT(sltDestroySerializer()));
251
/* Settings processor: */
254
/* Initialize COM for other thread: */
255
COMBase::InitializeCOM(false);
257
/* Mark all the pages initially as NOT processed: */
258
QList<UISettingsPage*> pageList = m_pages.values();
259
for (int iPageNumber = 0; iPageNumber < pageList.size(); ++iPageNumber)
260
pageList[iPageNumber]->setProcessed(false);
262
/* Iterate over the all left settings pages: */
263
UISettingsPageMap pages(m_pages);
264
while (!pages.empty())
266
/* Get required page pointer, protect map by mutex while getting pointer: */
267
UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ?
268
pages[m_iIdOfHighPriorityPage] : *pages.begin();
269
/* Reset request of high priority: */
270
if (m_iIdOfHighPriorityPage != -1)
271
m_iIdOfHighPriorityPage = -1;
272
/* Process this page if its enabled: */
273
if (pPage->isEnabled())
275
if (m_direction == UISettingsSerializeDirection_Load)
276
pPage->loadToCacheFrom(m_data);
277
if (m_direction == UISettingsSerializeDirection_Save)
278
pPage->saveFromCacheTo(m_data);
280
/* Remember what page was processed: */
281
pPage->setProcessed(true);
282
/* Remove processed page from our map: */
283
pages.remove(pPage->id());
284
/* Notify listeners about page was processed: */
285
emit sigNotifyAboutPageProcessed(pPage->id());
286
/* If serializer saves settings => wake up GUI thread: */
287
if (m_direction == UISettingsSerializeDirection_Save)
288
m_condition.wakeAll();
289
/* Break further processing if page had failed: */
293
/* Notify listeners about all pages were processed: */
294
emit sigNotifyAboutPagesProcessed();
295
/* If serializer saves settings => wake up GUI thread: */
296
if (m_direction == UISettingsSerializeDirection_Save)
297
m_condition.wakeAll();
299
/* Deinitialize COM for other thread: */
300
COMBase::CleanupCOM();
304
UISettingsSerializeDirection m_direction;
306
UISettingsPageMap m_pages;
307
bool m_fSavingComplete;
308
bool m_fAllowToDestroySerializer;
309
int m_iIdOfHighPriorityPage;
311
QWaitCondition m_condition;
312
static UISettingsSerializer *m_pInstance;
315
UISettingsSerializer* UISettingsSerializer::m_pInstance = 0;
317
UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent)
318
: UISettingsDialog(pParent)
322
setWindowIcon(QIcon(":/global_settings_16px.png"));
323
#endif /* !Q_WS_MAC */
325
/* Assign default dialog type: */
326
setDialogType(SettingsDialogType_Offline);
328
/* Creating settings pages: */
329
CVirtualBox vbox = vboxGlobal().virtualBox();
330
QList<GlobalSettingsPageType> restrictedGlobalSettingsPages = vboxGlobal().restrictedGlobalSettingsPages(vbox);
331
for (int iPageIndex = GlobalSettingsPageType_General; iPageIndex < GlobalSettingsPageType_Max; ++iPageIndex)
333
/* Make sure page was not restricted: */
334
if (restrictedGlobalSettingsPages.contains(static_cast<GlobalSettingsPageType>(iPageIndex)))
337
/* Make sure page is available: */
338
if (isPageAvailable(iPageIndex))
340
UISettingsPage *pSettingsPage = 0;
344
case GlobalSettingsPageType_General:
346
pSettingsPage = new UIGlobalSettingsGeneral;
347
addItem(":/machine_32px.png", ":/machine_disabled_32px.png",
348
":/machine_16px.png", ":/machine_disabled_16px.png",
349
iPageIndex, "#general", pSettingsPage);
353
case GlobalSettingsPageType_Input:
355
pSettingsPage = new UIGlobalSettingsInput;
356
addItem(":/hostkey_32px.png", ":/hostkey_disabled_32px.png",
357
":/hostkey_16px.png", ":/hostkey_disabled_16px.png",
358
iPageIndex, "#input", pSettingsPage);
361
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
363
case GlobalSettingsPageType_Update:
365
pSettingsPage = new UIGlobalSettingsUpdate;
366
addItem(":/refresh_32px.png", ":/refresh_disabled_32px.png",
367
":/refresh_16px.png", ":/refresh_disabled_16px.png",
368
iPageIndex, "#update", pSettingsPage);
371
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
373
case GlobalSettingsPageType_Language:
375
pSettingsPage = new UIGlobalSettingsLanguage;
376
addItem(":/site_32px.png", ":/site_disabled_32px.png",
377
":/site_16px.png", ":/site_disabled_16px.png",
378
iPageIndex, "#language", pSettingsPage);
382
case GlobalSettingsPageType_Display:
384
pSettingsPage = new UIGlobalSettingsDisplay;
385
addItem(":/vrdp_32px.png", ":/vrdp_disabled_32px.png",
386
":/vrdp_16px.png", ":/vrdp_disabled_16px.png",
387
iPageIndex, "#display", pSettingsPage);
391
case GlobalSettingsPageType_Network:
393
pSettingsPage = new UIGlobalSettingsNetwork;
394
addItem(":/nw_32px.png", ":/nw_disabled_32px.png",
395
":/nw_16px.png", ":/nw_disabled_16px.png",
396
iPageIndex, "#network", pSettingsPage);
399
/* Extensions page: */
400
case GlobalSettingsPageType_Extensions:
402
pSettingsPage = new UIGlobalSettingsExtension;
403
addItem(":/extension_pack_32px.png", ":/extension_pack_disabled_32px.png",
404
":/extension_pack_16px.png", ":/extension_pack_disabled_16px.png",
405
iPageIndex, "#extensions", pSettingsPage);
408
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
410
case GlobalSettingsPageType_Proxy:
412
pSettingsPage = new UIGlobalSettingsProxy;
413
addItem(":/proxy_32px.png", ":/proxy_disabled_32px.png",
414
":/proxy_16px.png", ":/proxy_disabled_16px.png",
415
iPageIndex, "#proxy", pSettingsPage);
418
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
423
pSettingsPage->setDialogType(dialogType());
427
/* Retranslate UI: */
430
/* Choose first item by default: */
431
m_pSelector->selectById(GlobalSettingsPageType_General);
434
UISettingsDialogGlobal::~UISettingsDialogGlobal()
436
/* Delete serializer early if exists: */
437
if (UISettingsSerializer::instance())
438
delete UISettingsSerializer::instance();
441
void UISettingsDialogGlobal::loadData()
443
/* Call for base-class: */
444
UISettingsDialog::loadData();
446
/* Prepare global data: */
447
qRegisterMetaType<UISettingsDataGlobal>();
448
UISettingsDataGlobal data(vboxGlobal().virtualBox().GetSystemProperties(), vboxGlobal().settings());
449
/* Create global settings loader,
450
* it will load global settings & delete itself in the appropriate time: */
451
UISettingsSerializer *pGlobalSettingsLoader = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Load);
452
connect(pGlobalSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded()));
453
/* Set pages to be loaded: */
454
pGlobalSettingsLoader->setPageList(m_pSelector->settingPages());
456
pGlobalSettingsLoader->start();
459
void UISettingsDialogGlobal::saveData()
461
/* Call for base-class: */
462
UISettingsDialog::saveData();
464
/* Get properties and settings: */
465
CSystemProperties properties = vboxGlobal().virtualBox().GetSystemProperties();
466
VBoxGlobalSettings settings = vboxGlobal().settings();
467
/* Prepare global data: */
468
qRegisterMetaType<UISettingsDataGlobal>();
469
UISettingsDataGlobal data(properties, settings);
470
/* Create global settings saver,
471
* it will save global settings & delete itself in the appropriate time: */
472
UISettingsSerializer *pGlobalSettingsSaver = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Save);
473
/* Set pages to be saved: */
474
pGlobalSettingsSaver->setPageList(m_pSelector->settingPages());
476
pGlobalSettingsSaver->start();
478
/* Get updated properties & settings: */
479
CSystemProperties newProperties = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_properties;
480
VBoxGlobalSettings newSettings = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_settings;
481
/* If properties are not OK => show the error: */
482
if (!newProperties.isOk())
483
msgCenter().cannotSetSystemProperties(newProperties, this);
484
/* Else save the new settings if they were changed: */
485
else if (!(newSettings == settings))
486
vboxGlobal().setSettings(newSettings);
488
/* Mark page processed: */
492
void UISettingsDialogGlobal::retranslateUi()
495
m_pSelector->setItemText(GlobalSettingsPageType_General, tr("General"));
498
m_pSelector->setItemText(GlobalSettingsPageType_Input, tr("Input"));
500
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
502
m_pSelector->setItemText(GlobalSettingsPageType_Update, tr("Update"));
503
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
506
m_pSelector->setItemText(GlobalSettingsPageType_Language, tr("Language"));
509
m_pSelector->setItemText(GlobalSettingsPageType_Display, tr("Display"));
512
m_pSelector->setItemText(GlobalSettingsPageType_Network, tr("Network"));
514
/* Extension page: */
515
m_pSelector->setItemText(GlobalSettingsPageType_Extensions, tr("Extensions"));
517
#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
519
m_pSelector->setItemText(GlobalSettingsPageType_Proxy, tr("Proxy"));
520
#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
522
/* Polish the selector: */
523
m_pSelector->polish();
525
/* Base-class UI translation: */
526
UISettingsDialog::retranslateUi();
528
/* Set dialog's name: */
529
setWindowTitle(title());
532
QString UISettingsDialogGlobal::title() const
534
return tr("VirtualBox - %1").arg(titleExtension());
537
bool UISettingsDialogGlobal::isPageAvailable(int iPageId)
541
case GlobalSettingsPageType_Network:
543
#ifndef VBOX_WITH_NETFLT
545
#endif /* !VBOX_WITH_NETFLT */
554
UISettingsDialogMachine::UISettingsDialogMachine(QWidget *pParent, const QString &strMachineId,
555
const QString &strCategory, const QString &strControl)
556
: UISettingsDialog(pParent)
557
, m_strMachineId(strMachineId)
558
, m_fAllowResetFirstRunFlag(false)
559
, m_fResetFirstRunFlag(false)
563
setWindowIcon(QIcon(":/vm_settings_16px.png"));
564
#endif /* Q_WS_MAC */
566
/* Allow to reset first-run flag just when medium enumeration was finished: */
567
connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished()), this, SLOT(sltAllowResetFirstRunFlag()));
569
/* Get corresponding machine (required to determine dialog type and page availability): */
570
m_machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId);
571
AssertMsg(!m_machine.isNull(), ("Can't find corresponding machine!\n"));
572
m_sessionState = m_machine.GetSessionState();
573
m_machineState = m_machine.GetState();
574
/* Recalculate current dialog-type: */
577
/* Creating settings pages: */
578
QList<MachineSettingsPageType> restrictedMachineSettingsPages = vboxGlobal().restrictedMachineSettingsPages(m_machine);
579
for (int iPageIndex = MachineSettingsPageType_General; iPageIndex < MachineSettingsPageType_Max; ++iPageIndex)
581
/* Make sure page was not restricted: */
582
if (restrictedMachineSettingsPages.contains(static_cast<MachineSettingsPageType>(iPageIndex)))
585
/* Make sure page is available: */
586
if (isPageAvailable(iPageIndex))
588
UISettingsPage *pSettingsPage = 0;
592
case MachineSettingsPageType_General:
594
pSettingsPage = new UIMachineSettingsGeneral;
595
addItem(":/machine_32px.png", ":/machine_disabled_32px.png",
596
":/machine_16px.png", ":/machine_disabled_16px.png",
597
iPageIndex, "#general", pSettingsPage);
601
case MachineSettingsPageType_System:
603
pSettingsPage = new UIMachineSettingsSystem;
604
addItem(":/chipset_32px.png", ":/chipset_disabled_32px.png",
605
":/chipset_16px.png", ":/chipset_disabled_16px.png",
606
iPageIndex, "#system", pSettingsPage);
610
case MachineSettingsPageType_Display:
612
pSettingsPage = new UIMachineSettingsDisplay;
613
addItem(":/vrdp_32px.png", ":/vrdp_disabled_32px.png",
614
":/vrdp_16px.png", ":/vrdp_disabled_16px.png",
615
iPageIndex, "#display", pSettingsPage);
619
case MachineSettingsPageType_Storage:
621
pSettingsPage = new UIMachineSettingsStorage;
622
connect(pSettingsPage, SIGNAL(storageChanged()), this, SLOT(sltResetFirstRunFlag()));
623
addItem(":/hd_32px.png", ":/hd_disabled_32px.png",
624
":/hd_16px.png", ":/hd_disabled_16px.png",
625
iPageIndex, "#storage", pSettingsPage);
629
case MachineSettingsPageType_Audio:
631
pSettingsPage = new UIMachineSettingsAudio;
632
addItem(":/sound_32px.png", ":/sound_disabled_32px.png",
633
":/sound_16px.png", ":/sound_disabled_16px.png",
634
iPageIndex, "#audio", pSettingsPage);
638
case MachineSettingsPageType_Network:
640
pSettingsPage = new UIMachineSettingsNetworkPage;
641
addItem(":/nw_32px.png", ":/nw_disabled_32px.png",
642
":/nw_16px.png", ":/nw_disabled_16px.png",
643
iPageIndex, "#network", pSettingsPage);
647
case MachineSettingsPageType_Ports:
649
addItem(":/serial_port_32px.png", ":/serial_port_disabled_32px.png",
650
":/serial_port_16px.png", ":/serial_port_disabled_16px.png",
651
iPageIndex, "#ports");
655
case MachineSettingsPageType_Serial:
657
pSettingsPage = new UIMachineSettingsSerialPage;
658
addItem(":/serial_port_32px.png", ":/serial_port_disabled_32px.png",
659
":/serial_port_16px.png", ":/serial_port_disabled_16px.png",
660
iPageIndex, "#serialPorts", pSettingsPage, MachineSettingsPageType_Ports);
664
case MachineSettingsPageType_Parallel:
666
pSettingsPage = new UIMachineSettingsParallelPage;
667
addItem(":/parallel_port_32px.png", ":/parallel_port_disabled_32px.png",
668
":/parallel_port_16px.png", ":/parallel_port_disabled_16px.png",
669
iPageIndex, "#parallelPorts", pSettingsPage, MachineSettingsPageType_Ports);
673
case MachineSettingsPageType_USB:
675
pSettingsPage = new UIMachineSettingsUSB;
676
addItem(":/usb_32px.png", ":/usb_disabled_32px.png",
677
":/usb_16px.png", ":/usb_disabled_16px.png",
678
iPageIndex, "#usb", pSettingsPage, MachineSettingsPageType_Ports);
681
/* Shared Folders page: */
682
case MachineSettingsPageType_SF:
684
pSettingsPage = new UIMachineSettingsSF;
685
addItem(":/sf_32px.png", ":/sf_disabled_32px.png",
686
":/sf_16px.png", ":/sf_disabled_16px.png",
687
iPageIndex, "#sharedFolders", pSettingsPage);
694
pSettingsPage->setDialogType(dialogType());
698
/* Retranslate UI: */
701
/* Setup settings window: */
702
if (!strCategory.isNull())
704
m_pSelector->selectByLink(strCategory);
705
/* Search for a widget with the given name: */
706
if (!strControl.isNull())
708
if (QWidget *pWidget = m_pStack->currentWidget()->findChild<QWidget*>(strControl))
710
QList<QWidget*> parents;
711
QWidget *pParentWidget = pWidget;
712
while ((pParentWidget = pParentWidget->parentWidget()) != 0)
714
if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget))
716
/* The tab contents widget is two steps down
717
* (QTabWidget -> QStackedWidget -> QWidget): */
718
QWidget *pTabPage = parents[parents.count() - 1];
720
pTabPage = parents[parents.count() - 2];
722
pTabWidget->setCurrentWidget(pTabPage);
724
parents.append(pParentWidget);
730
/* First item as default: */
732
m_pSelector->selectById(MachineSettingsPageType_General);
735
UISettingsDialogMachine::~UISettingsDialogMachine()
737
/* Delete serializer early if exists: */
738
if (UISettingsSerializer::instance())
739
delete UISettingsSerializer::instance();
742
void UISettingsDialogMachine::loadData()
744
/* Check that session is NOT created: */
745
if (!m_session.isNull())
748
/* Call for base-class: */
749
UISettingsDialog::loadData();
751
/* Disconnect global VBox events from this dialog: */
752
gVBoxEvents->disconnect(this);
754
/* Prepare session: */
755
m_session = dialogType() == SettingsDialogType_Wrong ? CSession() : vboxGlobal().openExistingSession(m_strMachineId);
756
/* Check that session was created: */
757
if (m_session.isNull())
760
/* Get machine from session: */
761
m_machine = m_session.GetMachine();
762
/* Get console from session: */
763
m_console = dialogType() == SettingsDialogType_Offline ? CConsole() : m_session.GetConsole();
765
/* Prepare machine data: */
766
qRegisterMetaType<UISettingsDataMachine>();
767
UISettingsDataMachine data(m_machine, m_console);
768
/* Create machine settings loader,
769
* it will load machine settings & delete itself in the appropriate time: */
770
UISettingsSerializer *pMachineSettingsLoader = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Load);
771
connect(pMachineSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded()));
772
connect(pMachineSettingsLoader, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltSetFirstRunFlag()));
773
/* Set pages to be loaded: */
774
pMachineSettingsLoader->setPageList(m_pSelector->settingPages());
775
/* Ask to raise required page priority: */
776
pMachineSettingsLoader->raisePriorityOfPage(m_pSelector->currentId());
777
/* Start page loader: */
778
pMachineSettingsLoader->start();
781
void UISettingsDialogMachine::saveData()
783
/* Check that session is NOT created: */
784
if (!m_session.isNull())
787
/* Call for base-class: */
788
UISettingsDialog::saveData();
790
/* Disconnect global VBox events from this dialog: */
791
gVBoxEvents->disconnect(this);
793
/* Prepare session: */
794
if (dialogType() == SettingsDialogType_Wrong)
795
m_session = CSession();
796
else if (dialogType() != SettingsDialogType_Offline)
797
m_session = vboxGlobal().openExistingSession(m_strMachineId);
799
m_session = vboxGlobal().openSession(m_strMachineId);
800
/* Check that session was created: */
801
if (m_session.isNull())
804
/* Get machine from session: */
805
m_machine = m_session.GetMachine();
806
/* Get console from session: */
807
m_console = dialogType() == SettingsDialogType_Offline ? CConsole() : m_session.GetConsole();
809
/* Prepare machine data: */
810
qRegisterMetaType<UISettingsDataMachine>();
811
UISettingsDataMachine data(m_machine, m_console);
812
/* Create machine settings saver,
813
* it will save machine settings & delete itself in the appropriate time: */
814
UISettingsSerializer *pMachineSettingsSaver = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Save);
815
/* Set pages to be saved: */
816
pMachineSettingsSaver->setPageList(m_pSelector->settingPages());
818
pMachineSettingsSaver->start();
820
/* Get updated machine: */
821
m_machine = pMachineSettingsSaver->data().value<UISettingsDataMachine>().m_machine;
822
/* If machine is ok => perform final operations: */
823
if (m_machine.isOk())
825
/* Guest OS type & VT-x/AMD-V option correlation auto-fix: */
826
UIMachineSettingsGeneral *pGeneralPage =
827
qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General));
828
UIMachineSettingsSystem *pSystemPage =
829
qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System));
830
if (pGeneralPage && pSystemPage &&
831
pGeneralPage->is64BitOSTypeSelected() && !pSystemPage->isHWVirtExEnabled())
832
m_machine.SetHWVirtExProperty(KHWVirtExPropertyType_Enabled, true);
834
#ifdef VBOX_WITH_VIDEOHWACCEL
835
/* Disable 2D Video Acceleration for non-Windows guests: */
836
if (pGeneralPage && !pGeneralPage->isWindowsOSTypeSelected())
838
UIMachineSettingsDisplay *pDisplayPage =
839
qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display));
840
if (pDisplayPage && pDisplayPage->isAcceleration2DVideoSelected())
841
m_machine.SetAccelerate2DVideoEnabled(false);
843
#endif /* VBOX_WITH_VIDEOHWACCEL */
845
/* Enable OHCI controller if HID is enabled: */
846
if (pSystemPage && pSystemPage->isHIDEnabled())
848
ULONG cOhciCtls = m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI);
850
m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI);
853
/* Clear the "GUI_FirstRun" extra data key in case if
854
* the boot order or disk configuration were changed: */
855
if (m_fResetFirstRunFlag)
856
m_machine.SetExtraData(GUI_FirstRun, QString::null);
858
/* Save settings finally: */
859
m_machine.SaveSettings();
862
/* If machine is NOT ok => show the error message: */
863
if (!m_machine.isOk())
864
msgCenter().cannotSaveMachineSettings(m_machine, this);
866
/* Mark page processed: */
870
void UISettingsDialogMachine::retranslateUi()
872
/* We have to make sure that the Network, Serial & Parallel pages are retranslated
873
* before they are revalidated. Cause: They do string comparing within
874
* vboxGlobal which is retranslated at that point already: */
875
QEvent event(QEvent::LanguageChange);
876
if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Network))
877
qApp->sendEvent(pPage, &event);
878
if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Serial))
879
qApp->sendEvent(pPage, &event);
880
if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Parallel))
881
qApp->sendEvent(pPage, &event);
884
m_pSelector->setItemText(MachineSettingsPageType_General, tr("General"));
887
m_pSelector->setItemText(MachineSettingsPageType_System, tr("System"));
890
m_pSelector->setItemText(MachineSettingsPageType_Display, tr("Display"));
893
m_pSelector->setItemText(MachineSettingsPageType_Storage, tr("Storage"));
896
m_pSelector->setItemText(MachineSettingsPageType_Audio, tr("Audio"));
899
m_pSelector->setItemText(MachineSettingsPageType_Network, tr("Network"));
902
m_pSelector->setItemText(MachineSettingsPageType_Ports, tr("Ports"));
905
m_pSelector->setItemText(MachineSettingsPageType_Serial, tr("Serial Ports"));
908
m_pSelector->setItemText(MachineSettingsPageType_Parallel, tr("Parallel Ports"));
911
m_pSelector->setItemText(MachineSettingsPageType_USB, tr("USB"));
914
m_pSelector->setItemText(MachineSettingsPageType_SF, tr("Shared Folders"));
916
/* Polish the selector: */
917
m_pSelector->polish();
919
/* Base-class UI translation: */
920
UISettingsDialog::retranslateUi();
922
/* Set dialog's name: */
923
setWindowTitle(title());
926
QString UISettingsDialogMachine::title() const
928
QString strDialogTitle;
929
/* Get corresponding machine (required to compose dialog title): */
930
const CMachine &machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId);
931
if (!machine.isNull())
932
strDialogTitle = tr("%1 - %2").arg(machine.GetName()).arg(titleExtension());
933
return strDialogTitle;
936
void UISettingsDialogMachine::recorrelate(UISettingsPage *pSettingsPage)
938
switch (pSettingsPage->id())
940
/* General page correlations: */
941
case MachineSettingsPageType_General:
943
/* Make changes on 'general' page influent 'display' page: */
944
UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(pSettingsPage);
945
UIMachineSettingsDisplay *pDisplayPage = qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display));
946
if (pGeneralPage && pDisplayPage)
947
pDisplayPage->setGuestOSType(pGeneralPage->guestOSType());
950
/* System page correlations: */
951
case MachineSettingsPageType_System:
953
/* Make changes on 'system' page influent 'general' and 'storage' page: */
954
UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(pSettingsPage);
955
UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General));
956
UIMachineSettingsStorage *pStoragePage = qobject_cast<UIMachineSettingsStorage*>(m_pSelector->idToPage(MachineSettingsPageType_Storage));
960
pGeneralPage->setHWVirtExEnabled(pSystemPage->isHWVirtExEnabled());
962
pStoragePage->setChipsetType(pSystemPage->chipsetType());
966
/* USB page correlations: */
967
case MachineSettingsPageType_USB:
969
/* Make changes on 'usb' page influent 'system' page: */
970
UIMachineSettingsUSB *pUsbPage = qobject_cast<UIMachineSettingsUSB*>(pSettingsPage);
971
UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System));
972
if (pUsbPage && pSystemPage)
973
pSystemPage->setOHCIEnabled(pUsbPage->isOHCIEnabled());
981
void UISettingsDialogMachine::sltMarkLoaded()
983
/* Call for base-class: */
984
UISettingsDialog::sltMarkLoaded();
986
/* Unlock the session if exists: */
987
if (!m_session.isNull())
989
m_session.UnlockMachine();
990
m_session = CSession();
991
m_machine = CMachine();
992
m_console = CConsole();
995
/* Make sure settings window will be updated on machine state/data changes: */
996
connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)),
997
this, SLOT(sltSessionStateChanged(QString, KSessionState)));
998
connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)),
999
this, SLOT(sltMachineStateChanged(QString, KMachineState)));
1000
connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)),
1001
this, SLOT(sltMachineDataChanged(QString)));
1004
void UISettingsDialogMachine::sltMarkSaved()
1006
/* Call for base-class: */
1007
UISettingsDialog::sltMarkSaved();
1009
/* Unlock the session if exists: */
1010
if (!m_session.isNull())
1012
m_session.UnlockMachine();
1013
m_session = CSession();
1014
m_machine = CMachine();
1015
m_console = CConsole();
1019
void UISettingsDialogMachine::sltSessionStateChanged(QString strMachineId, KSessionState sessionState)
1021
/* Ignore if thats NOT our VM: */
1022
if (strMachineId != m_strMachineId)
1025
/* Ignore if state was NOT actually changed: */
1026
if (m_sessionState == sessionState)
1029
/* Update current session state: */
1030
m_sessionState = sessionState;
1032
/* Update dialog-type if necessary: */
1036
void UISettingsDialogMachine::sltMachineStateChanged(QString strMachineId, KMachineState machineState)
1038
/* Ignore if thats NOT our VM: */
1039
if (strMachineId != m_strMachineId)
1042
/* Ignore if state was NOT actually changed: */
1043
if (m_machineState == machineState)
1046
/* Update current machine state: */
1047
m_machineState = machineState;
1049
/* Update dialog-type if necessary: */
1053
void UISettingsDialogMachine::sltMachineDataChanged(QString strMachineId)
1055
/* Ignore if thats NOT our VM: */
1056
if (strMachineId != m_strMachineId)
1059
/* Check if user had changed something and warn him about he will loose settings on reloading: */
1060
if (isSettingsChanged() && !msgCenter().confirmSettingsReloading(this))
1067
void UISettingsDialogMachine::sltCategoryChanged(int cId)
1069
if (UISettingsSerializer::instance())
1070
UISettingsSerializer::instance()->raisePriorityOfPage(cId);
1072
UISettingsDialog::sltCategoryChanged(cId);
1075
void UISettingsDialogMachine::sltAllowResetFirstRunFlag()
1077
m_fAllowResetFirstRunFlag = true;
1080
void UISettingsDialogMachine::sltSetFirstRunFlag()
1082
m_fResetFirstRunFlag = false;
1085
void UISettingsDialogMachine::sltResetFirstRunFlag()
1087
if (m_fAllowResetFirstRunFlag)
1088
m_fResetFirstRunFlag = true;
1091
bool UISettingsDialogMachine::isPageAvailable(int iPageId)
1093
if (m_machine.isNull())
1098
case MachineSettingsPageType_Serial:
1100
/* Depends on ports availability: */
1101
if (!isPageAvailable(MachineSettingsPageType_Ports))
1105
case MachineSettingsPageType_Parallel:
1107
/* Depends on ports availability: */
1108
if (!isPageAvailable(MachineSettingsPageType_Ports))
1110
/* But for now this page is always disabled: */
1113
case MachineSettingsPageType_USB:
1115
/* Depends on ports availability: */
1116
if (!isPageAvailable(MachineSettingsPageType_Ports))
1118
/* Check if USB is implemented: */
1119
if (!m_machine.GetUSBProxyAvailable())
1121
/* Get the USB controller object: */
1122
CUSBControllerVector controllerColl = m_machine.GetUSBControllers();
1123
/* Show the machine error message if any: */
1124
if ( !m_machine.isReallyOk()
1125
&& controllerColl.size() > 0
1126
&& m_machine.GetUSBControllerCountByType(KUSBControllerType_OHCI))
1127
msgCenter().warnAboutUnaccessibleUSB(m_machine, parentWidget());
1136
bool UISettingsDialogMachine::isSettingsChanged()
1138
bool fIsSettingsChanged = false;
1139
foreach (UISettingsPage *pPage, m_pSelector->settingPages())
1141
pPage->putToCache();
1142
if (!fIsSettingsChanged && pPage->changed())
1143
fIsSettingsChanged = true;
1145
return fIsSettingsChanged;
1148
void UISettingsDialogMachine::updateDialogType()
1150
/* Get new dialog type: */
1151
SettingsDialogType newDialogType = determineSettingsDialogType(m_sessionState, m_machineState);
1153
/* Ignore if dialog type was NOT actually changed: */
1154
if (dialogType() == newDialogType)
1157
/* Should we show a warning about leaving 'offline' state? */
1158
bool fShouldWe = dialogType() == SettingsDialogType_Offline;
1160
/* Update current dialog type: */
1161
setDialogType(newDialogType);
1163
/* Show a warning about leaving 'offline' state if we should: */
1164
if (isSettingsChanged() && fShouldWe)
1165
msgCenter().warnAboutStateChange(this);
1168
# include "UISettingsDialogSpecific.moc"