VirtualBox

Changeset 54886 in vbox


Ignore:
Timestamp:
Mar 20, 2015 5:50:46 PM (10 years ago)
Author:
vboxsync
Message:

FE/Qt: Machine settings Serializer: Cleanup rework to prepare to the encryption settings integration (step 2).

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r54733 r54886  
    357357        src/settings/UISettingsDialogSpecific.h \
    358358        src/settings/UISettingsPage.h \
     359        src/settings/UISettingsSerializer.h \
    359360        src/settings/VBoxSettingsSelector.h \
    360361        src/settings/global/UIGlobalSettingsExtension.h \
     
    370371        src/settings/machine/UIMachineSettingsDisplay.h \
    371372        src/settings/machine/UIMachineSettingsGeneral.h \
    372     src/settings/machine/UIMachineSettingsInterface.h \
    373     src/settings/machine/UIMachineSettingsNetwork.h \
     373        src/settings/machine/UIMachineSettingsInterface.h \
     374        src/settings/machine/UIMachineSettingsNetwork.h \
    374375        src/settings/machine/UIMachineSettingsParallel.h \
    375376        src/settings/machine/UIMachineSettingsPortForwardingDlg.h \
     
    498499        src/selector/UIActionPoolSelector.cpp \
    499500        src/selector/UIVMDesktop.cpp \
    500         src/settings/UISettingsDialogSpecific.cpp \
    501501        src/settings/machine/UIMachineSettingsStorage.cpp \
    502502        src/settings/machine/UIMachineSettingsUSB.cpp \
     
    639639        src/settings/UISettingsDialogSpecific.cpp \
    640640        src/settings/UISettingsPage.cpp \
     641        src/settings/UISettingsSerializer.cpp \
    641642        src/settings/VBoxSettingsSelector.cpp \
    642643        src/settings/global/UIGlobalSettingsExtension.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsDialogSpecific.cpp

    r54875 r54886  
    2020#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
    2121
    22 /* Qt includes: */
    23 # include <QStackedWidget>
    24 # include <QThread>
    25 # include <QMutex>
    26 # include <QWaitCondition>
    27 # include <QTimer>
    28 
    2922/* GUI includes: */
    3023# include "UISettingsDialogSpecific.h"
     24# include "UISettingsSerializer.h"
    3125# include "UISettingsDefs.h"
    3226# include "VBoxGlobal.h"
     
    6660
    6761#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: */
    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)
    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 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)
    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         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();
    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;
    32962
    33063UISettingsDialogGlobal::UISettingsDialogGlobal(QWidget *pParent,
     
    1198931}
    1199932
    1200 # include "UISettingsDialogSpecific.moc"
    1201 
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsSerializer.cpp

    r54883 r54886  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UISettingsDialogSpecific class implementation.
     3 * VBox Qt GUI - UISettingsSerializer class implementation.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919# include <precomp.h>
    2020#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
    21 
    2221/* Qt includes: */
    23 # include <QStackedWidget>
    24 # include <QThread>
    25 # include <QMutex>
    26 # include <QWaitCondition>
    2722# include <QTimer>
    28 
    2923/* 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"
    6726#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    6827
    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)
     28UISettingsSerializer* UISettingsSerializer::m_spInstance = 0;
     29
     30UISettingsSerializer::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
     58UISettingsSerializer::~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
     70void 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
     78void 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)
    12399        {
    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();
    126109        }
    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
     115void 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))
    172122        {
    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);
    176128        }
    177 
    178         /* Start async serializing thread: */
    179         QThread::start(priority);
    180 
    181         /* If serializer saves settings: */
    182         if (m_direction == Save)
     129    }
     130}
     131
     132void 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
     150void 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
     160void 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())
    183181        {
    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);
    199186        }
    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());
    297193        /* If serializer saves settings => wake up GUI thread: */
    298194        if (m_direction == Save)
    299195            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())
    582198            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$ */
    21/** @file
    3  * VBox Qt GUI - UISettingsDialogSpecific class implementation.
     2 * VBox Qt GUI - UISettingsSerializer class declaration.
    43 */
    54
    65/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     6 * Copyright (C) 2006-2015 Oracle Corporation
    87 *
    98 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1615 */
    1716
    18 #ifdef VBOX_WITH_PRECOMPILED_HEADERS
    19 # include <precomp.h>
    20 #else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
     17#ifndef ___UISettingsSerializer_h___
     18#define ___UISettingsSerializer_h___
    2119
    2220/* 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>
    2827
    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: */
     29class UISettingsPage;
    3830
    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: */
    7532typedef QList<UISettingsPage*> UISettingsPageList;
    7633typedef QMap<int, UISettingsPage*> UISettingsPageMap;
    7734
    7835/** 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. */
    8137class UISettingsSerializer : public QThread
    8238{
     
    10864      * @param pages     contains the page(s) to load/save the data to/from. */
    10965    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);
    13667
    13768    /** 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();
    14970
    15071    /** Returns the instance of wrapper(s) to load/save the data from/to. */
     
    15273
    15374    /** 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);
    16176
    16277public slots:
    16378
    16479    /** 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);
    20181
    20282protected slots:
    20383
    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);
    22186
    22287    /** 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();
    24089
    24190    /** 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();
    25192
    25293protected:
    25394
    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();
    30497
    30598    /** Holds the singleton instance. */
     
    326119};
    327120
    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.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette