VirtualBox

Changeset 67312 in vbox for trunk


Ignore:
Timestamp:
Jun 9, 2017 9:53:27 AM (8 years ago)
Author:
vboxsync
Message:

FE/Qt: Selector UI: Tools pane: Snapshot pane: Extending 'Details' pane with 'Preview' element, removing it from 'Attributes' pane.

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

Legend:

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

    r67308 r67312  
    3131# include <QStackedLayout>
    3232# include <QTabWidget>
     33# include <QTextBrowser>
    3334# include <QTextEdit>
    3435# include <QVBoxLayout>
     
    6970    Q_OBJECT;
    7071
     72signals:
     73
     74    /** Notifies listeners about @a link was clicked. */
     75    void sigAnchorClicked(const QUrl &link);
     76
    7177public:
    7278
    73     /** Constructs details element passing @a pParent to the base-class. */
    74     UISnapshotDetailsElement(QWidget *pParent = 0);
     79    /** Constructs details element passing @a pParent to the base-class.
     80      * @param  fLinkSupport  Brings whether we should construct text-browser
     81      *                       instead of simple text-edit otherwise. */
     82    UISnapshotDetailsElement(bool fLinkSupport, QWidget *pParent = 0);
    7583
    7684    /** Returns underlying text-document. */
     
    8795    /** Prepares all. */
    8896    void prepare();
     97
     98    /** Holds whether we should construct text-browser
     99      * instead of simple text-edit otherwise. */
     100    bool  m_fLinkSupport;
    89101
    90102    /** Holds the text-edit interface instance. */
     
    162174*********************************************************************************************************************************/
    163175
    164 UISnapshotDetailsElement::UISnapshotDetailsElement(QWidget *pParent /* = 0 */)
     176UISnapshotDetailsElement::UISnapshotDetailsElement(bool fLinkSupport, QWidget *pParent /* = 0 */)
    165177    : QWidget(pParent)
     178    , m_fLinkSupport(fLinkSupport)
    166179    , m_pTextEdit(0)
    167180{
     
    204217
    205218        /* Create text-browser if requested, text-edit otherwise: */
    206         m_pTextEdit = new QTextEdit;
     219        m_pTextEdit = m_fLinkSupport ? new QTextBrowser : new QTextEdit;
    207220        AssertPtrReturnVoid(m_pTextEdit);
    208221        {
     
    214227            m_pTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    215228            m_pTextEdit->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
     229            if (m_fLinkSupport)
     230            {
     231                // WORKAROUND:
     232                // Intentionally using old kind of API here:
     233                connect(m_pTextEdit, SIGNAL(anchorClicked(const QUrl &)),
     234                        this, SIGNAL(sigAnchorClicked(const QUrl &)));
     235            }
    216236
    217237            /* Add into layout: */
     
    412432    , m_pLayoutOptions(0)
    413433    , m_pLabelName(0), m_pEditorName(0)
    414     , m_pLabelThumbnail(0)
    415434    , m_pLabelDescription(0), m_pBrowserDescription(0)
    416435    , m_pLayoutDetails(0)
     
    447466}
    448467
    449 bool UISnapshotDetailsWidget::eventFilter(QObject *pObject, QEvent *pEvent)
    450 {
    451     /* We have filter for thumbnail label only: */
    452     AssertReturn(pObject == m_pLabelThumbnail, false);
    453 
    454     /* For a mouse-press event inside the thumbnail area: */
    455     if (pEvent->type() == QEvent::MouseButtonPress && !m_pixmapScreenshot.isNull())
     468void UISnapshotDetailsWidget::retranslateUi()
     469{
     470    /* Translate labels: */
     471    m_pEmptyWidgetLabel->setText("<p>You have the <b>Current State</b> item selected.<br>"
     472                                 "Press <b>Take</b> button if you wish to take a new snapshot.</p>");
     473    m_pTabWidget->setTabText(0, tr("&Attributes"));
     474    m_pTabWidget->setTabText(1, tr("D&etails"));
     475    m_pLabelName->setText(tr("&Name:"));
     476    m_pLabelDescription->setText(tr("&Description:"));
     477
     478    /* And if snapshot is valid: */
     479    if (!m_comSnapshot.isNull())
     480    {
     481        /* Get the machine: */
     482        const CMachine comMachine = m_comSnapshot.GetMachine();
     483
     484        /* Translate the picture tool-tip: */
     485        const QString strToolTip = m_pixmapScreenshot.isNull() ? QString() : tr("Click to enlarge the screenshot.");
     486        m_details.value(DetailsElementType_Preview)->setToolTip(strToolTip);
     487
     488        /* Rebuild the details report: */
     489        foreach (const DetailsElementType &enmType, m_details.keys())
     490            m_details.value(enmType)->setText(detailsReport(comMachine, enmType));
     491    }
     492    else
     493    {
     494        /* Clear the picture tool-tip: */
     495        m_details.value(DetailsElementType_Preview)->setToolTip(QString());
     496
     497        /* Clear the details report: */
     498        // WORKAROUND:
     499        // How stupid Qt *is* to wipe out registered icons not just on clear()
     500        // call but on setText(QString()) and even setText("") as well.
     501        // Nice way to oversmart itself..
     502        foreach (const DetailsElementType &enmType, m_details.keys())
     503            m_details.value(enmType)->setText("<empty>");
     504    }
     505}
     506
     507void UISnapshotDetailsWidget::sltHandleNameChange()
     508{
     509    m_newData.m_strName = m_pEditorName->text();
     510    // TODO: Validate
     511    //revalidate(m_pErrorPaneName);
     512    notify();
     513}
     514
     515void UISnapshotDetailsWidget::sltHandleDescriptionChange()
     516{
     517    m_newData.m_strDescription = m_pBrowserDescription->toPlainText();
     518    // TODO: Validate
     519    //revalidate(m_pErrorPaneName);
     520    notify();
     521}
     522
     523void UISnapshotDetailsWidget::sltHandleAnchorClicked(const QUrl &link)
     524{
     525    /* Get the link out of url: */
     526    const QString strLink = link.toString();
     527    if (strLink == "#thumbnail")
    456528    {
    457529        /* We are creating screenshot viewer and show it: */
     
    463535        pViewer->activateWindow();
    464536    }
    465 
    466     /* Call to base-class: */
    467     return QWidget::eventFilter(pObject, pEvent);
    468 }
    469 
    470 void UISnapshotDetailsWidget::retranslateUi()
    471 {
    472     /* Translate labels: */
    473     m_pEmptyWidgetLabel->setText("<p>You have the <b>Current State</b> item selected.<br>"
    474                                  "Press <b>Take</b> button if you wish to take a new snapshot.</p>");
    475     m_pTabWidget->setTabText(0, tr("&Attributes"));
    476     m_pTabWidget->setTabText(1, tr("D&etails"));
    477     m_pLabelName->setText(tr("&Name:"));
    478     m_pLabelDescription->setText(tr("&Description:"));
    479 
    480     /* And if snapshot is valid: */
    481     if (!m_comSnapshot.isNull())
    482     {
    483         /* Get the machine: */
    484         const CMachine comMachine = m_comSnapshot.GetMachine();
    485 
    486         /* Translate the picture tool-tip: */
    487         m_pLabelThumbnail->setToolTip(m_pixmapScreenshot.isNull() ? QString() : tr("Click to enlarge the screenshot."));
    488 
    489         /* Rebuild the details report: */
    490         foreach (const DetailsElementType &enmType, m_details.keys())
    491             m_details.value(enmType)->setText(detailsReport(comMachine, enmType));
    492     }
    493     else
    494     {
    495         /* Clear the picture tool-tip: */
    496         m_pLabelThumbnail->setToolTip(QString());
    497 
    498         /* Clear the details report: */
    499         // WORKAROUND:
    500         // How stupid Qt *is* to wipe out registered icons not just on clear()
    501         // call but on setText(QString()) and even setText("") as well.
    502         // Nice way to oversmart itself..
    503         foreach (const DetailsElementType &enmType, m_details.keys())
    504             m_details.value(enmType)->setText("<empty>");
    505     }
    506 }
    507 
    508 void UISnapshotDetailsWidget::sltHandleNameChange()
    509 {
    510     m_newData.m_strName = m_pEditorName->text();
    511     // TODO: Validate
    512     //revalidate(m_pErrorPaneName);
    513     notify();
    514 }
    515 
    516 void UISnapshotDetailsWidget::sltHandleDescriptionChange()
    517 {
    518     m_newData.m_strDescription = m_pBrowserDescription->toPlainText();
    519     // TODO: Validate
    520     //revalidate(m_pErrorPaneName);
    521     notify();
    522537}
    523538
     
    616631            }
    617632
    618             /* Create thumbnail label: */
    619             m_pLabelThumbnail = new QLabel;
    620             AssertPtrReturnVoid(m_pLabelThumbnail);
    621             {
    622                 /* Configure label: */
    623                 m_pLabelThumbnail->installEventFilter(this);
    624                 m_pLabelThumbnail->setFrameShape(QFrame::Panel);
    625                 m_pLabelThumbnail->setFrameShadow(QFrame::Sunken);
    626                 m_pLabelThumbnail->setCursor(Qt::PointingHandCursor);
    627                 m_pLabelThumbnail->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
    628                 m_pLabelThumbnail->setAutoFillBackground(true);
    629                 QPalette pal = m_pLabelThumbnail->palette();
    630                 pal.setColor(QPalette::Window, Qt::black);
    631                 m_pLabelThumbnail->setPalette(pal);
    632 
    633                 /* Add into layout: */
    634                 m_pLayoutOptions->addWidget(m_pLabelThumbnail, 0, 2, 2, 1);
    635             }
    636 
    637633            /* Create description label: */
    638634            m_pLabelDescription = new QLabel;
     
    643639
    644640                /* Add into layout: */
    645                 m_pLayoutOptions->addWidget(m_pLabelDescription, 2, 0);
     641                m_pLayoutOptions->addWidget(m_pLabelDescription, 1, 0);
    646642            }
    647643            /* Create description browser: */
     
    660656
    661657                /* Add into layout: */
    662                 m_pLayoutOptions->addWidget(m_pBrowserDescription, 2, 1, 1, 2);
     658                m_pLayoutOptions->addWidget(m_pBrowserDescription, 1, 1);
    663659            }
    664660        }
     
    702698                m_pLayoutDetails->addWidget(m_details[DetailsElementType_System], 1, 0);
    703699
     700                /* Create 'Preview' element: */
     701                m_details[DetailsElementType_Preview] = createDetailsElement(DetailsElementType_Preview);
     702                AssertPtrReturnVoid(m_details[DetailsElementType_Preview]);
     703                connect(m_details[DetailsElementType_Preview], &UISnapshotDetailsElement::sigAnchorClicked,
     704                        this, &UISnapshotDetailsWidget::sltHandleAnchorClicked);
     705                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Preview], 0, 1, 2, 1);
     706
    704707                /* Create 'Display' element: */
    705708                m_details[DetailsElementType_Display] = createDetailsElement(DetailsElementType_Display);
    706709                AssertPtrReturnVoid(m_details[DetailsElementType_Display]);
    707                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Display], 2, 0);
     710                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Display], 2, 0, 1, 2);
    708711
    709712                /* Create 'Storage' element: */
    710713                m_details[DetailsElementType_Storage] = createDetailsElement(DetailsElementType_Storage);
    711714                AssertPtrReturnVoid(m_details[DetailsElementType_Storage]);
    712                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Storage], 3, 0);
     715                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Storage], 3, 0, 1, 2);
    713716
    714717                /* Create 'Audio' element: */
    715718                m_details[DetailsElementType_Audio] = createDetailsElement(DetailsElementType_Audio);
    716719                AssertPtrReturnVoid(m_details[DetailsElementType_Audio]);
    717                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Audio], 4, 0);
     720                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Audio], 4, 0, 1, 2);
    718721
    719722                /* Create 'Network' element: */
    720723                m_details[DetailsElementType_Network] = createDetailsElement(DetailsElementType_Network);
    721724                AssertPtrReturnVoid(m_details[DetailsElementType_Network]);
    722                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Network], 5, 0);
     725                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Network], 5, 0, 1, 2);
    723726
    724727                /* Create 'Serial' element: */
    725728                m_details[DetailsElementType_Serial] = createDetailsElement(DetailsElementType_Serial);
    726729                AssertPtrReturnVoid(m_details[DetailsElementType_Serial]);
    727                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Serial], 6, 0);
     730                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Serial], 6, 0, 1, 2);
    728731
    729732#ifdef VBOX_WITH_PARALLEL_PORTS
     
    731734                m_details[DetailsElementType_Parallel] = createDetailsElement(DetailsElementType_Parallel);
    732735                AssertPtrReturnVoid(m_details[DetailsElementType_Parallel]);
    733                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_Parallel], 7, 0);
     736                m_pLayoutDetails->addWidget(m_details[DetailsElementType_Parallel], 7, 0, 1, 2);
    734737#endif
    735738
     
    737740                m_details[DetailsElementType_USB] = createDetailsElement(DetailsElementType_USB);
    738741                AssertPtrReturnVoid(m_details[DetailsElementType_USB]);
    739                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_USB], 8, 0);
     742                m_pLayoutDetails->addWidget(m_details[DetailsElementType_USB], 8, 0, 1, 2);
    740743
    741744                /* Create 'SF' element: */
    742745                m_details[DetailsElementType_SF] = createDetailsElement(DetailsElementType_SF);
    743746                AssertPtrReturnVoid(m_details[DetailsElementType_SF]);
    744                 m_pLayoutDetails->addWidget(m_details[DetailsElementType_SF], 9, 0);
     747                m_pLayoutDetails->addWidget(m_details[DetailsElementType_SF], 9, 0, 1, 2);
    745748            }
    746749
     
    759762{
    760763    /* Create element: */
    761     UISnapshotDetailsElement *pElement = new UISnapshotDetailsElement;
     764    const bool fWithHypertextNavigation = enmType == DetailsElementType_Preview;
     765    UISnapshotDetailsElement *pElement = new UISnapshotDetailsElement(fWithHypertextNavigation);
    762766    AssertPtrReturn(pElement, 0);
    763767    {
     
    765769        switch (enmType)
    766770        {
     771            case DetailsElementType_Preview:
     772                pElement->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
     773                break;
    767774            default:
    768775                pElement->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
     
    798805        ULONG iWidth = 0, iHeight = 0;
    799806
    800         /* Get thumbnail if present: */
    801         QVector<BYTE> thumbData = comMachine.ReadSavedThumbnailToArray(0, KBitmapFormat_BGR0, iWidth, iHeight);
    802         m_pixmapThumbnail = thumbData.size() != 0 ? QPixmap::fromImage(QImage(thumbData.data(),
    803                                                                               iWidth, iHeight,
    804                                                                               QImage::Format_RGB32).copy())
    805                                                   : QPixmap();
    806 
    807807        /* Get screenshot if present: */
    808808        QVector<BYTE> screenData = comMachine.ReadSavedScreenshotToArray(0, KBitmapFormat_PNG, iWidth, iHeight);
     
    812812                                                    : QPixmap();
    813813
    814         // TODO: Check whether layout manipulations are really
    815         //       necessary, they looks a bit dangerous to me..
    816         if (m_pixmapThumbnail.isNull())
    817         {
    818             m_pLabelThumbnail->setPixmap(QPixmap());
    819 
    820             m_pLayoutOptions->removeWidget(m_pLabelThumbnail);
    821             m_pLabelThumbnail->setHidden(true);
    822 
    823             m_pLayoutOptions->removeWidget(m_pEditorName);
    824             m_pLayoutOptions->addWidget(m_pEditorName, 0, 1, 1, 2);
    825         }
    826         else
    827         {
    828             const QStyle *pStyle = QApplication::style();
    829             const int iIconMetric = pStyle->pixelMetric(QStyle::PM_LargeIconSize);
    830             m_pLabelThumbnail->setPixmap(m_pixmapThumbnail.scaled(QSize(1, iIconMetric),
    831                                                                   Qt::KeepAspectRatioByExpanding,
    832                                                                   Qt::SmoothTransformation));
    833 
    834             m_pLayoutOptions->removeWidget(m_pEditorName);
    835             m_pLayoutOptions->addWidget(m_pEditorName, 0, 1);
    836 
    837             m_pLayoutOptions->removeWidget(m_pLabelThumbnail);
    838             m_pLayoutOptions->addWidget(m_pLabelThumbnail, 0, 2, 2, 1);
    839             m_pLabelThumbnail->setHidden(false);
    840         }
     814        /* Register thumbnail pixmap in preview element: */
     815        // WORKAROUND:
     816        // We are generating it from the screenshot because thumbnail
     817        // returned by the CMachine::ReadSavedThumbnailToArray is too small.
     818        const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
     819        const QSize thumbnailSize = QSize(iIconMetric * 4, iIconMetric * 4);
     820        m_details.value(DetailsElementType_Preview)->document()->addResource(
     821            QTextDocument::ImageResource, QUrl("details://thumbnail"),
     822            QVariant(m_pixmapScreenshot.scaled(thumbnailSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
    841823    }
    842824    else
     
    844826        /* Choose the empty-widget as current one: */
    845827        m_pStackedLayout->setCurrentWidget(m_pEmptyWidget);
    846 
    847         // TODO: Check whether layout manipulations are really
    848         //       necessary, they looks a bit dangerous to me..
    849         {
    850             m_pLabelThumbnail->setPixmap(QPixmap());
    851 
    852             m_pLayoutOptions->removeWidget(m_pLabelThumbnail);
    853             m_pLabelThumbnail->setHidden(true);
    854 
    855             m_pLayoutOptions->removeWidget(m_pEditorName);
    856             m_pLayoutOptions->addWidget(m_pEditorName, 0, 1, 1, 2);
    857         }
    858828    }
    859829
     
    883853        "</tr>"
    884854        "%5";
     855    static const char *sSectionBoldTpl2 =
     856        "<tr>"
     857        "<td width=%3 rowspan=%1 align=left><img src='%2'></td>"
     858        "<td><nobr><b>%4</b></nobr></td>"
     859        "</tr>"
     860        "%5";
    885861    static const char *sSectionItemTpl1 =
    886862        "<tr><td><nobr><i>%1</i></nobr></td><td/><td/></tr>";
     
    889865    static const char *sSectionItemTpl3 =
    890866        "<tr><td><nobr>%1</nobr></td><td/><td/></tr>";
     867    static const char *sSectionItemTpl4 =
     868        "<tr><td><a href='%2'><img src='%1'/></a></td></tr>";
    891869
    892870    /* Use the const ref on the basis of implicit QString constructor: */
    893     const QString &strSectionTpl = sSectionBoldTpl1;
     871    const QString &strSectionTpl = enmType == DetailsElementType_Preview
     872                                 ? sSectionBoldTpl2 : sSectionBoldTpl1;
    894873
    895874    /* Determine icon metric: */
     
    10241003                     tr("System", "details report"), /* title */
    10251004                     strItem); /* items */
     1005
     1006            break;
     1007        }
     1008        case DetailsElementType_Preview:
     1009        {
     1010            /* Preview: */
     1011            int iRowCount = 1;
     1012            QString strItem = QString(sSectionItemTpl4).arg("details://thumbnail").arg("#thumbnail");
     1013
     1014            /* Append report: */
     1015            if (!m_pixmapScreenshot.isNull())
     1016                strReport += strSectionTpl
     1017                    .arg(1 + iRowCount) /* rows */
     1018                    .arg("details://preview", /* icon */
     1019                         QString::number(iIconArea), /* icon area */
     1020                         tr("Preview", "details report"), /* title */
     1021                         strItem); /* items */
    10261022
    10271023            break;
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISnapshotDetailsWidget.h

    r67308 r67312  
    9595protected:
    9696
    97     /** Preprocesses any Qt @a pEvent for passed @a pObject. */
    98     virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */;
    99 
    10097    /** Handles translation event. */
    10198    virtual void retranslateUi() /* override */;
     
    107104    /** Handles snapshot description change. */
    108105    void sltHandleDescriptionChange();
     106
     107    /** Handles snapshot details anchor clicks. */
     108    void sltHandleAnchorClicked(const QUrl &link);
    109109
    110110private:
     
    141141    UIDataSnapshot  m_newData;
    142142
    143     /** Holds the cached thumbnail. */
    144     QPixmap  m_pixmapThumbnail;
    145143    /** Holds the cached screenshot. */
    146144    QPixmap  m_pixmapScreenshot;
     
    165163    QLineEdit *m_pEditorName;
    166164
    167     /** Holds the thumbnail label instance. */
    168     QLabel *m_pLabelThumbnail;
    169 
    170165    /** Holds the description label instance. */
    171166    QLabel    *m_pLabelDescription;
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