VirtualBox

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

Last change on this file since 35740 was 35131, checked in by vboxsync, 14 years ago

FE/Qt: Prevent closing global/machine settings dialog while not all the settings pages loaded.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use