void UISettingsSerializer::run()
{
    /* Initialize COM for other thread: */
    COMBase::InitializeCOM(false);

    /* Mark all the pages initially as NOT processed: */
    foreach (UISettingsPage *pPage, m_pages.values())
        pPage->setProcessed(false);

    /* Iterate over the all left settings pages: */
    UISettingsPageMap pages(m_pages);
    while (!pages.empty())
    {
        /* Get required page pointer, protect map by mutex while getting pointer: */
        UISettingsPage *pPage = m_iIdOfHighPriorityPage != -1 && pages.contains(m_iIdOfHighPriorityPage) ?
                                pages.value(m_iIdOfHighPriorityPage) : *pages.begin();
        /* Reset request of high priority: */
        if (m_iIdOfHighPriorityPage != -1)
            m_iIdOfHighPriorityPage = -1;
        /* Process this page if its enabled: */
        connect(pPage, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)),
                this, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)));
        connect(pPage, SIGNAL(sigOperationProgressError(QString)),
                this, SIGNAL(sigOperationProgressError(QString)));
        if (pPage->isEnabled())
        {
            if (m_enmDirection == Load)
                pPage->loadToCacheFrom(m_data);
            if (m_enmDirection == Save)
                pPage->saveFromCacheTo(m_data);
        }
        /* Remember what page was processed: */
        disconnect(pPage, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)),
                   this, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)));
        disconnect(pPage, SIGNAL(sigOperationProgressError(QString)),
                   this, SIGNAL(sigOperationProgressError(QString)));
        pPage->setProcessed(true);
        /* Remove processed page from our map: */
        pages.remove(pPage->id());
        /* Notify listeners about page was processed: */
        emit sigNotifyAboutPageProcessed(pPage->id());
        /* If serializer saves settings => wake up GUI thread: */
        if (m_enmDirection == Save)
            m_condition.wakeAll();
        /* Break further processing if page had failed: */
        if (pPage->failed())
            break;
    }
    /* Notify listeners about all pages were processed: */
    emit sigNotifyAboutPagesProcessed();
    /* If serializer saves settings => wake up GUI thread: */
    if (m_enmDirection == Save)
        m_condition.wakeAll();

    /* Deinitialize COM for other thread: */
    COMBase::CleanupCOM();
}
void UIMachineSettingsGeneral::saveFromCacheTo(QVariant &data)
{
    /* Fetch data to machine: */
    UISettingsPageMachine::fetchData(data);

    /* Check if general data was changed: */
    if (m_cache.wasChanged())
    {
        /* Get general data from cache: */
        const UIDataSettingsMachineGeneral &generalData = m_cache.data();

        if (isMachineInValidMode())
        {
            /* 'Advanced' tab data: */
            if (generalData.m_clipboardMode != m_cache.base().m_clipboardMode)
                m_machine.SetClipboardMode(generalData.m_clipboardMode);
            if (generalData.m_dndMode != m_cache.base().m_dndMode)
                m_machine.SetDnDMode(generalData.m_dndMode);

            /* 'Description' tab: */
            if (generalData.m_strDescription != m_cache.base().m_strDescription)
                m_machine.SetDescription(generalData.m_strDescription);
        }

        if (isMachineOffline())
        {
            /* 'Basic' tab data: Must update long mode CPU feature bit when os type changes. */
            if (generalData.m_strGuestOsTypeId != m_cache.base().m_strGuestOsTypeId)
            {
                m_machine.SetOSTypeId(generalData.m_strGuestOsTypeId);
                CVirtualBox vbox = vboxGlobal().virtualBox();
                CGuestOSType newType = vbox.GetGuestOSType(generalData.m_strGuestOsTypeId);
                m_machine.SetCPUProperty(KCPUPropertyType_LongMode, newType.GetIs64Bit());
            }

            /* 'Advanced' tab data: */
            if (generalData.m_strSnapshotsFolder != m_cache.base().m_strSnapshotsFolder)
                m_machine.SetSnapshotFolder(generalData.m_strSnapshotsFolder);

            /* 'Basic' (again) tab data: */
            /* VM name must be last as otherwise its VM rename magic
             * can collide with other settings in the config,
             * especially with the snapshot folder: */
            if (generalData.m_strName != m_cache.base().m_strName)
                m_machine.SetName(generalData.m_strName);

            /* Encryption tab data: */
            if (generalData.m_fEncryptionEnabled != m_cache.base().m_fEncryptionEnabled ||
                generalData.m_fEncryptionCipherChanged != m_cache.base().m_fEncryptionCipherChanged ||
                generalData.m_fEncryptionPasswordChanged != m_cache.base().m_fEncryptionPasswordChanged)
            {
                /* Cipher attribute changed? */
                QString strNewCipher;
                if (generalData.m_fEncryptionCipherChanged)
                {
                    strNewCipher = generalData.m_fEncryptionEnabled ?
                                   m_encryptionCiphers.at(generalData.m_iEncryptionCipherIndex) : QString();
                }
                /* Password attribute changed? */
                QString strNewPassword;
                QString strNewPasswordId;
                if (generalData.m_fEncryptionPasswordChanged)
                {
                    strNewPassword = generalData.m_fEncryptionEnabled ?
                                     generalData.m_strEncryptionPassword : QString();
                    strNewPasswordId = generalData.m_fEncryptionEnabled ?
                                       m_machine.GetName() : QString();
                }

                /* Get the maps of encrypted mediums and their passwords: */
                const EncryptedMediumMap &encryptedMedium = generalData.m_encryptedMediums;
                const EncryptionPasswordMap &encryptionPasswords = generalData.m_encryptionPasswords;
                /* Enumerate attachments: */
                foreach (const CMediumAttachment &attachment, m_machine.GetMediumAttachments())
                {
                    /* Enumerate hard-drives only: */
                    if (attachment.GetType() == KDeviceType_HardDisk)
                    {
                        /* Get corresponding medium: */
                        CMedium medium = attachment.GetMedium();

                        /* Check if old password exists/provided: */
                        QString strOldPasswordId = encryptedMedium.key(medium.GetId());
                        QString strOldPassword = encryptionPasswords.value(strOldPasswordId);

                        /* Update encryption: */
                        CProgress cprogress = medium.ChangeEncryption(strOldPassword,
                                                                      strNewCipher,
                                                                      strNewPassword,
                                                                      strNewPasswordId);
                        if (!medium.isOk())
                        {
                            QMetaObject::invokeMethod(this, "sigOperationProgressError", Qt::BlockingQueuedConnection,
                                                      Q_ARG(QString, UIMessageCenter::formatErrorInfo(medium)));
                            continue;
                        }
                        UIProgress uiprogress(cprogress);
                        connect(&uiprogress, SIGNAL(sigProgressChange(ulong, QString, ulong, ulong)),
                                this, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)),
                                Qt::QueuedConnection);
                        connect(&uiprogress, SIGNAL(sigProgressError(QString)),
                                this, SIGNAL(sigOperationProgressError(QString)),
                                Qt::BlockingQueuedConnection);
                        uiprogress.run(350);
                    }
                }
            }
        }
    }
