VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp@ 43138

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

FE/Qt: VM settings stuff: More precise way to distinguish between offline/online settings dialog types.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 41.4 KB
Line 
1/* $Id: UISettingsDialogSpecific.cpp 43128 2012-08-30 19:30:59Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UISettingsDialogSpecific class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2011 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Qt includes: */
21#include <QStackedWidget>
22#include <QThread>
23#include <QMutex>
24#include <QWaitCondition>
25#include <QTimer>
26
27/* GUI includes: */
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"
35
36#include "UIGlobalSettingsGeneral.h"
37#include "UIGlobalSettingsInput.h"
38#include "UIGlobalSettingsUpdate.h"
39#include "UIGlobalSettingsLanguage.h"
40#include "UIGlobalSettingsDisplay.h"
41#include "UIGlobalSettingsNetwork.h"
42#include "UIGlobalSettingsExtension.h"
43#include "UIGlobalSettingsProxy.h"
44
45#include "UIMachineSettingsGeneral.h"
46#include "UIMachineSettingsSystem.h"
47#include "UIMachineSettingsDisplay.h"
48#include "UIMachineSettingsStorage.h"
49#include "UIMachineSettingsAudio.h"
50#include "UIMachineSettingsNetwork.h"
51#include "UIMachineSettingsSerial.h"
52#include "UIMachineSettingsParallel.h"
53#include "UIMachineSettingsUSB.h"
54#include "UIMachineSettingsSF.h"
55
56/* COM includes: */
57#include "CUSBController.h"
58
59#if 0 /* Global USB filters are DISABLED now: */
60# define ENABLE_GLOBAL_USB
61#endif /* Global USB filters are DISABLED now: */
62
63/* Settings page list: */
64typedef QList<UISettingsPage*> UISettingsPageList;
65typedef QMap<int, UISettingsPage*> UISettingsPageMap;
66
67/* Serializer direction: */
68enum UISettingsSerializeDirection
69{
70 UISettingsSerializeDirection_Load,
71 UISettingsSerializeDirection_Save
72};
73
74/* QThread reimplementation for loading/saving settings in async mode: */
75class UISettingsSerializer : public QThread
76{
77 Q_OBJECT;
78
79signals:
80
81 /* Signal to notify main GUI thread about process has been started: */
82 void sigNotifyAboutProcessStarted();
83
84 /* Signal to notify main GUI thread about some page was processed: */
85 void sigNotifyAboutPageProcessed(int iPageId);
86
87 /* Signal to notify main GUI thread about all pages were processed: */
88 void sigNotifyAboutPagesProcessed();
89
90public:
91
92 /* Settings serializer instance: */
93 static UISettingsSerializer* instance() { return m_pInstance; }
94
95 /* Settings serializer constructor: */
96 UISettingsSerializer(QObject *pParent, const QVariant &data, UISettingsSerializeDirection direction)
97 : QThread(pParent)
98 , m_direction(direction)
99 , m_data(data)
100 , m_fSavingComplete(m_direction == UISettingsSerializeDirection_Load)
101 , m_fAllowToDestroySerializer(m_direction == UISettingsSerializeDirection_Load)
102 , m_iIdOfHighPriorityPage(-1)
103 {
104 /* Set instance: */
105 m_pInstance = this;
106
107 /* Connecting this signals: */
108 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection);
109 connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection);
110 connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection);
111 /* Connecting parent signals: */
112 connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection);
113 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection);
114 }
115
116 /* Settings serializer destructor: */
117 ~UISettingsSerializer()
118 {
119 /* If serializer is being destructed by it's parent,
120 * thread could still be running, we have to wait
121 * for it to be finished! */
122 if (isRunning())
123 wait();
124
125 /* Clear instance: */
126 m_pInstance = 0;
127 }
128
129 /* Set pages list: */
130 void setPageList(const UISettingsPageList &pageList)
131 {
132 for (int iPageIndex = 0; iPageIndex < pageList.size(); ++iPageIndex)
133 {
134 UISettingsPage *pPage = pageList[iPageIndex];
135 m_pages.insert(pPage->id(), pPage);
136 }
137 }
138
139 /* Raise priority of page: */
140 void raisePriorityOfPage(int iPageId)
141 {
142 /* If that page is not present or was processed already: */
143 if (!m_pages.contains(iPageId) || m_pages[iPageId]->processed())
144 {
145 /* We just ignoring that request: */
146 return;
147 }
148 else
149 {
150 /* Else remember which page we should be processed next: */
151 m_iIdOfHighPriorityPage = iPageId;
152 }
153 }
154
155 /* Return current m_data content: */
156 QVariant& data() { return m_data; }
157
158public slots:
159
160 void start(Priority priority = InheritPriority)
161 {
162 /* Notify listeners about we are starting: */
163 emit sigNotifyAboutProcessStarted();
164
165 /* If serializer saves settings: */
166 if (m_direction == UISettingsSerializeDirection_Save)
167 {
168 /* We should update internal page cache first: */
169 for (int iPageIndex = 0; iPageIndex < m_pages.values().size(); ++iPageIndex)
170 m_pages.values()[iPageIndex]->putToCache();
171 }
172
173 /* Start async serializing thread: */
174 QThread::start(priority);
175
176 /* If serializer saves settings: */
177 if (m_direction == UISettingsSerializeDirection_Save)
178 {
179 /* We should block calling thread until all pages will be saved: */
180 while (!m_fSavingComplete)
181 {
182 /* Lock mutex initially: */
183 m_mutex.lock();
184 /* Perform idle-processing every 100ms,
185 * and waiting for direct wake up signal: */
186 m_condition.wait(&m_mutex, 100);
187 /* Process queued signals posted to GUI thread: */
188 qApp->processEvents();
189 /* Unlock mutex finally: */
190 m_mutex.unlock();
191 }
192 m_fAllowToDestroySerializer = true;
193 }
194 }
195
196protected slots:
197
198 /* Slot to handle the fact of some page was processed: */
199 void sltHandleProcessedPage(int iPageId)
200 {
201 /* If serializer loads settings: */
202 if (m_direction == UISettingsSerializeDirection_Load)
203 {
204 /* If such page present we should fetch internal page cache: */
205 if (m_pages.contains(iPageId))
206 m_pages[iPageId]->getFromCache();
207 }
208 }
209
210 /* Slot to handle the fact of all pages were processed: */
211 void sltHandleProcessedPages()
212 {
213 /* If serializer saves settings: */
214 if (m_direction == UISettingsSerializeDirection_Save)
215 {
216 /* We should flag GUI thread to unlock itself: */
217 if (!m_fSavingComplete)
218 m_fSavingComplete = true;
219 }
220 }
221
222 /* Slot to destroy serializer: */
223 void sltDestroySerializer()
224 {
225 /* If not yet all events were processed,
226 * we should postpone destruction for now: */
227 if (!m_fAllowToDestroySerializer)
228 QTimer::singleShot(0, this, SLOT(sltDestroySerializer()));
229 else
230 deleteLater();
231 }
232
233protected:
234
235 /* Settings processor: */
236 void run()
237 {
238 /* Mark all the pages initially as NOT processed: */
239 QList<UISettingsPage*> pageList = m_pages.values();
240 for (int iPageNumber = 0; iPageNumber < pageList.size(); ++iPageNumber)
241 pageList[iPageNumber]->setProcessed(false);
242
243 /* Iterate over the all left settings pages: */
244 UISettingsPageMap pages(m_pages);
245 while (!pages.empty())
246 {
247 /* Get required page pointer, protect map by mutex while getting pointer: */
248 UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ?
249 pages[m_iIdOfHighPriorityPage] : *pages.begin();
250 /* Reset request of high priority: */
251 if (m_iIdOfHighPriorityPage != -1)
252 m_iIdOfHighPriorityPage = -1;
253 /* Process this page if its enabled: */
254 if (pPage->isEnabled())
255 {
256 if (m_direction == UISettingsSerializeDirection_Load)
257 pPage->loadToCacheFrom(m_data);
258 if (m_direction == UISettingsSerializeDirection_Save)
259 pPage->saveFromCacheTo(m_data);
260 }
261 /* Remember what page was processed: */
262 pPage->setProcessed(true);
263 /* Remove processed page from our map: */
264 pages.remove(pPage->id());
265 /* Notify listeners about page was processed: */
266 emit sigNotifyAboutPageProcessed(pPage->id());
267 /* If serializer saves settings => wake up GUI thread: */
268 if (m_direction == UISettingsSerializeDirection_Save)
269 m_condition.wakeAll();
270 /* Break further processing if page had failed: */
271 if (pPage->failed())
272 break;
273 }
274 /* Notify listeners about all pages were processed: */
275 emit sigNotifyAboutPagesProcessed();
276 /* If serializer saves settings => wake up GUI thread: */
277 if (m_direction == UISettingsSerializeDirection_Save)
278 m_condition.wakeAll();
279 }
280
281 /* Variables: */
282 UISettingsSerializeDirection m_direction;
283 QVariant m_data;
284 UISettingsPageMap m_pages;
285 bool m_fSavingComplete;
286 bool m_fAllowToDestroySerializer;
287 int m_iIdOfHighPriorityPage;
288 QMutex m_mutex;
289 QWaitCondition m_condition;
290 static UISettingsSerializer *m_pInstance;
291};
292
293UISettingsSerializer* UISettingsSerializer::m_pInstance = 0;
294
295UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent)
296 : UISettingsDialog(pParent)
297{
298 /* Window icon: */
299#ifndef Q_WS_MAC
300 setWindowIcon(QIcon(":/global_settings_16px.png"));
301#endif /* !Q_WS_MAC */
302
303 /* Assign default dialog type: */
304 setDialogType(SettingsDialogType_Offline);
305
306 /* Creating settings pages: */
307 for (int iPageIndex = GLSettingsPage_General; iPageIndex < GLSettingsPage_MAX; ++iPageIndex)
308 {
309 if (isPageAvailable(iPageIndex))
310 {
311 UISettingsPage *pSettingsPage = 0;
312 switch (iPageIndex)
313 {
314 /* General page: */
315 case GLSettingsPage_General:
316 {
317 pSettingsPage = new UIGlobalSettingsGeneral;
318 addItem(":/machine_32px.png", ":/machine_disabled_32px.png",
319 ":/machine_16px.png", ":/machine_disabled_16px.png",
320 iPageIndex, "#general", pSettingsPage);
321 break;
322 }
323 /* Input page: */
324 case GLSettingsPage_Input:
325 {
326 pSettingsPage = new UIGlobalSettingsInput;
327 addItem(":/hostkey_32px.png", ":/hostkey_disabled_32px.png",
328 ":/hostkey_16px.png", ":/hostkey_disabled_16px.png",
329 iPageIndex, "#input", pSettingsPage);
330 break;
331 }
332 /* Update page: */
333 case GLSettingsPage_Update:
334 {
335 pSettingsPage = new UIGlobalSettingsUpdate;
336 addItem(":/refresh_32px.png", ":/refresh_disabled_32px.png",
337 ":/refresh_16px.png", ":/refresh_disabled_16px.png",
338 iPageIndex, "#update", pSettingsPage);
339 break;
340 }
341 /* Language page: */
342 case GLSettingsPage_Language:
343 {
344 pSettingsPage = new UIGlobalSettingsLanguage;
345 addItem(":/site_32px.png", ":/site_disabled_32px.png",
346 ":/site_16px.png", ":/site_disabled_16px.png",
347 iPageIndex, "#language", pSettingsPage);
348 break;
349 }
350 /* Display page: */
351 case GLSettingsPage_Display:
352 {
353 pSettingsPage = new UIGlobalSettingsDisplay;
354 addItem(":/vrdp_32px.png", ":/vrdp_disabled_32px.png",
355 ":/vrdp_16px.png", ":/vrdp_disabled_16px.png",
356 iPageIndex, "#display", pSettingsPage);
357 break;
358 }
359 /* USB page: */
360 case GLSettingsPage_USB:
361 {
362 pSettingsPage = new UIMachineSettingsUSB(UISettingsPageType_Global);
363 addItem(":/usb_32px.png", ":/usb_disabled_32px.png",
364 ":/usb_16px.png", ":/usb_disabled_16px.png",
365 iPageIndex, "#usb", pSettingsPage);
366 break;
367 }
368 /* Network page: */
369 case GLSettingsPage_Network:
370 {
371 pSettingsPage = new UIGlobalSettingsNetwork;
372 addItem(":/nw_32px.png", ":/nw_disabled_32px.png",
373 ":/nw_16px.png", ":/nw_disabled_16px.png",
374 iPageIndex, "#language", pSettingsPage);
375 break;
376 }
377 /* Extension page: */
378 case GLSettingsPage_Extension:
379 {
380 pSettingsPage = new UIGlobalSettingsExtension;
381 addItem(":/extension_pack_32px.png", ":/extension_pack_disabled_32px.png",
382 ":/extension_pack_16px.png", ":/extension_pack_disabled_16px.png",
383 iPageIndex, "#extension", pSettingsPage);
384 break;
385 }
386 /* Proxy page: */
387 case GLSettingsPage_Proxy:
388 {
389 pSettingsPage = new UIGlobalSettingsProxy;
390 addItem(":/proxy_32px.png", ":/proxy_disabled_32px.png",
391 ":/proxy_16px.png", ":/proxy_disabled_16px.png",
392 iPageIndex, "#proxy", pSettingsPage);
393 break;
394 }
395 default:
396 break;
397 }
398 if (pSettingsPage)
399 {
400 pSettingsPage->setDialogType(dialogType());
401 pSettingsPage->setId(iPageIndex);
402 }
403 }
404 }
405
406 /* Retranslate UI: */
407 retranslateUi();
408
409 /* Choose first item by default: */
410 m_pSelector->selectById(0);
411}
412
413UISettingsDialogGlobal::~UISettingsDialogGlobal()
414{
415 /* Delete serializer early if exists: */
416 if (UISettingsSerializer::instance())
417 delete UISettingsSerializer::instance();
418}
419
420void UISettingsDialogGlobal::loadData()
421{
422 /* Call for base-class: */
423 UISettingsDialog::loadData();
424
425 /* Prepare global data: */
426 qRegisterMetaType<UISettingsDataGlobal>();
427 UISettingsDataGlobal data(vboxGlobal().virtualBox().GetSystemProperties(), vboxGlobal().settings());
428 /* Create global settings loader,
429 * it will load global settings & delete itself in the appropriate time: */
430 UISettingsSerializer *pGlobalSettingsLoader = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Load);
431 connect(pGlobalSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded()));
432 /* Set pages to be loaded: */
433 pGlobalSettingsLoader->setPageList(m_pSelector->settingPages());
434 /* Start loader: */
435 pGlobalSettingsLoader->start();
436}
437
438void UISettingsDialogGlobal::saveData()
439{
440 /* Call for base-class: */
441 UISettingsDialog::saveData();
442
443 /* Get properties and settings: */
444 CSystemProperties properties = vboxGlobal().virtualBox().GetSystemProperties();
445 VBoxGlobalSettings settings = vboxGlobal().settings();
446 /* Prepare global data: */
447 qRegisterMetaType<UISettingsDataGlobal>();
448 UISettingsDataGlobal data(properties, settings);
449 /* Create global settings saver,
450 * it will save global settings & delete itself in the appropriate time: */
451 UISettingsSerializer *pGlobalSettingsSaver = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Save);
452 /* Set pages to be saved: */
453 pGlobalSettingsSaver->setPageList(m_pSelector->settingPages());
454 /* Start saver: */
455 pGlobalSettingsSaver->start();
456
457 /* Get updated properties & settings: */
458 CSystemProperties newProperties = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_properties;
459 VBoxGlobalSettings newSettings = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_settings;
460 /* If properties are not OK => show the error: */
461 if (!newProperties.isOk())
462 msgCenter().cannotSetSystemProperties(newProperties);
463 /* Else save the new settings if they were changed: */
464 else if (!(newSettings == settings))
465 vboxGlobal().setSettings(newSettings);
466
467 /* Mark page processed: */
468 sltMarkSaved();
469}
470
471void UISettingsDialogGlobal::retranslateUi()
472{
473 /* General page: */
474 m_pSelector->setItemText(GLSettingsPage_General, tr("General"));
475
476 /* Input page: */
477 m_pSelector->setItemText(GLSettingsPage_Input, tr("Input"));
478
479 /* Update page: */
480 m_pSelector->setItemText(GLSettingsPage_Update, tr("Update"));
481
482 /* Language page: */
483 m_pSelector->setItemText(GLSettingsPage_Language, tr("Language"));
484
485 /* Display page: */
486 m_pSelector->setItemText(GLSettingsPage_Display, tr("Display"));
487
488 /* USB page: */
489 m_pSelector->setItemText(GLSettingsPage_USB, tr("USB"));
490
491 /* Network page: */
492 m_pSelector->setItemText(GLSettingsPage_Network, tr("Network"));
493
494 /* Extension page: */
495 m_pSelector->setItemText(GLSettingsPage_Extension, tr("Extensions"));
496
497 /* Proxy page: */
498 m_pSelector->setItemText(GLSettingsPage_Proxy, tr("Proxy"));
499
500 /* Polish the selector: */
501 m_pSelector->polish();
502
503 /* Base-class UI translation: */
504 UISettingsDialog::retranslateUi();
505
506 /* Set dialog's name: */
507 setWindowTitle(title());
508}
509
510QString UISettingsDialogGlobal::title() const
511{
512 return tr("VirtualBox - %1").arg(titleExtension());
513}
514
515bool UISettingsDialogGlobal::isPageAvailable(int iPageId)
516{
517 /* Show the host error message for particular group if present.
518 * We don't use the generic cannotLoadGlobalConfig()
519 * call here because we want this message to be suppressible: */
520 switch (iPageId)
521 {
522 case GLSettingsPage_USB:
523 {
524#ifdef ENABLE_GLOBAL_USB
525 /* Get the host object: */
526 CHost host = vboxGlobal().host();
527 /* Show the host error message if any: */
528 if (!host.isReallyOk())
529 msgCenter().cannotAccessUSB(host);
530 /* Check if USB is implemented: */
531 CHostUSBDeviceFilterVector filters = host.GetUSBDeviceFilters();
532 Q_UNUSED(filters);
533 if (host.lastRC() == E_NOTIMPL)
534 return false;
535#else
536 return false;
537#endif
538 break;
539 }
540 case GLSettingsPage_Network:
541 {
542#ifndef VBOX_WITH_NETFLT
543 return false;
544#endif /* !VBOX_WITH_NETFLT */
545 break;
546 }
547 default:
548 break;
549 }
550 return true;
551}
552
553UISettingsDialogMachine::UISettingsDialogMachine(QWidget *pParent, const QString &strMachineId,
554 const QString &strCategory, const QString &strControl)
555 : UISettingsDialog(pParent)
556 , m_strMachineId(strMachineId)
557 , m_fAllowResetFirstRunFlag(false)
558 , m_fResetFirstRunFlag(false)
559{
560 /* Window icon: */
561#ifndef Q_WS_MAC
562 setWindowIcon(QIcon(":/settings_16px.png"));
563#endif /* Q_WS_MAC */
564
565 /* Allow to reset first-run flag just when medium enumeration was finished: */
566 connect(&vboxGlobal(), SIGNAL(mediumEnumFinished(const VBoxMediaList &)), this, SLOT(sltAllowResetFirstRunFlag()));
567
568 /* Get corresponding machine (required to determine dialog type and page availability): */
569 m_machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId);
570 AssertMsg(!m_machine.isNull(), ("Can't find corresponding machine!\n"));
571 /* Assign current dialog type: */
572 setDialogType(determineSettingsDialogType(m_machine.GetSessionState(), m_machine.GetState()));
573
574 /* Creating settings pages: */
575 for (int iPageIndex = VMSettingsPage_General; iPageIndex < VMSettingsPage_MAX; ++iPageIndex)
576 {
577 if (isPageAvailable(iPageIndex))
578 {
579 UISettingsPage *pSettingsPage = 0;
580 switch (iPageIndex)
581 {
582 /* General page: */
583 case VMSettingsPage_General:
584 {
585 pSettingsPage = new UIMachineSettingsGeneral;
586 addItem(":/machine_32px.png", ":/machine_disabled_32px.png",
587 ":/machine_16px.png", ":/machine_disabled_16px.png",
588 iPageIndex, "#general", pSettingsPage);
589 break;
590 }
591 /* System page: */
592 case VMSettingsPage_System:
593 {
594 pSettingsPage = new UIMachineSettingsSystem;
595 connect(pSettingsPage, SIGNAL(tableChanged()), this, SLOT(sltResetFirstRunFlag()));
596 addItem(":/chipset_32px.png", ":/chipset_disabled_32px.png",
597 ":/chipset_16px.png", ":/chipset_disabled_16px.png",
598 iPageIndex, "#system", pSettingsPage);
599 break;
600 }
601 /* Display page: */
602 case VMSettingsPage_Display:
603 {
604 pSettingsPage = new UIMachineSettingsDisplay;
605 addItem(":/vrdp_32px.png", ":/vrdp_disabled_32px.png",
606 ":/vrdp_16px.png", ":/vrdp_disabled_16px.png",
607 iPageIndex, "#display", pSettingsPage);
608 break;
609 }
610 /* Storage page: */
611 case VMSettingsPage_Storage:
612 {
613 pSettingsPage = new UIMachineSettingsStorage;
614 connect(pSettingsPage, SIGNAL(storageChanged()), this, SLOT(sltResetFirstRunFlag()));
615 addItem(":/hd_32px.png", ":/hd_disabled_32px.png",
616 ":/attachment_16px.png", ":/attachment_disabled_16px.png",
617 iPageIndex, "#storage", pSettingsPage);
618 break;
619 }
620 /* Audio page: */
621 case VMSettingsPage_Audio:
622 {
623 pSettingsPage = new UIMachineSettingsAudio;
624 addItem(":/sound_32px.png", ":/sound_disabled_32px.png",
625 ":/sound_16px.png", ":/sound_disabled_16px.png",
626 iPageIndex, "#audio", pSettingsPage);
627 break;
628 }
629 /* Network page: */
630 case VMSettingsPage_Network:
631 {
632 pSettingsPage = new UIMachineSettingsNetworkPage;
633 addItem(":/nw_32px.png", ":/nw_disabled_32px.png",
634 ":/nw_16px.png", ":/nw_disabled_16px.png",
635 iPageIndex, "#network", pSettingsPage);
636 break;
637 }
638 /* Ports page: */
639 case VMSettingsPage_Ports:
640 {
641 addItem(":/serial_port_32px.png", ":/serial_port_disabled_32px.png",
642 ":/serial_port_16px.png", ":/serial_port_disabled_16px.png",
643 iPageIndex, "#ports");
644 break;
645 }
646 /* Serial page: */
647 case VMSettingsPage_Serial:
648 {
649 pSettingsPage = new UIMachineSettingsSerialPage;
650 addItem(":/serial_port_32px.png", ":/serial_port_disabled_32px.png",
651 ":/serial_port_16px.png", ":/serial_port_disabled_16px.png",
652 iPageIndex, "#serialPorts", pSettingsPage, VMSettingsPage_Ports);
653 break;
654 }
655 /* Parallel page: */
656 case VMSettingsPage_Parallel:
657 {
658 pSettingsPage = new UIMachineSettingsParallelPage;
659 addItem(":/parallel_port_32px.png", ":/parallel_port_disabled_32px.png",
660 ":/parallel_port_16px.png", ":/parallel_port_disabled_16px.png",
661 iPageIndex, "#parallelPorts", pSettingsPage, VMSettingsPage_Ports);
662 break;
663 }
664 /* USB page: */
665 case VMSettingsPage_USB:
666 {
667 pSettingsPage = new UIMachineSettingsUSB(UISettingsPageType_Machine);
668 addItem(":/usb_32px.png", ":/usb_disabled_32px.png",
669 ":/usb_16px.png", ":/usb_disabled_16px.png",
670 iPageIndex, "#usb", pSettingsPage, VMSettingsPage_Ports);
671 break;
672 }
673 /* Shared Folders page: */
674 case VMSettingsPage_SF:
675 {
676 pSettingsPage = new UIMachineSettingsSF;
677 addItem(":/shared_folder_32px.png", ":/shared_folder_disabled_32px.png",
678 ":/shared_folder_16px.png", ":/shared_folder_disabled_16px.png",
679 iPageIndex, "#sharedFolders", pSettingsPage);
680 break;
681 }
682 default:
683 break;
684 }
685 if (pSettingsPage)
686 {
687 pSettingsPage->setDialogType(dialogType());
688 pSettingsPage->setId(iPageIndex);
689 }
690 }
691 }
692
693 /* Retranslate UI: */
694 retranslateUi();
695
696 /* Setup settings dialog: */
697 if (!strCategory.isNull())
698 {
699 m_pSelector->selectByLink(strCategory);
700 /* Search for a widget with the given name: */
701 if (!strControl.isNull())
702 {
703 if (QWidget *pWidget = m_pStack->currentWidget()->findChild<QWidget*>(strControl))
704 {
705 QList<QWidget*> parents;
706 QWidget *pParentWidget = pWidget;
707 while ((pParentWidget = pParentWidget->parentWidget()) != 0)
708 {
709 if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget))
710 {
711 /* The tab contents widget is two steps down
712 * (QTabWidget -> QStackedWidget -> QWidget): */
713 QWidget *pTabPage = parents[parents.count() - 1];
714 if (pTabPage)
715 pTabPage = parents[parents.count() - 2];
716 if (pTabPage)
717 pTabWidget->setCurrentWidget(pTabPage);
718 }
719 parents.append(pParentWidget);
720 }
721 pWidget->setFocus();
722 }
723 }
724 }
725 /* First item as default: */
726 else
727 m_pSelector->selectById(0);
728}
729
730UISettingsDialogMachine::~UISettingsDialogMachine()
731{
732 /* Delete serializer early if exists: */
733 if (UISettingsSerializer::instance())
734 delete UISettingsSerializer::instance();
735}
736
737void UISettingsDialogMachine::loadData()
738{
739 /* Check that session is NOT created: */
740 if (!m_session.isNull())
741 return;
742
743 /* Call for base-class: */
744 UISettingsDialog::loadData();
745
746 /* Disconnect global VBox events from this dialog: */
747 gVBoxEvents->disconnect(this);
748
749 /* Prepare session: */
750 m_session = dialogType() == SettingsDialogType_Wrong ? CSession() : vboxGlobal().openExistingSession(m_strMachineId);
751 /* Check that session was created: */
752 if (m_session.isNull())
753 return;
754
755 /* Get machine from session: */
756 m_machine = m_session.GetMachine();
757 /* Get console from session: */
758 m_console = dialogType() == SettingsDialogType_Offline ? CConsole() : m_session.GetConsole();
759
760 /* Prepare machine data: */
761 qRegisterMetaType<UISettingsDataMachine>();
762 UISettingsDataMachine data(m_machine, m_console);
763 /* Create machine settings loader,
764 * it will load machine settings & delete itself in the appropriate time: */
765 UISettingsSerializer *pMachineSettingsLoader = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Load);
766 connect(pMachineSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded()));
767 connect(pMachineSettingsLoader, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltSetFirstRunFlag()));
768 /* Set pages to be loaded: */
769 pMachineSettingsLoader->setPageList(m_pSelector->settingPages());
770 /* Ask to raise required page priority: */
771 pMachineSettingsLoader->raisePriorityOfPage(m_pSelector->currentId());
772 /* Start page loader: */
773 pMachineSettingsLoader->start();
774}
775
776void UISettingsDialogMachine::saveData()
777{
778 /* Check that session is NOT created: */
779 if (!m_session.isNull())
780 return;
781
782 /* Call for base-class: */
783 UISettingsDialog::saveData();
784
785 /* Disconnect global VBox events from this dialog: */
786 gVBoxEvents->disconnect(this);
787
788 /* Prepare session: */
789 if (dialogType() == SettingsDialogType_Wrong)
790 m_session = CSession();
791 else if (dialogType() != SettingsDialogType_Offline)
792 m_session = vboxGlobal().openExistingSession(m_strMachineId);
793 else
794 m_session = vboxGlobal().openSession(m_strMachineId);
795 /* Check that session was created: */
796 if (m_session.isNull())
797 return;
798
799 /* Get machine from session: */
800 m_machine = m_session.GetMachine();
801 /* Get console from session: */
802 m_console = dialogType() == SettingsDialogType_Offline ? CConsole() : m_session.GetConsole();
803
804 /* Prepare machine data: */
805 qRegisterMetaType<UISettingsDataMachine>();
806 UISettingsDataMachine data(m_machine, m_console);
807 /* Create machine settings saver,
808 * it will save machine settings & delete itself in the appropriate time: */
809 UISettingsSerializer *pMachineSettingsSaver = new UISettingsSerializer(this, QVariant::fromValue(data), UISettingsSerializeDirection_Save);
810 /* Set pages to be saved: */
811 pMachineSettingsSaver->setPageList(m_pSelector->settingPages());
812 /* Start saver: */
813 pMachineSettingsSaver->start();
814
815 /* Get updated machine: */
816 m_machine = pMachineSettingsSaver->data().value<UISettingsDataMachine>().m_machine;
817 /* If machine is ok => perform final operations: */
818 if (m_machine.isOk())
819 {
820 /* Guest OS type & VT-x/AMD-V option correlation auto-fix: */
821 UIMachineSettingsGeneral *pGeneralPage =
822 qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(VMSettingsPage_General));
823 UIMachineSettingsSystem *pSystemPage =
824 qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(VMSettingsPage_System));
825 if (pGeneralPage && pSystemPage &&
826 pGeneralPage->is64BitOSTypeSelected() && !pSystemPage->isHWVirtExEnabled())
827 m_machine.SetHWVirtExProperty(KHWVirtExPropertyType_Enabled, true);
828
829#ifdef VBOX_WITH_VIDEOHWACCEL
830 /* Disable 2D Video Acceleration for non-Windows guests: */
831 if (pGeneralPage && !pGeneralPage->isWindowsOSTypeSelected())
832 {
833 UIMachineSettingsDisplay *pDisplayPage =
834 qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(VMSettingsPage_Display));
835 if (pDisplayPage && pDisplayPage->isAcceleration2DVideoSelected())
836 m_machine.SetAccelerate2DVideoEnabled(false);
837 }
838#endif /* VBOX_WITH_VIDEOHWACCEL */
839
840 /* Enable OHCI controller if HID is enabled: */
841 if (pSystemPage && pSystemPage->isHIDEnabled())
842 {
843 CUSBController controller = m_machine.GetUSBController();
844 if (!controller.isNull())
845 controller.SetEnabled(true);
846 }
847
848 /* Clear the "GUI_FirstRun" extra data key in case if
849 * the boot order or disk configuration were changed: */
850 if (m_fResetFirstRunFlag)
851 m_machine.SetExtraData(GUI_FirstRun, QString::null);
852
853 /* Save settings finally: */
854 m_machine.SaveSettings();
855 }
856
857 /* If machine is NOT ok => show the error message: */
858 if (!m_machine.isOk())
859 msgCenter().cannotSaveMachineSettings(m_machine);
860
861 /* Mark page processed: */
862 sltMarkSaved();
863}
864
865void UISettingsDialogMachine::retranslateUi()
866{
867 /* We have to make sure that the Network, Serial & Parallel pages are retranslated
868 * before they are revalidated. Cause: They do string comparing within
869 * vboxGlobal which is retranslated at that point already: */
870 QEvent event(QEvent::LanguageChange);
871 if (QWidget *pPage = m_pSelector->idToPage(VMSettingsPage_Network))
872 qApp->sendEvent(pPage, &event);
873 if (QWidget *pPage = m_pSelector->idToPage(VMSettingsPage_Serial))
874 qApp->sendEvent(pPage, &event);
875 if (QWidget *pPage = m_pSelector->idToPage(VMSettingsPage_Parallel))
876 qApp->sendEvent(pPage, &event);
877
878 /* General page: */
879 m_pSelector->setItemText(VMSettingsPage_General, tr("General"));
880
881 /* System page: */
882 m_pSelector->setItemText(VMSettingsPage_System, tr("System"));
883
884 /* Display page: */
885 m_pSelector->setItemText(VMSettingsPage_Display, tr("Display"));
886
887 /* Storage page: */
888 m_pSelector->setItemText(VMSettingsPage_Storage, tr("Storage"));
889
890 /* Audio page: */
891 m_pSelector->setItemText(VMSettingsPage_Audio, tr("Audio"));
892
893 /* Network page: */
894 m_pSelector->setItemText(VMSettingsPage_Network, tr("Network"));
895
896 /* Ports page: */
897 m_pSelector->setItemText(VMSettingsPage_Ports, tr("Ports"));
898
899 /* Serial page: */
900 m_pSelector->setItemText(VMSettingsPage_Serial, tr("Serial Ports"));
901
902 /* Parallel page: */
903 m_pSelector->setItemText(VMSettingsPage_Parallel, tr("Parallel Ports"));
904
905 /* USB page: */
906 m_pSelector->setItemText(VMSettingsPage_USB, tr("USB"));
907
908 /* SFolders page: */
909 m_pSelector->setItemText(VMSettingsPage_SF, tr("Shared Folders"));
910
911 /* Polish the selector: */
912 m_pSelector->polish();
913
914 /* Base-class UI translation: */
915 UISettingsDialog::retranslateUi();
916
917 /* Set dialog's name: */
918 setWindowTitle(title());
919}
920
921QString UISettingsDialogMachine::title() const
922{
923 QString strDialogTitle;
924 /* Get corresponding machine (required to compose dialog title): */
925 const CMachine &machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId);
926 if (!machine.isNull())
927 strDialogTitle = tr("%1 - %2").arg(machine.GetName()).arg(titleExtension());
928 return strDialogTitle;
929}
930
931void UISettingsDialogMachine::recorrelate(UISettingsPage *pSettingsPage)
932{
933 switch (pSettingsPage->id())
934 {
935 case VMSettingsPage_General:
936 {
937 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(pSettingsPage);
938 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(VMSettingsPage_System));
939 if (pGeneralPage && pSystemPage)
940 pGeneralPage->setHWVirtExEnabled(pSystemPage->isHWVirtExEnabled());
941 break;
942 }
943 case VMSettingsPage_Display:
944 {
945 UIMachineSettingsDisplay *pDisplayPage = qobject_cast<UIMachineSettingsDisplay*>(pSettingsPage);
946 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(VMSettingsPage_General));
947 if (pDisplayPage && pGeneralPage)
948 pDisplayPage->setGuestOSType(pGeneralPage->guestOSType());
949 break;
950 }
951 case VMSettingsPage_System:
952 {
953 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(pSettingsPage);
954 UIMachineSettingsUSB *pUsbPage = qobject_cast<UIMachineSettingsUSB*>(m_pSelector->idToPage(VMSettingsPage_USB));
955 if (pSystemPage && pUsbPage)
956 pSystemPage->setOHCIEnabled(pUsbPage->isOHCIEnabled());
957 break;
958 }
959 case VMSettingsPage_Storage:
960 {
961 UIMachineSettingsStorage *pStoragePage = qobject_cast<UIMachineSettingsStorage*>(pSettingsPage);
962 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(VMSettingsPage_System));
963 if (pStoragePage && pSystemPage)
964 pStoragePage->setChipsetType(pSystemPage->chipsetType());
965 break;
966 }
967 default:
968 break;
969 }
970}
971
972void UISettingsDialogMachine::sltMarkLoaded()
973{
974 /* Call for base-class: */
975 UISettingsDialog::sltMarkLoaded();
976
977 /* Unlock the session if exists: */
978 if (!m_session.isNull())
979 {
980 m_session.UnlockMachine();
981 m_session = CSession();
982 m_machine = CMachine();
983 m_console = CConsole();
984 }
985
986 /* Make sure settings dialog will be updated on machine state/data changes: */
987 connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)),
988 this, SLOT(sltMachineStateChanged(QString, KMachineState)));
989 connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)),
990 this, SLOT(sltMachineDataChanged(QString)));
991}
992
993void UISettingsDialogMachine::sltMarkSaved()
994{
995 /* Call for base-class: */
996 UISettingsDialog::sltMarkSaved();
997
998 /* Unlock the session if exists: */
999 if (!m_session.isNull())
1000 {
1001 m_session.UnlockMachine();
1002 m_session = CSession();
1003 m_machine = CMachine();
1004 m_console = CConsole();
1005 }
1006}
1007
1008void UISettingsDialogMachine::sltMachineStateChanged(QString strMachineId, KMachineState machineState)
1009{
1010 /* Ignore if thats NOT our VM: */
1011 if (strMachineId != m_strMachineId)
1012 return;
1013
1014 /* Ignore if state was NOT actually changed: */
1015 if (m_machineState == machineState)
1016 return;
1017
1018 /* Update current machine state: */
1019 m_machineState = machineState;
1020
1021 /* Get new dialog type: */
1022 SettingsDialogType newDialogType = determineSettingsDialogType(m_machine.GetSessionState(), m_machineState);
1023
1024 /* Ignore if dialog type was NOT actually changed: */
1025 if (dialogType() == newDialogType)
1026 return;
1027
1028 /* Should we show a warning about leaving 'offline' state? */
1029 bool fShouldWe = dialogType() == SettingsDialogType_Offline;
1030
1031 /* Update current dialog type: */
1032 setDialogType(newDialogType);
1033
1034 /* Show a warning about leaving 'offline' state if we should: */
1035 if (isSettingsChanged() && fShouldWe)
1036 msgCenter().warnAboutStateChange(this);
1037}
1038
1039void UISettingsDialogMachine::sltMachineDataChanged(QString strMachineId)
1040{
1041 /* Ignore if thats NOT our VM: */
1042 if (strMachineId != m_strMachineId)
1043 return;
1044
1045 /* Check if user had changed something and warn him about he will loose settings on reloading: */
1046 if (isSettingsChanged() && !msgCenter().confirmedSettingsReloading(this))
1047 return;
1048
1049 /* Reload data: */
1050 loadData();
1051}
1052
1053void UISettingsDialogMachine::sltCategoryChanged(int cId)
1054{
1055 if (UISettingsSerializer::instance())
1056 UISettingsSerializer::instance()->raisePriorityOfPage(cId);
1057
1058 UISettingsDialog::sltCategoryChanged(cId);
1059}
1060
1061void UISettingsDialogMachine::sltAllowResetFirstRunFlag()
1062{
1063 m_fAllowResetFirstRunFlag = true;
1064}
1065
1066void UISettingsDialogMachine::sltSetFirstRunFlag()
1067{
1068 m_fResetFirstRunFlag = false;
1069}
1070
1071void UISettingsDialogMachine::sltResetFirstRunFlag()
1072{
1073 if (m_fAllowResetFirstRunFlag)
1074 m_fResetFirstRunFlag = true;
1075}
1076
1077bool UISettingsDialogMachine::isPageAvailable(int iPageId)
1078{
1079 if (m_machine.isNull())
1080 return false;
1081
1082 /* Show the machine error message for particular group if present.
1083 * We don't use the generic cannotLoadMachineSettings()
1084 * call here because we want this message to be suppressible. */
1085 switch (iPageId)
1086 {
1087 case VMSettingsPage_Serial:
1088 {
1089 /* Depends on ports availability: */
1090 if (!isPageAvailable(VMSettingsPage_Ports))
1091 return false;
1092 break;
1093 }
1094 case VMSettingsPage_Parallel:
1095 {
1096 /* Depends on ports availability: */
1097 if (!isPageAvailable(VMSettingsPage_Ports))
1098 return false;
1099 /* But for now this page is always disabled: */
1100 return false;
1101 }
1102 case VMSettingsPage_USB:
1103 {
1104 /* Depends on ports availability: */
1105 if (!isPageAvailable(VMSettingsPage_Ports))
1106 return false;
1107 /* Get the USB controller object: */
1108 CUSBController controller = m_machine.GetUSBController();
1109 /* Show the machine error message if any: */
1110 if (!m_machine.isReallyOk() && !controller.isNull() && controller.GetEnabled())
1111 msgCenter().cannotAccessUSB(m_machine);
1112 /* Check if USB is implemented: */
1113 if (controller.isNull() || !controller.GetProxyAvailable())
1114 return false;
1115 break;
1116 }
1117 default:
1118 break;
1119 }
1120 return true;
1121}
1122
1123bool UISettingsDialogMachine::isSettingsChanged()
1124{
1125 bool fIsSettingsChanged = false;
1126 for (int iWidgetNumber = 0; iWidgetNumber < m_pStack->count() && !fIsSettingsChanged; ++iWidgetNumber)
1127 {
1128 UISettingsPage *pPage = static_cast<UISettingsPage*>(m_pStack->widget(iWidgetNumber));
1129 pPage->putToCache();
1130 if (pPage->changed())
1131 fIsSettingsChanged = true;
1132 }
1133 return fIsSettingsChanged;
1134}
1135
1136# include "UISettingsDialogSpecific.moc"
1137
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use