VirtualBox

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

© 2023 Oracle
ContactPrivacy policyTerms of Use