Changeset 54886 in vbox
- Timestamp:
- Mar 20, 2015 5:50:46 PM (10 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r54733 r54886 357 357 src/settings/UISettingsDialogSpecific.h \ 358 358 src/settings/UISettingsPage.h \ 359 src/settings/UISettingsSerializer.h \ 359 360 src/settings/VBoxSettingsSelector.h \ 360 361 src/settings/global/UIGlobalSettingsExtension.h \ … … 370 371 src/settings/machine/UIMachineSettingsDisplay.h \ 371 372 src/settings/machine/UIMachineSettingsGeneral.h \ 372 373 373 src/settings/machine/UIMachineSettingsInterface.h \ 374 src/settings/machine/UIMachineSettingsNetwork.h \ 374 375 src/settings/machine/UIMachineSettingsParallel.h \ 375 376 src/settings/machine/UIMachineSettingsPortForwardingDlg.h \ … … 498 499 src/selector/UIActionPoolSelector.cpp \ 499 500 src/selector/UIVMDesktop.cpp \ 500 src/settings/UISettingsDialogSpecific.cpp \501 501 src/settings/machine/UIMachineSettingsStorage.cpp \ 502 502 src/settings/machine/UIMachineSettingsUSB.cpp \ … … 639 639 src/settings/UISettingsDialogSpecific.cpp \ 640 640 src/settings/UISettingsPage.cpp \ 641 src/settings/UISettingsSerializer.cpp \ 641 642 src/settings/VBoxSettingsSelector.cpp \ 642 643 src/settings/global/UIGlobalSettingsExtension.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp
r54875 r54886 20 20 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 21 21 22 /* Qt includes: */23 # include <QStackedWidget>24 # include <QThread>25 # include <QMutex>26 # include <QWaitCondition>27 # include <QTimer>28 29 22 /* GUI includes: */ 30 23 # include "UISettingsDialogSpecific.h" 24 # include "UISettingsSerializer.h" 31 25 # include "UISettingsDefs.h" 32 26 # include "VBoxGlobal.h" … … 66 60 67 61 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 68 69 70 #if 0 /* Global USB filters are DISABLED now: */71 # define ENABLE_GLOBAL_USB72 #endif /* Global USB filters are DISABLED now: */73 74 /* Settings page list: */75 typedef QList<UISettingsPage*> UISettingsPageList;76 typedef QMap<int, UISettingsPage*> UISettingsPageMap;77 78 /** QThread reimplementation used for79 * loading/saving settings in async mode.80 * @todo To be moved into the separate files! */81 class UISettingsSerializer : public QThread82 {83 Q_OBJECT;84 85 signals:86 87 /** Notifies GUI thread about process has been started. */88 void sigNotifyAboutProcessStarted();89 90 /** Notifies GUI thread about some page was processed. */91 void sigNotifyAboutPageProcessed(int iPageId);92 93 /** Notifies GUI thread about all pages were processed. */94 void sigNotifyAboutPagesProcessed();95 96 public:97 98 /** Serialization directions. */99 enum SerializationDirection { Load, Save };100 101 /** Returns the singleton instance. */102 static UISettingsSerializer* instance() { return m_spInstance; }103 104 /** Constructor.105 * @param pParent being passed to the base-class,106 * @param direction determines the load/save direction,107 * @param data contains the wrapper(s) to load/save the data from/to,108 * @param pages contains the page(s) to load/save the data to/from. */109 UISettingsSerializer(QObject *pParent, SerializationDirection direction,110 const QVariant &data, const UISettingsPageList &pages)111 : QThread(pParent)112 , m_direction(direction)113 , m_data(data)114 , m_fSavingComplete(m_direction == Load)115 , m_fAllowToDestroySerializer(m_direction == Load)116 , m_iIdOfHighPriorityPage(-1)117 {118 /* Prepare instance: */119 m_spInstance = this;120 121 /* Copy the page(s) from incoming list to our map: */122 for (int iPageIndex = 0; iPageIndex < pages.size(); ++iPageIndex)123 {124 UISettingsPage *pPage = pages[iPageIndex];125 m_pages.insert(pPage->id(), pPage);126 }127 128 /* Connecting this signals: */129 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection);130 connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection);131 connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection);132 /* Connecting parent signals: */133 connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection);134 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection);135 }136 137 /** Destructor. */138 ~UISettingsSerializer()139 {140 /* If serializer is being destructed by it's parent,141 * thread could still be running, we have to wait142 * for it to be finished! */143 if (isRunning())144 wait();145 146 /* Cleanup instance: */147 m_spInstance = 0;148 }149 150 /** Returns the instance of wrapper(s) to load/save the data from/to. */151 QVariant& data() { return m_data; }152 153 /** Raises the priority of page with @a iPageId. */154 void raisePriorityOfPage(int iPageId)155 {156 /* If that page is present and was not processed already =>157 * we should remember which page should be processed next: */158 if (m_pages.contains(iPageId) && !(m_pages[iPageId]->processed()))159 m_iIdOfHighPriorityPage = iPageId;160 }161 162 public slots:163 164 /** Starts the process of data loading with passed @a priority. */165 void start(Priority priority = InheritPriority)166 {167 /* Notify listeners about we are starting: */168 emit sigNotifyAboutProcessStarted();169 170 /* If serializer saves settings: */171 if (m_direction == Save)172 {173 /* We should update internal page cache first: */174 foreach (UISettingsPage *pPage, m_pages.values())175 pPage->putToCache();176 }177 178 /* Start async serializing thread: */179 QThread::start(priority);180 181 /* If serializer saves settings: */182 if (m_direction == Save)183 {184 /* We should block calling thread until all pages will be saved: */185 while (!m_fSavingComplete)186 {187 /* Lock mutex initially: */188 m_mutex.lock();189 /* Perform idle-processing every 100ms,190 * and waiting for direct wake up signal: */191 m_condition.wait(&m_mutex, 100);192 /* Process queued signals posted to GUI thread: */193 qApp->processEvents();194 /* Unlock mutex finally: */195 m_mutex.unlock();196 }197 /* Allow to destroy serializer finally: */198 m_fAllowToDestroySerializer = true;199 }200 }201 202 protected slots:203 204 /** Handles the fact of some page was processed. */205 void sltHandleProcessedPage(int iPageId)206 {207 /* If serializer loads settings: */208 if (m_direction == Load)209 {210 /* If such page present: */211 if (m_pages.contains(iPageId))212 {213 /* We should fetch internal page cache: */214 UISettingsPage *pSettingsPage = m_pages[iPageId];215 pSettingsPage->setValidatorBlocked(true);216 pSettingsPage->getFromCache();217 pSettingsPage->setValidatorBlocked(false);218 }219 }220 }221 222 /** Handles the fact of all pages were processed. */223 void sltHandleProcessedPages()224 {225 /* If serializer saves settings: */226 if (m_direction == Save)227 {228 /* We should flag GUI thread to unlock itself: */229 if (!m_fSavingComplete)230 m_fSavingComplete = true;231 }232 /* If serializer loads settings: */233 else234 {235 /* We have to do initial validation finally: */236 foreach (UISettingsPage *pPage, m_pages.values())237 pPage->revalidate();238 }239 }240 241 /** Killing serializer, softly :) */242 void sltDestroySerializer()243 {244 /* If not yet all events were processed,245 * we should postpone destruction for now: */246 if (!m_fAllowToDestroySerializer)247 QTimer::singleShot(0, this, SLOT(sltDestroySerializer()));248 else249 deleteLater();250 }251 252 protected:253 254 /** Settings serializer. */255 void run()256 {257 /* Initialize COM for other thread: */258 COMBase::InitializeCOM(false);259 260 /* Mark all the pages initially as NOT processed: */261 foreach (UISettingsPage *pPage, m_pages.values())262 pPage->setProcessed(false);263 264 /* Iterate over the all left settings pages: */265 UISettingsPageMap pages(m_pages);266 while (!pages.empty())267 {268 /* Get required page pointer, protect map by mutex while getting pointer: */269 UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ?270 pages.value(m_iIdOfHighPriorityPage) : *pages.begin();271 /* Reset request of high priority: */272 if (m_iIdOfHighPriorityPage != -1)273 m_iIdOfHighPriorityPage = -1;274 /* Process this page if its enabled: */275 if (pPage->isEnabled())276 {277 if (m_direction == Load)278 pPage->loadToCacheFrom(m_data);279 if (m_direction == Save)280 pPage->saveFromCacheTo(m_data);281 }282 /* Remember what page was processed: */283 pPage->setProcessed(true);284 /* Remove processed page from our map: */285 pages.remove(pPage->id());286 /* Notify listeners about page was processed: */287 emit sigNotifyAboutPageProcessed(pPage->id());288 /* If serializer saves settings => wake up GUI thread: */289 if (m_direction == Save)290 m_condition.wakeAll();291 /* Break further processing if page had failed: */292 if (pPage->failed())293 break;294 }295 /* Notify listeners about all pages were processed: */296 emit sigNotifyAboutPagesProcessed();297 /* If serializer saves settings => wake up GUI thread: */298 if (m_direction == Save)299 m_condition.wakeAll();300 301 /* Deinitialize COM for other thread: */302 COMBase::CleanupCOM();303 }304 305 /** Holds the singleton instance. */306 static UISettingsSerializer *m_spInstance;307 308 /** Holds the the load/save direction. */309 SerializationDirection m_direction;310 311 /** Holds the wrapper(s) to load/save the data from/to. */312 QVariant m_data;313 /** Holds the page(s) to load/save the data to/from. */314 UISettingsPageMap m_pages;315 316 /** Holds whether the save was complete. */317 bool m_fSavingComplete;318 /** Holds whether it is allowed to destroy the serializer. */319 bool m_fAllowToDestroySerializer;320 /** Holds the ID of the high priority page. */321 int m_iIdOfHighPriorityPage;322 /** Holds the synchronization mutex. */323 QMutex m_mutex;324 /** Holds the synchronization condition. */325 QWaitCondition m_condition;326 };327 328 UISettingsSerializer* UISettingsSerializer::m_spInstance = 0;329 62 330 63 UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent, … … 1198 931 } 1199 932 1200 # include "UISettingsDialogSpecific.moc"1201 -
trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsSerializer.cpp
r54883 r54886 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UISettings DialogSpecificclass implementation.3 * VBox Qt GUI - UISettingsSerializer class implementation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 2Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 19 19 # include <precomp.h> 20 20 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 21 22 21 /* Qt includes: */ 23 # include <QStackedWidget>24 # include <QThread>25 # include <QMutex>26 # include <QWaitCondition>27 22 # include <QTimer> 28 29 23 /* GUI includes: */ 30 # include "UISettingsDialogSpecific.h" 31 # include "UISettingsDefs.h" 32 # include "VBoxGlobal.h" 33 # include "UIMessageCenter.h" 34 # include "UIExtraDataManager.h" 35 # include "QIWidgetValidator.h" 36 # include "VBoxSettingsSelector.h" 37 # include "UIVirtualBoxEventHandler.h" 38 39 # include "UIGlobalSettingsGeneral.h" 40 # include "UIGlobalSettingsInput.h" 41 # ifdef VBOX_GUI_WITH_NETWORK_MANAGER 42 # include "UIGlobalSettingsUpdate.h" 43 # endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 44 # include "UIGlobalSettingsLanguage.h" 45 # include "UIGlobalSettingsDisplay.h" 46 # include "UIGlobalSettingsNetwork.h" 47 # include "UIGlobalSettingsExtension.h" 48 # ifdef VBOX_GUI_WITH_NETWORK_MANAGER 49 # include "UIGlobalSettingsProxy.h" 50 # endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 51 52 # include "UIMachineSettingsGeneral.h" 53 # include "UIMachineSettingsSystem.h" 54 # include "UIMachineSettingsDisplay.h" 55 # include "UIMachineSettingsStorage.h" 56 # include "UIMachineSettingsAudio.h" 57 # include "UIMachineSettingsNetwork.h" 58 # include "UIMachineSettingsSerial.h" 59 # include "UIMachineSettingsParallel.h" 60 # include "UIMachineSettingsUSB.h" 61 # include "UIMachineSettingsSF.h" 62 # include "UIMachineSettingsInterface.h" 63 64 /* COM includes: */ 65 # include "CUSBController.h" 66 24 # include "UISettingsSerializer.h" 25 # include "UISettingsPage.h" 67 26 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 68 27 69 70 #if 0 /* Global USB filters are DISABLED now: */ 71 # define ENABLE_GLOBAL_USB 72 #endif /* Global USB filters are DISABLED now: */ 73 74 /* Settings page list: */ 75 typedef QList<UISettingsPage*> UISettingsPageList; 76 typedef QMap<int, UISettingsPage*> UISettingsPageMap; 77 78 /** QThread reimplementation used for 79 * loading/saving settings in async mode. 80 * @todo To be moved into the separate files! */ 81 class UISettingsSerializer : public QThread 82 { 83 Q_OBJECT; 84 85 signals: 86 87 /** Notifies GUI thread about process has been started. */ 88 void sigNotifyAboutProcessStarted(); 89 90 /** Notifies GUI thread about some page was processed. */ 91 void sigNotifyAboutPageProcessed(int iPageId); 92 93 /** Notifies GUI thread about all pages were processed. */ 94 void sigNotifyAboutPagesProcessed(); 95 96 public: 97 98 /** Serialization directions. */ 99 enum SerializationDirection { Load, Save }; 100 101 /** Returns the singleton instance. */ 102 static UISettingsSerializer* instance() { return m_spInstance; } 103 104 /** Constructor. 105 * @param pParent being passed to the base-class, 106 * @param direction determines the load/save direction, 107 * @param data contains the wrapper(s) to load/save the data from/to, 108 * @param pages contains the page(s) to load/save the data to/from. */ 109 UISettingsSerializer(QObject *pParent, SerializationDirection direction, 110 const QVariant &data, const UISettingsPageList &pages) 111 : QThread(pParent) 112 , m_direction(direction) 113 , m_data(data) 114 , m_fSavingComplete(m_direction == Load) 115 , m_fAllowToDestroySerializer(m_direction == Load) 116 , m_iIdOfHighPriorityPage(-1) 117 { 118 /* Prepare instance: */ 119 m_spInstance = this; 120 121 /* Copy the page(s) from incoming list to our map: */ 122 for (int iPageIndex = 0; iPageIndex < pages.size(); ++iPageIndex) 28 UISettingsSerializer* UISettingsSerializer::m_spInstance = 0; 29 30 UISettingsSerializer::UISettingsSerializer(QObject *pParent, SerializationDirection direction, 31 const QVariant &data, const UISettingsPageList &pages) 32 : QThread(pParent) 33 , m_direction(direction) 34 , m_data(data) 35 , m_fSavingComplete(m_direction == Load) 36 , m_fAllowToDestroySerializer(m_direction == Load) 37 , m_iIdOfHighPriorityPage(-1) 38 { 39 /* Prepare instance: */ 40 m_spInstance = this; 41 42 /* Copy the page(s) from incoming list to our map: */ 43 for (int iPageIndex = 0; iPageIndex < pages.size(); ++iPageIndex) 44 { 45 UISettingsPage *pPage = pages[iPageIndex]; 46 m_pages.insert(pPage->id(), pPage); 47 } 48 49 /* Connecting this signals: */ 50 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection); 51 connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection); 52 connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection); 53 /* Connecting parent signals: */ 54 connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection); 55 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection); 56 } 57 58 UISettingsSerializer::~UISettingsSerializer() 59 { 60 /* If serializer is being destructed by it's parent, 61 * thread could still be running, we have to wait 62 * for it to be finished! */ 63 if (isRunning()) 64 wait(); 65 66 /* Cleanup instance: */ 67 m_spInstance = 0; 68 } 69 70 void UISettingsSerializer::raisePriorityOfPage(int iPageId) 71 { 72 /* If that page is present and was not processed already => 73 * we should remember which page should be processed next: */ 74 if (m_pages.contains(iPageId) && !(m_pages[iPageId]->processed())) 75 m_iIdOfHighPriorityPage = iPageId; 76 } 77 78 void UISettingsSerializer::start(Priority priority /* = InheritPriority */) 79 { 80 /* Notify listeners about we are starting: */ 81 emit sigNotifyAboutProcessStarted(); 82 83 /* If serializer saves settings: */ 84 if (m_direction == Save) 85 { 86 /* We should update internal page cache first: */ 87 foreach (UISettingsPage *pPage, m_pages.values()) 88 pPage->putToCache(); 89 } 90 91 /* Start async serializing thread: */ 92 QThread::start(priority); 93 94 /* If serializer saves settings: */ 95 if (m_direction == Save) 96 { 97 /* We should block calling thread until all pages will be saved: */ 98 while (!m_fSavingComplete) 123 99 { 124 UISettingsPage *pPage = pages[iPageIndex]; 125 m_pages.insert(pPage->id(), pPage); 100 /* Lock mutex initially: */ 101 m_mutex.lock(); 102 /* Perform idle-processing every 100ms, 103 * and waiting for direct wake up signal: */ 104 m_condition.wait(&m_mutex, 100); 105 /* Process queued signals posted to GUI thread: */ 106 qApp->processEvents(); 107 /* Unlock mutex finally: */ 108 m_mutex.unlock(); 126 109 } 127 128 /* Connecting this signals: */ 129 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection); 130 connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection); 131 connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection); 132 /* Connecting parent signals: */ 133 connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection); 134 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection); 135 } 136 137 /** Destructor. */ 138 ~UISettingsSerializer() 139 { 140 /* If serializer is being destructed by it's parent, 141 * thread could still be running, we have to wait 142 * for it to be finished! */ 143 if (isRunning()) 144 wait(); 145 146 /* Cleanup instance: */ 147 m_spInstance = 0; 148 } 149 150 /** Returns the instance of wrapper(s) to load/save the data from/to. */ 151 QVariant& data() { return m_data; } 152 153 /** Raises the priority of page with @a iPageId. */ 154 void raisePriorityOfPage(int iPageId) 155 { 156 /* If that page is present and was not processed already => 157 * we should remember which page should be processed next: */ 158 if (m_pages.contains(iPageId) && !(m_pages[iPageId]->processed())) 159 m_iIdOfHighPriorityPage = iPageId; 160 } 161 162 public slots: 163 164 /** Starts the process of data loading with passed @a priority. */ 165 void start(Priority priority = InheritPriority) 166 { 167 /* Notify listeners about we are starting: */ 168 emit sigNotifyAboutProcessStarted(); 169 170 /* If serializer saves settings: */ 171 if (m_direction == Save) 110 /* Allow to destroy serializer finally: */ 111 m_fAllowToDestroySerializer = true; 112 } 113 } 114 115 void UISettingsSerializer::sltHandleProcessedPage(int iPageId) 116 { 117 /* If serializer loads settings: */ 118 if (m_direction == Load) 119 { 120 /* If such page present: */ 121 if (m_pages.contains(iPageId)) 172 122 { 173 /* We should update internal page cache first: */ 174 foreach (UISettingsPage *pPage, m_pages.values()) 175 pPage->putToCache(); 123 /* We should fetch internal page cache: */ 124 UISettingsPage *pSettingsPage = m_pages[iPageId]; 125 pSettingsPage->setValidatorBlocked(true); 126 pSettingsPage->getFromCache(); 127 pSettingsPage->setValidatorBlocked(false); 176 128 } 177 178 /* Start async serializing thread: */ 179 QThread::start(priority); 180 181 /* If serializer saves settings: */ 182 if (m_direction == Save) 129 } 130 } 131 132 void UISettingsSerializer::sltHandleProcessedPages() 133 { 134 /* If serializer saves settings: */ 135 if (m_direction == Save) 136 { 137 /* We should flag GUI thread to unlock itself: */ 138 if (!m_fSavingComplete) 139 m_fSavingComplete = true; 140 } 141 /* If serializer loads settings: */ 142 else 143 { 144 /* We have to do initial validation finally: */ 145 foreach (UISettingsPage *pPage, m_pages.values()) 146 pPage->revalidate(); 147 } 148 } 149 150 void UISettingsSerializer::sltDestroySerializer() 151 { 152 /* If not yet all events were processed, 153 * we should postpone destruction for now: */ 154 if (!m_fAllowToDestroySerializer) 155 QTimer::singleShot(0, this, SLOT(sltDestroySerializer())); 156 else 157 deleteLater(); 158 } 159 160 void UISettingsSerializer::run() 161 { 162 /* Initialize COM for other thread: */ 163 COMBase::InitializeCOM(false); 164 165 /* Mark all the pages initially as NOT processed: */ 166 foreach (UISettingsPage *pPage, m_pages.values()) 167 pPage->setProcessed(false); 168 169 /* Iterate over the all left settings pages: */ 170 UISettingsPageMap pages(m_pages); 171 while (!pages.empty()) 172 { 173 /* Get required page pointer, protect map by mutex while getting pointer: */ 174 UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ? 175 pages.value(m_iIdOfHighPriorityPage) : *pages.begin(); 176 /* Reset request of high priority: */ 177 if (m_iIdOfHighPriorityPage != -1) 178 m_iIdOfHighPriorityPage = -1; 179 /* Process this page if its enabled: */ 180 if (pPage->isEnabled()) 183 181 { 184 /* We should block calling thread until all pages will be saved: */ 185 while (!m_fSavingComplete) 186 { 187 /* Lock mutex initially: */ 188 m_mutex.lock(); 189 /* Perform idle-processing every 100ms, 190 * and waiting for direct wake up signal: */ 191 m_condition.wait(&m_mutex, 100); 192 /* Process queued signals posted to GUI thread: */ 193 qApp->processEvents(); 194 /* Unlock mutex finally: */ 195 m_mutex.unlock(); 196 } 197 /* Allow to destroy serializer finally: */ 198 m_fAllowToDestroySerializer = true; 182 if (m_direction == Load) 183 pPage->loadToCacheFrom(m_data); 184 if (m_direction == Save) 185 pPage->saveFromCacheTo(m_data); 199 186 } 200 } 201 202 protected slots: 203 204 /** Handles the fact of some page was processed. */ 205 void sltHandleProcessedPage(int iPageId) 206 { 207 /* If serializer loads settings: */ 208 if (m_direction == Load) 209 { 210 /* If such page present: */ 211 if (m_pages.contains(iPageId)) 212 { 213 /* We should fetch internal page cache: */ 214 UISettingsPage *pSettingsPage = m_pages[iPageId]; 215 pSettingsPage->setValidatorBlocked(true); 216 pSettingsPage->getFromCache(); 217 pSettingsPage->setValidatorBlocked(false); 218 } 219 } 220 } 221 222 /** Handles the fact of all pages were processed. */ 223 void sltHandleProcessedPages() 224 { 225 /* If serializer saves settings: */ 226 if (m_direction == Save) 227 { 228 /* We should flag GUI thread to unlock itself: */ 229 if (!m_fSavingComplete) 230 m_fSavingComplete = true; 231 } 232 /* If serializer loads settings: */ 233 else 234 { 235 /* We have to do initial validation finally: */ 236 foreach (UISettingsPage *pPage, m_pages.values()) 237 pPage->revalidate(); 238 } 239 } 240 241 /** Killing serializer, softly :) */ 242 void sltDestroySerializer() 243 { 244 /* If not yet all events were processed, 245 * we should postpone destruction for now: */ 246 if (!m_fAllowToDestroySerializer) 247 QTimer::singleShot(0, this, SLOT(sltDestroySerializer())); 248 else 249 deleteLater(); 250 } 251 252 protected: 253 254 /** Settings serializer. */ 255 void run() 256 { 257 /* Initialize COM for other thread: */ 258 COMBase::InitializeCOM(false); 259 260 /* Mark all the pages initially as NOT processed: */ 261 foreach (UISettingsPage *pPage, m_pages.values()) 262 pPage->setProcessed(false); 263 264 /* Iterate over the all left settings pages: */ 265 UISettingsPageMap pages(m_pages); 266 while (!pages.empty()) 267 { 268 /* Get required page pointer, protect map by mutex while getting pointer: */ 269 UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ? 270 pages.value(m_iIdOfHighPriorityPage) : *pages.begin(); 271 /* Reset request of high priority: */ 272 if (m_iIdOfHighPriorityPage != -1) 273 m_iIdOfHighPriorityPage = -1; 274 /* Process this page if its enabled: */ 275 if (pPage->isEnabled()) 276 { 277 if (m_direction == Load) 278 pPage->loadToCacheFrom(m_data); 279 if (m_direction == Save) 280 pPage->saveFromCacheTo(m_data); 281 } 282 /* Remember what page was processed: */ 283 pPage->setProcessed(true); 284 /* Remove processed page from our map: */ 285 pages.remove(pPage->id()); 286 /* Notify listeners about page was processed: */ 287 emit sigNotifyAboutPageProcessed(pPage->id()); 288 /* If serializer saves settings => wake up GUI thread: */ 289 if (m_direction == Save) 290 m_condition.wakeAll(); 291 /* Break further processing if page had failed: */ 292 if (pPage->failed()) 293 break; 294 } 295 /* Notify listeners about all pages were processed: */ 296 emit sigNotifyAboutPagesProcessed(); 187 /* Remember what page was processed: */ 188 pPage->setProcessed(true); 189 /* Remove processed page from our map: */ 190 pages.remove(pPage->id()); 191 /* Notify listeners about page was processed: */ 192 emit sigNotifyAboutPageProcessed(pPage->id()); 297 193 /* If serializer saves settings => wake up GUI thread: */ 298 194 if (m_direction == Save) 299 195 m_condition.wakeAll(); 300 301 /* Deinitialize COM for other thread: */ 302 COMBase::CleanupCOM(); 303 } 304 305 /** Holds the singleton instance. */ 306 static UISettingsSerializer *m_spInstance; 307 308 /** Holds the the load/save direction. */ 309 SerializationDirection m_direction; 310 311 /** Holds the wrapper(s) to load/save the data from/to. */ 312 QVariant m_data; 313 /** Holds the page(s) to load/save the data to/from. */ 314 UISettingsPageMap m_pages; 315 316 /** Holds whether the save was complete. */ 317 bool m_fSavingComplete; 318 /** Holds whether it is allowed to destroy the serializer. */ 319 bool m_fAllowToDestroySerializer; 320 /** Holds the ID of the high priority page. */ 321 int m_iIdOfHighPriorityPage; 322 /** Holds the synchronization mutex. */ 323 QMutex m_mutex; 324 /** Holds the synchronization condition. */ 325 QWaitCondition m_condition; 326 }; 327 328 UISettingsSerializer* UISettingsSerializer::m_spInstance = 0; 329 330 UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent, 331 const QString &strCategory /* = QString() */, 332 const QString &strControl /* = QString() */) 333 : UISettingsDialog(pParent) 334 { 335 /* Window icon: */ 336 #ifndef Q_WS_MAC 337 setWindowIcon(QIcon(":/global_settings_16px.png")); 338 #endif /* !Q_WS_MAC */ 339 340 /* Creating settings pages: */ 341 QList<GlobalSettingsPageType> restrictedGlobalSettingsPages = gEDataManager->restrictedGlobalSettingsPages(); 342 for (int iPageIndex = GlobalSettingsPageType_General; iPageIndex < GlobalSettingsPageType_Max; ++iPageIndex) 343 { 344 /* Make sure page was not restricted: */ 345 if (restrictedGlobalSettingsPages.contains(static_cast<GlobalSettingsPageType>(iPageIndex))) 346 continue; 347 348 /* Make sure page is available: */ 349 if (isPageAvailable(iPageIndex)) 350 { 351 UISettingsPage *pSettingsPage = 0; 352 switch (iPageIndex) 353 { 354 /* General page: */ 355 case GlobalSettingsPageType_General: 356 { 357 pSettingsPage = new UIGlobalSettingsGeneral; 358 addItem(":/machine_32px.png", ":/machine_24px.png", ":/machine_16px.png", 359 iPageIndex, "#general", pSettingsPage); 360 break; 361 } 362 /* Input page: */ 363 case GlobalSettingsPageType_Input: 364 { 365 pSettingsPage = new UIGlobalSettingsInput; 366 addItem(":/keyboard_32px.png", ":/keyboard_24px.png", ":/keyboard_16px.png", 367 iPageIndex, "#input", pSettingsPage); 368 break; 369 } 370 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 371 /* Update page: */ 372 case GlobalSettingsPageType_Update: 373 { 374 pSettingsPage = new UIGlobalSettingsUpdate; 375 addItem(":/refresh_32px.png", ":/refresh_24px.png", ":/refresh_16px.png", 376 iPageIndex, "#update", pSettingsPage); 377 break; 378 } 379 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 380 /* Language page: */ 381 case GlobalSettingsPageType_Language: 382 { 383 pSettingsPage = new UIGlobalSettingsLanguage; 384 addItem(":/site_32px.png", ":/site_24px.png", ":/site_16px.png", 385 iPageIndex, "#language", pSettingsPage); 386 break; 387 } 388 /* Display page: */ 389 case GlobalSettingsPageType_Display: 390 { 391 pSettingsPage = new UIGlobalSettingsDisplay; 392 addItem(":/vrdp_32px.png", ":/vrdp_24px.png", ":/vrdp_16px.png", 393 iPageIndex, "#display", pSettingsPage); 394 break; 395 } 396 /* Network page: */ 397 case GlobalSettingsPageType_Network: 398 { 399 pSettingsPage = new UIGlobalSettingsNetwork; 400 addItem(":/nw_32px.png", ":/nw_24px.png", ":/nw_16px.png", 401 iPageIndex, "#network", pSettingsPage); 402 break; 403 } 404 /* Extensions page: */ 405 case GlobalSettingsPageType_Extensions: 406 { 407 pSettingsPage = new UIGlobalSettingsExtension; 408 addItem(":/extension_pack_32px.png", ":/extension_pack_24px.png", ":/extension_pack_16px.png", 409 iPageIndex, "#extensions", pSettingsPage); 410 break; 411 } 412 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 413 /* Proxy page: */ 414 case GlobalSettingsPageType_Proxy: 415 { 416 pSettingsPage = new UIGlobalSettingsProxy; 417 addItem(":/proxy_32px.png", ":/proxy_24px.png", ":/proxy_16px.png", 418 iPageIndex, "#proxy", pSettingsPage); 419 break; 420 } 421 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 422 default: 423 break; 424 } 425 } 426 } 427 428 /* Assign default (full) configuration access level: */ 429 setConfigurationAccessLevel(ConfigurationAccessLevel_Full); 430 431 /* Retranslate UI: */ 432 retranslateUi(); 433 434 /* Setup settings window: */ 435 if (!strCategory.isNull()) 436 { 437 m_pSelector->selectByLink(strCategory); 438 /* Search for a widget with the given name: */ 439 if (!strControl.isNull()) 440 { 441 if (QWidget *pWidget = m_pStack->findChild<QWidget*>(strControl)) 442 { 443 QList<QWidget*> parents; 444 QWidget *pParentWidget = pWidget; 445 while ((pParentWidget = pParentWidget->parentWidget()) != 0) 446 { 447 if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget)) 448 { 449 /* The tab contents widget is two steps down 450 * (QTabWidget -> QStackedWidget -> QWidget): */ 451 QWidget *pTabPage = parents[parents.count() - 1]; 452 if (pTabPage) 453 pTabPage = parents[parents.count() - 2]; 454 if (pTabPage) 455 pTabWidget->setCurrentWidget(pTabPage); 456 } 457 parents.append(pParentWidget); 458 } 459 pWidget->setFocus(); 460 } 461 } 462 } 463 /* First item as default: */ 464 else 465 m_pSelector->selectById(GlobalSettingsPageType_General); 466 } 467 468 UISettingsDialogGlobal::~UISettingsDialogGlobal() 469 { 470 /* Delete serializer early if exists: */ 471 if (UISettingsSerializer::instance()) 472 delete UISettingsSerializer::instance(); 473 } 474 475 void UISettingsDialogGlobal::loadData() 476 { 477 /* Call for base-class: */ 478 UISettingsDialog::loadData(); 479 480 /* Prepare global data: */ 481 qRegisterMetaType<UISettingsDataGlobal>(); 482 UISettingsDataGlobal data(vboxGlobal().virtualBox().GetSystemProperties(), vboxGlobal().settings()); 483 /* Create global settings loader, 484 * it will load global settings & delete itself in the appropriate time: */ 485 UISettingsSerializer *pGlobalSettingsLoader = new UISettingsSerializer(this, 486 UISettingsSerializer::Load, 487 QVariant::fromValue(data), 488 m_pSelector->settingPages()); 489 connect(pGlobalSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded())); 490 /* Start loader: */ 491 pGlobalSettingsLoader->start(); 492 } 493 494 void UISettingsDialogGlobal::saveData() 495 { 496 /* Call for base-class: */ 497 UISettingsDialog::saveData(); 498 499 /* Get properties and settings: */ 500 CSystemProperties properties = vboxGlobal().virtualBox().GetSystemProperties(); 501 VBoxGlobalSettings settings = vboxGlobal().settings(); 502 /* Prepare global data: */ 503 qRegisterMetaType<UISettingsDataGlobal>(); 504 UISettingsDataGlobal data(properties, settings); 505 /* Create global settings saver, 506 * it will save global settings & delete itself in the appropriate time: */ 507 UISettingsSerializer *pGlobalSettingsSaver = new UISettingsSerializer(this, 508 UISettingsSerializer::Save, 509 QVariant::fromValue(data), 510 m_pSelector->settingPages()); 511 /* Start saver: */ 512 pGlobalSettingsSaver->start(); 513 514 /* Get updated properties & settings: */ 515 CSystemProperties newProperties = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_properties; 516 VBoxGlobalSettings newSettings = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_settings; 517 /* If properties are not OK => show the error: */ 518 if (!newProperties.isOk()) 519 msgCenter().cannotSetSystemProperties(newProperties, this); 520 /* Else save the new settings if they were changed: */ 521 else if (!(newSettings == settings)) 522 vboxGlobal().setSettings(newSettings); 523 524 /* Mark page processed: */ 525 sltMarkSaved(); 526 } 527 528 void UISettingsDialogGlobal::retranslateUi() 529 { 530 /* General page: */ 531 m_pSelector->setItemText(GlobalSettingsPageType_General, tr("General")); 532 533 /* Input page: */ 534 m_pSelector->setItemText(GlobalSettingsPageType_Input, tr("Input")); 535 536 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 537 /* Update page: */ 538 m_pSelector->setItemText(GlobalSettingsPageType_Update, tr("Update")); 539 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 540 541 /* Language page: */ 542 m_pSelector->setItemText(GlobalSettingsPageType_Language, tr("Language")); 543 544 /* Display page: */ 545 m_pSelector->setItemText(GlobalSettingsPageType_Display, tr("Display")); 546 547 /* Network page: */ 548 m_pSelector->setItemText(GlobalSettingsPageType_Network, tr("Network")); 549 550 /* Extension page: */ 551 m_pSelector->setItemText(GlobalSettingsPageType_Extensions, tr("Extensions")); 552 553 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 554 /* Proxy page: */ 555 m_pSelector->setItemText(GlobalSettingsPageType_Proxy, tr("Proxy")); 556 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 557 558 /* Polish the selector: */ 559 m_pSelector->polish(); 560 561 /* Base-class UI translation: */ 562 UISettingsDialog::retranslateUi(); 563 564 /* Set dialog's name: */ 565 setWindowTitle(title()); 566 } 567 568 QString UISettingsDialogGlobal::title() const 569 { 570 return tr("VirtualBox - %1").arg(titleExtension()); 571 } 572 573 bool UISettingsDialogGlobal::isPageAvailable(int iPageId) 574 { 575 switch (iPageId) 576 { 577 case GlobalSettingsPageType_Network: 578 { 579 #ifndef VBOX_WITH_NETFLT 580 return false; 581 #endif /* !VBOX_WITH_NETFLT */ 196 /* Break further processing if page had failed: */ 197 if (pPage->failed()) 582 198 break; 583 } 584 default: 585 break; 586 } 587 return true; 588 } 589 590 UISettingsDialogMachine::UISettingsDialogMachine(QWidget *pParent, const QString &strMachineId, 591 const QString &strCategory, const QString &strControl) 592 : UISettingsDialog(pParent) 593 , m_strMachineId(strMachineId) 594 , m_fAllowResetFirstRunFlag(false) 595 , m_fResetFirstRunFlag(false) 596 { 597 /* Window icon: */ 598 #ifndef Q_WS_MAC 599 setWindowIcon(QIcon(":/vm_settings_16px.png")); 600 #endif /* Q_WS_MAC */ 601 602 /* Allow to reset first-run flag just when medium enumeration was finished: */ 603 connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished()), this, SLOT(sltAllowResetFirstRunFlag())); 604 605 /* Get corresponding machine (required to determine dialog type and page availability): */ 606 m_machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId); 607 AssertMsg(!m_machine.isNull(), ("Can't find corresponding machine!\n")); 608 m_sessionState = m_machine.GetSessionState(); 609 m_machineState = m_machine.GetState(); 610 611 /* Creating settings pages: */ 612 QList<MachineSettingsPageType> restrictedMachineSettingsPages = gEDataManager->restrictedMachineSettingsPages(m_strMachineId); 613 for (int iPageIndex = MachineSettingsPageType_General; iPageIndex < MachineSettingsPageType_Max; ++iPageIndex) 614 { 615 /* Make sure page was not restricted: */ 616 if (restrictedMachineSettingsPages.contains(static_cast<MachineSettingsPageType>(iPageIndex))) 617 continue; 618 619 /* Make sure page is available: */ 620 if (isPageAvailable(iPageIndex)) 621 { 622 UISettingsPage *pSettingsPage = 0; 623 switch (iPageIndex) 624 { 625 /* General page: */ 626 case MachineSettingsPageType_General: 627 { 628 pSettingsPage = new UIMachineSettingsGeneral; 629 addItem(":/machine_32px.png", ":/machine_24px.png", ":/machine_16px.png", 630 iPageIndex, "#general", pSettingsPage); 631 break; 632 } 633 /* System page: */ 634 case MachineSettingsPageType_System: 635 { 636 pSettingsPage = new UIMachineSettingsSystem; 637 addItem(":/chipset_32px.png", ":/chipset_24px.png", ":/chipset_16px.png", 638 iPageIndex, "#system", pSettingsPage); 639 break; 640 } 641 /* Display page: */ 642 case MachineSettingsPageType_Display: 643 { 644 pSettingsPage = new UIMachineSettingsDisplay; 645 addItem(":/vrdp_32px.png", ":/vrdp_24px.png", ":/vrdp_16px.png", 646 iPageIndex, "#display", pSettingsPage); 647 break; 648 } 649 /* Storage page: */ 650 case MachineSettingsPageType_Storage: 651 { 652 pSettingsPage = new UIMachineSettingsStorage; 653 connect(pSettingsPage, SIGNAL(storageChanged()), this, SLOT(sltResetFirstRunFlag())); 654 addItem(":/hd_32px.png", ":/hd_24px.png", ":/hd_16px.png", 655 iPageIndex, "#storage", pSettingsPage); 656 break; 657 } 658 /* Audio page: */ 659 case MachineSettingsPageType_Audio: 660 { 661 pSettingsPage = new UIMachineSettingsAudio; 662 addItem(":/sound_32px.png", ":/sound_24px.png", ":/sound_16px.png", 663 iPageIndex, "#audio", pSettingsPage); 664 break; 665 } 666 /* Network page: */ 667 case MachineSettingsPageType_Network: 668 { 669 pSettingsPage = new UIMachineSettingsNetworkPage; 670 addItem(":/nw_32px.png", ":/nw_24px.png", ":/nw_16px.png", 671 iPageIndex, "#network", pSettingsPage); 672 break; 673 } 674 /* Ports page: */ 675 case MachineSettingsPageType_Ports: 676 { 677 addItem(":/serial_port_32px.png", ":/serial_port_24px.png", ":/serial_port_16px.png", 678 iPageIndex, "#ports"); 679 break; 680 } 681 /* Serial page: */ 682 case MachineSettingsPageType_Serial: 683 { 684 pSettingsPage = new UIMachineSettingsSerialPage; 685 addItem(":/serial_port_32px.png", ":/serial_port_24px.png", ":/serial_port_16px.png", 686 iPageIndex, "#serialPorts", pSettingsPage, MachineSettingsPageType_Ports); 687 break; 688 } 689 /* Parallel page: */ 690 case MachineSettingsPageType_Parallel: 691 { 692 pSettingsPage = new UIMachineSettingsParallelPage; 693 addItem(":/parallel_port_32px.png", ":/parallel_port_24px.png", ":/parallel_port_16px.png", 694 iPageIndex, "#parallelPorts", pSettingsPage, MachineSettingsPageType_Ports); 695 break; 696 } 697 /* USB page: */ 698 case MachineSettingsPageType_USB: 699 { 700 pSettingsPage = new UIMachineSettingsUSB; 701 addItem(":/usb_32px.png", ":/usb_24px.png", ":/usb_16px.png", 702 iPageIndex, "#usb", pSettingsPage, MachineSettingsPageType_Ports); 703 break; 704 } 705 /* Shared Folders page: */ 706 case MachineSettingsPageType_SF: 707 { 708 pSettingsPage = new UIMachineSettingsSF; 709 addItem(":/sf_32px.png", ":/sf_24px.png", ":/sf_16px.png", 710 iPageIndex, "#sharedFolders", pSettingsPage); 711 break; 712 } 713 /* Interface page: */ 714 case MachineSettingsPageType_Interface: 715 { 716 pSettingsPage = new UIMachineSettingsInterface(m_machine.GetId()); 717 addItem(":/interface_32px.png", ":/interface_24px.png", ":/interface_16px.png", 718 iPageIndex, "#userInterface", pSettingsPage); 719 break; 720 } 721 default: 722 break; 723 } 724 } 725 } 726 727 /* Recalculate configuration access level: */ 728 updateConfigurationAccessLevel(); 729 730 /* Retranslate UI: */ 731 retranslateUi(); 732 733 /* Setup settings window: */ 734 if (!strCategory.isNull()) 735 { 736 m_pSelector->selectByLink(strCategory); 737 /* Search for a widget with the given name: */ 738 if (!strControl.isNull()) 739 { 740 if (QWidget *pWidget = m_pStack->findChild<QWidget*>(strControl)) 741 { 742 QList<QWidget*> parents; 743 QWidget *pParentWidget = pWidget; 744 while ((pParentWidget = pParentWidget->parentWidget()) != 0) 745 { 746 if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget)) 747 { 748 /* The tab contents widget is two steps down 749 * (QTabWidget -> QStackedWidget -> QWidget): */ 750 QWidget *pTabPage = parents[parents.count() - 1]; 751 if (pTabPage) 752 pTabPage = parents[parents.count() - 2]; 753 if (pTabPage) 754 pTabWidget->setCurrentWidget(pTabPage); 755 } 756 parents.append(pParentWidget); 757 } 758 pWidget->setFocus(); 759 } 760 } 761 } 762 /* First item as default: */ 763 else 764 m_pSelector->selectById(MachineSettingsPageType_General); 765 } 766 767 UISettingsDialogMachine::~UISettingsDialogMachine() 768 { 769 /* Delete serializer early if exists: */ 770 if (UISettingsSerializer::instance()) 771 delete UISettingsSerializer::instance(); 772 } 773 774 void UISettingsDialogMachine::loadData() 775 { 776 /* Check that session is NOT created: */ 777 if (!m_session.isNull()) 778 return; 779 780 /* Call for base-class: */ 781 UISettingsDialog::loadData(); 782 783 /* Disconnect global VBox events from this dialog: */ 784 gVBoxEvents->disconnect(this); 785 786 /* Prepare session: */ 787 m_session = configurationAccessLevel() == ConfigurationAccessLevel_Null ? CSession() : vboxGlobal().openExistingSession(m_strMachineId); 788 /* Check that session was created: */ 789 if (m_session.isNull()) 790 return; 791 792 /* Get machine from session: */ 793 m_machine = m_session.GetMachine(); 794 /* Get console from session: */ 795 m_console = configurationAccessLevel() == ConfigurationAccessLevel_Full ? CConsole() : m_session.GetConsole(); 796 797 /* Prepare machine data: */ 798 qRegisterMetaType<UISettingsDataMachine>(); 799 UISettingsDataMachine data(m_machine, m_console); 800 /* Create machine settings loader, 801 * it will load machine settings & delete itself in the appropriate time: */ 802 UISettingsSerializer *pMachineSettingsLoader = new UISettingsSerializer(this, 803 UISettingsSerializer::Load, 804 QVariant::fromValue(data), 805 m_pSelector->settingPages()); 806 connect(pMachineSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded())); 807 connect(pMachineSettingsLoader, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltSetFirstRunFlag())); 808 /* Ask to raise required page priority: */ 809 pMachineSettingsLoader->raisePriorityOfPage(m_pSelector->currentId()); 810 /* Start page loader: */ 811 pMachineSettingsLoader->start(); 812 } 813 814 void UISettingsDialogMachine::saveData() 815 { 816 /* Check that session is NOT created: */ 817 if (!m_session.isNull()) 818 return; 819 820 /* Call for base-class: */ 821 UISettingsDialog::saveData(); 822 823 /* Disconnect global VBox events from this dialog: */ 824 gVBoxEvents->disconnect(this); 825 826 /* Prepare session: */ 827 if (configurationAccessLevel() == ConfigurationAccessLevel_Null) 828 m_session = CSession(); 829 else if (configurationAccessLevel() != ConfigurationAccessLevel_Full) 830 m_session = vboxGlobal().openExistingSession(m_strMachineId); 831 else 832 m_session = vboxGlobal().openSession(m_strMachineId); 833 /* Check that session was created: */ 834 if (m_session.isNull()) 835 return; 836 837 /* Get machine from session: */ 838 m_machine = m_session.GetMachine(); 839 /* Get console from session: */ 840 m_console = configurationAccessLevel() == ConfigurationAccessLevel_Full ? CConsole() : m_session.GetConsole(); 841 842 /* Prepare machine data: */ 843 qRegisterMetaType<UISettingsDataMachine>(); 844 UISettingsDataMachine data(m_machine, m_console); 845 /* Create machine settings saver, 846 * it will save machine settings & delete itself in the appropriate time: */ 847 UISettingsSerializer *pMachineSettingsSaver = new UISettingsSerializer(this, 848 UISettingsSerializer::Save, 849 QVariant::fromValue(data), 850 m_pSelector->settingPages()); 851 /* Start saver: */ 852 pMachineSettingsSaver->start(); 853 854 /* Get updated machine: */ 855 m_machine = pMachineSettingsSaver->data().value<UISettingsDataMachine>().m_machine; 856 /* If machine is ok => perform final operations: */ 857 if (m_machine.isOk()) 858 { 859 /* Guest OS type & VT-x/AMD-V option correlation auto-fix: */ 860 UIMachineSettingsGeneral *pGeneralPage = 861 qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General)); 862 UIMachineSettingsSystem *pSystemPage = 863 qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System)); 864 if (pGeneralPage && pSystemPage && 865 pGeneralPage->is64BitOSTypeSelected() && !pSystemPage->isHWVirtExEnabled()) 866 m_machine.SetHWVirtExProperty(KHWVirtExPropertyType_Enabled, true); 867 868 #ifdef VBOX_WITH_VIDEOHWACCEL 869 /* Disable 2D Video Acceleration for non-Windows guests: */ 870 if (pGeneralPage && !pGeneralPage->isWindowsOSTypeSelected()) 871 { 872 UIMachineSettingsDisplay *pDisplayPage = 873 qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display)); 874 if (pDisplayPage && pDisplayPage->isAcceleration2DVideoSelected()) 875 m_machine.SetAccelerate2DVideoEnabled(false); 876 } 877 #endif /* VBOX_WITH_VIDEOHWACCEL */ 878 879 /* Enable OHCI controller if HID is enabled but no USB controllers present: */ 880 if (pSystemPage && pSystemPage->isHIDEnabled() && m_machine.GetUSBControllers().isEmpty()) 881 m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI); 882 883 /* Disable First RUN Wizard: */ 884 if (m_fResetFirstRunFlag) 885 gEDataManager->setMachineFirstTimeStarted(false, m_strMachineId); 886 887 /* Save settings finally: */ 888 m_machine.SaveSettings(); 889 } 890 891 /* If machine is NOT ok => show the error message: */ 892 if (!m_machine.isOk()) 893 msgCenter().cannotSaveMachineSettings(m_machine, this); 894 895 /* Mark page processed: */ 896 sltMarkSaved(); 897 } 898 899 void UISettingsDialogMachine::retranslateUi() 900 { 901 /* We have to make sure that the Network, Serial & Parallel pages are retranslated 902 * before they are revalidated. Cause: They do string comparing within 903 * vboxGlobal which is retranslated at that point already: */ 904 QEvent event(QEvent::LanguageChange); 905 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Network)) 906 qApp->sendEvent(pPage, &event); 907 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Serial)) 908 qApp->sendEvent(pPage, &event); 909 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Parallel)) 910 qApp->sendEvent(pPage, &event); 911 912 /* General page: */ 913 m_pSelector->setItemText(MachineSettingsPageType_General, tr("General")); 914 915 /* System page: */ 916 m_pSelector->setItemText(MachineSettingsPageType_System, tr("System")); 917 918 /* Display page: */ 919 m_pSelector->setItemText(MachineSettingsPageType_Display, tr("Display")); 920 921 /* Storage page: */ 922 m_pSelector->setItemText(MachineSettingsPageType_Storage, tr("Storage")); 923 924 /* Audio page: */ 925 m_pSelector->setItemText(MachineSettingsPageType_Audio, tr("Audio")); 926 927 /* Network page: */ 928 m_pSelector->setItemText(MachineSettingsPageType_Network, tr("Network")); 929 930 /* Ports page: */ 931 m_pSelector->setItemText(MachineSettingsPageType_Ports, tr("Ports")); 932 933 /* Serial page: */ 934 m_pSelector->setItemText(MachineSettingsPageType_Serial, tr("Serial Ports")); 935 936 /* Parallel page: */ 937 m_pSelector->setItemText(MachineSettingsPageType_Parallel, tr("Parallel Ports")); 938 939 /* USB page: */ 940 m_pSelector->setItemText(MachineSettingsPageType_USB, tr("USB")); 941 942 /* SFolders page: */ 943 m_pSelector->setItemText(MachineSettingsPageType_SF, tr("Shared Folders")); 944 945 /* Interface page: */ 946 m_pSelector->setItemText(MachineSettingsPageType_Interface, tr("User Interface")); 947 948 /* Polish the selector: */ 949 m_pSelector->polish(); 950 951 /* Base-class UI translation: */ 952 UISettingsDialog::retranslateUi(); 953 954 /* Set dialog's name: */ 955 setWindowTitle(title()); 956 } 957 958 QString UISettingsDialogMachine::title() const 959 { 960 QString strDialogTitle; 961 /* Get corresponding machine (required to compose dialog title): */ 962 const CMachine &machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId); 963 if (!machine.isNull()) 964 strDialogTitle = tr("%1 - %2").arg(machine.GetName()).arg(titleExtension()); 965 return strDialogTitle; 966 } 967 968 void UISettingsDialogMachine::recorrelate(UISettingsPage *pSettingsPage) 969 { 970 switch (pSettingsPage->id()) 971 { 972 /* General page correlations: */ 973 case MachineSettingsPageType_General: 974 { 975 /* Make changes on 'general' page influent 'display' page: */ 976 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(pSettingsPage); 977 UIMachineSettingsDisplay *pDisplayPage = qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display)); 978 if (pGeneralPage && pDisplayPage) 979 pDisplayPage->setGuestOSType(pGeneralPage->guestOSType()); 980 break; 981 } 982 /* System page correlations: */ 983 case MachineSettingsPageType_System: 984 { 985 /* Make changes on 'system' page influent 'general' and 'storage' page: */ 986 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(pSettingsPage); 987 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General)); 988 UIMachineSettingsStorage *pStoragePage = qobject_cast<UIMachineSettingsStorage*>(m_pSelector->idToPage(MachineSettingsPageType_Storage)); 989 if (pSystemPage) 990 { 991 if (pGeneralPage) 992 pGeneralPage->setHWVirtExEnabled(pSystemPage->isHWVirtExEnabled()); 993 if (pStoragePage) 994 pStoragePage->setChipsetType(pSystemPage->chipsetType()); 995 } 996 break; 997 } 998 /* USB page correlations: */ 999 case MachineSettingsPageType_USB: 1000 { 1001 /* Make changes on 'usb' page influent 'system' page: */ 1002 UIMachineSettingsUSB *pUsbPage = qobject_cast<UIMachineSettingsUSB*>(pSettingsPage); 1003 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System)); 1004 if (pUsbPage && pSystemPage) 1005 pSystemPage->setUSBEnabled(pUsbPage->isUSBEnabled()); 1006 break; 1007 } 1008 default: 1009 break; 1010 } 1011 } 1012 1013 void UISettingsDialogMachine::sltMarkLoaded() 1014 { 1015 /* Call for base-class: */ 1016 UISettingsDialog::sltMarkLoaded(); 1017 1018 /* Unlock the session if exists: */ 1019 if (!m_session.isNull()) 1020 { 1021 m_session.UnlockMachine(); 1022 m_session = CSession(); 1023 m_machine = CMachine(); 1024 m_console = CConsole(); 1025 } 1026 1027 /* Make sure settings window will be updated on machine state/data changes: */ 1028 connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)), 1029 this, SLOT(sltSessionStateChanged(QString, KSessionState))); 1030 connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)), 1031 this, SLOT(sltMachineStateChanged(QString, KMachineState))); 1032 connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), 1033 this, SLOT(sltMachineDataChanged(QString))); 1034 } 1035 1036 void UISettingsDialogMachine::sltMarkSaved() 1037 { 1038 /* Call for base-class: */ 1039 UISettingsDialog::sltMarkSaved(); 1040 1041 /* Unlock the session if exists: */ 1042 if (!m_session.isNull()) 1043 { 1044 m_session.UnlockMachine(); 1045 m_session = CSession(); 1046 m_machine = CMachine(); 1047 m_console = CConsole(); 1048 } 1049 } 1050 1051 void UISettingsDialogMachine::sltSessionStateChanged(QString strMachineId, KSessionState sessionState) 1052 { 1053 /* Ignore if thats NOT our VM: */ 1054 if (strMachineId != m_strMachineId) 1055 return; 1056 1057 /* Ignore if state was NOT actually changed: */ 1058 if (m_sessionState == sessionState) 1059 return; 1060 1061 /* Update current session state: */ 1062 m_sessionState = sessionState; 1063 1064 /* Recalculate configuration access level: */ 1065 updateConfigurationAccessLevel(); 1066 } 1067 1068 void UISettingsDialogMachine::sltMachineStateChanged(QString strMachineId, KMachineState machineState) 1069 { 1070 /* Ignore if thats NOT our VM: */ 1071 if (strMachineId != m_strMachineId) 1072 return; 1073 1074 /* Ignore if state was NOT actually changed: */ 1075 if (m_machineState == machineState) 1076 return; 1077 1078 /* Update current machine state: */ 1079 m_machineState = machineState; 1080 1081 /* Recalculate configuration access level: */ 1082 updateConfigurationAccessLevel(); 1083 } 1084 1085 void UISettingsDialogMachine::sltMachineDataChanged(QString strMachineId) 1086 { 1087 /* Ignore if thats NOT our VM: */ 1088 if (strMachineId != m_strMachineId) 1089 return; 1090 1091 /* Check if user had changed something and warn him about he will loose settings on reloading: */ 1092 if (isSettingsChanged() && !msgCenter().confirmSettingsReloading(this)) 1093 return; 1094 1095 /* Reload data: */ 1096 loadData(); 1097 } 1098 1099 void UISettingsDialogMachine::sltCategoryChanged(int cId) 1100 { 1101 if (UISettingsSerializer::instance()) 1102 UISettingsSerializer::instance()->raisePriorityOfPage(cId); 1103 1104 UISettingsDialog::sltCategoryChanged(cId); 1105 } 1106 1107 void UISettingsDialogMachine::sltAllowResetFirstRunFlag() 1108 { 1109 m_fAllowResetFirstRunFlag = true; 1110 } 1111 1112 void UISettingsDialogMachine::sltSetFirstRunFlag() 1113 { 1114 m_fResetFirstRunFlag = false; 1115 } 1116 1117 void UISettingsDialogMachine::sltResetFirstRunFlag() 1118 { 1119 if (m_fAllowResetFirstRunFlag) 1120 m_fResetFirstRunFlag = true; 1121 } 1122 1123 bool UISettingsDialogMachine::isPageAvailable(int iPageId) 1124 { 1125 if (m_machine.isNull()) 1126 return false; 1127 1128 switch (iPageId) 1129 { 1130 case MachineSettingsPageType_Serial: 1131 { 1132 /* Depends on ports availability: */ 1133 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1134 return false; 1135 break; 1136 } 1137 case MachineSettingsPageType_Parallel: 1138 { 1139 /* Depends on ports availability: */ 1140 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1141 return false; 1142 /* But for now this page is always disabled: */ 1143 return false; 1144 } 1145 case MachineSettingsPageType_USB: 1146 { 1147 /* Depends on ports availability: */ 1148 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1149 return false; 1150 /* Check if USB is implemented: */ 1151 if (!m_machine.GetUSBProxyAvailable()) 1152 return false; 1153 /* Get the USB controller object: */ 1154 CUSBControllerVector controllerColl = m_machine.GetUSBControllers(); 1155 /* Show the machine error message if any: */ 1156 if ( !m_machine.isReallyOk() 1157 && controllerColl.size() > 0 1158 && !m_machine.GetUSBControllers().isEmpty()) 1159 msgCenter().warnAboutUnaccessibleUSB(m_machine, parentWidget()); 1160 break; 1161 } 1162 default: 1163 break; 1164 } 1165 return true; 1166 } 1167 1168 bool UISettingsDialogMachine::isSettingsChanged() 1169 { 1170 bool fIsSettingsChanged = false; 1171 foreach (UISettingsPage *pPage, m_pSelector->settingPages()) 1172 { 1173 pPage->putToCache(); 1174 if (!fIsSettingsChanged && pPage->changed()) 1175 fIsSettingsChanged = true; 1176 } 1177 return fIsSettingsChanged; 1178 } 1179 1180 void UISettingsDialogMachine::updateConfigurationAccessLevel() 1181 { 1182 /* Determine new configuration access level: */ 1183 ConfigurationAccessLevel newConfigurationAccessLevel = ::configurationAccessLevel(m_sessionState, m_machineState); 1184 1185 /* Make sure someting changed: */ 1186 if (configurationAccessLevel() == newConfigurationAccessLevel) 1187 return; 1188 1189 /* Should we warn a user about access level decrease? */ 1190 bool fShouldWeWarn = configurationAccessLevel() == ConfigurationAccessLevel_Full; 1191 1192 /* Apply new configuration access level: */ 1193 setConfigurationAccessLevel(newConfigurationAccessLevel); 1194 1195 /* Show a warning about access level decrease if we should: */ 1196 if (isSettingsChanged() && fShouldWeWarn) 1197 msgCenter().warnAboutStateChange(this); 1198 } 1199 1200 # include "UISettingsDialogSpecific.moc" 1201 199 } 200 /* Notify listeners about all pages were processed: */ 201 emit sigNotifyAboutPagesProcessed(); 202 /* If serializer saves settings => wake up GUI thread: */ 203 if (m_direction == Save) 204 m_condition.wakeAll(); 205 206 /* Deinitialize COM for other thread: */ 207 COMBase::CleanupCOM(); 208 } 209 -
trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsSerializer.h
r54883 r54886 1 /* $Id$ */2 1 /** @file 3 * VBox Qt GUI - UISettings DialogSpecific class implementation.2 * VBox Qt GUI - UISettingsSerializer class declaration. 4 3 */ 5 4 6 5 /* 7 * Copyright (C) 2006-201 2Oracle Corporation6 * Copyright (C) 2006-2015 Oracle Corporation 8 7 * 9 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 15 */ 17 16 18 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 19 # include <precomp.h> 20 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 17 #ifndef ___UISettingsSerializer_h___ 18 #define ___UISettingsSerializer_h___ 21 19 22 20 /* Qt includes: */ 23 # include <QStackedWidget> 24 # include <QThread> 25 # include <QMutex> 26 # include <QWaitCondition> 27 # include <QTimer> 21 #include <QThread> 22 #include <QVariant> 23 #include <QWaitCondition> 24 #include <QMutex> 25 #include <QList> 26 #include <QMap> 28 27 29 /* GUI includes: */ 30 # include "UISettingsDialogSpecific.h" 31 # include "UISettingsDefs.h" 32 # include "VBoxGlobal.h" 33 # include "UIMessageCenter.h" 34 # include "UIExtraDataManager.h" 35 # include "QIWidgetValidator.h" 36 # include "VBoxSettingsSelector.h" 37 # include "UIVirtualBoxEventHandler.h" 28 /* Forward declarations: */ 29 class UISettingsPage; 38 30 39 # include "UIGlobalSettingsGeneral.h" 40 # include "UIGlobalSettingsInput.h" 41 # ifdef VBOX_GUI_WITH_NETWORK_MANAGER 42 # include "UIGlobalSettingsUpdate.h" 43 # endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 44 # include "UIGlobalSettingsLanguage.h" 45 # include "UIGlobalSettingsDisplay.h" 46 # include "UIGlobalSettingsNetwork.h" 47 # include "UIGlobalSettingsExtension.h" 48 # ifdef VBOX_GUI_WITH_NETWORK_MANAGER 49 # include "UIGlobalSettingsProxy.h" 50 # endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 51 52 # include "UIMachineSettingsGeneral.h" 53 # include "UIMachineSettingsSystem.h" 54 # include "UIMachineSettingsDisplay.h" 55 # include "UIMachineSettingsStorage.h" 56 # include "UIMachineSettingsAudio.h" 57 # include "UIMachineSettingsNetwork.h" 58 # include "UIMachineSettingsSerial.h" 59 # include "UIMachineSettingsParallel.h" 60 # include "UIMachineSettingsUSB.h" 61 # include "UIMachineSettingsSF.h" 62 # include "UIMachineSettingsInterface.h" 63 64 /* COM includes: */ 65 # include "CUSBController.h" 66 67 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 68 69 70 #if 0 /* Global USB filters are DISABLED now: */ 71 # define ENABLE_GLOBAL_USB 72 #endif /* Global USB filters are DISABLED now: */ 73 74 /* Settings page list: */ 31 /* Type definitions: */ 75 32 typedef QList<UISettingsPage*> UISettingsPageList; 76 33 typedef QMap<int, UISettingsPage*> UISettingsPageMap; 77 34 78 35 /** QThread reimplementation used for 79 * loading/saving settings in async mode. 80 * @todo To be moved into the separate files! */ 36 * loading/saving settings in async mode. */ 81 37 class UISettingsSerializer : public QThread 82 38 { … … 108 64 * @param pages contains the page(s) to load/save the data to/from. */ 109 65 UISettingsSerializer(QObject *pParent, SerializationDirection direction, 110 const QVariant &data, const UISettingsPageList &pages) 111 : QThread(pParent) 112 , m_direction(direction) 113 , m_data(data) 114 , m_fSavingComplete(m_direction == Load) 115 , m_fAllowToDestroySerializer(m_direction == Load) 116 , m_iIdOfHighPriorityPage(-1) 117 { 118 /* Prepare instance: */ 119 m_spInstance = this; 120 121 /* Copy the page(s) from incoming list to our map: */ 122 for (int iPageIndex = 0; iPageIndex < pages.size(); ++iPageIndex) 123 { 124 UISettingsPage *pPage = pages[iPageIndex]; 125 m_pages.insert(pPage->id(), pPage); 126 } 127 128 /* Connecting this signals: */ 129 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), this, SLOT(sltHandleProcessedPage(int)), Qt::QueuedConnection); 130 connect(this, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltHandleProcessedPages()), Qt::QueuedConnection); 131 connect(this, SIGNAL(finished()), this, SLOT(sltDestroySerializer()), Qt::QueuedConnection); 132 /* Connecting parent signals: */ 133 connect(this, SIGNAL(sigNotifyAboutProcessStarted()), parent(), SLOT(sltHandleProcessStarted()), Qt::QueuedConnection); 134 connect(this, SIGNAL(sigNotifyAboutPageProcessed(int)), parent(), SLOT(sltHandlePageProcessed()), Qt::QueuedConnection); 135 } 66 const QVariant &data, const UISettingsPageList &pages); 136 67 137 68 /** Destructor. */ 138 ~UISettingsSerializer() 139 { 140 /* If serializer is being destructed by it's parent, 141 * thread could still be running, we have to wait 142 * for it to be finished! */ 143 if (isRunning()) 144 wait(); 145 146 /* Cleanup instance: */ 147 m_spInstance = 0; 148 } 69 ~UISettingsSerializer(); 149 70 150 71 /** Returns the instance of wrapper(s) to load/save the data from/to. */ … … 152 73 153 74 /** Raises the priority of page with @a iPageId. */ 154 void raisePriorityOfPage(int iPageId) 155 { 156 /* If that page is present and was not processed already => 157 * we should remember which page should be processed next: */ 158 if (m_pages.contains(iPageId) && !(m_pages[iPageId]->processed())) 159 m_iIdOfHighPriorityPage = iPageId; 160 } 75 void raisePriorityOfPage(int iPageId); 161 76 162 77 public slots: 163 78 164 79 /** Starts the process of data loading with passed @a priority. */ 165 void start(Priority priority = InheritPriority) 166 { 167 /* Notify listeners about we are starting: */ 168 emit sigNotifyAboutProcessStarted(); 169 170 /* If serializer saves settings: */ 171 if (m_direction == Save) 172 { 173 /* We should update internal page cache first: */ 174 foreach (UISettingsPage *pPage, m_pages.values()) 175 pPage->putToCache(); 176 } 177 178 /* Start async serializing thread: */ 179 QThread::start(priority); 180 181 /* If serializer saves settings: */ 182 if (m_direction == Save) 183 { 184 /* We should block calling thread until all pages will be saved: */ 185 while (!m_fSavingComplete) 186 { 187 /* Lock mutex initially: */ 188 m_mutex.lock(); 189 /* Perform idle-processing every 100ms, 190 * and waiting for direct wake up signal: */ 191 m_condition.wait(&m_mutex, 100); 192 /* Process queued signals posted to GUI thread: */ 193 qApp->processEvents(); 194 /* Unlock mutex finally: */ 195 m_mutex.unlock(); 196 } 197 /* Allow to destroy serializer finally: */ 198 m_fAllowToDestroySerializer = true; 199 } 200 } 80 void start(Priority priority = InheritPriority); 201 81 202 82 protected slots: 203 83 204 /** Handles the fact of some page was processed. */ 205 void sltHandleProcessedPage(int iPageId) 206 { 207 /* If serializer loads settings: */ 208 if (m_direction == Load) 209 { 210 /* If such page present: */ 211 if (m_pages.contains(iPageId)) 212 { 213 /* We should fetch internal page cache: */ 214 UISettingsPage *pSettingsPage = m_pages[iPageId]; 215 pSettingsPage->setValidatorBlocked(true); 216 pSettingsPage->getFromCache(); 217 pSettingsPage->setValidatorBlocked(false); 218 } 219 } 220 } 84 /** Handles the fact of page with @a iPageId was processed. */ 85 void sltHandleProcessedPage(int iPageId); 221 86 222 87 /** Handles the fact of all pages were processed. */ 223 void sltHandleProcessedPages() 224 { 225 /* If serializer saves settings: */ 226 if (m_direction == Save) 227 { 228 /* We should flag GUI thread to unlock itself: */ 229 if (!m_fSavingComplete) 230 m_fSavingComplete = true; 231 } 232 /* If serializer loads settings: */ 233 else 234 { 235 /* We have to do initial validation finally: */ 236 foreach (UISettingsPage *pPage, m_pages.values()) 237 pPage->revalidate(); 238 } 239 } 88 void sltHandleProcessedPages(); 240 89 241 90 /** Killing serializer, softly :) */ 242 void sltDestroySerializer() 243 { 244 /* If not yet all events were processed, 245 * we should postpone destruction for now: */ 246 if (!m_fAllowToDestroySerializer) 247 QTimer::singleShot(0, this, SLOT(sltDestroySerializer())); 248 else 249 deleteLater(); 250 } 91 void sltDestroySerializer(); 251 92 252 93 protected: 253 94 254 /** Settings serializer. */ 255 void run() 256 { 257 /* Initialize COM for other thread: */ 258 COMBase::InitializeCOM(false); 259 260 /* Mark all the pages initially as NOT processed: */ 261 foreach (UISettingsPage *pPage, m_pages.values()) 262 pPage->setProcessed(false); 263 264 /* Iterate over the all left settings pages: */ 265 UISettingsPageMap pages(m_pages); 266 while (!pages.empty()) 267 { 268 /* Get required page pointer, protect map by mutex while getting pointer: */ 269 UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ? 270 pages.value(m_iIdOfHighPriorityPage) : *pages.begin(); 271 /* Reset request of high priority: */ 272 if (m_iIdOfHighPriorityPage != -1) 273 m_iIdOfHighPriorityPage = -1; 274 /* Process this page if its enabled: */ 275 if (pPage->isEnabled()) 276 { 277 if (m_direction == Load) 278 pPage->loadToCacheFrom(m_data); 279 if (m_direction == Save) 280 pPage->saveFromCacheTo(m_data); 281 } 282 /* Remember what page was processed: */ 283 pPage->setProcessed(true); 284 /* Remove processed page from our map: */ 285 pages.remove(pPage->id()); 286 /* Notify listeners about page was processed: */ 287 emit sigNotifyAboutPageProcessed(pPage->id()); 288 /* If serializer saves settings => wake up GUI thread: */ 289 if (m_direction == Save) 290 m_condition.wakeAll(); 291 /* Break further processing if page had failed: */ 292 if (pPage->failed()) 293 break; 294 } 295 /* Notify listeners about all pages were processed: */ 296 emit sigNotifyAboutPagesProcessed(); 297 /* If serializer saves settings => wake up GUI thread: */ 298 if (m_direction == Save) 299 m_condition.wakeAll(); 300 301 /* Deinitialize COM for other thread: */ 302 COMBase::CleanupCOM(); 303 } 95 /** Worker-thread serialization rutine. */ 96 void run(); 304 97 305 98 /** Holds the singleton instance. */ … … 326 119 }; 327 120 328 UISettingsSerializer* UISettingsSerializer::m_spInstance = 0; 329 330 UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent, 331 const QString &strCategory /* = QString() */, 332 const QString &strControl /* = QString() */) 333 : UISettingsDialog(pParent) 334 { 335 /* Window icon: */ 336 #ifndef Q_WS_MAC 337 setWindowIcon(QIcon(":/global_settings_16px.png")); 338 #endif /* !Q_WS_MAC */ 339 340 /* Creating settings pages: */ 341 QList<GlobalSettingsPageType> restrictedGlobalSettingsPages = gEDataManager->restrictedGlobalSettingsPages(); 342 for (int iPageIndex = GlobalSettingsPageType_General; iPageIndex < GlobalSettingsPageType_Max; ++iPageIndex) 343 { 344 /* Make sure page was not restricted: */ 345 if (restrictedGlobalSettingsPages.contains(static_cast<GlobalSettingsPageType>(iPageIndex))) 346 continue; 347 348 /* Make sure page is available: */ 349 if (isPageAvailable(iPageIndex)) 350 { 351 UISettingsPage *pSettingsPage = 0; 352 switch (iPageIndex) 353 { 354 /* General page: */ 355 case GlobalSettingsPageType_General: 356 { 357 pSettingsPage = new UIGlobalSettingsGeneral; 358 addItem(":/machine_32px.png", ":/machine_24px.png", ":/machine_16px.png", 359 iPageIndex, "#general", pSettingsPage); 360 break; 361 } 362 /* Input page: */ 363 case GlobalSettingsPageType_Input: 364 { 365 pSettingsPage = new UIGlobalSettingsInput; 366 addItem(":/keyboard_32px.png", ":/keyboard_24px.png", ":/keyboard_16px.png", 367 iPageIndex, "#input", pSettingsPage); 368 break; 369 } 370 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 371 /* Update page: */ 372 case GlobalSettingsPageType_Update: 373 { 374 pSettingsPage = new UIGlobalSettingsUpdate; 375 addItem(":/refresh_32px.png", ":/refresh_24px.png", ":/refresh_16px.png", 376 iPageIndex, "#update", pSettingsPage); 377 break; 378 } 379 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 380 /* Language page: */ 381 case GlobalSettingsPageType_Language: 382 { 383 pSettingsPage = new UIGlobalSettingsLanguage; 384 addItem(":/site_32px.png", ":/site_24px.png", ":/site_16px.png", 385 iPageIndex, "#language", pSettingsPage); 386 break; 387 } 388 /* Display page: */ 389 case GlobalSettingsPageType_Display: 390 { 391 pSettingsPage = new UIGlobalSettingsDisplay; 392 addItem(":/vrdp_32px.png", ":/vrdp_24px.png", ":/vrdp_16px.png", 393 iPageIndex, "#display", pSettingsPage); 394 break; 395 } 396 /* Network page: */ 397 case GlobalSettingsPageType_Network: 398 { 399 pSettingsPage = new UIGlobalSettingsNetwork; 400 addItem(":/nw_32px.png", ":/nw_24px.png", ":/nw_16px.png", 401 iPageIndex, "#network", pSettingsPage); 402 break; 403 } 404 /* Extensions page: */ 405 case GlobalSettingsPageType_Extensions: 406 { 407 pSettingsPage = new UIGlobalSettingsExtension; 408 addItem(":/extension_pack_32px.png", ":/extension_pack_24px.png", ":/extension_pack_16px.png", 409 iPageIndex, "#extensions", pSettingsPage); 410 break; 411 } 412 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 413 /* Proxy page: */ 414 case GlobalSettingsPageType_Proxy: 415 { 416 pSettingsPage = new UIGlobalSettingsProxy; 417 addItem(":/proxy_32px.png", ":/proxy_24px.png", ":/proxy_16px.png", 418 iPageIndex, "#proxy", pSettingsPage); 419 break; 420 } 421 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 422 default: 423 break; 424 } 425 } 426 } 427 428 /* Assign default (full) configuration access level: */ 429 setConfigurationAccessLevel(ConfigurationAccessLevel_Full); 430 431 /* Retranslate UI: */ 432 retranslateUi(); 433 434 /* Setup settings window: */ 435 if (!strCategory.isNull()) 436 { 437 m_pSelector->selectByLink(strCategory); 438 /* Search for a widget with the given name: */ 439 if (!strControl.isNull()) 440 { 441 if (QWidget *pWidget = m_pStack->findChild<QWidget*>(strControl)) 442 { 443 QList<QWidget*> parents; 444 QWidget *pParentWidget = pWidget; 445 while ((pParentWidget = pParentWidget->parentWidget()) != 0) 446 { 447 if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget)) 448 { 449 /* The tab contents widget is two steps down 450 * (QTabWidget -> QStackedWidget -> QWidget): */ 451 QWidget *pTabPage = parents[parents.count() - 1]; 452 if (pTabPage) 453 pTabPage = parents[parents.count() - 2]; 454 if (pTabPage) 455 pTabWidget->setCurrentWidget(pTabPage); 456 } 457 parents.append(pParentWidget); 458 } 459 pWidget->setFocus(); 460 } 461 } 462 } 463 /* First item as default: */ 464 else 465 m_pSelector->selectById(GlobalSettingsPageType_General); 466 } 467 468 UISettingsDialogGlobal::~UISettingsDialogGlobal() 469 { 470 /* Delete serializer early if exists: */ 471 if (UISettingsSerializer::instance()) 472 delete UISettingsSerializer::instance(); 473 } 474 475 void UISettingsDialogGlobal::loadData() 476 { 477 /* Call for base-class: */ 478 UISettingsDialog::loadData(); 479 480 /* Prepare global data: */ 481 qRegisterMetaType<UISettingsDataGlobal>(); 482 UISettingsDataGlobal data(vboxGlobal().virtualBox().GetSystemProperties(), vboxGlobal().settings()); 483 /* Create global settings loader, 484 * it will load global settings & delete itself in the appropriate time: */ 485 UISettingsSerializer *pGlobalSettingsLoader = new UISettingsSerializer(this, 486 UISettingsSerializer::Load, 487 QVariant::fromValue(data), 488 m_pSelector->settingPages()); 489 connect(pGlobalSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded())); 490 /* Start loader: */ 491 pGlobalSettingsLoader->start(); 492 } 493 494 void UISettingsDialogGlobal::saveData() 495 { 496 /* Call for base-class: */ 497 UISettingsDialog::saveData(); 498 499 /* Get properties and settings: */ 500 CSystemProperties properties = vboxGlobal().virtualBox().GetSystemProperties(); 501 VBoxGlobalSettings settings = vboxGlobal().settings(); 502 /* Prepare global data: */ 503 qRegisterMetaType<UISettingsDataGlobal>(); 504 UISettingsDataGlobal data(properties, settings); 505 /* Create global settings saver, 506 * it will save global settings & delete itself in the appropriate time: */ 507 UISettingsSerializer *pGlobalSettingsSaver = new UISettingsSerializer(this, 508 UISettingsSerializer::Save, 509 QVariant::fromValue(data), 510 m_pSelector->settingPages()); 511 /* Start saver: */ 512 pGlobalSettingsSaver->start(); 513 514 /* Get updated properties & settings: */ 515 CSystemProperties newProperties = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_properties; 516 VBoxGlobalSettings newSettings = pGlobalSettingsSaver->data().value<UISettingsDataGlobal>().m_settings; 517 /* If properties are not OK => show the error: */ 518 if (!newProperties.isOk()) 519 msgCenter().cannotSetSystemProperties(newProperties, this); 520 /* Else save the new settings if they were changed: */ 521 else if (!(newSettings == settings)) 522 vboxGlobal().setSettings(newSettings); 523 524 /* Mark page processed: */ 525 sltMarkSaved(); 526 } 527 528 void UISettingsDialogGlobal::retranslateUi() 529 { 530 /* General page: */ 531 m_pSelector->setItemText(GlobalSettingsPageType_General, tr("General")); 532 533 /* Input page: */ 534 m_pSelector->setItemText(GlobalSettingsPageType_Input, tr("Input")); 535 536 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 537 /* Update page: */ 538 m_pSelector->setItemText(GlobalSettingsPageType_Update, tr("Update")); 539 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 540 541 /* Language page: */ 542 m_pSelector->setItemText(GlobalSettingsPageType_Language, tr("Language")); 543 544 /* Display page: */ 545 m_pSelector->setItemText(GlobalSettingsPageType_Display, tr("Display")); 546 547 /* Network page: */ 548 m_pSelector->setItemText(GlobalSettingsPageType_Network, tr("Network")); 549 550 /* Extension page: */ 551 m_pSelector->setItemText(GlobalSettingsPageType_Extensions, tr("Extensions")); 552 553 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 554 /* Proxy page: */ 555 m_pSelector->setItemText(GlobalSettingsPageType_Proxy, tr("Proxy")); 556 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 557 558 /* Polish the selector: */ 559 m_pSelector->polish(); 560 561 /* Base-class UI translation: */ 562 UISettingsDialog::retranslateUi(); 563 564 /* Set dialog's name: */ 565 setWindowTitle(title()); 566 } 567 568 QString UISettingsDialogGlobal::title() const 569 { 570 return tr("VirtualBox - %1").arg(titleExtension()); 571 } 572 573 bool UISettingsDialogGlobal::isPageAvailable(int iPageId) 574 { 575 switch (iPageId) 576 { 577 case GlobalSettingsPageType_Network: 578 { 579 #ifndef VBOX_WITH_NETFLT 580 return false; 581 #endif /* !VBOX_WITH_NETFLT */ 582 break; 583 } 584 default: 585 break; 586 } 587 return true; 588 } 589 590 UISettingsDialogMachine::UISettingsDialogMachine(QWidget *pParent, const QString &strMachineId, 591 const QString &strCategory, const QString &strControl) 592 : UISettingsDialog(pParent) 593 , m_strMachineId(strMachineId) 594 , m_fAllowResetFirstRunFlag(false) 595 , m_fResetFirstRunFlag(false) 596 { 597 /* Window icon: */ 598 #ifndef Q_WS_MAC 599 setWindowIcon(QIcon(":/vm_settings_16px.png")); 600 #endif /* Q_WS_MAC */ 601 602 /* Allow to reset first-run flag just when medium enumeration was finished: */ 603 connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished()), this, SLOT(sltAllowResetFirstRunFlag())); 604 605 /* Get corresponding machine (required to determine dialog type and page availability): */ 606 m_machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId); 607 AssertMsg(!m_machine.isNull(), ("Can't find corresponding machine!\n")); 608 m_sessionState = m_machine.GetSessionState(); 609 m_machineState = m_machine.GetState(); 610 611 /* Creating settings pages: */ 612 QList<MachineSettingsPageType> restrictedMachineSettingsPages = gEDataManager->restrictedMachineSettingsPages(m_strMachineId); 613 for (int iPageIndex = MachineSettingsPageType_General; iPageIndex < MachineSettingsPageType_Max; ++iPageIndex) 614 { 615 /* Make sure page was not restricted: */ 616 if (restrictedMachineSettingsPages.contains(static_cast<MachineSettingsPageType>(iPageIndex))) 617 continue; 618 619 /* Make sure page is available: */ 620 if (isPageAvailable(iPageIndex)) 621 { 622 UISettingsPage *pSettingsPage = 0; 623 switch (iPageIndex) 624 { 625 /* General page: */ 626 case MachineSettingsPageType_General: 627 { 628 pSettingsPage = new UIMachineSettingsGeneral; 629 addItem(":/machine_32px.png", ":/machine_24px.png", ":/machine_16px.png", 630 iPageIndex, "#general", pSettingsPage); 631 break; 632 } 633 /* System page: */ 634 case MachineSettingsPageType_System: 635 { 636 pSettingsPage = new UIMachineSettingsSystem; 637 addItem(":/chipset_32px.png", ":/chipset_24px.png", ":/chipset_16px.png", 638 iPageIndex, "#system", pSettingsPage); 639 break; 640 } 641 /* Display page: */ 642 case MachineSettingsPageType_Display: 643 { 644 pSettingsPage = new UIMachineSettingsDisplay; 645 addItem(":/vrdp_32px.png", ":/vrdp_24px.png", ":/vrdp_16px.png", 646 iPageIndex, "#display", pSettingsPage); 647 break; 648 } 649 /* Storage page: */ 650 case MachineSettingsPageType_Storage: 651 { 652 pSettingsPage = new UIMachineSettingsStorage; 653 connect(pSettingsPage, SIGNAL(storageChanged()), this, SLOT(sltResetFirstRunFlag())); 654 addItem(":/hd_32px.png", ":/hd_24px.png", ":/hd_16px.png", 655 iPageIndex, "#storage", pSettingsPage); 656 break; 657 } 658 /* Audio page: */ 659 case MachineSettingsPageType_Audio: 660 { 661 pSettingsPage = new UIMachineSettingsAudio; 662 addItem(":/sound_32px.png", ":/sound_24px.png", ":/sound_16px.png", 663 iPageIndex, "#audio", pSettingsPage); 664 break; 665 } 666 /* Network page: */ 667 case MachineSettingsPageType_Network: 668 { 669 pSettingsPage = new UIMachineSettingsNetworkPage; 670 addItem(":/nw_32px.png", ":/nw_24px.png", ":/nw_16px.png", 671 iPageIndex, "#network", pSettingsPage); 672 break; 673 } 674 /* Ports page: */ 675 case MachineSettingsPageType_Ports: 676 { 677 addItem(":/serial_port_32px.png", ":/serial_port_24px.png", ":/serial_port_16px.png", 678 iPageIndex, "#ports"); 679 break; 680 } 681 /* Serial page: */ 682 case MachineSettingsPageType_Serial: 683 { 684 pSettingsPage = new UIMachineSettingsSerialPage; 685 addItem(":/serial_port_32px.png", ":/serial_port_24px.png", ":/serial_port_16px.png", 686 iPageIndex, "#serialPorts", pSettingsPage, MachineSettingsPageType_Ports); 687 break; 688 } 689 /* Parallel page: */ 690 case MachineSettingsPageType_Parallel: 691 { 692 pSettingsPage = new UIMachineSettingsParallelPage; 693 addItem(":/parallel_port_32px.png", ":/parallel_port_24px.png", ":/parallel_port_16px.png", 694 iPageIndex, "#parallelPorts", pSettingsPage, MachineSettingsPageType_Ports); 695 break; 696 } 697 /* USB page: */ 698 case MachineSettingsPageType_USB: 699 { 700 pSettingsPage = new UIMachineSettingsUSB; 701 addItem(":/usb_32px.png", ":/usb_24px.png", ":/usb_16px.png", 702 iPageIndex, "#usb", pSettingsPage, MachineSettingsPageType_Ports); 703 break; 704 } 705 /* Shared Folders page: */ 706 case MachineSettingsPageType_SF: 707 { 708 pSettingsPage = new UIMachineSettingsSF; 709 addItem(":/sf_32px.png", ":/sf_24px.png", ":/sf_16px.png", 710 iPageIndex, "#sharedFolders", pSettingsPage); 711 break; 712 } 713 /* Interface page: */ 714 case MachineSettingsPageType_Interface: 715 { 716 pSettingsPage = new UIMachineSettingsInterface(m_machine.GetId()); 717 addItem(":/interface_32px.png", ":/interface_24px.png", ":/interface_16px.png", 718 iPageIndex, "#userInterface", pSettingsPage); 719 break; 720 } 721 default: 722 break; 723 } 724 } 725 } 726 727 /* Recalculate configuration access level: */ 728 updateConfigurationAccessLevel(); 729 730 /* Retranslate UI: */ 731 retranslateUi(); 732 733 /* Setup settings window: */ 734 if (!strCategory.isNull()) 735 { 736 m_pSelector->selectByLink(strCategory); 737 /* Search for a widget with the given name: */ 738 if (!strControl.isNull()) 739 { 740 if (QWidget *pWidget = m_pStack->findChild<QWidget*>(strControl)) 741 { 742 QList<QWidget*> parents; 743 QWidget *pParentWidget = pWidget; 744 while ((pParentWidget = pParentWidget->parentWidget()) != 0) 745 { 746 if (QTabWidget *pTabWidget = qobject_cast<QTabWidget*>(pParentWidget)) 747 { 748 /* The tab contents widget is two steps down 749 * (QTabWidget -> QStackedWidget -> QWidget): */ 750 QWidget *pTabPage = parents[parents.count() - 1]; 751 if (pTabPage) 752 pTabPage = parents[parents.count() - 2]; 753 if (pTabPage) 754 pTabWidget->setCurrentWidget(pTabPage); 755 } 756 parents.append(pParentWidget); 757 } 758 pWidget->setFocus(); 759 } 760 } 761 } 762 /* First item as default: */ 763 else 764 m_pSelector->selectById(MachineSettingsPageType_General); 765 } 766 767 UISettingsDialogMachine::~UISettingsDialogMachine() 768 { 769 /* Delete serializer early if exists: */ 770 if (UISettingsSerializer::instance()) 771 delete UISettingsSerializer::instance(); 772 } 773 774 void UISettingsDialogMachine::loadData() 775 { 776 /* Check that session is NOT created: */ 777 if (!m_session.isNull()) 778 return; 779 780 /* Call for base-class: */ 781 UISettingsDialog::loadData(); 782 783 /* Disconnect global VBox events from this dialog: */ 784 gVBoxEvents->disconnect(this); 785 786 /* Prepare session: */ 787 m_session = configurationAccessLevel() == ConfigurationAccessLevel_Null ? CSession() : vboxGlobal().openExistingSession(m_strMachineId); 788 /* Check that session was created: */ 789 if (m_session.isNull()) 790 return; 791 792 /* Get machine from session: */ 793 m_machine = m_session.GetMachine(); 794 /* Get console from session: */ 795 m_console = configurationAccessLevel() == ConfigurationAccessLevel_Full ? CConsole() : m_session.GetConsole(); 796 797 /* Prepare machine data: */ 798 qRegisterMetaType<UISettingsDataMachine>(); 799 UISettingsDataMachine data(m_machine, m_console); 800 /* Create machine settings loader, 801 * it will load machine settings & delete itself in the appropriate time: */ 802 UISettingsSerializer *pMachineSettingsLoader = new UISettingsSerializer(this, 803 UISettingsSerializer::Load, 804 QVariant::fromValue(data), 805 m_pSelector->settingPages()); 806 connect(pMachineSettingsLoader, SIGNAL(destroyed(QObject*)), this, SLOT(sltMarkLoaded())); 807 connect(pMachineSettingsLoader, SIGNAL(sigNotifyAboutPagesProcessed()), this, SLOT(sltSetFirstRunFlag())); 808 /* Ask to raise required page priority: */ 809 pMachineSettingsLoader->raisePriorityOfPage(m_pSelector->currentId()); 810 /* Start page loader: */ 811 pMachineSettingsLoader->start(); 812 } 813 814 void UISettingsDialogMachine::saveData() 815 { 816 /* Check that session is NOT created: */ 817 if (!m_session.isNull()) 818 return; 819 820 /* Call for base-class: */ 821 UISettingsDialog::saveData(); 822 823 /* Disconnect global VBox events from this dialog: */ 824 gVBoxEvents->disconnect(this); 825 826 /* Prepare session: */ 827 if (configurationAccessLevel() == ConfigurationAccessLevel_Null) 828 m_session = CSession(); 829 else if (configurationAccessLevel() != ConfigurationAccessLevel_Full) 830 m_session = vboxGlobal().openExistingSession(m_strMachineId); 831 else 832 m_session = vboxGlobal().openSession(m_strMachineId); 833 /* Check that session was created: */ 834 if (m_session.isNull()) 835 return; 836 837 /* Get machine from session: */ 838 m_machine = m_session.GetMachine(); 839 /* Get console from session: */ 840 m_console = configurationAccessLevel() == ConfigurationAccessLevel_Full ? CConsole() : m_session.GetConsole(); 841 842 /* Prepare machine data: */ 843 qRegisterMetaType<UISettingsDataMachine>(); 844 UISettingsDataMachine data(m_machine, m_console); 845 /* Create machine settings saver, 846 * it will save machine settings & delete itself in the appropriate time: */ 847 UISettingsSerializer *pMachineSettingsSaver = new UISettingsSerializer(this, 848 UISettingsSerializer::Save, 849 QVariant::fromValue(data), 850 m_pSelector->settingPages()); 851 /* Start saver: */ 852 pMachineSettingsSaver->start(); 853 854 /* Get updated machine: */ 855 m_machine = pMachineSettingsSaver->data().value<UISettingsDataMachine>().m_machine; 856 /* If machine is ok => perform final operations: */ 857 if (m_machine.isOk()) 858 { 859 /* Guest OS type & VT-x/AMD-V option correlation auto-fix: */ 860 UIMachineSettingsGeneral *pGeneralPage = 861 qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General)); 862 UIMachineSettingsSystem *pSystemPage = 863 qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System)); 864 if (pGeneralPage && pSystemPage && 865 pGeneralPage->is64BitOSTypeSelected() && !pSystemPage->isHWVirtExEnabled()) 866 m_machine.SetHWVirtExProperty(KHWVirtExPropertyType_Enabled, true); 867 868 #ifdef VBOX_WITH_VIDEOHWACCEL 869 /* Disable 2D Video Acceleration for non-Windows guests: */ 870 if (pGeneralPage && !pGeneralPage->isWindowsOSTypeSelected()) 871 { 872 UIMachineSettingsDisplay *pDisplayPage = 873 qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display)); 874 if (pDisplayPage && pDisplayPage->isAcceleration2DVideoSelected()) 875 m_machine.SetAccelerate2DVideoEnabled(false); 876 } 877 #endif /* VBOX_WITH_VIDEOHWACCEL */ 878 879 /* Enable OHCI controller if HID is enabled but no USB controllers present: */ 880 if (pSystemPage && pSystemPage->isHIDEnabled() && m_machine.GetUSBControllers().isEmpty()) 881 m_machine.AddUSBController("OHCI", KUSBControllerType_OHCI); 882 883 /* Disable First RUN Wizard: */ 884 if (m_fResetFirstRunFlag) 885 gEDataManager->setMachineFirstTimeStarted(false, m_strMachineId); 886 887 /* Save settings finally: */ 888 m_machine.SaveSettings(); 889 } 890 891 /* If machine is NOT ok => show the error message: */ 892 if (!m_machine.isOk()) 893 msgCenter().cannotSaveMachineSettings(m_machine, this); 894 895 /* Mark page processed: */ 896 sltMarkSaved(); 897 } 898 899 void UISettingsDialogMachine::retranslateUi() 900 { 901 /* We have to make sure that the Network, Serial & Parallel pages are retranslated 902 * before they are revalidated. Cause: They do string comparing within 903 * vboxGlobal which is retranslated at that point already: */ 904 QEvent event(QEvent::LanguageChange); 905 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Network)) 906 qApp->sendEvent(pPage, &event); 907 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Serial)) 908 qApp->sendEvent(pPage, &event); 909 if (QWidget *pPage = m_pSelector->idToPage(MachineSettingsPageType_Parallel)) 910 qApp->sendEvent(pPage, &event); 911 912 /* General page: */ 913 m_pSelector->setItemText(MachineSettingsPageType_General, tr("General")); 914 915 /* System page: */ 916 m_pSelector->setItemText(MachineSettingsPageType_System, tr("System")); 917 918 /* Display page: */ 919 m_pSelector->setItemText(MachineSettingsPageType_Display, tr("Display")); 920 921 /* Storage page: */ 922 m_pSelector->setItemText(MachineSettingsPageType_Storage, tr("Storage")); 923 924 /* Audio page: */ 925 m_pSelector->setItemText(MachineSettingsPageType_Audio, tr("Audio")); 926 927 /* Network page: */ 928 m_pSelector->setItemText(MachineSettingsPageType_Network, tr("Network")); 929 930 /* Ports page: */ 931 m_pSelector->setItemText(MachineSettingsPageType_Ports, tr("Ports")); 932 933 /* Serial page: */ 934 m_pSelector->setItemText(MachineSettingsPageType_Serial, tr("Serial Ports")); 935 936 /* Parallel page: */ 937 m_pSelector->setItemText(MachineSettingsPageType_Parallel, tr("Parallel Ports")); 938 939 /* USB page: */ 940 m_pSelector->setItemText(MachineSettingsPageType_USB, tr("USB")); 941 942 /* SFolders page: */ 943 m_pSelector->setItemText(MachineSettingsPageType_SF, tr("Shared Folders")); 944 945 /* Interface page: */ 946 m_pSelector->setItemText(MachineSettingsPageType_Interface, tr("User Interface")); 947 948 /* Polish the selector: */ 949 m_pSelector->polish(); 950 951 /* Base-class UI translation: */ 952 UISettingsDialog::retranslateUi(); 953 954 /* Set dialog's name: */ 955 setWindowTitle(title()); 956 } 957 958 QString UISettingsDialogMachine::title() const 959 { 960 QString strDialogTitle; 961 /* Get corresponding machine (required to compose dialog title): */ 962 const CMachine &machine = vboxGlobal().virtualBox().FindMachine(m_strMachineId); 963 if (!machine.isNull()) 964 strDialogTitle = tr("%1 - %2").arg(machine.GetName()).arg(titleExtension()); 965 return strDialogTitle; 966 } 967 968 void UISettingsDialogMachine::recorrelate(UISettingsPage *pSettingsPage) 969 { 970 switch (pSettingsPage->id()) 971 { 972 /* General page correlations: */ 973 case MachineSettingsPageType_General: 974 { 975 /* Make changes on 'general' page influent 'display' page: */ 976 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(pSettingsPage); 977 UIMachineSettingsDisplay *pDisplayPage = qobject_cast<UIMachineSettingsDisplay*>(m_pSelector->idToPage(MachineSettingsPageType_Display)); 978 if (pGeneralPage && pDisplayPage) 979 pDisplayPage->setGuestOSType(pGeneralPage->guestOSType()); 980 break; 981 } 982 /* System page correlations: */ 983 case MachineSettingsPageType_System: 984 { 985 /* Make changes on 'system' page influent 'general' and 'storage' page: */ 986 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(pSettingsPage); 987 UIMachineSettingsGeneral *pGeneralPage = qobject_cast<UIMachineSettingsGeneral*>(m_pSelector->idToPage(MachineSettingsPageType_General)); 988 UIMachineSettingsStorage *pStoragePage = qobject_cast<UIMachineSettingsStorage*>(m_pSelector->idToPage(MachineSettingsPageType_Storage)); 989 if (pSystemPage) 990 { 991 if (pGeneralPage) 992 pGeneralPage->setHWVirtExEnabled(pSystemPage->isHWVirtExEnabled()); 993 if (pStoragePage) 994 pStoragePage->setChipsetType(pSystemPage->chipsetType()); 995 } 996 break; 997 } 998 /* USB page correlations: */ 999 case MachineSettingsPageType_USB: 1000 { 1001 /* Make changes on 'usb' page influent 'system' page: */ 1002 UIMachineSettingsUSB *pUsbPage = qobject_cast<UIMachineSettingsUSB*>(pSettingsPage); 1003 UIMachineSettingsSystem *pSystemPage = qobject_cast<UIMachineSettingsSystem*>(m_pSelector->idToPage(MachineSettingsPageType_System)); 1004 if (pUsbPage && pSystemPage) 1005 pSystemPage->setUSBEnabled(pUsbPage->isUSBEnabled()); 1006 break; 1007 } 1008 default: 1009 break; 1010 } 1011 } 1012 1013 void UISettingsDialogMachine::sltMarkLoaded() 1014 { 1015 /* Call for base-class: */ 1016 UISettingsDialog::sltMarkLoaded(); 1017 1018 /* Unlock the session if exists: */ 1019 if (!m_session.isNull()) 1020 { 1021 m_session.UnlockMachine(); 1022 m_session = CSession(); 1023 m_machine = CMachine(); 1024 m_console = CConsole(); 1025 } 1026 1027 /* Make sure settings window will be updated on machine state/data changes: */ 1028 connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)), 1029 this, SLOT(sltSessionStateChanged(QString, KSessionState))); 1030 connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)), 1031 this, SLOT(sltMachineStateChanged(QString, KMachineState))); 1032 connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), 1033 this, SLOT(sltMachineDataChanged(QString))); 1034 } 1035 1036 void UISettingsDialogMachine::sltMarkSaved() 1037 { 1038 /* Call for base-class: */ 1039 UISettingsDialog::sltMarkSaved(); 1040 1041 /* Unlock the session if exists: */ 1042 if (!m_session.isNull()) 1043 { 1044 m_session.UnlockMachine(); 1045 m_session = CSession(); 1046 m_machine = CMachine(); 1047 m_console = CConsole(); 1048 } 1049 } 1050 1051 void UISettingsDialogMachine::sltSessionStateChanged(QString strMachineId, KSessionState sessionState) 1052 { 1053 /* Ignore if thats NOT our VM: */ 1054 if (strMachineId != m_strMachineId) 1055 return; 1056 1057 /* Ignore if state was NOT actually changed: */ 1058 if (m_sessionState == sessionState) 1059 return; 1060 1061 /* Update current session state: */ 1062 m_sessionState = sessionState; 1063 1064 /* Recalculate configuration access level: */ 1065 updateConfigurationAccessLevel(); 1066 } 1067 1068 void UISettingsDialogMachine::sltMachineStateChanged(QString strMachineId, KMachineState machineState) 1069 { 1070 /* Ignore if thats NOT our VM: */ 1071 if (strMachineId != m_strMachineId) 1072 return; 1073 1074 /* Ignore if state was NOT actually changed: */ 1075 if (m_machineState == machineState) 1076 return; 1077 1078 /* Update current machine state: */ 1079 m_machineState = machineState; 1080 1081 /* Recalculate configuration access level: */ 1082 updateConfigurationAccessLevel(); 1083 } 1084 1085 void UISettingsDialogMachine::sltMachineDataChanged(QString strMachineId) 1086 { 1087 /* Ignore if thats NOT our VM: */ 1088 if (strMachineId != m_strMachineId) 1089 return; 1090 1091 /* Check if user had changed something and warn him about he will loose settings on reloading: */ 1092 if (isSettingsChanged() && !msgCenter().confirmSettingsReloading(this)) 1093 return; 1094 1095 /* Reload data: */ 1096 loadData(); 1097 } 1098 1099 void UISettingsDialogMachine::sltCategoryChanged(int cId) 1100 { 1101 if (UISettingsSerializer::instance()) 1102 UISettingsSerializer::instance()->raisePriorityOfPage(cId); 1103 1104 UISettingsDialog::sltCategoryChanged(cId); 1105 } 1106 1107 void UISettingsDialogMachine::sltAllowResetFirstRunFlag() 1108 { 1109 m_fAllowResetFirstRunFlag = true; 1110 } 1111 1112 void UISettingsDialogMachine::sltSetFirstRunFlag() 1113 { 1114 m_fResetFirstRunFlag = false; 1115 } 1116 1117 void UISettingsDialogMachine::sltResetFirstRunFlag() 1118 { 1119 if (m_fAllowResetFirstRunFlag) 1120 m_fResetFirstRunFlag = true; 1121 } 1122 1123 bool UISettingsDialogMachine::isPageAvailable(int iPageId) 1124 { 1125 if (m_machine.isNull()) 1126 return false; 1127 1128 switch (iPageId) 1129 { 1130 case MachineSettingsPageType_Serial: 1131 { 1132 /* Depends on ports availability: */ 1133 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1134 return false; 1135 break; 1136 } 1137 case MachineSettingsPageType_Parallel: 1138 { 1139 /* Depends on ports availability: */ 1140 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1141 return false; 1142 /* But for now this page is always disabled: */ 1143 return false; 1144 } 1145 case MachineSettingsPageType_USB: 1146 { 1147 /* Depends on ports availability: */ 1148 if (!isPageAvailable(MachineSettingsPageType_Ports)) 1149 return false; 1150 /* Check if USB is implemented: */ 1151 if (!m_machine.GetUSBProxyAvailable()) 1152 return false; 1153 /* Get the USB controller object: */ 1154 CUSBControllerVector controllerColl = m_machine.GetUSBControllers(); 1155 /* Show the machine error message if any: */ 1156 if ( !m_machine.isReallyOk() 1157 && controllerColl.size() > 0 1158 && !m_machine.GetUSBControllers().isEmpty()) 1159 msgCenter().warnAboutUnaccessibleUSB(m_machine, parentWidget()); 1160 break; 1161 } 1162 default: 1163 break; 1164 } 1165 return true; 1166 } 1167 1168 bool UISettingsDialogMachine::isSettingsChanged() 1169 { 1170 bool fIsSettingsChanged = false; 1171 foreach (UISettingsPage *pPage, m_pSelector->settingPages()) 1172 { 1173 pPage->putToCache(); 1174 if (!fIsSettingsChanged && pPage->changed()) 1175 fIsSettingsChanged = true; 1176 } 1177 return fIsSettingsChanged; 1178 } 1179 1180 void UISettingsDialogMachine::updateConfigurationAccessLevel() 1181 { 1182 /* Determine new configuration access level: */ 1183 ConfigurationAccessLevel newConfigurationAccessLevel = ::configurationAccessLevel(m_sessionState, m_machineState); 1184 1185 /* Make sure someting changed: */ 1186 if (configurationAccessLevel() == newConfigurationAccessLevel) 1187 return; 1188 1189 /* Should we warn a user about access level decrease? */ 1190 bool fShouldWeWarn = configurationAccessLevel() == ConfigurationAccessLevel_Full; 1191 1192 /* Apply new configuration access level: */ 1193 setConfigurationAccessLevel(newConfigurationAccessLevel); 1194 1195 /* Show a warning about access level decrease if we should: */ 1196 if (isSettingsChanged() && fShouldWeWarn) 1197 msgCenter().warnAboutStateChange(this); 1198 } 1199 1200 # include "UISettingsDialogSpecific.moc" 1201 121 #endif /* !___UISettingsSerializer_h___ */
Note:
See TracChangeset
for help on using the changeset viewer.