VirtualBox

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

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

FE/Qt: UICommon: Get rid of last access media stuff 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.3 KB
Line 
1/* $Id: UIMediumSelector.cpp 104899 2024-06-12 14:28:47Z 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 "UICommon.h"
45#include "UIDesktopWidgetWatchdog.h"
46#include "UIExtraDataManager.h"
47#include "UILoggingDefs.h"
48#include "UIMediumEnumerator.h"
49#include "UIMediumSearchWidget.h"
50#include "UIMediumSelector.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(&uiCommon(), &UICommon::sigMediumCreated,
286 this, &UIMediumSelector::sltHandleMediumCreated);
287 connect(&uiCommon(), &UICommon::sigMediumEnumerationStarted,
288 this, &UIMediumSelector::sltHandleMediumEnumerationStart);
289 connect(&uiCommon(), &UICommon::sigMediumEnumerated,
290 this, &UIMediumSelector::sltHandleMediumEnumerated);
291 connect(&uiCommon(), &UICommon::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 = uiCommon().openMediumWithFileOpenDialog(m_enmMediumType, this, m_strMachineFolder, true /* fUseLastFolder */);
497 if (uMediumID.isNull())
498 return;
499 repopulateTreeWidget();
500 selectMedium(uMediumID);
501}
502
503void UIMediumSelector::sltCreateMedium()
504{
505 QUuid uMediumId = uiCommon().openMediumCreatorDialog(m_pActionPool, this, m_enmMediumType, m_strMachineFolder,
506 m_strMachineName, m_strMachineGuestOSTypeId);
507 /* Make sure that the data structure is updated and newly created medium is selected and visible: */
508 sltHandleMediumCreated(uMediumId);
509}
510
511void UIMediumSelector::sltHandleItemSelectionChanged()
512{
513 updateChooseButton();
514}
515
516void UIMediumSelector::sltHandleTreeWidgetDoubleClick(QTreeWidgetItem * item, int column)
517{
518 Q_UNUSED(column);
519 if (!dynamic_cast<UIMediumItem*>(item))
520 return;
521 accept();
522}
523
524void UIMediumSelector::sltHandleMediumCreated(const QUuid &uMediumId)
525{
526 if (uMediumId.isNull())
527 return;
528 /* Update the tree widget making sure we show the new item: */
529 repopulateTreeWidget();
530 /* Select the new item: */
531 selectMedium(uMediumId);
532 /* Update the search: */
533 m_pSearchWidget->search(m_pTreeWidget);
534}
535
536void UIMediumSelector::sltHandleMediumEnumerationStart()
537{
538 /* Disable controls. Left Alone button box 'Ok' button. it is handle by tree population: */
539 if (m_pActionRefresh)
540 m_pActionRefresh->setEnabled(false);
541}
542
543void UIMediumSelector::sltHandleMediumEnumerated()
544{
545}
546
547void UIMediumSelector::sltHandleMediumEnumerationFinish()
548{
549 repopulateTreeWidget();
550 if (m_pActionRefresh)
551 m_pActionRefresh->setEnabled(true);
552}
553
554void UIMediumSelector::sltHandleRefresh()
555{
556 /* Restart full medium-enumeration: */
557 gpMediumEnumerator->enumerateMedia();
558 /* Update the search: */
559 m_pSearchWidget->search(m_pTreeWidget);
560}
561
562void UIMediumSelector::sltHandlePerformSearch()
563{
564 if (!m_pSearchWidget)
565 return;
566 m_pSearchWidget->search(m_pTreeWidget);
567}
568
569void UIMediumSelector::sltHandleTreeContextMenuRequest(const QPoint &point)
570{
571 QWidget *pSender = qobject_cast<QWidget*>(sender());
572 if (!pSender)
573 return;
574
575 QMenu menu;
576 QAction *pExpandAll = menu.addAction(tr("Expand All"));
577 QAction *pCollapseAll = menu.addAction(tr("Collapse All"));
578 if (!pExpandAll || !pCollapseAll)
579 return;
580
581 pExpandAll->setIcon(UIIconPool::iconSet(":/expand_all_16px.png"));
582 pCollapseAll->setIcon(UIIconPool::iconSet(":/collapse_all_16px.png"));
583
584 connect(pExpandAll, &QAction::triggered, this, &UIMediumSelector::sltHandleTreeExpandAllSignal);
585 connect(pCollapseAll, &QAction::triggered, this, &UIMediumSelector::sltHandleTreeCollapseAllSignal);
586
587 menu.exec(pSender->mapToGlobal(point));
588}
589
590void UIMediumSelector::sltHandleTreeExpandAllSignal()
591{
592 if (m_pTreeWidget)
593 m_pTreeWidget->expandAll();
594}
595
596void UIMediumSelector::sltHandleTreeCollapseAllSignal()
597{
598 if (m_pTreeWidget)
599 m_pTreeWidget->collapseAll();
600
601 if (m_pAttachedSubTreeRoot)
602 m_pTreeWidget->setExpanded(m_pTreeWidget->itemIndex(m_pAttachedSubTreeRoot), true);
603 if (m_pNotAttachedSubTreeRoot)
604 m_pTreeWidget->setExpanded(m_pTreeWidget->itemIndex(m_pNotAttachedSubTreeRoot), true);
605}
606
607void UIMediumSelector::selectMedium(const QUuid &uMediumID)
608{
609 if (!m_pTreeWidget || uMediumID.isNull())
610 return;
611 UIMediumItem *pMediumItem = searchItem(0, uMediumID);
612 if (pMediumItem)
613 {
614 m_pTreeWidget->setCurrentItem(pMediumItem);
615 QModelIndex itemIndex = m_pTreeWidget->itemIndex(pMediumItem);
616 if (itemIndex.isValid())
617 m_pTreeWidget->scrollTo(itemIndex, QAbstractItemView::PositionAtCenter);
618 }
619}
620
621void UIMediumSelector::updateChooseButton()
622{
623 if (!m_pTreeWidget || !m_pChooseButton)
624 return;
625 QList<QTreeWidgetItem*> selectedItems = m_pTreeWidget->selectedItems();
626 if (selectedItems.isEmpty())
627 {
628 m_pChooseButton->setEnabled(false);
629 return;
630 }
631
632 /* check if at least one of the selected items is a UIMediumItem */
633 bool mediumItemSelected = false;
634 for (int i = 0; i < selectedItems.size() && !mediumItemSelected; ++i)
635 {
636 if (dynamic_cast<UIMediumItem*>(selectedItems.at(i)))
637 mediumItemSelected = true;
638 }
639 if (mediumItemSelected)
640 m_pChooseButton->setEnabled(true);
641 else
642 m_pChooseButton->setEnabled(false);
643}
644
645void UIMediumSelector::finalize()
646{
647 /* Apply language settings: */
648 sltRetranslateUI();
649 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
650 this, &UIMediumSelector::sltRetranslateUI);
651}
652
653void UIMediumSelector::showEvent(QShowEvent *pEvent)
654{
655 Q_UNUSED(pEvent);
656
657 if (m_pTreeWidget)
658 m_pTreeWidget->setFocus();
659}
660
661void UIMediumSelector::repopulateTreeWidget()
662{
663 if (!m_pTreeWidget)
664 return;
665 /* Cache the currently selected items: */
666 QList<QTreeWidgetItem*> selectedItems = m_pTreeWidget->selectedItems();
667 QList<QUuid> selectedMedia = selectedMediumIds();
668 /* uuid list of selected items: */
669 /* Reset the related data structure: */
670 m_mediumItemList.clear();
671 m_pTreeWidget->clear();
672 m_pAttachedSubTreeRoot = 0;
673 m_pNotAttachedSubTreeRoot = 0;
674 QVector<UIMediumItem*> menuItemVector;
675 foreach (const QUuid &uMediumID, gpMediumEnumerator->mediumIDs())
676 {
677 UIMedium medium = gpMediumEnumerator->medium(uMediumID);
678 if (medium.type() == m_enmMediumType)
679 {
680 bool isMediumAttached = !(medium.medium().GetMachineIds().isEmpty());
681 QITreeWidgetItem *pParent = 0;
682 if (isMediumAttached)
683 {
684 if (!m_pAttachedSubTreeRoot)
685 {
686 QStringList strList;
687 strList << "Attached";
688 m_pAttachedSubTreeRoot = new QITreeWidgetItem(m_pTreeWidget, strList);
689 }
690 pParent = m_pAttachedSubTreeRoot;
691
692 }
693 else
694 {
695 if (!m_pNotAttachedSubTreeRoot)
696 {
697 QStringList strList;
698 strList << "Not Attached";
699 m_pNotAttachedSubTreeRoot = new QITreeWidgetItem(m_pTreeWidget, strList);
700 }
701 pParent = m_pNotAttachedSubTreeRoot;
702 }
703 UIMediumItem *treeItem = addTreeItem(medium, pParent);
704 m_mediumItemList.append(treeItem);
705 menuItemVector.push_back(treeItem);
706 }
707 }
708 restoreSelection(selectedMedia, menuItemVector);
709 saveDefaultForeground();
710 updateChooseButton();
711 if (m_pAttachedSubTreeRoot)
712 m_pTreeWidget->expandItem(m_pAttachedSubTreeRoot);
713 if (m_pNotAttachedSubTreeRoot)
714 m_pTreeWidget->expandItem(m_pNotAttachedSubTreeRoot);
715 m_pTreeWidget->resizeColumnToContents(0);
716}
717
718void UIMediumSelector::saveDefaultForeground()
719{
720 if (!m_pTreeWidget)
721 return;
722 if (m_defaultItemForeground == QBrush() && m_pTreeWidget->topLevelItemCount() >= 1)
723 {
724 QTreeWidgetItem *item = m_pTreeWidget->topLevelItem(0);
725 if (item)
726 {
727 QVariant data = item->data(0, Qt::ForegroundRole);
728 if (data.canConvert<QBrush>())
729 {
730 m_defaultItemForeground = data.value<QBrush>();
731 }
732 }
733 }
734}
735
736UIMediumItem* UIMediumSelector::searchItem(const QTreeWidgetItem *pParent, const QUuid &mediumId)
737{
738 if (!m_pTreeWidget)
739 return 0;
740 if (!pParent)
741 pParent = m_pTreeWidget->invisibleRootItem();
742 if (!pParent)
743 return 0;
744
745 for (int i = 0; i < pParent->childCount(); ++i)
746 {
747 QTreeWidgetItem *pChild = pParent->child(i);
748 if (!pChild)
749 continue;
750 UIMediumItem *mediumItem = dynamic_cast<UIMediumItem*>(pChild);
751 if (mediumItem)
752 {
753 if (mediumItem->id() == mediumId)
754 return mediumItem;
755 }
756 UIMediumItem *pResult = searchItem(pChild, mediumId);
757 if (pResult)
758 return pResult;
759 }
760 return 0;
761}
762
763void UIMediumSelector::setTitle()
764{
765 switch (m_enmMediumType)
766 {
767 case UIMediumDeviceType_DVD:
768 if (!m_strMachineName.isEmpty())
769 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Optical Disk Selector")));
770 else
771 setWindowTitle(QString("%1").arg(tr("Optical Disk Selector")));
772 break;
773 case UIMediumDeviceType_Floppy:
774 if (!m_strMachineName.isEmpty())
775 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Floppy Disk Selector")));
776 else
777 setWindowTitle(QString("%1").arg(tr("Floppy Disk Selector")));
778 break;
779 case UIMediumDeviceType_HardDisk:
780 if (!m_strMachineName.isEmpty())
781 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Hard Disk Selector")));
782 else
783 setWindowTitle(QString("%1").arg(tr("Hard Disk Selector")));
784 break;
785 case UIMediumDeviceType_All:
786 case UIMediumDeviceType_Invalid:
787 default:
788 if (!m_strMachineName.isEmpty())
789 setWindowTitle(QString("%1 - %2").arg(m_strMachineName).arg(tr("Virtual Medium Selector")));
790 else
791 setWindowTitle(QString("%1").arg(tr("Virtual Medium Selector")));
792 break;
793 }
794}
795
796void UIMediumSelector::saveDialogGeometry()
797{
798 const QRect geo = currentGeometry();
799 LogRel2(("GUI: UIMediumSelector: Saving geometry as: Origin=%dx%d, Size=%dx%d\n",
800 geo.x(), geo.y(), geo.width(), geo.height()));
801 gEDataManager->setMediumSelectorDialogGeometry(geo, isCurrentlyMaximized());
802}
803
804void UIMediumSelector::loadSettings()
805{
806 const QRect availableGeo = gpDesktop->availableGeometry(this);
807 int iDefaultWidth = availableGeo.width() / 2;
808 int iDefaultHeight = availableGeo.height() * 3 / 4;
809 QRect defaultGeo(0, 0, iDefaultWidth, iDefaultHeight);
810
811 QWidget *pParent = windowManager().realParentWindow(m_pParent ? m_pParent : windowManager().mainWindowShown());
812 /* Load geometry from extradata: */
813 const QRect geo = gEDataManager->mediumSelectorDialogGeometry(this, pParent, defaultGeo);
814 LogRel2(("GUI: UISoftKeyboard: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
815 geo.x(), geo.y(), geo.width(), geo.height()));
816
817 restoreGeometry(geo);
818}
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