- Timestamp:
- Jan 21, 2013 10:15:45 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83250
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/selector
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
r44313 r44318 847 847 { 848 848 /* The VM is inaccessible: */ 849 m_pVMDesktop->updateDetailsError Text(UIMessageCenter::formatErrorInfo(pItem->accessError()));849 m_pVMDesktop->updateDetailsError(UIMessageCenter::formatErrorInfo(pItem->accessError())); 850 850 } 851 851 else -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.cpp
r42854 r44318 7 7 8 8 /* 9 * Copyright (C) 2010-201 1Oracle Corporation9 * Copyright (C) 2010-2013 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 19 19 20 20 /* Qt includes: */ 21 #include <QDir>22 21 #include <QLabel> 23 #include <QScrollArea>24 22 #include <QStackedLayout> 25 23 #include <QStackedWidget> 26 24 #include <QToolButton> 27 #include <QUrl>28 25 29 26 /* GUI includes */ 30 #include "QILabel.h"31 27 #include "UIBar.h" 32 28 #include "UIIconPool.h" 33 #include "UIImageTools.h"34 #include "UIPopupBox.h"35 29 #include "UISpacerWidgets.h" 36 30 #include "UISpecialControls.h" 37 31 #include "UIVMDesktop.h" 38 32 #include "UIVMItem.h" 39 #include "UIVMPreviewWindow.h" 40 #include "UIVirtualBoxEventHandler.h" 33 #include "UIToolBar.h" 41 34 #include "VBoxSnapshotsWgt.h" 42 #include "UIToolBar.h"43 35 #include "VBoxUtils.h" 44 #include "UIConverter.h"45 46 /* COM includes: */47 #include "CSystemProperties.h"48 #include "CStorageController.h"49 #include "CMediumAttachment.h"50 #include "CVRDEServer.h"51 #include "CAudioAdapter.h"52 #include "CNetworkAdapter.h"53 #include "CSerialPort.h"54 #include "CUSBController.h"55 #include "CUSBDeviceFilter.h"56 #include "CSharedFolder.h"57 36 58 37 /* Other VBox includes: */ 59 38 #include <iprt/assert.h> 60 39 61 /* Forward declarations: */62 class UIDetails;63 class UIDetailsBlock;64 class UIDetailsPagePrivate;65 66 40 //#ifdef Q_WS_MAC 67 # define DARWIN_USE_TOOLBAR41 # define USE_TOOLBAR 68 42 //#endif /* Q_WS_MAC */ 69 70 static const QString sTableTpl = "<table border=0 cellspacing=1 cellpadding=0>%1</table>";71 static const QString sSectionItemTpl1 = "<tr><td width=40%><nobr><i>%1</i></nobr></td><td/><td/></tr>";72 static const QString sSectionItemTpl2 = "<tr><td><nobr>%1:</nobr></td><td/><td>%2</td></tr>";73 static const QString sSectionItemTpl3 = "<tr><td width=40%><nobr>%1</nobr></td><td/><td/></tr>";74 static const QString sSectionItemTpl4 = "<tr><td>%1</td><td/><td/></tr>";75 43 76 44 #ifdef Q_WS_MAC … … 86 54 #endif /* !Q_WS_MAC */ 87 55 88 class UIEventDetailsPrepareStart : public QEvent 89 { 56 /* Container to store VM desktop panes. */ 57 class UIVMDesktopPrivate : public QIWithRetranslateUI<QStackedWidget> 58 { 59 Q_OBJECT; 60 90 61 public: 91 62 92 enum { Type = QEvent::User + 1 }; 93 UIEventDetailsPrepareStart() : QEvent((QEvent::Type)Type) {} 94 }; 95 96 class UIEventDetailsPrepareBlockStart : public QEvent 97 { 98 public: 99 100 enum { Type = QEvent::User + 2 }; 101 UIEventDetailsPrepareBlockStart(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {} 102 int blockNumber() const { return m_iBlockNumber; } 63 /* Constructor: */ 64 UIVMDesktopPrivate(QWidget *pParent, QAction *pRefreshAction); 65 66 /* API: Pane text setters stuff: */ 67 void setText(const QString &strText); 68 void setError(const QString &strError); 103 69 104 70 private: 105 71 106 int m_iBlockNumber; 107 }; 108 109 class UIEventDetailsPrepareBlockFinish : public QEvent 110 { 111 public: 112 113 enum { Type = QEvent::User + 3 }; 114 UIEventDetailsPrepareBlockFinish(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {} 115 int blockNumber() const { return m_iBlockNumber; } 116 117 private: 118 119 int m_iBlockNumber; 120 }; 121 122 class UIEventDetailsBlockPrepareStart : public QEvent 123 { 124 public: 125 126 enum { Type = QEvent::User + 1 }; 127 UIEventDetailsBlockPrepareStart() : QEvent((QEvent::Type)Type) {} 128 }; 129 130 class UIEventDetailsBlockPrepareSectionStart : public QEvent 131 { 132 public: 133 134 enum { Type = QEvent::User + 2 }; 135 UIEventDetailsBlockPrepareSectionStart(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {} 136 int sectionNumber() const { return m_iSectionNumber; } 137 138 private: 139 140 int m_iSectionNumber; 141 }; 142 143 class UIEventDetailsBlockPrepareSectionFinish : public QEvent 144 { 145 public: 146 147 enum { Type = QEvent::User + 3 }; 148 UIEventDetailsBlockPrepareSectionFinish(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {} 149 int sectionNumber() const { return m_iSectionNumber; } 150 151 private: 152 153 int m_iSectionNumber; 154 }; 155 156 /* Section types: */ 157 enum Section 158 { 159 Section_General, 160 Section_System, 161 Section_Preview, 162 Section_Display, 163 Section_Storage, 164 Section_Audio, 165 Section_Network, 166 Section_Serial, 167 #ifdef VBOX_WITH_PARALLEL_PORTS 168 Section_Parallel, 169 #endif /* VBOX_WITH_PARALLEL_PORTS */ 170 Section_USB, 171 Section_SharedFolders, 172 Section_Description, 173 Section_End 174 }; 175 176 /** 177 * UIDetails class. 178 * QWidget container to store UIDetailsBlock(s). 179 */ 180 class UIDetails : public QWidget 181 { 182 Q_OBJECT; 183 184 public: 185 186 /* Constructor: */ 187 UIDetails(UIDetailsPagePrivate *pDetailsPage); 188 189 /* Operator: */ 190 UIDetailsBlock*& operator[](int i) { return m_details[i]; } 191 192 /* Machine list setter: */ 193 void setMachines(const QList<CMachine> &machines); 194 195 /* Own wrappers: */ 196 UIDetailsPagePrivate* detailsPage() const { return m_pUIDetailsPage; } 197 const QList<Section>& sections() const { return m_sections; } 198 bool accessibility(int iBlockNumber) const { return m_accessibilities[iBlockNumber]; } 199 void setUSBAvailable(bool fAvailable) { m_fUSBAvailable = fAvailable; } 200 201 /* Parent wrappers: */ 202 bool sectionOpened(Section section) const; 203 void setSectionOpened(Section section, bool fOpened); 204 QAction* action(Section section) const; 205 206 private slots: 207 208 /* Details pane context menu handler: */ 209 void sltContextMenuRequested(const QPoint &pos); 210 211 /* Details pane popup widget toggle handler: */ 212 void sltPopupToggled(bool fPopupOpened); 213 214 private: 215 216 /* Main event handler: */ 217 bool event(QEvent *pEvent); 218 219 /* Block preparation delegate(s): */ 220 void createBlock(int iBlockNumber); 221 void layoutBlock(int iBlockNumber); 222 223 /* Variables: */ 224 UIDetailsPagePrivate *m_pUIDetailsPage; 225 int m_cBlockCount; 226 QVector<CMachine> m_machines; 227 QVector<bool> m_accessibilities; 228 QList<Section> m_sections; 229 QMap<int, UIDetailsBlock*> m_details; 230 bool m_fUSBAvailable; 231 }; 232 233 /** 234 * UIDetailsBlock class. 235 * QWidget container to store UIPopupBox(s). 236 */ 237 class UIDetailsBlock : public QWidget 238 { 239 Q_OBJECT; 240 241 public: 242 243 /* Constructor: */ 244 UIDetailsBlock(UIDetails *pParent, const QList<Section> §ions, int iBlockNumber); 245 246 /* Operator: */ 247 UIPopupBox*& operator[](Section section) { return m_block[section]; } 248 249 /* Machine setter: */ 250 void setMachine(const CMachine &machine); 251 252 /* Own wrappers: */ 253 UIDetails* details() const { return m_pUIDetails; } 254 255 /* Parent wrappers: */ 256 bool accessibility() const; 257 bool sectionOpened(Section section) const; 258 void setUSBAvailable(bool fAvailable); 259 260 private slots: 261 262 /* Popup preparation handlers: */ 263 void sltUpdateGeneral(); 264 void sltUpdateSystem(); 265 void sltUpdatePreview(); 266 void sltUpdateDisplay(); 267 void sltUpdateStorage(); 268 void sltUpdateAudio(); 269 void sltUpdateNetwork(); 270 void sltUpdateSerialPorts(); 271 #ifdef VBOX_WITH_PARALLEL_PORTS 272 void sltUpdateParallelPorts(); 273 #endif /* VBOX_WITH_PARALLEL_PORTS */ 274 void sltUpdateUSB(); 275 void sltUpdateSharedFolders(); 276 void sltUpdateDescription(); 277 278 private: 279 280 /* Main event handler: */ 281 bool event(QEvent *pEvent); 282 283 /* Section preparation delegate: */ 284 void createSection(int iSectionNumber); 285 286 /* Static stuff: */ 287 static QString summarizeGenericProperties(const CNetworkAdapter &adapter); 288 289 /* Variables: */ 290 CVirtualBox m_vbox; 291 CHost m_host; 292 UIDetails *m_pUIDetails; 293 int m_iBlockNumber; 294 int m_cSectionCount; 295 CMachine m_machine; 296 QList<Section> m_sections; 297 UIPopupBoxGroup *m_pPopupBoxGroup; 298 QMap<Section, UIPopupBox*> m_block; 299 }; 300 301 /** 302 * UIDetailsPagePrivate class. 303 * QWidget container to store UIDetails. 304 */ 305 class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget> 306 { 307 Q_OBJECT; 308 309 public: 310 311 /* Constructor/destructor: */ 312 UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction = 0); 313 ~UIDetailsPagePrivate(); 314 315 /* Setters: */ 316 void setMachines(const QList<CMachine> &machines); 317 void setText(const QString &aText); 318 void setErrorText(const QString &aText); 319 320 /* Own wrappers: */ 321 bool sectionOpened(Section section) const { return m_sectionOpened[section]; } 322 void setSectionOpened(Section section, bool fOpened) { m_sectionOpened[section] = fOpened; } 323 QAction* action(Section section) { return m_actions[section]; } 324 325 signals: 326 327 void linkClicked(const QString &url); 328 329 protected: 330 72 /* Helper: Translate stuff: */ 331 73 void retranslateUi(); 332 74 333 private slots: 334 335 void sltLinkClicked(const QUrl &url) { emit linkClicked(url.toString()); } 336 337 private: 338 339 void prepareDetailsPage(); 340 void cleanupDetailsPage(); 341 342 void prepareTextPage(); 343 344 void prepareErrorPage(); 345 346 void prepareDetails(const QList<CMachine> &machines); 347 348 void saveSectionSetting(); 349 350 /* Details-view variables: */ 351 int m_cMachineCount; 352 QScrollArea *m_pScrollArea; 353 UIDetails *m_pDetails; 354 QMap<Section, QString> m_sectionSettings; 355 QMap<Section, QString> m_sectionNames; 356 QMap<Section, bool> m_sectionOpened; 357 QMap<Section, QAction*> m_actions; 358 359 /* Free text: */ 75 /* Helpers: Prepare stuff: */ 76 void prepareTextPane(); 77 void prepareErrorPane(); 78 79 /* Text pane stuff: */ 360 80 QRichTextBrowser *m_pText; 361 81 362 /* Error text: */82 /* Error pane stuff: */ 363 83 QWidget *m_pErrBox; 364 84 QLabel *m_pErrLabel; … … 368 88 }; 369 89 370 UIDetails::UIDetails(UIDetailsPagePrivate *pDetailsPage) 371 : QWidget(pDetailsPage) 372 , m_pUIDetailsPage(pDetailsPage) 373 , m_cBlockCount(0) 374 , m_fUSBAvailable(true) 375 { 376 /* Configure context menu policy: */ 377 setContextMenuPolicy(Qt::CustomContextMenu); 378 connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltContextMenuRequested(const QPoint&))); 379 380 /* Create and configure main layout: */ 381 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 382 pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 383 pMainLayout->addStretch(1); 384 } 385 386 void UIDetails::setMachines(const QList<CMachine> &machines) 387 { 388 /* If details preparing is NOT yet started: */ 389 if (m_cBlockCount != machines.size()) 390 { 391 /* Get new machine count: */ 392 m_cBlockCount = machines.size(); 393 394 /* Populate list of available sections: */ 395 if (m_cBlockCount == 1) 396 { 397 m_sections << Section_General 398 << Section_System 399 << Section_Preview 400 << Section_Display 401 << Section_Storage 402 << Section_Audio 403 << Section_Network 404 << Section_Serial 405 #ifdef VBOX_WITH_PARALLEL_PORTS 406 << Section_Parallel 407 #endif /* VBOX_WITH_PARALLEL_PORTS */ 408 << Section_USB 409 << Section_SharedFolders 410 << Section_Description; 411 } 412 else 413 { 414 m_sections << Section_General 415 << Section_System 416 << Section_Preview; 417 } 418 } 419 420 /* Reset variables: */ 421 m_machines.clear(); 422 m_machines.resize(m_cBlockCount); 423 m_accessibilities.clear(); 424 m_accessibilities.resize(m_cBlockCount); 425 m_fUSBAvailable = true; 426 427 /* Fetch passed VMs: */ 428 for (int i = 0; i < machines.size(); ++i) 429 { 430 /* Get current VM: */ 431 const CMachine &machine = machines[i]; 432 /* Assign corresponding vector values: */ 433 m_machines[i] = machine; 434 m_accessibilities[i] = machine.isNull() || !machine.GetAccessible() ? false : 435 machine.GetState() != KMachineState_Stuck && 436 machine.GetState() != KMachineState_Saved /* for now! */; 437 } 438 439 /* Start preparing details content (blocks): */ 440 QCoreApplication::postEvent(this, new UIEventDetailsPrepareStart); 441 } 442 443 QAction* UIDetails::action(Section section) const 444 { 445 return m_pUIDetailsPage->action(section); 446 } 447 448 bool UIDetails::sectionOpened(Section section) const 449 { 450 return m_pUIDetailsPage->sectionOpened(section); 451 } 452 453 void UIDetails::setSectionOpened(Section section, bool fOpened) 454 { 455 m_pUIDetailsPage->setSectionOpened(section, fOpened); 456 } 457 458 void UIDetails::sltContextMenuRequested(const QPoint &pos) 459 { 460 /* Populate list of allowed actions: */ 461 QList<QAction*> actions; 462 for (int i = 0; i < m_sections.size(); ++i) 463 actions << action(m_sections[i]); 464 /* Restrict USB action if USB is NOT available: */ 465 if (!m_fUSBAvailable) 466 actions.removeOne(action(Section_USB)); 467 /* Popup menu to show/hide sections: */ 468 QAction *pReturn = QMenu::exec(actions, mapToGlobal(pos), 0); 469 /* If some action was toggled: */ 470 if (pReturn) 471 { 472 /* Get corresponding section type: */ 473 Section section = static_cast<Section>(pReturn->data().toInt()); 474 /* Enumerate all the available blocks: */ 475 for (int i = 0; i < m_cBlockCount; ++i) 476 { 477 /* Get current popup: */ 478 UIPopupBox *pPopup = (*m_details[i])[section]; 479 /* Show/hide popup if necessary: */ 480 if (pReturn->isChecked()) 481 pPopup->show(); 482 else 483 pPopup->hide(); 484 } 485 } 486 } 487 488 void UIDetails::sltPopupToggled(bool fPopupOpened) 489 { 490 /* Get current sender: */ 491 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 492 AssertMsg(pSender, ("Sender should be valid!\n")); 493 /* Get section type: */ 494 Section section = static_cast<Section>(pSender->property("section-type").toInt()); 495 /* Update the state of corresponding map: */ 496 setSectionOpened(section, fPopupOpened); 497 /* Open/Close all the blocks: */ 498 for (int i = 0; i < m_cBlockCount; ++i) 499 (*m_details[i])[section]->setOpen(fPopupOpened); 500 } 501 502 bool UIDetails::event(QEvent *pEvent) 503 { 504 /* Handle special events: */ 505 switch (pEvent->type()) 506 { 507 /* Handle details-prepare-start event: */ 508 case UIEventDetailsPrepareStart::Type: 509 { 510 /* Cast and accept event: */ 511 UIEventDetailsPrepareStart *pEventDetailsPrepareStart = static_cast<UIEventDetailsPrepareStart*>(pEvent); 512 pEventDetailsPrepareStart->accept(); 513 /* Create request for the first block: */ 514 QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(0)); 515 /* Finish processing: */ 516 return true; 517 } 518 /* Handle details-block-prepare-start event: */ 519 case UIEventDetailsPrepareBlockStart::Type: 520 { 521 /* Cast and accept event: */ 522 UIEventDetailsPrepareBlockStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsPrepareBlockStart*>(pEvent); 523 pEventDetailsBlockPrepareStart->accept(); 524 /* Start preparing block: */ 525 createBlock(pEventDetailsBlockPrepareStart->blockNumber()); 526 /* Finish processing: */ 527 return true; 528 } 529 /* Handle details-block-prepare-finish event: */ 530 case UIEventDetailsPrepareBlockFinish::Type: 531 { 532 /* Cast and accept event: */ 533 UIEventDetailsPrepareBlockFinish *pEventDetailsBlockPrepareFinish = static_cast<UIEventDetailsPrepareBlockFinish*>(pEvent); 534 pEventDetailsBlockPrepareFinish->accept(); 535 /* Finish preparing block: */ 536 layoutBlock(pEventDetailsBlockPrepareFinish->blockNumber()); 537 /* Create request for the next block if possible: */ 538 if (pEventDetailsBlockPrepareFinish->blockNumber() < m_cBlockCount - 1) 539 QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(pEventDetailsBlockPrepareFinish->blockNumber() + 1)); 540 /* Finish processing: */ 541 return true; 542 } 543 default: 544 break; 545 } 546 /* Propagate to base-class: */ 547 return QWidget::event(pEvent); 548 } 549 550 void UIDetails::createBlock(int iBlockNumber) 551 { 552 /* If block creation is NOT yet started: */ 553 if (!m_details.contains(iBlockNumber)) 554 { 555 /* Create new block: */ 556 m_details[iBlockNumber] = new UIDetailsBlock(this, m_sections, iBlockNumber); 557 } 558 559 /* Assign block with corresponding machine: */ 560 m_details[iBlockNumber]->setMachine(m_machines[iBlockNumber]); 561 } 562 563 void UIDetails::layoutBlock(int iBlockNumber) 564 { 565 /* Get current block: */ 566 UIDetailsBlock *pBlock = m_details[iBlockNumber]; 567 568 /* If block layouting is NOT yet started: */ 569 if (!pBlock->layout()) 570 { 571 /* Declare variables: */ 572 UIDetailsBlock &block = *pBlock; 573 574 /* Layout block content: */ 575 QVBoxLayout *pContainerLayout = new QVBoxLayout(pBlock); 576 pContainerLayout->setContentsMargins(0, 0, 0, 0); 577 QHBoxLayout *pt1 = new QHBoxLayout; 578 QVBoxLayout *pt2 = new QVBoxLayout; 579 if (m_sections.contains(Section_General)) 580 pt2->addWidget(block[Section_General]); 581 if (m_sections.contains(Section_System)) 582 pt2->addWidget(block[Section_System]); 583 pt2->addStretch(1); 584 pt1->addLayout(pt2); 585 QVBoxLayout *pt3 = new QVBoxLayout; 586 if (m_sections.contains(Section_Preview)) 587 pt3->addWidget(block[Section_Preview]); 588 pt3->addStretch(1); 589 pt1->addLayout(pt3); 590 pContainerLayout->addLayout(pt1); 591 if (m_sections.contains(Section_Display)) 592 pContainerLayout->addWidget(block[Section_Display]); 593 if (m_sections.contains(Section_Storage)) 594 pContainerLayout->addWidget(block[Section_Storage]); 595 if (m_sections.contains(Section_Audio)) 596 pContainerLayout->addWidget(block[Section_Audio]); 597 if (m_sections.contains(Section_Network)) 598 pContainerLayout->addWidget(block[Section_Network]); 599 if (m_sections.contains(Section_Serial)) 600 pContainerLayout->addWidget(block[Section_Serial]); 601 #ifdef VBOX_WITH_PARALLEL_PORTS 602 if (m_sections.contains(Section_Parallel)) 603 pContainerLayout->addWidget(block[Section_Parallel]); 604 #endif /* VBOX_WITH_PARALLEL_PORTS */ 605 if (m_sections.contains(Section_USB)) 606 pContainerLayout->addWidget(block[Section_USB]); 607 if (m_sections.contains(Section_SharedFolders)) 608 pContainerLayout->addWidget(block[Section_SharedFolders]); 609 if (m_sections.contains(Section_Description)) 610 pContainerLayout->addWidget(block[Section_Description]); 611 QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>(layout()); 612 pMainLayout->insertWidget(pMainLayout->count() - 1, pBlock); 613 614 /* Configure block content: */ 615 for (int i = 0; i < m_sections.size(); ++i) 616 { 617 /* Assign corresponding action text as section title: */ 618 block[m_sections[i]]->setTitle(action(m_sections[i])->text()); 619 620 /* If corresponding action is checked: */ 621 if (action(m_sections[i])->isChecked()) 622 { 623 /* Unhide corresponding section: */ 624 block[m_sections[i]]->show(); 625 } 626 } 627 628 /* Show block: */ 629 block.show(); 630 631 /* Layout parent scroll-area: */ 632 QEvent layoutEvent(QEvent::LayoutRequest); 633 QCoreApplication::sendEvent(parent(), &layoutEvent); 634 } 635 636 /* Paint block: */ 637 pBlock->repaint(); 638 } 639 640 UIDetailsBlock::UIDetailsBlock(UIDetails *pParent, const QList<Section> §ions, int iBlockNumber) 641 : QWidget(pParent) 642 , m_vbox(vboxGlobal().virtualBox()) 643 , m_host(vboxGlobal().host()) 644 , m_pUIDetails(pParent) 645 , m_iBlockNumber(iBlockNumber) 646 , m_cSectionCount(0) 647 , m_sections(sections) 648 , m_pPopupBoxGroup(new UIPopupBoxGroup(this)) 649 { 650 } 651 652 void UIDetailsBlock::setMachine(const CMachine &machine) 653 { 654 /* If block preparing is NOT yet started: */ 655 if (m_cSectionCount != m_sections.size()) 656 { 657 /* Get new section count: */ 658 m_cSectionCount = m_sections.size(); 659 } 660 661 /* Set passed VM: */ 662 m_machine = machine; 663 664 /* Start preparing details block content (sections): */ 665 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareStart); 666 } 667 668 bool UIDetailsBlock::accessibility() const 669 { 670 return m_pUIDetails->accessibility(m_iBlockNumber); 671 } 672 673 bool UIDetailsBlock::sectionOpened(Section section) const 674 { 675 return m_pUIDetails->sectionOpened(section); 676 } 677 678 void UIDetailsBlock::setUSBAvailable(bool fAvailable) 679 { 680 m_pUIDetails->setUSBAvailable(fAvailable); 681 } 682 683 void UIDetailsBlock::sltUpdateGeneral() 684 { 685 /* Get current sender: */ 686 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 687 AssertMsg(pSender, ("Sender should be valid!\n")); 688 /* Get corresponding content widget: */ 689 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_General]->contentWidget()); 690 AssertMsg(pLabel, ("Content widget should be valid!")); 691 692 /* Enable link: */ 693 m_block[Section_General]->setTitleLinkEnabled(accessibility()); 694 695 /* Update if content widget is visible: */ 696 if (pSender->isOpen()) 697 { 698 if (!m_machine.isNull()) 699 { 700 QString item; 701 if (m_machine.GetAccessible()) 702 { 703 item = sSectionItemTpl2.arg(tr("Name", "details report"), m_machine.GetName()) 704 + sSectionItemTpl2.arg(tr("OS Type", "details report"), vboxGlobal().vmGuestOSTypeDescription(m_machine.GetOSTypeId())); 705 } 706 else 707 { 708 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 709 } 710 pLabel->setText(sTableTpl.arg(item)); 711 } 712 else 713 pLabel->clear(); 714 } 715 } 716 717 void UIDetailsBlock::sltUpdateSystem() 718 { 719 /* Get current sender: */ 720 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 721 AssertMsg(pSender, ("Sender should be valid!\n")); 722 /* Get corresponding content widget: */ 723 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_System]->contentWidget()); 724 AssertMsg(pLabel, ("Content widget should be valid!")); 725 726 /* Enable link: */ 727 m_block[Section_System]->setTitleLinkEnabled(accessibility()); 728 729 /* Update if content widget is visible: */ 730 if (pSender->isOpen()) 731 { 732 if (!m_machine.isNull()) 733 { 734 QString item; 735 if (m_machine.GetAccessible()) 736 { 737 item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 738 .arg(m_machine.GetMemorySize()); 739 740 int cCPU = m_machine.GetCPUCount(); 741 if (cCPU > 1) 742 item += sSectionItemTpl2.arg(tr("Processors", "details report"), tr("<nobr>%1</nobr>", "details report")) 743 .arg(cCPU); 744 745 int iCPUExecCap = m_machine.GetCPUExecutionCap(); 746 if (iCPUExecCap < 100) 747 item += sSectionItemTpl2.arg(tr("Execution Cap", "details report"), tr("<nobr>%1%</nobr>", "details report")) 748 .arg(iCPUExecCap); 749 750 /* Boot order: */ 751 QStringList bootOrder; 752 for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i) 753 { 754 KDeviceType device = m_machine.GetBootOrder(i); 755 if (device == KDeviceType_Null) 756 continue; 757 bootOrder << gpConverter->toString(device); 758 } 759 if (bootOrder.isEmpty()) 760 bootOrder << gpConverter->toString(KDeviceType_Null); 761 762 item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", ")); 763 764 #ifdef VBOX_WITH_FULL_DETAILS_REPORT 765 /* BIOS Settings holder: */ 766 const CBIOSSettings &biosSettings = m_machine.GetBIOSSettings(); 767 QStringList bios; 768 769 /* ACPI: */ 770 if (biosSettings.GetACPIEnabled()) 771 bios << tr("ACPI", "details report"); 772 773 /* IO APIC: */ 774 if (biosSettings.GetIOAPICEnabled()) 775 bios << tr("IO APIC", "details report"); 776 777 if (!bios.isEmpty()) 778 item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", ")); 779 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */ 780 781 QStringList accel; 782 if (m_host.GetProcessorFeature(KProcessorFeature_HWVirtEx)) 783 { 784 /* VT-x/AMD-V: */ 785 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)) 786 { 787 accel << tr("VT-x/AMD-V", "details report"); 788 789 /* Nested Paging (only when hw virt is enabled): */ 790 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)) 791 accel << tr("Nested Paging", "details report"); 792 } 793 } 794 795 /* PAE/NX: */ 796 if (m_machine.GetCPUProperty(KCPUPropertyType_PAE)) 797 accel << tr("PAE/NX", "details report"); 798 799 if (!accel.isEmpty()) 800 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 801 } 802 else 803 { 804 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 805 } 806 pLabel->setText(sTableTpl.arg(item)); 807 } 808 else 809 pLabel->clear(); 810 } 811 } 812 813 void UIDetailsBlock::sltUpdatePreview() 814 { 815 /* Get current sender: */ 816 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 817 AssertMsg(pSender, ("Sender should be valid!\n")); 818 /* Get corresponding content widget: */ 819 UIVMPreviewWindow *pPreview = qobject_cast<UIVMPreviewWindow*>(m_block[Section_Preview]->contentWidget()); 820 AssertMsg(pPreview, ("Content widget should be valid!")); 821 822 /* Update if content widget is visible: */ 823 if (pSender->isOpen()) 824 { 825 /* Update preview widget: */ 826 pPreview->setMachine(m_machine); 827 } 828 } 829 830 void UIDetailsBlock::sltUpdateDisplay() 831 { 832 /* Get current sender: */ 833 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 834 AssertMsg(pSender, ("Sender should be valid!\n")); 835 /* Get corresponding content widget: */ 836 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Display]->contentWidget()); 837 AssertMsg(pLabel, ("Content widget should be valid!")); 838 839 /* Enable link: */ 840 m_block[Section_Display]->setTitleLinkEnabled(accessibility()); 841 842 /* Update if content widget is visible: */ 843 if (pSender->isOpen()) 844 { 845 if (!m_machine.isNull()) 846 { 847 /* Video tab: */ 848 QString item = QString(sSectionItemTpl2).arg(tr("Video Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 849 .arg(m_machine.GetVRAMSize()); 850 851 int cGuestScreens = m_machine.GetMonitorCount(); 852 if (cGuestScreens > 1) 853 item += QString(sSectionItemTpl2).arg(tr("Screens", "details report")).arg(cGuestScreens); 854 855 QStringList accel; 856 #ifdef VBOX_WITH_VIDEOHWACCEL 857 if (m_machine.GetAccelerate2DVideoEnabled()) 858 accel << tr("2D Video", "details report"); 859 #endif /* VBOX_WITH_VIDEOHWACCEL */ 860 if (m_machine.GetAccelerate3DEnabled()) 861 accel << tr("3D", "details report"); 862 863 if (!accel.isEmpty()) 864 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 865 866 /* VRDE tab: */ 867 CVRDEServer srv = m_machine.GetVRDEServer(); 868 if (!srv.isNull()) 869 { 870 if (srv.GetEnabled()) 871 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server Port", "details report (VRDE Server)")) 872 .arg(srv.GetVRDEProperty("TCP/Ports")); 873 else 874 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server", "details report (VRDE Server)")) 875 .arg(tr("Disabled", "details report (VRDE Server)")); 876 } 877 878 pLabel->setText(sTableTpl.arg(item)); 879 } 880 else 881 pLabel->clear(); 882 } 883 } 884 885 void UIDetailsBlock::sltUpdateStorage() 886 { 887 /* Get current sender: */ 888 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 889 AssertMsg(pSender, ("Sender should be valid!\n")); 890 /* Get corresponding content widget: */ 891 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Storage]->contentWidget()); 892 AssertMsg(pLabel, ("Content widget should be valid!")); 893 894 /* Enable link: */ 895 m_block[Section_Storage]->setTitleLinkEnabled(accessibility()); 896 897 /* Update if content widget is visible: */ 898 if (pSender->isOpen()) 899 { 900 if (!m_machine.isNull()) 901 { 902 QString item; 903 /* Iterate over the all m_machine controllers: */ 904 const CStorageControllerVector &controllers = m_machine.GetStorageControllers(); 905 for (int i = 0; i < controllers.size(); ++i) 906 { 907 /* Get current controller: */ 908 const CStorageController &controller = controllers[i]; 909 /* Add controller information: */ 910 item += QString(sSectionItemTpl3).arg(controller.GetName()); 911 912 /* Populate sorted map with attachments information: */ 913 QMap<StorageSlot,QString> attachmentsMap; 914 const CMediumAttachmentVector &attachments = m_machine.GetMediumAttachmentsOfController(controller.GetName()); 915 for (int j = 0; j < attachments.size(); ++j) 916 { 917 /* Get current attachment: */ 918 const CMediumAttachment &attachment = attachments[j]; 919 /* Prepare current storage slot: */ 920 StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()); 921 /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */ 922 QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString(); 923 if (!strDeviceType.isNull()) 924 strDeviceType.prepend(' '); 925 /* Prepare current medium object: */ 926 const CMedium &medium = attachment.GetMedium(); 927 /* Prepare information about current medium & attachment: */ 928 QString strAttachmentInfo = !attachment.isOk() ? QString() : 929 QString(sSectionItemTpl2) 930 .arg(QString(" ") + 931 gpConverter->toString(StorageSlot(controller.GetBus(), 932 attachment.GetPort(), 933 attachment.GetDevice())) + 934 strDeviceType) 935 .arg(vboxGlobal().details(medium, false)); 936 /* Insert that attachment into map: */ 937 if (!strAttachmentInfo.isNull()) 938 attachmentsMap.insert(attachmentSlot, strAttachmentInfo); 939 } 940 941 /* Iterate over the sorted map with attachments information: */ 942 QMapIterator<StorageSlot,QString> it(attachmentsMap); 943 while (it.hasNext()) 944 { 945 /* Add controller information: */ 946 it.next(); 947 item += it.value(); 948 } 949 } 950 951 if (item.isNull()) 952 item = QString(sSectionItemTpl1).arg(tr("Not Attached", "details report (Storage)")); 953 954 pLabel->setText(sTableTpl.arg(item)); 955 } 956 else 957 pLabel->clear(); 958 } 959 } 960 961 void UIDetailsBlock::sltUpdateAudio() 962 { 963 /* Get current sender: */ 964 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 965 AssertMsg(pSender, ("Sender should be valid!\n")); 966 /* Get corresponding content widget: */ 967 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Audio]->contentWidget()); 968 AssertMsg(pLabel, ("Content widget should be valid!")); 969 970 /* Enable link: */ 971 m_block[Section_Audio]->setTitleLinkEnabled(accessibility()); 972 973 /* Update if content widget is visible: */ 974 if (pSender->isOpen()) 975 { 976 if (!m_machine.isNull()) 977 { 978 QString item; 979 980 const CAudioAdapter &audio = m_machine.GetAudioAdapter(); 981 if (audio.GetEnabled()) 982 item = QString(sSectionItemTpl2).arg(tr("Host Driver", "details report (audio)"), 983 gpConverter->toString(audio.GetAudioDriver())) + 984 QString(sSectionItemTpl2).arg(tr("Controller", "details report (audio)"), 985 gpConverter->toString(audio.GetAudioController())); 986 else 987 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (audio)")); 988 989 pLabel->setText(sTableTpl.arg(item)); 990 } 991 else 992 pLabel->clear(); 993 } 994 } 995 996 void UIDetailsBlock::sltUpdateNetwork() 997 { 998 /* Get current sender: */ 999 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1000 AssertMsg(pSender, ("Sender should be valid!\n")); 1001 /* Get corresponding content widget: */ 1002 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Network]->contentWidget()); 1003 AssertMsg(pLabel, ("Content widget should be valid!")); 1004 1005 /* Enable link: */ 1006 m_block[Section_Network]->setTitleLinkEnabled(accessibility()); 1007 1008 /* Update if content widget is visible: */ 1009 if (pSender->isOpen()) 1010 { 1011 if (!m_machine.isNull()) 1012 { 1013 QString item; 1014 1015 ulong count = m_vbox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3); 1016 for (ulong slot = 0; slot < count; slot ++) 1017 { 1018 const CNetworkAdapter &adapter = m_machine.GetNetworkAdapter(slot); 1019 if (adapter.GetEnabled()) 1020 { 1021 KNetworkAttachmentType type = adapter.GetAttachmentType(); 1022 QString attType = gpConverter->toString(adapter.GetAdapterType()) 1023 .replace(QRegExp("\\s\\(.+\\)"), " (%1)"); 1024 /* Don't use the adapter type string for types that have 1025 * an additional symbolic network/interface name field, 1026 * use this name instead: */ 1027 if (type == KNetworkAttachmentType_Bridged) 1028 attType = attType.arg(tr("Bridged adapter, %1", "details report (network)").arg(adapter.GetBridgedInterface())); 1029 else if (type == KNetworkAttachmentType_Internal) 1030 attType = attType.arg(tr("Internal network, '%1'", "details report (network)").arg(adapter.GetInternalNetwork())); 1031 else if (type == KNetworkAttachmentType_HostOnly) 1032 attType = attType.arg(tr("Host-only adapter, '%1'", "details report (network)").arg(adapter.GetHostOnlyInterface())); 1033 else if (type == KNetworkAttachmentType_Generic) 1034 { 1035 QString strGenericDriverProperties(summarizeGenericProperties(adapter)); 1036 attType = strGenericDriverProperties.isNull() ? 1037 attType.arg(tr("Generic driver, '%1'", "details report (network)").arg(adapter.GetGenericDriver())) : 1038 attType.arg(tr("Generic driver, '%1' { %2 }", "details report (network)") 1039 .arg(adapter.GetGenericDriver(), strGenericDriverProperties)); 1040 } 1041 else 1042 attType = attType.arg(gpConverter->toString(type)); 1043 1044 item += QString(sSectionItemTpl2).arg(tr("Adapter %1", "details report (network)").arg(adapter.GetSlot() + 1)) 1045 .arg(attType); 1046 } 1047 } 1048 if (item.isNull()) 1049 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (network)")); 1050 1051 pLabel->setText(sTableTpl.arg(item)); 1052 } 1053 else 1054 pLabel->clear(); 1055 } 1056 } 1057 1058 void UIDetailsBlock::sltUpdateSerialPorts() 1059 { 1060 /* Get current sender: */ 1061 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1062 AssertMsg(pSender, ("Sender should be valid!\n")); 1063 /* Get corresponding content widget: */ 1064 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Serial]->contentWidget()); 1065 AssertMsg(pLabel, ("Content widget should be valid!")); 1066 1067 /* Enable link: */ 1068 m_block[Section_Serial]->setTitleLinkEnabled(accessibility()); 1069 1070 /* Update if content widget is visible: */ 1071 if (pSender->isOpen()) 1072 { 1073 if (!m_machine.isNull()) 1074 { 1075 QString item; 1076 1077 ulong count = m_vbox.GetSystemProperties().GetSerialPortCount(); 1078 for (ulong slot = 0; slot < count; slot ++) 1079 { 1080 const CSerialPort &port = m_machine.GetSerialPort(slot); 1081 if (port.GetEnabled()) 1082 { 1083 KPortMode mode = port.GetHostMode(); 1084 QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", "; 1085 if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice || mode == KPortMode_RawFile) 1086 data += QString("%1 (<nobr>%2</nobr>)").arg(gpConverter->toString(mode)).arg(QDir::toNativeSeparators(port.GetPath())); 1087 else 1088 data += gpConverter->toString(mode); 1089 1090 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (serial ports)").arg(port.GetSlot() + 1)) 1091 .arg(data); 1092 } 1093 } 1094 if (item.isNull()) 1095 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (serial ports)")); 1096 1097 pLabel->setText(sTableTpl.arg(item)); 1098 } 1099 else 1100 pLabel->clear(); 1101 } 1102 } 1103 1104 #ifdef VBOX_WITH_PARALLEL_PORTS 1105 void UIDetailsBlock::sltUpdateParallelPorts() 1106 { 1107 /* Get current sender: */ 1108 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1109 AssertMsg(pSender, ("Sender should be valid!\n")); 1110 /* Get corresponding content widget: */ 1111 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Parallel]->contentWidget()); 1112 AssertMsg(pLabel, ("Content widget should be valid!")); 1113 1114 /* Enable link: */ 1115 m_block[Section_Parallel]->setTitleLinkEnabled(accessibility()); 1116 1117 /* Update if content widget is visible: */ 1118 if (pSender->isOpen()) 1119 { 1120 if (!m_machine.isNull()) 1121 { 1122 QString item; 1123 1124 ulong count = m_vbox.GetSystemProperties().GetParallelPortCount(); 1125 for (ulong slot = 0; slot < count; slot ++) 1126 { 1127 const CParallelPort &port = m_machine.GetParallelPort(slot); 1128 if (port.GetEnabled()) 1129 { 1130 QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) + 1131 QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath())); 1132 1133 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (parallel ports)").arg(port.GetSlot() + 1)) 1134 .arg(data); 1135 } 1136 } 1137 if (item.isNull()) 1138 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (parallel ports)")); 1139 1140 pLabel->setText(sTableTpl.arg(item)); 1141 } 1142 else 1143 pLabel->clear(); 1144 } 1145 } 1146 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1147 1148 void UIDetailsBlock::sltUpdateUSB() 1149 { 1150 /* Get current sender: */ 1151 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1152 AssertMsg(pSender, ("Sender should be valid!\n")); 1153 /* Get corresponding content widget: */ 1154 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_USB]->contentWidget()); 1155 AssertMsg(pLabel, ("Content widget should be valid!")); 1156 1157 /* Enable link: */ 1158 m_block[Section_USB]->setTitleLinkEnabled(accessibility()); 1159 1160 /* Update if content widget is visible: */ 1161 if (pSender->isOpen()) 1162 { 1163 if (!m_machine.isNull()) 1164 { 1165 QString item; 1166 1167 const CUSBController &ctl = m_machine.GetUSBController(); 1168 if (!ctl.isNull() && ctl.GetProxyAvailable()) 1169 { 1170 setUSBAvailable(true); 1171 /* The USB controller may be unavailable (i.e. in VirtualBox OSE): */ 1172 if (ctl.GetEnabled()) 1173 { 1174 const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters(); 1175 uint active = 0; 1176 for (int i = 0; i < coll.size(); ++i) 1177 if (coll[i].GetActive()) 1178 ++active; 1179 1180 item = QString(sSectionItemTpl2).arg(tr("Device Filters", "details report (USB)"), 1181 tr("%1 (%2 active)", "details report (USB)").arg(coll.size()).arg(active)); 1182 } 1183 else 1184 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (USB)")); 1185 1186 pLabel->setText(sTableTpl.arg(item)); 1187 } 1188 else 1189 { 1190 setUSBAvailable(false); 1191 /* Fully hide when USB is not available: */ 1192 m_block[Section_USB]->hide(); 1193 } 1194 } 1195 else 1196 pLabel->clear(); 1197 } 1198 } 1199 1200 void UIDetailsBlock::sltUpdateSharedFolders() 1201 { 1202 /* Get current sender: */ 1203 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1204 AssertMsg(pSender, ("Sender should be valid!\n")); 1205 /* Get corresponding content widget: */ 1206 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_SharedFolders]->contentWidget()); 1207 AssertMsg(pLabel, ("Content widget should be valid!")); 1208 1209 /* Enable link: */ 1210 m_block[Section_SharedFolders]->setTitleLinkEnabled(accessibility()); 1211 1212 /* Update if content widget is visible: */ 1213 if (pSender->isOpen()) 1214 { 1215 if (!m_machine.isNull()) 1216 { 1217 QString item; 1218 1219 ulong count = m_machine.GetSharedFolders().size(); 1220 if (count > 0) 1221 { 1222 item = QString(sSectionItemTpl2).arg(tr("Shared Folders", "details report (shared folders)")).arg(count); 1223 } 1224 else 1225 item = QString(sSectionItemTpl1).arg(tr("None", "details report (shared folders)")); 1226 1227 pLabel->setText(sTableTpl.arg(item)); 1228 } 1229 else 1230 pLabel->clear(); 1231 } 1232 } 1233 1234 void UIDetailsBlock::sltUpdateDescription() 1235 { 1236 /* Get current sender: */ 1237 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1238 AssertMsg(pSender, ("Sender should be valid!\n")); 1239 /* Get corresponding content widget: */ 1240 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Description]->contentWidget()); 1241 AssertMsg(pLabel, ("Content widget should be valid!")); 1242 1243 /* Enable link: */ 1244 m_block[Section_Description]->setTitleLinkEnabled(accessibility()); 1245 1246 /* Update if content widget is visible: */ 1247 if (pSender->isOpen()) 1248 { 1249 if (!m_machine.isNull()) 1250 { 1251 QString item; 1252 const QString &strDesc = m_machine.GetDescription(); 1253 if (!strDesc.isEmpty()) 1254 item = QString(sSectionItemTpl4).arg(strDesc); 1255 else 1256 item = QString(sSectionItemTpl1).arg(tr("None", "details report (description)")); 1257 1258 pLabel->setText(sTableTpl.arg(item)); 1259 } 1260 else 1261 pLabel->clear(); 1262 } 1263 } 1264 1265 bool UIDetailsBlock::event(QEvent *pEvent) 1266 { 1267 /* Handle special events: */ 1268 switch (pEvent->type()) 1269 { 1270 /* Handle details-block-prepare-start event: */ 1271 case UIEventDetailsBlockPrepareStart::Type: 1272 { 1273 /* Cast and accept event: */ 1274 UIEventDetailsBlockPrepareStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsBlockPrepareStart*>(pEvent); 1275 pEventDetailsBlockPrepareStart->accept(); 1276 /* Create request for the first section: */ 1277 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(0)); 1278 /* Finish processing: */ 1279 return true; 1280 } 1281 /* Handle details-block-section-prepare-start event: */ 1282 case UIEventDetailsBlockPrepareSectionStart::Type: 1283 { 1284 /* Cast and accept event: */ 1285 UIEventDetailsBlockPrepareSectionStart *pEventDetailsBlockPrepareSectionStart = static_cast<UIEventDetailsBlockPrepareSectionStart*>(pEvent); 1286 pEventDetailsBlockPrepareSectionStart->accept(); 1287 /* Preparing section: */ 1288 createSection(pEventDetailsBlockPrepareSectionStart->sectionNumber()); 1289 /* Create request to finish current section: */ 1290 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionFinish(pEventDetailsBlockPrepareSectionStart->sectionNumber())); 1291 /* Finish processing: */ 1292 return true; 1293 } 1294 /* Handle details-block-section-prepare-finish event: */ 1295 case UIEventDetailsBlockPrepareSectionFinish::Type: 1296 { 1297 /* Cast and accept event: */ 1298 UIEventDetailsBlockPrepareSectionFinish *pEventDetailsBlockPrepareSectionFinish = static_cast<UIEventDetailsBlockPrepareSectionFinish*>(pEvent); 1299 pEventDetailsBlockPrepareSectionFinish->accept(); 1300 if (pEventDetailsBlockPrepareSectionFinish->sectionNumber() < m_sections.size() - 1) 1301 { 1302 /* Create request for the next section: */ 1303 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(pEventDetailsBlockPrepareSectionFinish->sectionNumber() + 1)); 1304 } 1305 else 1306 { 1307 /* Create reply for the current block: */ 1308 QCoreApplication::postEvent(parent(), new UIEventDetailsPrepareBlockFinish(m_iBlockNumber)); 1309 } 1310 /* Finish processing: */ 1311 return true; 1312 } 1313 default: 1314 break; 1315 } 1316 /* Propagate to base-class: */ 1317 return QWidget::event(pEvent); 1318 } 1319 1320 void UIDetailsBlock::createSection(int iSectionNumber) 1321 { 1322 /* If section creation is NOT yet started: */ 1323 Section section = m_sections[iSectionNumber]; 1324 if (!m_block.contains(section)) 1325 { 1326 /* Prepare new section (popup box): */ 1327 UIPopupBox *pPopup = m_block[section] = new UIPopupBox(this); 1328 m_pPopupBoxGroup->addPopupBox(pPopup); 1329 pPopup->hide(); 1330 connect(pPopup, SIGNAL(sigTitleClicked(const QString &)), details()->detailsPage(), SIGNAL(linkClicked(const QString &))); 1331 connect(pPopup, SIGNAL(sigToggled(bool)), parent(), SLOT(sltPopupToggled(bool))); 1332 pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 1333 pPopup->setProperty("section-type", static_cast<int>(section)); 1334 if (!m_machine.GetAccessible()) 1335 pPopup->setWarningIcon(UIIconPool::iconSet(":/state_aborted_16px.png")); 1336 1337 /* Configure the popup box: */ 1338 switch (section) 1339 { 1340 case Section_General: 1341 { 1342 QILabel *pLabel = new QILabel(pPopup); 1343 pLabel->setWordWrap(true); 1344 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1345 pPopup->setTitleLink("#general"); 1346 pPopup->setContentWidget(pLabel); 1347 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateGeneral())); 1348 break; 1349 } 1350 case Section_System: 1351 { 1352 QILabel *pLabel = new QILabel(pPopup); 1353 pLabel->setWordWrap(true); 1354 pPopup->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png")); 1355 pPopup->setTitleLink("#system"); 1356 pPopup->setContentWidget(pLabel); 1357 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSystem())); 1358 break; 1359 } 1360 case Section_Preview: 1361 { 1362 UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(pPopup); 1363 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1364 pPopup->setContentWidget(pWidget); 1365 pPopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 1366 /* Make sure the width is always the same, regardless if the preview is shown or not: */ 1367 pPopup->setFixedWidth(pPopup->sizeHint().width()); 1368 pWidget->updateGeometry(); 1369 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdatePreview())); 1370 break; 1371 } 1372 case Section_Display: 1373 { 1374 QILabel *pLabel = new QILabel(pPopup); 1375 pLabel->setWordWrap(true); 1376 pPopup->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png")); 1377 pPopup->setTitleLink("#display"); 1378 pPopup->setContentWidget(pLabel); 1379 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDisplay())); 1380 break; 1381 } 1382 case Section_Storage: 1383 { 1384 QILabel *pLabel = new QILabel(pPopup); 1385 pLabel->setWordWrap(true); 1386 pPopup->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png")); 1387 pPopup->setTitleLink("#storage"); 1388 pPopup->setContentWidget(pLabel); 1389 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateStorage())); 1390 break; 1391 } 1392 case Section_Audio: 1393 { 1394 QILabel *pLabel = new QILabel(pPopup); 1395 pLabel->setWordWrap(true); 1396 pPopup->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png")); 1397 pPopup->setTitleLink("#audio"); 1398 pPopup->setContentWidget(pLabel); 1399 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateAudio())); 1400 break; 1401 } 1402 case Section_Network: 1403 { 1404 QILabel *pLabel = new QILabel(pPopup); 1405 pLabel->setWordWrap(true); 1406 pPopup->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png")); 1407 pPopup->setTitleLink("#network"); 1408 pPopup->setContentWidget(pLabel); 1409 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateNetwork())); 1410 break; 1411 } 1412 case Section_Serial: 1413 { 1414 QILabel *pLabel = new QILabel(pPopup); 1415 pLabel->setWordWrap(true); 1416 pPopup->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png")); 1417 pPopup->setTitleLink("#serialPorts"); 1418 pPopup->setContentWidget(pLabel); 1419 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSerialPorts())); 1420 break; 1421 } 1422 #ifdef VBOX_WITH_PARALLEL_PORTS 1423 case Section_Parallel: 1424 { 1425 QILabel *pLabel = new QILabel(pPopup); 1426 pLabel->setWordWrap(true); 1427 pPopup->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png")); 1428 pPopup->setTitleLink("#parallelPorts"); 1429 pPopup->setContentWidget(pLabel); 1430 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateParallelPorts())); 1431 break; 1432 } 1433 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1434 case Section_USB: 1435 { 1436 QILabel *pLabel = new QILabel(pPopup); 1437 pLabel->setWordWrap(true); 1438 pPopup->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png")); 1439 pPopup->setTitleLink("#usb"); 1440 pPopup->setContentWidget(pLabel); 1441 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateUSB())); 1442 break; 1443 } 1444 case Section_SharedFolders: 1445 { 1446 QILabel *pLabel = new QILabel(pPopup); 1447 pLabel->setWordWrap(true); 1448 pPopup->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png")); 1449 pPopup->setTitleLink("#sfolders"); 1450 pPopup->setContentWidget(pLabel); 1451 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSharedFolders())); 1452 break; 1453 } 1454 case Section_Description: 1455 { 1456 QILabel *pLabel = new QILabel(pPopup); 1457 pLabel->setWordWrap(true); 1458 pPopup->setTitleIcon(UIIconPool::iconSet(":/description_16px.png")); 1459 pPopup->setTitleLink("#general%%mTeDescription"); 1460 pPopup->setContentWidget(pLabel); 1461 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDescription())); 1462 break; 1463 } 1464 default: 1465 break; 1466 } 1467 1468 /* Open/close section if necessary: */ 1469 pPopup->setOpen(sectionOpened(section)); 1470 } 1471 1472 /* Call for update: */ 1473 m_block[section]->callForUpdateContentWidget(); 1474 } 1475 1476 /* static */ 1477 QString UIDetailsBlock::summarizeGenericProperties(const CNetworkAdapter &adapter) 1478 { 1479 QVector<QString> names; 1480 QVector<QString> props; 1481 props = adapter.GetProperties(QString(), names); 1482 QString strResult; 1483 for (int i = 0; i < names.size(); ++i) 1484 { 1485 strResult += names[i] + "=" + props[i]; 1486 if (i < names.size() - 1) 1487 strResult += ", "; 1488 } 1489 return strResult; 1490 } 1491 1492 UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction /* = 0 */) 90 UIVMDesktopPrivate::UIVMDesktopPrivate(QWidget *pParent, QAction *pRefreshAction) 1493 91 : QIWithRetranslateUI<QStackedWidget>(pParent) 1494 , m_cMachineCount(0)1495 , m_pScrollArea(0)1496 , m_pDetails(0)1497 92 , m_pText(0) 1498 93 , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0) 1499 94 , m_pRefreshButton(0), m_pRefreshAction(pRefreshAction) 1500 95 { 1501 /* Check that refresh action was passed: */ 1502 Assert(m_pRefreshAction); 1503 } 1504 1505 UIDetailsPagePrivate::~UIDetailsPagePrivate() 1506 { 1507 /* Cleanup details: */ 1508 cleanupDetailsPage(); 1509 } 1510 1511 void UIDetailsPagePrivate::setMachines(const QList<CMachine> &machines) 1512 { 1513 /* Prepare machine details page if necessary: */ 1514 prepareDetailsPage(); 1515 1516 /* Prepare machine details: */ 1517 prepareDetails(machines); 1518 1519 /* Select corresponding widget: */ 1520 setCurrentIndex(indexOf(m_pScrollArea)); 1521 } 1522 1523 void UIDetailsPagePrivate::setText(const QString &aText) 1524 { 1525 /* Prepare text page if necessary: */ 1526 prepareTextPage(); 96 /* Make sure refresh action was passed: */ 97 AssertMsg(m_pRefreshAction, ("Refresh action was NOT passed!")); 98 99 /* Translate finally: */ 100 retranslateUi(); 101 } 102 103 void UIVMDesktopPrivate::setText(const QString &strText) 104 { 105 /* Prepare text pane if necessary: */ 106 prepareTextPane(); 1527 107 1528 108 /* Assign corresponding text: */ 1529 m_pText->setText( aText);1530 1531 /* Selectcorresponding widget: */109 m_pText->setText(strText); 110 111 /* Raise corresponding widget: */ 1532 112 setCurrentIndex(indexOf(m_pText)); 1533 113 } 1534 114 1535 void UI DetailsPagePrivate::setErrorText(const QString &aText)1536 { 1537 /* Prepare error pa ge if necessary: */1538 prepareErrorPa ge();1539 1540 /* Assign corresponding error: */1541 m_pErrText->setText( aText);1542 1543 /* Selectcorresponding widget: */115 void UIVMDesktopPrivate::setError(const QString &strError) 116 { 117 /* Prepare error pane if necessary: */ 118 prepareErrorPane(); 119 120 /* Assign corresponding text: */ 121 m_pErrText->setText(strError); 122 123 /* Raise corresponding widget: */ 1544 124 setCurrentIndex(indexOf(m_pErrBox)); 1545 125 } 1546 126 1547 void UIDetailsPagePrivate::retranslateUi() 1548 { 1549 /* Translate context menu actions: */ 1550 { 1551 if (m_actions.contains(Section_General)) 1552 m_actions[Section_General]->setText(tr("General", "details report")); 1553 if (m_actions.contains(Section_System)) 1554 m_actions[Section_System]->setText(tr("System", "details report")); 1555 if (m_actions.contains(Section_Preview)) 1556 m_actions[Section_Preview]->setText(tr("Preview", "details report")); 1557 if (m_actions.contains(Section_Display)) 1558 m_actions[Section_Display]->setText(tr("Display", "details report")); 1559 if (m_actions.contains(Section_Storage)) 1560 m_actions[Section_Storage]->setText(tr("Storage", "details report")); 1561 if (m_actions.contains(Section_Audio)) 1562 m_actions[Section_Audio]->setText(tr("Audio", "details report")); 1563 if (m_actions.contains(Section_Network)) 1564 m_actions[Section_Network]->setText(tr("Network", "details report")); 1565 if (m_actions.contains(Section_Serial)) 1566 m_actions[Section_Serial]->setText(tr("Serial Ports", "details report")); 1567 #ifdef VBOX_WITH_PARALLEL_PORTS 1568 if (m_actions.contains(Section_Parallel)) 1569 m_actions[Section_Parallel]->setText(tr("Parallel Ports", "details report")); 1570 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1571 if (m_actions.contains(Section_USB)) 1572 m_actions[Section_USB]->setText(tr("USB", "details report")); 1573 if (m_actions.contains(Section_SharedFolders)) 1574 m_actions[Section_SharedFolders]->setText(tr("Shared Folders", "details report")); 1575 if (m_actions.contains(Section_Description)) 1576 m_actions[Section_Description]->setText(tr("Description", "details report")); 1577 } 1578 127 void UIVMDesktopPrivate::retranslateUi() 128 { 1579 129 /* Translate error-label text: */ 1580 130 if (m_pErrLabel) 1581 m_pErrLabel->setText(tr("The selected virtual machine is <i>inaccessible</i>. " 1582 "Please inspect the error message shown below and press the " 1583 "<b>Refresh</b> button if you want to repeat the accessibility check:")); 131 m_pErrLabel->setText(QApplication::translate("UIDetailsPagePrivate", 132 "The selected virtual machine is <i>inaccessible</i>. " 133 "Please inspect the error message shown below and press the " 134 "<b>Refresh</b> button if you want to repeat the accessibility check:")); 1584 135 1585 136 /* Translate refresh button & action text: */ … … 1592 143 } 1593 144 1594 void UIDetailsPagePrivate::prepareDetails(const QList<CMachine> &machines) 1595 { 1596 /* Was machine count changed? */ 1597 bool fCountChanged = m_cMachineCount != machines.size(); 1598 1599 /* Do we need to recreate details? */ 1600 if (fCountChanged) 1601 { 1602 /* Get new machine count: */ 1603 m_cMachineCount = machines.size(); 1604 1605 /* Delete current details if exists:*/ 1606 if (m_pDetails) 1607 delete m_pDetails; 1608 1609 /* Create and configure new details: */ 1610 m_pDetails = new UIDetails(this); 1611 m_pScrollArea->setWidget(m_pDetails); 1612 } 1613 1614 /* Assign new machine array for the details: */ 1615 m_pDetails->setMachines(machines); 1616 } 1617 1618 void UIDetailsPagePrivate::prepareDetailsPage() 1619 { 1620 if (m_pScrollArea) 1621 return; 1622 1623 /* Prepare scroll area: */ 1624 m_pScrollArea = new QScrollArea(this); 1625 m_pScrollArea->setFrameStyle(QFrame::NoFrame); 1626 m_pScrollArea->setWidgetResizable(true); 1627 addWidget(m_pScrollArea); 1628 1629 /* Prepare section names: */ 1630 m_sectionNames[Section_General] = "general"; 1631 m_sectionNames[Section_System] = "system"; 1632 m_sectionNames[Section_Preview] = "preview"; 1633 m_sectionNames[Section_Display] = "display"; 1634 m_sectionNames[Section_Storage] = "storage"; 1635 m_sectionNames[Section_Audio] = "audio"; 1636 m_sectionNames[Section_Network] = "network"; 1637 m_sectionNames[Section_Serial] = "serialPorts"; 1638 #ifdef VBOX_WITH_PARALLEL_PORTS 1639 m_sectionNames[Section_Parallel] = "parallelPorts"; 1640 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1641 m_sectionNames[Section_USB] = "usb"; 1642 m_sectionNames[Section_SharedFolders] = "sharedFolders"; 1643 m_sectionNames[Section_Description] = "description"; 1644 1645 /* Prepare context menu actions: */ 1646 for (int i = 0; i < Section_End; ++i) 1647 { 1648 Section section = static_cast<Section>(i); 1649 m_actions[section] = new QAction(m_pScrollArea); 1650 QAction *pAction = m_actions[section]; 1651 pAction->setData(i); 1652 pAction->setCheckable(true); 1653 } 1654 1655 /* Load section configuration from extra data: */ 1656 QStringList values = vboxGlobal().virtualBox().GetExtraDataStringList(GUI_DetailsPageBoxes, 1657 /* Default keys: */ 1658 QStringList() 1659 << m_sectionNames.value(Section_General) 1660 << m_sectionNames.value(Section_System) 1661 << m_sectionNames.value(Section_Preview) 1662 << m_sectionNames.value(Section_Display) 1663 << m_sectionNames.value(Section_Storage) 1664 << m_sectionNames.value(Section_Audio) 1665 << m_sectionNames.value(Section_Network) 1666 << m_sectionNames.value(Section_USB) 1667 << m_sectionNames.value(Section_SharedFolders) 1668 << m_sectionNames.value(Section_Description)); 1669 /* Parse loaded section configuration: */ 1670 for (int i = 0; i < values.size(); ++i) 1671 { 1672 /* Get current section setting: */ 1673 QString strSectionSetting = values[i]; 1674 1675 /* Is this section opened? */ 1676 bool fSectionOpened = !strSectionSetting.endsWith("Closed"); 1677 1678 /* Get current section: */ 1679 Section section = m_sectionNames.key(fSectionOpened ? strSectionSetting : strSectionSetting.remove("Closed"), Section_End); 1680 1681 /* Assign values: */ 1682 if (section != Section_End) 1683 { 1684 m_sectionSettings[section] = strSectionSetting; 1685 m_actions[section]->setChecked(true); 1686 m_sectionOpened[section] = fSectionOpened; 1687 } 1688 } 1689 1690 /* Translate UI: */ 1691 retranslateUi(); 1692 } 1693 1694 void UIDetailsPagePrivate::cleanupDetailsPage() 1695 { 1696 if (!m_pScrollArea) 1697 return; 1698 1699 /* Update loaded section configuration with current values: */ 1700 for (int i = 0; i < Section_End; ++i) 1701 { 1702 /* Get current section: */ 1703 Section section = static_cast<Section>(i); 1704 1705 /* Process only existing sections: */ 1706 if (!m_pDetails->sections().contains(section)) 1707 continue; 1708 1709 /* Compose section key to save: */ 1710 QString strSectionSetting = !m_actions[section]->isChecked() ? QString() : 1711 m_sectionOpened[section] ? m_sectionNames[section] : 1712 m_sectionNames[section] + "Closed"; 1713 1714 /* Update corresponding setting: */ 1715 m_sectionSettings[section] = strSectionSetting; 1716 } 1717 /* Save section configuration to extra data: */ 1718 vboxGlobal().virtualBox().SetExtraDataStringList(GUI_DetailsPageBoxes, m_sectionSettings.values()); 1719 } 1720 1721 void UIDetailsPagePrivate::prepareTextPage() 145 void UIVMDesktopPrivate::prepareTextPane() 1722 146 { 1723 147 if (m_pText) 1724 148 return; 1725 149 1726 /* Create normal text page: */150 /* Create text pane: */ 1727 151 m_pText = new QRichTextBrowser(this); 1728 152 m_pText->setFocusPolicy(Qt::StrongFocus); 1729 153 m_pText->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 1730 /* Make "transparent": */154 /* Make text pane transparent: */ 1731 155 m_pText->setFrameShape(QFrame::NoFrame); 1732 156 m_pText->viewport()->setAutoFillBackground(false); 1733 157 m_pText->setOpenLinks(false); 1734 158 1735 connect(m_pText, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(sltLinkClicked(const QUrl &))); 1736 159 /* Add into the stack: */ 1737 160 addWidget(m_pText); 1738 161 162 /* Retranslate finally: */ 1739 163 retranslateUi(); 1740 164 } 1741 165 1742 void UI DetailsPagePrivate::prepareErrorPage()166 void UIVMDesktopPrivate::prepareErrorPane() 1743 167 { 1744 168 if (m_pErrBox) 1745 169 return; 1746 170 1747 /* Create inaccessible details page */ 1748 m_pErrBox = new QWidget(); 1749 1750 QVBoxLayout *vLayout = new QVBoxLayout(m_pErrBox); 1751 vLayout->setSpacing(10); 1752 vLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 1753 171 /* Create error pane: */ 172 m_pErrBox = new QWidget; 173 174 /* Create main layout: */ 175 QVBoxLayout *pMainLayout = new QVBoxLayout(m_pErrBox); 176 pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 177 pMainLayout->setSpacing(10); 178 179 /* Create error label: */ 1754 180 m_pErrLabel = new QLabel(m_pErrBox); 1755 181 m_pErrLabel->setWordWrap(true); 1756 182 m_pErrLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 1757 vLayout->addWidget(m_pErrLabel); 1758 183 pMainLayout->addWidget(m_pErrLabel); 184 185 /* Create error text browser: */ 1759 186 m_pErrText = new QTextBrowser(m_pErrBox); 1760 187 m_pErrText->setFocusPolicy(Qt::StrongFocus); 1761 188 m_pErrText->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 1762 vLayout->addWidget(m_pErrText); 1763 189 pMainLayout->addWidget(m_pErrText); 190 191 /* If refresh action was set: */ 1764 192 if (m_pRefreshAction) 1765 193 { 194 /* Create refresh button: */ 1766 195 m_pRefreshButton = new QToolButton(m_pErrBox); 1767 196 m_pRefreshButton->setFocusPolicy(Qt::StrongFocus); 1768 197 1769 QHBoxLayout *hLayout = new QHBoxLayout(); 1770 vLayout->addLayout(hLayout); 1771 hLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); 1772 hLayout->addWidget(m_pRefreshButton); 1773 1774 connect(m_pRefreshButton, SIGNAL(clicked()), 1775 m_pRefreshAction, SIGNAL(triggered())); 1776 } 1777 1778 vLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 1779 198 /* Create refresh button layout: */ 199 QHBoxLayout *pButtonLayout = new QHBoxLayout; 200 pMainLayout->addLayout(pButtonLayout); 201 pButtonLayout->addStretch(); 202 pButtonLayout->addWidget(m_pRefreshButton); 203 204 /* Connect refresh button: */ 205 connect(m_pRefreshButton, SIGNAL(clicked()), m_pRefreshAction, SIGNAL(triggered())); 206 } 207 208 pMainLayout->addStretch(); 209 210 /* Add into the stack: */ 1780 211 addWidget(m_pErrBox); 1781 212 213 /* Retranslate finally: */ 1782 214 retranslateUi(); 1783 215 } 1784 216 1785 /** 1786 * UIDescriptionPagePrivate 1787 */ 1788 class UIDescriptionPagePrivate : public QIWithRetranslateUI<QWidget> 1789 { 1790 Q_OBJECT; 1791 1792 public: 1793 1794 UIDescriptionPagePrivate(QWidget *pParent = 0); 1795 ~UIDescriptionPagePrivate() {} 1796 1797 void setMachineItem(UIVMItem *pVMItem); 1798 1799 void updateState(); 1800 1801 signals: 1802 1803 void linkClicked(const QString &aURL); 1804 1805 protected: 1806 1807 void retranslateUi(); 1808 1809 private slots: 1810 1811 void goToSettings(); 1812 1813 private: 1814 1815 UIVMItem *m_pVMItem; 1816 1817 QToolButton *m_pEditBtn; 1818 QTextBrowser *m_pBrowser; 1819 QLabel *m_pLabel; 217 enum 218 { 219 Dtls = 0, 220 Snap 1820 221 }; 1821 222 1822 UI DescriptionPagePrivate::UIDescriptionPagePrivate(QWidget *pParent /* = 0 */)223 UIVMDesktop::UIVMDesktop(UIToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent) 1823 224 : QIWithRetranslateUI<QWidget>(pParent) 1824 , m_pVMItem(0) 1825 , m_pEditBtn(0) 1826 , m_pBrowser(0) 1827 , m_pLabel(0) 1828 { 1829 /* Main layout */ 1830 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 1831 pMainLayout->setSpacing(10); 1832 VBoxGlobal::setLayoutMargin(pMainLayout, 0); 1833 1834 /* m_pBrowser */ 1835 m_pBrowser = new QTextBrowser(this); 1836 m_pBrowser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 1837 m_pBrowser->setFocusPolicy(Qt::StrongFocus); 1838 m_pBrowser->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 1839 pMainLayout->addWidget(m_pBrowser); 1840 /* hidden by default */ 1841 m_pBrowser->setHidden(true); 1842 1843 m_pLabel = new QLabel(this); 1844 m_pLabel->setFrameStyle(m_pBrowser->frameStyle()); 1845 m_pLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 1846 m_pLabel->setAlignment(Qt::AlignCenter); 1847 m_pLabel->setWordWrap(true); 1848 pMainLayout->addWidget(m_pLabel); 1849 /* always disabled */ 1850 m_pLabel->setEnabled(false); 1851 1852 /* button layout */ 1853 QHBoxLayout *hBtnLayout = new QHBoxLayout(); 1854 pMainLayout->addLayout(hBtnLayout); 1855 hBtnLayout->setSpacing(10); 1856 hBtnLayout->addItem(new QSpacerItem(0, 0, 1857 QSizePolicy::Expanding, 1858 QSizePolicy::Minimum)); 1859 1860 /* button */ 1861 m_pEditBtn = new QToolButton(this); 1862 m_pEditBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 1863 m_pEditBtn->setFocusPolicy(Qt::StrongFocus); 1864 m_pEditBtn->setIcon(UIIconPool::iconSet(":/edit_description_16px.png", 1865 ":/edit_description_disabled_16px.png")); 1866 m_pEditBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1867 connect(m_pEditBtn, SIGNAL(clicked()), this, SLOT(goToSettings())); 1868 hBtnLayout->addWidget(m_pEditBtn); 1869 1870 pMainLayout->addItem(new QSpacerItem(0, 0, 1871 QSizePolicy::Expanding, 1872 QSizePolicy::Minimum)); 1873 1874 /* apply language settings */ 1875 retranslateUi(); 1876 1877 updateState(); 1878 } 1879 1880 /** 1881 * The machine list @a pVMItem is used to access cached machine data w/o making 1882 * unnecessary RPC calls. 1883 */ 1884 void UIDescriptionPagePrivate::setMachineItem(UIVMItem *pVMItem) 1885 { 1886 m_pVMItem = pVMItem; 1887 1888 QString text = pVMItem ? pVMItem->machine().GetDescription() : QString::null; 1889 1890 if (!text.isEmpty()) 1891 { 1892 m_pLabel->setHidden(true); 1893 m_pBrowser->setText(text); 1894 m_pBrowser->setVisible(true); 1895 } 1896 else 1897 { 1898 m_pBrowser->setHidden(true); 1899 m_pBrowser->clear(); 1900 m_pLabel->setVisible(true); 1901 } 1902 1903 /* check initial machine and session states */ 1904 updateState(); 1905 } 1906 1907 void UIDescriptionPagePrivate::retranslateUi() 1908 { 1909 m_pLabel->setText(tr("No description. Press the Edit button below to add it.")); 1910 1911 m_pEditBtn->setText(tr("Edit")); 1912 m_pEditBtn->setShortcut(QKeySequence("Ctrl+E")); 1913 m_pEditBtn->setToolTip(tr("Edit (Ctrl+E)")); 1914 m_pEditBtn->adjustSize(); 1915 m_pEditBtn->updateGeometry(); 1916 } 1917 1918 /** 1919 * Called by the parent from machineStateChanged() and sessionStateChanged() 1920 * signal handlers. We cannot connect to these signals ourselves because we 1921 * use the UIVMListBoxItem which needs to be properly updated by the parent 1922 * first. 1923 */ 1924 void UIDescriptionPagePrivate::updateState() 1925 { 1926 /// @todo disabling the edit button for a saved VM will not be necessary 1927 /// when we implement the selective VM Settings dialog, where only fields 1928 /// that can be changed in the saved state, can be changed. 1929 1930 if (m_pVMItem) 1931 { 1932 bool saved = m_pVMItem->machineState() == KMachineState_Saved; 1933 bool busy = m_pVMItem->sessionState() != KSessionState_Unlocked; 1934 m_pEditBtn->setEnabled(!saved && !busy); 1935 } 1936 else 1937 m_pEditBtn->setEnabled(false); 1938 } 1939 1940 void UIDescriptionPagePrivate::goToSettings() 1941 { 1942 emit linkClicked("#general%%mTeDescription"); 1943 } 1944 1945 /** 1946 * UIVMDesktop 1947 */ 1948 enum 1949 { 1950 Dtls = 0, 1951 Snap, 1952 // Desc 1953 }; 1954 1955 UIVMDesktop::UIVMDesktop(UIToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent /* = 0 */) 1956 : QIWithRetranslateUI<QWidget>(pParent) 1957 { 225 { 226 /* Prepare buttons: */ 1958 227 m_pHeaderBtn = new UITexturedSegmentedButton(2); 1959 228 m_pHeaderBtn->setIcon(Dtls, UIIconPool::iconSet(":/settings_16px.png")); 1960 229 m_pHeaderBtn->setIcon(Snap, UIIconPool::iconSet(":/take_snapshot_16px.png", 1961 230 ":/take_snapshot_dis_16px.png")); 1962 // m_pHeaderBtn->setIcon(Desc, UIIconPool::iconSet(":/description_16px.png",1963 // ":/description_disabled_16px.png"));1964 231 m_pHeaderBtn->animateClick(0); 1965 232 233 /* Prepare main layout: */ 1966 234 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 1967 235 pMainLayout->setContentsMargins(0, 0, 0, 0); 1968 236 1969 /* The header to select the different pages. Has different styles on the1970 * different platforms. */1971 #ifdef DARWIN_USE_TOOLBAR237 /* The header to select the different pages. 238 * Has different styles on the different platforms. */ 239 #ifdef USE_TOOLBAR 1972 240 if (pToolBar) 1973 241 { … … 1982 250 pToolBar->addWidget(pSpace); 1983 251 pToolBar->updateLayout(); 1984 } else 1985 #else /* DARWIN_USE_TOOLBAR */ 252 } 253 else 254 #else /* USE_TOOLBAR */ 1986 255 NOREF(pToolBar); 1987 #endif /* ! DARWIN_USE_TOOLBAR */256 #endif /* !USE_TOOLBAR */ 1988 257 { 1989 258 UIBar *pBar = new UIBar(this); 1990 #ifndef Q_WS_MAC1991 // pBar->setFixedHeight(65);1992 #endif /* !Q_WS_MAC */1993 259 pBar->setContentWidget(m_pHeaderBtn); 1994 260 pMainLayout->addWidget(pBar); 1995 261 } 1996 262 1997 /* Add the pages */ 263 /* Create desktop pane: */ 264 m_pDesktopPrivate = new UIVMDesktopPrivate(this, pRefreshAction); 265 266 /* Create snapshot pane: */ 267 m_pSnapshotsPane = new VBoxSnapshotsWgt(this); 268 m_pSnapshotsPane->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 269 270 /* Add the pages: */ 1998 271 m_pStackedLayout = new QStackedLayout(pMainLayout); 1999 2000 m_pDetails = new UIDetailsPagePrivate(this, pRefreshAction); 2001 connect(m_pDetails, SIGNAL(linkClicked(const QString&)), 2002 this, SIGNAL(linkClicked(const QString&))); 2003 m_pStackedLayout->addWidget(m_pDetails); 2004 m_pSnapshotsPage = new VBoxSnapshotsWgt(this); 2005 m_pSnapshotsPage->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 2006 m_pStackedLayout->addWidget(m_pSnapshotsPage); 2007 // m_pDescription = new UIDescriptionPagePrivate(this); 2008 // connect(m_pDescription, SIGNAL(linkClicked(const QString&)), 2009 // this, SIGNAL(linkClicked(const QString&))); 2010 // m_pDescription->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 2011 // m_pStackedLayout->addWidget(m_pDescription); 2012 2013 /* Connect the header buttons with the stack layout. */ 2014 connect(m_pHeaderBtn, SIGNAL(clicked(int)), 2015 m_pStackedLayout, SLOT(setCurrentIndex(int))); 2016 connect(m_pStackedLayout, SIGNAL(currentChanged(int)), 2017 this, SIGNAL(sigCurrentChanged(int))); 2018 272 m_pStackedLayout->addWidget(m_pDesktopPrivate); 273 m_pStackedLayout->addWidget(m_pSnapshotsPane); 274 275 /* Connect the header buttons with the stack layout: */ 276 connect(m_pHeaderBtn, SIGNAL(clicked(int)), m_pStackedLayout, SLOT(setCurrentIndex(int))); 277 connect(m_pStackedLayout, SIGNAL(currentChanged(int)), this, SIGNAL(sigCurrentChanged(int))); 278 279 /* Translate finally: */ 2019 280 retranslateUi(); 2020 281 } 2021 282 2022 void UIVMDesktop::retranslateUi() 2023 { 2024 m_pHeaderBtn->setTitle(Dtls, tr("&Details")); 2025 } 2026 2027 void UIVMDesktop::updateDetails(UIVMItem * /* pVMItem */, const QList<CMachine> &machines) 2028 { 2029 // KMachineState state = pVMItem->state(); 2030 // bool fRunning = pVMItem->sessionState() != KSessionState_Closed; 2031 // bool fModifyEnabled = !fRunning && state != KMachineState_Saved; 2032 m_pDetails->setMachines(machines); 283 int UIVMDesktop::widgetIndex() const 284 { 285 return m_pStackedLayout->currentIndex(); 2033 286 } 2034 287 2035 288 void UIVMDesktop::updateDetailsText(const QString &strText) 2036 289 { 2037 m_pDe tails->setText(strText);2038 } 2039 2040 void UIVMDesktop::updateDetailsError Text(const QString &strText)2041 { 2042 m_pDe tails->setErrorText(strText);290 m_pDesktopPrivate->setText(strText); 291 } 292 293 void UIVMDesktop::updateDetailsError(const QString &strError) 294 { 295 m_pDesktopPrivate->setError(strError); 2043 296 } 2044 297 2045 298 void UIVMDesktop::updateSnapshots(UIVMItem *pVMItem, const CMachine& machine) 2046 299 { 2047 /* Update the snapshots header name */300 /* Update the snapshots header name: */ 2048 301 QString name = tr("&Snapshots"); 2049 302 if (pVMItem) … … 2054 307 } 2055 308 m_pHeaderBtn->setTitle(Snap, name); 2056 /* Refresh the snapshots widget */ 309 310 /* Refresh the snapshots widget: */ 2057 311 if (!machine.isNull()) 2058 312 { 2059 313 m_pHeaderBtn->setEnabled(Snap, true); 2060 m_pSnapshotsPa ge->setMachine(machine);314 m_pSnapshotsPane->setMachine(machine); 2061 315 } 2062 316 else … … 2070 324 } 2071 325 2072 int UIVMDesktop::widgetIndex() const 2073 { 2074 return m_pStackedLayout->currentIndex(); 2075 } 2076 2077 //void UIVMDesktop::updateDescription(UIVMItem *pVMItem, const CMachine& machine) 2078 //{ 2079 // /* Update the description header name */ 2080 // QString name = tr("D&escription"); 2081 // if (pVMItem) 2082 // { 2083 // if(!machine.GetDescription().isEmpty()) 2084 // name += " *"; 2085 // } 2086 // m_pHeaderBtn->setTitle(Desc, name); 2087 // /* refresh the description widget */ 2088 // if (!machine.isNull()) 2089 // { 2090 // m_pHeaderBtn->setEnabled(Desc, true); 2091 // m_pDescription->setMachineItem(pVMItem); 2092 // } else 2093 // { 2094 // m_pHeaderBtn->animateClick(Dtls); 2095 // m_pHeaderBtn->setEnabled(Desc, false); 2096 // } 2097 //} 2098 // 2099 //void UIVMDesktop::updateDescriptionState() 2100 //{ 2101 // m_pDescription->updateState(); 2102 //} 326 void UIVMDesktop::retranslateUi() 327 { 328 m_pHeaderBtn->setTitle(Dtls, tr("&Details")); 329 } 2103 330 2104 331 #include "UIVMDesktop.moc" -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.h
r42854 r44318 6 6 7 7 /* 8 * Copyright (C) 2010 Oracle Corporation8 * Copyright (C) 2010-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 20 #define __UIVMDesktop_h__ 21 21 22 /* Local includes */ 22 /* Qt includes: */ 23 #include <QWidget> 24 25 /* GUI includes: */ 23 26 #include "QIWithRetranslateUI.h" 24 27 25 /* Global includes */ 26 #include <QWidget> 27 28 /* Local forward declarations */ 28 /* Forward declarations: */ 29 29 class CMachine; 30 class UIDescriptionPagePrivate; 31 class UIDetailsPagePrivate; 30 class UIVMDesktopPrivate; 32 31 class UITexturedSegmentedButton; 33 32 class UIVMItem; … … 36 35 class QStackedLayout; 37 36 37 /* Class representing widget which contains three panes: 38 * 1. Information pane reflecting base information about VirtualBox, 39 * 2. Inaccessible machine pane reflecting information about 40 * currently chosen inaccessible VM and allowing to operate over it, 41 * 3. Snapshot pane allowing to operate over the snapshots. */ 38 42 class UIVMDesktop: public QIWithRetranslateUI<QWidget> 39 43 { … … 42 46 signals: 43 47 44 void linkClicked(const QString &strURL);48 /* Notifier: Current widget stuff: */ 45 49 void sigCurrentChanged(int iWidgetIndex); 46 50 47 51 public: 48 52 49 UIVMDesktop(UIToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent = 0); 53 /* Constructor: */ 54 UIVMDesktop(UIToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent); 50 55 51 void updateDetails(UIVMItem *pVMItem, const QList<CMachine> &machines); 56 /* API: Current pane index: */ 57 int widgetIndex() const; 58 59 /* Helpers: Update stuff: */ 52 60 void updateDetailsText(const QString &strText); 53 void updateDetailsErrorText(const QString &strText); 54 61 void updateDetailsError(const QString &strError); 55 62 void updateSnapshots(UIVMItem *pVMItem, const CMachine& machine); 56 63 void lockSnapshots(); 57 // void updateDescription(UIVMItem *pVMItem, const CMachine& machine);58 // void updateDescriptionState();59 60 int widgetIndex() const;61 62 protected:63 64 void retranslateUi();65 64 66 65 private: 67 66 68 /* Private member vars */ 67 /* Helper: Translate stuff: */ 68 void retranslateUi(); 69 70 /* Variables: */ 69 71 QStackedLayout *m_pStackedLayout; 70 72 UITexturedSegmentedButton *m_pHeaderBtn; 71 UIDetailsPagePrivate *m_pDetails; 72 VBoxSnapshotsWgt *m_pSnapshotsPage; 73 // UIDescriptionPagePrivate *m_pDescription; 73 UIVMDesktopPrivate *m_pDesktopPrivate; 74 VBoxSnapshotsWgt *m_pSnapshotsPane; 74 75 }; 75 76
Note:
See TracChangeset
for help on using the changeset viewer.