VirtualBox

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

Last change on this file was 104393, checked in by vboxsync, 4 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the UIActionPool class.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use