VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.cpp@ 102493

Last change on this file since 102493 was 102269, checked in by vboxsync, 10 months ago

FE/Qt: bugref:10450: macOS: No need to QIToolBar layout/paint hacks since Qt6.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 65.5 KB
Line 
1/* $Id: UIMediumManager.cpp 102269 2023-11-22 18:50:08Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMediumManager class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QFrame>
30#include <QHBoxLayout>
31#include <QHeaderView>
32#include <QLabel>
33#include <QMenuBar>
34#include <QProgressBar>
35#include <QPushButton>
36
37/* GUI includes: */
38#include "QIDialogButtonBox.h"
39#include "QIFileDialog.h"
40#include "QILabel.h"
41#include "QIMessageBox.h"
42#include "QITabWidget.h"
43#include "UIActionPoolManager.h"
44#include "UICommon.h"
45#include "UIExtraDataManager.h"
46#include "UIIconPool.h"
47#include "UIMediumDetailsWidget.h"
48#include "UIMediumItem.h"
49#include "UIMediumManager.h"
50#include "UIMediumSearchWidget.h"
51#include "UINotificationCenter.h"
52#include "UIWizardCloneVD.h"
53#include "UIMessageCenter.h"
54#include "QIToolBar.h"
55#include "UIIconPool.h"
56#include "UIMedium.h"
57#include "UIVirtualBoxEventHandler.h"
58
59/* COM includes: */
60#include "COMEnums.h"
61#include "CMachine.h"
62#include "CMediumAttachment.h"
63#include "CMediumFormat.h"
64#include "CStorageController.h"
65#include "CSystemProperties.h"
66
67#ifdef VBOX_WS_MAC
68# include "UIWindowMenuManager.h"
69#endif /* VBOX_WS_MAC */
70
71
72
73/** Functor allowing to check if passed UIMediumItem is suitable by @a uID. */
74class CheckIfSuitableByID : public CheckIfSuitableBy
75{
76public:
77 /** Constructor accepting @a uID to compare with. */
78 CheckIfSuitableByID(const QUuid &uID) : m_uID(uID) {}
79
80private:
81 /** Determines whether passed UIMediumItem is suitable by @a uID. */
82 bool isItSuitable(UIMediumItem *pItem) const { return pItem->id() == m_uID; }
83 /** Holds the @a uID to compare to. */
84 QUuid m_uID;
85};
86
87/** Functor allowing to check if passed UIMediumItem is suitable by @a state. */
88class CheckIfSuitableByState : public CheckIfSuitableBy
89{
90public:
91 /** Constructor accepting @a state to compare with. */
92 CheckIfSuitableByState(KMediumState state) : m_state(state) {}
93
94private:
95 /** Determines whether passed UIMediumItem is suitable by @a state. */
96 bool isItSuitable(UIMediumItem *pItem) const { return pItem->state() == m_state; }
97 /** Holds the @a state to compare to. */
98 KMediumState m_state;
99};
100
101
102/*********************************************************************************************************************************
103* Class UIEnumerationProgressBar implementation. *
104*********************************************************************************************************************************/
105
106UIEnumerationProgressBar::UIEnumerationProgressBar(QWidget *pParent /* = 0 */)
107 : QWidget(pParent)
108{
109 /* Prepare: */
110 prepare();
111}
112
113void UIEnumerationProgressBar::setText(const QString &strText)
114{
115 m_pLabel->setText(strText);
116}
117
118int UIEnumerationProgressBar::value() const
119{
120 return m_pProgressBar->value();
121}
122
123void UIEnumerationProgressBar::setValue(int iValue)
124{
125 m_pProgressBar->setValue(iValue);
126}
127
128void UIEnumerationProgressBar::setMaximum(int iValue)
129{
130 m_pProgressBar->setMaximum(iValue);
131}
132
133void UIEnumerationProgressBar::prepare()
134{
135 /* Create layout: */
136 QHBoxLayout *pLayout = new QHBoxLayout(this);
137 {
138 /* Configure layout: */
139 pLayout->setContentsMargins(0, 0, 0, 0);
140 /* Create label: */
141 m_pLabel = new QLabel;
142 /* Create progress-bar: */
143 m_pProgressBar = new QProgressBar;
144 {
145 /* Configure progress-bar: */
146 m_pProgressBar->setTextVisible(false);
147 }
148 /* Add widgets into layout: */
149 pLayout->addWidget(m_pLabel);
150 pLayout->addWidget(m_pProgressBar);
151 }
152}
153
154
155/*********************************************************************************************************************************
156* Class UIMediumManagerWidget implementation. *
157*********************************************************************************************************************************/
158
159UIMediumManagerWidget::UIMediumManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
160 bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
161 : QIWithRetranslateUI<QWidget>(pParent)
162 , m_enmEmbedding(enmEmbedding)
163 , m_pActionPool(pActionPool)
164 , m_fShowToolbar(fShowToolbar)
165 , m_fPreventChangeCurrentItem(false)
166 , m_pTabWidget(0)
167 , m_iTabCount(3)
168 , m_fInaccessibleHD(false)
169 , m_fInaccessibleCD(false)
170 , m_fInaccessibleFD(false)
171 , m_iconHD(UIIconPool::iconSet(":/hd_16px.png", ":/hd_disabled_16px.png"))
172 , m_iconCD(UIIconPool::iconSet(":/cd_16px.png", ":/cd_disabled_16px.png"))
173 , m_iconFD(UIIconPool::iconSet(":/fd_16px.png", ":/fd_disabled_16px.png"))
174 , m_pDetailsWidget(0)
175 , m_pToolBar(0)
176 , m_pProgressBar(0)
177 , m_pSearchWidget(0)
178{
179 /* Prepare: */
180 prepare();
181}
182
183QMenu *UIMediumManagerWidget::menu() const
184{
185 return m_pActionPool->action(UIActionIndexMN_M_MediumWindow)->menu();
186}
187
188void UIMediumManagerWidget::setProgressBar(UIEnumerationProgressBar *pProgressBar)
189{
190 /* Cache progress-bar reference:*/
191 m_pProgressBar = pProgressBar;
192
193 /* Update translation: */
194 retranslateUi();
195}
196
197void UIMediumManagerWidget::retranslateUi()
198{
199 /* Translate tab-widget: */
200 if (m_pTabWidget)
201 {
202 m_pTabWidget->setTabText(tabIndex(UIMediumDeviceType_HardDisk), UIMediumManager::tr("&Hard disks"));
203 m_pTabWidget->setTabText(tabIndex(UIMediumDeviceType_DVD), UIMediumManager::tr("&Optical disks"));
204 m_pTabWidget->setTabText(tabIndex(UIMediumDeviceType_Floppy), UIMediumManager::tr("&Floppy disks"));
205 }
206
207 /* Translate HD tree-widget: */
208 QITreeWidget *pTreeWidgetHD = treeWidget(UIMediumDeviceType_HardDisk);
209 if (pTreeWidgetHD)
210 {
211 pTreeWidgetHD->setWhatsThis(UIMediumManager::tr("Registered hard drives"));
212 pTreeWidgetHD->headerItem()->setText(0, UIMediumManager::tr("Name"));
213 pTreeWidgetHD->headerItem()->setText(1, UIMediumManager::tr("Virtual Size"));
214 pTreeWidgetHD->headerItem()->setText(2, UIMediumManager::tr("Actual Size"));
215 }
216
217 /* Translate CD tree-widget: */
218 QITreeWidget *pTreeWidgetCD = treeWidget(UIMediumDeviceType_DVD);
219 if (pTreeWidgetCD)
220 {
221 pTreeWidgetCD->setWhatsThis(UIMediumManager::tr("Registered optical disks"));
222 pTreeWidgetCD->headerItem()->setText(0, UIMediumManager::tr("Name"));
223 pTreeWidgetCD->headerItem()->setText(1, UIMediumManager::tr("Size"));
224 }
225
226 /* Translate FD tree-widget: */
227 QITreeWidget *pTreeWidgetFD = treeWidget(UIMediumDeviceType_Floppy);
228 if (pTreeWidgetFD)
229 {
230 pTreeWidgetFD->setWhatsThis(UIMediumManager::tr("Registered floppy disks"));
231 pTreeWidgetFD->headerItem()->setText(0, UIMediumManager::tr("Name"));
232 pTreeWidgetFD->headerItem()->setText(1, UIMediumManager::tr("Size"));
233 }
234
235 /* Translate progress-bar: */
236 if (m_pProgressBar)
237 {
238 m_pProgressBar->setText(UIMediumManager::tr("Checking accessibility"));
239#ifdef VBOX_WS_MAC
240 /* Make sure that the widgets aren't jumping around
241 * while the progress-bar get visible. */
242 m_pProgressBar->adjustSize();
243 //int h = m_pProgressBar->height();
244 //if (m_pButtonBox)
245 // m_pButtonBox->setMinimumHeight(h + 12);
246#endif
247 }
248
249 /* Full refresh if there is at least one item present: */
250 if ( (pTreeWidgetHD && pTreeWidgetHD->topLevelItemCount())
251 || (pTreeWidgetCD && pTreeWidgetCD->topLevelItemCount())
252 || (pTreeWidgetFD && pTreeWidgetFD->topLevelItemCount()))
253 sltRefreshAll();
254}
255
256void UIMediumManagerWidget::sltResetMediumDetailsChanges()
257{
258 /* Push the current item data into details-widget: */
259 sltHandleCurrentTabChanged();
260}
261
262void UIMediumManagerWidget::sltApplyMediumDetailsChanges()
263{
264 /* Get current medium-item: */
265 UIMediumItem *pMediumItem = currentMediumItem();
266 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
267 AssertReturnVoid(!pMediumItem->id().isNull());
268
269 /* Get item data: */
270 UIDataMedium oldData = *pMediumItem;
271 UIDataMedium newData = m_pDetailsWidget->data();
272
273 /* Search for corresponding medium: */
274 CMedium comMedium = uiCommon().medium(pMediumItem->id()).medium();
275
276 /* Try to assign new medium type: */
277 if ( comMedium.isOk()
278 && newData.m_options.m_enmMediumType != oldData.m_options.m_enmMediumType)
279 pMediumItem->changeMediumType(newData.m_options.m_enmMediumType);
280
281 /* Try to assign new medium description: */
282 if ( comMedium.isOk()
283 && newData.m_options.m_strDescription != oldData.m_options.m_strDescription)
284 {
285 comMedium.SetDescription(newData.m_options.m_strDescription);
286
287 /* Show error message if necessary: */
288 if (!comMedium.isOk())
289 UINotificationMessage::cannotChangeMediumParameter(comMedium);
290 }
291
292 /* Try to assign new medium location: */
293 if ( comMedium.isOk()
294 && newData.m_options.m_strLocation != oldData.m_options.m_strLocation)
295 {
296 /* Assign new medium location: */
297 UINotificationProgressMediumMove *pNotification = new UINotificationProgressMediumMove(comMedium,
298 newData.m_options.m_strLocation);
299 connect(pNotification, &UINotificationProgressMediumMove::sigProgressFinished,
300 this, &UIMediumManagerWidget::sltHandleMoveProgressFinished);
301 gpNotificationCenter->append(pNotification);
302 }
303
304 /* Try to assign new medium size: */
305 if ( comMedium.isOk()
306 && newData.m_options.m_uLogicalSize != oldData.m_options.m_uLogicalSize)
307 {
308 /* Assign new medium size: */
309 UINotificationProgressMediumResize *pNotification = new UINotificationProgressMediumResize(comMedium,
310 newData.m_options.m_uLogicalSize);
311 connect(pNotification, &UINotificationProgressMediumResize::sigProgressFinished,
312 this, &UIMediumManagerWidget::sltHandleResizeProgressFinished);
313 gpNotificationCenter->append(pNotification);
314 }
315
316 /* Recache current item: */
317 pMediumItem->refreshAll();
318
319 /* Push the current item data into details-widget: */
320 sltHandleCurrentTabChanged();
321}
322
323void UIMediumManagerWidget::sltHandleMediumCreated(const QUuid &uMediumID)
324{
325 /* Search for corresponding medium: */
326 UIMedium medium = uiCommon().medium(uMediumID);
327
328 /* Ignore non-interesting media: */
329 if (medium.isNull() || medium.isHostDrive())
330 return;
331
332 /* Ignore media (and their children) which are
333 * marked as hidden or attached to hidden machines only: */
334 if (UIMedium::isMediumAttachedToHiddenMachinesOnly(medium))
335 return;
336
337 /* Create medium-item for corresponding medium: */
338 UIMediumItem *pMediumItem = createMediumItem(medium);
339
340 /* Make sure medium-item was created: */
341 if (!pMediumItem)
342 return;
343
344 /* If medium-item change allowed and
345 * 1. medium-enumeration is not currently in progress or
346 * 2. if there is no currently medium-item selected
347 * we have to choose newly added medium-item as current one: */
348 if ( !m_fPreventChangeCurrentItem
349 && ( !uiCommon().isMediumEnumerationInProgress()
350 || !mediumItem(medium.type())))
351 setCurrentItem(treeWidget(medium.type()), pMediumItem);
352}
353
354void UIMediumManagerWidget::sltHandleMediumDeleted(const QUuid &uMediumID)
355{
356 /* Make sure corresponding medium-item deleted: */
357 deleteMediumItem(uMediumID);
358}
359
360void UIMediumManagerWidget::sltHandleMediumEnumerationStart()
361{
362 /* Disable 'refresh' action: */
363 if (m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh))
364 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh)->setEnabled(false);
365
366 /* Disable details-widget: */
367 if (m_pDetailsWidget)
368 m_pDetailsWidget->setOptionsEnabled(false);
369
370 /* Reset and show progress-bar: */
371 if (m_pProgressBar)
372 {
373 m_pProgressBar->setMaximum(uiCommon().mediumIDs().size());
374 m_pProgressBar->setValue(0);
375 m_pProgressBar->show();
376 }
377
378 /* Reset inaccessibility flags: */
379 m_fInaccessibleHD =
380 m_fInaccessibleCD =
381 m_fInaccessibleFD = false;
382
383 /* Reset tab-widget icons: */
384 if (m_pTabWidget)
385 {
386 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_HardDisk), m_iconHD);
387 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_DVD), m_iconCD);
388 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_Floppy), m_iconFD);
389 }
390
391 /* Repopulate tree-widgets content: */
392 repopulateTreeWidgets();
393
394 /* Re-fetch all current medium-items: */
395 refetchCurrentMediumItems();
396 refetchCurrentChosenMediumItem();
397}
398
399void UIMediumManagerWidget::sltHandleMediumEnumerated(const QUuid &uMediumID)
400{
401 /* Search for corresponding medium: */
402 UIMedium medium = uiCommon().medium(uMediumID);
403
404 /* Ignore non-interesting media: */
405 if (medium.isNull() || medium.isHostDrive())
406 return;
407
408 /* Ignore media (and their children) which are
409 * marked as hidden or attached to hidden machines only: */
410 if (UIMedium::isMediumAttachedToHiddenMachinesOnly(medium))
411 return;
412
413 /* Update medium-item for corresponding medium: */
414 updateMediumItem(medium);
415
416 /* Advance progress-bar: */
417 if (m_pProgressBar)
418 m_pProgressBar->setValue(m_pProgressBar->value() + 1);
419}
420
421void UIMediumManagerWidget::sltHandleMediumEnumerationFinish()
422{
423 /* Hide progress-bar: */
424 if (m_pProgressBar)
425 m_pProgressBar->hide();
426
427 /* Enable details-widget: */
428 if (m_pDetailsWidget)
429 m_pDetailsWidget->setOptionsEnabled(true);
430
431 /* Enable 'refresh' action: */
432 if (m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh))
433 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh)->setEnabled(true);
434
435 /* Re-fetch all current medium-items: */
436 refetchCurrentMediumItems();
437 refetchCurrentChosenMediumItem();
438}
439
440void UIMediumManagerWidget::sltHandleMachineStateChange(const QUuid &uId, const KMachineState state)
441{
442 UIMediumItem *pCurrentItem = currentMediumItem();
443 if (!pCurrentItem)
444 return;
445 /* If this machine is not using the current medium then we don't care about its state: */
446 if (!pCurrentItem->isMediumAttachedTo(uId))
447 return;
448 bool fMediumIsModifiable = true;
449 if (state != KMachineState_Aborted && state != KMachineState_PoweredOff && state != KMachineState_AbortedSaved)
450 fMediumIsModifiable = false;
451 m_pDetailsWidget->enableDisableMediumModificationWidgets(fMediumIsModifiable);
452}
453
454void UIMediumManagerWidget::sltAddMedium()
455{
456 QString strDefaultMachineFolder = uiCommon().virtualBox().GetSystemProperties().GetDefaultMachineFolder();
457 uiCommon().openMediumWithFileOpenDialog(currentMediumType(), this,
458 strDefaultMachineFolder, true /* use most recent medium folder */);
459}
460
461void UIMediumManagerWidget::sltCreateMedium()
462{
463 /* What's with current medium type? */
464 const UIMediumDeviceType enmMediumType = currentMediumType();
465
466 /* Ask listener to start hard-disk creation: */
467 if (enmMediumType == UIMediumDeviceType_HardDisk)
468 emit sigCreateMedium();
469 else
470 uiCommon().openMediumCreatorDialog(m_pActionPool, this, currentMediumType());
471}
472
473void UIMediumManagerWidget::sltCopyMedium()
474{
475 /* Get current medium-item: */
476 UIMediumItem *pMediumItem = currentMediumItem();
477 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
478 AssertReturnVoid(!pMediumItem->id().isNull());
479
480 /* Ask listener to start medium copying: */
481 emit sigCopyMedium(pMediumItem->medium().id());
482}
483
484void UIMediumManagerWidget::sltMoveMedium()
485{
486 /* Get current medium-item: */
487 UIMediumItem *pMediumItem = currentMediumItem();
488 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
489 AssertReturnVoid(!pMediumItem->id().isNull());
490
491 /* Copy current medium-item: */
492 pMediumItem->move();
493
494 /* Push the current item data into details-widget: */
495 sltHandleCurrentTabChanged();
496}
497
498void UIMediumManagerWidget::sltRemoveMedium()
499{
500 /* Get current medium-item: */
501 UIMediumItem *pMediumItem = currentMediumItem();
502 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
503 AssertReturnVoid(!pMediumItem->id().isNull());
504
505 /* Remove current medium-item: */
506 pMediumItem->remove(true /* show message box */);
507}
508
509void UIMediumManagerWidget::sltReleaseMedium()
510{
511 /* Get current medium-item: */
512 UIMediumItem *pMediumItem = currentMediumItem();
513 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
514 AssertReturnVoid(!pMediumItem->id().isNull());
515
516 /* Remove current medium-item: */
517 bool fResult = pMediumItem->release(true /* show message box */, false /* induced */);
518
519 /* Refetch currently chosen medium-item: */
520 if (fResult)
521 refetchCurrentChosenMediumItem();
522}
523
524void UIMediumManagerWidget::sltClear()
525{
526 /* Currently we clear only DVD medium type items: */
527 if (currentMediumType() != UIMediumDeviceType_DVD && currentMediumType() != UIMediumDeviceType_Floppy)
528 return;
529 QITreeWidget* pTreeWidget = currentTreeWidget();
530 AssertReturnVoid(pTreeWidget);
531 /* Iterate over the tree items assuming medium items are immediate children of the root and they dont have children
532 * themselves which currently holds for DVD and floppy medium types: */
533 QList<UIMediumItem*> mediumsToRemove;
534 QStringList nameList;
535 for (int i = 0; i < pTreeWidget->childCount(); ++i)
536 {
537 UIMediumItem *pMediumItem = qobject_cast<UIMediumItem*>(pTreeWidget->childItem(i));
538 if (!pMediumItem)
539 continue;
540 if (pMediumItem->state() == KMediumState_Inaccessible)
541 {
542 mediumsToRemove << pMediumItem;
543 nameList << pMediumItem->name();
544 }
545 }
546 if (!msgCenter().confirmInaccesibleMediaClear(nameList, currentMediumType(), this))
547 return;
548
549 foreach (UIMediumItem *pMediumItem, mediumsToRemove)
550 {
551 pMediumItem->release(false /* no messag box */, false /* induced */);
552 pMediumItem->remove(false /* show no message box */);
553 }
554}
555
556void UIMediumManagerWidget::sltToggleMediumDetailsVisibility(bool fVisible)
557{
558 /* Save the setting: */
559 gEDataManager->setVirtualMediaManagerDetailsExpanded(fVisible);
560 /* Toggle medium details visibility: */
561 if (m_pDetailsWidget)
562 m_pDetailsWidget->setVisible(fVisible);
563 /* Notify external lsiteners: */
564 emit sigMediumDetailsVisibilityChanged(fVisible);
565}
566
567void UIMediumManagerWidget::sltToggleMediumSearchVisibility(bool fVisible)
568{
569 /* Save the setting: */
570 gEDataManager->setVirtualMediaManagerSearchWidgetExpanded(fVisible);
571 /* Toggle medium details visibility: */
572 if (m_pSearchWidget)
573 m_pSearchWidget->setVisible(fVisible);
574}
575
576void UIMediumManagerWidget::sltRefreshAll()
577{
578 /* Restart full medium-enumeration: */
579 uiCommon().enumerateMedia();
580}
581
582void UIMediumManagerWidget::sltHandleMoveProgressFinished()
583{
584 /* Get current medium-item: */
585 UIMediumItem *pMediumItem = currentMediumItem();
586 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
587 AssertReturnVoid(!pMediumItem->id().isNull());
588
589 /* Recache current item: */
590 pMediumItem->refreshAll();
591
592 /* Push the current item data into details-widget: */
593 sltHandleCurrentTabChanged();
594}
595
596void UIMediumManagerWidget::sltHandleResizeProgressFinished()
597{
598 /* Get current medium-item: */
599 UIMediumItem *pMediumItem = currentMediumItem();
600 AssertMsgReturnVoid(pMediumItem, ("Current item must not be null"));
601 AssertReturnVoid(!pMediumItem->id().isNull());
602
603 /* Recache current item: */
604 pMediumItem->refreshAll();
605
606 /* Push the current item data into details-widget: */
607 sltHandleCurrentTabChanged();
608}
609
610void UIMediumManagerWidget::sltHandleCurrentTabChanged()
611{
612 /* Get current tree-widget: */
613 QITreeWidget *pTreeWidget = currentTreeWidget();
614 if (pTreeWidget)
615 {
616 /* If another tree-widget was focused before,
617 * move focus to current tree-widget: */
618 if (qobject_cast<QITreeWidget*>(focusWidget()))
619 pTreeWidget->setFocus();
620 }
621
622 /* Update action icons: */
623 updateActionIcons();
624
625 /* Raise the required information-container: */
626 if (m_pDetailsWidget)
627 m_pDetailsWidget->setCurrentType(currentMediumType());
628
629 enableClearAction();
630
631 /* Re-fetch currently chosen medium-item: */
632 refetchCurrentChosenMediumItem();
633 sltHandlePerformSearch();
634}
635
636void UIMediumManagerWidget::sltHandleCurrentItemChanged()
637{
638 /* Get sender() tree-widget: */
639 QITreeWidget *pTreeWidget = qobject_cast<QITreeWidget*>(sender());
640 AssertMsgReturnVoid(pTreeWidget, ("This slot should be called by tree-widget only!\n"));
641
642 /* Re-fetch current medium-item of required type: */
643 refetchCurrentMediumItem(mediumType(pTreeWidget));
644}
645
646void UIMediumManagerWidget::sltHandleContextMenuRequest(const QPoint &position)
647{
648 /* Get current tree-widget: */
649 QITreeWidget *pTreeWidget = currentTreeWidget();
650 AssertPtrReturnVoid(pTreeWidget);
651
652 /* If underlaying item was found => make sure that item is current one: */
653 QTreeWidgetItem *pItem = pTreeWidget->itemAt(position);
654 if (pItem)
655 setCurrentItem(pTreeWidget, pItem);
656
657 /* Compose temporary context-menu: */
658 QMenu menu;
659 if (pTreeWidget->itemAt(position))
660 {
661 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy));
662 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move));
663 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove));
664 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release));
665 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search));
666 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details));
667 }
668 else
669 {
670 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Add));
671 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Create));
672 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search));
673 menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh));
674 }
675 /* And show it: */
676 menu.exec(pTreeWidget->viewport()->mapToGlobal(position));
677}
678
679void UIMediumManagerWidget::sltPerformTablesAdjustment()
680{
681 /* Get all the tree-widgets: */
682 const QList<QITreeWidget*> trees = m_trees.values();
683
684 /* Calculate deduction for every header: */
685 QList<int> deductions;
686 foreach (QITreeWidget *pTreeWidget, trees)
687 {
688 int iDeduction = 0;
689 for (int iHeaderIndex = 1; iHeaderIndex < pTreeWidget->header()->count(); ++iHeaderIndex)
690 iDeduction += pTreeWidget->header()->sectionSize(iHeaderIndex);
691 deductions << iDeduction;
692 }
693
694 /* Adjust the table's first column: */
695 for (int iTreeIndex = 0; iTreeIndex < trees.size(); ++iTreeIndex)
696 {
697 QITreeWidget *pTreeWidget = trees[iTreeIndex];
698 int iSize0 = pTreeWidget->viewport()->width() - deductions[iTreeIndex];
699 if (pTreeWidget->header()->sectionSize(0) != iSize0)
700 pTreeWidget->header()->resizeSection(0, iSize0);
701 }
702}
703
704void UIMediumManagerWidget::sltHandlePerformSearch()
705{
706 performSearch(true);
707}
708
709void UIMediumManagerWidget::sltDetachCOM()
710{
711 /* Clear tree-widgets: */
712 QITreeWidget *pTreeWidgetHD = treeWidget(UIMediumDeviceType_HardDisk);
713 if (pTreeWidgetHD)
714 pTreeWidgetHD->clear();
715 QITreeWidget *pTreeWidgetCD = treeWidget(UIMediumDeviceType_DVD);
716 if (pTreeWidgetCD)
717 pTreeWidgetCD->clear();
718 QITreeWidget *pTreeWidgetFD = treeWidget(UIMediumDeviceType_Floppy);
719 if (pTreeWidgetFD)
720 pTreeWidgetFD->clear();
721}
722
723void UIMediumManagerWidget::prepare()
724{
725 /* Prepare connections: */
726 prepareConnections();
727 /* Prepare actions: */
728 prepareActions();
729 /* Prepare widgets: */
730 prepareWidgets();
731
732 /* Load settings: */
733 loadSettings();
734
735 /* Apply language settings: */
736 retranslateUi();
737
738 /* Start full medium-enumeration (if necessary): */
739 if (!uiCommon().isFullMediumEnumerationRequested())
740 uiCommon().enumerateMedia();
741 /* Emulate medium-enumeration otherwise: */
742 else
743 {
744 /* Emulate medium-enumeration start: */
745 sltHandleMediumEnumerationStart();
746
747 /* Emulate medium-enumeration finish (if necessary): */
748 if (!uiCommon().isMediumEnumerationInProgress())
749 sltHandleMediumEnumerationFinish();
750 }
751 uiCommon().setHelpKeyword(this,"virtual-media-manager");
752}
753
754void UIMediumManagerWidget::prepareConnections()
755{
756 /* Listen to vm state changed event so that we can disable/enable widgets related to the current medium if neds be: */
757 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
758 this, &UIMediumManagerWidget::sltHandleMachineStateChange);
759
760 /* Configure medium-processing connections: */
761 connect(&uiCommon(), &UICommon::sigMediumCreated,
762 this, &UIMediumManagerWidget::sltHandleMediumCreated);
763 connect(&uiCommon(), &UICommon::sigMediumDeleted,
764 this, &UIMediumManagerWidget::sltHandleMediumDeleted);
765
766 /* Configure medium-enumeration connections: */
767 connect(&uiCommon(), &UICommon::sigMediumEnumerationStarted,
768 this, &UIMediumManagerWidget::sltHandleMediumEnumerationStart);
769 connect(&uiCommon(), &UICommon::sigMediumEnumerated,
770 this, &UIMediumManagerWidget::sltHandleMediumEnumerated);
771 connect(&uiCommon(), &UICommon::sigMediumEnumerationFinished,
772 this, &UIMediumManagerWidget::sltHandleMediumEnumerationFinish);
773
774 /* Configure COM related connections: */
775 connect(&uiCommon(), &UICommon::sigAskToDetachCOM,
776 this, &UIMediumManagerWidget::sltDetachCOM);
777}
778
779void UIMediumManagerWidget::prepareActions()
780{
781 /* First of all, add actions which has smaller shortcut scope: */
782 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Add));
783 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Create));
784 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy));
785 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move));
786 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove));
787 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release));
788 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear));
789 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search));
790 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details));
791 addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh));
792
793 /* Connect actions: */
794 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Add), &QAction::triggered,
795 this, &UIMediumManagerWidget::sltAddMedium);
796 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Create), &QAction::triggered,
797 this, &UIMediumManagerWidget::sltCreateMedium);
798 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy), &QAction::triggered,
799 this, &UIMediumManagerWidget::sltCopyMedium);
800 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move), &QAction::triggered,
801 this, &UIMediumManagerWidget::sltMoveMedium);
802 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove), &QAction::triggered,
803 this, &UIMediumManagerWidget::sltRemoveMedium);
804 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release), &QAction::triggered,
805 this, &UIMediumManagerWidget::sltReleaseMedium);
806 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear), &QAction::triggered,
807 this, &UIMediumManagerWidget::sltClear);
808 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details), &QAction::toggled,
809 this, &UIMediumManagerWidget::sltToggleMediumDetailsVisibility);
810 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search), &QAction::toggled,
811 this, &UIMediumManagerWidget::sltToggleMediumSearchVisibility);
812 connect(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh), &QAction::triggered,
813 this, &UIMediumManagerWidget::sltRefreshAll);
814
815 /* Update action icons: */
816 updateActionIcons();
817}
818
819void UIMediumManagerWidget::prepareWidgets()
820{
821 /* Create main-layout: */
822 new QVBoxLayout(this);
823 AssertPtrReturnVoid(layout());
824 {
825 /* Configure layout: */
826 layout()->setContentsMargins(0, 0, 0, 0);
827#ifdef VBOX_WS_MAC
828 layout()->setSpacing(10);
829#else
830 layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
831#endif
832
833 /* Prepare toolbar, if requested: */
834 if (m_fShowToolbar)
835 prepareToolBar();
836 /* Prepare tab-widget: */
837 prepareTabWidget();
838 /* Prepare search-widget: */
839 prepareSearchWidget();
840 /* Prepare details-widget: */
841 prepareDetailsWidget();
842 }
843}
844
845void UIMediumManagerWidget::prepareToolBar()
846{
847 /* Create toolbar: */
848 m_pToolBar = new QIToolBar(parentWidget());
849 AssertPtrReturnVoid(m_pToolBar);
850 {
851 /* Configure toolbar: */
852 const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
853 m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
854 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
855
856 /* Add toolbar actions: */
857 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Add));
858 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Create));
859 m_pToolBar->addSeparator();
860 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy));
861 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move));
862 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove));
863 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release));
864 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear));
865 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search));
866 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details));
867 m_pToolBar->addSeparator();
868 m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Medium_S_Refresh));
869
870#ifdef VBOX_WS_MAC
871 /* Check whether we are embedded into a stack: */
872 if (m_enmEmbedding == EmbedTo_Stack)
873 {
874 /* Add into layout: */
875 layout()->addWidget(m_pToolBar);
876 }
877#else
878 /* Add into layout: */
879 layout()->addWidget(m_pToolBar);
880#endif
881 }
882}
883
884void UIMediumManagerWidget::prepareTabWidget()
885{
886 /* Create tab-widget: */
887 m_pTabWidget = new QITabWidget;
888 AssertPtrReturnVoid(m_pTabWidget);
889 {
890 /* Create tabs: */
891 for (int i = 0; i < m_iTabCount; ++i)
892 prepareTab((UIMediumDeviceType)i);
893 /* Configure tab-widget: */
894 m_pTabWidget->setFocusPolicy(Qt::TabFocus);
895 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_HardDisk), m_iconHD);
896 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_DVD), m_iconCD);
897 m_pTabWidget->setTabIcon(tabIndex(UIMediumDeviceType_Floppy), m_iconFD);
898 connect(m_pTabWidget, &QITabWidget::currentChanged, this, &UIMediumManagerWidget::sltHandleCurrentTabChanged);
899
900 /* Add tab-widget into central layout: */
901 layout()->addWidget(m_pTabWidget);
902
903 /* Update other widgets according chosen tab: */
904 sltHandleCurrentTabChanged();
905 }
906}
907
908void UIMediumManagerWidget::prepareTab(UIMediumDeviceType type)
909{
910 /* Create tab: */
911 m_pTabWidget->addTab(new QWidget, QString());
912 QWidget *pTab = tab(type);
913 AssertPtrReturnVoid(pTab);
914 {
915 /* Create tab layout: */
916 QVBoxLayout *pLayout = new QVBoxLayout(pTab);
917 AssertPtrReturnVoid(pLayout);
918 {
919#ifdef VBOX_WS_MAC
920 /* Configure layout: */
921 pLayout->setContentsMargins(10, 10, 10, 10);
922#endif
923
924 /* Prepare tree-widget: */
925 prepareTreeWidget(type, type == UIMediumDeviceType_HardDisk ? 3 : 2);
926 }
927 }
928}
929
930void UIMediumManagerWidget::prepareTreeWidget(UIMediumDeviceType type, int iColumns)
931{
932 /* Create tree-widget: */
933 m_trees.insert(tabIndex(type), new QITreeWidget);
934 QITreeWidget *pTreeWidget = treeWidget(type);
935 AssertPtrReturnVoid(pTreeWidget);
936 {
937 /* Configure tree-widget: */
938 pTreeWidget->setExpandsOnDoubleClick(false);
939 pTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
940 pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
941 pTreeWidget->setAlternatingRowColors(true);
942 pTreeWidget->setAllColumnsShowFocus(true);
943 pTreeWidget->setAcceptDrops(true);
944 pTreeWidget->setColumnCount(iColumns);
945 pTreeWidget->sortItems(0, Qt::AscendingOrder);
946 if (iColumns > 0)
947 pTreeWidget->header()->setSectionResizeMode(0, QHeaderView::Fixed);
948 if (iColumns > 1)
949 pTreeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
950 if (iColumns > 2)
951 pTreeWidget->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
952 pTreeWidget->header()->setStretchLastSection(false);
953 pTreeWidget->setSortingEnabled(true);
954 connect(pTreeWidget, &QITreeWidget::currentItemChanged,
955 this, &UIMediumManagerWidget::sltHandleCurrentItemChanged);
956 connect(pTreeWidget, &QITreeWidget::itemDoubleClicked,
957 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details), &QAction::setChecked);
958 connect(pTreeWidget, &QITreeWidget::customContextMenuRequested,
959 this, &UIMediumManagerWidget::sltHandleContextMenuRequest);
960 connect(pTreeWidget, &QITreeWidget::resized,
961 this, &UIMediumManagerWidget::sltPerformTablesAdjustment, Qt::QueuedConnection);
962 connect(pTreeWidget->header(), &QHeaderView::sectionResized,
963 this, &UIMediumManagerWidget::sltPerformTablesAdjustment, Qt::QueuedConnection);
964 /* Add tree-widget into tab layout: */
965 tab(type)->layout()->addWidget(pTreeWidget);
966 }
967}
968
969void UIMediumManagerWidget::prepareDetailsWidget()
970{
971 /* Create details-widget: */
972 m_pDetailsWidget = new UIMediumDetailsWidget(this, m_enmEmbedding);
973 AssertPtrReturnVoid(m_pDetailsWidget);
974 {
975 /* Configure details-widget: */
976 m_pDetailsWidget->setVisible(false);
977 m_pDetailsWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
978 connect(m_pDetailsWidget, &UIMediumDetailsWidget::sigAcceptAllowed,
979 this, &UIMediumManagerWidget::sigAcceptAllowed);
980 connect(m_pDetailsWidget, &UIMediumDetailsWidget::sigRejectAllowed,
981 this, &UIMediumManagerWidget::sigRejectAllowed);
982 connect(m_pDetailsWidget, &UIMediumDetailsWidget::sigDataChangeRejected,
983 this, &UIMediumManagerWidget::sltResetMediumDetailsChanges);
984 connect(m_pDetailsWidget, &UIMediumDetailsWidget::sigDataChangeAccepted,
985 this, &UIMediumManagerWidget::sltApplyMediumDetailsChanges);
986
987 /* Add into layout: */
988 layout()->addWidget(m_pDetailsWidget);
989 }
990}
991
992void UIMediumManagerWidget::prepareSearchWidget()
993{
994 m_pSearchWidget = new UIMediumSearchWidget(this);
995 AssertPtrReturnVoid(m_pSearchWidget);
996 {
997 m_pSearchWidget->setVisible(false);
998 m_pSearchWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
999 connect(m_pSearchWidget, &UIMediumSearchWidget::sigPerformSearch,
1000 this, &UIMediumManagerWidget::sltHandlePerformSearch);
1001
1002 /* Add into layout: */
1003 layout()->addWidget(m_pSearchWidget);
1004 }
1005
1006}
1007
1008void UIMediumManagerWidget::loadSettings()
1009{
1010 /* Details action/widget: */
1011 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details)->setChecked(gEDataManager->virtualMediaManagerDetailsExpanded());
1012 sltToggleMediumDetailsVisibility(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details)->isChecked());
1013
1014 /* Search action/widget: */
1015 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search)->setChecked(gEDataManager->virtualMediaManagerSearchWidgetExpanded());
1016 sltToggleMediumSearchVisibility(m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search)->isChecked());
1017}
1018
1019void UIMediumManagerWidget::repopulateTreeWidgets()
1020{
1021 /* Remember current medium-items: */
1022 if (UIMediumItem *pMediumItem = mediumItem(UIMediumDeviceType_HardDisk))
1023 m_uCurrentIdHD = pMediumItem->id();
1024 if (UIMediumItem *pMediumItem = mediumItem(UIMediumDeviceType_DVD))
1025 m_uCurrentIdCD = pMediumItem->id();
1026 if (UIMediumItem *pMediumItem = mediumItem(UIMediumDeviceType_Floppy))
1027 m_uCurrentIdFD = pMediumItem->id();
1028
1029 /* Clear tree-widgets: */
1030 QITreeWidget *pTreeWidgetHD = treeWidget(UIMediumDeviceType_HardDisk);
1031 if (pTreeWidgetHD)
1032 {
1033 setCurrentItem(pTreeWidgetHD, 0);
1034 pTreeWidgetHD->clear();
1035 }
1036 QITreeWidget *pTreeWidgetCD = treeWidget(UIMediumDeviceType_DVD);
1037 if (pTreeWidgetCD)
1038 {
1039 setCurrentItem(pTreeWidgetCD, 0);
1040 pTreeWidgetCD->clear();
1041 }
1042 QITreeWidget *pTreeWidgetFD = treeWidget(UIMediumDeviceType_Floppy);
1043 if (pTreeWidgetFD)
1044 {
1045 setCurrentItem(pTreeWidgetFD, 0);
1046 pTreeWidgetFD->clear();
1047 }
1048
1049 /* Create medium-items (do not change current one): */
1050 m_fPreventChangeCurrentItem = true;
1051 foreach (const QUuid &uMediumID, uiCommon().mediumIDs())
1052 sltHandleMediumCreated(uMediumID);
1053 m_fPreventChangeCurrentItem = false;
1054
1055 /* Select first item as current one if nothing selected: */
1056 if (pTreeWidgetHD && !mediumItem(UIMediumDeviceType_HardDisk))
1057 if (QTreeWidgetItem *pItem = pTreeWidgetHD->topLevelItem(0))
1058 setCurrentItem(pTreeWidgetHD, pItem);
1059 if (pTreeWidgetCD && !mediumItem(UIMediumDeviceType_DVD))
1060 if (QTreeWidgetItem *pItem = pTreeWidgetCD->topLevelItem(0))
1061 setCurrentItem(pTreeWidgetCD, pItem);
1062 if (pTreeWidgetFD && !mediumItem(UIMediumDeviceType_Floppy))
1063 if (QTreeWidgetItem *pItem = pTreeWidgetFD->topLevelItem(0))
1064 setCurrentItem(pTreeWidgetFD, pItem);
1065
1066 sltHandlePerformSearch();
1067}
1068
1069void UIMediumManagerWidget::refetchCurrentMediumItem(UIMediumDeviceType type)
1070{
1071 /* Get corresponding medium-item: */
1072 UIMediumItem *pMediumItem = mediumItem(type);
1073
1074#ifdef VBOX_WS_MAC
1075 /* Set the file for the proxy icon: */
1076 if (pMediumItem == currentMediumItem())
1077 setWindowFilePath(pMediumItem ? pMediumItem->location() : QString());
1078#endif /* VBOX_WS_MAC */
1079
1080 /* Make sure current medium-item visible: */
1081 if (pMediumItem)
1082 treeWidget(type)->scrollToItem(pMediumItem, QAbstractItemView::EnsureVisible);
1083
1084 /* Update actions: */
1085 updateActions();
1086
1087 /* Update details-widget: */
1088 if (m_pDetailsWidget)
1089 {
1090 m_pDetailsWidget->setData(pMediumItem ? *pMediumItem : UIDataMedium(type));
1091 if (pMediumItem && currentMediumItem())
1092 m_pDetailsWidget->enableDisableMediumModificationWidgets(currentMediumItem()->isMediumModifiable());
1093 }
1094}
1095
1096void UIMediumManagerWidget::refetchCurrentChosenMediumItem()
1097{
1098 refetchCurrentMediumItem(currentMediumType());
1099}
1100
1101void UIMediumManagerWidget::refetchCurrentMediumItems()
1102{
1103 refetchCurrentMediumItem(UIMediumDeviceType_HardDisk);
1104 refetchCurrentMediumItem(UIMediumDeviceType_DVD);
1105 refetchCurrentMediumItem(UIMediumDeviceType_Floppy);
1106}
1107
1108void UIMediumManagerWidget::updateActions()
1109{
1110 /* Get current medium-item: */
1111 UIMediumItem *pMediumItem = currentMediumItem();
1112
1113 /* Calculate actions accessibility: */
1114 bool fNotInEnumeration = !uiCommon().isMediumEnumerationInProgress();
1115
1116 /* Apply actions accessibility: */
1117 bool fActionEnabledCopy = fNotInEnumeration && pMediumItem && checkMediumFor(pMediumItem, Action_Copy);
1118 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy)->setEnabled(fActionEnabledCopy);
1119 bool fActionEnabledMove = fNotInEnumeration && pMediumItem && checkMediumFor(pMediumItem, Action_Edit);
1120 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move)->setEnabled(fActionEnabledMove);
1121 bool fActionEnabledRemove = fNotInEnumeration && pMediumItem && checkMediumFor(pMediumItem, Action_Remove);
1122 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove)->setEnabled(fActionEnabledRemove);
1123 bool fActionEnabledRelease = fNotInEnumeration && pMediumItem && checkMediumFor(pMediumItem, Action_Release);
1124 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release)->setEnabled(fActionEnabledRelease);
1125 bool fActionEnabledDetails = true;
1126 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details)->setEnabled(fActionEnabledDetails);
1127}
1128
1129void UIMediumManagerWidget::updateActionIcons()
1130{
1131 const UIMediumDeviceType enmCurrentMediumType = currentMediumType();
1132 if (enmCurrentMediumType != UIMediumDeviceType_Invalid)
1133 {
1134 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Add)->setState((int)enmCurrentMediumType);
1135 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Create)->setState((int)enmCurrentMediumType);
1136 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Copy)->setState((int)enmCurrentMediumType);
1137 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Move)->setState((int)enmCurrentMediumType);
1138 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Remove)->setState((int)enmCurrentMediumType);
1139 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Release)->setState((int)enmCurrentMediumType);
1140 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear)->setState((int)enmCurrentMediumType);
1141 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Search)->setState((int)enmCurrentMediumType);
1142 m_pActionPool->action(UIActionIndexMN_M_Medium_T_Details)->setState((int)enmCurrentMediumType);
1143 }
1144}
1145
1146void UIMediumManagerWidget::updateTabIcons(UIMediumItem *pMediumItem, Action action)
1147{
1148 /* Make sure medium-item is valid: */
1149 AssertReturnVoid(pMediumItem);
1150
1151 /* Prepare data for tab: */
1152 const QIcon *pIcon = 0;
1153 bool *pfInaccessible = 0;
1154 const UIMediumDeviceType mediumType = pMediumItem->mediumType();
1155 switch (mediumType)
1156 {
1157 case UIMediumDeviceType_HardDisk:
1158 pIcon = &m_iconHD;
1159 pfInaccessible = &m_fInaccessibleHD;
1160 break;
1161 case UIMediumDeviceType_DVD:
1162 pIcon = &m_iconCD;
1163 pfInaccessible = &m_fInaccessibleCD;
1164 break;
1165 case UIMediumDeviceType_Floppy:
1166 pIcon = &m_iconFD;
1167 pfInaccessible = &m_fInaccessibleFD;
1168 break;
1169 default:
1170 AssertFailed();
1171 }
1172 AssertReturnVoid(pIcon && pfInaccessible);
1173
1174 switch (action)
1175 {
1176 case Action_Add:
1177 {
1178 /* Does it change the overall state? */
1179 if (*pfInaccessible || pMediumItem->state() != KMediumState_Inaccessible)
1180 break; /* no */
1181
1182 *pfInaccessible = true;
1183
1184 if (m_pTabWidget)
1185 m_pTabWidget->setTabIcon(tabIndex(mediumType), generalIconPool().warningIcon());
1186
1187 break;
1188 }
1189 case Action_Edit:
1190 case Action_Remove:
1191 {
1192 bool fCheckRest = false;
1193
1194 if (action == Action_Edit)
1195 {
1196 /* Does it change the overall state? */
1197 if ((*pfInaccessible && pMediumItem->state() == KMediumState_Inaccessible) ||
1198 (!*pfInaccessible && pMediumItem->state() != KMediumState_Inaccessible))
1199 break; /* no */
1200
1201 /* Is the given item in charge? */
1202 if (!*pfInaccessible && pMediumItem->state() == KMediumState_Inaccessible)
1203 *pfInaccessible = true; /* yes */
1204 else
1205 fCheckRest = true; /* no */
1206 }
1207 else
1208 fCheckRest = true;
1209
1210 if (fCheckRest)
1211 {
1212 /* Find the first KMediumState_Inaccessible item to be in charge: */
1213 CheckIfSuitableByState lookForState(KMediumState_Inaccessible);
1214 CheckIfSuitableByID ignoreID(pMediumItem->id());
1215 UIMediumItem *pInaccessibleMediumItem = searchItem(pMediumItem->parentTree(), lookForState, &ignoreID);
1216 *pfInaccessible = !!pInaccessibleMediumItem;
1217 }
1218
1219 if (m_pTabWidget)
1220 {
1221 if (*pfInaccessible)
1222 m_pTabWidget->setTabIcon(tabIndex(mediumType), generalIconPool().warningIcon());
1223 else
1224 m_pTabWidget->setTabIcon(tabIndex(mediumType), *pIcon);
1225 }
1226
1227 break;
1228 }
1229
1230 default:
1231 break;
1232 }
1233}
1234
1235UIMediumItem* UIMediumManagerWidget::createMediumItem(const UIMedium &medium)
1236{
1237 /* Get medium type: */
1238 UIMediumDeviceType type = medium.type();
1239
1240 /* Create medium-item: */
1241 UIMediumItem *pMediumItem = 0;
1242 switch (type)
1243 {
1244 /* Of hard-drive type: */
1245 case UIMediumDeviceType_HardDisk:
1246 {
1247 /* Make sure corresponding tree-widget exists: */
1248 QITreeWidget *pTreeWidget = treeWidget(UIMediumDeviceType_HardDisk);
1249 if (pTreeWidget)
1250 {
1251 /* Recursively create hard-drive item: */
1252 pMediumItem = createHardDiskItem(medium);
1253 /* Make sure item was created: */
1254 if (!pMediumItem)
1255 break;
1256 if (pMediumItem->id() == m_uCurrentIdHD)
1257 {
1258 setCurrentItem(pTreeWidget, pMediumItem);
1259 m_uCurrentIdHD = QUuid();
1260 }
1261 }
1262 break;
1263 }
1264 /* Of optical-image type: */
1265 case UIMediumDeviceType_DVD:
1266 {
1267 /* Make sure corresponding tree-widget exists: */
1268 QITreeWidget *pTreeWidget = treeWidget(UIMediumDeviceType_DVD);
1269 if (pTreeWidget)
1270 {
1271 /* Create optical-disk item: */
1272 pMediumItem = new UIMediumItemCD(medium, pTreeWidget);
1273 /* Make sure item was created: */
1274 if (!pMediumItem)
1275 break;
1276 LogRel2(("UIMediumManager: Optical medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
1277 if (pMediumItem->id() == m_uCurrentIdCD)
1278 {
1279 setCurrentItem(pTreeWidget, pMediumItem);
1280 m_uCurrentIdCD = QUuid();
1281 }
1282 }
1283 break;
1284 }
1285 /* Of floppy-image type: */
1286 case UIMediumDeviceType_Floppy:
1287 {
1288 /* Make sure corresponding tree-widget exists: */
1289 QITreeWidget *pTreeWidget = treeWidget(UIMediumDeviceType_Floppy);
1290 if (pTreeWidget)
1291 {
1292 /* Create floppy-disk item: */
1293 pMediumItem = new UIMediumItemFD(medium, pTreeWidget);
1294 /* Make sure item was created: */
1295 if (!pMediumItem)
1296 break;
1297 LogRel2(("UIMediumManager: Floppy medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
1298 if (pMediumItem->id() == m_uCurrentIdFD)
1299 {
1300 setCurrentItem(pTreeWidget, pMediumItem);
1301 m_uCurrentIdFD = QUuid();
1302 }
1303 }
1304 break;
1305 }
1306 default: AssertMsgFailed(("Medium-type unknown: %d\n", type)); break;
1307 }
1308
1309 /* Make sure item was created: */
1310 if (!pMediumItem)
1311 return 0;
1312
1313 /* Update tab-icons: */
1314 updateTabIcons(pMediumItem, Action_Add);
1315
1316 /* Toogle enable/disable of clear action: */
1317 enableClearAction();
1318
1319 /* Reperform the medium search (don't jump to the found element): */
1320 performSearch(false);
1321
1322 /* Re-fetch medium-item if it is current one created: */
1323 if (pMediumItem == mediumItem(type))
1324 refetchCurrentMediumItem(type);
1325
1326 /* Return created medium-item: */
1327 return pMediumItem;
1328}
1329
1330UIMediumItem* UIMediumManagerWidget::createHardDiskItem(const UIMedium &medium)
1331{
1332 /* Make sure passed medium is valid: */
1333 AssertReturn(!medium.medium().isNull(), 0);
1334
1335 /* Make sure corresponding tree-widget exists: */
1336 QITreeWidget *pTreeWidget = treeWidget(UIMediumDeviceType_HardDisk);
1337 if (pTreeWidget)
1338 {
1339 /* Search for existing medium-item: */
1340 UIMediumItem *pMediumItem = searchItem(pTreeWidget, CheckIfSuitableByID(medium.id()));
1341
1342 /* If medium-item do not exists: */
1343 if (!pMediumItem)
1344 {
1345 /* If medium have a parent: */
1346 if (medium.parentID() != UIMedium::nullID())
1347 {
1348 /* Try to find parent medium-item: */
1349 UIMediumItem *pParentMediumItem = searchItem(pTreeWidget, CheckIfSuitableByID(medium.parentID()));
1350 /* If parent medium-item was not found: */
1351 if (!pParentMediumItem)
1352 {
1353 /* Make sure corresponding parent medium is already cached! */
1354 UIMedium parentMedium = uiCommon().medium(medium.parentID());
1355 if (parentMedium.isNull())
1356 AssertMsgFailed(("Parent medium with ID={%s} was not found!\n", medium.parentID().toString().toUtf8().constData()));
1357 /* Try to create parent medium-item: */
1358 else
1359 pParentMediumItem = createHardDiskItem(parentMedium);
1360 }
1361 /* If parent medium-item was found: */
1362 if (pParentMediumItem)
1363 {
1364 pMediumItem = new UIMediumItemHD(medium, pParentMediumItem);
1365 LogRel2(("UIMediumManager: Child hard-disk medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
1366 }
1367 }
1368 /* Else just create item as top-level one: */
1369 if (!pMediumItem)
1370 {
1371 pMediumItem = new UIMediumItemHD(medium, pTreeWidget);
1372 LogRel2(("UIMediumManager: Root hard-disk medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
1373 }
1374 }
1375
1376 /* Return created medium-item: */
1377 return pMediumItem;
1378 }
1379
1380 /* Return null by default: */
1381 return 0;
1382}
1383
1384void UIMediumManagerWidget::updateMediumItem(const UIMedium &medium)
1385{
1386 /* Get medium type: */
1387 UIMediumDeviceType type = medium.type();
1388
1389 /* Search for existing medium-item: */
1390 UIMediumItem *pMediumItem = searchItem(treeWidget(type), CheckIfSuitableByID(medium.id()));
1391
1392 /* Create item if doesn't exists: */
1393 if (!pMediumItem)
1394 pMediumItem = createMediumItem(medium);
1395
1396 /* Make sure item was created: */
1397 if (!pMediumItem)
1398 return;
1399
1400 /* Update medium-item: */
1401 pMediumItem->setMedium(medium);
1402 LogRel2(("UIMediumManager: Medium-item with ID={%s} updated.\n", medium.id().toString().toUtf8().constData()));
1403
1404 /* Update tab-icons: */
1405 updateTabIcons(pMediumItem, Action_Edit);
1406
1407 /* Toogle enable/disable of clear action: */
1408 enableClearAction();
1409
1410 /* Re-fetch medium-item if it is current one updated: */
1411 if (pMediumItem == mediumItem(type))
1412 refetchCurrentMediumItem(type);
1413
1414 /* Update all the children recursively as well: */
1415 foreach(const QUuid &uMediumId, uiCommon().mediumIDs())
1416 {
1417 UIMedium guiMedium = uiCommon().medium(uMediumId);
1418 if ( !guiMedium.isNull()
1419 && guiMedium.parentID() == medium.id())
1420 updateMediumItem(guiMedium);
1421 }
1422}
1423
1424void UIMediumManagerWidget::deleteMediumItem(const QUuid &uMediumID)
1425{
1426 /* Search for corresponding tree-widget: */
1427 QList<UIMediumDeviceType> types;
1428 types << UIMediumDeviceType_HardDisk << UIMediumDeviceType_DVD << UIMediumDeviceType_Floppy;
1429 QITreeWidget *pTreeWidget = 0;
1430 UIMediumItem *pMediumItem = 0;
1431 foreach (UIMediumDeviceType type, types)
1432 {
1433 /* Get iterated tree-widget: */
1434 pTreeWidget = treeWidget(type);
1435 /* Search for existing medium-item: */
1436 pMediumItem = searchItem(pTreeWidget, CheckIfSuitableByID(uMediumID));
1437 if (pMediumItem)
1438 break;
1439 }
1440
1441 /* Make sure item was found: */
1442 if (!pMediumItem)
1443 return;
1444
1445 /* Update tab-icons: */
1446 updateTabIcons(pMediumItem, Action_Remove);
1447
1448 /* Toogle enable/disable of clear action: */
1449 enableClearAction();
1450
1451 /* Delete medium-item: */
1452 delete pMediumItem;
1453 LogRel2(("UIMediumManager: Medium-item with ID={%s} deleted.\n", uMediumID.toString().toUtf8().constData()));
1454
1455 /* Reperform the medium search (don't jump to the found element): */
1456 performSearch(false);
1457
1458 /* If there is no current medium-item now selected
1459 * we have to choose first-available medium-item as current one: */
1460 if (!pTreeWidget->currentItem())
1461 setCurrentItem(pTreeWidget, pTreeWidget->topLevelItem(0));
1462}
1463
1464QWidget* UIMediumManagerWidget::tab(UIMediumDeviceType type) const
1465{
1466 /* Determine tab index for passed medium type: */
1467 int iIndex = tabIndex(type);
1468
1469 /* Return tab for known tab index: */
1470 if (iIndex >= 0 && iIndex < m_iTabCount)
1471 return iIndex < m_pTabWidget->count() ? m_pTabWidget->widget(iIndex) : 0;
1472
1473 /* Null by default: */
1474 return 0;
1475}
1476
1477QITreeWidget* UIMediumManagerWidget::treeWidget(UIMediumDeviceType type) const
1478{
1479 /* Determine tab index for passed medium type: */
1480 int iIndex = tabIndex(type);
1481
1482 /* Return tree-widget for known tab index: */
1483 if (iIndex >= 0 && iIndex < m_iTabCount)
1484 return m_trees.value(iIndex, 0);
1485
1486 /* Null by default: */
1487 return 0;
1488}
1489
1490UIMediumItem* UIMediumManagerWidget::mediumItem(UIMediumDeviceType type) const
1491{
1492 /* Get corresponding tree-widget: */
1493 QITreeWidget *pTreeWidget = treeWidget(type);
1494 /* Return corresponding medium-item: */
1495 return pTreeWidget ? toMediumItem(pTreeWidget->currentItem()) : 0;
1496}
1497
1498UIMediumDeviceType UIMediumManagerWidget::mediumType(QITreeWidget *pTreeWidget) const
1499{
1500 /* Determine tab index of passed tree-widget: */
1501 int iIndex = m_trees.key(pTreeWidget, -1);
1502
1503 /* Return medium type for known tab index: */
1504 if (iIndex >= 0 && iIndex < m_iTabCount)
1505 return (UIMediumDeviceType)iIndex;
1506
1507 /* Invalid by default: */
1508 AssertFailedReturn(UIMediumDeviceType_Invalid);
1509}
1510
1511UIMediumDeviceType UIMediumManagerWidget::currentMediumType() const
1512{
1513 /* Invalid if tab-widget doesn't exists: */
1514 if (!m_pTabWidget)
1515 return UIMediumDeviceType_Invalid;
1516
1517 /* Return current medium type: */
1518 return (UIMediumDeviceType)m_pTabWidget->currentIndex();
1519}
1520
1521QITreeWidget* UIMediumManagerWidget::currentTreeWidget() const
1522{
1523 /* Return current tree-widget: */
1524 return treeWidget(currentMediumType());
1525}
1526
1527UIMediumItem* UIMediumManagerWidget::currentMediumItem() const
1528{
1529 /* Return current medium-item: */
1530 return mediumItem(currentMediumType());
1531}
1532
1533void UIMediumManagerWidget::setCurrentItem(QITreeWidget *pTreeWidget, QTreeWidgetItem *pItem)
1534{
1535 /* Make sure passed tree-widget is valid: */
1536 AssertPtrReturnVoid(pTreeWidget);
1537
1538 /* Make passed item current for passed tree-widget: */
1539 pTreeWidget->setCurrentItem(pItem);
1540
1541 /* If non NULL item was passed: */
1542 if (pItem)
1543 {
1544 /* Make sure it's also selected, and visible: */
1545 pItem->setSelected(true);
1546 pTreeWidget->scrollToItem(pItem, QAbstractItemView::EnsureVisible);
1547 }
1548
1549 /* Re-fetch currently chosen medium-item: */
1550 refetchCurrentChosenMediumItem();
1551}
1552
1553void UIMediumManagerWidget::enableClearAction()
1554{
1555 if (!m_pActionPool || !m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear))
1556 return;
1557
1558 if (currentMediumType() == UIMediumDeviceType_HardDisk)
1559 {
1560 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear)->setVisible(false);
1561 return;
1562 }
1563 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear)->setVisible(true);
1564 bool fEnable = ((currentMediumType() == UIMediumDeviceType_DVD) && m_fInaccessibleCD) ||
1565 ((currentMediumType() == UIMediumDeviceType_Floppy) && m_fInaccessibleFD);
1566 m_pActionPool->action(UIActionIndexMN_M_Medium_S_Clear)->setEnabled(fEnable);
1567}
1568
1569void UIMediumManagerWidget::performSearch(bool fSelectNext)
1570{
1571 if (!m_pSearchWidget || !m_pTabWidget)
1572 return;
1573
1574 QITreeWidget *pTreeWidget = treeWidget(static_cast<UIMediumDeviceType>(m_pTabWidget->currentIndex()));
1575 if (!pTreeWidget)
1576 return;
1577 m_pSearchWidget->search(pTreeWidget, fSelectNext);
1578}
1579
1580/* static */
1581int UIMediumManagerWidget::tabIndex(UIMediumDeviceType type)
1582{
1583 /* Return tab index corresponding to known medium type: */
1584 switch (type)
1585 {
1586 case UIMediumDeviceType_HardDisk: return 0;
1587 case UIMediumDeviceType_DVD: return 1;
1588 case UIMediumDeviceType_Floppy: return 2;
1589 default: break;
1590 }
1591
1592 /* -1 by default: */
1593 return -1;
1594}
1595
1596/* static */
1597UIMediumItem* UIMediumManagerWidget::searchItem(QITreeWidget *pTreeWidget, const CheckIfSuitableBy &condition, CheckIfSuitableBy *pException)
1598{
1599 /* Make sure argument is valid: */
1600 if (!pTreeWidget)
1601 return 0;
1602
1603 /* Return wrapper: */
1604 return searchItem(pTreeWidget->invisibleRootItem(), condition, pException);
1605}
1606
1607/* static */
1608UIMediumItem* UIMediumManagerWidget::searchItem(QTreeWidgetItem *pParentItem, const CheckIfSuitableBy &condition, CheckIfSuitableBy *pException)
1609{
1610 /* Make sure argument is valid: */
1611 if (!pParentItem)
1612 return 0;
1613
1614 /* Verify passed item if it is of 'medium' type too: */
1615 if (UIMediumItem *pMediumParentItem = toMediumItem(pParentItem))
1616 if ( condition.isItSuitable(pMediumParentItem)
1617 && (!pException || !pException->isItSuitable(pMediumParentItem)))
1618 return pMediumParentItem;
1619
1620 /* Iterate other all the children: */
1621 for (int iChildIndex = 0; iChildIndex < pParentItem->childCount(); ++iChildIndex)
1622 if (UIMediumItem *pMediumChildItem = toMediumItem(pParentItem->child(iChildIndex)))
1623 if (UIMediumItem *pRequiredMediumChildItem = searchItem(pMediumChildItem, condition, pException))
1624 return pRequiredMediumChildItem;
1625
1626 /* Null by default: */
1627 return 0;
1628}
1629
1630/* static */
1631bool UIMediumManagerWidget::checkMediumFor(UIMediumItem *pItem, Action action)
1632{
1633 /* Make sure passed ID is valid: */
1634 AssertReturn(pItem, false);
1635
1636 switch (action)
1637 {
1638 case Action_Edit:
1639 {
1640 /* Edit means changing the description and alike; any media that is
1641 * not being read to or written from can be altered in these terms. */
1642 switch (pItem->state())
1643 {
1644 case KMediumState_NotCreated:
1645 case KMediumState_Inaccessible:
1646 case KMediumState_LockedRead:
1647 case KMediumState_LockedWrite:
1648 return false;
1649 default:
1650 break;
1651 }
1652 return true;
1653 }
1654 case Action_Copy:
1655 {
1656 return true;
1657 }
1658 case Action_Remove:
1659 {
1660 /* Removable if not attached to anything: */
1661 return !pItem->isUsed();
1662 }
1663 case Action_Release:
1664 {
1665 /* Releasable if attached but not in snapshots: */
1666 return pItem->isUsed() && !pItem->isUsedInSnapshots();
1667 }
1668
1669 default:
1670 break;
1671 }
1672
1673 AssertFailedReturn(false);
1674}
1675
1676/* static */
1677UIMediumItem* UIMediumManagerWidget::toMediumItem(QTreeWidgetItem *pItem)
1678{
1679 /* Cast passed QTreeWidgetItem to UIMediumItem if possible: */
1680 return pItem && pItem->type() == QITreeWidgetItem::ItemType ? static_cast<UIMediumItem*>(pItem) : 0;
1681}
1682
1683
1684/*********************************************************************************************************************************
1685* Class UIMediumManagerFactory implementation. *
1686*********************************************************************************************************************************/
1687
1688UIMediumManagerFactory::UIMediumManagerFactory(UIActionPool *pActionPool /* = 0 */)
1689 : m_pActionPool(pActionPool)
1690{
1691}
1692
1693void UIMediumManagerFactory::create(QIManagerDialog *&pDialog, QWidget *pCenterWidget)
1694{
1695 pDialog = new UIMediumManager(pCenterWidget, m_pActionPool);
1696}
1697
1698
1699/*********************************************************************************************************************************
1700* Class UIMediumManager implementation. *
1701*********************************************************************************************************************************/
1702
1703UIMediumManager::UIMediumManager(QWidget *pCenterWidget, UIActionPool *pActionPool)
1704 : QIWithRetranslateUI<QIManagerDialog>(pCenterWidget)
1705 , m_pActionPool(pActionPool)
1706 , m_pProgressBar(0)
1707{
1708}
1709
1710void UIMediumManager::sltHandleButtonBoxClick(QAbstractButton *pButton)
1711{
1712 /* Disable buttons first of all: */
1713 button(ButtonType_Reset)->setEnabled(false);
1714 button(ButtonType_Apply)->setEnabled(false);
1715
1716 /* Compare with known buttons: */
1717 if (pButton == button(ButtonType_Reset))
1718 emit sigDataChangeRejected();
1719 else
1720 if (pButton == button(ButtonType_Apply))
1721 emit sigDataChangeAccepted();
1722}
1723
1724void UIMediumManager::retranslateUi()
1725{
1726 /* Translate window title: */
1727 setWindowTitle(tr("Virtual Media Manager"));
1728
1729 /* Translate buttons: */
1730 button(ButtonType_Reset)->setText(tr("Reset"));
1731 button(ButtonType_Apply)->setText(tr("Apply"));
1732 button(ButtonType_Close)->setText(tr("Close"));
1733 button(ButtonType_Help)->setText(tr("Help"));
1734 button(ButtonType_Reset)->setStatusTip(tr("Reset changes in current medium details"));
1735 button(ButtonType_Apply)->setStatusTip(tr("Apply changes in current medium details"));
1736 button(ButtonType_Close)->setStatusTip(tr("Close dialog without saving"));
1737 button(ButtonType_Help)->setStatusTip(tr("Show dialog help"));
1738 button(ButtonType_Reset)->setShortcut(QString("Ctrl+Backspace"));
1739 button(ButtonType_Apply)->setShortcut(QString("Ctrl+Return"));
1740 button(ButtonType_Close)->setShortcut(Qt::Key_Escape);
1741 button(ButtonType_Help)->setShortcut(QKeySequence::HelpContents);
1742 button(ButtonType_Reset)->setToolTip(tr("Reset Changes (%1)").arg(button(ButtonType_Reset)->shortcut().toString()));
1743 button(ButtonType_Apply)->setToolTip(tr("Apply Changes (%1)").arg(button(ButtonType_Apply)->shortcut().toString()));
1744 button(ButtonType_Close)->setToolTip(tr("Close Window (%1)").arg(button(ButtonType_Close)->shortcut().toString()));
1745 button(ButtonType_Help)->setToolTip(tr("Show Help (%1)").arg(button(ButtonType_Help)->shortcut().toString()));
1746}
1747
1748void UIMediumManager::configure()
1749{
1750#ifndef VBOX_WS_MAC
1751 /* Assign window icon: */
1752 setWindowIcon(UIIconPool::iconSetFull(":/media_manager_32px.png", ":/media_manager_16px.png"));
1753#endif
1754}
1755
1756void UIMediumManager::configureCentralWidget()
1757{
1758 /* Create widget: */
1759 UIMediumManagerWidget *pWidget = new UIMediumManagerWidget(EmbedTo_Dialog, m_pActionPool, true, this);
1760 AssertPtrReturnVoid(pWidget);
1761 {
1762 /* Configure widget: */
1763 setWidget(pWidget);
1764 setWidgetMenu(pWidget->menu());
1765#ifdef VBOX_WS_MAC
1766 setWidgetToolbar(pWidget->toolbar());
1767#endif
1768 connect(this, &UIMediumManager::sigDataChangeRejected,
1769 pWidget, &UIMediumManagerWidget::sltResetMediumDetailsChanges);
1770 connect(this, &UIMediumManager::sigDataChangeAccepted,
1771 pWidget, &UIMediumManagerWidget::sltApplyMediumDetailsChanges);
1772
1773 /* Add into layout: */
1774 centralWidget()->layout()->addWidget(pWidget);
1775 }
1776}
1777
1778void UIMediumManager::configureButtonBox()
1779{
1780 /* Configure button-box: */
1781 connect(widget(), &UIMediumManagerWidget::sigMediumDetailsVisibilityChanged,
1782 button(ButtonType_Apply), &QPushButton::setVisible);
1783 connect(widget(), &UIMediumManagerWidget::sigMediumDetailsVisibilityChanged,
1784 button(ButtonType_Reset), &QPushButton::setVisible);
1785 connect(widget(), &UIMediumManagerWidget::sigAcceptAllowed,
1786 button(ButtonType_Apply), &QPushButton::setEnabled);
1787 connect(widget(), &UIMediumManagerWidget::sigRejectAllowed,
1788 button(ButtonType_Reset), &QPushButton::setEnabled);
1789 connect(buttonBox(), &QIDialogButtonBox::clicked,
1790 this, &UIMediumManager::sltHandleButtonBoxClick);
1791 // WORKAROUND:
1792 // Since we connected signals later than extra-data loaded
1793 // for signals above, we should handle that stuff here again:
1794 button(ButtonType_Apply)->setVisible(gEDataManager->virtualMediaManagerDetailsExpanded());
1795 button(ButtonType_Reset)->setVisible(gEDataManager->virtualMediaManagerDetailsExpanded());
1796
1797 /* Create progress-bar: */
1798 m_pProgressBar = new UIEnumerationProgressBar;
1799 AssertPtrReturnVoid(m_pProgressBar);
1800 {
1801 /* Configure progress-bar: */
1802 m_pProgressBar->hide();
1803 /* Add progress-bar into button-box layout: */
1804 buttonBox()->addExtraWidget(m_pProgressBar);
1805 /* Notify widget it has progress-bar: */
1806 widget()->setProgressBar(m_pProgressBar);
1807 }
1808}
1809
1810void UIMediumManager::finalize()
1811{
1812 /* Apply language settings: */
1813 retranslateUi();
1814}
1815
1816UIMediumManagerWidget *UIMediumManager::widget()
1817{
1818 return qobject_cast<UIMediumManagerWidget*>(QIManagerDialog::widget());
1819}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette