VirtualBox

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

Last change on this file since 104158 was 103988, checked in by vboxsync, 9 months ago

FE/Qt. bugref:10624. Adding missing override keywords gcc has found.

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