void UISettingsSerializerProgress::prepare()
{
    /* Configure self: */
    setWindowModality(Qt::WindowModal);
    setWindowTitle(parentWidget()->windowTitle());
    connect(this, SIGNAL(sigAskForProcessStart()),
            this, SLOT(sltStartProcess()), Qt::QueuedConnection);

    /* Create serializer: */
    m_pSerializer = new UISettingsSerializer(this, m_enmDirection, m_data, m_pages);
    AssertPtrReturnVoid(m_pSerializer);
    {
        /* Install progress handler: */
        connect(m_pSerializer, SIGNAL(sigNotifyAboutProcessProgressChanged(int)),
                this, SLOT(sltHandleProcessProgressChange(int)));
        connect(m_pSerializer, SIGNAL(sigOperationProgressChange(ulong, QString, ulong, ulong)),
                this, SLOT(sltHandleOperationProgressChange(ulong, QString, ulong, ulong)));
        connect(m_pSerializer, SIGNAL(sigOperationProgressError(QString)),
                this, SLOT(sltHandleOperationProgressError(QString)));
    }

    /* Create layout: */
    QVBoxLayout *pLayout = new QVBoxLayout(this);
    AssertPtrReturnVoid(pLayout);
    {
        /* Create top layout: */
        QHBoxLayout *pLayoutTop = new QHBoxLayout;
        AssertPtrReturnVoid(pLayoutTop);
        {
            /* Create pixmap layout: */
            QVBoxLayout *pLayoutPixmap = new QVBoxLayout;
            AssertPtrReturnVoid(pLayoutPixmap);
            {
                /* Create pixmap label: */
                QLabel *pLabelPixmap = new QLabel;
                AssertPtrReturnVoid(pLabelPixmap);
                {
                    /* Configure label: */
                    const QIcon icon = UIIconPool::iconSet(":/progress_settings_90px.png");
                    pLabelPixmap->setPixmap(icon.pixmap(icon.availableSizes().value(0, QSize(90, 90))));
                    /* Add label into layout: */
                    pLayoutPixmap->addWidget(pLabelPixmap);
                }
                /* Add stretch: */
                pLayoutPixmap->addStretch();
                /* Add layout into parent: */
                pLayoutTop->addLayout(pLayoutPixmap);
            }
            /* Create progress layout: */
            QVBoxLayout *pLayoutProgress = new QVBoxLayout;
            AssertPtrReturnVoid(pLayoutProgress);
            {
                /* Create operation progress label: */
                m_pLabelOperationProgress = new QLabel;
                AssertPtrReturnVoid(m_pLabelOperationProgress);
                {
                    /* Add label into layout: */
                    pLayoutProgress->addWidget(m_pLabelOperationProgress);
                }
                /* Create operation progress bar: */
                m_pBarOperationProgress = new QProgressBar;
                AssertPtrReturnVoid(m_pBarOperationProgress);
                {
                    /* Configure progress bar: */
                    m_pBarOperationProgress->setMinimumWidth(300);
                    m_pBarOperationProgress->setMaximum(100);
                    m_pBarOperationProgress->setMinimum(0);
                    m_pBarOperationProgress->setValue(0);
                    /* Add bar into layout: */
                    pLayoutProgress->addWidget(m_pBarOperationProgress);
                }
                /* Create sub-operation progress label: */
                m_pLabelSubOperationProgress = new QILabel;
                AssertPtrReturnVoid(m_pLabelSubOperationProgress);
                {
                    /* Configure label: */
                    m_pLabelSubOperationProgress->hide();
                    m_pLabelSubOperationProgress->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
                    /* Add label into layout: */
                    pLayoutProgress->addWidget(m_pLabelSubOperationProgress);
                }
                /* Create sub-operation progress bar: */
                m_pBarSubOperationProgress = new QProgressBar;
                AssertPtrReturnVoid(m_pBarSubOperationProgress);
                {
                    /* Configure progress bar: */
                    m_pBarSubOperationProgress->hide();
                    m_pBarSubOperationProgress->setMinimumWidth(300);
                    m_pBarSubOperationProgress->setMaximum(100);
                    m_pBarSubOperationProgress->setMinimum(0);
                    m_pBarSubOperationProgress->setValue(0);
                    /* Add bar into layout: */
                    pLayoutProgress->addWidget(m_pBarSubOperationProgress);
                }
                /* Add stretch: */
                pLayoutProgress->addStretch();
                /* Add layout into parent: */
                pLayoutTop->addLayout(pLayoutProgress);
            }
            /* Add layout into parent: */
            pLayout->addLayout(pLayoutTop);
        }
    }
}