VirtualBox

Ignore:
Timestamp:
Sep 12, 2017 11:45:58 AM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
117954
Message:

FE/Qt: bugref:8901: Allow to take snapshots directly from the snapshot-details pane.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/selector
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISnapshotDetailsWidget.cpp

    r68490 r68722  
    3030# include <QPushButton>
    3131# include <QScrollArea>
    32 # include <QStackedLayout>
    3332# include <QTabWidget>
    3433# include <QTextBrowser>
     
    515514UISnapshotDetailsWidget::UISnapshotDetailsWidget(QWidget *pParent /* = 0 */)
    516515    : QIWithRetranslateUI<QWidget>(pParent)
    517     , m_pStackedLayout(0)
    518     , m_pEmptyWidget(0)
    519     , m_pEmptyWidgetLabel(0)
    520516    , m_pTabWidget(0)
    521517    , m_pLayoutOptions(0)
     
    525521    , m_pLayoutDetails(0)
    526522    , m_pScrollAreaDetails(0)
     523    , m_fSnapshotNameEdited(false)
    527524{
    528525    /* Prepare: */
     
    530527}
    531528
     529void UISnapshotDetailsWidget::setData(const CMachine &comMachine)
     530{
     531    /* Reset defaults: */
     532    m_fSnapshotNameEdited = false;
     533
     534    /* Cache old/new data: */
     535    m_oldData = UIDataSnapshot();
     536    m_newData = m_oldData;
     537
     538    /* Cache machine/snapshot: */
     539    m_comMachine = comMachine;
     540    m_comSnapshot = CSnapshot();
     541
     542    /* Retranslate buttons: */
     543    retranslateButtons();
     544    /* Load snapshot data: */
     545    loadSnapshotData();
     546}
     547
    532548void UISnapshotDetailsWidget::setData(const UIDataSnapshot &data, const CSnapshot &comSnapshot)
    533549{
     550    /* Reset defaults: */
     551    m_fSnapshotNameEdited = false;
     552
    534553    /* Cache old/new data: */
    535554    m_oldData = data;
    536555    m_newData = m_oldData;
    537556
    538     /* Cache snapshot: */
     557    /* Cache machine/snapshot: */
     558    m_comMachine = CMachine();
    539559    m_comSnapshot = comSnapshot;
    540560
     561    /* Retranslate buttons: */
     562    retranslateButtons();
    541563    /* Load snapshot data: */
    542564    loadSnapshotData();
     
    545567void UISnapshotDetailsWidget::clearData()
    546568{
     569    /* Reset defaults: */
     570    m_fSnapshotNameEdited = false;
     571
    547572    /* Reset old/new data: */
    548573    m_oldData = UIDataSnapshot();
    549574    m_newData = m_oldData;
    550575
    551     /* Reset snapshot: */
     576    /* Reset machine/snapshot: */
     577    m_comMachine = CMachine();
    552578    m_comSnapshot = CSnapshot();
    553579
     580    /* Retranslate buttons: */
     581    retranslateButtons();
    554582    /* Load snapshot data: */
    555583    loadSnapshotData();
     
    559587{
    560588    /* Translate labels: */
    561     m_pEmptyWidgetLabel->setText(tr("<p>You have the <b>Current State</b> item selected.<br>"
    562                                     "Press the <b>Take</b> button if you wish to take a new snapshot.</p>"));
    563589    m_pTabWidget->setTabText(0, tr("&Attributes"));
    564590    m_pTabWidget->setTabText(1, tr("&Information"));
     
    567593    m_pEditorName->setToolTip(tr("Holds the snapshot name."));
    568594    m_pBrowserDescription->setToolTip(tr("Holds the snapshot description."));
    569     m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
    570     m_pButtonBox->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
     595
     596    /* Translate placeholders: */
     597    m_pEditorName->setPlaceholderText(  m_comMachine.isNotNull()
     598                                      ? tr("Enter a name for the new snapshot...")
     599                                      : m_comSnapshot.isNotNull()
     600                                      ? tr("Enter a name for this snapshot...")
     601                                      : QString());
     602
     603    /* Translate buttons:  */
    571604    m_pButtonBox->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
    572605    m_pButtonBox->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
    573     m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current snapshot details"));
    574     m_pButtonBox->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current snapshot details"));
    575     m_pButtonBox->button(QDialogButtonBox::Ok)->
    576         setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
    577     m_pButtonBox->button(QDialogButtonBox::Cancel)->
    578         setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Cancel)->shortcut().toString()));
    579 
    580     /* And if snapshot is valid: */
    581     if (!m_comSnapshot.isNull())
    582     {
    583         /* Get the machine: */
    584         const CMachine comMachine = m_comSnapshot.GetMachine();
    585 
    586         /* Update the picture tool-tip and visibility: */
    587         m_details.value(DetailsElementType_Preview)->setToolTip(tr("Click to enlarge the screenshot."));
    588         if (!m_pixmapScreenshot.isNull() && m_details.value(DetailsElementType_Preview)->isHidden())
    589             m_details.value(DetailsElementType_Preview)->setHidden(false);
    590         else if (m_pixmapScreenshot.isNull() && !m_details.value(DetailsElementType_Preview)->isHidden())
    591             m_details.value(DetailsElementType_Preview)->setHidden(true);
    592 
     606    retranslateButtons();
     607
     608    /* Update the picture tool-tip and visibility: */
     609    m_details.value(DetailsElementType_Preview)->setToolTip(tr("Click to enlarge the screenshot."));
     610    if (!m_pixmapScreenshot.isNull() && m_details.value(DetailsElementType_Preview)->isHidden())
     611        m_details.value(DetailsElementType_Preview)->setHidden(false);
     612    else if (m_pixmapScreenshot.isNull() && !m_details.value(DetailsElementType_Preview)->isHidden())
     613        m_details.value(DetailsElementType_Preview)->setHidden(true);
     614
     615    /* Prepare machine: */
     616    const CMachine &comMachine = m_comMachine.isNotNull()
     617                               ? m_comMachine
     618                               : m_comSnapshot.isNotNull()
     619                               ? m_comSnapshot.GetMachine()
     620                               : CMachine();
     621
     622    /* Make sure machine is valid: */
     623    if (comMachine.isNotNull())
     624    {
    593625        /* Update USB details visibility: */
    594626        const CUSBDeviceFilters &comFilters = comMachine.GetUSBDeviceFilters();
     
    601633            m_details.value(enmType)->setText(detailsReport(comMachine, enmType));
    602634    }
    603     else
    604     {
    605         /* Clear the details report: */
    606         // WORKAROUND:
    607         // How stupid Qt *is* to wipe out registered icons not just on clear()
    608         // call but on setText(QString()) and even setText("") as well.
    609         // Nice way to oversmart itself..
    610         foreach (const DetailsElementType &enmType, m_details.keys())
    611             m_details.value(enmType)->setText("<empty>");
    612     }
    613635
    614636    /* Retranslate validation: */
    615637    retranslateValidation();
     638}
     639
     640void UISnapshotDetailsWidget::retranslateButtons()
     641{
     642    /* Common: 'Reset' button: */
     643    m_pButtonBox->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
     644    m_pButtonBox->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current snapshot details"));
     645    m_pButtonBox->button(QDialogButtonBox::Cancel)->
     646        setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Cancel)->shortcut().toString()));
     647    /* Common: 'Apply' button: */
     648    m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
     649    m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current snapshot details"));
     650    m_pButtonBox->button(QDialogButtonBox::Ok)->
     651        setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
     652
     653    if (m_comMachine.isNotNull())
     654    {
     655        /* Machine: 'Take' button: */
     656        m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Take"));
     657        m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Take snapshot on the basis of current machine state"));
     658        m_pButtonBox->button(QDialogButtonBox::Ok)->
     659            setToolTip(tr("Take Snapshot (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
     660    }
     661}
     662
     663void UISnapshotDetailsWidget::sltHandleNameEdit()
     664{
     665    m_fSnapshotNameEdited = true;
    616666}
    617667
     
    667717void UISnapshotDetailsWidget::prepare()
    668718{
    669     /* Create stacked layout: */
    670     m_pStackedLayout = new QStackedLayout(this);
    671     AssertPtrReturnVoid(m_pStackedLayout);
    672     {
    673         /* Prepare empty-widget: */
    674         prepareEmptyWidget();
    675         /* Prepare tab-widget: */
    676         prepareTabWidget();
    677     }
    678 }
    679 
    680 void UISnapshotDetailsWidget::prepareEmptyWidget()
    681 {
    682     /* Create empty-widget: */
    683     m_pEmptyWidget = new QWidget;
    684     AssertPtrReturnVoid(m_pEmptyWidget);
    685     {
    686         /* Create empty-widget layout: */
    687         new QVBoxLayout(m_pEmptyWidget);
    688         AssertPtrReturnVoid(m_pEmptyWidget->layout());
     719    /* Create layout: */
     720    QVBoxLayout *pLayout = new QVBoxLayout(this);
     721    AssertPtrReturnVoid(pLayout);
     722    {
     723        /* Configure layout: */
     724        pLayout->setContentsMargins(0, 0, 0, 0);
     725
     726        /* Create tab-widget: */
     727        m_pTabWidget = new QTabWidget;
     728        AssertPtrReturnVoid(m_pTabWidget);
    689729        {
    690             /* Create empty-widget label: */
    691             m_pEmptyWidgetLabel = new QLabel;
    692             {
    693                 /* Configure label: */
    694                 QFont font = m_pEmptyWidgetLabel->font();
    695                 font.setPointSize(font.pointSize() * 1.5);
    696                 m_pEmptyWidgetLabel->setAlignment(Qt::AlignCenter);
    697                 m_pEmptyWidgetLabel->setFont(font);
    698 
    699                 /* Add into layout: */
    700                 m_pEmptyWidget->layout()->addWidget(m_pEmptyWidgetLabel);
    701             }
     730            /* Prepare 'Options' tab: */
     731            prepareTabOptions();
     732            /* Prepare 'Details' tab: */
     733            prepareTabDetails();
     734
     735            /* Add into layout: */
     736            pLayout->addWidget(m_pTabWidget);
    702737        }
    703 
    704         /* Add into layout: */
    705         m_pStackedLayout->addWidget(m_pEmptyWidget);
    706     }
    707 }
    708 
    709 void UISnapshotDetailsWidget::prepareTabWidget()
    710 {
    711     /* Create tab-widget: */
    712     m_pTabWidget = new QTabWidget;
    713     AssertPtrReturnVoid(m_pTabWidget);
    714     {
    715         /* Prepare 'Options' tab: */
    716         prepareTabOptions();
    717         /* Prepare 'Details' tab: */
    718         prepareTabDetails();
    719 
    720         /* Add into layout: */
    721         m_pStackedLayout->addWidget(m_pTabWidget);
    722738    }
    723739}
     
    765781                    policy.setHorizontalStretch(1);
    766782                    m_pEditorName->setSizePolicy(policy);
     783                    connect(m_pEditorName, &QLineEdit::textEdited,
     784                            this, &UISnapshotDetailsWidget::sltHandleNameEdit);
    767785                    connect(m_pEditorName, &QLineEdit::textChanged,
    768786                            this, &UISnapshotDetailsWidget::sltHandleNameChange);
     
    10251043    m_pEditorName->setText(m_newData.m_strName);
    10261044    m_pBrowserDescription->setText(m_newData.m_strDescription);
    1027 
     1045    revalidate();
     1046
     1047    /* If there is a machine: */
     1048    if (m_comMachine.isNotNull())
     1049    {
     1050        /* No screenshot: */
     1051        m_pixmapScreenshot = QPixmap();
     1052    }
    10281053    /* If there is a snapshot: */
    1029     if (m_comSnapshot.isNotNull())
    1030     {
    1031         /* Choose the tab-widget as current one: */
    1032         m_pStackedLayout->setCurrentWidget(m_pTabWidget);
    1033 
     1054    else if (m_comSnapshot.isNotNull())
     1055    {
    10341056        /* Read snapshot display contents: */
    10351057        CMachine comMachine = m_comSnapshot.GetMachine();
     
    10541076            QTextDocument::ImageResource, QUrl("details://thumbnail"), QVariant(pixThumbnail));
    10551077    }
    1056     else
    1057     {
    1058         /* Choose the empty-widget as current one: */
    1059         m_pStackedLayout->setCurrentWidget(m_pEmptyWidget);
    1060     }
    10611078
    10621079    /* Retranslate: */
     
    10721089    {
    10731090        const bool fError = m_newData.m_strName.isEmpty();
    1074         m_pErrorPaneName->setVisible(fError);
     1091        m_pErrorPaneName->setVisible(fError && m_fSnapshotNameEdited);
    10751092    }
    10761093    if (!pWidget || pWidget == m_pErrorPaneDescription)
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISnapshotDetailsWidget.h

    r68365 r68722  
    2727
    2828/* COM includes: */
     29#include "COMEnums.h"
     30#include "CMachine.h"
    2931#include "CSnapshot.h"
    3032
     
    3537class QLineEdit;
    3638class QScrollArea;
    37 class QStackedLayout;
    3839class QTabWidget;
    3940class QTextEdit;
     
    9192    /** Returns the snapshot data. */
    9293    const UIDataSnapshot &data() const { return m_newData; }
    93     /** Defines the snapshot @a data. */
     94    /** Defines the @a comMachine. */
     95    void setData(const CMachine &comMachine);
     96    /** Defines the @a comSnapshot and it's @a data. */
    9497    void setData(const UIDataSnapshot &data, const CSnapshot &comSnapshot);
    9598    /** Clears the snapshot data. */
     
    100103    /** Handles translation event. */
    101104    virtual void retranslateUi() /* override */;
     105    /** Handles buttons translation. */
     106    void retranslateButtons();
    102107
    103108private slots:
    104109
     110    /** Handles snapshot name edit. */
     111    void sltHandleNameEdit();
    105112    /** Handles snapshot name change. */
    106113    void sltHandleNameChange();
     
    120127    /** Prepares all. */
    121128    void prepare();
    122     /** Prepares empty-widget. */
    123     void prepareEmptyWidget();
    124129    /** Prepares tab-widget. */
    125130    void prepareTabWidget();
     
    148153    static QString summarizeGenericProperties(const CNetworkAdapter &adapter);
    149154
     155    /** Holds the machine object to load data from. */
     156    CMachine   m_comMachine;
    150157    /** Holds the snapshot object to load data from. */
    151158    CSnapshot  m_comSnapshot;
     
    158165    /** Holds the cached screenshot. */
    159166    QPixmap  m_pixmapScreenshot;
    160 
    161     /** Holds the stacked layout instance. */
    162     QStackedLayout *m_pStackedLayout;
    163 
    164     /** Holds the empty-widget instance. */
    165     QWidget *m_pEmptyWidget;
    166     /** Holds the empty-widget label instance. */
    167     QLabel  *m_pEmptyWidgetLabel;
    168167
    169168    /** Holds the tab-widget instance. */
     
    198197    /** Holds the details element map. */
    199198    QMap<DetailsElementType, UISnapshotDetailsElement*> m_details;
     199
     200    /** Holds whether the snapshot name was edited. */
     201    bool  m_fSnapshotNameEdited;
    200202};
    201203
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISnapshotPane.cpp

    r68721 r68722  
    917917    if (m_pDetailsWidget->isVisible())
    918918    {
    919         /* Acquire "current snapshot" item: */
     919        /* Acquire selected item: */
    920920        const UISnapshotItem *pSnapshotItem = UISnapshotItem::toSnapshotItem(m_pSnapshotTree->currentItem());
     921        AssertPtrReturnVoid(pSnapshotItem);
    921922        /* Update details-widget: */
    922         m_pDetailsWidget->setData(*pSnapshotItem, pSnapshotItem->snapshot());
     923        if (pSnapshotItem->isCurrentStateItem())
     924            m_pDetailsWidget->setData(m_comMachine);
     925        else
     926            m_pDetailsWidget->setData(*pSnapshotItem, pSnapshotItem->snapshot());
    923927    }
    924928}
     
    930934    AssertPtrReturnVoid(pSnapshotItem);
    931935
     936    /* For current state item: */
     937    if (pSnapshotItem->isCurrentStateItem())
     938    {
     939        /* Get item data: */
     940        UIDataSnapshot newData = m_pDetailsWidget->data();
     941
     942        /* Open a session (this call will handle all errors): */
     943        CSession comSession;
     944        if (m_enmSessionState != KSessionState_Unlocked)
     945            comSession = vboxGlobal().openExistingSession(m_strMachineId);
     946        else
     947            comSession = vboxGlobal().openSession(m_strMachineId);
     948        if (comSession.isNotNull())
     949        {
     950            /* Get corresponding machine object: */
     951            CMachine comMachine = comSession.GetMachine();
     952
     953            /* Perform separate linked steps: */
     954            do
     955            {
     956                /* Take snapshot: */
     957                QString strSnapshotId;
     958                CProgress comProgress = comMachine.TakeSnapshot(newData.m_strName,
     959                                                                newData.m_strDescription,
     960                                                                true, strSnapshotId);
     961                if (!comMachine.isOk())
     962                {
     963                    msgCenter().cannotTakeSnapshot(comMachine, comMachine.GetName());
     964                    break;
     965                }
     966
     967                /* Show snapshot taking progress: */
     968                msgCenter().showModalProgressDialog(comProgress, comMachine.GetName(),
     969                                                    ":/progress_snapshot_create_90px.png");
     970                if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
     971                {
     972                    msgCenter().cannotTakeSnapshot(comProgress, comMachine.GetName());
     973                    break;
     974                }
     975            }
     976            while (0);
     977
     978            /* Cleanup session: */
     979            comSession.UnlockMachine();
     980        }
     981    }
    932982    /* For snapshot items: */
    933     if (!pSnapshotItem->isCurrentStateItem())
     983    else
    934984    {
    935985        /* Make sure nothing being edited in the meantime: */
     
    10141064    /* Update details-widget if it's visible: */
    10151065    if (pSnapshotItem && m_pDetailsWidget->isVisible())
    1016         m_pDetailsWidget->setData(*pSnapshotItem, pSnapshotItem->snapshot());
     1066    {
     1067        if (pSnapshotItem->isCurrentStateItem())
     1068            m_pDetailsWidget->setData(m_comMachine);
     1069        else
     1070            m_pDetailsWidget->setData(*pSnapshotItem, pSnapshotItem->snapshot());
     1071    }
    10171072}
    10181073
Note: See TracChangeset for help on using the changeset viewer.

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