VirtualBox

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

Last change on this file was 105565, checked in by vboxsync, 6 weeks ago

FE/Qt: bugref:10736. Removing now-obsolete clone vd wizard files.

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