VirtualBox

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

Last change on this file was 104904, checked in by vboxsync, 3 months ago

FE/Qt: UICommon: Get rid of rest of media related stuff (especially medium-enumeration signals and slots) by moving it to UIMediumEnumerator; Adjust the GUI to work accodringly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.4 KB
Line 
1/* $Id: UIMediumSelector.cpp 104904 2024-06-12 17:06:56Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMediumSelector 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 <QAction>
30#include <QApplication>
31#include <QHeaderView>
32#include <QMenuBar>
33#include <QVBoxLayout>
34#include <QPushButton>
35
36/* GUI includes: */
37#include "QIDialogButtonBox.h"
38#include "QIFileDialog.h"
39#include "QIMessageBox.h"
40#include "QITabWidget.h"
41#include "QIToolBar.h"
42#include "QIToolButton.h"
43#include "UIActionPool.h"
44#include "UIDesktopWidgetWatchdog.h"
45#include "UIExtraDataManager.h"
46#include "UILoggingDefs.h"
47#include "UIMediumEnumerator.h"
48#include "UIMediumSearchWidget.h"
49#include "UIMediumSelector.h"
50#include "UIMediumTools.h"
51#include "UIMessageCenter.h"
52#include "UIModalWindowManager.h"
53#include "UIIconPool.h"
54#include "UIMedium.h"
55#include "UIMediumItem.h"
56#include "UITranslationEventListener.h"
57
58/* COM includes: */
59#include "CMachine.h"
60#include "CMediumAttachment.h"
61#include "CMediumFormat.h"
62#include "CStorageController.h"
63#include "CSystemProperties.h"
64
65#ifdef VBOX_WS_MAC
66# include "UIWindowMenuManager.h"
67#endif /* VBOX_WS_MAC */
68
69
70UIMediumSelector::UIMediumSelector(const QUuid &uCurrentMediumId, UIMediumDeviceType enmMediumType, const QString &machineName,
71 const QString &machineSettingsFilePath, const QString &strMachineGuestOSTypeId,
72 const QUuid &uMachineID, QWidget *pParent, UIActionPool *pActionPool)
73 : QIWithRestorableGeometry<QIMainDialog>(pParent)
74 , m_pCentralWidget(0)
75 , m_pMainLayout(0)
76 , m_pTreeWidget(0)
77 , m_enmMediumType(enmMediumType)
78 , m_pButtonBox(0)
79 , m_pCancelButton(0)
80 , m_pChooseButton(0)
81 , m_pLeaveEmptyButton(0)
82 , m_pMainMenu(0)
83 , m_pToolBar(0)
84 , m_pActionAdd(0)
85 , m_pActionCreate(0)
86 , m_pActionRefresh(0)
87 , m_pAttachedSubTreeRoot(0)
88 , m_pNotAttachedSubTreeRoot(0)
89 , m_pParent(pParent)
90 , m_pSearchWidget(0)
91 , m_iCurrentShownIndex(0)
92 , m_strMachineFolder(machineSettingsFilePath)
93 , m_strMachineName(machineName)
94 , m_strMachineGuestOSTypeId(strMachineGuestOSTypeId)
95 , m_uMachineID(uMachineID)
96 , m_pActionPool(pActionPool)
97 , m_iGeometrySaveTimerId(-1)
98{
99 /* Start full medium-enumeration (if necessary): */
100 if (!gpMediumEnumerator->isFullMediumEnumerationRequested())
101 gpMediumEnumerator->enumerateMedia();
102 configure();
103 finalize();
104 selectMedium(uCurrentMediumId);
105 loadSettings();
106}
107
108void UIMediumSelector::setEnableCreateAction(bool fEnable)
109{
110 if (!m_pActionCreate)
111 return;
112 m_pActionCreate->setEnabled(fEnable);
113 m_pActionCreate->setVisible(fEnable);
114}
115
116QList<QUuid> UIMediumSelector::selectedMediumIds() const
117{
118 QList<QUuid> selectedIds;
119 if (!m_pTreeWidget)
120 return selectedIds;
121 QList<QTreeWidgetItem*> selectedItems = m_pTreeWidget->selectedItems();
122 for (int i = 0; i < selectedItems.size(); ++i)
123 {
124 UIMediumItem *item = dynamic_cast<UIMediumItem*>(selectedItems.at(i));
125 if (item)
126 selectedIds.push_back(item->medium().id());
127 }
128 return selectedIds;
129}
130
131/* static */
132int UIMediumSelector::openMediumSelectorDialog(QWidget *pParent, UIMediumDeviceType enmMediumType, const QUuid &uCurrentMediumId,
133 QUuid &uSelectedMediumUuid, const QString &strMachineFolder, const QString &strMachineName,
134 const QString &strMachineGuestOSTypeId, bool fEnableCreate, const QUuid &uMachineID,
135 UIActionPool *pActionPool)
136{
137 QUuid uMachineOrGlobalId = uMachineID == QUuid() ? gEDataManager->GlobalID : uMachineID;
138
139 QWidget *pDialogParent = windowManager().realParentWindow(pParent);
140 QPointer<UIMediumSelector> pSelector = new UIMediumSelector(uCurrentMediumId, enmMediumType, strMachineName,
141 strMachineFolder, strMachineGuestOSTypeId,
142 uMachineOrGlobalId, pDialogParent, pActionPool);
143
144 if (!pSelector)
145 return static_cast<int>(UIMediumSelector::ReturnCode_Rejected);
146 pSelector->setEnableCreateAction(fEnableCreate);
147 windowManager().registerNewParent(pSelector, pDialogParent);
148
149 int iResult = pSelector->exec(false);
150 UIMediumSelector::ReturnCode returnCode;
151
152 if (iResult >= static_cast<int>(UIMediumSelector::ReturnCode_Max) || iResult < 0)
153 returnCode = UIMediumSelector::ReturnCode_Rejected;
154 else
155 returnCode = static_cast<UIMediumSelector::ReturnCode>(iResult);
156
157 if (returnCode == UIMediumSelector::ReturnCode_Accepted)
158 {
159 QList<QUuid> selectedMediumIds = pSelector->selectedMediumIds();
160
161 /* Currently we only care about the 0th since we support single selection by intention: */
162 if (selectedMediumIds.isEmpty())
163 returnCode = UIMediumSelector::ReturnCode_Rejected;
164 else
165 {
166 uSelectedMediumUuid = selectedMediumIds[0];
167 gpMediumEnumerator->updateRecentlyUsedMediumListAndFolder(enmMediumType,
168 gpMediumEnumerator->medium(uSelectedMediumUuid).location());
169 }
170 }
171 delete pSelector;
172 return static_cast<int>(returnCode);
173}
174
175void UIMediumSelector::sltRetranslateUI()
176{
177 if (m_pCancelButton)
178 {
179 m_pCancelButton->setText(tr("&Cancel"));
180 m_pCancelButton->setToolTip(tr("Cancel"));
181 }
182 if (m_pLeaveEmptyButton)
183 {
184 m_pLeaveEmptyButton->setText(tr("Leave &Empty"));
185 m_pLeaveEmptyButton->setToolTip(tr("Leave the drive empty"));
186 }
187
188 if (m_pChooseButton)
189 {
190 m_pChooseButton->setText(tr("C&hoose"));
191 m_pChooseButton->setToolTip(tr("Attach the selected medium to the drive"));
192 }
193
194 if (m_pTreeWidget)
195 {
196 m_pTreeWidget->setWhatsThis(tr("Shows a list of all registered media"));
197 m_pTreeWidget->headerItem()->setText(0, tr("Name"));
198 m_pTreeWidget->headerItem()->setText(1, tr("Virtual Size"));
199 m_pTreeWidget->headerItem()->setText(2, tr("Actual Size"));
200 }
201}
202
203bool UIMediumSelector::event(QEvent *pEvent)
204{
205 if (pEvent->type() == QEvent::Resize || pEvent->type() == QEvent::Move)
206 {
207 if (m_iGeometrySaveTimerId != -1)
208 killTimer(m_iGeometrySaveTimerId);
209 m_iGeometrySaveTimerId = startTimer(300);
210 }
211 else if (pEvent->type() == QEvent::Timer)
212 {
213 QTimerEvent *pTimerEvent = static_cast<QTimerEvent*>(pEvent);
214 if (pTimerEvent->timerId() == m_iGeometrySaveTimerId)
215 {
216 killTimer(m_iGeometrySaveTimerId);
217 m_iGeometrySaveTimerId = -1;
218 saveDialogGeometry();
219 }
220 }
221 return QIWithRestorableGeometry<QIMainDialog>::event(pEvent);
222}
223
224void UIMediumSelector::configure()
225{
226#ifndef VBOX_WS_MAC
227 /* Assign window icon: */
228 setWindowIcon(UIIconPool::iconSetFull(":/media_manager_32px.png", ":/media_manager_16px.png"));
229#endif
230
231 setTitle();
232 prepareWidgets();
233 prepareActions();
234 prepareMenuAndToolBar();
235 prepareConnections();
236}
237
238void UIMediumSelector::prepareActions()
239{
240 if (!m_pActionPool)
241 return;
242
243 switch (m_enmMediumType)
244 {
245 case UIMediumDeviceType_DVD:
246 m_pActionAdd = m_pActionPool->action(UIActionIndex_M_MediumSelector_AddCD);
247 m_pActionCreate = m_pActionPool->action(UIActionIndex_M_MediumSelector_CreateCD);
248 break;
249 case UIMediumDeviceType_Floppy:
250 m_pActionAdd = m_pActionPool->action(UIActionIndex_M_MediumSelector_AddFD);
251 m_pActionCreate = m_pActionPool->action(UIActionIndex_M_MediumSelector_CreateFD);
252 break;
253 case UIMediumDeviceType_HardDisk:
254 case UIMediumDeviceType_All:
255 case UIMediumDeviceType_Invalid:
256 default:
257 m_pActionAdd = m_pActionPool->action(UIActionIndex_M_MediumSelector_AddHD);
258 m_pActionCreate = m_pActionPool->action(UIActionIndex_M_MediumSelector_CreateHD);
259 break;
260 }
261
262 m_pActionRefresh = m_pActionPool->action(UIActionIndex_M_MediumSelector_Refresh);
263}
264
265void UIMediumSelector::prepareMenuAndToolBar()
266{
267 if (!m_pMainMenu || !m_pToolBar)
268 return;
269
270 m_pMainMenu->addAction(m_pActionAdd);
271 m_pMainMenu->addAction(m_pActionCreate);
272 m_pMainMenu->addSeparator();
273 m_pMainMenu->addAction(m_pActionRefresh);
274
275 m_pToolBar->addAction(m_pActionAdd);
276 if (!(gEDataManager->restrictedDialogTypes(m_uMachineID) & UIExtraDataMetaDefs::DialogType_VISOCreator))
277 m_pToolBar->addAction(m_pActionCreate);
278 m_pToolBar->addSeparator();
279 m_pToolBar->addAction(m_pActionRefresh);
280}
281
282void UIMediumSelector::prepareConnections()
283{
284 /* Configure medium-enumeration connections: */
285 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumCreated,
286 this, &UIMediumSelector::sltHandleMediumCreated);
287 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationStarted,
288 this, &UIMediumSelector::sltHandleMediumEnumerationStart);
289 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerated,
290 this, &UIMediumSelector::sltHandleMediumEnumerated);
291 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationFinished,
292 this, &UIMediumSelector::sltHandleMediumEnumerationFinish);
293 if (m_pActionAdd)
294 connect(m_pActionAdd, &QAction::triggered, this, &UIMediumSelector::sltAddMedium);
295 if (m_pActionCreate)
296 connect(m_pActionCreate, &QAction::triggered, this, &UIMediumSelector::sltCreateMedium);
297 if (m_pActionRefresh)
298 connect(m_pActionRefresh, &QAction::triggered, this, &UIMediumSelector::sltHandleRefresh);
299
300 if (m_pTreeWidget)
301 {
302 connect(m_pTreeWidget, &QITreeWidget::itemSelectionChanged, this, &UIMediumSelector::sltHandleItemSelectionChanged);
303 connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked, this, &UIMediumSelector::sltHandleTreeWidgetDoubleClick);
304 connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested, this, &UIMediumSelector::sltHandleTreeContextMenuRequest);
305 }
306
307 if (m_pCancelButton)
308 connect(m_pCancelButton, &QPushButton::clicked, this, &UIMediumSelector::sltButtonCancel);
309 if (m_pChooseButton)
310 connect(m_pChooseButton, &QPushButton::clicked, this, &UIMediumSelector::sltButtonChoose);
311 if (m_pLeaveEmptyButton)
312 connect(m_pLeaveEmptyButton, &QPushButton::clicked, this, &UIMediumSelector::sltButtonLeaveEmpty);
313
314 if (m_pSearchWidget)
315 {
316 connect(m_pSearchWidget, &UIMediumSearchWidget::sigPerformSearch,
317 this, &UIMediumSelector::sltHandlePerformSearch);
318 }
319}
320
321UIMediumItem* UIMediumSelector::addTreeItem(const UIMedium &medium, QITreeWidgetItem *pParent)
322{
323 if (!pParent)
324 return 0;
325 switch (m_enmMediumType)
326 {
327 case UIMediumDeviceType_DVD:
328 return new UIMediumItemCD(medium, pParent);
329 break;
330 case UIMediumDeviceType_Floppy:
331 return new UIMediumItemFD(medium, pParent);
332 break;
333 case UIMediumDeviceType_HardDisk:
334 case UIMediumDeviceType_All:
335 case UIMediumDeviceType_Invalid:
336 default:
337 return createHardDiskItem(medium, pParent);
338 break;
339 }
340}
341
342UIMediumItem* UIMediumSelector::createHardDiskItem(const UIMedium &medium, QITreeWidgetItem *pParent)
343{
344 if (medium.medium().isNull())
345 return 0;
346 if (!m_pTreeWidget)
347 return 0;
348 /* Search the tree to see if we already have the item: */
349 UIMediumItem *pMediumItem = searchItem(0, medium.id());
350 if (pMediumItem)
351 return pMediumItem;
352 /* Check if the corresponding medium has a parent */
353 if (medium.parentID() != UIMedium::nullID())
354 {
355 UIMediumItem *pParentMediumItem = searchItem(0, medium.parentID());
356 /* If parent medium-item was not found we create it: */
357 if (!pParentMediumItem)
358 {
359 /* Make sure corresponding parent medium is already cached! */
360 UIMedium parentMedium = gpMediumEnumerator->medium(medium.parentID());
361 if (parentMedium.isNull())
362 AssertMsgFailed(("Parent medium with ID={%s} was not found!\n", medium.parentID().toString().toUtf8().constData()));
363 /* Try to create parent medium-item: */
364 else
365 pParentMediumItem = createHardDiskItem(parentMedium, pParent);
366 }
367 if (pParentMediumItem)
368 {
369 pMediumItem = new UIMediumItemHD(medium, pParentMediumItem);
370 LogRel2(("UIMediumManager: Child hard-disk medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
371 }
372 else
373 AssertMsgFailed(("Parent medium with ID={%s} could not be created!\n", medium.parentID().toString().toUtf8().constData()));
374 }
375
376 /* No parents, thus just create item as top-level one: */
377 else
378 {
379 pMediumItem = new UIMediumItemHD(medium, pParent);
380 LogRel2(("UIMediumManager: Root hard-disk medium-item with ID={%s} created.\n", medium.id().toString().toUtf8().constData()));
381 }
382 return pMediumItem;
383}
384
385void UIMediumSelector::restoreSelection(const QList<QUuid> &selectedMediums, QVector<UIMediumItem*> &mediumList)
386{
387 if (!m_pTreeWidget)
388 return;
389 if (selectedMediums.isEmpty())
390 {
391 m_pTreeWidget->setCurrentItem(0);
392 return;
393 }
394 bool selected = false;
395 for (int i = 0; i < mediumList.size(); ++i)
396 {
397 if (!mediumList[i])
398 continue;
399 if (selectedMediums.contains(mediumList[i]->medium().id()))
400 {
401 mediumList[i]->setSelected(true);
402 selected = true;
403 }
404 }
405
406 if (!selected)
407 m_pTreeWidget->setCurrentItem(0);
408}
409
410void UIMediumSelector::prepareWidgets()
411{
412 m_pCentralWidget = new QWidget;
413 if (!m_pCentralWidget)
414 return;
415 setCentralWidget(m_pCentralWidget);
416
417 m_pMainLayout = new QVBoxLayout;
418 m_pCentralWidget->setLayout(m_pMainLayout);
419
420 if (!m_pMainLayout || !menuBar())
421 return;
422
423 if (m_pActionPool && m_pActionPool->action(UIActionIndex_M_MediumSelector))
424 {
425 m_pMainMenu = m_pActionPool->action(UIActionIndex_M_MediumSelector)->menu();
426 if (m_pMainMenu)
427 menuBar()->addMenu(m_pMainMenu);
428 }
429
430 m_pToolBar = new QIToolBar;
431 if (m_pToolBar)
432 {
433 /* Configure toolbar: */
434 const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
435 m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
436 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
437 m_pMainLayout->addWidget(m_pToolBar);
438 }
439
440 m_pTreeWidget = new QITreeWidget;
441 if (m_pTreeWidget)
442 {
443 m_pTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
444 m_pMainLayout->addWidget(m_pTreeWidget);
445 m_pTreeWidget->setAlternatingRowColors(true);
446 int iColumnCount = (m_enmMediumType == UIMediumDeviceType_HardDisk) ? 3 : 2;
447 m_pTreeWidget->setColumnCount(iColumnCount);
448 m_pTreeWidget->setSortingEnabled(true);
449 m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
450 m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
451 }
452
453 m_pSearchWidget = new UIMediumSearchWidget;
454 if (m_pSearchWidget)
455 {
456 m_pMainLayout->addWidget(m_pSearchWidget);
457 }
458
459 m_pButtonBox = new QIDialogButtonBox;
460 if (m_pButtonBox)
461 {
462 /* Configure button-box: */
463 m_pCancelButton = m_pButtonBox->addButton(tr("Cancel"), QDialogButtonBox::RejectRole);
464
465 /* Only DVDs and Floppies can be left empty: */
466 if (m_enmMediumType == UIMediumDeviceType_DVD || m_enmMediumType == UIMediumDeviceType_Floppy)
467 m_pLeaveEmptyButton = m_pButtonBox->addButton(tr("Leave Empty"), QDialogButtonBox::ActionRole);
468
469 m_pChooseButton = m_pButtonBox->addButton(tr("Choose"), QDialogButtonBox::AcceptRole);
470 m_pCancelButton->setShortcut(Qt::Key_Escape);
471
472 /* Add button-box into main layout: */
473 m_pMainLayout->addWidget(m_pButtonBox);
474 }
475
476 repopulateTreeWidget();
477}
478
479void UIMediumSelector::sltButtonChoose()
480{
481 done(static_cast<int>(ReturnCode_Accepted));
482}
483
484void UIMediumSelector::sltButtonCancel()
485{
486 done(static_cast<int>(ReturnCode_Rejected));
487}
488
489void UIMediumSelector::sltButtonLeaveEmpty()
490{
491 done(static_cast<int>(ReturnCode_LeftEmpty));
492}
493
494void UIMediumSelector::sltAddMedium()
495{
496 QUuid uMediumID = UIMediumTools::openMediumWithFileOpenDialog(m_enmMediumType, this, m_strMachineFolder,
497 true /* fUseLastFolder */);
498 if (uMediumID.isNull())
499 return;
500 repopulateTreeWidget();
501 selectMedium(uMediumID);
502}
503
504void UIMediumSelector::sltCreateMedium()
505{
506 QUuid uMediumId = UIMediumTools::openMediumCreatorDialog(m_pActionPool, this, m_enmMediumType, m_strMachineFolder,
507 m_strMachineName, m_strMachineGuestOSTypeId);
508 /* Make sure that the data structure is updated and newly created medium is selected and visible: */
509 sltHandleMediumCreated(uMediumId);
510}
511
512void UIMediumSelector::sltHandleItemSelectionChanged()
513{
514 updateChooseButton();
515}
516
517void UIMediumSelector::sltHandleTreeWidgetDoubleClick(QTreeWidgetItem * item, int column)
518{
519 Q_UNUSED(column);
520 if (!dynamic_cast<UIMediumItem*>(item))
521 return;
522 accept();
523}
524
525void UIMediumSelector::sltHandleMediumCreated(const QUuid &uMediumId)
526{
527 if (uMediumId.isNull())
528 return;
529 /* Update the tree widget making sure we show the new item: */
530 repopulateTreeWidget();
531 /* Select the new item: */
532 selectMedium(uMediumId);
533 /* Update the search: */
534 m_pSearchWidget->search(m_pTreeWidget);
535}
536
537void UIMediumSelector::sltHandleMediumEnumerationStart()
538{
539 /* Disable controls. Left Alone button box 'Ok' button. it is handle by tree population: */
540 if (m_pActionRefresh)
541 m_pActionRefresh->setEnabled(false);
542}
543
544void UIMediumSelector::sltHandleMediumEnumerated()
545{
546}
547
548void UIMediumSelector::sltHandleMediumEnumerationFinish()
549{
550 repopulateTreeWidget();
551 if (m_pActionRefresh)
552 m_pActionRefresh->setEnabled(true);
553}
554
555void UIMediumSelector::sltHandleRefresh()
556{
557 /* Restart full medium-enumeration: */
558 gpMediumEnumerator->enumerateMedia();
559 /* Update the search: */
560 m_pSearchWidget->search(m_pTreeWidget);
561}
562
563void UIMediumSelector::sltHandlePerformSearch()
564{
565 if (!m_pSearchWidget)
566 return;
567 m_pSearchWidget->search(m_pTreeWidget);
568}
569
570void UIMediumSelector::sltHandleTreeContextMenuRequest(const QPoint &point)
571{
572 QWidget *pSender = qobject_cast<QWidget*>(sender());
573 if (!pSender)
574 return;
575
576 QMenu menu;
577 QAction *pExpandAll = menu.addAction(tr("Expand All"));
578 QAction *pCollapseAll = menu.addAction(tr("Collapse All"));
579 if (!pExpandAll || !pCollapseAll)
580 return;
581
582 pExpandAll->setIcon(UIIconPool::iconSet(":/expand_all_16px.png"));
583 pCollapseAll->setIcon(UIIconPool::iconSet(":/collapse_all_16px.png"));
584
585 connect(pExpandAll, &QAction::triggered, this, &UIMediumSelector::sltHandleTreeExpandAllSignal);
586 connect(pCollapseAll, &QAction::triggered, this, &UIMediumSelector::sltHandleTreeCollapseAllSignal);
587
588 menu.exec(pSender->mapToGlobal(point));
589}
590
591void UIMediumSelector::sltHandleTreeExpandAllSignal()
592{
593 if (m_pTreeWidget)
594 m_pTreeWidget->expandAll();
595}
596
597void UIMediumSelector::sltHandleTreeCollapseAllSignal()
598{
599 if (m_pTreeWidget)
600 m_pTreeWidget->collapseAll();
601
602 if (m_pAttachedSubTreeRoot)
603 m_pTreeWidget->setExpanded(m_pTreeWidget->itemIndex(m_pAttachedSubTreeRoot), true);
604 if (m_pNotAttachedSubTreeRoot)
605 m_pTreeWidget->setExpanded(m_pTreeWidget->itemIndex(m_pNotAttachedSubTreeRoot), true);
606}
607
608void UIMediumSelector::selectMedium(const QUuid &uMediumID)
609{
610 if (!m_pTreeWidget || uMediumID.isNull())
611 return;
612 UIMediumItem *pMediumItem = searchItem(0, uMediumID);
613 if (pMediumItem)
614 {
615 m_pTreeWidget->setCurrentItem(pMediumItem);
616 QModelIndex itemIndex = m_pTreeWidget->itemIndex(pMediumItem);
617 if (itemIndex.isValid())
618 m_pTreeWidget->scrollTo(itemIndex, QAbstractItemView::PositionAtCenter);
619 }
620}
621
622void UIMediumSelector::updateChooseButton()
623{
624 if (!m_pTreeWidget || !m_pChooseButton)
625 return;
626 QList<QTreeWidgetItem*> selectedItems = m_pTreeWidget->selectedItems();
627 if (selectedItems.isEmpty())
628 {
629 m_pChooseButton->setEnabled(false);
630 return;
631 }
632
633 /* check if at least one of the selected items is a UIMediumItem */
634 bool mediumItemSelected = false;
635 for (int i = 0; i < selectedItems.size() && !mediumItemSelected; ++i)
636 {
637 if (dynamic_cast<UIMediumItem*>(selectedItems.at(i)))
638 mediumItemSelected = true;
639 }
640 if (mediumItemSelected)
641 m_pChooseButton->setEnabled(true);
642 else
643 m_pChooseButton->setEnabled(false);
644}
645
646void UIMediumSelector::finalize()
647{
648 /* Apply language settings: */
649 sltRetranslateUI();
650 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
651 this, &UIMediumSelector::sltRetranslateUI);
652}
653
654void UIMediumSelector::showEvent(QShowEvent *pEvent)
655{
656 Q_UNUSED(pEvent);
657
658 if (m_pTreeWidget)
659 m_pTreeWidget->setFocus();
660}
661
662void UIMediumSelector::repopulateTreeWidget()
663{
664 if (!m_pTreeWidget)
665 return;
666 /* Cache the currently selected items: */
667 QList<QTreeWidgetItem*> selectedItems = m_pTreeWidget->selectedItems();
668 QList<QUuid> selectedMedia = selectedMediumIds();
669 /* uuid list of selected items: */
670 /* Reset the related data structure: */
671 m_mediumItemList.clear();
672 m_pTreeWidget->clear();
673 m_pAttachedSubTreeRoot = 0;
674 m_pNotAttachedSubTreeRoot = 0;
675 QVector<UIMediumItem*> menuItemVector;
676 foreach (const QUuid &uMediumID, gpMediumEnumerator->mediumIDs())
677 {
678 UIMedium medium = gpMediumEnumerator->medium(uMediumID);
679 if (medium.type() == m_enmMediumType)
680 {
681 bool isMediumAttached = !(medium.medium().GetMachineIds().isEmpty());
682 QITreeWidgetItem *pParent = 0;
683 if (isMediumAttached)
684 {
685 if (!m_pAttachedSubTreeRoot)
686 {
687 QStringList strList;
688 strList << "Attached";
689 m_pAttachedSubTreeRoot = new QITreeWidgetItem(m_pTreeWidget, strList);
690 }
691 pParent = m_pAttachedSubTreeRoot;
692
693 }
694 else
695 {
696 if (!m_pNotAttachedSubTreeRoot)
697 {
698 QStringList strList;
699 strList << "Not Attached";
700 m_pNotAttachedSubTreeRoot = new QITreeWidgetItem(m_pTreeWidget, strList);
701 }
702 pParent = m_pNotAttachedSubTreeRoot;
703 }
704 UIMediumItem *treeItem = addTreeItem(medium, pParent);
705 m_mediumItemList.append(treeItem);
706 menuItemVector.push_back(treeItem);
707 }
708 }
709 restoreSelection(selectedMedia, menuItemVector);
710 saveDefaultForeground();
711 updateChooseButton();
712 if (m_pAttachedSubTreeRoot)
713 m_pTreeWidget->expandItem(m_pAttachedSubTreeRoot);
714 if (m_pNotAttachedSubTreeRoot)
715 m_pTreeWidget->expandItem(m_pNotAttachedSubTreeRoot);
716 m_pTreeWidget->resizeColumnToContents(0);
717}
718
719void UIMediumSelector::saveDefaultForeground()
720{
721 if (!m_pTreeWidget)
722 return;
723 if (m_defaultItemForeground == QBrush() && m_pTreeWidget->topLevelItemCount() >= 1)
724 {
725 QTreeWidgetItem *item = m_pTreeWidget->topLevelItem(0);
726 if (item)
727 {
728 QVariant data = item->data(0, Qt::ForegroundRole);
729 if (data.canConvert<QBrush>())
730 {
731 m_defaultItemForeground = data.value<QBrush>();
732 }
733 }
734 }
735}
736
737UIMediumItem* UIMediumSelector::searchItem(const QTreeWidgetItem *pParent, const QUuid &mediumId)
738{
739 if (!m_pTreeWidget)
740 return 0;
741 if (!pParent)
742 pParent = m_pTreeWidget->invisibleRootItem();
743 if (!pParent)
744 return 0;
745
746 for (int i = 0; i < pParent->childCount(); ++i)
747 {
748 QTreeWidgetItem *pChild = pParent->child(i);
749 if (!pChild)
750 continue;
751 UIMediumItem *mediumItem = dynamic_cast<UIMediumItem*>(pChild);
752 if (mediumItem)
753 {
754 if (mediumItem->id() == mediumId)
755 return mediumItem;
756 }
757 UIMediumItem *pResult = searchItem(pChild, mediumId);
758 if (pResult)
759 return pResult;
760 }
761 return 0;
762}
763
764void UIMediumSelector::setTitle()
765{
766 switch (m_enmMediumType)
767 {
768 case UIMediumDeviceType_DVD:
769 if (!m_strMachineName.isEmpty())
770 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Optical Disk Selector")));
771 else
772 setWindowTitle(QString("%1").arg(tr("Optical Disk Selector")));
773 break;
774 case UIMediumDeviceType_Floppy:
775 if (!m_strMachineName.isEmpty())
776 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Floppy Disk Selector")));
777 else
778 setWindowTitle(QString("%1").arg(tr("Floppy Disk Selector")));
779 break;
780 case UIMediumDeviceType_HardDisk:
781 if (!m_strMachineName.isEmpty())
782 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Hard Disk Selector")));
783 else
784 setWindowTitle(QString("%1").arg(tr("Hard Disk Selector")));
785 break;
786 case UIMediumDeviceType_All:
787 case UIMediumDeviceType_Invalid:
788 default:
789 if (!m_strMachineName.isEmpty())
790 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Virtual Medium Selector")));
791 else
792 setWindowTitle(QString("%1").arg(tr("Virtual Medium Selector")));
793 break;
794 }
795}
796
797void UIMediumSelector::saveDialogGeometry()
798{
799 const QRect geo = currentGeometry();
800 LogRel2(("GUI: UIMediumSelector: Saving geometry as: Origin=%dx%d, Size=%dx%d\n",
801 geo.x(), geo.y(), geo.width(), geo.height()));
802 gEDataManager->setMediumSelectorDialogGeometry(geo, isCurrentlyMaximized());
803}
804
805void UIMediumSelector::loadSettings()
806{
807 const QRect availableGeo = gpDesktop->availableGeometry(this);
808 int iDefaultWidth = availableGeo.width() / 2;
809 int iDefaultHeight = availableGeo.height() * 3 / 4;
810 QRect defaultGeo(0, 0, iDefaultWidth, iDefaultHeight);
811
812 QWidget *pParent = windowManager().realParentWindow(m_pParent ? m_pParent : windowManager().mainWindowShown());
813 /* Load geometry from extradata: */
814 const QRect geo = gEDataManager->mediumSelectorDialogGeometry(this, pParent, defaultGeo);
815 LogRel2(("GUI: UISoftKeyboard: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
816 geo.x(), geo.y(), geo.width(), geo.height()));
817
818 restoreGeometry(geo);
819}
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