- Timestamp:
- Jun 9, 2017 9:53:27 AM (8 years ago)
- 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 31 31 # include <QStackedLayout> 32 32 # include <QTabWidget> 33 # include <QTextBrowser> 33 34 # include <QTextEdit> 34 35 # include <QVBoxLayout> … … 69 70 Q_OBJECT; 70 71 72 signals: 73 74 /** Notifies listeners about @a link was clicked. */ 75 void sigAnchorClicked(const QUrl &link); 76 71 77 public: 72 78 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); 75 83 76 84 /** Returns underlying text-document. */ … … 87 95 /** Prepares all. */ 88 96 void prepare(); 97 98 /** Holds whether we should construct text-browser 99 * instead of simple text-edit otherwise. */ 100 bool m_fLinkSupport; 89 101 90 102 /** Holds the text-edit interface instance. */ … … 162 174 *********************************************************************************************************************************/ 163 175 164 UISnapshotDetailsElement::UISnapshotDetailsElement( QWidget *pParent /* = 0 */)176 UISnapshotDetailsElement::UISnapshotDetailsElement(bool fLinkSupport, QWidget *pParent /* = 0 */) 165 177 : QWidget(pParent) 178 , m_fLinkSupport(fLinkSupport) 166 179 , m_pTextEdit(0) 167 180 { … … 204 217 205 218 /* Create text-browser if requested, text-edit otherwise: */ 206 m_pTextEdit = new QTextEdit;219 m_pTextEdit = m_fLinkSupport ? new QTextBrowser : new QTextEdit; 207 220 AssertPtrReturnVoid(m_pTextEdit); 208 221 { … … 214 227 m_pTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 215 228 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 } 216 236 217 237 /* Add into layout: */ … … 412 432 , m_pLayoutOptions(0) 413 433 , m_pLabelName(0), m_pEditorName(0) 414 , m_pLabelThumbnail(0)415 434 , m_pLabelDescription(0), m_pBrowserDescription(0) 416 435 , m_pLayoutDetails(0) … … 447 466 } 448 467 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()) 468 void 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 507 void UISnapshotDetailsWidget::sltHandleNameChange() 508 { 509 m_newData.m_strName = m_pEditorName->text(); 510 // TODO: Validate 511 //revalidate(m_pErrorPaneName); 512 notify(); 513 } 514 515 void UISnapshotDetailsWidget::sltHandleDescriptionChange() 516 { 517 m_newData.m_strDescription = m_pBrowserDescription->toPlainText(); 518 // TODO: Validate 519 //revalidate(m_pErrorPaneName); 520 notify(); 521 } 522 523 void UISnapshotDetailsWidget::sltHandleAnchorClicked(const QUrl &link) 524 { 525 /* Get the link out of url: */ 526 const QString strLink = link.toString(); 527 if (strLink == "#thumbnail") 456 528 { 457 529 /* We are creating screenshot viewer and show it: */ … … 463 535 pViewer->activateWindow(); 464 536 } 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 else494 {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: Validate512 //revalidate(m_pErrorPaneName);513 notify();514 }515 516 void UISnapshotDetailsWidget::sltHandleDescriptionChange()517 {518 m_newData.m_strDescription = m_pBrowserDescription->toPlainText();519 // TODO: Validate520 //revalidate(m_pErrorPaneName);521 notify();522 537 } 523 538 … … 616 631 } 617 632 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 637 633 /* Create description label: */ 638 634 m_pLabelDescription = new QLabel; … … 643 639 644 640 /* Add into layout: */ 645 m_pLayoutOptions->addWidget(m_pLabelDescription, 2, 0);641 m_pLayoutOptions->addWidget(m_pLabelDescription, 1, 0); 646 642 } 647 643 /* Create description browser: */ … … 660 656 661 657 /* Add into layout: */ 662 m_pLayoutOptions->addWidget(m_pBrowserDescription, 2, 1, 1, 2);658 m_pLayoutOptions->addWidget(m_pBrowserDescription, 1, 1); 663 659 } 664 660 } … … 702 698 m_pLayoutDetails->addWidget(m_details[DetailsElementType_System], 1, 0); 703 699 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 704 707 /* Create 'Display' element: */ 705 708 m_details[DetailsElementType_Display] = createDetailsElement(DetailsElementType_Display); 706 709 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); 708 711 709 712 /* Create 'Storage' element: */ 710 713 m_details[DetailsElementType_Storage] = createDetailsElement(DetailsElementType_Storage); 711 714 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); 713 716 714 717 /* Create 'Audio' element: */ 715 718 m_details[DetailsElementType_Audio] = createDetailsElement(DetailsElementType_Audio); 716 719 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); 718 721 719 722 /* Create 'Network' element: */ 720 723 m_details[DetailsElementType_Network] = createDetailsElement(DetailsElementType_Network); 721 724 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); 723 726 724 727 /* Create 'Serial' element: */ 725 728 m_details[DetailsElementType_Serial] = createDetailsElement(DetailsElementType_Serial); 726 729 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); 728 731 729 732 #ifdef VBOX_WITH_PARALLEL_PORTS … … 731 734 m_details[DetailsElementType_Parallel] = createDetailsElement(DetailsElementType_Parallel); 732 735 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); 734 737 #endif 735 738 … … 737 740 m_details[DetailsElementType_USB] = createDetailsElement(DetailsElementType_USB); 738 741 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); 740 743 741 744 /* Create 'SF' element: */ 742 745 m_details[DetailsElementType_SF] = createDetailsElement(DetailsElementType_SF); 743 746 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); 745 748 } 746 749 … … 759 762 { 760 763 /* Create element: */ 761 UISnapshotDetailsElement *pElement = new UISnapshotDetailsElement; 764 const bool fWithHypertextNavigation = enmType == DetailsElementType_Preview; 765 UISnapshotDetailsElement *pElement = new UISnapshotDetailsElement(fWithHypertextNavigation); 762 766 AssertPtrReturn(pElement, 0); 763 767 { … … 765 769 switch (enmType) 766 770 { 771 case DetailsElementType_Preview: 772 pElement->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 773 break; 767 774 default: 768 775 pElement->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); … … 798 805 ULONG iWidth = 0, iHeight = 0; 799 806 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 807 807 /* Get screenshot if present: */ 808 808 QVector<BYTE> screenData = comMachine.ReadSavedScreenshotToArray(0, KBitmapFormat_PNG, iWidth, iHeight); … … 812 812 : QPixmap(); 813 813 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))); 841 823 } 842 824 else … … 844 826 /* Choose the empty-widget as current one: */ 845 827 m_pStackedLayout->setCurrentWidget(m_pEmptyWidget); 846 847 // TODO: Check whether layout manipulations are really848 // 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 }858 828 } 859 829 … … 883 853 "</tr>" 884 854 "%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"; 885 861 static const char *sSectionItemTpl1 = 886 862 "<tr><td><nobr><i>%1</i></nobr></td><td/><td/></tr>"; … … 889 865 static const char *sSectionItemTpl3 = 890 866 "<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>"; 891 869 892 870 /* 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; 894 873 895 874 /* Determine icon metric: */ … … 1024 1003 tr("System", "details report"), /* title */ 1025 1004 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 */ 1026 1022 1027 1023 break; -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UISnapshotDetailsWidget.h
r67308 r67312 95 95 protected: 96 96 97 /** Preprocesses any Qt @a pEvent for passed @a pObject. */98 virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */;99 100 97 /** Handles translation event. */ 101 98 virtual void retranslateUi() /* override */; … … 107 104 /** Handles snapshot description change. */ 108 105 void sltHandleDescriptionChange(); 106 107 /** Handles snapshot details anchor clicks. */ 108 void sltHandleAnchorClicked(const QUrl &link); 109 109 110 110 private: … … 141 141 UIDataSnapshot m_newData; 142 142 143 /** Holds the cached thumbnail. */144 QPixmap m_pixmapThumbnail;145 143 /** Holds the cached screenshot. */ 146 144 QPixmap m_pixmapScreenshot; … … 165 163 QLineEdit *m_pEditorName; 166 164 167 /** Holds the thumbnail label instance. */168 QLabel *m_pLabelThumbnail;169 170 165 /** Holds the description label instance. */ 171 166 QLabel *m_pLabelDescription;
Note:
See TracChangeset
for help on using the changeset viewer.