Changeset 39546 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Dec 7, 2011 12:19:44 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.cpp
r39399 r39546 45 45 #include "VBoxUtils.h" 46 46 47 /* 48 * Todo: 49 * - dynamically change size of preview window! 50 */ 47 /* Forward declarations: */ 48 class UIDetails; 49 class UIDetailsBlock; 50 class UIDetailsPagePrivate; 51 51 52 52 //#ifdef Q_WS_MAC … … 72 72 #endif /* !Q_WS_MAC */ 73 73 74 class UIEvent ForBlockUpdate: public QEvent74 class UIEventDetailsPrepareStart : public QEvent 75 75 { 76 76 public: 77 77 78 78 enum { Type = QEvent::User + 1 }; 79 80 UIEventForBlockUpdate(const QUuid &requestId, int iBlockNumber, bool fNewBlock) 81 : QEvent((QEvent::Type)Type), m_requestId(requestId), m_iBlockNumber(iBlockNumber), m_fNewBlock(fNewBlock) 82 { 83 } 84 85 QUuid requestId() const { return m_requestId; } 79 UIEventDetailsPrepareStart() : QEvent((QEvent::Type)Type) {} 80 }; 81 82 class UIEventDetailsPrepareBlockStart : public QEvent 83 { 84 public: 85 86 enum { Type = QEvent::User + 2 }; 87 UIEventDetailsPrepareBlockStart(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {} 86 88 int blockNumber() const { return m_iBlockNumber; } 87 bool newBlock() const { return m_fNewBlock; }88 89 89 90 private: 90 91 91 QUuid m_requestId;92 92 int m_iBlockNumber; 93 bool m_fNewBlock; 93 }; 94 95 class UIEventDetailsPrepareBlockFinish : public QEvent 96 { 97 public: 98 99 enum { Type = QEvent::User + 3 }; 100 UIEventDetailsPrepareBlockFinish(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {} 101 int blockNumber() const { return m_iBlockNumber; } 102 103 private: 104 105 int m_iBlockNumber; 106 }; 107 108 class UIEventDetailsBlockPrepareStart : public QEvent 109 { 110 public: 111 112 enum { Type = QEvent::User + 1 }; 113 UIEventDetailsBlockPrepareStart() : QEvent((QEvent::Type)Type) {} 114 }; 115 116 class UIEventDetailsBlockPrepareSectionStart : public QEvent 117 { 118 public: 119 120 enum { Type = QEvent::User + 2 }; 121 UIEventDetailsBlockPrepareSectionStart(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {} 122 int sectionNumber() const { return m_iSectionNumber; } 123 124 private: 125 126 int m_iSectionNumber; 127 }; 128 129 class UIEventDetailsBlockPrepareSectionFinish : public QEvent 130 { 131 public: 132 133 enum { Type = QEvent::User + 3 }; 134 UIEventDetailsBlockPrepareSectionFinish(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {} 135 int sectionNumber() const { return m_iSectionNumber; } 136 137 private: 138 139 int m_iSectionNumber; 94 140 }; 95 141 … … 115 161 116 162 /** 163 * UIDetails class. 164 * QWidget container to store UIDetailsBlock(s). 165 */ 166 class UIDetails : public QWidget 167 { 168 Q_OBJECT; 169 170 public: 171 172 /* Constructor: */ 173 UIDetails(UIDetailsPagePrivate *pDetailsPage); 174 175 /* Operator: */ 176 UIDetailsBlock*& operator[](int i) { return m_details[i]; } 177 178 /* Machine list setter: */ 179 void setMachines(const QList<CMachine> &machines); 180 181 /* Own wrappers: */ 182 UIDetailsPagePrivate* detailsPage() const { return m_pUIDetailsPage; } 183 const QList<Section>& sections() const { return m_sections; } 184 bool accessibility(int iBlockNumber) const { return m_accessibilities[iBlockNumber]; } 185 void setUSBAvailable(bool fAvailable) { m_fUSBAvailable = fAvailable; } 186 187 /* Parent wrappers: */ 188 bool sectionOpened(Section section) const; 189 void setSectionOpened(Section section, bool fOpened); 190 QAction* action(Section section) const; 191 192 private slots: 193 194 /* Details pane context menu handler: */ 195 void sltContextMenuRequested(const QPoint &pos); 196 197 /* Details pane popup widget toggle handler: */ 198 void sltPopupToggled(bool fPopupOpened); 199 200 private: 201 202 /* Main event handler: */ 203 bool event(QEvent *pEvent); 204 205 /* Block preparation delegate(s): */ 206 void createBlock(int iBlockNumber); 207 void layoutBlock(int iBlockNumber); 208 209 /* Variables: */ 210 UIDetailsPagePrivate *m_pUIDetailsPage; 211 int m_cBlockCount; 212 QVector<CMachine> m_machines; 213 QVector<bool> m_accessibilities; 214 QList<Section> m_sections; 215 QMap<int, UIDetailsBlock*> m_details; 216 bool m_fUSBAvailable; 217 }; 218 219 /** 117 220 * UIDetailsBlock class. 118 * QWidget container to store UIPopupBox sections.221 * QWidget container to store UIPopupBox(s). 119 222 */ 120 223 class UIDetailsBlock : public QWidget … … 124 227 public: 125 228 126 UIDetailsBlock(QWidget *pParent) 127 : QWidget(pParent) 128 { 129 } 130 131 UIPopupBox*& operator[](Section section) 132 { 133 return m_sections[section]; 134 } 135 136 private: 137 138 QMap<Section, UIPopupBox*> m_sections; 139 }; 140 typedef QVector<UIDetailsBlock*> UIDetailsSet; 141 142 /** 143 * UIDescriptionPagePrivate 144 */ 145 class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget> 146 { 147 Q_OBJECT; 148 149 public: 150 151 UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction = 0); 152 ~UIDetailsPagePrivate(); 153 154 void setMachines(const QList<CMachine> &machines); 155 void setText(const QString &aText); 156 void setErrorText(const QString &aText); 157 158 signals: 159 160 void linkClicked(const QString &url); 161 162 protected: 163 164 void retranslateUi(); 165 bool event(QEvent *pEvent); 229 /* Constructor: */ 230 UIDetailsBlock(UIDetails *pParent, const QList<Section> §ions, int iBlockNumber); 231 232 /* Operator: */ 233 UIPopupBox*& operator[](Section section) { return m_block[section]; } 234 235 /* Machine setter: */ 236 void setMachine(const CMachine &machine); 237 238 /* Own wrappers: */ 239 UIDetails* details() const { return m_pUIDetails; } 240 241 /* Parent wrappers: */ 242 bool accessibility() const; 243 bool sectionOpened(Section section) const; 244 void setUSBAvailable(bool fAvailable); 166 245 167 246 private slots: 168 247 248 /* Popup preparation handlers: */ 169 249 void sltUpdateGeneral(); 250 void sltUpdateSystem(); 170 251 void sltUpdatePreview(); 171 void sltUpdateSystem();172 252 void sltUpdateDisplay(); 173 253 void sltUpdateStorage(); … … 182 262 void sltUpdateDescription(); 183 263 184 void sltContextMenuRequested(const QPoint &pos); 264 private: 265 266 /* Main event handler: */ 267 bool event(QEvent *pEvent); 268 269 /* Section preparation delegate: */ 270 void createSection(int iSectionNumber); 271 272 /* Static stuff: */ 273 static QString summarizeGenericProperties(const CNetworkAdapter &adapter); 274 275 /* Variables: */ 276 CVirtualBox m_vbox; 277 UIDetails *m_pUIDetails; 278 int m_iBlockNumber; 279 int m_cSectionCount; 280 CMachine m_machine; 281 QList<Section> m_sections; 282 QMap<Section, UIPopupBox*> m_block; 283 }; 284 285 /** 286 * UIDetailsPagePrivate class. 287 * QWidget container to store UIDetails. 288 */ 289 class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget> 290 { 291 Q_OBJECT; 292 293 public: 294 295 /* Constructor/destructor: */ 296 UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction = 0); 297 ~UIDetailsPagePrivate(); 298 299 /* Setters: */ 300 void setMachines(const QList<CMachine> &machines); 301 void setText(const QString &aText); 302 void setErrorText(const QString &aText); 303 304 /* Own wrappers: */ 305 bool sectionOpened(Section section) const { return m_sectionOpened[section]; } 306 void setSectionOpened(Section section, bool fOpened) { m_sectionOpened[section] = fOpened; } 307 QAction* action(Section section) { return m_actions[section]; } 308 309 signals: 310 311 void linkClicked(const QString &url); 312 313 protected: 314 315 void retranslateUi(); 316 317 private slots: 185 318 186 319 void sltLinkClicked(const QUrl &url) { emit linkClicked(url.toString()); } 187 320 188 void sltPopupToggled(bool fPopupOpened);189 190 321 private: 191 322 192 void prepareDetails ();193 void cleanupDetails ();323 void prepareDetailsPage(); 324 void cleanupDetailsPage(); 194 325 195 326 void prepareTextPage(); … … 197 328 void prepareErrorPage(); 198 329 199 void prepareSet(bool fNewSet); 200 void prepareBlock(int iBlockNumber, bool fNewBlock); 201 void prepareSection(UIDetailsBlock &block, int iBlockNumber, Section section); 330 void prepareDetails(const QList<CMachine> &machines); 202 331 203 332 void saveSectionSetting(); 204 333 205 static QString summarizeGenericProperties(const CNetworkAdapter &adapter); 206 207 /* Common variables: */ 208 CVirtualBox m_vbox; 334 /* Details-view variables: */ 209 335 int m_cMachineCount; 210 QVector<CMachine> m_machines;211 QVector<bool> m_changeable;212 213 /* Details-view variables: */214 336 QScrollArea *m_pScrollArea; 215 QWidget*m_pDetails;337 UIDetails *m_pDetails; 216 338 QMap<Section, QString> m_sectionSettings; 217 339 QMap<Section, QString> m_sectionNames; 218 340 QMap<Section, bool> m_sectionOpened; 219 341 QMap<Section, QAction*> m_actions; 220 QList<Section> m_sections;221 UIDetailsSet m_set;222 bool m_fUSBAvailable;223 QUuid m_currentRequestId;224 342 225 343 /* Free text: */ … … 234 352 }; 235 353 236 UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction /* = 0 */) 237 : QIWithRetranslateUI<QStackedWidget>(pParent) 238 , m_vbox(vboxGlobal().virtualBox()) 239 , m_cMachineCount(0) 240 , m_pScrollArea(0) 241 , m_pDetails(0) 354 UIDetails::UIDetails(UIDetailsPagePrivate *pDetailsPage) 355 : QWidget(pDetailsPage) 356 , m_pUIDetailsPage(pDetailsPage) 357 , m_cBlockCount(0) 242 358 , m_fUSBAvailable(true) 243 , m_pText(0) 244 , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0) 245 , m_pRefreshButton(0), m_pRefreshAction(pRefreshAction) 246 { 247 /* Check that refresh action was passed: */ 248 Assert(m_pRefreshAction); 249 } 250 251 UIDetailsPagePrivate::~UIDetailsPagePrivate() 252 { 253 /* Cleanup details: */ 254 cleanupDetails(); 255 } 256 257 void UIDetailsPagePrivate::setMachines(const QList<CMachine> &machines) 258 { 259 /* Prepare variables: */ 260 bool fCountChanged = machines.size() != m_cMachineCount; 261 m_cMachineCount = machines.size(); 262 /* Recreate corresponding vectors: */ 263 m_machines.clear(); 264 m_machines.resize(m_cMachineCount); 265 m_changeable.clear(); 266 m_changeable.resize(m_cMachineCount); 267 /* Fetch passed VMs: */ 268 for (int i = 0; i < machines.size(); ++i) 269 { 270 /* Get current VM: */ 271 const CMachine &machine = machines[i]; 272 /* Assign corresponding vector values: */ 273 m_machines[i] = machine; 274 m_changeable[i] = machine.isNull() || !machine.GetAccessible() ? false : 275 machine.GetState() != KMachineState_Stuck && 276 machine.GetState() != KMachineState_Saved /* for now! */; 277 } 278 279 /* Prepare machine details page if necessary: */ 280 prepareDetails(); 281 282 /* Prepare set of blocks: */ 283 prepareSet(fCountChanged /* new set? */); 284 285 /* Select corresponding widget: */ 286 setCurrentIndex(indexOf(m_pScrollArea)); 287 } 288 289 void UIDetailsPagePrivate::setText(const QString &aText) 290 { 291 /* Clear machine maps: */ 292 m_machines.clear(); 293 m_machines.resize(0); 294 m_changeable.clear(); 295 m_changeable.resize(0); 296 297 /* Prepare text page if necessary: */ 298 prepareTextPage(); 299 300 /* Assign corresponding text: */ 301 m_pText->setText(aText); 302 303 /* Select corresponding widget: */ 304 setCurrentIndex(indexOf(m_pText)); 305 } 306 307 void UIDetailsPagePrivate::setErrorText(const QString &aText) 308 { 309 /* Clear machine maps: */ 310 m_machines.clear(); 311 m_machines.resize(0); 312 m_changeable.clear(); 313 m_changeable.resize(0); 314 315 /* Prepare error page if necessary: */ 316 prepareErrorPage(); 317 318 /* Assign corresponding error: */ 319 m_pErrText->setText(aText); 320 321 /* Select corresponding widget: */ 322 setCurrentIndex(indexOf(m_pErrBox)); 323 } 324 325 void UIDetailsPagePrivate::retranslateUi() 326 { 327 /* Translate context menu actions: */ 328 { 329 if (m_actions.contains(Section_General)) 330 m_actions[Section_General]->setText(tr("General", "details report")); 331 if (m_actions.contains(Section_System)) 332 m_actions[Section_System]->setText(tr("System", "details report")); 333 if (m_actions.contains(Section_Preview)) 334 m_actions[Section_Preview]->setText(tr("Preview", "details report")); 335 if (m_actions.contains(Section_Display)) 336 m_actions[Section_Display]->setText(tr("Display", "details report")); 337 if (m_actions.contains(Section_Storage)) 338 m_actions[Section_Storage]->setText(tr("Storage", "details report")); 339 if (m_actions.contains(Section_Audio)) 340 m_actions[Section_Audio]->setText(tr("Audio", "details report")); 341 if (m_actions.contains(Section_Network)) 342 m_actions[Section_Network]->setText(tr("Network", "details report")); 343 if (m_actions.contains(Section_Serial)) 344 m_actions[Section_Serial]->setText(tr("Serial Ports", "details report")); 345 #ifdef VBOX_WITH_PARALLEL_PORTS 346 if (m_actions.contains(Section_Parallel)) 347 m_actions[Section_Parallel]->setText(tr("Parallel Ports", "details report")); 348 #endif /* VBOX_WITH_PARALLEL_PORTS */ 349 if (m_actions.contains(Section_USB)) 350 m_actions[Section_USB]->setText(tr("USB", "details report")); 351 if (m_actions.contains(Section_SharedFolders)) 352 m_actions[Section_SharedFolders]->setText(tr("Shared Folders", "details report")); 353 if (m_actions.contains(Section_Description)) 354 m_actions[Section_Description]->setText(tr("Description", "details report")); 355 } 356 357 /* Translate error-label text: */ 358 if (m_pErrLabel) 359 m_pErrLabel->setText(tr("The selected virtual machine is <i>inaccessible</i>. " 360 "Please inspect the error message shown below and press the " 361 "<b>Refresh</b> button if you want to repeat the accessibility check:")); 362 363 /* Translate refresh button & action text: */ 364 if (m_pRefreshAction && m_pRefreshButton) 365 { 366 m_pRefreshButton->setText(m_pRefreshAction->text()); 367 m_pRefreshButton->setIcon(m_pRefreshAction->icon()); 368 m_pRefreshButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 369 } 370 } 371 372 bool UIDetailsPagePrivate::event(QEvent *pEvent) 373 { 374 /* Handle special cases: */ 375 switch (pEvent->type()) 376 { 377 case UIEventForBlockUpdate::Type: 378 { 379 /* Cast and accept event: */ 380 UIEventForBlockUpdate *pEventForBlockUpdate = static_cast<UIEventForBlockUpdate*>(pEvent); 381 pEventForBlockUpdate->accept(); 382 /* Check that request is NOT outdated: */ 383 if (pEventForBlockUpdate->requestId() == m_currentRequestId) 384 { 385 /* Process current request: */ 386 prepareBlock(pEventForBlockUpdate->blockNumber(), pEventForBlockUpdate->newBlock()); 387 /* Create next request: */ 388 if (pEventForBlockUpdate->blockNumber() < m_cMachineCount - 1) 389 QCoreApplication::postEvent(this, new UIEventForBlockUpdate(pEventForBlockUpdate->requestId(), 390 pEventForBlockUpdate->blockNumber() + 1, 391 pEventForBlockUpdate->newBlock())); 392 } 393 return true; 394 } 395 default: 396 break; 397 } 398 /* Call to base-class: */ 399 return QIWithRetranslateUI<QStackedWidget>::event(pEvent); 400 } 401 402 void UIDetailsPagePrivate::sltUpdateGeneral() 403 { 404 /* Get current sender: */ 405 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 406 AssertMsg(pSender, ("Sender should be valid!\n")); 407 /* Get current block number: */ 408 int iBlockNumber = pSender->property("block-number").toInt(); 409 /* Get current machine: */ 410 CMachine &machine = m_machines[iBlockNumber]; 411 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 412 /* Get details block: */ 413 UIDetailsBlock &block = *m_set[iBlockNumber]; 414 /* Get corresponding content widget: */ 415 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_General]->contentWidget()); 416 AssertMsg(pLabel, ("Content widget should be valid!")); 417 418 /* Enable link: */ 419 block[Section_General]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 420 421 /* Update if content widget is visible: */ 422 if (pSender->isOpen()) 423 { 424 if (!machine.isNull()) 425 { 426 QString item; 427 if (machine.GetAccessible()) 428 { 429 item = sSectionItemTpl2.arg(tr("Name", "details report"), machine.GetName()) 430 + sSectionItemTpl2.arg(tr("OS Type", "details report"), vboxGlobal().vmGuestOSTypeDescription(machine.GetOSTypeId())); 431 } 432 else 433 { 434 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 435 } 436 pLabel->setText(sTableTpl.arg(item)); 437 } 438 else 439 pLabel->clear(); 440 } 441 } 442 443 void UIDetailsPagePrivate::sltUpdateSystem() 444 { 445 /* Get current sender: */ 446 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 447 AssertMsg(pSender, ("Sender should be valid!\n")); 448 /* Get current block number: */ 449 int iBlockNumber = pSender->property("block-number").toInt(); 450 /* Get current machine: */ 451 CMachine &machine = m_machines[iBlockNumber]; 452 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 453 /* Get details block: */ 454 UIDetailsBlock &block = *m_set[iBlockNumber]; 455 /* Get corresponding content widget: */ 456 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_System]->contentWidget()); 457 AssertMsg(pLabel, ("Content widget should be valid!")); 458 459 /* Enable link: */ 460 block[Section_System]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 461 462 /* Update if content widget is visible: */ 463 if (pSender->isOpen()) 464 { 465 if (!machine.isNull()) 466 { 467 QString item; 468 if (machine.GetAccessible()) 469 { 470 item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 471 .arg(machine.GetMemorySize()); 472 473 int cCPU = machine.GetCPUCount(); 474 if (cCPU > 1) 475 item += sSectionItemTpl2.arg(tr("Processors", "details report"), tr("<nobr>%1</nobr>", "details report")) 476 .arg(cCPU); 477 478 int iCPUExecCap = machine.GetCPUExecutionCap(); 479 if (iCPUExecCap < 100) 480 item += sSectionItemTpl2.arg(tr("Execution Cap", "details report"), tr("<nobr>%1%</nobr>", "details report")) 481 .arg(iCPUExecCap); 482 483 /* Boot order: */ 484 QStringList bootOrder; 485 for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i) 486 { 487 KDeviceType device = machine.GetBootOrder(i); 488 if (device == KDeviceType_Null) 489 continue; 490 bootOrder << vboxGlobal().toString(device); 491 } 492 if (bootOrder.isEmpty()) 493 bootOrder << vboxGlobal().toString(KDeviceType_Null); 494 495 item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", ")); 496 497 #ifdef VBOX_WITH_FULL_DETAILS_REPORT 498 /* BIOS Settings holder: */ 499 const CBIOSSettings &biosSettings = machine.GetBIOSSettings(); 500 QStringList bios; 501 502 /* ACPI: */ 503 if (biosSettings.GetACPIEnabled()) 504 bios << tr("ACPI", "details report"); 505 506 /* IO APIC: */ 507 if (biosSettings.GetIOAPICEnabled()) 508 bios << tr("IO APIC", "details report"); 509 510 if (!bios.isEmpty()) 511 item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", ")); 512 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */ 513 514 QStringList accel; 515 if (m_vbox.GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx)) 516 { 517 /* VT-x/AMD-V: */ 518 if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)) 519 { 520 accel << tr("VT-x/AMD-V", "details report"); 521 522 /* Nested Paging (only when hw virt is enabled): */ 523 if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)) 524 accel << tr("Nested Paging", "details report"); 525 } 526 } 527 528 /* PAE/NX: */ 529 if (machine.GetCPUProperty(KCPUPropertyType_PAE)) 530 accel << tr("PAE/NX", "details report"); 531 532 if (!accel.isEmpty()) 533 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 534 } 535 else 536 { 537 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 538 } 539 pLabel->setText(sTableTpl.arg(item)); 540 } 541 else 542 pLabel->clear(); 543 } 544 } 545 546 void UIDetailsPagePrivate::sltUpdatePreview() 547 { 548 /* Get current sender: */ 549 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 550 AssertMsg(pSender, ("Sender should be valid!\n")); 551 /* Get current block number: */ 552 int iBlockNumber = pSender->property("block-number").toInt(); 553 /* Get current machine: */ 554 CMachine &machine = m_machines[iBlockNumber]; 555 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 556 /* Get details block: */ 557 UIDetailsBlock &block = *m_set[iBlockNumber]; 558 /* Get corresponding content widget: */ 559 UIVMPreviewWindow *pPreview = qobject_cast<UIVMPreviewWindow*>(block[Section_Preview]->contentWidget()); 560 AssertMsg(pPreview, ("Content widget should be valid!")); 561 562 /* Update if content widget is visible: */ 563 if (pSender->isOpen()) 564 { 565 /* Update preview widget: */ 566 pPreview->setMachine(machine); 567 } 568 } 569 570 void UIDetailsPagePrivate::sltUpdateDisplay() 571 { 572 /* Get current sender: */ 573 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 574 AssertMsg(pSender, ("Sender should be valid!\n")); 575 /* Get current block number: */ 576 int iBlockNumber = pSender->property("block-number").toInt(); 577 /* Get current machine: */ 578 CMachine &machine = m_machines[iBlockNumber]; 579 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 580 /* Get details block: */ 581 UIDetailsBlock &block = *m_set[iBlockNumber]; 582 /* Get corresponding content widget: */ 583 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Display]->contentWidget()); 584 AssertMsg(pLabel, ("Content widget should be valid!")); 585 586 /* Enable link: */ 587 block[Section_Display]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 588 589 /* Update if content widget is visible: */ 590 if (pSender->isOpen()) 591 { 592 if (!machine.isNull()) 593 { 594 /* Video tab: */ 595 QString item = QString(sSectionItemTpl2).arg(tr("Video Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 596 .arg(machine.GetVRAMSize()); 597 598 int cGuestScreens = machine.GetMonitorCount(); 599 if (cGuestScreens > 1) 600 item += QString(sSectionItemTpl2).arg(tr("Screens", "details report")).arg(cGuestScreens); 601 602 QStringList accel; 603 #ifdef VBOX_WITH_VIDEOHWACCEL 604 if (machine.GetAccelerate2DVideoEnabled()) 605 accel << tr("2D Video", "details report"); 606 #endif /* VBOX_WITH_VIDEOHWACCEL */ 607 if (machine.GetAccelerate3DEnabled()) 608 accel << tr("3D", "details report"); 609 610 if (!accel.isEmpty()) 611 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 612 613 /* VRDE tab: */ 614 CVRDEServer srv = machine.GetVRDEServer(); 615 if (!srv.isNull()) 616 { 617 if (srv.GetEnabled()) 618 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server Port", "details report (VRDE Server)")) 619 .arg(srv.GetVRDEProperty("TCP/Ports")); 620 else 621 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server", "details report (VRDE Server)")) 622 .arg(tr("Disabled", "details report (VRDE Server)")); 623 } 624 625 pLabel->setText(sTableTpl.arg(item)); 626 } 627 else 628 pLabel->clear(); 629 } 630 } 631 632 void UIDetailsPagePrivate::sltUpdateStorage() 633 { 634 /* Get current sender: */ 635 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 636 AssertMsg(pSender, ("Sender should be valid!\n")); 637 /* Get current block number: */ 638 int iBlockNumber = pSender->property("block-number").toInt(); 639 /* Get current machine: */ 640 CMachine &machine = m_machines[iBlockNumber]; 641 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 642 /* Get details block: */ 643 UIDetailsBlock &block = *m_set[iBlockNumber]; 644 /* Get corresponding content widget: */ 645 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Storage]->contentWidget()); 646 AssertMsg(pLabel, ("Content widget should be valid!")); 647 648 /* Enable link: */ 649 block[Section_Storage]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 650 651 /* Update if content widget is visible: */ 652 if (pSender->isOpen()) 653 { 654 if (!machine.isNull()) 655 { 656 QString item; 657 /* Iterate over the all machine controllers: */ 658 const CStorageControllerVector &controllers = machine.GetStorageControllers(); 659 for (int i = 0; i < controllers.size(); ++i) 660 { 661 /* Get current controller: */ 662 const CStorageController &controller = controllers[i]; 663 /* Add controller information: */ 664 item += QString(sSectionItemTpl3).arg(controller.GetName()); 665 666 /* Populate sorted map with attachments information: */ 667 QMap<StorageSlot,QString> attachmentsMap; 668 const CMediumAttachmentVector &attachments = machine.GetMediumAttachmentsOfController(controller.GetName()); 669 for (int j = 0; j < attachments.size(); ++j) 670 { 671 /* Get current attachment: */ 672 const CMediumAttachment &attachment = attachments[j]; 673 /* Prepare current storage slot: */ 674 StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()); 675 /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */ 676 QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString(); 677 if (!strDeviceType.isNull()) 678 strDeviceType.prepend(' '); 679 /* Prepare current medium object: */ 680 const CMedium &medium = attachment.GetMedium(); 681 /* Prepare information about current medium & attachment: */ 682 QString strAttachmentInfo = !attachment.isOk() ? QString() : 683 QString(sSectionItemTpl2) 684 .arg(QString(" ") + 685 vboxGlobal().toString(StorageSlot(controller.GetBus(), 686 attachment.GetPort(), 687 attachment.GetDevice())) + 688 strDeviceType) 689 .arg(vboxGlobal().details(medium, false)); 690 /* Insert that attachment into map: */ 691 if (!strAttachmentInfo.isNull()) 692 attachmentsMap.insert(attachmentSlot, strAttachmentInfo); 693 } 694 695 /* Iterate over the sorted map with attachments information: */ 696 QMapIterator<StorageSlot,QString> it(attachmentsMap); 697 while (it.hasNext()) 698 { 699 /* Add controller information: */ 700 it.next(); 701 item += it.value(); 702 } 703 } 704 705 if (item.isNull()) 706 item = QString(sSectionItemTpl1).arg(tr("Not Attached", "details report (Storage)")); 707 708 pLabel->setText(sTableTpl.arg(item)); 709 } 710 else 711 pLabel->clear(); 712 } 713 } 714 715 void UIDetailsPagePrivate::sltUpdateAudio() 716 { 717 /* Get current sender: */ 718 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 719 AssertMsg(pSender, ("Sender should be valid!\n")); 720 /* Get current block number: */ 721 int iBlockNumber = pSender->property("block-number").toInt(); 722 /* Get current machine: */ 723 CMachine &machine = m_machines[iBlockNumber]; 724 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 725 /* Get details block: */ 726 UIDetailsBlock &block = *m_set[iBlockNumber]; 727 /* Get corresponding content widget: */ 728 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Audio]->contentWidget()); 729 AssertMsg(pLabel, ("Content widget should be valid!")); 730 731 /* Enable link: */ 732 block[Section_Audio]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 733 734 /* Update if content widget is visible: */ 735 if (pSender->isOpen()) 736 { 737 if (!machine.isNull()) 738 { 739 QString item; 740 741 const CAudioAdapter &audio = machine.GetAudioAdapter(); 742 if (audio.GetEnabled()) 743 item = QString(sSectionItemTpl2).arg(tr("Host Driver", "details report (audio)"), 744 vboxGlobal().toString(audio.GetAudioDriver())) + 745 QString(sSectionItemTpl2).arg(tr("Controller", "details report (audio)"), 746 vboxGlobal().toString(audio.GetAudioController())); 747 else 748 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (audio)")); 749 750 pLabel->setText(sTableTpl.arg(item)); 751 } 752 else 753 pLabel->clear(); 754 } 755 } 756 757 void UIDetailsPagePrivate::sltUpdateNetwork() 758 { 759 /* Get current sender: */ 760 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 761 AssertMsg(pSender, ("Sender should be valid!\n")); 762 /* Get current block number: */ 763 int iBlockNumber = pSender->property("block-number").toInt(); 764 /* Get current machine: */ 765 CMachine &machine = m_machines[iBlockNumber]; 766 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 767 /* Get details block: */ 768 UIDetailsBlock &block = *m_set[iBlockNumber]; 769 /* Get corresponding content widget: */ 770 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Network]->contentWidget()); 771 AssertMsg(pLabel, ("Content widget should be valid!")); 772 773 /* Enable link: */ 774 block[Section_Network]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 775 776 /* Update if content widget is visible: */ 777 if (pSender->isOpen()) 778 { 779 if (!machine.isNull()) 780 { 781 QString item; 782 783 ulong count = m_vbox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3); 784 for (ulong slot = 0; slot < count; slot ++) 785 { 786 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(slot); 787 if (adapter.GetEnabled()) 788 { 789 KNetworkAttachmentType type = adapter.GetAttachmentType(); 790 QString attType = vboxGlobal().toString(adapter.GetAdapterType()) 791 .replace(QRegExp("\\s\\(.+\\)"), " (%1)"); 792 /* Don't use the adapter type string for types that have 793 * an additional symbolic network/interface name field, 794 * use this name instead: */ 795 if (type == KNetworkAttachmentType_Bridged) 796 attType = attType.arg(tr("Bridged adapter, %1", "details report (network)").arg(adapter.GetBridgedInterface())); 797 else if (type == KNetworkAttachmentType_Internal) 798 attType = attType.arg(tr("Internal network, '%1'", "details report (network)").arg(adapter.GetInternalNetwork())); 799 else if (type == KNetworkAttachmentType_HostOnly) 800 attType = attType.arg(tr("Host-only adapter, '%1'", "details report (network)").arg(adapter.GetHostOnlyInterface())); 801 else if (type == KNetworkAttachmentType_Generic) 802 { 803 QString strGenericDriverProperties(summarizeGenericProperties(adapter)); 804 attType = strGenericDriverProperties.isNull() ? 805 attType.arg(tr("Generic driver, '%1'", "details report (network)").arg(adapter.GetGenericDriver())) : 806 attType.arg(tr("Generic driver, '%1' { %2 }", "details report (network)") 807 .arg(adapter.GetGenericDriver(), strGenericDriverProperties)); 808 } 809 else 810 attType = attType.arg(vboxGlobal().toString(type)); 811 812 item += QString(sSectionItemTpl2).arg(tr("Adapter %1", "details report (network)").arg(adapter.GetSlot() + 1)) 813 .arg(attType); 814 } 815 } 816 if (item.isNull()) 817 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (network)")); 818 819 pLabel->setText(sTableTpl.arg(item)); 820 } 821 else 822 pLabel->clear(); 823 } 824 } 825 826 void UIDetailsPagePrivate::sltUpdateSerialPorts() 827 { 828 /* Get current sender: */ 829 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 830 AssertMsg(pSender, ("Sender should be valid!\n")); 831 /* Get current block number: */ 832 int iBlockNumber = pSender->property("block-number").toInt(); 833 /* Get current machine: */ 834 CMachine &machine = m_machines[iBlockNumber]; 835 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 836 /* Get details block: */ 837 UIDetailsBlock &block = *m_set[iBlockNumber]; 838 /* Get corresponding content widget: */ 839 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Serial]->contentWidget()); 840 AssertMsg(pLabel, ("Content widget should be valid!")); 841 842 /* Enable link: */ 843 block[Section_Serial]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 844 845 /* Update if content widget is visible: */ 846 if (pSender->isOpen()) 847 { 848 if (!machine.isNull()) 849 { 850 QString item; 851 852 ulong count = m_vbox.GetSystemProperties().GetSerialPortCount(); 853 for (ulong slot = 0; slot < count; slot ++) 854 { 855 const CSerialPort &port = machine.GetSerialPort(slot); 856 if (port.GetEnabled()) 857 { 858 KPortMode mode = port.GetHostMode(); 859 QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", "; 860 if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice || mode == KPortMode_RawFile) 861 data += QString("%1 (<nobr>%2</nobr>)").arg(vboxGlobal().toString(mode)).arg(QDir::toNativeSeparators(port.GetPath())); 862 else 863 data += vboxGlobal().toString(mode); 864 865 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (serial ports)").arg(port.GetSlot() + 1)) 866 .arg(data); 867 } 868 } 869 if (item.isNull()) 870 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (serial ports)")); 871 872 pLabel->setText(sTableTpl.arg(item)); 873 } 874 else 875 pLabel->clear(); 876 } 877 } 878 879 #ifdef VBOX_WITH_PARALLEL_PORTS 880 void UIDetailsPagePrivate::sltUpdateParallelPorts() 881 { 882 /* Get current sender: */ 883 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 884 AssertMsg(pSender, ("Sender should be valid!\n")); 885 /* Get current block number: */ 886 int iBlockNumber = pSender->property("block-number").toInt(); 887 /* Get current machine: */ 888 CMachine &machine = m_machines[iBlockNumber]; 889 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 890 /* Get details block: */ 891 UIDetailsBlock &block = *m_set[iBlockNumber]; 892 /* Get corresponding content widget: */ 893 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Parallel]->contentWidget()); 894 AssertMsg(pLabel, ("Content widget should be valid!")); 895 896 /* Enable link: */ 897 block[Section_Parallel]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 898 899 /* Update if content widget is visible: */ 900 if (pSender->isOpen()) 901 { 902 if (!machine.isNull()) 903 { 904 QString item; 905 906 ulong count = m_vbox.GetSystemProperties().GetParallelPortCount(); 907 for (ulong slot = 0; slot < count; slot ++) 908 { 909 const CParallelPort &port = machine.GetParallelPort(slot); 910 if (port.GetEnabled()) 911 { 912 QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) + 913 QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath())); 914 915 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (parallel ports)").arg(port.GetSlot() + 1)) 916 .arg(data); 917 } 918 } 919 if (item.isNull()) 920 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (parallel ports)")); 921 922 pLabel->setText(sTableTpl.arg(item)); 923 } 924 else 925 pLabel->clear(); 926 } 927 } 928 #endif /* VBOX_WITH_PARALLEL_PORTS */ 929 930 void UIDetailsPagePrivate::sltUpdateUSB() 931 { 932 /* Get current sender: */ 933 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 934 AssertMsg(pSender, ("Sender should be valid!\n")); 935 /* Get current block number: */ 936 int iBlockNumber = pSender->property("block-number").toInt(); 937 /* Get current machine: */ 938 CMachine &machine = m_machines[iBlockNumber]; 939 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 940 /* Get details block: */ 941 UIDetailsBlock &block = *m_set[iBlockNumber]; 942 /* Get corresponding content widget: */ 943 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_USB]->contentWidget()); 944 AssertMsg(pLabel, ("Content widget should be valid!")); 945 946 /* Enable link: */ 947 block[Section_USB]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 948 949 /* Update if content widget is visible: */ 950 if (pSender->isOpen()) 951 { 952 if (!machine.isNull()) 953 { 954 QString item; 955 956 const CUSBController &ctl = machine.GetUSBController(); 957 if (!ctl.isNull() && ctl.GetProxyAvailable()) 958 { 959 m_fUSBAvailable = true; 960 /* The USB controller may be unavailable (i.e. in VirtualBox OSE): */ 961 if (ctl.GetEnabled()) 962 { 963 const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters(); 964 uint active = 0; 965 for (int i = 0; i < coll.size(); ++i) 966 if (coll[i].GetActive()) 967 ++active; 968 969 item = QString(sSectionItemTpl2).arg(tr("Device Filters", "details report (USB)"), 970 tr("%1 (%2 active)", "details report (USB)").arg(coll.size()).arg(active)); 971 } 972 else 973 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (USB)")); 974 975 pLabel->setText(sTableTpl.arg(item)); 976 } 977 else 978 { 979 m_fUSBAvailable = false; 980 /* Fully hide when USB is not available: */ 981 block[Section_USB]->hide(); 982 } 983 } 984 else 985 pLabel->clear(); 986 } 987 } 988 989 void UIDetailsPagePrivate::sltUpdateSharedFolders() 990 { 991 /* Get current sender: */ 992 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 993 AssertMsg(pSender, ("Sender should be valid!\n")); 994 /* Get current block number: */ 995 int iBlockNumber = pSender->property("block-number").toInt(); 996 /* Get current machine: */ 997 CMachine &machine = m_machines[iBlockNumber]; 998 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 999 /* Get details block: */ 1000 UIDetailsBlock &block = *m_set[iBlockNumber]; 1001 /* Get corresponding content widget: */ 1002 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_SharedFolders]->contentWidget()); 1003 AssertMsg(pLabel, ("Content widget should be valid!")); 1004 1005 /* Enable link: */ 1006 block[Section_SharedFolders]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 1007 1008 /* Update if content widget is visible: */ 1009 if (pSender->isOpen()) 1010 { 1011 if (!machine.isNull()) 1012 { 1013 QString item; 1014 1015 ulong count = machine.GetSharedFolders().size(); 1016 if (count > 0) 1017 { 1018 item = QString(sSectionItemTpl2).arg(tr("Shared Folders", "details report (shared folders)")).arg(count); 1019 } 1020 else 1021 item = QString(sSectionItemTpl1).arg(tr("None", "details report (shared folders)")); 1022 1023 pLabel->setText(sTableTpl.arg(item)); 1024 } 1025 else 1026 pLabel->clear(); 1027 } 1028 } 1029 1030 void UIDetailsPagePrivate::sltUpdateDescription() 1031 { 1032 /* Get current sender: */ 1033 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1034 AssertMsg(pSender, ("Sender should be valid!\n")); 1035 /* Get current block number: */ 1036 int iBlockNumber = pSender->property("block-number").toInt(); 1037 /* Get current machine: */ 1038 CMachine &machine = m_machines[iBlockNumber]; 1039 AssertMsg(!machine.isNull(), ("Machine should be valid!\n")); 1040 /* Get details block: */ 1041 UIDetailsBlock &block = *m_set[iBlockNumber]; 1042 /* Get corresponding content widget: */ 1043 QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Description]->contentWidget()); 1044 AssertMsg(pLabel, ("Content widget should be valid!")); 1045 1046 /* Enable link: */ 1047 block[Section_Description]->setTitleLinkEnabled(m_changeable[iBlockNumber]); 1048 1049 /* Update if content widget is visible: */ 1050 if (pSender->isOpen()) 1051 { 1052 if (!machine.isNull()) 1053 { 1054 QString item; 1055 const QString &strDesc = machine.GetDescription(); 1056 if (!strDesc.isEmpty()) 1057 item = QString(sSectionItemTpl4).arg(strDesc); 1058 else 1059 item = QString(sSectionItemTpl1).arg(tr("None", "details report (description)")); 1060 1061 pLabel->setText(sTableTpl.arg(item)); 1062 } 1063 else 1064 pLabel->clear(); 1065 } 1066 } 1067 1068 void UIDetailsPagePrivate::sltContextMenuRequested(const QPoint &pos) 1069 { 1070 /* Populate list of allowed actions: */ 1071 QList<QAction*> actions; 1072 for (int i = 0; i < m_sections.size(); ++i) 1073 actions << m_actions[m_sections[i]]; 1074 /* Restrict USB action if USB is NOT available: */ 1075 if (!m_fUSBAvailable) 1076 actions.removeOne(m_actions[Section_USB]); 1077 /* Popup menu to show/hide sections: */ 1078 QAction *pReturn = QMenu::exec(actions, m_pDetails->mapToGlobal(pos), 0); 1079 /* If some action was toggled: */ 1080 if (pReturn) 1081 { 1082 /* Get corresponding section type: */ 1083 Section section = static_cast<Section>(pReturn->data().toInt()); 1084 /* Enumerate all the available blocks: */ 1085 for (int i = 0; i < m_cMachineCount; ++i) 1086 { 1087 /* Get current popup: */ 1088 UIPopupBox *pPopup = (*m_set[i])[section]; 1089 /* Show/hide popup if necessary: */ 1090 if (pReturn->isChecked()) 1091 pPopup->show(); 1092 else 1093 pPopup->hide(); 1094 } 1095 } 1096 } 1097 1098 void UIDetailsPagePrivate::sltPopupToggled(bool fPopupOpened) 1099 { 1100 /* Get current sender: */ 1101 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1102 AssertMsg(pSender, ("Sender should be valid!\n")); 1103 /* Get section type: */ 1104 Section section = static_cast<Section>(pSender->property("section-type").toInt()); 1105 /* Update the state of corresponding map: */ 1106 m_sectionOpened[section] = fPopupOpened; 1107 /* Open/Close all the blocks: */ 1108 for (int i = 0; i < m_cMachineCount; ++i) 1109 (*m_set[i])[section]->setOpen(fPopupOpened); 1110 } 1111 1112 void UIDetailsPagePrivate::prepareSet(bool fNew) 1113 { 1114 /* Do we need to create new set? */ 1115 if (fNew) 1116 { 1117 /* Which sections should be available: */ 1118 m_sections.clear(); 1119 if (m_cMachineCount == 1) 359 { 360 /* Configure context menu policy: */ 361 setContextMenuPolicy(Qt::CustomContextMenu); 362 connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltContextMenuRequested(const QPoint&))); 363 364 /* Create and configure main layout: */ 365 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 366 pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 367 pMainLayout->addStretch(1); 368 } 369 370 void UIDetails::setMachines(const QList<CMachine> &machines) 371 { 372 /* If details preparing is NOT yet started: */ 373 if (m_cBlockCount != machines.size()) 374 { 375 /* Get new machine count: */ 376 m_cBlockCount = machines.size(); 377 378 /* Populate list of available sections: */ 379 if (m_cBlockCount == 1) 1120 380 { 1121 381 m_sections << Section_General … … 1127 387 << Section_Network 1128 388 << Section_Serial 1129 389 #ifdef VBOX_WITH_PARALLEL_PORTS 1130 390 << Section_Parallel 1131 391 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1132 392 << Section_USB 1133 393 << Section_SharedFolders … … 1140 400 << Section_Preview; 1141 401 } 1142 1143 /* Recreate details set: */ 1144 m_set.clear(); 1145 m_set.resize(m_cMachineCount); 1146 1147 /* Re-create details widget: */ 1148 if (m_pDetails) 1149 delete m_pDetails; 1150 m_pDetails = new QWidget(m_pScrollArea); 1151 m_pScrollArea->setWidget(m_pDetails); 1152 m_pDetails->setContextMenuPolicy(Qt::CustomContextMenu); 1153 connect(m_pDetails, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltContextMenuRequested(const QPoint&))); 1154 QVBoxLayout *pMainLayout = new QVBoxLayout(m_pDetails); 1155 pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 1156 pMainLayout->addStretch(1); 1157 1158 /* Generate new set id: */ 1159 m_currentRequestId = QUuid::createUuid(); 1160 } 1161 1162 /* Prepare set content (blocks): */ 1163 QCoreApplication::postEvent(this, new UIEventForBlockUpdate(m_currentRequestId, 0, fNew /* recreate block? */)); 1164 } 1165 1166 void UIDetailsPagePrivate::prepareBlock(int iBlockNumber, bool fNew) 1167 { 1168 /* Prepare block pointer: */ 1169 UIDetailsBlock *pBlock = 0; 1170 1171 /* Do we need to create new block? */ 1172 if (fNew) 402 } 403 404 /* Reset variables: */ 405 m_machines.clear(); 406 m_machines.resize(m_cBlockCount); 407 m_accessibilities.clear(); 408 m_accessibilities.resize(m_cBlockCount); 409 m_fUSBAvailable = true; 410 411 /* Fetch passed VMs: */ 412 for (int i = 0; i < machines.size(); ++i) 413 { 414 /* Get current VM: */ 415 const CMachine &machine = machines[i]; 416 /* Assign corresponding vector values: */ 417 m_machines[i] = machine; 418 m_accessibilities[i] = machine.isNull() || !machine.GetAccessible() ? false : 419 machine.GetState() != KMachineState_Stuck && 420 machine.GetState() != KMachineState_Saved /* for now! */; 421 } 422 423 /* Start preparing details content (blocks): */ 424 QCoreApplication::postEvent(this, new UIEventDetailsPrepareStart); 425 } 426 427 QAction* UIDetails::action(Section section) const 428 { 429 return m_pUIDetailsPage->action(section); 430 } 431 432 bool UIDetails::sectionOpened(Section section) const 433 { 434 return m_pUIDetailsPage->sectionOpened(section); 435 } 436 437 void UIDetails::setSectionOpened(Section section, bool fOpened) 438 { 439 m_pUIDetailsPage->setSectionOpened(section, fOpened); 440 } 441 442 void UIDetails::sltContextMenuRequested(const QPoint &pos) 443 { 444 /* Populate list of allowed actions: */ 445 QList<QAction*> actions; 446 for (int i = 0; i < m_sections.size(); ++i) 447 actions << action(m_sections[i]); 448 /* Restrict USB action if USB is NOT available: */ 449 if (!m_fUSBAvailable) 450 actions.removeOne(action(Section_USB)); 451 /* Popup menu to show/hide sections: */ 452 QAction *pReturn = QMenu::exec(actions, mapToGlobal(pos), 0); 453 /* If some action was toggled: */ 454 if (pReturn) 455 { 456 /* Get corresponding section type: */ 457 Section section = static_cast<Section>(pReturn->data().toInt()); 458 /* Enumerate all the available blocks: */ 459 for (int i = 0; i < m_cBlockCount; ++i) 460 { 461 /* Get current popup: */ 462 UIPopupBox *pPopup = (*m_details[i])[section]; 463 /* Show/hide popup if necessary: */ 464 if (pReturn->isChecked()) 465 pPopup->show(); 466 else 467 pPopup->hide(); 468 } 469 } 470 } 471 472 void UIDetails::sltPopupToggled(bool fPopupOpened) 473 { 474 /* Get current sender: */ 475 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 476 AssertMsg(pSender, ("Sender should be valid!\n")); 477 /* Get section type: */ 478 Section section = static_cast<Section>(pSender->property("section-type").toInt()); 479 /* Update the state of corresponding map: */ 480 setSectionOpened(section, fPopupOpened); 481 /* Open/Close all the blocks: */ 482 for (int i = 0; i < m_cBlockCount; ++i) 483 (*m_details[i])[section]->setOpen(fPopupOpened); 484 } 485 486 bool UIDetails::event(QEvent *pEvent) 487 { 488 /* Handle special events: */ 489 switch (pEvent->type()) 490 { 491 /* Handle details-prepare-start event: */ 492 case UIEventDetailsPrepareStart::Type: 493 { 494 /* Cast and accept event: */ 495 UIEventDetailsPrepareStart *pEventDetailsPrepareStart = static_cast<UIEventDetailsPrepareStart*>(pEvent); 496 pEventDetailsPrepareStart->accept(); 497 /* Create request for the first block: */ 498 QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(0)); 499 /* Finish processing: */ 500 return true; 501 } 502 /* Handle details-block-prepare-start event: */ 503 case UIEventDetailsPrepareBlockStart::Type: 504 { 505 /* Cast and accept event: */ 506 UIEventDetailsPrepareBlockStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsPrepareBlockStart*>(pEvent); 507 pEventDetailsBlockPrepareStart->accept(); 508 /* Start preparing block: */ 509 createBlock(pEventDetailsBlockPrepareStart->blockNumber()); 510 /* Finish processing: */ 511 return true; 512 } 513 /* Handle details-block-prepare-finish event: */ 514 case UIEventDetailsPrepareBlockFinish::Type: 515 { 516 /* Cast and accept event: */ 517 UIEventDetailsPrepareBlockFinish *pEventDetailsBlockPrepareFinish = static_cast<UIEventDetailsPrepareBlockFinish*>(pEvent); 518 pEventDetailsBlockPrepareFinish->accept(); 519 /* Finish preparing block: */ 520 layoutBlock(pEventDetailsBlockPrepareFinish->blockNumber()); 521 /* Create request for the next block if possible: */ 522 if (pEventDetailsBlockPrepareFinish->blockNumber() < m_cBlockCount - 1) 523 QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(pEventDetailsBlockPrepareFinish->blockNumber() + 1)); 524 /* Finish processing: */ 525 return true; 526 } 527 default: 528 break; 529 } 530 /* Propagate to base-class: */ 531 return QWidget::event(pEvent); 532 } 533 534 void UIDetails::createBlock(int iBlockNumber) 535 { 536 /* If block creation is NOT yet started: */ 537 if (!m_details.contains(iBlockNumber)) 1173 538 { 1174 539 /* Create new block: */ 1175 pBlock = m_set[iBlockNumber] = new UIDetailsBlock(m_pDetails); 540 m_details[iBlockNumber] = new UIDetailsBlock(this, m_sections, iBlockNumber); 541 } 542 543 /* Assign block with corresponding machine: */ 544 m_details[iBlockNumber]->setMachine(m_machines[iBlockNumber]); 545 } 546 547 void UIDetails::layoutBlock(int iBlockNumber) 548 { 549 /* Get current block: */ 550 UIDetailsBlock *pBlock = m_details[iBlockNumber]; 551 552 /* If block layouting is NOT yet started: */ 553 if (!pBlock->layout()) 554 { 555 /* Declare variables: */ 1176 556 UIDetailsBlock &block = *pBlock; 1177 1178 /* Prepare block content (sections): */1179 for(int i = 0; i < m_sections.size(); ++i)1180 prepareSection(block, iBlockNumber, m_sections[i]);1181 557 1182 558 /* Layout block content: */ … … 1207 583 if (m_sections.contains(Section_Serial)) 1208 584 pContainerLayout->addWidget(block[Section_Serial]); 1209 585 #ifdef VBOX_WITH_PARALLEL_PORTS 1210 586 if (m_sections.contains(Section_Parallel)) 1211 587 pContainerLayout->addWidget(block[Section_Parallel]); 1212 588 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1213 589 if (m_sections.contains(Section_USB)) 1214 590 pContainerLayout->addWidget(block[Section_USB]); … … 1217 593 if (m_sections.contains(Section_Description)) 1218 594 pContainerLayout->addWidget(block[Section_Description]); 1219 QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>( m_pDetails->layout());595 QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>(layout()); 1220 596 pMainLayout->insertWidget(pMainLayout->count() - 1, pBlock); 1221 597 1222 /* Configure created block: */598 /* Configure block content: */ 1223 599 for (int i = 0; i < m_sections.size(); ++i) 1224 600 { 1225 601 /* Assign corresponding action text as section title: */ 1226 block[m_sections[i]]->setTitle( m_actions[m_sections[i]]->text());602 block[m_sections[i]]->setTitle(action(m_sections[i])->text()); 1227 603 1228 604 /* If corresponding action is checked: */ 1229 if ( m_actions[m_sections[i]]->isChecked())605 if (action(m_sections[i])->isChecked()) 1230 606 { 1231 607 /* Unhide corresponding section: */ … … 1237 613 block.show(); 1238 614 1239 /* Send and process layout request for thescroll-area: */615 /* Layout parent scroll-area: */ 1240 616 QEvent layoutEvent(QEvent::LayoutRequest); 1241 QCoreApplication::sendEvent(m_pScrollArea, &layoutEvent); 1242 } 1243 else 1244 { 1245 /* Get existing block: */ 1246 pBlock = m_set[iBlockNumber]; 1247 UIDetailsBlock &block = *pBlock; 1248 1249 /* For every section of block: */ 1250 for (int i = 0; i < m_sections.size(); ++i) 1251 { 1252 /* Call for update: */ 1253 block[m_sections[i]]->callForUpdateContentWidget(); 1254 } 617 QCoreApplication::sendEvent(parent(), &layoutEvent); 1255 618 } 1256 619 … … 1259 622 } 1260 623 1261 void UIDetailsPagePrivate::prepareSection(UIDetailsBlock &block, int iBlockNumber, Section section) 1262 { 1263 /* Prepare new section (popup box): */ 1264 UIPopupBox *pPopup = block[section] = new UIPopupBox(&block); 1265 pPopup->hide(); 1266 connect(pPopup, SIGNAL(titleClicked(const QString &)), this, SIGNAL(linkClicked(const QString &))); 1267 connect(pPopup, SIGNAL(toggled(bool)), this, SLOT(sltPopupToggled(bool))); 1268 pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 1269 pPopup->setProperty("block-number", iBlockNumber); 1270 pPopup->setProperty("section-type", static_cast<int>(section)); 1271 if (!m_machines[iBlockNumber].GetAccessible()) 1272 pPopup->setWarningIcon(UIIconPool::iconSet(":/state_aborted_16px.png")); 1273 1274 /* Configure the popup box: */ 1275 switch (section) 1276 { 1277 case Section_General: 1278 { 1279 QILabel *pLabel = new QILabel(pPopup); 1280 pLabel->setWordWrap(true); 1281 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1282 pPopup->setTitleLink("#general"); 1283 pPopup->setContentWidget(pLabel); 1284 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateGeneral())); 1285 break; 1286 } 1287 case Section_System: 1288 { 1289 QILabel *pLabel = new QILabel(pPopup); 1290 pLabel->setWordWrap(true); 1291 pPopup->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png")); 1292 pPopup->setTitleLink("#system"); 1293 pPopup->setContentWidget(pLabel); 1294 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSystem())); 1295 break; 1296 } 1297 case Section_Preview: 1298 { 1299 UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(pPopup); 1300 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1301 pPopup->setContentWidget(pWidget); 1302 pPopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 1303 /* Make sure the width is always the same, regardless if the preview is shown or not: */ 1304 pPopup->setFixedWidth(pPopup->sizeHint().width()); 1305 pWidget->updateGeometry(); 1306 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdatePreview())); 1307 break; 1308 } 1309 case Section_Display: 1310 { 1311 QILabel *pLabel = new QILabel(pPopup); 1312 pLabel->setWordWrap(true); 1313 pPopup->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png")); 1314 pPopup->setTitleLink("#display"); 1315 pPopup->setContentWidget(pLabel); 1316 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDisplay())); 1317 break; 1318 } 1319 case Section_Storage: 1320 { 1321 QILabel *pLabel = new QILabel(pPopup); 1322 pLabel->setWordWrap(true); 1323 pPopup->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png")); 1324 pPopup->setTitleLink("#storage"); 1325 pPopup->setContentWidget(pLabel); 1326 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateStorage())); 1327 break; 1328 } 1329 case Section_Audio: 1330 { 1331 QILabel *pLabel = new QILabel(pPopup); 1332 pLabel->setWordWrap(true); 1333 pPopup->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png")); 1334 pPopup->setTitleLink("#audio"); 1335 pPopup->setContentWidget(pLabel); 1336 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateAudio())); 1337 break; 1338 } 1339 case Section_Network: 1340 { 1341 QILabel *pLabel = new QILabel(pPopup); 1342 pLabel->setWordWrap(true); 1343 pPopup->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png")); 1344 pPopup->setTitleLink("#network"); 1345 pPopup->setContentWidget(pLabel); 1346 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateNetwork())); 1347 break; 1348 } 1349 case Section_Serial: 1350 { 1351 QILabel *pLabel = new QILabel(pPopup); 1352 pLabel->setWordWrap(true); 1353 pPopup->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png")); 1354 pPopup->setTitleLink("#serialPorts"); 1355 pPopup->setContentWidget(pLabel); 1356 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSerialPorts())); 1357 break; 1358 } 624 UIDetailsBlock::UIDetailsBlock(UIDetails *pParent, const QList<Section> §ions, int iBlockNumber) 625 : QWidget(pParent) 626 , m_vbox(vboxGlobal().virtualBox()) 627 , m_pUIDetails(pParent) 628 , m_iBlockNumber(iBlockNumber) 629 , m_cSectionCount(0) 630 , m_sections(sections) 631 { 632 } 633 634 void UIDetailsBlock::setMachine(const CMachine &machine) 635 { 636 /* If block preparing is NOT yet started: */ 637 if (m_cSectionCount != m_sections.size()) 638 { 639 /* Get new section count: */ 640 m_cSectionCount = m_sections.size(); 641 } 642 643 /* Set passed VM: */ 644 m_machine = machine; 645 646 /* Start preparing details block content (sections): */ 647 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareStart); 648 } 649 650 bool UIDetailsBlock::accessibility() const 651 { 652 return m_pUIDetails->accessibility(m_iBlockNumber); 653 } 654 655 bool UIDetailsBlock::sectionOpened(Section section) const 656 { 657 return m_pUIDetails->sectionOpened(section); 658 } 659 660 void UIDetailsBlock::setUSBAvailable(bool fAvailable) 661 { 662 m_pUIDetails->setUSBAvailable(fAvailable); 663 } 664 665 void UIDetailsBlock::sltUpdateGeneral() 666 { 667 /* Get current sender: */ 668 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 669 AssertMsg(pSender, ("Sender should be valid!\n")); 670 /* Get corresponding content widget: */ 671 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_General]->contentWidget()); 672 AssertMsg(pLabel, ("Content widget should be valid!")); 673 674 /* Enable link: */ 675 m_block[Section_General]->setTitleLinkEnabled(accessibility()); 676 677 /* Update if content widget is visible: */ 678 if (pSender->isOpen()) 679 { 680 if (!m_machine.isNull()) 681 { 682 QString item; 683 if (m_machine.GetAccessible()) 684 { 685 item = sSectionItemTpl2.arg(tr("Name", "details report"), m_machine.GetName()) 686 + sSectionItemTpl2.arg(tr("OS Type", "details report"), vboxGlobal().vmGuestOSTypeDescription(m_machine.GetOSTypeId())); 687 } 688 else 689 { 690 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 691 } 692 pLabel->setText(sTableTpl.arg(item)); 693 } 694 else 695 pLabel->clear(); 696 } 697 } 698 699 void UIDetailsBlock::sltUpdateSystem() 700 { 701 /* Get current sender: */ 702 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 703 AssertMsg(pSender, ("Sender should be valid!\n")); 704 /* Get corresponding content widget: */ 705 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_System]->contentWidget()); 706 AssertMsg(pLabel, ("Content widget should be valid!")); 707 708 /* Enable link: */ 709 m_block[Section_System]->setTitleLinkEnabled(accessibility()); 710 711 /* Update if content widget is visible: */ 712 if (pSender->isOpen()) 713 { 714 if (!m_machine.isNull()) 715 { 716 QString item; 717 if (m_machine.GetAccessible()) 718 { 719 item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 720 .arg(m_machine.GetMemorySize()); 721 722 int cCPU = m_machine.GetCPUCount(); 723 if (cCPU > 1) 724 item += sSectionItemTpl2.arg(tr("Processors", "details report"), tr("<nobr>%1</nobr>", "details report")) 725 .arg(cCPU); 726 727 int iCPUExecCap = m_machine.GetCPUExecutionCap(); 728 if (iCPUExecCap < 100) 729 item += sSectionItemTpl2.arg(tr("Execution Cap", "details report"), tr("<nobr>%1%</nobr>", "details report")) 730 .arg(iCPUExecCap); 731 732 /* Boot order: */ 733 QStringList bootOrder; 734 for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i) 735 { 736 KDeviceType device = m_machine.GetBootOrder(i); 737 if (device == KDeviceType_Null) 738 continue; 739 bootOrder << vboxGlobal().toString(device); 740 } 741 if (bootOrder.isEmpty()) 742 bootOrder << vboxGlobal().toString(KDeviceType_Null); 743 744 item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", ")); 745 746 #ifdef VBOX_WITH_FULL_DETAILS_REPORT 747 /* BIOS Settings holder: */ 748 const CBIOSSettings &biosSettings = m_machine.GetBIOSSettings(); 749 QStringList bios; 750 751 /* ACPI: */ 752 if (biosSettings.GetACPIEnabled()) 753 bios << tr("ACPI", "details report"); 754 755 /* IO APIC: */ 756 if (biosSettings.GetIOAPICEnabled()) 757 bios << tr("IO APIC", "details report"); 758 759 if (!bios.isEmpty()) 760 item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", ")); 761 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */ 762 763 QStringList accel; 764 if (m_vbox.GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx)) 765 { 766 /* VT-x/AMD-V: */ 767 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)) 768 { 769 accel << tr("VT-x/AMD-V", "details report"); 770 771 /* Nested Paging (only when hw virt is enabled): */ 772 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)) 773 accel << tr("Nested Paging", "details report"); 774 } 775 } 776 777 /* PAE/NX: */ 778 if (m_machine.GetCPUProperty(KCPUPropertyType_PAE)) 779 accel << tr("PAE/NX", "details report"); 780 781 if (!accel.isEmpty()) 782 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 783 } 784 else 785 { 786 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report")); 787 } 788 pLabel->setText(sTableTpl.arg(item)); 789 } 790 else 791 pLabel->clear(); 792 } 793 } 794 795 void UIDetailsBlock::sltUpdatePreview() 796 { 797 /* Get current sender: */ 798 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 799 AssertMsg(pSender, ("Sender should be valid!\n")); 800 /* Get corresponding content widget: */ 801 UIVMPreviewWindow *pPreview = qobject_cast<UIVMPreviewWindow*>(m_block[Section_Preview]->contentWidget()); 802 AssertMsg(pPreview, ("Content widget should be valid!")); 803 804 /* Update if content widget is visible: */ 805 if (pSender->isOpen()) 806 { 807 /* Update preview widget: */ 808 pPreview->setMachine(m_machine); 809 } 810 } 811 812 void UIDetailsBlock::sltUpdateDisplay() 813 { 814 /* Get current sender: */ 815 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 816 AssertMsg(pSender, ("Sender should be valid!\n")); 817 /* Get corresponding content widget: */ 818 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Display]->contentWidget()); 819 AssertMsg(pLabel, ("Content widget should be valid!")); 820 821 /* Enable link: */ 822 m_block[Section_Display]->setTitleLinkEnabled(accessibility()); 823 824 /* Update if content widget is visible: */ 825 if (pSender->isOpen()) 826 { 827 if (!m_machine.isNull()) 828 { 829 /* Video tab: */ 830 QString item = QString(sSectionItemTpl2).arg(tr("Video Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report")) 831 .arg(m_machine.GetVRAMSize()); 832 833 int cGuestScreens = m_machine.GetMonitorCount(); 834 if (cGuestScreens > 1) 835 item += QString(sSectionItemTpl2).arg(tr("Screens", "details report")).arg(cGuestScreens); 836 837 QStringList accel; 838 #ifdef VBOX_WITH_VIDEOHWACCEL 839 if (m_machine.GetAccelerate2DVideoEnabled()) 840 accel << tr("2D Video", "details report"); 841 #endif /* VBOX_WITH_VIDEOHWACCEL */ 842 if (m_machine.GetAccelerate3DEnabled()) 843 accel << tr("3D", "details report"); 844 845 if (!accel.isEmpty()) 846 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 847 848 /* VRDE tab: */ 849 CVRDEServer srv = m_machine.GetVRDEServer(); 850 if (!srv.isNull()) 851 { 852 if (srv.GetEnabled()) 853 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server Port", "details report (VRDE Server)")) 854 .arg(srv.GetVRDEProperty("TCP/Ports")); 855 else 856 item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server", "details report (VRDE Server)")) 857 .arg(tr("Disabled", "details report (VRDE Server)")); 858 } 859 860 pLabel->setText(sTableTpl.arg(item)); 861 } 862 else 863 pLabel->clear(); 864 } 865 } 866 867 void UIDetailsBlock::sltUpdateStorage() 868 { 869 /* Get current sender: */ 870 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 871 AssertMsg(pSender, ("Sender should be valid!\n")); 872 /* Get corresponding content widget: */ 873 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Storage]->contentWidget()); 874 AssertMsg(pLabel, ("Content widget should be valid!")); 875 876 /* Enable link: */ 877 m_block[Section_Storage]->setTitleLinkEnabled(accessibility()); 878 879 /* Update if content widget is visible: */ 880 if (pSender->isOpen()) 881 { 882 if (!m_machine.isNull()) 883 { 884 QString item; 885 /* Iterate over the all m_machine controllers: */ 886 const CStorageControllerVector &controllers = m_machine.GetStorageControllers(); 887 for (int i = 0; i < controllers.size(); ++i) 888 { 889 /* Get current controller: */ 890 const CStorageController &controller = controllers[i]; 891 /* Add controller information: */ 892 item += QString(sSectionItemTpl3).arg(controller.GetName()); 893 894 /* Populate sorted map with attachments information: */ 895 QMap<StorageSlot,QString> attachmentsMap; 896 const CMediumAttachmentVector &attachments = m_machine.GetMediumAttachmentsOfController(controller.GetName()); 897 for (int j = 0; j < attachments.size(); ++j) 898 { 899 /* Get current attachment: */ 900 const CMediumAttachment &attachment = attachments[j]; 901 /* Prepare current storage slot: */ 902 StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()); 903 /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */ 904 QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString(); 905 if (!strDeviceType.isNull()) 906 strDeviceType.prepend(' '); 907 /* Prepare current medium object: */ 908 const CMedium &medium = attachment.GetMedium(); 909 /* Prepare information about current medium & attachment: */ 910 QString strAttachmentInfo = !attachment.isOk() ? QString() : 911 QString(sSectionItemTpl2) 912 .arg(QString(" ") + 913 vboxGlobal().toString(StorageSlot(controller.GetBus(), 914 attachment.GetPort(), 915 attachment.GetDevice())) + 916 strDeviceType) 917 .arg(vboxGlobal().details(medium, false)); 918 /* Insert that attachment into map: */ 919 if (!strAttachmentInfo.isNull()) 920 attachmentsMap.insert(attachmentSlot, strAttachmentInfo); 921 } 922 923 /* Iterate over the sorted map with attachments information: */ 924 QMapIterator<StorageSlot,QString> it(attachmentsMap); 925 while (it.hasNext()) 926 { 927 /* Add controller information: */ 928 it.next(); 929 item += it.value(); 930 } 931 } 932 933 if (item.isNull()) 934 item = QString(sSectionItemTpl1).arg(tr("Not Attached", "details report (Storage)")); 935 936 pLabel->setText(sTableTpl.arg(item)); 937 } 938 else 939 pLabel->clear(); 940 } 941 } 942 943 void UIDetailsBlock::sltUpdateAudio() 944 { 945 /* Get current sender: */ 946 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 947 AssertMsg(pSender, ("Sender should be valid!\n")); 948 /* Get corresponding content widget: */ 949 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Audio]->contentWidget()); 950 AssertMsg(pLabel, ("Content widget should be valid!")); 951 952 /* Enable link: */ 953 m_block[Section_Audio]->setTitleLinkEnabled(accessibility()); 954 955 /* Update if content widget is visible: */ 956 if (pSender->isOpen()) 957 { 958 if (!m_machine.isNull()) 959 { 960 QString item; 961 962 const CAudioAdapter &audio = m_machine.GetAudioAdapter(); 963 if (audio.GetEnabled()) 964 item = QString(sSectionItemTpl2).arg(tr("Host Driver", "details report (audio)"), 965 vboxGlobal().toString(audio.GetAudioDriver())) + 966 QString(sSectionItemTpl2).arg(tr("Controller", "details report (audio)"), 967 vboxGlobal().toString(audio.GetAudioController())); 968 else 969 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (audio)")); 970 971 pLabel->setText(sTableTpl.arg(item)); 972 } 973 else 974 pLabel->clear(); 975 } 976 } 977 978 void UIDetailsBlock::sltUpdateNetwork() 979 { 980 /* Get current sender: */ 981 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 982 AssertMsg(pSender, ("Sender should be valid!\n")); 983 /* Get corresponding content widget: */ 984 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Network]->contentWidget()); 985 AssertMsg(pLabel, ("Content widget should be valid!")); 986 987 /* Enable link: */ 988 m_block[Section_Network]->setTitleLinkEnabled(accessibility()); 989 990 /* Update if content widget is visible: */ 991 if (pSender->isOpen()) 992 { 993 if (!m_machine.isNull()) 994 { 995 QString item; 996 997 ulong count = m_vbox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3); 998 for (ulong slot = 0; slot < count; slot ++) 999 { 1000 const CNetworkAdapter &adapter = m_machine.GetNetworkAdapter(slot); 1001 if (adapter.GetEnabled()) 1002 { 1003 KNetworkAttachmentType type = adapter.GetAttachmentType(); 1004 QString attType = vboxGlobal().toString(adapter.GetAdapterType()) 1005 .replace(QRegExp("\\s\\(.+\\)"), " (%1)"); 1006 /* Don't use the adapter type string for types that have 1007 * an additional symbolic network/interface name field, 1008 * use this name instead: */ 1009 if (type == KNetworkAttachmentType_Bridged) 1010 attType = attType.arg(tr("Bridged adapter, %1", "details report (network)").arg(adapter.GetBridgedInterface())); 1011 else if (type == KNetworkAttachmentType_Internal) 1012 attType = attType.arg(tr("Internal network, '%1'", "details report (network)").arg(adapter.GetInternalNetwork())); 1013 else if (type == KNetworkAttachmentType_HostOnly) 1014 attType = attType.arg(tr("Host-only adapter, '%1'", "details report (network)").arg(adapter.GetHostOnlyInterface())); 1015 else if (type == KNetworkAttachmentType_Generic) 1016 { 1017 QString strGenericDriverProperties(summarizeGenericProperties(adapter)); 1018 attType = strGenericDriverProperties.isNull() ? 1019 attType.arg(tr("Generic driver, '%1'", "details report (network)").arg(adapter.GetGenericDriver())) : 1020 attType.arg(tr("Generic driver, '%1' { %2 }", "details report (network)") 1021 .arg(adapter.GetGenericDriver(), strGenericDriverProperties)); 1022 } 1023 else 1024 attType = attType.arg(vboxGlobal().toString(type)); 1025 1026 item += QString(sSectionItemTpl2).arg(tr("Adapter %1", "details report (network)").arg(adapter.GetSlot() + 1)) 1027 .arg(attType); 1028 } 1029 } 1030 if (item.isNull()) 1031 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (network)")); 1032 1033 pLabel->setText(sTableTpl.arg(item)); 1034 } 1035 else 1036 pLabel->clear(); 1037 } 1038 } 1039 1040 void UIDetailsBlock::sltUpdateSerialPorts() 1041 { 1042 /* Get current sender: */ 1043 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1044 AssertMsg(pSender, ("Sender should be valid!\n")); 1045 /* Get corresponding content widget: */ 1046 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Serial]->contentWidget()); 1047 AssertMsg(pLabel, ("Content widget should be valid!")); 1048 1049 /* Enable link: */ 1050 m_block[Section_Serial]->setTitleLinkEnabled(accessibility()); 1051 1052 /* Update if content widget is visible: */ 1053 if (pSender->isOpen()) 1054 { 1055 if (!m_machine.isNull()) 1056 { 1057 QString item; 1058 1059 ulong count = m_vbox.GetSystemProperties().GetSerialPortCount(); 1060 for (ulong slot = 0; slot < count; slot ++) 1061 { 1062 const CSerialPort &port = m_machine.GetSerialPort(slot); 1063 if (port.GetEnabled()) 1064 { 1065 KPortMode mode = port.GetHostMode(); 1066 QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", "; 1067 if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice || mode == KPortMode_RawFile) 1068 data += QString("%1 (<nobr>%2</nobr>)").arg(vboxGlobal().toString(mode)).arg(QDir::toNativeSeparators(port.GetPath())); 1069 else 1070 data += vboxGlobal().toString(mode); 1071 1072 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (serial ports)").arg(port.GetSlot() + 1)) 1073 .arg(data); 1074 } 1075 } 1076 if (item.isNull()) 1077 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (serial ports)")); 1078 1079 pLabel->setText(sTableTpl.arg(item)); 1080 } 1081 else 1082 pLabel->clear(); 1083 } 1084 } 1085 1359 1086 #ifdef VBOX_WITH_PARALLEL_PORTS 1360 case Section_Parallel: 1361 { 1362 QILabel *pLabel = new QILabel(pPopup); 1363 pLabel->setWordWrap(true); 1364 pPopup->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png")); 1365 pPopup->setTitleLink("#parallelPorts"); 1366 pPopup->setContentWidget(pLabel); 1367 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateParallelPorts())); 1368 break; 1369 } 1087 void UIDetailsBlock::sltUpdateParallelPorts() 1088 { 1089 /* Get current sender: */ 1090 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1091 AssertMsg(pSender, ("Sender should be valid!\n")); 1092 /* Get corresponding content widget: */ 1093 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Parallel]->contentWidget()); 1094 AssertMsg(pLabel, ("Content widget should be valid!")); 1095 1096 /* Enable link: */ 1097 m_block[Section_Parallel]->setTitleLinkEnabled(accessibility()); 1098 1099 /* Update if content widget is visible: */ 1100 if (pSender->isOpen()) 1101 { 1102 if (!m_machine.isNull()) 1103 { 1104 QString item; 1105 1106 ulong count = m_vbox.GetSystemProperties().GetParallelPortCount(); 1107 for (ulong slot = 0; slot < count; slot ++) 1108 { 1109 const CParallelPort &port = m_machine.GetParallelPort(slot); 1110 if (port.GetEnabled()) 1111 { 1112 QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) + 1113 QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath())); 1114 1115 item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (parallel ports)").arg(port.GetSlot() + 1)) 1116 .arg(data); 1117 } 1118 } 1119 if (item.isNull()) 1120 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (parallel ports)")); 1121 1122 pLabel->setText(sTableTpl.arg(item)); 1123 } 1124 else 1125 pLabel->clear(); 1126 } 1127 } 1370 1128 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1371 case Section_USB: 1372 { 1373 QILabel *pLabel = new QILabel(pPopup); 1374 pLabel->setWordWrap(true); 1375 pPopup->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png")); 1376 pPopup->setTitleLink("#usb"); 1377 pPopup->setContentWidget(pLabel); 1378 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateUSB())); 1379 break; 1380 } 1381 case Section_SharedFolders: 1382 { 1383 QILabel *pLabel = new QILabel(pPopup); 1384 pLabel->setWordWrap(true); 1385 pPopup->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png")); 1386 pPopup->setTitleLink("#sfolders"); 1387 pPopup->setContentWidget(pLabel); 1388 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSharedFolders())); 1389 break; 1390 } 1391 case Section_Description: 1392 { 1393 QILabel *pLabel = new QILabel(pPopup); 1394 pLabel->setWordWrap(true); 1395 pPopup->setTitleIcon(UIIconPool::iconSet(":/description_16px.png")); 1396 pPopup->setTitleLink("#general%%mTeDescription"); 1397 pPopup->setContentWidget(pLabel); 1398 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDescription())); 1399 break; 1129 1130 void UIDetailsBlock::sltUpdateUSB() 1131 { 1132 /* Get current sender: */ 1133 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1134 AssertMsg(pSender, ("Sender should be valid!\n")); 1135 /* Get corresponding content widget: */ 1136 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_USB]->contentWidget()); 1137 AssertMsg(pLabel, ("Content widget should be valid!")); 1138 1139 /* Enable link: */ 1140 m_block[Section_USB]->setTitleLinkEnabled(accessibility()); 1141 1142 /* Update if content widget is visible: */ 1143 if (pSender->isOpen()) 1144 { 1145 if (!m_machine.isNull()) 1146 { 1147 QString item; 1148 1149 const CUSBController &ctl = m_machine.GetUSBController(); 1150 if (!ctl.isNull() && ctl.GetProxyAvailable()) 1151 { 1152 setUSBAvailable(true); 1153 /* The USB controller may be unavailable (i.e. in VirtualBox OSE): */ 1154 if (ctl.GetEnabled()) 1155 { 1156 const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters(); 1157 uint active = 0; 1158 for (int i = 0; i < coll.size(); ++i) 1159 if (coll[i].GetActive()) 1160 ++active; 1161 1162 item = QString(sSectionItemTpl2).arg(tr("Device Filters", "details report (USB)"), 1163 tr("%1 (%2 active)", "details report (USB)").arg(coll.size()).arg(active)); 1164 } 1165 else 1166 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (USB)")); 1167 1168 pLabel->setText(sTableTpl.arg(item)); 1169 } 1170 else 1171 { 1172 setUSBAvailable(false); 1173 /* Fully hide when USB is not available: */ 1174 m_block[Section_USB]->hide(); 1175 } 1176 } 1177 else 1178 pLabel->clear(); 1179 } 1180 } 1181 1182 void UIDetailsBlock::sltUpdateSharedFolders() 1183 { 1184 /* Get current sender: */ 1185 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1186 AssertMsg(pSender, ("Sender should be valid!\n")); 1187 /* Get corresponding content widget: */ 1188 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_SharedFolders]->contentWidget()); 1189 AssertMsg(pLabel, ("Content widget should be valid!")); 1190 1191 /* Enable link: */ 1192 m_block[Section_SharedFolders]->setTitleLinkEnabled(accessibility()); 1193 1194 /* Update if content widget is visible: */ 1195 if (pSender->isOpen()) 1196 { 1197 if (!m_machine.isNull()) 1198 { 1199 QString item; 1200 1201 ulong count = m_machine.GetSharedFolders().size(); 1202 if (count > 0) 1203 { 1204 item = QString(sSectionItemTpl2).arg(tr("Shared Folders", "details report (shared folders)")).arg(count); 1205 } 1206 else 1207 item = QString(sSectionItemTpl1).arg(tr("None", "details report (shared folders)")); 1208 1209 pLabel->setText(sTableTpl.arg(item)); 1210 } 1211 else 1212 pLabel->clear(); 1213 } 1214 } 1215 1216 void UIDetailsBlock::sltUpdateDescription() 1217 { 1218 /* Get current sender: */ 1219 UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0; 1220 AssertMsg(pSender, ("Sender should be valid!\n")); 1221 /* Get corresponding content widget: */ 1222 QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Description]->contentWidget()); 1223 AssertMsg(pLabel, ("Content widget should be valid!")); 1224 1225 /* Enable link: */ 1226 m_block[Section_Description]->setTitleLinkEnabled(accessibility()); 1227 1228 /* Update if content widget is visible: */ 1229 if (pSender->isOpen()) 1230 { 1231 if (!m_machine.isNull()) 1232 { 1233 QString item; 1234 const QString &strDesc = m_machine.GetDescription(); 1235 if (!strDesc.isEmpty()) 1236 item = QString(sSectionItemTpl4).arg(strDesc); 1237 else 1238 item = QString(sSectionItemTpl1).arg(tr("None", "details report (description)")); 1239 1240 pLabel->setText(sTableTpl.arg(item)); 1241 } 1242 else 1243 pLabel->clear(); 1244 } 1245 } 1246 1247 bool UIDetailsBlock::event(QEvent *pEvent) 1248 { 1249 /* Handle special events: */ 1250 switch (pEvent->type()) 1251 { 1252 /* Handle details-block-prepare-start event: */ 1253 case UIEventDetailsBlockPrepareStart::Type: 1254 { 1255 /* Cast and accept event: */ 1256 UIEventDetailsBlockPrepareStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsBlockPrepareStart*>(pEvent); 1257 pEventDetailsBlockPrepareStart->accept(); 1258 /* Create request for the first section: */ 1259 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(0)); 1260 /* Finish processing: */ 1261 return true; 1262 } 1263 /* Handle details-block-section-prepare-start event: */ 1264 case UIEventDetailsBlockPrepareSectionStart::Type: 1265 { 1266 /* Cast and accept event: */ 1267 UIEventDetailsBlockPrepareSectionStart *pEventDetailsBlockPrepareSectionStart = static_cast<UIEventDetailsBlockPrepareSectionStart*>(pEvent); 1268 pEventDetailsBlockPrepareSectionStart->accept(); 1269 /* Preparing section: */ 1270 createSection(pEventDetailsBlockPrepareSectionStart->sectionNumber()); 1271 /* Create request to finish current section: */ 1272 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionFinish(pEventDetailsBlockPrepareSectionStart->sectionNumber())); 1273 /* Finish processing: */ 1274 return true; 1275 } 1276 /* Handle details-block-section-prepare-finish event: */ 1277 case UIEventDetailsBlockPrepareSectionFinish::Type: 1278 { 1279 /* Cast and accept event: */ 1280 UIEventDetailsBlockPrepareSectionFinish *pEventDetailsBlockPrepareSectionFinish = static_cast<UIEventDetailsBlockPrepareSectionFinish*>(pEvent); 1281 pEventDetailsBlockPrepareSectionFinish->accept(); 1282 if (pEventDetailsBlockPrepareSectionFinish->sectionNumber() < m_sections.size() - 1) 1283 { 1284 /* Create request for the next section: */ 1285 QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(pEventDetailsBlockPrepareSectionFinish->sectionNumber() + 1)); 1286 } 1287 else 1288 { 1289 /* Create reply for the current block: */ 1290 QCoreApplication::postEvent(parent(), new UIEventDetailsPrepareBlockFinish(m_iBlockNumber)); 1291 } 1292 /* Finish processing: */ 1293 return true; 1400 1294 } 1401 1295 default: 1402 1296 break; 1403 1297 } 1404 1405 /* Open/close section if necessary: */ 1406 pPopup->setOpen(m_sectionOpened[section]); 1298 /* Propagate to base-class: */ 1299 return QWidget::event(pEvent); 1300 } 1301 1302 void UIDetailsBlock::createSection(int iSectionNumber) 1303 { 1304 /* If section creation is NOT yet started: */ 1305 Section section = m_sections[iSectionNumber]; 1306 if (!m_block.contains(section)) 1307 { 1308 /* Prepare new section (popup box): */ 1309 UIPopupBox *pPopup = m_block[section] = new UIPopupBox(this); 1310 pPopup->hide(); 1311 connect(pPopup, SIGNAL(titleClicked(const QString &)), details()->detailsPage(), SIGNAL(linkClicked(const QString &))); 1312 connect(pPopup, SIGNAL(toggled(bool)), parent(), SLOT(sltPopupToggled(bool))); 1313 pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 1314 pPopup->setProperty("section-type", static_cast<int>(section)); 1315 if (!m_machine.GetAccessible()) 1316 pPopup->setWarningIcon(UIIconPool::iconSet(":/state_aborted_16px.png")); 1317 1318 /* Configure the popup box: */ 1319 switch (section) 1320 { 1321 case Section_General: 1322 { 1323 QILabel *pLabel = new QILabel(pPopup); 1324 pLabel->setWordWrap(true); 1325 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1326 pPopup->setTitleLink("#general"); 1327 pPopup->setContentWidget(pLabel); 1328 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateGeneral())); 1329 break; 1330 } 1331 case Section_System: 1332 { 1333 QILabel *pLabel = new QILabel(pPopup); 1334 pLabel->setWordWrap(true); 1335 pPopup->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png")); 1336 pPopup->setTitleLink("#system"); 1337 pPopup->setContentWidget(pLabel); 1338 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSystem())); 1339 break; 1340 } 1341 case Section_Preview: 1342 { 1343 UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(pPopup); 1344 pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 1345 pPopup->setContentWidget(pWidget); 1346 pPopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 1347 /* Make sure the width is always the same, regardless if the preview is shown or not: */ 1348 pPopup->setFixedWidth(pPopup->sizeHint().width()); 1349 pWidget->updateGeometry(); 1350 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdatePreview())); 1351 break; 1352 } 1353 case Section_Display: 1354 { 1355 QILabel *pLabel = new QILabel(pPopup); 1356 pLabel->setWordWrap(true); 1357 pPopup->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png")); 1358 pPopup->setTitleLink("#display"); 1359 pPopup->setContentWidget(pLabel); 1360 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDisplay())); 1361 break; 1362 } 1363 case Section_Storage: 1364 { 1365 QILabel *pLabel = new QILabel(pPopup); 1366 pLabel->setWordWrap(true); 1367 pPopup->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png")); 1368 pPopup->setTitleLink("#storage"); 1369 pPopup->setContentWidget(pLabel); 1370 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateStorage())); 1371 break; 1372 } 1373 case Section_Audio: 1374 { 1375 QILabel *pLabel = new QILabel(pPopup); 1376 pLabel->setWordWrap(true); 1377 pPopup->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png")); 1378 pPopup->setTitleLink("#audio"); 1379 pPopup->setContentWidget(pLabel); 1380 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateAudio())); 1381 break; 1382 } 1383 case Section_Network: 1384 { 1385 QILabel *pLabel = new QILabel(pPopup); 1386 pLabel->setWordWrap(true); 1387 pPopup->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png")); 1388 pPopup->setTitleLink("#network"); 1389 pPopup->setContentWidget(pLabel); 1390 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateNetwork())); 1391 break; 1392 } 1393 case Section_Serial: 1394 { 1395 QILabel *pLabel = new QILabel(pPopup); 1396 pLabel->setWordWrap(true); 1397 pPopup->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png")); 1398 pPopup->setTitleLink("#serialPorts"); 1399 pPopup->setContentWidget(pLabel); 1400 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSerialPorts())); 1401 break; 1402 } 1403 #ifdef VBOX_WITH_PARALLEL_PORTS 1404 case Section_Parallel: 1405 { 1406 QILabel *pLabel = new QILabel(pPopup); 1407 pLabel->setWordWrap(true); 1408 pPopup->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png")); 1409 pPopup->setTitleLink("#parallelPorts"); 1410 pPopup->setContentWidget(pLabel); 1411 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateParallelPorts())); 1412 break; 1413 } 1414 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1415 case Section_USB: 1416 { 1417 QILabel *pLabel = new QILabel(pPopup); 1418 pLabel->setWordWrap(true); 1419 pPopup->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png")); 1420 pPopup->setTitleLink("#usb"); 1421 pPopup->setContentWidget(pLabel); 1422 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateUSB())); 1423 break; 1424 } 1425 case Section_SharedFolders: 1426 { 1427 QILabel *pLabel = new QILabel(pPopup); 1428 pLabel->setWordWrap(true); 1429 pPopup->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png")); 1430 pPopup->setTitleLink("#sfolders"); 1431 pPopup->setContentWidget(pLabel); 1432 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSharedFolders())); 1433 break; 1434 } 1435 case Section_Description: 1436 { 1437 QILabel *pLabel = new QILabel(pPopup); 1438 pLabel->setWordWrap(true); 1439 pPopup->setTitleIcon(UIIconPool::iconSet(":/description_16px.png")); 1440 pPopup->setTitleLink("#general%%mTeDescription"); 1441 pPopup->setContentWidget(pLabel); 1442 connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDescription())); 1443 break; 1444 } 1445 default: 1446 break; 1447 } 1448 1449 /* Open/close section if necessary: */ 1450 pPopup->setOpen(sectionOpened(section)); 1451 } 1407 1452 1408 1453 /* Call for update: */ 1409 pPopup->callForUpdateContentWidget(); 1410 } 1411 1412 void UIDetailsPagePrivate::prepareDetails() 1454 m_block[section]->callForUpdateContentWidget(); 1455 } 1456 1457 /* static */ 1458 QString UIDetailsBlock::summarizeGenericProperties(const CNetworkAdapter &adapter) 1459 { 1460 QVector<QString> names; 1461 QVector<QString> props; 1462 props = adapter.GetProperties(QString(), names); 1463 QString strResult; 1464 for (int i = 0; i < names.size(); ++i) 1465 { 1466 strResult += names[i] + "=" + props[i]; 1467 if (i < names.size() - 1) 1468 strResult += ", "; 1469 } 1470 return strResult; 1471 } 1472 1473 UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction /* = 0 */) 1474 : QIWithRetranslateUI<QStackedWidget>(pParent) 1475 , m_cMachineCount(0) 1476 , m_pScrollArea(0) 1477 , m_pDetails(0) 1478 , m_pText(0) 1479 , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0) 1480 , m_pRefreshButton(0), m_pRefreshAction(pRefreshAction) 1481 { 1482 /* Check that refresh action was passed: */ 1483 Assert(m_pRefreshAction); 1484 } 1485 1486 UIDetailsPagePrivate::~UIDetailsPagePrivate() 1487 { 1488 /* Cleanup details: */ 1489 cleanupDetailsPage(); 1490 } 1491 1492 void UIDetailsPagePrivate::setMachines(const QList<CMachine> &machines) 1493 { 1494 /* Prepare machine details page if necessary: */ 1495 prepareDetailsPage(); 1496 1497 /* Prepare machine details: */ 1498 prepareDetails(machines); 1499 1500 /* Select corresponding widget: */ 1501 setCurrentIndex(indexOf(m_pScrollArea)); 1502 } 1503 1504 void UIDetailsPagePrivate::setText(const QString &aText) 1505 { 1506 /* Prepare text page if necessary: */ 1507 prepareTextPage(); 1508 1509 /* Assign corresponding text: */ 1510 m_pText->setText(aText); 1511 1512 /* Select corresponding widget: */ 1513 setCurrentIndex(indexOf(m_pText)); 1514 } 1515 1516 void UIDetailsPagePrivate::setErrorText(const QString &aText) 1517 { 1518 /* Prepare error page if necessary: */ 1519 prepareErrorPage(); 1520 1521 /* Assign corresponding error: */ 1522 m_pErrText->setText(aText); 1523 1524 /* Select corresponding widget: */ 1525 setCurrentIndex(indexOf(m_pErrBox)); 1526 } 1527 1528 void UIDetailsPagePrivate::retranslateUi() 1529 { 1530 /* Translate context menu actions: */ 1531 { 1532 if (m_actions.contains(Section_General)) 1533 m_actions[Section_General]->setText(tr("General", "details report")); 1534 if (m_actions.contains(Section_System)) 1535 m_actions[Section_System]->setText(tr("System", "details report")); 1536 if (m_actions.contains(Section_Preview)) 1537 m_actions[Section_Preview]->setText(tr("Preview", "details report")); 1538 if (m_actions.contains(Section_Display)) 1539 m_actions[Section_Display]->setText(tr("Display", "details report")); 1540 if (m_actions.contains(Section_Storage)) 1541 m_actions[Section_Storage]->setText(tr("Storage", "details report")); 1542 if (m_actions.contains(Section_Audio)) 1543 m_actions[Section_Audio]->setText(tr("Audio", "details report")); 1544 if (m_actions.contains(Section_Network)) 1545 m_actions[Section_Network]->setText(tr("Network", "details report")); 1546 if (m_actions.contains(Section_Serial)) 1547 m_actions[Section_Serial]->setText(tr("Serial Ports", "details report")); 1548 #ifdef VBOX_WITH_PARALLEL_PORTS 1549 if (m_actions.contains(Section_Parallel)) 1550 m_actions[Section_Parallel]->setText(tr("Parallel Ports", "details report")); 1551 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1552 if (m_actions.contains(Section_USB)) 1553 m_actions[Section_USB]->setText(tr("USB", "details report")); 1554 if (m_actions.contains(Section_SharedFolders)) 1555 m_actions[Section_SharedFolders]->setText(tr("Shared Folders", "details report")); 1556 if (m_actions.contains(Section_Description)) 1557 m_actions[Section_Description]->setText(tr("Description", "details report")); 1558 } 1559 1560 /* Translate error-label text: */ 1561 if (m_pErrLabel) 1562 m_pErrLabel->setText(tr("The selected virtual machine is <i>inaccessible</i>. " 1563 "Please inspect the error message shown below and press the " 1564 "<b>Refresh</b> button if you want to repeat the accessibility check:")); 1565 1566 /* Translate refresh button & action text: */ 1567 if (m_pRefreshAction && m_pRefreshButton) 1568 { 1569 m_pRefreshButton->setText(m_pRefreshAction->text()); 1570 m_pRefreshButton->setIcon(m_pRefreshAction->icon()); 1571 m_pRefreshButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1572 } 1573 } 1574 1575 void UIDetailsPagePrivate::prepareDetails(const QList<CMachine> &machines) 1576 { 1577 /* Was machine count changed? */ 1578 bool fCountChanged = m_cMachineCount != machines.size(); 1579 1580 /* Do we need to recreate details? */ 1581 if (fCountChanged) 1582 { 1583 /* Get new machine count: */ 1584 m_cMachineCount = machines.size(); 1585 1586 /* Delete current details if exists:*/ 1587 if (m_pDetails) 1588 delete m_pDetails; 1589 1590 /* Create and configure new details: */ 1591 m_pDetails = new UIDetails(this); 1592 m_pScrollArea->setWidget(m_pDetails); 1593 } 1594 1595 /* Assign new machine array for the details: */ 1596 m_pDetails->setMachines(machines); 1597 } 1598 1599 void UIDetailsPagePrivate::prepareDetailsPage() 1413 1600 { 1414 1601 if (m_pScrollArea) … … 1486 1673 } 1487 1674 1488 void UIDetailsPagePrivate::cleanupDetails ()1675 void UIDetailsPagePrivate::cleanupDetailsPage() 1489 1676 { 1490 1677 if (!m_pScrollArea) … … 1498 1685 1499 1686 /* Process only existing sections: */ 1500 if (!m_ sections.contains(section))1687 if (!m_pDetails->sections().contains(section)) 1501 1688 continue; 1502 1689 … … 1575 1762 1576 1763 retranslateUi(); 1577 }1578 1579 /**1580 * Return a text summary of the properties of a generic network adapter1581 */1582 /* static */1583 QString UIDetailsPagePrivate::summarizeGenericProperties(const CNetworkAdapter &adapter)1584 {1585 QVector<QString> names;1586 QVector<QString> props;1587 props = adapter.GetProperties(QString(), names);1588 QString strResult;1589 for (int i = 0; i < names.size(); ++i)1590 {1591 strResult += names[i] + "=" + props[i];1592 if (i < names.size() - 1)1593 strResult += ", ";1594 }1595 return strResult;1596 1764 } 1597 1765
Note:
See TracChangeset
for help on using the changeset viewer.