Changeset 48086 in vbox
- Timestamp:
- Aug 27, 2013 3:12:31 PM (11 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.cpp
r47998 r48086 35 35 #include <QUrl> 36 36 37 /* GUI includes */37 /* GUI includes: */ 38 38 #include "VBoxGlobal.h" 39 39 #include "UIMediumManager.h" 40 //#include "UIWizardNewVD.h"41 40 #include "UIWizardCloneVD.h" 42 41 #include "UIMessageCenter.h" … … 54 53 #include "CMediumAttachment.h" 55 54 55 # ifdef Q_WS_MAC 56 # include "UIWindowMenuManager.h" 57 # endif /* Q_WS_MAC */ 58 56 59 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 57 60 58 #ifdef Q_WS_MAC 59 # include "UIWindowMenuManager.h" 60 #endif /* Q_WS_MAC */ 61 62 class AddVDMUrlsEvent: public QEvent 61 class UIMediumItem : public QTreeWidgetItem 63 62 { 64 63 public: 65 64 66 AddVDMUrlsEvent (const QList <QUrl> &aUrls)67 : QEvent (static_cast <QEvent::Type> (AddVDMUrlsEventType))68 , mUrls (aUrls)69 {}70 71 const QList <QUrl> &urls() const { return mUrls; }72 73 private:74 75 const QList <QUrl> mUrls;76 };77 78 class MediaItem : public QTreeWidgetItem79 {80 public:81 82 65 enum { MediaItemType = QTreeWidgetItem::UserType + 1 }; 83 66 84 MediaItem (MediaItem *aParent, const UIMedium &aMedium, const UIMediumManager *aManager)67 UIMediumItem (UIMediumItem *aParent, const UIMedium &aMedium, const UIMediumManager *aManager) 85 68 : QTreeWidgetItem (aParent, MediaItemType) 86 69 , mMedium (aMedium) … … 88 71 { refresh(); } 89 72 90 MediaItem (QTreeWidget *aParent, const UIMedium &aMedium, const UIMediumManager *aManager)73 UIMediumItem (QTreeWidget *aParent, const UIMedium &aMedium, const UIMediumManager *aManager) 91 74 : QTreeWidgetItem (aParent, MediaItemType) 92 75 , mMedium (aMedium) … … 110 93 UIMediumType type() const { return mMedium.type(); } 111 94 112 KMediumState state() const { return mMedium.state (!mManager->showDiffs()); }95 KMediumState state() const { return mMedium.state(); } 113 96 114 97 QString id() const { return mMedium.id(); } 115 98 116 QString location() const { return mMedium.location (!mManager->showDiffs()); }117 118 QString hardDiskFormat() const { return mMedium.hardDiskFormat (!mManager->showDiffs()); }119 QString hardDiskType() const { return mMedium.hardDiskType (!mManager->showDiffs()); }99 QString location() const { return mMedium.location(); } 100 101 QString hardDiskFormat() const { return mMedium.hardDiskFormat(); } 102 QString hardDiskType() const { return mMedium.hardDiskType(); } 120 103 121 104 QString details() const { return mMedium.storageDetails(); } 122 105 123 QString usage() const { return mMedium.usage (!mManager->showDiffs()); }124 125 QString toolTip() const { return mMedium.toolTip (!mManager->showDiffs(), mManager->inAttachMode()); }106 QString usage() const { return mMedium.usage(); } 107 108 QString toolTip() const { return mMedium.toolTip(); } 126 109 127 110 bool isUsed() const { return mMedium.isUsed(); } … … 141 124 { 142 125 /* Fill in columns */ 143 setIcon (0, mMedium.icon (!mManager->showDiffs(), mManager->inAttachMode()));126 setIcon (0, mMedium.icon()); 144 127 /* Set the text */ 145 setText (0, mMedium.name (!mManager->showDiffs()));146 setText (1, mMedium.logicalSize (!mManager->showDiffs()));147 setText (2, mMedium.size (!mManager->showDiffs()));128 setText (0, mMedium.name()); 129 setText (1, mMedium.logicalSize()); 130 setText (2, mMedium.size()); 148 131 /* All columns get the same tooltip */ 149 QString tt = mMedium.toolTip (!mManager->showDiffs());132 QString tt = mMedium.toolTip(); 150 133 for (int i = 0; i < treeWidget()->columnCount(); ++ i) 151 134 setToolTip (i, tt); … … 163 146 : QTreeWidgetItemIterator (aTree) {} 164 147 165 MediaItem* operator*()148 UIMediumItem* operator*() 166 149 { 167 150 QTreeWidgetItem *item = QTreeWidgetItemIterator::operator*(); 168 return item && item->type() == MediaItem::MediaItemType ?169 static_cast < MediaItem*> (item) : 0;151 return item && item->type() == UIMediumItem::MediaItemType ? 152 static_cast <UIMediumItem*> (item) : 0; 170 153 } 171 154 … … 186 169 { 187 170 mText = new QLabel (this); 188 m ProgressBar = new QProgressBar (this);189 m ProgressBar->setTextVisible (false);171 m_pProgressBar = new QProgressBar (this); 172 m_pProgressBar->setTextVisible (false); 190 173 191 174 QHBoxLayout *layout = new QHBoxLayout (this); 192 175 layout->setContentsMargins(0, 0, 0, 0); 193 176 layout->addWidget (mText); 194 layout->addWidget (m ProgressBar);177 layout->addWidget (m_pProgressBar); 195 178 } 196 179 197 180 void setText (const QString &aText) { mText->setText (aText); } 198 void setValue (int aValue) { m ProgressBar->setValue (aValue); }199 void setMaximum (int aValue) { m ProgressBar->setMaximum (aValue); }200 201 int value() const { return m ProgressBar->value(); }181 void setValue (int aValue) { m_pProgressBar->setValue (aValue); } 182 void setMaximum (int aValue) { m_pProgressBar->setMaximum (aValue); } 183 184 int value() const { return m_pProgressBar->value(); } 202 185 203 186 private: 204 187 205 188 QLabel *mText; 206 QProgressBar *m ProgressBar;189 QProgressBar *m_pProgressBar; 207 190 }; 208 191 209 192 210 UIMediumManager* UIMediumManager::mModelessDialog = 0; 211 212 UIMediumManager::UIMediumManager (QWidget *aParent /* = 0 */, Qt::WindowFlags aFlags /* = Qt::Dialog */) 213 : QIWithRetranslateUI2 <QIMainDialog> (aParent, aFlags) 214 , mType (UIMediumType_Invalid) 215 , mShowDiffs (true) 216 , mSetupMode (false) 217 { 218 /* Apply UI decorations */ 219 Ui::UIMediumManager::setupUi (this); 220 221 /* No need to count that window as important for application, 222 * it will NOT be taken into account when other top-level windows will be closed: */ 193 /* static */ 194 UIMediumManager* UIMediumManager::m_spInstance = 0; 195 UIMediumManager* UIMediumManager::instance() { return m_spInstance; } 196 197 UIMediumManager::UIMediumManager(QWidget *pCenterWidget, bool fRefresh /*= true*/) 198 : QIWithRetranslateUI2<QIMainDialog>(0, Qt::Dialog) 199 , m_pCenterWidget(pCenterWidget) 200 , m_fRefresh(fRefresh) 201 , m_fInaccessibleHD(false) 202 , m_fInaccessibleCD(false) 203 , m_fInaccessibleFD(false) 204 , m_iconHD(UIIconPool::iconSet(":/hd_16px.png", ":/hd_disabled_16px.png")) 205 , m_iconCD(UIIconPool::iconSet(":/cd_16px.png", ":/cd_disabled_16px.png")) 206 , m_iconFD(UIIconPool::iconSet(":/fd_16px.png", ":/fd_disabled_16px.png")) 207 { 208 /* Prepare: */ 209 prepare(); 210 } 211 212 UIMediumManager::~UIMediumManager() 213 { 214 /* Cleanup: */ 215 cleanup(); 216 217 /* Cleanup instance: */ 218 m_spInstance = 0; 219 } 220 221 /* static */ 222 void UIMediumManager::showModeless(QWidget *pCenterWidget /*= 0*/, bool fRefresh /*= true*/) 223 { 224 /* Prepare instance if not prepared: */ 225 if (!m_spInstance) 226 m_spInstance = new UIMediumManager(pCenterWidget, fRefresh); 227 228 /* Show instance: */ 229 m_spInstance->show(); 230 m_spInstance->setWindowState(m_spInstance->windowState() & ~Qt::WindowMinimized); 231 m_spInstance->activateWindow(); 232 } 233 234 void UIMediumManager::refreshAll() 235 { 236 // TODO (Planned to 4.3.release by Dsen) 237 // Currently we just restarting medium-enumeration which is *very* expensive. 238 // To make it proper way, we have to invalidate mediums which were known as *related* 239 // to machine who's event called for *full-refresh* and start medium-enumeration. 240 // But medium-enumeration itself should update *only* invalidated mediums. 241 vboxGlobal().startEnumeratingMedia(); 242 } 243 244 void UIMediumManager::sltHandleMediumAdded(const UIMedium &medium) 245 { 246 /* Ignore non-interesting mediums: */ 247 if ((medium.isNull()) || (medium.isHostDrive())) 248 return; 249 250 /* Ignore mediums (and their children) which are 251 * marked as hidden or attached to hidden machines only: */ 252 if (isMediumAttachedToHiddenMachinesOnly(medium)) 253 return; 254 255 /* Prepare medium-item: */ 256 UIMediumItem *pMediumItem = 0; 257 switch (medium.type()) 258 { 259 case UIMediumType_HardDisk: 260 { 261 pMediumItem = createHardDiskItem(mTwHD, medium); 262 AssertReturnVoid(pMediumItem); 263 if (pMediumItem->id() == m_strSelectedIdHD) 264 { 265 setCurrentItem(mTwHD, pMediumItem); 266 m_strSelectedIdHD = QString(); 267 } 268 break; 269 } 270 case UIMediumType_DVD: 271 { 272 pMediumItem = new UIMediumItem(mTwCD, medium, this); 273 AssertReturnVoid(pMediumItem); 274 if (pMediumItem->id() == m_strSelectedIdCD) 275 { 276 setCurrentItem(mTwCD, pMediumItem); 277 m_strSelectedIdCD = QString(); 278 } 279 break; 280 } 281 case UIMediumType_Floppy: 282 { 283 pMediumItem = new UIMediumItem(mTwFD, medium, this); 284 AssertReturnVoid(pMediumItem); 285 if (pMediumItem->id() == m_strSelectedIdFD) 286 { 287 setCurrentItem(mTwFD, pMediumItem); 288 m_strSelectedIdFD = QString(); 289 } 290 break; 291 } 292 default: AssertFailed(); 293 } 294 AssertPtrReturnVoid(pMediumItem); 295 296 /* Update tab-icons: */ 297 updateTabIcons(pMediumItem, ItemAction_Added); 298 299 /* If the media enumeration process is not started we have to select the 300 * newly added item as the current one for the case of new image was added or created */ 301 if (!vboxGlobal().isMediaEnumerationStarted()) 302 setCurrentItem(treeWidget(medium.type()), pMediumItem); 303 304 /* Update stuff if that was current-item added: */ 305 if (pMediumItem == currentTreeWidget()->currentItem()) 306 sltHandleCurrentItemChanged(pMediumItem); 307 } 308 309 void UIMediumManager::sltHandleMediumUpdated(const UIMedium &medium) 310 { 311 /* Ignore non-interesting mediums: */ 312 if ((medium.isNull()) || (medium.isHostDrive())) 313 return; 314 315 /* Ignore mediums (and their children) which are 316 * marked as hidden or attached to hidden machines only: */ 317 if (isMediumAttachedToHiddenMachinesOnly(medium)) 318 return; 319 320 /* Prepare medium-item: */ 321 UIMediumItem *pMediumItem = 0; 322 switch (medium.type()) 323 { 324 case UIMediumType_HardDisk: pMediumItem = searchItem(mTwHD, medium.id()); break; 325 case UIMediumType_DVD: pMediumItem = searchItem(mTwCD, medium.id()); break; 326 case UIMediumType_Floppy: pMediumItem = searchItem(mTwFD, medium.id()); break; 327 default: AssertFailed(); 328 } 329 AssertPtrReturnVoid(pMediumItem); 330 331 /* Update medium-item: */ 332 pMediumItem->setMedium(medium); 333 334 /* Update tab-icons: */ 335 updateTabIcons(pMediumItem, ItemAction_Updated); 336 337 /* Update stuff if that was current-item updated: */ 338 if (pMediumItem == currentTreeWidget()->currentItem()) 339 sltHandleCurrentItemChanged(pMediumItem); 340 } 341 342 void UIMediumManager::sltHandleMediumRemoved(UIMediumType type, const QString &strId) 343 { 344 /* Get tree/item: */ 345 QTreeWidget *pTree = treeWidget(type); 346 UIMediumItem *pMediumItem = toMediumItem(searchItem(pTree, strId)); 347 if (!pMediumItem) 348 return; 349 350 /* Update tab-icons: */ 351 updateTabIcons(pMediumItem, ItemAction_Removed); 352 353 /* We need to silently delete item without selecting 354 * the new one because of complex selection mechanism 355 * which could provoke a segfault choosing the new 356 * one item during last item deletion routine. So blocking 357 * the tree-view for the time of item removing. */ 358 pTree->blockSignals(true); 359 delete pMediumItem; 360 pTree->blockSignals(false); 361 362 /* Set new current-item: */ 363 setCurrentItem(pTree, pTree->currentItem()); 364 } 365 366 void UIMediumManager::sltHandleMediumEnumerationStart() 367 { 368 /* Reset inaccessibility flags: */ 369 m_fInaccessibleHD = 370 m_fInaccessibleCD = 371 m_fInaccessibleFD = false; 372 373 /* Load default tab-widget icons: */ 374 mTabWidget->setTabIcon(HDTab, m_iconHD); 375 mTabWidget->setTabIcon(CDTab, m_iconCD); 376 mTabWidget->setTabIcon(FDTab, m_iconFD); 377 378 /* Load current mediums: */ 379 const VBoxMediaList &mediums = vboxGlobal().currentMediaList(); 380 prepareToRefresh(mediums.size()); 381 VBoxMediaList::const_iterator it; 382 for (it = mediums.begin(); it != mediums.end(); ++it) 383 sltHandleMediumAdded(*it); 384 385 /* Select the first item to be the current one 386 * if the previous saved item was not selected yet. */ 387 if (!mTwHD->currentItem()) 388 if (QTreeWidgetItem *pItem = mTwHD->topLevelItem(0)) 389 setCurrentItem(mTwHD, pItem); 390 if (!mTwCD->currentItem()) 391 if (QTreeWidgetItem *pItem = mTwCD->topLevelItem(0)) 392 setCurrentItem(mTwCD, pItem); 393 if (!mTwFD->currentItem()) 394 if (QTreeWidgetItem *pItem = mTwFD->topLevelItem(0)) 395 setCurrentItem(mTwFD, pItem); 396 397 /* Update current tab: */ 398 sltHandleCurrentTabChanged(); 399 } 400 401 void UIMediumManager::sltHandleMediumEnumerated(const UIMedium &medium) 402 { 403 /* Handle medium-update: */ 404 sltHandleMediumUpdated(medium); 405 406 /* Advance progress-bar: */ 407 m_pProgressBar->setValue(m_pProgressBar->value() + 1); 408 } 409 410 void UIMediumManager::sltHandleMediumEnumerationFinish() 411 { 412 /* Hide progress-bar: */ 413 m_pProgressBar->hide(); 414 415 /* Enable 'refresh' action: */ 416 m_pActionRefresh->setEnabled(true); 417 418 /* Unset 'busy' cursor: */ 419 unsetCursor(); 420 421 /* Update current tab: */ 422 sltHandleCurrentTabChanged(); 423 } 424 425 void UIMediumManager::sltCopyMedium() 426 { 427 /* Get current-item: */ 428 UIMediumItem *pMediumItem = toMediumItem(currentTreeWidget()->currentItem()); 429 430 /* Show Clone VD wizard: */ 431 UISafePointerWizard pWizard = new UIWizardCloneVD(this, pMediumItem->medium().medium()); 432 pWizard->prepare(); 433 pWizard->exec(); 434 435 /* Delete if still exists: */ 436 if (pWizard) 437 delete pWizard; 438 } 439 440 void UIMediumManager::sltModifyMedium() 441 { 442 /* Get current-item: */ 443 UIMediumItem *pMediumItem = toMediumItem(currentTreeWidget()->currentItem()); 444 445 /* Show Modify VD dialog: */ 446 UISafePointerDialog pDialog = new UIMediumTypeChangeDialog(this, pMediumItem->id()); 447 if (pDialog->exec() == QDialog::Accepted) 448 { 449 /* Safe spot because if dialog is deleted inside ::exec() => 450 * returned result will be QDialog::Rejected. */ 451 pMediumItem->refreshAll(); 452 m_pTypePane->setText(pMediumItem->hardDiskType()); 453 } 454 455 /* Delete if still exists: */ 456 if (pDialog) 457 delete pDialog; 458 } 459 460 void UIMediumManager::sltRemoveMedium() 461 { 462 /* Get current medium-item: */ 463 UIMediumItem *pMediumItem = toMediumItem(currentTreeWidget()->currentItem()); 464 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null")); 465 466 /* Remember ID/type as they may get lost after the closure/deletion: */ 467 QString strId = pMediumItem->id(); 468 AssertReturnVoid(!strId.isNull()); 469 UIMediumType type = pMediumItem->type(); 470 471 /* Confirm medium removal: */ 472 if (!msgCenter().confirmMediumRemoval(pMediumItem->medium(), this)) 473 return; 474 475 /* Prepare result: */ 476 COMResult result; 477 switch (type) 478 { 479 case UIMediumType_HardDisk: 480 { 481 /* We don't want to try to delete inaccessible storage as it will most likely fail. 482 * Note that UIMessageCenter::confirmMediumRemoval() is aware of that and 483 * will give a corresponding hint. Therefore, once the code is changed below, 484 * the hint should be re-checked for validity. */ 485 bool fDeleteStorage = false; 486 qulonglong uCapability = 0; 487 QVector<KMediumFormatCapabilities> capabilities = pMediumItem->medium().medium().GetMediumFormat().GetCapabilities(); 488 foreach (KMediumFormatCapabilities capability, capabilities) 489 uCapability |= capability; 490 if (pMediumItem->state() != KMediumState_Inaccessible && 491 uCapability & MediumFormatCapabilities_File) 492 { 493 int rc = msgCenter().confirmDeleteHardDiskStorage(pMediumItem->location(), this); 494 if (rc == AlertButton_Cancel) 495 return; 496 fDeleteStorage = rc == AlertButton_Choice1; 497 } 498 499 /* Get hard-disk: */ 500 CMedium hardDisk = pMediumItem->medium().medium(); 501 502 if (fDeleteStorage) 503 { 504 /* Remember hard-disk attributes: */ 505 QString strLocation = hardDisk.GetLocation(); 506 /* Prepare delete storage progress: */ 507 CProgress progress = hardDisk.DeleteStorage(); 508 if (hardDisk.isOk()) 509 { 510 /* Show delete storage progress: */ 511 msgCenter().showModalProgressDialog(progress, windowTitle(), ":/progress_media_delete_90px.png", this); 512 if (!progress.isOk() || progress.GetResultCode() != 0) 513 { 514 msgCenter().cannotDeleteHardDiskStorage(progress, strLocation, this); 515 return; 516 } 517 } 518 else 519 { 520 msgCenter().cannotDeleteHardDiskStorage(hardDisk, strLocation, this); 521 return; 522 } 523 } 524 525 /* Close hard-disk: */ 526 hardDisk.Close(); 527 result = hardDisk; 528 break; 529 } 530 case UIMediumType_DVD: 531 { 532 /* Get optical-disk: */ 533 CMedium image = pMediumItem->medium().medium(); 534 /* Close optical-disk: */ 535 image.Close(); 536 result = image; 537 break; 538 } 539 case UIMediumType_Floppy: 540 { 541 /* Get floppy-disk: */ 542 CMedium image = pMediumItem->medium().medium(); 543 /* Close floppy-disk: */ 544 image.Close(); 545 result = image; 546 break; 547 } 548 default: AssertFailedReturnVoid(); 549 } 550 551 /* Verify result: */ 552 if (result.isOk()) 553 vboxGlobal().removeMedium(type, strId); 554 else 555 msgCenter().cannotCloseMedium(pMediumItem->medium(), result, this); 556 } 557 558 void UIMediumManager::sltReleaseMedium() 559 { 560 /* Get current medium-item: */ 561 UIMediumItem *pMediumItem = toMediumItem(currentTreeWidget()->currentItem()); 562 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null")); 563 AssertReturnVoid(!pMediumItem->id().isNull()); 564 565 /* Refresh attached VM id list: */ 566 pMediumItem->refreshAll(); 567 const QList<QString> machineIds(pMediumItem->medium().curStateMachineIds()); 568 /* If the machine id list is empty: */ 569 if (machineIds.isEmpty()) 570 { 571 /* This may happen if medium was already released by a third party, 572 * update the details and silently return. */ 573 sltHandleCurrentItemChanged(pMediumItem); 574 return; 575 } 576 577 /* Gather usage list: */ 578 QStringList usage; 579 foreach (const QString &strMachineId, machineIds) 580 { 581 CMachine machine = m_vbox.FindMachine(strMachineId); 582 if (!m_vbox.isOk()) 583 continue; 584 usage << machine.GetName(); 585 } 586 AssertReturnVoid(!usage.isEmpty()); 587 588 /* Confirm release: */ 589 if (!msgCenter().confirmMediumRelease(pMediumItem->medium(), usage.join(", "), this)) 590 return; 591 592 /* Release: */ 593 foreach (const QString &strMachineId, machineIds) 594 if (!releaseMediumFrom(pMediumItem->medium(), strMachineId)) 595 break; 596 597 /* Update medium-item: */ 598 pMediumItem->refreshAll(); 599 /* Inform others about medium changes: */ 600 vboxGlobal().updateMedium(pMediumItem->medium()); 601 } 602 603 void UIMediumManager::sltHandleCurrentTabChanged() 604 { 605 /* Get current-tree: */ 606 QTreeWidget *pTree = currentTreeWidget(); 607 608 /* If other tree was focused previously, moving focus to new tree: */ 609 if (qobject_cast<QTreeWidget*>(focusWidget())) 610 pTree->setFocus(); 611 612 /* Update current tree-item: */ 613 sltHandleCurrentItemChanged(pTree->currentItem()); 614 } 615 616 void UIMediumManager::sltHandleCurrentItemChanged(QTreeWidgetItem *pItem, 617 QTreeWidgetItem *pPrevItem /* = 0 */) 618 { 619 /* Get medium-item: */ 620 UIMediumItem *pMediumItem = toMediumItem(pItem); 621 622 /* We have to make sure some item is always selected: */ 623 if (!pMediumItem && pPrevItem) 624 { 625 /* If the new item is 0, set the old item again. */ 626 UIMediumItem *pPrevMediumItem = toMediumItem(pPrevItem); 627 setCurrentItem(currentTreeWidget(), pPrevMediumItem); 628 } 629 630 if (pMediumItem) 631 { 632 /* Set the file for the proxy icon: */ 633 setFileForProxyIcon(pMediumItem->location()); 634 /* Ensures current item visible every time we are switching page: */ 635 pMediumItem->treeWidget()->scrollToItem(pMediumItem, QAbstractItemView::EnsureVisible); 636 } 637 638 /* Update action availability: */ 639 bool fNotInEnumeration = !vboxGlobal().isMediaEnumerationStarted(); 640 bool fActionEnabledCopy = currentTreeWidgetType() == UIMediumType_HardDisk && 641 fNotInEnumeration && pMediumItem && checkMediumFor (pMediumItem, Action_Copy); 642 bool fActionEnabledModify = currentTreeWidgetType() == UIMediumType_HardDisk && 643 fNotInEnumeration && pMediumItem && checkMediumFor (pMediumItem, Action_Modify); 644 bool fActionEnabledRemove = fNotInEnumeration && pMediumItem && checkMediumFor (pMediumItem, Action_Remove); 645 bool fActionEnabledRelease = pMediumItem && checkMediumFor (pMediumItem, Action_Release); 646 m_pActionCopy->setEnabled(fActionEnabledCopy); 647 m_pActionModify->setEnabled(fActionEnabledModify); 648 m_pActionRemove->setEnabled(fActionEnabledRemove); 649 m_pActionRelease->setEnabled(fActionEnabledRelease); 650 651 /* Update information-panes: */ 652 if (pMediumItem) 653 { 654 QString strDetails = pMediumItem->details(); 655 QString strUsage = pMediumItem->usage().isNull() ? 656 formatPaneText(QApplication::translate("VBoxMediaManagerDlg", "<i>Not Attached</i>"), false) : 657 formatPaneText(pMediumItem->usage()); 658 if (pMediumItem->treeWidget() == mTwHD) 659 { 660 m_pTypePane->setText(pMediumItem->hardDiskType()); 661 m_pLocationPane->setText(formatPaneText(pMediumItem->location(), true, "end")); 662 m_pFormatPane->setText(pMediumItem->hardDiskFormat()); 663 m_pDetailsPane->setText(strDetails); 664 m_pUsagePane->setText(strUsage); 665 } 666 else if (pMediumItem->treeWidget() == mTwCD) 667 { 668 mIpCD1->setText (formatPaneText (pMediumItem->location(), true, "end")); 669 mIpCD2->setText (strUsage); 670 } 671 else if (pMediumItem->treeWidget() == mTwFD) 672 { 673 mIpFD1->setText (formatPaneText (pMediumItem->location(), true, "end")); 674 mIpFD2->setText (strUsage); 675 } 676 } 677 else 678 clearInfoPanes(); 679 680 /* Enable/disable information-pane containers: */ 681 mHDContainer->setEnabled(pMediumItem); 682 mCDContainer->setEnabled(pMediumItem); 683 mFDContainer->setEnabled(pMediumItem); 684 } 685 686 void UIMediumManager::sltHandleDoubleClick() 687 { 688 /* Call for modify-action if hard-disk double-clicked: */ 689 if (currentTreeWidgetType() == UIMediumType_HardDisk) 690 sltModifyMedium(); 691 } 692 693 void UIMediumManager::sltHandleContextMenuCall(const QPoint &position) 694 { 695 /* Get surrent widget/item: */ 696 QTreeWidget *pTree = currentTreeWidget(); 697 QTreeWidgetItem *pItem = pTree->itemAt(position); 698 if (pItem) 699 { 700 /* Make sure the item is selected and current: */ 701 setCurrentItem(pTree, pItem); 702 /* Show context menu: */ 703 m_pContextMenu->exec(pTree->viewport()->mapToGlobal(position)); 704 } 705 } 706 707 void UIMediumManager::sltHandleMachineStateChanged(QString, KMachineState state) 708 { 709 switch (state) 710 { 711 case KMachineState_PoweredOff: 712 case KMachineState_Aborted: 713 case KMachineState_Saved: 714 case KMachineState_Teleported: 715 case KMachineState_Starting: 716 case KMachineState_Restoring: 717 case KMachineState_TeleportingIn: 718 { 719 refreshAll(); 720 break; 721 } 722 default: 723 break; 724 } 725 } 726 727 void UIMediumManager::sltMakeRequestForTableAdjustment() 728 { 729 /* We have to perform tables adjustment only after all the [auto]resize 730 * events processed for every column of corresponding table. */ 731 QTimer::singleShot(0, this, SLOT(sltPerformTablesAdjustment())); 732 } 733 734 void UIMediumManager::sltPerformTablesAdjustment() 735 { 736 /* Get all the tree-widgets: */ 737 QList<QITreeWidget*> trees; 738 trees << mTwHD; 739 trees << mTwCD; 740 trees << mTwFD; 741 742 /* Calculate deduction for every header: */ 743 QList<int> deductions; 744 foreach (QITreeWidget *pTree, trees) 745 { 746 int iDeduction = 0; 747 for (int iHeaderIndex = 1; iHeaderIndex < pTree->header()->count(); ++iHeaderIndex) 748 iDeduction += pTree->header()->sectionSize(iHeaderIndex); 749 deductions << iDeduction; 750 } 751 752 /* Adjust the table's first column: */ 753 for (int iTreeIndex = 0; iTreeIndex < trees.size(); ++iTreeIndex) 754 { 755 QITreeWidget *pTree = trees[iTreeIndex]; 756 int iSize0 = pTree->viewport()->width() - deductions[iTreeIndex]; 757 if (pTree->header()->sectionSize(0) != iSize0) 758 pTree->header()->resizeSection(0, iSize0); 759 } 760 } 761 762 void UIMediumManager::prepare() 763 { 764 /* Prepare this: */ 765 prepareThis(); 766 /* Prepare actions: */ 767 prepareActions(); 768 /* Prepare menu-bar: */ 769 prepareMenuBar(); 770 /* Prepare tool-bar: */ 771 prepareToolBar(); 772 /* Prepare context-menu: */ 773 prepareContextMenu(); 774 /* Prepare tab-widget: */ 775 preapreTabWidget(); 776 /* Prepare tree-widgets: */ 777 prepareTreeWidgets(); 778 /* Prepare information-panes: */ 779 prepareInformationPanes(); 780 /* Prepare button-box: */ 781 prepareButtonBox(); 782 /* Prepare progress-bar: */ 783 prepareProgressBar(); 784 785 /* Translate dialog: */ 786 retranslateUi(); 787 788 #ifdef Q_WS_MAC 789 /* Prepare Mac window-menu. 790 * Should go *after* translation! */ 791 prepareMacWindowMenu(); 792 #endif /* Q_WS_MAC */ 793 794 /* Center according passed widget: */ 795 centerAccording(m_pCenterWidget); 796 797 /* Populate content for tree-widgets: */ 798 populateTreeWidgets(); 799 } 800 801 void UIMediumManager::prepareThis() 802 { 803 /* Dialog should delete itself on 'close': */ 804 setAttribute(Qt::WA_DeleteOnClose); 805 806 /* And no need to count it as important for application. 807 * This way it will NOT be taken into account 808 * when other top-level windows will be closed: */ 223 809 setAttribute(Qt::WA_QuitOnClose, false); 224 810 225 /* Apply window icons */226 setWindowIcon(UIIconPool::iconSetFull(QSize (32, 32), QSize(16, 16),811 /* Apply window icons: */ 812 setWindowIcon(UIIconPool::iconSetFull(QSize(32, 32), QSize(16, 16), 227 813 ":/diskimage_32px.png", ":/diskimage_16px.png")); 228 814 229 mVBox = vboxGlobal().virtualBox(); 230 Assert (!mVBox.isNull()); 231 232 mHardDisksInaccessible = 233 mDVDImagesInaccessible = 234 mFloppyImagesInaccessible = false; 235 236 mHardDiskIcon = UIIconPool::iconSet(":/hd_16px.png", ":/hd_disabled_16px.png"); 237 mDVDImageIcon = UIIconPool::iconSet(":/cd_16px.png", ":/cd_disabled_16px.png"); 238 mFloppyImageIcon = UIIconPool::iconSet(":/fd_16px.png", ":/fd_disabled_16px.png"); 239 240 /* Setup tab-widget icons */ 241 mTabWidget->setTabIcon (HDTab, mHardDiskIcon); 242 mTabWidget->setTabIcon (CDTab, mDVDImageIcon); 243 mTabWidget->setTabIcon (FDTab, mFloppyImageIcon); 244 245 connect (mTabWidget, SIGNAL (currentChanged (int)), this, SLOT (processCurrentChanged (int))); 246 247 /* Setup the tree-widgets */ 248 mTwHD->sortItems (0, Qt::AscendingOrder); 249 mTwHD->setColumnCount(3); 250 mTwHD->header()->setResizeMode (0, QHeaderView::Fixed); 251 mTwHD->header()->setResizeMode (1, QHeaderView::ResizeToContents); 252 mTwHD->header()->setResizeMode (2, QHeaderView::ResizeToContents); 253 mTwHD->header()->setStretchLastSection (false); 254 mTwHD->setSortingEnabled (true); 255 mTwHD->installEventFilter (this); 256 connect (mTwHD, SIGNAL (currentItemChanged (QTreeWidgetItem *, QTreeWidgetItem *)), 257 this, SLOT (processCurrentChanged (QTreeWidgetItem *, QTreeWidgetItem *))); 258 connect (mTwHD, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), 259 this, SLOT (processDoubleClick (QTreeWidgetItem *, int))); 260 connect (mTwHD, SIGNAL (customContextMenuRequested (const QPoint &)), 261 this, SLOT (showContextMenu (const QPoint &))); 262 connect (mTwHD, SIGNAL (resized (const QSize &, const QSize &)), 263 this, SLOT (makeRequestForAdjustTable())); 264 connect (mTwHD->header(), SIGNAL (sectionResized (int, int, int)), 265 this, SLOT (makeRequestForAdjustTable())); 266 267 mTwCD->sortItems (0, Qt::AscendingOrder); 268 mTwCD->setColumnCount(2); 269 mTwCD->header()->setResizeMode (0, QHeaderView::Fixed); 270 mTwCD->header()->setResizeMode (1, QHeaderView::ResizeToContents); 271 mTwCD->header()->setStretchLastSection (false); 272 mTwCD->setSortingEnabled (true); 273 mTwCD->installEventFilter (this); 274 connect (mTwCD, SIGNAL (currentItemChanged (QTreeWidgetItem *, QTreeWidgetItem *)), 275 this, SLOT (processCurrentChanged (QTreeWidgetItem *, QTreeWidgetItem *))); 276 connect (mTwCD, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), 277 this, SLOT (processDoubleClick (QTreeWidgetItem *, int))); 278 connect (mTwCD, SIGNAL (customContextMenuRequested (const QPoint &)), 279 this, SLOT (showContextMenu (const QPoint &))); 280 connect (mTwCD, SIGNAL (resized (const QSize&, const QSize&)), 281 this, SLOT (makeRequestForAdjustTable())); 282 connect (mTwCD->header(), SIGNAL (sectionResized (int, int, int)), 283 this, SLOT (makeRequestForAdjustTable())); 284 285 mTwFD->sortItems (0, Qt::AscendingOrder); 286 mTwFD->setColumnCount(2); 287 mTwFD->header()->setResizeMode (0, QHeaderView::Fixed); 288 mTwFD->header()->setResizeMode (1, QHeaderView::ResizeToContents); 289 mTwFD->header()->setStretchLastSection (false); 290 mTwFD->setSortingEnabled (true); 291 mTwFD->installEventFilter (this); 292 connect (mTwFD, SIGNAL (currentItemChanged (QTreeWidgetItem *, QTreeWidgetItem *)), 293 this, SLOT (processCurrentChanged (QTreeWidgetItem *, QTreeWidgetItem *))); 294 connect (mTwFD, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)), 295 this, SLOT (processDoubleClick (QTreeWidgetItem *, int))); 296 connect (mTwFD, SIGNAL (customContextMenuRequested (const QPoint &)), 297 this, SLOT (showContextMenu (const QPoint &))); 298 connect (mTwFD, SIGNAL (resized (const QSize&, const QSize&)), 299 this, SLOT (makeRequestForAdjustTable())); 300 connect (mTwFD->header(), SIGNAL (sectionResized (int, int, int)), 301 this, SLOT (makeRequestForAdjustTable())); 302 303 /* Context menu composing */ 304 mActionsContextMenu = new QMenu (this); 305 306 mNewAction = new QAction (this); 307 mAddAction = new QAction (this); 308 mCopyAction = new QAction (this); 309 mModifyAction = new QAction (this); 310 mRemoveAction = new QAction (this); 311 mReleaseAction = new QAction (this); 312 mRefreshAction = new QAction (this); 313 314 connect (mNewAction, SIGNAL (triggered()), this, SLOT (doNewMedium())); 315 connect (mAddAction, SIGNAL (triggered()), this, SLOT (doAddMedium())); 316 connect (mCopyAction, SIGNAL (triggered()), this, SLOT (doCopyMedium())); 317 connect (mModifyAction, SIGNAL (triggered()), this, SLOT (doModifyMedium())); 318 connect (mRemoveAction, SIGNAL (triggered()), this, SLOT (doRemoveMedium())); 319 connect (mReleaseAction, SIGNAL (triggered()), this, SLOT (doReleaseMedium())); 320 connect (mRefreshAction, SIGNAL (triggered()), this, SLOT (refreshAll())); 321 322 mNewAction->setIcon(UIIconPool::iconSetFull ( 323 QSize (22, 22), QSize (16, 16), 324 ":/hd_new_22px.png", ":/hd_new_16px.png", 325 ":/hd_new_disabled_22px.png", ":/hd_new_disabled_16px.png")); 326 mAddAction->setIcon(UIIconPool::iconSetFull ( 327 QSize (22, 22), QSize (16, 16), 328 ":/hd_add_22px.png", ":/hd_add_16px.png", 329 ":/hd_add_disabled_22px.png", ":/hd_add_disabled_16px.png")); 330 mCopyAction->setIcon(UIIconPool::iconSetFull ( 331 QSize (22, 22), QSize (16, 16), 332 ":/hd_add_22px.png", ":/hd_add_16px.png", 333 ":/hd_add_disabled_22px.png", ":/hd_add_disabled_16px.png")); 334 mModifyAction->setIcon(UIIconPool::iconSetFull ( 335 QSize (22, 22), QSize (16, 16), 336 ":/hd_new_22px.png", ":/hd_new_16px.png", 337 ":/hd_new_disabled_22px.png", ":/hd_new_disabled_16px.png")); 338 mRemoveAction->setIcon(UIIconPool::iconSetFull ( 339 QSize (22, 22), QSize (16, 16), 340 ":/hd_remove_22px.png", ":/hd_remove_16px.png", 341 ":/hd_remove_disabled_22px.png", ":/hd_remove_disabled_16px.png")); 342 mReleaseAction->setIcon(UIIconPool::iconSetFull ( 343 QSize (22, 22), QSize (16, 16), 344 ":/hd_release_22px.png", ":/hd_release_16px.png", 345 ":/hd_release_disabled_22px.png", ":/hd_release_disabled_16px.png")); 346 mRefreshAction->setIcon(UIIconPool::iconSetFull ( 347 QSize (22, 22), QSize (16, 16), 348 ":/refresh_22px.png", ":/refresh_16px.png", 349 ":/refresh_disabled_22px.png", ":/refresh_disabled_16px.png")); 350 351 mActionsContextMenu->addAction (mCopyAction); 352 mActionsContextMenu->addAction (mModifyAction); 353 mActionsContextMenu->addAction (mRemoveAction); 354 mActionsContextMenu->addAction (mReleaseAction); 355 356 /* Toolbar composing */ 357 mToolBar = new UIToolBar (this); 358 mToolBar->setIconSize (QSize (22, 22)); 359 mToolBar->setToolButtonStyle (Qt::ToolButtonTextUnderIcon); 360 mToolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred); 361 362 QVBoxLayout *mainLayout = qobject_cast <QVBoxLayout*> (centralWidget()->layout()); 363 Assert (mainLayout); 364 #if MAC_LEOPARD_STYLE 365 /* Enable unified toolbars on Mac OS X. Available on Qt >= 4.3 */ 366 addToolBar (mToolBar); 367 mToolBar->setMacToolbar(); 368 /* No spacing/margin on the mac */ 369 mainLayout->setContentsMargins(0, 0, 0, 0); 370 mainLayout->insertSpacing (0, 10); 371 #else /* MAC_LEOPARD_STYLE */ 372 /* Add the toolbar */ 373 mainLayout->insertWidget (0, mToolBar); 374 /* Set spacing/margin like in the selector window */ 375 mainLayout->setSpacing (5); 376 mainLayout->setContentsMargins(5, 5, 5, 5); 377 #endif /* MAC_LEOPARD_STYLE */ 378 379 // mToolBar->addAction (mNewAction); 380 // mToolBar->addAction (mAddAction); 381 mToolBar->addAction (mCopyAction); 382 mToolBar->addAction (mModifyAction); 383 // mToolBar->addSeparator(); 384 mToolBar->addAction (mRemoveAction); 385 mToolBar->addAction (mReleaseAction); 386 // mToolBar->addSeparator(); 387 mToolBar->addAction (mRefreshAction); 388 389 /* Menu bar */ 390 mActionsMenu = menuBar()->addMenu (QString::null); 391 // mActionsMenu->addAction (mNewAction); 392 // mActionsMenu->addAction (mAddAction); 393 mActionsMenu->addAction (mCopyAction); 394 mActionsMenu->addAction (mModifyAction); 395 // mActionsMenu->addSeparator(); 396 mActionsMenu->addAction (mRemoveAction); 397 mActionsMenu->addAction (mReleaseAction); 398 // mActionsMenu->addSeparator(); 399 mActionsMenu->addAction (mRefreshAction); 400 401 /* Setup information pane */ 402 QList <QILabel*> paneList = findChildren <QILabel*>(); 403 foreach (QILabel *infoPane, paneList) 404 infoPane->setFullSizeSelection (true); 405 406 /* Enumeration progressbar creation */ 407 mProgressBar = new VBoxProgressBar (this); 408 /* Add to the dialog button box */ 409 mButtonBox->addExtraWidget (mProgressBar); 410 /* Default is invisible */ 411 mProgressBar->setVisible (false); 412 413 /* Set the default button */ 414 mButtonBox->button (QDialogButtonBox::Ok)->setDefault (true); 415 416 /* Connects for the button box */ 417 connect (mButtonBox, SIGNAL (accepted()), this, SLOT (accept())); 418 connect (mButtonBox, SIGNAL (rejected()), this, SLOT (reject())); 419 connect (mButtonBox, SIGNAL (helpRequested()), &msgCenter(), SLOT (sltShowHelpHelpDialog())); 420 } 421 422 UIMediumManager::~UIMediumManager() 423 { 424 #ifdef Q_WS_MAC 425 if (!mDoSelect) 426 { 427 UIWindowMenuManager::instance()->removeWindow(this); 428 UIWindowMenuManager::instance()->destroyMenu(this); 429 } 430 #endif /* Q_WS_MAC */ 431 delete mToolBar; 432 } 433 434 /** 435 * Sets up the dialog. 436 * 437 * @param aType Media type to display (either one type or all). 438 * @param aDoSelect Whether to enable the select action (OK button). 439 * @param aRefresh Whether to do a media refresh. 440 * @param aSessionMachine Session machine object if this dialog is opened for 441 * a machine from its settings dialog. 442 * @param aSelectId Which medium to make selected? (ignored when @a 443 * aType is UIMediumType_All) 444 * @param aShowDiffs @c true to show differencing hard disks initially 445 * (ignored if @a aSessionMachine is null assuming 446 * @c true). 447 * @param aUsedMediaIds List containing IDs of mediums used in other 448 * attachments to restrict selection. 449 */ 450 void UIMediumManager::setup (UIMediumType aType, bool aDoSelect, 451 bool aRefresh /* = true */, 452 const CMachine &aSessionMachine /* = CMachine() */, 453 const QString &aSelectId /* = QString() */, 454 bool aShowDiffs /* = true */, 455 const QStringList &aUsedMediaIds /* = QStringList() */) 456 { 457 mSetupMode = true; 458 459 mType = aType; 460 461 mDoSelect = aDoSelect; 462 463 mSessionMachine = aSessionMachine; 464 mSessionMachineId = mSessionMachine.isNull() ? QString::null : mSessionMachine.GetId(); 465 mShowDiffs = mSessionMachine.isNull() ? true : aShowDiffs; 466 467 switch (aType) 468 { 469 case UIMediumType_HardDisk: mHDSelectedId = aSelectId; break; 470 case UIMediumType_DVD: mCDSelectedId = aSelectId; break; 471 case UIMediumType_Floppy: mFDSelectedId = aSelectId; break; 472 case UIMediumType_All: break; 473 default: 474 AssertFailedReturnVoid(); 475 } 476 477 mTabWidget->setTabEnabled (HDTab, 478 aType == UIMediumType_All || 479 aType == UIMediumType_HardDisk); 480 mTabWidget->setTabEnabled (CDTab, 481 aType == UIMediumType_All || 482 aType == UIMediumType_DVD); 483 mTabWidget->setTabEnabled (FDTab, 484 aType == UIMediumType_All || 485 aType == UIMediumType_Floppy); 486 487 mDoSelect = aDoSelect; 488 mUsedMediaIds = aUsedMediaIds; 489 490 mButtonBox->button (QDialogButtonBox::Cancel)->setVisible (mDoSelect); 815 /* Apply UI decorations: */ 816 Ui::UIMediumManager::setupUi(this); 817 818 /* Prepare some global stuff: */ 819 m_vbox = vboxGlobal().virtualBox(); 820 Assert(!m_vbox.isNull()); 821 822 /* Configure medium-processing connections: */ 823 connect(&vboxGlobal(), SIGNAL(mediumAdded(const UIMedium&)), 824 this, SLOT(sltHandleMediumAdded(const UIMedium&))); 825 connect(&vboxGlobal(), SIGNAL(mediumUpdated(const UIMedium&)), 826 this, SLOT(sltHandleMediumUpdated(const UIMedium&))); 827 connect(&vboxGlobal(), SIGNAL(mediumRemoved(UIMediumType, const QString&)), 828 this, SLOT(sltHandleMediumRemoved(UIMediumType, const QString&))); 491 829 492 830 /* Configure medium-enumeration connections: */ … … 496 834 this, SLOT(sltHandleMediumEnumerated(const UIMedium&))); 497 835 connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished(const VBoxMediaList&)), 498 this, SLOT(sltHandleMediumEnumerationFinish(const VBoxMediaList&))); 499 500 /* Listen to "media add" signals */ 501 connect (&vboxGlobal(), SIGNAL (mediumAdded (const UIMedium &)), 502 this, SLOT (mediumAdded (const UIMedium &))); 503 /* Listen to "media update" signals */ 504 connect (&vboxGlobal(), SIGNAL (mediumUpdated (const UIMedium &)), 505 this, SLOT (mediumUpdated (const UIMedium &))); 506 /* Listen to "media remove" signals */ 507 connect (&vboxGlobal(), SIGNAL (mediumRemoved (UIMediumType, const QString &)), 508 this, SLOT (mediumRemoved (UIMediumType, const QString &))); 509 510 if (aRefresh && !vboxGlobal().isMediaEnumerationStarted()) 836 this, SLOT(sltHandleMediumEnumerationFinish())); 837 838 /* Configure Main event connections: */ 839 connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), this, SLOT(refreshAll())); 840 connect(gVBoxEvents, SIGNAL(sigMachineRegistered(QString, bool)), this, SLOT(refreshAll())); 841 connect(gVBoxEvents, SIGNAL(sigSnapshotChange(QString, QString)), this, SLOT(refreshAll())); 842 } 843 844 void UIMediumManager::prepareActions() 845 { 846 /* Create copy-action: */ 847 m_pActionCopy = new QAction(this); 848 { 849 /* Configure copy-action: */ 850 m_pActionCopy->setShortcut(QKeySequence("Ctrl+O")); 851 m_pActionCopy->setIcon(UIIconPool::iconSetFull(QSize(22, 22), QSize(16, 16), 852 ":/hd_add_22px.png", ":/hd_add_16px.png", 853 ":/hd_add_disabled_22px.png", ":/hd_add_disabled_16px.png")); 854 connect(m_pActionCopy, SIGNAL(triggered()), this, SLOT(sltCopyMedium())); 855 } 856 857 /* Create modify-action: */ 858 m_pActionModify = new QAction(this); 859 { 860 /* Configure modify-action: */ 861 m_pActionModify->setShortcut(QKeySequence("Ctrl+Space")); 862 m_pActionModify->setIcon(UIIconPool::iconSetFull(QSize(22, 22), QSize(16, 16), 863 ":/hd_new_22px.png", ":/hd_new_16px.png", 864 ":/hd_new_disabled_22px.png", ":/hd_new_disabled_16px.png")); 865 connect(m_pActionModify, SIGNAL(triggered()), this, SLOT(sltModifyMedium())); 866 } 867 868 /* Create remove-action: */ 869 m_pActionRemove = new QAction(this); 870 { 871 /* Configure remove-action: */ 872 m_pActionRemove->setShortcut(QKeySequence(QKeySequence::Delete)); 873 m_pActionRemove->setIcon(UIIconPool::iconSetFull(QSize(22, 22), QSize(16, 16), 874 ":/hd_remove_22px.png", ":/hd_remove_16px.png", 875 ":/hd_remove_disabled_22px.png", ":/hd_remove_disabled_16px.png")); 876 connect(m_pActionRemove, SIGNAL(triggered()), this, SLOT(sltRemoveMedium())); 877 } 878 879 /* Create release-action: */ 880 m_pActionRelease = new QAction(this); 881 { 882 /* Configure release-action: */ 883 m_pActionRelease->setShortcut(QKeySequence("Ctrl+L")); 884 m_pActionRelease->setIcon(UIIconPool::iconSetFull(QSize(22, 22), QSize(16, 16), 885 ":/hd_release_22px.png", ":/hd_release_16px.png", 886 ":/hd_release_disabled_22px.png", ":/hd_release_disabled_16px.png")); 887 connect(m_pActionRelease, SIGNAL(triggered()), this, SLOT(sltReleaseMedium())); 888 } 889 890 /* Create refresh-action: */ 891 m_pActionRefresh = new QAction(this); 892 { 893 /* Configure refresh-action: */ 894 m_pActionRefresh->setShortcut(QKeySequence(QKeySequence::Refresh)); 895 m_pActionRefresh->setIcon(UIIconPool::iconSetFull(QSize(22, 22), QSize(16, 16), 896 ":/refresh_22px.png", ":/refresh_16px.png", 897 ":/refresh_disabled_22px.png", ":/refresh_disabled_16px.png")); 898 connect(m_pActionRefresh, SIGNAL(triggered()), this, SLOT(refreshAll())); 899 } 900 } 901 902 void UIMediumManager::prepareMenuBar() 903 { 904 /* Create actions-menu for menu-bar: */ 905 m_pMenu = menuBar()->addMenu(QString()); 906 { 907 /* Configure menu-bar menu: */ 908 m_pMenu->addAction(m_pActionCopy); 909 m_pMenu->addAction(m_pActionModify); 910 m_pMenu->addAction(m_pActionRemove); 911 m_pMenu->addAction(m_pActionRelease); 912 m_pMenu->addAction(m_pActionRefresh); 913 } 914 } 915 916 void UIMediumManager::prepareToolBar() 917 { 918 /* Create tool-bar: */ 919 mToolBar = new UIToolBar(this); 920 { 921 /* Configure tool-bar: */ 922 mToolBar->setIconSize(QSize(22, 22)); 923 mToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 924 mToolBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); 925 /* Add tool-bar actions: */ 926 mToolBar->addAction(m_pActionCopy); 927 mToolBar->addAction(m_pActionModify); 928 mToolBar->addAction(m_pActionRemove); 929 mToolBar->addAction(m_pActionRelease); 930 mToolBar->addAction(m_pActionRefresh); 931 /* Integrate tool-bar into dialog: */ 932 QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>(centralWidget()->layout()); 933 Assert(pMainLayout); 934 #if MAC_LEOPARD_STYLE 935 /* Enable unified tool-bars on Mac OS X. Available on Qt >= 4.3: */ 936 addToolBar(mToolBar); 937 mToolBar->setMacToolbar(); 938 /* No spacing/margin on the Mac: */ 939 pMainLayout->setContentsMargins(0, 0, 0, 0); 940 pMainLayout->insertSpacing(0, 10); 941 #else /* MAC_LEOPARD_STYLE */ 942 /* Add the tool-bar: */ 943 pMainLayout->insertWidget(0, mToolBar); 944 /* Set spacing/margin like in the selector window: */ 945 pMainLayout->setSpacing(5); 946 pMainLayout->setContentsMargins(5, 5, 5, 5); 947 #endif /* MAC_LEOPARD_STYLE */ 948 } 949 } 950 951 void UIMediumManager::prepareContextMenu() 952 { 953 /* Create context-menu: */ 954 m_pContextMenu = new QMenu(this); 955 { 956 /* Configure contex-menu: */ 957 m_pContextMenu->addAction(m_pActionCopy); 958 m_pContextMenu->addAction(m_pActionModify); 959 m_pContextMenu->addAction(m_pActionRemove); 960 m_pContextMenu->addAction(m_pActionRelease); 961 } 962 } 963 964 void UIMediumManager::preapreTabWidget() 965 { 966 /* Tab-widget created in .ui file. */ 967 { 968 /* Setup tab-widget: */ 969 mTabWidget->setFocusPolicy(Qt::TabFocus); 970 mTabWidget->setTabIcon(HDTab, m_iconHD); 971 mTabWidget->setTabIcon(CDTab, m_iconCD); 972 mTabWidget->setTabIcon(FDTab, m_iconFD); 973 connect(mTabWidget, SIGNAL(currentChanged(int)), this, SLOT(sltHandleCurrentTabChanged())); 974 } 975 } 976 977 void UIMediumManager::prepareTreeWidgets() 978 { 979 /* Prepare tree-widget HD: */ 980 prepareTreeWidgetHD(); 981 /* Prepare tree-widget CD: */ 982 prepareTreeWidgetCD(); 983 /* Prepare tree-widget FD: */ 984 prepareTreeWidgetFD(); 985 986 /* Focus current tree: */ 987 currentTreeWidget()->setFocus(); 988 } 989 990 void UIMediumManager::prepareTreeWidgetHD() 991 { 992 /* HD tree-widget created in .ui file. */ 993 { 994 /* Setup HD tree-widget: */ 995 mTwHD->setColumnCount(3); 996 mTwHD->sortItems(0, Qt::AscendingOrder); 997 mTwHD->header()->setResizeMode(0, QHeaderView::Fixed); 998 mTwHD->header()->setResizeMode(1, QHeaderView::ResizeToContents); 999 mTwHD->header()->setResizeMode(2, QHeaderView::ResizeToContents); 1000 mTwHD->header()->setStretchLastSection(false); 1001 mTwHD->setSortingEnabled(true); 1002 connect(mTwHD, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 1003 this, SLOT(sltHandleCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); 1004 connect(mTwHD, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 1005 this, SLOT(sltHandleDoubleClick())); 1006 connect(mTwHD, SIGNAL(customContextMenuRequested(const QPoint&)), 1007 this, SLOT(sltHandleContextMenuCall(const QPoint&))); 1008 connect(mTwHD, SIGNAL(resized(const QSize&, const QSize&)), 1009 this, SLOT(sltMakeRequestForTableAdjustment())); 1010 connect(mTwHD->header(), SIGNAL(sectionResized(int, int, int)), 1011 this, SLOT(sltMakeRequestForTableAdjustment())); 1012 } 1013 } 1014 1015 void UIMediumManager::prepareTreeWidgetCD() 1016 { 1017 /* CD tree-widget created in .ui file. */ 1018 { 1019 /* Setup CD tree-widget: */ 1020 mTwCD->setColumnCount(2); 1021 mTwCD->sortItems(0, Qt::AscendingOrder); 1022 mTwCD->header()->setResizeMode(0, QHeaderView::Fixed); 1023 mTwCD->header()->setResizeMode(1, QHeaderView::ResizeToContents); 1024 mTwCD->header()->setStretchLastSection(false); 1025 mTwCD->setSortingEnabled(true); 1026 connect(mTwCD, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 1027 this, SLOT(sltHandleCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); 1028 connect(mTwCD, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 1029 this, SLOT(sltHandleDoubleClick())); 1030 connect(mTwCD, SIGNAL(customContextMenuRequested(const QPoint&)), 1031 this, SLOT(sltHandleContextMenuCall(const QPoint&))); 1032 connect(mTwCD, SIGNAL(resized(const QSize&, const QSize&)), 1033 this, SLOT(sltMakeRequestForTableAdjustment())); 1034 connect(mTwCD->header(), SIGNAL(sectionResized(int, int, int)), 1035 this, SLOT(sltMakeRequestForTableAdjustment())); 1036 } 1037 } 1038 1039 void UIMediumManager::prepareTreeWidgetFD() 1040 { 1041 /* FD tree-widget created in .ui file. */ 1042 { 1043 /* Setup FD tree-widget: */ 1044 mTwFD->setColumnCount(2); 1045 mTwFD->sortItems(0, Qt::AscendingOrder); 1046 mTwFD->header()->setResizeMode(0, QHeaderView::Fixed); 1047 mTwFD->header()->setResizeMode(1, QHeaderView::ResizeToContents); 1048 mTwFD->header()->setStretchLastSection(false); 1049 mTwFD->setSortingEnabled(true); 1050 connect(mTwFD, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 1051 this, SLOT(sltHandleCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); 1052 connect(mTwFD, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), 1053 this, SLOT(sltHandleDoubleClick())); 1054 connect(mTwFD, SIGNAL(customContextMenuRequested(const QPoint&)), 1055 this, SLOT(sltHandleContextMenuCall(const QPoint&))); 1056 connect(mTwFD, SIGNAL(resized(const QSize&, const QSize&)), 1057 this, SLOT(sltMakeRequestForTableAdjustment())); 1058 connect(mTwFD->header(), SIGNAL(sectionResized(int, int, int)), 1059 this, SLOT(sltMakeRequestForTableAdjustment())); 1060 } 1061 } 1062 1063 void UIMediumManager::prepareInformationPanes() 1064 { 1065 /* Information-panes created in .ui file. */ 1066 { 1067 /* Configure information-panes: */ 1068 QList<QILabel*> panes = findChildren<QILabel*>(); 1069 foreach (QILabel *pPane, panes) 1070 pPane->setFullSizeSelection(true); 1071 } 1072 } 1073 1074 void UIMediumManager::prepareButtonBox() 1075 { 1076 /* Button-box created in .ui file. */ 1077 { 1078 /* Configure button-box: */ 1079 mButtonBox->button(QDialogButtonBox::Ok)->setDefault(true); 1080 connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 1081 connect(mButtonBox, SIGNAL(helpRequested()), &msgCenter(), SLOT(sltShowHelpHelpDialog())); 1082 } 1083 } 1084 1085 void UIMediumManager::prepareProgressBar() 1086 { 1087 /* Create progress-bar: */ 1088 m_pProgressBar = new VBoxProgressBar(this); 1089 { 1090 /* Hidden by default: */ 1091 m_pProgressBar->hide(); 1092 /* Integrate to the button-box: */ 1093 mButtonBox->addExtraWidget(m_pProgressBar); 1094 } 1095 } 1096 1097 #ifdef Q_WS_MAC 1098 void UIMediumManager::prepareMacWindowMenu() 1099 { 1100 /* Create window-menu for menu-bar: */ 1101 menuBar()->addMenu(UIWindowMenuManager::instance()->createMenu(this)); 1102 UIWindowMenuManager::instance()->addWindow(this); 1103 } 1104 #endif /* Q_WS_MAC */ 1105 1106 void UIMediumManager::populateTreeWidgets() 1107 { 1108 /* If refresh was requested and enumeration was not yet started: */ 1109 if (m_fRefresh && !vboxGlobal().isMediaEnumerationStarted()) 1110 { 1111 /* Just start medium-enumeration: */ 511 1112 vboxGlobal().startEnumeratingMedia(); 1113 } 1114 /* If refresh was not requested or enumeration already started: */ 512 1115 else 513 1116 { 514 /* Insert already enumerated media*/515 const VBoxMediaList & list= vboxGlobal().currentMediaList();516 prepareToRefresh (list.size());1117 /* Emulate (possible partial) medium-enumeration: */ 1118 const VBoxMediaList &mediums = vboxGlobal().currentMediaList(); 1119 prepareToRefresh(mediums.size()); 517 1120 VBoxMediaList::const_iterator it; 518 int index = 0; 519 for (it = list.begin(); it != list.end(); ++ it) 520 { 521 mediumAdded (*it); 1121 /* Add every medium we have into trees: */ 1122 for (it = mediums.begin(); it != mediums.end(); ++it) 1123 { 1124 sltHandleMediumAdded(*it); 1125 /* But advance progress-bar only for created mediums: */ 522 1126 if ((*it).state() != KMediumState_NotCreated) 523 m ProgressBar->setValue (++ index);524 } 525 526 /* Emulate the finished signal to reuse the code*/1127 m_pProgressBar->setValue(m_pProgressBar->value() + 1); 1128 } 1129 /* Finally, emulate enumeration finish, 1130 * if enumeration already finished or wasn't started: */ 527 1131 if (!vboxGlobal().isMediaEnumerationStarted()) 528 sltHandleMediumEnumerationFinish(list); 529 } 530 531 /* For a newly opened dialog, select the first item */ 532 if (mTwHD->selectedItems().isEmpty()) 533 if (QTreeWidgetItem *item = mTwHD->topLevelItem (0)) 534 setCurrentItem (mTwHD, item); 535 if (mTwCD->selectedItems().isEmpty()) 536 if (QTreeWidgetItem *item = mTwCD->topLevelItem (0)) 537 setCurrentItem (mTwCD, item); 538 if (mTwFD->selectedItems().isEmpty()) 539 if (QTreeWidgetItem *item = mTwFD->topLevelItem (0)) 540 setCurrentItem (mTwFD, item); 541 542 /* Applying language settings */ 543 retranslateUi(); 1132 sltHandleMediumEnumerationFinish(); 1133 } 1134 1135 /* For a newly opened dialog, select the first item: */ 1136 if (!mTwHD->currentItem()) 1137 if (QTreeWidgetItem *pItem = mTwHD->topLevelItem(0)) 1138 setCurrentItem(mTwHD, pItem); 1139 if (!mTwCD->currentItem()) 1140 if (QTreeWidgetItem *pItem = mTwCD->topLevelItem(0)) 1141 setCurrentItem(mTwCD, pItem); 1142 if (!mTwFD->currentItem()) 1143 if (QTreeWidgetItem *pItem = mTwFD->topLevelItem(0)) 1144 setCurrentItem(mTwFD, pItem); 1145 } 544 1146 545 1147 #ifdef Q_WS_MAC 546 if (!mDoSelect) 547 { 548 menuBar()->addMenu(UIWindowMenuManager::instance()->createMenu(this)); 549 UIWindowMenuManager::instance()->addWindow(this); 550 } 1148 void UIMediumManager::cleanupMacWindowMenu() 1149 { 1150 /* Destroy window-menu of menu-bar: */ 1151 UIWindowMenuManager::instance()->removeWindow(this); 1152 UIWindowMenuManager::instance()->destroyMenu(this); 1153 } 551 1154 #endif /* Q_WS_MAC */ 552 1155 553 mSetupMode = false; 554 } 555 556 /* static */ 557 void UIMediumManager::showModeless (QWidget *aCenterWidget /* = 0 */, bool aRefresh /* = true */) 558 { 559 if (!mModelessDialog) 560 { 561 mModelessDialog = new UIMediumManager (0, Qt::Window); 562 mModelessDialog->centerAccording (aCenterWidget); 563 mModelessDialog->setAttribute (Qt::WA_DeleteOnClose); 564 mModelessDialog->setup (UIMediumType_All, false /* aDoSelect */, aRefresh); 565 566 /* listen to events that may change the media status and refresh 567 * the contents of the modeless dialog */ 568 /// @todo refreshAll() may be slow, so it may be better to analyze 569 // event details and update only what is changed */ 570 connect (gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), 571 mModelessDialog, SLOT(refreshAll())); 572 connect (gVBoxEvents, SIGNAL(sigMachineRegistered(QString, bool)), 573 mModelessDialog, SLOT(refreshAll())); 574 connect (gVBoxEvents, SIGNAL(sigSnapshotChange(QString, QString)), 575 mModelessDialog, SLOT(refreshAll())); 576 } 577 578 mModelessDialog->show(); 579 mModelessDialog->setWindowState (mModelessDialog->windowState() & ~Qt::WindowMinimized); 580 mModelessDialog->activateWindow(); 581 } 582 583 /* static */ 584 UIMediumManager* UIMediumManager::modelessInstance() 585 { 586 return mModelessDialog; 587 } 588 589 QString UIMediumManager::selectedId() const 590 { 591 QTreeWidget *tree = currentTreeWidget(); 592 QString uuid; 593 594 MediaItem *item = toMediaItem (selectedItem (tree)); 595 if (item) 596 uuid = item->id(); 597 598 return uuid; 599 } 600 601 QString UIMediumManager::selectedLocation() const 602 { 603 QTreeWidget *tree = currentTreeWidget(); 604 QString loc; 605 606 MediaItem *item = toMediaItem (selectedItem (tree)); 607 if (item) 608 loc = item->location().trimmed(); 609 610 return loc; 611 } 612 613 void UIMediumManager::refreshAll() 614 { 615 /* Start enumerating media */ 616 vboxGlobal().startEnumeratingMedia(); 1156 void UIMediumManager::cleanup() 1157 { 1158 #ifdef Q_WS_MAC 1159 /* Cleanup Mac window-menu: */ 1160 cleanupMacWindowMenu(); 1161 #endif /* Q_WS_MAC */ 617 1162 } 618 1163 619 1164 void UIMediumManager::retranslateUi() 620 1165 { 621 /* Translate uic generated strings */ 622 Ui::UIMediumManager::retranslateUi (this); 623 1166 /* Translate uic generated strings: */ 1167 Ui::UIMediumManager::retranslateUi(this); 1168 1169 /* Menu: */ 1170 m_pMenu->setTitle(QApplication::translate("VBoxMediaManagerDlg", "&Actions")); 1171 /* Action names: */ 1172 m_pActionCopy->setText(QApplication::translate("VBoxMediaManagerDlg", "&Copy...")); 1173 m_pActionModify->setText(QApplication::translate("VBoxMediaManagerDlg", "&Modify...")); 1174 m_pActionRemove->setText(QApplication::translate("VBoxMediaManagerDlg", "R&emove")); 1175 m_pActionRelease->setText(QApplication::translate("VBoxMediaManagerDlg", "Re&lease")); 1176 m_pActionRefresh->setText(QApplication::translate("VBoxMediaManagerDlg", "Re&fresh")); 1177 /* Action tool-tips: */ 1178 m_pActionCopy->setToolTip(m_pActionCopy->text().remove('&') + QString(" (%1)").arg(m_pActionCopy->shortcut().toString())); 1179 m_pActionModify->setToolTip(m_pActionModify->text().remove('&') + QString(" (%1)").arg(m_pActionModify->shortcut().toString())); 1180 m_pActionRemove->setToolTip(m_pActionRemove->text().remove('&') + QString(" (%1)").arg(m_pActionRemove->shortcut().toString())); 1181 m_pActionRelease->setToolTip(m_pActionRelease->text().remove('&') + QString(" (%1)").arg(m_pActionRelease->shortcut().toString())); 1182 m_pActionRefresh->setToolTip(m_pActionRefresh->text().remove('&') + QString(" (%1)").arg(m_pActionRefresh->shortcut().toString())); 1183 /* Action status-tips: */ 1184 m_pActionCopy->setStatusTip(QApplication::translate("VBoxMediaManagerDlg", "Copy an existing medium")); 1185 m_pActionModify->setStatusTip(QApplication::translate("VBoxMediaManagerDlg", "Modify the attributes of the selected medium")); 1186 m_pActionRemove->setStatusTip(QApplication::translate("VBoxMediaManagerDlg", "Remove the selected medium")); 1187 m_pActionRelease->setStatusTip(QApplication::translate("VBoxMediaManagerDlg", "Release the selected medium by detaching it from the machines")); 1188 m_pActionRefresh->setStatusTip(QApplication::translate("VBoxMediaManagerDlg", "Refresh the media list")); 1189 1190 /* Tool-bar: */ 1191 #ifdef Q_WS_MAC 1192 # ifdef QT_MAC_USE_COCOA 1193 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when 1194 the necessary size of the toolbar is increased. Also for some languages 1195 the with doesn't match if the text increase. So manually adjust the size 1196 after changing the text. */ 1197 mToolBar->updateLayout(); 1198 # endif /* QT_MAC_USE_COCOA */ 1199 #endif /* Q_WS_MAC */ 1200 1201 // TODO: Just rename translation context in .nls files! 624 1202 /* Translations moved from VBoxMediaManagerDlg.ui file to keep old translation context: */ 625 1203 setWindowTitle(QApplication::translate("VBoxMediaManagerDlg", "Virtual Media Manager")); … … 644 1222 mLbFD2->setText(QApplication::translate("VBoxMediaManagerDlg", "Attached to:")); 645 1223 646 mActionsMenu->setTitle (QApplication::translate("VBoxMediaManagerDlg", "&Actions")); 647 648 mNewAction->setText (QApplication::translate("VBoxMediaManagerDlg", "&New...")); 649 mAddAction->setText (QApplication::translate("VBoxMediaManagerDlg", "&Add...")); 650 mCopyAction->setText (QApplication::translate("VBoxMediaManagerDlg", "&Copy...")); 651 mModifyAction->setText (QApplication::translate("VBoxMediaManagerDlg", "&Modify...")); 652 mRemoveAction->setText (QApplication::translate("VBoxMediaManagerDlg", "R&emove")); 653 mReleaseAction->setText (QApplication::translate("VBoxMediaManagerDlg", "Re&lease")); 654 mRefreshAction->setText (QApplication::translate("VBoxMediaManagerDlg", "Re&fresh")); 655 656 mNewAction->setShortcut (QKeySequence (QKeySequence::New)); 657 mAddAction->setShortcut (QKeySequence ("Ins")); 658 mCopyAction->setShortcut (QKeySequence ("Ctrl+C")); 659 mModifyAction->setShortcut (QKeySequence ("Ctrl+Space")); 660 mRemoveAction->setShortcut (QKeySequence (QKeySequence::Delete)); 661 mReleaseAction->setShortcut (QKeySequence ("Ctrl+L")); 662 mRefreshAction->setShortcut (QKeySequence (QKeySequence::Refresh)); 663 664 mNewAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Create a new virtual hard drive")); 665 mAddAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Add an existing medium")); 666 mCopyAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Copy an existing medium")); 667 mModifyAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Modify the attributes of the selected medium")); 668 mRemoveAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Remove the selected medium")); 669 mReleaseAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Release the selected medium by detaching it from the machines")); 670 mRefreshAction->setStatusTip (QApplication::translate("VBoxMediaManagerDlg", "Refresh the media list")); 671 672 mNewAction->setToolTip (mNewAction->text().remove ('&') + 673 QString (" (%1)").arg (mNewAction->shortcut().toString())); 674 mAddAction->setToolTip (mAddAction->text().remove ('&') + 675 QString (" (%1)").arg (mAddAction->shortcut().toString())); 676 mCopyAction->setToolTip (mCopyAction->text().remove ('&') + 677 QString (" (%1)").arg (mCopyAction->shortcut().toString())); 678 mModifyAction->setToolTip (mModifyAction->text().remove ('&') + 679 QString (" (%1)").arg (mModifyAction->shortcut().toString())); 680 mRemoveAction->setToolTip (mRemoveAction->text().remove ('&') + 681 QString (" (%1)").arg (mRemoveAction->shortcut().toString())); 682 mReleaseAction->setToolTip (mReleaseAction->text().remove ('&') + 683 QString (" (%1)").arg (mReleaseAction->shortcut().toString())); 684 mRefreshAction->setToolTip (mRefreshAction->text().remove ('&') + 685 QString (" (%1)").arg (mRefreshAction->shortcut().toString())); 686 687 mProgressBar->setText (QApplication::translate("VBoxMediaManagerDlg", "Checking accessibility")); 1224 /* Progress-bar: */ 1225 m_pProgressBar->setText(QApplication::translate("VBoxMediaManagerDlg", "Checking accessibility")); 688 1226 #ifdef Q_WS_MAC 689 /* Make sure that the widgets aren't jumping around while the progress bar get visible. */ 690 mProgressBar->adjustSize(); 691 int h = mProgressBar->height(); 692 mButtonBox->setMinimumHeight (h + 12); 693 #endif 694 #ifdef QT_MAC_USE_COCOA 695 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when 696 the necessary size of the toolbar is increased. Also for some languages 697 the with doesn't match if the text increase. So manually adjust the size 698 after changing the text. */ 699 mToolBar->updateLayout(); 700 #endif /* QT_MAC_USE_COCOA */ 701 702 mButtonBox->button(QDialogButtonBox::Ok)->setText(mDoSelect ? tr("&Select") : tr("C&lose")); 703 704 if (mTwHD->model()->rowCount() || mTwCD->model()->rowCount() || mTwFD->model()->rowCount()) 1227 /* Make sure that the widgets aren't jumping around 1228 * while the progress-bar get visible. */ 1229 m_pProgressBar->adjustSize(); 1230 int h = m_pProgressBar->height(); 1231 mButtonBox->setMinimumHeight(h + 12); 1232 #endif /* Q_WS_MAC */ 1233 1234 /* Button-box: */ 1235 mButtonBox->button(QDialogButtonBox::Ok)->setText(tr("C&lose")); 1236 1237 /* Full refresh if there is at least one item present: */ 1238 if (mTwHD->topLevelItemCount() || mTwCD->topLevelItemCount() || mTwFD->topLevelItemCount()) 705 1239 refreshAll(); 706 1240 } 707 1241 708 void UIMediumManager::closeEvent (QCloseEvent *aEvent) 709 { 710 mModelessDialog = 0; 711 aEvent->accept(); 712 } 713 714 bool UIMediumManager::eventFilter (QObject *aObject, QEvent *aEvent) 715 { 716 /* Check for interesting objects */ 717 if (!(aObject == mTwHD || aObject == mTwCD || aObject == mTwFD)) 718 return QIMainDialog::eventFilter (aObject, aEvent); 719 720 switch (aEvent->type()) 721 { 722 case QEvent::DragEnter: 723 { 724 QDragEnterEvent *deEvent = static_cast <QDragEnterEvent*> (aEvent); 725 if (deEvent->mimeData()->hasUrls()) 726 { 727 QList <QUrl> urls = deEvent->mimeData()->urls(); 728 /* Sometimes urls has an empty Url entry. Filter them out. */ 729 urls.removeAll (QUrl()); 730 if (checkDndUrls (urls)) 731 { 732 deEvent->setDropAction (Qt::LinkAction); 733 deEvent->acceptProposedAction(); 734 } 735 } 1242 bool UIMediumManager::releaseMediumFrom(const UIMedium &medium, const QString &strMachineId) 1243 { 1244 /* Open session: */ 1245 CSession session = vboxGlobal().openSession(strMachineId); 1246 if (session.isNull()) 1247 return false; 1248 1249 /* Get machine: */ 1250 CMachine machine = session.GetMachine(); 1251 1252 /* Prepare result: */ 1253 bool fSuccess = true; 1254 1255 /* Depending on medium-type: */ 1256 switch (medium.type()) 1257 { 1258 case UIMediumType_HardDisk: fSuccess = releaseHardDiskFrom(medium, machine); break; 1259 case UIMediumType_DVD: fSuccess = releaseOpticalDiskFrom(medium, machine); break; 1260 case UIMediumType_Floppy: fSuccess = releaseFloppyDiskFrom(medium, machine); break; 1261 default: AssertMsgFailed(("Medium-type unknown: %d\n", medium.type())); break; 1262 } 1263 1264 /* If medium was released: */ 1265 if (fSuccess) 1266 { 1267 /* Save machine settings: */ 1268 machine.SaveSettings(); 1269 if (!machine.isOk()) 1270 { 1271 msgCenter().cannotSaveMachineSettings(machine, this); 1272 fSuccess = false; 1273 } 1274 } 1275 1276 /* Close session: */ 1277 session.UnlockMachine(); 1278 1279 /* Return result: */ 1280 return fSuccess; 1281 } 1282 1283 bool UIMediumManager::releaseHardDiskFrom(const UIMedium &medium, CMachine &machine) 1284 { 1285 /* Enumerate attachments: */ 1286 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1287 foreach (const CMediumAttachment &attachment, attachments) 1288 { 1289 /* Skip non-hard-disks: */ 1290 if (attachment.GetType() != KDeviceType_HardDisk) 1291 continue; 1292 1293 /* Skip unrelated hard-disks: */ 1294 if (attachment.GetMedium().GetId() != medium.id()) 1295 continue; 1296 1297 /* Try detaching device: */ 1298 machine.DetachDevice(attachment.GetController(), attachment.GetPort(), attachment.GetDevice()); 1299 if (machine.isOk()) 1300 { 1301 /* Return success: */ 736 1302 return true; 1303 } 1304 else 1305 { 1306 /* Show error: */ 1307 CStorageController controller = machine.GetStorageControllerByName(attachment.GetController()); 1308 msgCenter().cannotDetachDevice(machine, UIMediumType_HardDisk, medium.location(), 1309 StorageSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()), this); 1310 /* Return failure: */ 1311 return false; 1312 } 1313 } 1314 /* Return failure: */ 1315 return false; 1316 } 1317 1318 bool UIMediumManager::releaseOpticalDiskFrom(const UIMedium &medium, CMachine &machine) 1319 { 1320 /* Enumerate attachments: */ 1321 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1322 foreach (const CMediumAttachment &attachment, attachments) 1323 { 1324 /* Skip non-optical-disks: */ 1325 if (attachment.GetType() != KDeviceType_DVD) 1326 continue; 1327 1328 /* Skip unrelated optical-disks: */ 1329 if (attachment.GetMedium().GetId() != medium.id()) 1330 continue; 1331 1332 /* Try device unmounting: */ 1333 machine.MountMedium(attachment.GetController(), attachment.GetPort(), attachment.GetDevice(), CMedium(), false /* force */); 1334 if (machine.isOk()) 1335 { 1336 /* Return success: */ 1337 return true; 1338 } 1339 else 1340 { 1341 /* Show error: */ 1342 msgCenter().cannotRemountMedium(machine, medium, false /* mount? */, false /* retry? */, this); 1343 /* Return failure: */ 1344 return false; 1345 } 1346 } 1347 /* Return failure: */ 1348 return false; 1349 } 1350 1351 bool UIMediumManager::releaseFloppyDiskFrom(const UIMedium &medium, CMachine &machine) 1352 { 1353 /* Enumerate attachments: */ 1354 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1355 foreach (const CMediumAttachment &attachment, attachments) 1356 { 1357 /* Skip non-floppy-disks: */ 1358 if (attachment.GetType() != KDeviceType_Floppy) 1359 continue; 1360 1361 /* Skip unrelated floppy-disks: */ 1362 if (attachment.GetMedium().GetId() != medium.id()) 1363 continue; 1364 1365 /* Try device unmounting: */ 1366 machine.MountMedium(attachment.GetController(), attachment.GetPort(), attachment.GetDevice(), CMedium(), false /* force */); 1367 if (machine.isOk()) 1368 { 1369 /* Return success: */ 1370 return true; 1371 } 1372 else 1373 { 1374 /* Show error: */ 1375 msgCenter().cannotRemountMedium(machine, medium, false /* mount? */, false /* retry? */, this); 1376 /* Return failure: */ 1377 return false; 1378 } 1379 } 1380 /* Return failure: */ 1381 return false; 1382 } 1383 1384 QTreeWidget* UIMediumManager::treeWidget(UIMediumType type) const 1385 { 1386 /* Return corresponding tree-widget: */ 1387 switch (type) 1388 { 1389 case UIMediumType_HardDisk: return mTwHD; 1390 case UIMediumType_DVD: return mTwCD; 1391 case UIMediumType_Floppy: return mTwFD; 1392 default: AssertMsgFailed(("Medium-type unknown: %d\n", type)); break; 1393 } 1394 /* Null by default: */ 1395 return 0; 1396 } 1397 1398 UIMediumType UIMediumManager::currentTreeWidgetType() const 1399 { 1400 /* Return corresponding medium-type: */ 1401 switch (mTabWidget->currentIndex()) 1402 { 1403 case HDTab: return UIMediumType_HardDisk; 1404 case CDTab: return UIMediumType_DVD; 1405 case FDTab: return UIMediumType_Floppy; 1406 default: AssertMsgFailed(("Page-type unknown: %d\n", mTabWidget->currentIndex())); break; 1407 } 1408 /* Invalid by default: */ 1409 return UIMediumType_Invalid; 1410 } 1411 1412 QTreeWidget* UIMediumManager::currentTreeWidget() const 1413 { 1414 return treeWidget(currentTreeWidgetType()); 1415 } 1416 1417 UIMediumItem* UIMediumManager::toMediumItem(QTreeWidgetItem *pItem) const 1418 { 1419 /* Return UIMediumItem based on QTreeWidgetItem if it is valid: */ 1420 if (pItem && pItem->type() == UIMediumItem::MediaItemType) 1421 return static_cast<UIMediumItem*>(pItem); 1422 /* Null by default: */ 1423 return 0; 1424 } 1425 1426 void UIMediumManager::setCurrentItem(QTreeWidget *pTree, QTreeWidgetItem *pItem) 1427 { 1428 if (pTree && pItem) 1429 { 1430 pItem->setSelected(true); 1431 pTree->setCurrentItem(pItem); 1432 pTree->scrollToItem(pItem, QAbstractItemView::EnsureVisible); 1433 sltHandleCurrentItemChanged(pItem); 1434 } 1435 else 1436 sltHandleCurrentTabChanged(); 1437 } 1438 1439 UIMediumItem* UIMediumManager::createHardDiskItem(QTreeWidget *pTree, const UIMedium &medium) const 1440 { 1441 /* Make sure passed medium is valid: */ 1442 AssertReturn(!medium.medium().isNull(), 0); 1443 1444 /* Prepare medium-item: */ 1445 UIMediumItem *pMediumItem = 0; 1446 CMedium parent = medium.medium().GetParent(); 1447 1448 /* First try to create item under corresponding parent: */ 1449 if (!parent.isNull()) 1450 if (UIMediumItem *pRoot = searchItem(pTree, parent.GetId())) 1451 pMediumItem = new UIMediumItem(pRoot, medium, this); 1452 /* Else just create item as top-level one: */ 1453 if (!pMediumItem) 1454 pMediumItem = new UIMediumItem(pTree, medium, this); 1455 1456 /* Return created item: */ 1457 return pMediumItem; 1458 } 1459 1460 void UIMediumManager::updateTabIcons(UIMediumItem *pMediumItem, ItemAction action) 1461 { 1462 /* Make sure medium-item is valid: */ 1463 AssertReturnVoid(pMediumItem); 1464 1465 /* Prepare data for tab: */ 1466 int iTab = -1; 1467 const QIcon *pIcon = 0; 1468 bool *pfInaccessible = 0; 1469 switch (pMediumItem->type()) 1470 { 1471 case UIMediumType_HardDisk: 1472 iTab = HDTab; 1473 pIcon = &m_iconHD; 1474 pfInaccessible = &m_fInaccessibleHD; 737 1475 break; 738 } 739 case QEvent::Drop: 740 { 741 QDropEvent *dEvent = static_cast <QDropEvent*> (aEvent); 742 if (dEvent->mimeData()->hasUrls()) 743 { 744 QList <QUrl> urls = dEvent->mimeData()->urls(); 745 /* Sometimes urls has an empty Url entry. Filter them out. */ 746 urls.removeAll (QUrl()); 747 AddVDMUrlsEvent *event = new AddVDMUrlsEvent (urls); 748 QApplication::postEvent (currentTreeWidget(), event); 749 dEvent->acceptProposedAction(); 750 } 751 return true; 1476 case UIMediumType_DVD: 1477 iTab = CDTab; 1478 pIcon = &m_iconCD; 1479 pfInaccessible = &m_fInaccessibleCD; 752 1480 break; 753 } 754 case AddVDMUrlsEventType: 755 { 756 if (aObject == currentTreeWidget()) 757 { 758 AddVDMUrlsEvent *addEvent = static_cast <AddVDMUrlsEvent*> (aEvent); 759 addDndUrls (addEvent->urls()); 760 return true; 761 } 1481 case UIMediumType_Floppy: 1482 iTab = FDTab; 1483 pIcon = &m_iconFD; 1484 pfInaccessible = &m_fInaccessibleFD; 762 1485 break; 763 }764 default:765 break;766 }767 return QIMainDialog::eventFilter (aObject, aEvent);768 }769 770 void UIMediumManager::mediumAdded (const UIMedium &aMedium)771 {772 /* Ignore non-interesting aMedium */773 if ((aMedium.isNull()) ||774 (mType != UIMediumType_All && mType != aMedium.type()) ||775 (aMedium.isHostDrive()))776 return;777 778 /* Ignore mediums (and their children) which are marked as hidden or779 * which are attached to hidden machines only: */780 if (isMediumAttachedToHiddenMachinesOnly(aMedium))781 return;782 783 if (!mShowDiffs && aMedium.type() == UIMediumType_HardDisk)784 {785 if (aMedium.parent() && !mSessionMachineId.isNull())786 {787 /* In !mShowDiffs mode, we ignore all diffs except ones that are788 * directly attached to the related VM in the current state */789 if (!aMedium.isAttachedInCurStateTo (mSessionMachineId))790 return;791 792 /* Since the base hard disk of this diff has been already appended,793 * we want to replace it with this diff to avoid duplicates in794 * !mShowDiffs mode. */795 MediaItem *item = searchItem (mTwHD, aMedium.root().id());796 AssertReturnVoid (item);797 798 item->setMedium (aMedium);799 800 /* Check if swapped diff disk is required one */801 if (item->id() == mHDSelectedId)802 {803 setCurrentItem (mTwHD, item);804 mHDSelectedId = QString::null;805 }806 807 updateTabIcons (item, ItemAction_Updated);808 return;809 }810 }811 812 MediaItem *item = 0;813 814 switch (aMedium.type())815 {816 case UIMediumType_HardDisk:817 {818 item = createHardDiskItem (mTwHD, aMedium);819 AssertReturnVoid (item);820 821 /* Damn Qt4 didn't notifies the table's QHeaderView on adding822 * new tree-widget items, so initialize the header adjustment823 * by calling resizeSections() slot... */824 QTimer::singleShot (0, mTwHD->header(), SLOT (resizeSections()));825 826 if (item->id() == mHDSelectedId)827 {828 setCurrentItem (mTwHD, item);829 mHDSelectedId = QString::null;830 }831 break;832 }833 case UIMediumType_DVD:834 {835 item = new MediaItem (mTwCD, aMedium, this);836 AssertReturnVoid (item);837 838 /* Damn Qt4 didn't notifies the table's QHeaderView on adding839 * new tree-widget items, so initialize the header adjustment840 * by calling resizeSections() slot... */841 QTimer::singleShot (0, mTwCD->header(), SLOT (resizeSections()));842 843 if (item->id() == mCDSelectedId)844 {845 setCurrentItem (mTwCD, item);846 mCDSelectedId = QString::null;847 }848 break;849 }850 case UIMediumType_Floppy:851 {852 item = new MediaItem (mTwFD, aMedium, this);853 AssertReturnVoid (item);854 855 /* Damn Qt4 didn't notifies the table's QHeaderView on adding856 * new tree-widget items, so initialize the header adjustment857 * by calling resizeSections() slot... */858 QTimer::singleShot (0, mTwFD->header(), SLOT (resizeSections()));859 860 if (item->id() == mFDSelectedId)861 {862 setCurrentItem (mTwFD, item);863 mFDSelectedId = QString::null;864 }865 break;866 }867 1486 default: 868 1487 AssertFailed(); 869 1488 } 870 871 AssertReturnVoid (item); 872 873 updateTabIcons (item, ItemAction_Added); 874 875 /* If the media enumeration process is not started we have to select the 876 * newly added item as the current one for the case of new image was added 877 * or created. But we have to avoid this in case of we are adding already 878 * enumerated medias in setup() function when the media enumeration is not 879 * running. So the mSetupMode variable reflects the setup status for it. */ 880 if (!mSetupMode && !vboxGlobal().isMediaEnumerationStarted()) 881 setCurrentItem (treeWidget (aMedium.type()), item); 882 if (item == currentTreeWidget()->currentItem()) 883 processCurrentChanged (item); 884 } 885 886 void UIMediumManager::mediumUpdated (const UIMedium &aMedium) 887 { 888 /* Ignore non-interesting aMedium */ 889 if ((aMedium.isNull()) || 890 (mType != UIMediumType_All && mType != aMedium.type()) || 891 (aMedium.isHostDrive())) 892 return; 893 894 /* Ignore mediums (and their children) which are marked as hidden or 895 * which are attached to hidden machines only: */ 896 if (isMediumAttachedToHiddenMachinesOnly(aMedium)) 897 return; 898 899 MediaItem *item = 0; 900 901 switch (aMedium.type()) 902 { 903 case UIMediumType_HardDisk: 904 { 905 item = searchItem (mTwHD, aMedium.id()); 1489 AssertReturnVoid(iTab != -1 && pIcon && pfInaccessible); 1490 1491 switch (action) 1492 { 1493 case ItemAction_Added: 1494 { 1495 /* Does it change the overall state? */ 1496 if (*pfInaccessible || pMediumItem->state() != KMediumState_Inaccessible) 1497 break; /* no */ 1498 1499 *pfInaccessible = true; 1500 1501 mTabWidget->setTabIcon(iTab, vboxGlobal().warningIcon()); 1502 906 1503 break; 907 1504 } 908 case UIMediumType_DVD: 909 { 910 item = searchItem (mTwCD, aMedium.id()); 911 break; 912 } 913 case UIMediumType_Floppy: 914 { 915 item = searchItem (mTwFD, aMedium.id()); 916 break; 917 } 918 default: 919 AssertFailed(); 920 } 921 922 /* There may be unwanted items due to !mShowDiffs */ 923 if (!item) 924 return; 925 926 item->setMedium (aMedium); 927 928 updateTabIcons (item, ItemAction_Updated); 929 930 /* Note: current items on invisible tabs are not updated because 931 * it is always done in processCurrentChanged() when the user switches 932 * to an invisible tab */ 933 if (item == currentTreeWidget()->currentItem()) 934 processCurrentChanged (item); 935 } 936 937 void UIMediumManager::mediumRemoved (UIMediumType aType, const QString &aId) 938 { 939 /* Ignore non-interesting aMedium */ 940 if (mType != UIMediumType_All && mType != aType) 941 return; 942 943 QTreeWidget *tree = currentTreeWidget(); 944 MediaItem *item = toMediaItem (searchItem (tree, aId)); 945 946 /* There may be unwanted items due to !mShowDiffs */ 947 if (!item) 948 return; 949 950 updateTabIcons (item, ItemAction_Removed); 951 952 /* We need to silently delete item without selecting 953 * the new one because of complex selection mechanism 954 * which could provoke a segfault choosing the new 955 * one item during last item deletion routine. So blocking 956 * the tree-view for the time of item removing. */ 957 tree->blockSignals (true); 958 delete item; 959 tree->blockSignals (false); 960 961 /* Note: current items on invisible tabs are not updated because 962 * it is always done in processCurrentChanged() when the user switches 963 * to an invisible tab */ 964 setCurrentItem (tree, tree->currentItem()); 965 } 966 967 void UIMediumManager::sltHandleMediumEnumerationStart() 968 { 969 /* Reset inaccessible flags */ 970 mHardDisksInaccessible = 971 mDVDImagesInaccessible = 972 mFloppyImagesInaccessible = false; 973 974 /* Load default tab icons */ 975 mTabWidget->setTabIcon (HDTab, mHardDiskIcon); 976 mTabWidget->setTabIcon (CDTab, mDVDImageIcon); 977 mTabWidget->setTabIcon (FDTab, mFloppyImageIcon); 978 979 /* Load current media list */ 980 const VBoxMediaList &list = vboxGlobal().currentMediaList(); 981 prepareToRefresh (list.size()); 982 VBoxMediaList::const_iterator it; 983 for (it = list.begin(); it != list.end(); ++ it) 984 mediumAdded (*it); 985 986 /* Select the first item to be the current one if the previous saved item 987 * was not selected yet. */ 988 if (!mTwHD->currentItem()) 989 if (QTreeWidgetItem *item = mTwHD->topLevelItem (0)) 990 setCurrentItem (mTwHD, item); 991 if (!mTwCD->currentItem()) 992 if (QTreeWidgetItem *item = mTwCD->topLevelItem (0)) 993 setCurrentItem (mTwCD, item); 994 if (!mTwFD->currentItem()) 995 if (QTreeWidgetItem *item = mTwFD->topLevelItem (0)) 996 setCurrentItem (mTwFD, item); 997 998 processCurrentChanged(); 999 } 1000 1001 void UIMediumManager::sltHandleMediumEnumerated(const UIMedium &aMedium) 1002 { 1003 mediumUpdated (aMedium); 1004 1005 mProgressBar->setValue (mProgressBar->value() + 1); 1006 } 1007 1008 void UIMediumManager::sltHandleMediumEnumerationFinish(const VBoxMediaList &/* aList */) 1009 { 1010 mProgressBar->setVisible (false); 1011 1012 mRefreshAction->setEnabled (true); 1013 unsetCursor(); 1014 1015 processCurrentChanged(); 1016 } 1017 1018 void UIMediumManager::doNewMedium() 1019 { 1020 AssertReturnVoid (currentTreeWidgetType() == UIMediumType_HardDisk); 1021 1022 // UIWizardNewVD dlg(this); 1023 // if (dlg.exec() == QDialog::Accepted) 1024 // { 1025 // CMedium virtualDisk = dlg.virtualDisk(); 1026 // MediaItem *pItem = searchItem(mTwHD, virtualDisk.GetId()); 1027 // AssertReturnVoid(pItem); 1028 // mTwHD->setCurrentItem(pItem); 1029 // } 1030 } 1031 1032 void UIMediumManager::doAddMedium() 1033 { 1034 QTreeWidget *tree = currentTreeWidget(); 1035 MediaItem *item = toMediaItem (tree->currentItem()); 1036 1037 QString title; 1038 QString filter; 1039 UIMediumType type = currentTreeWidgetType(); 1040 1041 QString dir; 1042 if (item && item->state() != KMediumState_Inaccessible 1043 && item->state() != KMediumState_NotCreated) 1044 dir = QFileInfo (item->location().trimmed()).absolutePath(); 1045 1046 if (dir.isEmpty() || !QFileInfo (dir).exists()) 1047 dir = mVBox.GetHomeFolder(); 1048 1049 QList < QPair <QString, QString> > filterList; 1050 QStringList backends; 1051 QStringList allPrefix; 1052 QString allType; 1053 1054 switch (type) 1055 { 1056 case UIMediumType_HardDisk: 1057 { 1058 filterList = vboxGlobal().HDDBackends(); 1059 title = VBoxGlobal::tr("Please choose a virtual hard drive file"); 1060 allType = VBoxGlobal::tr("All virtual hard drive files (%1)"); 1061 break; 1062 } 1063 case UIMediumType_DVD: 1064 { 1065 filterList = vboxGlobal().DVDBackends(); 1066 title = VBoxGlobal::tr("Please choose a virtual optical disk file"); 1067 allType = VBoxGlobal::tr("All virtual optical disk files (%1)"); 1068 break; 1069 } 1070 case UIMediumType_Floppy: 1071 { 1072 filterList = vboxGlobal().FloppyBackends(); 1073 title = VBoxGlobal::tr("Please choose a virtual floppy disk file"); 1074 allType = VBoxGlobal::tr("All virtual floppy disk files (%1)"); 1075 break; 1076 } 1077 default: 1078 AssertMsgFailed (("Selected tree should be equal to one item in UIMediumType.\n")); 1079 break; 1080 } 1081 1082 for (int i = 0; i < filterList.count(); ++i) 1083 { 1084 QPair <QString, QString> item = filterList.at (i); 1085 /* Create one backend filter string */ 1086 backends << QString ("%1 (%2)").arg (item.first). arg (item.second); 1087 /* Save the suffix's for the "All" entry */ 1088 allPrefix << item.second; 1089 } 1090 if (!allPrefix.isEmpty()) 1091 backends.insert(0, allType.arg(allPrefix.join(" ").trimmed())); 1092 backends << QApplication::translate("VBoxMediaManagerDlg", "All files (*)"); 1093 filter = backends.join (";;").trimmed(); 1094 1095 QStringList files = QIFileDialog::getOpenFileNames (dir, filter, this, title); 1096 foreach (QString loc, files) 1097 { 1098 loc = QDir::convertSeparators (loc); 1099 1100 if (!loc.isEmpty()) 1101 addMediumToList (loc, type); 1102 } 1103 } 1104 1105 void UIMediumManager::doCopyMedium() 1106 { 1107 /* Get current tree: */ 1108 QTreeWidget *pTree = currentTreeWidget(); 1109 /* Get current item of current tree: */ 1110 MediaItem *pItem = toMediaItem(pTree->currentItem()); 1111 1112 /* Show Clone VD wizard: */ 1113 UISafePointerWizard pWizard = new UIWizardCloneVD(this, pItem->medium().medium()); 1114 pWizard->prepare(); 1115 pWizard->exec(); 1116 if (pWizard) 1117 delete pWizard; 1118 } 1119 1120 void UIMediumManager::doModifyMedium() 1121 { 1122 MediaItem *pMediumItem = toMediaItem(currentTreeWidget()->currentItem()); 1123 UIMediumTypeChangeDialog dlg(this, pMediumItem->id()); 1124 if (dlg.exec() == QDialog::Accepted) 1125 { 1126 pMediumItem->refreshAll(); 1127 m_pTypePane->setText(pMediumItem->hardDiskType()); 1128 } 1129 } 1130 1131 void UIMediumManager::doRemoveMedium() 1132 { 1133 QTreeWidget *tree = currentTreeWidget(); 1134 MediaItem *item = toMediaItem (tree->currentItem()); 1135 AssertMsgReturnVoid (item, ("Current item must not be null")); 1136 1137 /* Remember ID/type as they may get lost after the closure/deletion */ 1138 QString id = item->id(); 1139 AssertReturnVoid (!id.isNull()); 1140 UIMediumType type = item->type(); 1141 1142 /* Confirm medium removal: */ 1143 if (!msgCenter().confirmMediumRemoval(item->medium(), this)) 1144 return; 1145 1146 COMResult result; 1147 1148 switch (type) 1149 { 1150 case UIMediumType_HardDisk: 1151 { 1152 bool deleteStorage = false; 1153 1154 /* We don't want to try to delete inaccessible storage as it will most likely fail. 1155 * Note that UIMessageCenter::confirmMediumRemoval() is aware of that and 1156 * will give a corresponding hint. Therefore, once the code is changed below, 1157 * the hint should be re-checked for validity. */ 1158 1159 qulonglong caps = 0; 1160 QVector<KMediumFormatCapabilities> capabilities; 1161 capabilities = item->medium().medium().GetMediumFormat().GetCapabilities(); 1162 for (int i = 0; i < capabilities.size(); i++) 1163 caps |= capabilities[i]; 1164 1165 if (item->state() != KMediumState_Inaccessible && 1166 caps & MediumFormatCapabilities_File) 1505 case ItemAction_Updated: 1506 case ItemAction_Removed: 1507 { 1508 bool fCheckRest = false; 1509 1510 if (action == ItemAction_Updated) 1167 1511 { 1168 int rc = msgCenter().confirmDeleteHardDiskStorage(item->location(), this); 1169 if (rc == AlertButton_Cancel) 1170 return; 1171 deleteStorage = rc == AlertButton_Choice1; 1512 /* Does it change the overall state? */ 1513 if ((*pfInaccessible && pMediumItem->state() == KMediumState_Inaccessible) || 1514 (!*pfInaccessible && pMediumItem->state() != KMediumState_Inaccessible)) 1515 break; /* no */ 1516 1517 /* Is the given item in charge? */ 1518 if (!*pfInaccessible && pMediumItem->state() == KMediumState_Inaccessible) 1519 *pfInaccessible = true; /* yes */ 1520 else 1521 fCheckRest = true; /* no */ 1172 1522 } 1173 1174 CMedium hardDisk = item->medium().medium();1175 1176 if ( deleteStorage)1523 else 1524 fCheckRest = true; 1525 1526 if (fCheckRest) 1177 1527 { 1178 /* Remember virtual-disk attributes: */ 1179 QString strLocation = hardDisk.GetLocation(); 1180 /* Prepare delete storage progress: */ 1181 CProgress progress = hardDisk.DeleteStorage(); 1182 if (hardDisk.isOk()) 1528 *pfInaccessible = false; 1529 1530 QTreeWidget *pTree = pMediumItem->treeWidget(); 1531 1532 /* Find the first pfInaccessible item to be in charge: */ 1533 MediaItemIterator it(pTree); 1534 for (; *it; ++ it) 1183 1535 { 1184 /* Show delete storage progress: */ 1185 msgCenter().showModalProgressDialog(progress, windowTitle(), ":/progress_media_delete_90px.png", this); 1186 if (!progress.isOk() || progress.GetResultCode() != 0) 1536 if (*it != pMediumItem && (*it)->state() == KMediumState_Inaccessible) 1187 1537 { 1188 msgCenter().cannotDeleteHardDiskStorage(progress, strLocation, this); 1189 return; 1190 } 1191 } 1192 else 1193 { 1194 msgCenter().cannotDeleteHardDiskStorage(hardDisk, strLocation, this); 1195 return; 1196 } 1197 } 1198 1199 hardDisk.Close(); 1200 result = hardDisk; 1201 break; 1202 } 1203 case UIMediumType_DVD: 1204 { 1205 CMedium image = item->medium().medium(); 1206 image.Close(); 1207 result = image; 1208 break; 1209 } 1210 case UIMediumType_Floppy: 1211 { 1212 CMedium image = item->medium().medium(); 1213 image.Close(); 1214 result = image; 1215 break; 1216 } 1217 default: 1218 AssertFailedReturnVoid(); 1219 } 1220 1221 if (result.isOk()) 1222 vboxGlobal().removeMedium(type, id); 1223 else 1224 msgCenter().cannotCloseMedium(item->medium(), result, this); 1225 } 1226 1227 void UIMediumManager::doReleaseMedium() 1228 { 1229 QTreeWidget *tree = currentTreeWidget(); 1230 MediaItem *item = toMediaItem (tree->currentItem()); 1231 AssertMsgReturnVoid (item, ("Current item must not be null")); 1232 1233 AssertReturnVoid (!item->id().isNull()); 1234 1235 /* Get the fresh attached VM list */ 1236 item->refreshAll(); 1237 1238 QString usage; 1239 CMachineVector machines; 1240 1241 const QList <QString> &machineIds = item->medium().curStateMachineIds(); 1242 for (QList <QString>::const_iterator it = machineIds.begin(); it != machineIds.end(); ++ it) 1243 { 1244 CMachine m = mVBox.FindMachine (*it); 1245 if (!mVBox.isOk()) 1246 continue; 1247 1248 if (!usage.isEmpty()) 1249 usage += ", "; 1250 usage += m.GetName(); 1251 1252 machines.push_back (m); 1253 } 1254 1255 if (machineIds.size() == 0) 1256 { 1257 /* It may happen that the new machine list is empty (medium was already 1258 * released by a third party); update the details and silently return.*/ 1259 processCurrentChanged (item); 1260 return; 1261 } 1262 1263 AssertReturnVoid (machines.size() > 0); 1264 1265 if (!msgCenter().confirmMediumRelease(item->medium(), usage, this)) 1266 return; 1267 1268 for (QList <QString>::const_iterator it = machineIds.begin(); it != machineIds.end(); ++ it) 1269 { 1270 if (!releaseMediumFrom (item->medium(), *it)) 1271 break; 1272 } 1273 1274 /* Inform others about medium changes (use a copy since data owning is not 1275 * clean there (to be fixed one day using shared_ptr)) */ 1276 UIMedium newMedium = item->medium(); 1277 newMedium.refresh(); 1278 vboxGlobal().updateMedium (newMedium); 1279 } 1280 1281 bool UIMediumManager::releaseMediumFrom (const UIMedium &aMedium, const QString &aMachineId) 1282 { 1283 CSession session; 1284 CMachine machine; 1285 1286 /* Is this medium is attached to the VM we are setting up */ 1287 if (mSessionMachineId == aMachineId) 1288 { 1289 machine = mSessionMachine; 1290 } 1291 /* or to some other */ 1292 else 1293 { 1294 session = vboxGlobal().openSession(aMachineId); 1295 if (session.isNull()) 1296 return false; 1297 1298 machine = session.GetMachine(); 1299 } 1300 1301 bool success = true; 1302 1303 switch (aMedium.type()) 1304 { 1305 case UIMediumType_HardDisk: 1306 { 1307 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1308 foreach (const CMediumAttachment &attachment, attachments) 1309 { 1310 if (attachment.GetType() != KDeviceType_HardDisk) continue; 1311 1312 if (attachment.GetMedium().GetId() == aMedium.id()) 1313 { 1314 machine.DetachDevice (attachment.GetController(), attachment.GetPort(), attachment.GetDevice()); 1315 if (!machine.isOk()) 1316 { 1317 CStorageController controller = machine.GetStorageControllerByName (attachment.GetController()); 1318 msgCenter().cannotDetachDevice(machine, UIMediumType_HardDisk, aMedium.location(), 1319 StorageSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()), this); 1320 success = false; 1538 *pfInaccessible = true; 1321 1539 break; 1322 1540 } 1323 1541 } 1324 1542 } 1543 1544 if (*pfInaccessible) 1545 mTabWidget->setTabIcon(iTab, vboxGlobal().warningIcon()); 1546 else 1547 mTabWidget->setTabIcon(iTab, *pIcon); 1548 1325 1549 break; 1326 1550 } 1327 case UIMediumType_DVD: 1328 { 1329 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1330 foreach (const CMediumAttachment &attachment, attachments) 1331 { 1332 if (attachment.GetType() != KDeviceType_DVD) continue; 1333 1334 UIMedium medium = vboxGlobal().findMedium (attachment.GetMedium().isNull() ? QString() : attachment.GetMedium().GetId()); 1335 if (medium.id() == aMedium.id()) 1336 { 1337 machine.MountMedium (attachment.GetController(), attachment.GetPort(), attachment.GetDevice(), CMedium(), false /* force */); 1338 if (!machine.isOk()) 1339 { 1340 msgCenter().cannotRemountMedium(machine, aMedium, false /* mount? */, false /* retry? */, this); 1341 success = false; 1342 break; 1343 } 1344 } 1345 } 1346 break; 1347 } 1348 case UIMediumType_Floppy: 1349 { 1350 CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1351 foreach (const CMediumAttachment &attachment, attachments) 1352 { 1353 if (attachment.GetType() != KDeviceType_Floppy) continue; 1354 1355 UIMedium medium = vboxGlobal().findMedium (attachment.GetMedium().isNull() ? QString() : attachment.GetMedium().GetId()); 1356 if (medium.id() == aMedium.id()) 1357 { 1358 machine.MountMedium (attachment.GetController(), attachment.GetPort(), attachment.GetDevice(), CMedium(), false /* force */); 1359 if (!machine.isOk()) 1360 { 1361 msgCenter().cannotRemountMedium(machine, aMedium, false /* mount? */, false /* retry? */, this); 1362 success = false; 1363 break; 1364 } 1365 } 1366 } 1367 break; 1368 } 1369 default: 1370 AssertFailedBreakStmt (success = false); 1371 } 1372 1373 if (success) 1374 { 1375 machine.SaveSettings(); 1376 if (!machine.isOk()) 1377 { 1378 msgCenter().cannotSaveMachineSettings(machine, this); 1379 success = false; 1380 } 1381 } 1382 1383 /* If a new session was opened, we must close it */ 1384 if (!session.isNull()) 1385 session.UnlockMachine(); 1386 1387 return success; 1388 } 1389 1390 QTreeWidget* UIMediumManager::treeWidget (UIMediumType aType) const 1391 { 1392 QTreeWidget* tree = 0; 1393 switch (aType) 1394 { 1395 case UIMediumType_HardDisk: 1396 tree = mTwHD; 1397 break; 1398 case UIMediumType_DVD: 1399 tree = mTwCD; 1400 break; 1401 case UIMediumType_Floppy: 1402 tree = mTwFD; 1403 break; 1404 default: 1405 AssertMsgFailed (("Disk type %d unknown!\n", aType)); 1406 break; 1407 } 1408 return tree; 1409 } 1410 1411 UIMediumType UIMediumManager::currentTreeWidgetType() const 1412 { 1413 UIMediumType type = UIMediumType_Invalid; 1414 switch (mTabWidget->currentIndex()) 1415 { 1416 case HDTab: 1417 type = UIMediumType_HardDisk; 1418 break; 1419 case CDTab: 1420 type = UIMediumType_DVD; 1421 break; 1422 case FDTab: 1423 type = UIMediumType_Floppy; 1424 break; 1425 default: 1426 AssertMsgFailed (("Page type %d unknown!\n", mTabWidget->currentIndex())); 1427 break; 1428 } 1429 return type; 1430 } 1431 1432 QTreeWidget* UIMediumManager::currentTreeWidget() const 1433 { 1434 return treeWidget (currentTreeWidgetType()); 1435 } 1436 1437 QTreeWidgetItem *UIMediumManager::selectedItem (const QTreeWidget *aTree) const 1438 { 1439 /* Return the current selected item. The user can select one item at the 1440 * time only, so return the first element always. */ 1441 QList <QTreeWidgetItem*> selItems = aTree->selectedItems(); 1442 return selItems.isEmpty() ? 0 : selItems.first(); 1443 } 1444 1445 1446 MediaItem* UIMediumManager::toMediaItem (QTreeWidgetItem *aItem) const 1447 { 1448 /* Convert the QTreeWidgetItem to a MediaItem if it is valid. */ 1449 MediaItem *item = 0; 1450 if (aItem && aItem->type() == MediaItem::MediaItemType) 1451 item = static_cast <MediaItem*> (aItem); 1452 return item; 1453 } 1454 1455 void UIMediumManager::setCurrentItem (QTreeWidget *aTree, QTreeWidgetItem *aItem) 1456 { 1457 if (aTree && aItem) 1458 { 1459 aItem->setSelected (true); 1460 aTree->setCurrentItem (aItem); 1461 aTree->scrollToItem (aItem, QAbstractItemView::EnsureVisible); 1462 processCurrentChanged (aItem); 1463 } 1464 else processCurrentChanged(); 1465 } 1466 1467 void UIMediumManager::processCurrentChanged (int /* aIndex = -1 */) 1468 { 1469 QTreeWidget *tree = currentTreeWidget(); 1470 tree->setFocus(); 1471 processCurrentChanged (tree->currentItem()); 1472 } 1473 1474 void UIMediumManager::processCurrentChanged (QTreeWidgetItem *aItem, 1475 QTreeWidgetItem *aPrevItem /* = 0 */) 1476 { 1477 MediaItem *item = toMediaItem (aItem); 1478 1479 if (!item && aPrevItem) 1480 { 1481 MediaItem *itemOld = toMediaItem (aPrevItem); 1482 /* We have to make sure that one item is selected always. If the new 1483 * item is 0, set the old item again. */ 1484 setCurrentItem (currentTreeWidget(), itemOld); 1485 } 1486 1487 if (item) 1488 { 1489 /* Set the file for the proxy icon */ 1490 setFileForProxyIcon (item->location()); 1491 /* Ensures current item visible every time we are switching page */ 1492 item->treeWidget()->scrollToItem (item, QAbstractItemView::EnsureVisible); 1493 } 1494 1495 bool notInEnum = !vboxGlobal().isMediaEnumerationStarted(); 1496 1497 /* New and Add are now enabled even when enumerating since it should be safe */ 1498 bool newEnabled = currentTreeWidgetType() == UIMediumType_HardDisk; 1499 bool addEnabled = true; 1500 bool copyEnabled = currentTreeWidgetType() == UIMediumType_HardDisk && 1501 notInEnum && item && checkMediumFor (item, Action_Copy); 1502 bool modifyEnabled = currentTreeWidgetType() == UIMediumType_HardDisk && 1503 notInEnum && item && checkMediumFor (item, Action_Modify); 1504 bool removeEnabled = notInEnum && item && checkMediumFor (item, Action_Remove); 1505 bool releaseEnabled = item && checkMediumFor (item, Action_Release); 1506 1507 mNewAction->setEnabled (newEnabled); 1508 mAddAction->setEnabled (addEnabled); 1509 mCopyAction->setEnabled (copyEnabled); 1510 mModifyAction->setEnabled (modifyEnabled); 1511 mRemoveAction->setEnabled (removeEnabled); 1512 mReleaseAction->setEnabled (releaseEnabled); 1513 1514 if (mDoSelect) 1515 { 1516 bool selectEnabled = item && checkMediumFor (item, Action_Select); 1517 mButtonBox->button (QDialogButtonBox::Ok)->setEnabled (selectEnabled); 1518 } 1519 1520 if (item) 1521 { 1522 QString details = item->details(); 1523 QString usage = item->usage().isNull() ? 1524 formatPaneText (QApplication::translate("VBoxMediaManagerDlg", "<i>Not Attached</i>"), false) : 1525 formatPaneText (item->usage()); 1526 1527 if (item->treeWidget() == mTwHD) 1528 { 1529 m_pTypePane->setText(item->hardDiskType()); 1530 m_pLocationPane->setText(formatPaneText(item->location(), true, "end")); 1531 m_pFormatPane->setText(item->hardDiskFormat()); 1532 m_pDetailsPane->setText(details); 1533 m_pUsagePane->setText(usage); 1534 } 1535 else if (item->treeWidget() == mTwCD) 1536 { 1537 mIpCD1->setText (formatPaneText (item->location(), true, "end")); 1538 mIpCD2->setText (usage); 1539 } 1540 else if (item->treeWidget() == mTwFD) 1541 { 1542 mIpFD1->setText (formatPaneText (item->location(), true, "end")); 1543 mIpFD2->setText (usage); 1544 } 1545 } 1546 else 1547 clearInfoPanes(); 1548 1549 mHDContainer->setEnabled (item); 1550 mCDContainer->setEnabled (item); 1551 mFDContainer->setEnabled (item); 1552 } 1553 1554 void UIMediumManager::processDoubleClick (QTreeWidgetItem * /* aItem */, int /* aColumn */) 1555 { 1556 QTreeWidget *tree = currentTreeWidget(); 1557 1558 if (mDoSelect) 1559 { 1560 if (selectedItem (tree) && mButtonBox->button (QDialogButtonBox::Ok)->isEnabled()) 1561 accept(); 1562 } 1563 else 1564 { 1565 if (currentTreeWidgetType() == UIMediumType_HardDisk) 1566 doModifyMedium(); 1567 } 1568 } 1569 1570 void UIMediumManager::showContextMenu (const QPoint &aPos) 1571 { 1572 QTreeWidget *curWidget = currentTreeWidget(); 1573 QTreeWidgetItem *curItem = curWidget->itemAt (aPos); 1574 if (curItem) 1575 { 1576 /* Make sure the item is selected and current */ 1577 setCurrentItem (curWidget, curItem); 1578 mActionsContextMenu->exec (curWidget->viewport()->mapToGlobal (aPos)); 1579 } 1580 } 1581 1582 void UIMediumManager::machineStateChanged(QString /* strId */, KMachineState state) 1583 { 1584 switch (state) 1585 { 1586 case KMachineState_PoweredOff: 1587 case KMachineState_Aborted: 1588 case KMachineState_Saved: 1589 case KMachineState_Teleported: 1590 case KMachineState_Starting: 1591 case KMachineState_Restoring: 1592 case KMachineState_TeleportingIn: 1593 { 1594 refreshAll(); 1595 break; 1596 } 1597 default: 1598 break; 1599 } 1600 } 1601 1602 void UIMediumManager::makeRequestForAdjustTable() 1603 { 1604 /* We have to perform table adjustment only after all the [auto]resize 1605 * events processed for every column of this table. */ 1606 QTimer::singleShot (0, this, SLOT (performTablesAdjustment())); 1607 } 1608 1609 void UIMediumManager::performTablesAdjustment() 1610 { 1611 /* Get all the tree widgets */ 1612 QList <QITreeWidget*> widgetList; 1613 widgetList << mTwHD; 1614 widgetList << mTwCD; 1615 widgetList << mTwFD; 1616 1617 /* Calculate deduction for every header */ 1618 QList <int> deductionsList; 1619 foreach (QITreeWidget *widget, widgetList) 1620 { 1621 int deduction = 0; 1622 for (int i = 1; i < widget->header()->count(); ++ i) 1623 deduction += widget->header()->sectionSize (i); 1624 deductionsList << deduction; 1625 } 1626 1627 /* Adjust the table's first column */ 1628 for (int i = 0; i < widgetList.size(); ++ i) 1629 { 1630 int size0 = widgetList [i]->viewport()->width() - deductionsList [i]; 1631 if (widgetList [i]->header()->sectionSize (0) != size0) 1632 widgetList [i]->header()->resizeSection (0, size0); 1633 } 1634 } 1635 1636 void UIMediumManager::addMediumToList(const QString &aLocation, UIMediumType aType) 1637 { 1638 AssertReturnVoid (!aLocation.isEmpty()); 1639 1640 UIMedium medium; 1641 KDeviceType devType; 1642 1643 switch (aType) 1644 { 1645 case UIMediumType_HardDisk: 1646 devType = KDeviceType_HardDisk; 1647 break; 1648 case UIMediumType_DVD: 1649 devType = KDeviceType_DVD; 1650 break; 1651 case UIMediumType_Floppy: 1652 devType = KDeviceType_Floppy; 1653 break; 1654 default: 1655 AssertMsgFailedReturnVoid (("Invalid aType %d\n", aType)); 1656 } 1657 1658 CMedium med = mVBox.OpenMedium(aLocation, devType, KAccessMode_ReadWrite, false /* fForceNewUuid */); 1659 if (mVBox.isOk()) 1660 medium = UIMedium(CMedium(med), aType, KMediumState_Created); 1661 1662 if (!mVBox.isOk()) 1663 msgCenter().cannotOpenMedium(mVBox, aType, aLocation, this); 1664 else 1665 vboxGlobal().addMedium(medium); 1666 } 1667 1668 MediaItem* UIMediumManager::createHardDiskItem (QTreeWidget *aTree, const UIMedium &aMedium) const 1669 { 1670 AssertReturn (!aMedium.medium().isNull(), 0); 1671 1672 MediaItem *item = 0; 1673 1674 CMedium parent = aMedium.medium().GetParent(); 1675 if (parent.isNull()) 1676 { 1677 item = new MediaItem(aTree, aMedium, this); 1678 } 1679 else 1680 { 1681 MediaItem *root = searchItem (aTree, parent.GetId()); 1682 if (root) 1683 item = new MediaItem(root, aMedium, this); 1684 else 1685 item = new MediaItem(aTree, aMedium, this); 1686 } 1687 1688 return item; 1689 } 1690 1691 void UIMediumManager::updateTabIcons (MediaItem *aItem, ItemAction aAction) 1692 { 1693 AssertReturnVoid (aItem); 1694 1695 int tab = -1; 1696 QIcon *icon = 0; 1697 bool *inaccessible = 0; 1698 1699 switch (aItem->type()) 1700 { 1701 case UIMediumType_HardDisk: 1702 tab = HDTab; 1703 icon = &mHardDiskIcon; 1704 inaccessible = &mHardDisksInaccessible; 1705 break; 1706 case UIMediumType_DVD: 1707 tab = CDTab; 1708 icon = &mDVDImageIcon; 1709 inaccessible = &mDVDImagesInaccessible; 1710 break; 1711 case UIMediumType_Floppy: 1712 tab = FDTab; 1713 icon = &mFloppyImageIcon; 1714 inaccessible = &mFloppyImagesInaccessible; 1715 break; 1716 default: 1717 AssertFailed(); 1718 } 1719 1720 AssertReturnVoid (tab != -1 && icon && inaccessible); 1721 1722 switch (aAction) 1723 { 1724 case ItemAction_Added: 1725 { 1726 /* Does it change the overall state? */ 1727 if (*inaccessible || aItem->state() != KMediumState_Inaccessible) 1728 break; /* no */ 1729 1730 *inaccessible = true; 1731 1732 mTabWidget->setTabIcon (tab, vboxGlobal().warningIcon()); 1733 1734 break; 1735 } 1736 case ItemAction_Updated: 1737 case ItemAction_Removed: 1738 { 1739 bool checkRest = false; 1740 1741 if (aAction == ItemAction_Updated) 1742 { 1743 /* Does it change the overall state? */ 1744 if ((*inaccessible && aItem->state() == KMediumState_Inaccessible) || 1745 (!*inaccessible && aItem->state() != KMediumState_Inaccessible)) 1746 break; /* no */ 1747 1748 /* Is the given item in charge? */ 1749 if (!*inaccessible && aItem->state() == KMediumState_Inaccessible) 1750 *inaccessible = true; /* yes */ 1751 else 1752 checkRest = true; /* no */ 1753 } 1754 else 1755 checkRest = true; 1756 1757 if (checkRest) 1758 { 1759 *inaccessible = false; 1760 1761 QTreeWidget *tree = aItem->treeWidget(); 1762 1763 /* Find the first inaccessible item to be in charge */ 1764 MediaItemIterator it (tree); 1765 for (; *it; ++ it) 1766 { 1767 if (*it != aItem && (*it)->state() == KMediumState_Inaccessible) 1768 { 1769 *inaccessible = true; 1770 break; 1771 } 1772 } 1773 } 1774 1775 if (*inaccessible) 1776 mTabWidget->setTabIcon (tab, vboxGlobal().warningIcon()); 1777 else 1778 mTabWidget->setTabIcon (tab, *icon); 1779 1780 break; 1781 } 1782 } 1783 } 1784 1785 MediaItem* UIMediumManager::searchItem (QTreeWidget *aTree, const QString &aId) const 1786 { 1787 if (aId.isNull()) 1551 } 1552 } 1553 1554 UIMediumItem* UIMediumManager::searchItem(QTreeWidget *pTree, const QString &strId) const 1555 { 1556 /* Make sure passed ID is valid: */ 1557 if (strId.isNull()) 1788 1558 return 0; 1789 1559 1790 MediaItemIterator iterator (aTree); 1560 /* Iterate other all the mediums of passed tree: */ 1561 MediaItemIterator iterator(pTree); 1791 1562 while (*iterator) 1792 1563 { 1793 if ((*iterator)->id() == aId)1564 if ((*iterator)->id() == strId) 1794 1565 return *iterator; 1795 ++ iterator; 1796 } 1566 ++iterator; 1567 } 1568 1569 /* Null by default: */ 1797 1570 return 0; 1798 1571 } 1799 1572 1800 /** 1801 * Checks if a specific action is valid for the given medium at its current 1802 * state. 1803 * 1804 * @param aItem Media item. 1805 * @param aAction Action to check. 1806 * 1807 * @return @c true if the action is possible and false otherwise. 1808 */ 1809 bool UIMediumManager::checkMediumFor (MediaItem *aItem, Action aAction) 1810 { 1811 AssertReturn (aItem, false); 1812 1813 switch (aAction) 1814 { 1815 case Action_Select: 1816 { 1817 /* Restrict selecting mediums 1818 * already used by other attachments */ 1819 return !mUsedMediaIds.contains (aItem->id()); 1820 } 1573 bool UIMediumManager::checkMediumFor(UIMediumItem *pItem, Action action) 1574 { 1575 /* Make sure passed ID is valid: */ 1576 AssertReturn(pItem, false); 1577 1578 switch (action) 1579 { 1821 1580 case Action_Edit: 1822 1581 { 1823 1582 /* Edit means changing the description and alike; any media that is 1824 * not being read to or written from can be altered in these 1825 * terms */ 1826 switch (aItem->state()) 1583 * not being read to or written from can be altered in these terms. */ 1584 switch (pItem->state()) 1827 1585 { 1828 1586 case KMediumState_NotCreated: … … 1839 1597 { 1840 1598 /* False for children: */ 1841 return ! aItem->medium().parent();1599 return !pItem->medium().parent(); 1842 1600 } 1843 1601 case Action_Modify: 1844 1602 { 1845 1603 /* False for children: */ 1846 return ! aItem->medium().parent();1604 return !pItem->medium().parent(); 1847 1605 } 1848 1606 case Action_Remove: 1849 1607 { 1850 /* Removable if not attached to anything */1851 return ! aItem->isUsed();1608 /* Removable if not attached to anything: */ 1609 return !pItem->isUsed(); 1852 1610 } 1853 1611 case Action_Release: 1854 1612 { 1855 /* Releasable if attached but not in snapshots */ 1856 return aItem->isUsed() && !aItem->isUsedInSnapshots(); 1857 } 1858 } 1859 1860 AssertFailedReturn (false); 1861 } 1862 1863 bool UIMediumManager::checkDndUrls (const QList <QUrl> &aUrls) const 1864 { 1865 bool err = false; 1866 /* Check that all file extensions fit to the current 1867 * selected tree view and the files are valid. */ 1868 foreach (QUrl u, aUrls) 1869 { 1870 QFileInfo fi (u.toLocalFile()); 1871 /* Check dropped media type */ 1872 /// @todo On OS/2 and windows (and mac?) extension checks should be case 1873 /// insensitive, as OPPOSED to linux and the rest where case matters. 1874 QString suffix = fi.suffix().toLower(); 1875 switch (currentTreeWidgetType()) 1876 { 1877 case UIMediumType_HardDisk: 1878 { 1879 QList < QPair <QString, QString> > filterList = vboxGlobal().HDDBackends(); 1880 bool match = false; 1881 for (int i = 0; i < filterList.count(); ++i) 1882 { 1883 QPair <QString, QString> item = filterList.at (i); 1884 if (QString ("*.%1").arg (suffix) == item.second) 1885 { 1886 match = true; 1887 break; 1888 } 1889 } 1890 err |= !match; 1891 break; 1892 } 1893 case UIMediumType_DVD: 1894 err |= (suffix != "iso"); 1895 break; 1896 case UIMediumType_Floppy: 1897 err |= (suffix != "img"); 1898 break; 1899 default: 1900 AssertMsgFailed (("Selected tree should be equal to one item in UIMediumType.\n")); 1901 break; 1902 } 1903 } 1904 return !err; 1905 } 1906 1907 void UIMediumManager::addDndUrls (const QList <QUrl> &aUrls) 1908 { 1909 foreach (QUrl u, aUrls) 1910 { 1911 QString file = u.toLocalFile(); 1912 UIMediumType type = currentTreeWidgetType(); 1913 addMediumToList (file, type); 1914 } 1613 /* Releasable if attached but not in snapshots: */ 1614 return pItem->isUsed() && !pItem->isUsedInSnapshots(); 1615 } 1616 } 1617 1618 AssertFailedReturn(false); 1915 1619 } 1916 1620 … … 1922 1626 } 1923 1627 1924 void UIMediumManager::prepareToRefresh (int aTotal)1925 { 1926 /* Info panel clearing */1628 void UIMediumManager::prepareToRefresh(int iTotal) 1629 { 1630 /* Info panel clearing: */ 1927 1631 clearInfoPanes(); 1928 1632 1929 /* Prepare progressbar */1930 if (m ProgressBar)1931 { 1932 m ProgressBar->setMaximum (aTotal);1933 m ProgressBar->setValue(0);1934 m ProgressBar->setVisible(true);1935 } 1936 1937 mRefreshAction->setEnabled (false);1938 setCursor (QCursor (Qt::BusyCursor));1939 1940 /* S tore the current list selections*/1941 MediaItem *mi;1942 1943 mi = toMediaItem (mTwHD->currentItem());1944 if (mHDSelectedId.isNull())1945 mHDSelectedId = mi ? mi->id() : QString::null;1946 1947 mi = toMediaItem (mTwCD->currentItem());1948 if (mCDSelectedId.isNull())1949 mCDSelectedId = mi ? mi->id() : QString::null;1950 1951 mi = toMediaItem (mTwFD->currentItem());1952 if (m FDSelectedId.isNull())1953 m FDSelectedId = mi ? mi->id() : QString::null;1633 /* Prepare progressbar: */ 1634 if (m_pProgressBar) 1635 { 1636 m_pProgressBar->setMaximum(iTotal); 1637 m_pProgressBar->setValue(0); 1638 m_pProgressBar->setVisible(true); 1639 } 1640 1641 /* Enable refresh action: */ 1642 m_pActionRefresh->setEnabled(false); 1643 1644 /* Set busy cursor: */ 1645 setCursor(QCursor(Qt::BusyCursor)); 1646 1647 /* Store the current list selections: */ 1648 UIMediumItem *pMediumItem = 0; 1649 pMediumItem = toMediumItem(mTwHD->currentItem()); 1650 if (m_strSelectedIdHD.isNull()) 1651 m_strSelectedIdHD = pMediumItem ? pMediumItem->id() : QString(); 1652 pMediumItem = toMediumItem (mTwCD->currentItem()); 1653 if (m_strSelectedIdCD.isNull()) 1654 m_strSelectedIdCD = pMediumItem ? pMediumItem->id() : QString(); 1655 pMediumItem = toMediumItem (mTwFD->currentItem()); 1656 if (m_strSelectedIdFD.isNull()) 1657 m_strSelectedIdFD = pMediumItem ? pMediumItem->id() : QString(); 1954 1658 1955 1659 /* Finally, clear all the lists... … … 1961 1665 * is null and at least one element have to be selected (by policy). 1962 1666 * So just blocking any signals outgoing from the list during clearing. */ 1963 mTwHD->blockSignals 1667 mTwHD->blockSignals(true); 1964 1668 mTwHD->clear(); 1965 mTwHD->blockSignals 1669 mTwHD->blockSignals(false); 1966 1670 mTwCD->clear(); 1967 1671 mTwFD->clear(); 1968 1672 } 1969 1673 1970 /** 1971 * Modifies the given text string for QILabel so that it optionally uses the 1972 * <compact> syntax controlling visual text "compression" with elipsis. 1973 * 1974 * @param aText Original text string. 1975 * @param aCompact @c true if "compression" should be activated. 1976 * @param aElipsis Where to put the elipsis (see <compact> in QILabel). 1977 * 1978 * @return Modified text string. 1979 */ 1980 QString UIMediumManager::formatPaneText (const QString &aText, bool aCompact /* = true */, 1981 const QString &aElipsis /* = "middle" */) 1982 { 1983 QString compactString = QString ("<compact elipsis=\"%1\">").arg (aElipsis); 1984 QString info = QString ("<nobr>%1%2%3</nobr>") 1985 .arg (aCompact ? compactString : "") 1986 .arg (aText.isEmpty() ? 1987 QApplication::translate("VBoxMediaManagerDlg", "--", "no info") : 1988 aText) 1989 .arg (aCompact ? "</compact>" : ""); 1990 return info; 1674 QString UIMediumManager::formatPaneText(const QString &strText, bool fCompact /* = true */, 1675 const QString &strElipsis /* = "middle" */) 1676 { 1677 QString compactString = QString("<compact elipsis=\"%1\">").arg(strElipsis); 1678 QString strInfo = QString("<nobr>%1%2%3</nobr>") 1679 .arg(fCompact ? compactString : "") 1680 .arg(strText.isEmpty() ? 1681 QApplication::translate("VBoxMediaManagerDlg", "--", "no info") : 1682 strText) 1683 .arg(fCompact ? "</compact>" : ""); 1684 return strInfo; 1991 1685 } 1992 1686 -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.h
r47998 r48086 20 20 #define __UIMediumManager_h__ 21 21 22 /* GUI includes */22 /* GUI includes: */ 23 23 #include "UIMediumManager.gen.h" 24 #include "QIWithRetranslateUI.h" 24 25 #include "QIMainDialog.h" 25 #include "QIWithRetranslateUI.h" 26 #include "VBoxMediaComboBox.h" 26 #include "UIMedium.h" 27 27 28 28 /* COM includes: */ 29 #include "COMEnums.h" 29 30 #include "CMachine.h" 31 #include "CVirtualBox.h" 30 32 31 33 /* Forward declarations: */ 32 class MediaItem; 34 class UIToolBar; 35 class UIMediumItem; 33 36 class VBoxProgressBar; 34 class UIToolBar;35 37 36 class UIMediumManager : public QIWithRetranslateUI2<QIMainDialog>, 37 38 /* Medium Manager Dialog: */ 39 class UIMediumManager : public QIWithRetranslateUI2<QIMainDialog>, public Ui::UIMediumManager 38 40 { 39 41 Q_OBJECT; 40 42 43 /* Enumerators: */ 41 44 enum TabIndex { HDTab = 0, CDTab, FDTab }; 42 45 enum ItemAction { ItemAction_Added, ItemAction_Updated, ItemAction_Removed }; 43 enum Action { Action_Select, Action_Edit, Action_Copy, Action_Modify, Action_Remove, Action_Release }; 46 enum Action { Action_Edit, Action_Copy, Action_Modify, Action_Remove, Action_Release }; 47 48 /* Constructor/destructor: */ 49 UIMediumManager(QWidget *pCenterWidget, bool fRefresh = true); 50 ~UIMediumManager(); 44 51 45 52 public: 46 53 47 UIMediumManager (QWidget *aParent = NULL, 48 Qt::WindowFlags aFlags = Qt::Dialog); 49 ~UIMediumManager(); 50 51 void setup (UIMediumType aType, bool aDoSelect, 52 bool aRefresh = true, 53 const CMachine &aSessionMachine = CMachine(), 54 const QString &aSelectId = QString::null, 55 bool aShowDiffs = true, 56 const QStringList &aUsedMediaIds = QStringList()); 57 58 static void showModeless (QWidget *aParent = NULL, bool aRefresh = true); 59 static UIMediumManager* modelessInstance(); 60 61 QString selectedId() const; 62 QString selectedLocation() const; 63 64 bool showDiffs() const { return mShowDiffs; }; 65 bool inAttachMode() const { return !mSessionMachine.isNull(); }; 54 /* Static API: Singleton stuff: */ 55 static UIMediumManager* instance(); 56 static void showModeless(QWidget *pCenterWidget, bool fRefresh = true); 66 57 67 58 public slots: 68 59 60 /* Handler: Refresh stuff: */ 69 61 void refreshAll(); 70 71 protected:72 73 void retranslateUi();74 virtual void closeEvent (QCloseEvent *aEvent);75 virtual bool eventFilter (QObject *aObject, QEvent *aEvent);76 62 77 63 private slots: 78 64 79 void mediumAdded (const UIMedium &aMedium); 80 void mediumUpdated (const UIMedium &aMedium); 81 void mediumRemoved (UIMediumType aType, const QString &aId); 65 /* Handlers: Medium-processing stuff: */ 66 void sltHandleMediumAdded(const UIMedium &medium); 67 void sltHandleMediumUpdated(const UIMedium &medium); 68 void sltHandleMediumRemoved(UIMediumType type, const QString &strId); 82 69 70 /* Handlers: Medium-enumeration stuff: */ 83 71 void sltHandleMediumEnumerationStart(); 84 void sltHandleMediumEnumerated(const UIMedium & aMedium);85 void sltHandleMediumEnumerationFinish( const VBoxMediaList &aList);72 void sltHandleMediumEnumerated(const UIMedium &medium); 73 void sltHandleMediumEnumerationFinish(); 86 74 87 void doNewMedium(); 88 void doAddMedium(); 89 void doCopyMedium(); 90 void doModifyMedium(); 91 void doRemoveMedium(); 92 void doReleaseMedium(); 75 /* Handlers: Medium-modification stuff: */ 76 void sltCopyMedium(); 77 void sltModifyMedium(); 78 void sltRemoveMedium(); 79 void sltReleaseMedium(); 93 80 94 bool releaseMediumFrom (const UIMedium &aMedium, const QString &aMachineId); 81 /* Handlers: Navigation stuff: */ 82 void sltHandleCurrentTabChanged(); 83 void sltHandleCurrentItemChanged(QTreeWidgetItem *pItem, QTreeWidgetItem *pPrevItem = 0); 84 void sltHandleDoubleClick(); 85 void sltHandleContextMenuCall(const QPoint &position); 95 86 96 void processCurrentChanged (int index = -1); 97 void processCurrentChanged (QTreeWidgetItem *aItem, QTreeWidgetItem *aPrevItem = 0); 98 void processDoubleClick (QTreeWidgetItem *aItem, int aColumn); 99 void showContextMenu (const QPoint &aPos); 87 /* Handler: Machine stuff: */ 88 void sltHandleMachineStateChanged(QString strId, KMachineState state); 100 89 101 void machineStateChanged(QString strId, KMachineState state); 102 103 void makeRequestForAdjustTable(); 104 void performTablesAdjustment(); 90 /* Handlers: Geometry stuff: */ 91 void sltMakeRequestForTableAdjustment(); 92 void sltPerformTablesAdjustment(); 105 93 106 94 private: 107 95 108 QTreeWidget* treeWidget (UIMediumType aType) const; 96 /* Helpers: Prepare stuff: */ 97 void prepare(); 98 void prepareThis(); 99 void prepareActions(); 100 void prepareMenuBar(); 101 void prepareToolBar(); 102 void prepareContextMenu(); 103 void preapreTabWidget(); 104 void prepareTreeWidgets(); 105 void prepareTreeWidgetHD(); 106 void prepareTreeWidgetCD(); 107 void prepareTreeWidgetFD(); 108 void prepareInformationPanes(); 109 void prepareButtonBox(); 110 void prepareProgressBar(); 111 #ifdef Q_WS_MAC 112 void prepareMacWindowMenu(); 113 #endif /* Q_WS_MAC */ 114 115 /* Helper: Populate stuff: */ 116 void populateTreeWidgets(); 117 118 /* Helpers: Cleanup stuff: */ 119 #ifdef Q_WS_MAC 120 void cleanupMacWindowMenu(); 121 #endif /* Q_WS_MAC */ 122 void cleanup(); 123 124 /* Handler: Translation stuff: */ 125 void retranslateUi(); 126 127 /* Helper: Medium-modification stuff: */ 128 bool releaseMediumFrom(const UIMedium &medium, const QString &strMachineId); 129 bool releaseHardDiskFrom(const UIMedium &medium, CMachine &machine); 130 bool releaseOpticalDiskFrom(const UIMedium &medium, CMachine &machine); 131 bool releaseFloppyDiskFrom(const UIMedium &medium, CMachine &machine); 132 133 /* Internal API: Tree-widget access stuff: */ 134 QTreeWidget* treeWidget(UIMediumType type) const; 109 135 UIMediumType currentTreeWidgetType() const; 110 136 QTreeWidget* currentTreeWidget() const; 137 UIMediumItem* toMediumItem(QTreeWidgetItem *aItem) const; 138 void setCurrentItem(QTreeWidget *pTree, QTreeWidgetItem *pItem); 111 139 112 QTreeWidgetItem* selectedItem (const QTreeWidget *aTree) const; 113 MediaItem* toMediaItem (QTreeWidgetItem *aItem) const; 140 UIMediumItem* createHardDiskItem (QTreeWidget *aTree, const UIMedium &aMedium) const; 114 141 115 void setCurrentItem (QTreeWidget *aTree, QTreeWidgetItem *aItem);142 void updateTabIcons (UIMediumItem *aItem, ItemAction aAction); 116 143 117 void addMediumToList (const QString &aLocation, UIMediumType aType);144 UIMediumItem* searchItem (QTreeWidget *aTree, const QString &aId) const; 118 145 119 MediaItem* createHardDiskItem (QTreeWidget *aTree, const UIMedium &aMedium) const; 120 121 void updateTabIcons (MediaItem *aItem, ItemAction aAction); 122 123 MediaItem* searchItem (QTreeWidget *aTree, const QString &aId) const; 124 125 bool checkMediumFor (MediaItem *aItem, Action aAction); 126 127 bool checkDndUrls (const QList<QUrl> &aUrls) const; 128 void addDndUrls (const QList<QUrl> &aUrls); 146 bool checkMediumFor (UIMediumItem *aItem, Action aAction); 129 147 130 148 void clearInfoPanes(); … … 136 154 static bool isMediumAttachedToHiddenMachinesOnly(const UIMedium &medium); 137 155 138 /* Private member vars */ 139 /* Window status */ 140 bool mDoSelect; 141 static UIMediumManager *mModelessDialog; 142 VBoxProgressBar *mProgressBar; 156 /* Variable: Singleton instance: */ 157 static UIMediumManager *m_spInstance; 143 158 144 /* The global VirtualBox instance */ 145 CVirtualBox mVBox; 159 /* Variables: General stuff: */ 160 CVirtualBox m_vbox; 161 QWidget *m_pCenterWidget; 162 bool m_fRefresh; 146 163 147 /* Type if we are in the select modus */ 148 int mType; 164 /* Variables: Tab-widget stuff: */ 165 bool m_fInaccessibleHD; 166 bool m_fInaccessibleCD; 167 bool m_fInaccessibleFD; 168 const QIcon m_iconHD; 169 const QIcon m_iconCD; 170 const QIcon m_iconFD; 171 QString m_strSelectedIdHD; 172 QString m_strSelectedIdCD; 173 QString m_strSelectedIdFD; 149 174 150 bool mShowDiffs : 1; 151 bool mSetupMode : 1; 175 /* Variables: Menu & Toolbar stuff: */ 176 UIToolBar *mToolBar; 177 QMenu *m_pContextMenu; 178 QMenu *m_pMenu; 179 QAction *m_pActionCopy; 180 QAction *m_pActionModify; 181 QAction *m_pActionRemove; 182 QAction *m_pActionRelease; 183 QAction *m_pActionRefresh; 152 184 153 /* Icon definitions */ 154 QIcon mHardDiskIcon; 155 QIcon mDVDImageIcon; 156 QIcon mFloppyImageIcon; 157 158 /* Menu & Toolbar */ 159 QMenu *mActionsContextMenu; 160 QMenu *mActionsMenu; 161 UIToolBar *mToolBar; 162 QAction *mNewAction; 163 QAction *mAddAction; 164 QAction *mCopyAction; 165 QAction *mModifyAction; 166 QAction *mRemoveAction; 167 QAction *mReleaseAction; 168 QAction *mRefreshAction; 169 170 /* Machine */ 171 CMachine mSessionMachine; 172 QString mSessionMachineId; 173 bool mHardDisksInaccessible; 174 bool mDVDImagesInaccessible; 175 bool mFloppyImagesInaccessible; 176 QString mHDSelectedId; 177 QString mCDSelectedId; 178 QString mFDSelectedId; 179 QStringList mUsedMediaIds; 185 /* Variable: Progress-bar stuff: */ 186 VBoxProgressBar *m_pProgressBar; 180 187 }; 181 188 -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.ui
r43106 r48086 287 287 <widget class="QIDialogButtonBox" name="mButtonBox" > 288 288 <property name="standardButtons" > 289 <set>QDialogButtonBox:: Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>289 <set>QDialogButtonBox::Help|QDialogButtonBox::Ok</set> 290 290 </property> 291 291 </widget> -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp
r47998 r48086 187 187 188 188 /* Make sure MM window is not opened: */ 189 if (UIMediumManager:: modelessInstance())189 if (UIMediumManager::instance()) 190 190 return; 191 191
Note:
See TracChangeset
for help on using the changeset viewer.