[26715] | 1 | /* $Id: UIMediaComboBox.cpp 103771 2024-03-11 15:16:04Z vboxsync $ */
|
---|
[25178] | 2 | /** @file
|
---|
[71948] | 3 | * VBox Qt GUI - UIMediaComboBox class implementation.
|
---|
[25178] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[25178] | 8 | *
|
---|
[96407] | 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
|
---|
[25178] | 26 | */
|
---|
| 27 |
|
---|
[48314] | 28 | /* Qt includes: */
|
---|
[76606] | 29 | #include <QAbstractItemView>
|
---|
| 30 | #include <QDir>
|
---|
| 31 | #include <QFileInfo>
|
---|
[25178] | 32 |
|
---|
[48314] | 33 | /* GUI includes: */
|
---|
[103546] | 34 | #include "UICommon.h"
|
---|
[103771] | 35 | #include "UIGlobalSession.h"
|
---|
[76606] | 36 | #include "UIMediaComboBox.h"
|
---|
| 37 | #include "UIMedium.h"
|
---|
[48314] | 38 |
|
---|
[52730] | 39 |
|
---|
[85063] | 40 | UIMediaComboBox::UIMediaComboBox(QWidget *pParent /* = 0 */)
|
---|
[71948] | 41 | : QComboBox(pParent)
|
---|
[73953] | 42 | , m_enmMediaType(UIMediumDeviceType_Invalid)
|
---|
[74878] | 43 | , m_uMachineId(QUuid())
|
---|
| 44 | , m_uLastItemId(QUuid())
|
---|
[25178] | 45 | {
|
---|
[71948] | 46 | /* Prepare: */
|
---|
| 47 | prepare();
|
---|
[25178] | 48 | }
|
---|
| 49 |
|
---|
[71948] | 50 | void UIMediaComboBox::refresh()
|
---|
[25178] | 51 | {
|
---|
[71948] | 52 | /* Clearing lists: */
|
---|
| 53 | clear(), m_media.clear();
|
---|
[25178] | 54 |
|
---|
[71948] | 55 | /* Use the medium creation handler to add all the items: */
|
---|
[79365] | 56 | foreach (const QUuid &uMediumId, uiCommon().mediumIDs())
|
---|
[74878] | 57 | sltHandleMediumCreated(uMediumId);
|
---|
[25178] | 58 |
|
---|
[80897] | 59 | /* If at least one real medium present,
|
---|
| 60 | * remove null medium: */
|
---|
| 61 | if (count() > 1)
|
---|
[25178] | 62 | {
|
---|
[71948] | 63 | removeItem(0);
|
---|
[80445] | 64 | m_media.erase(m_media.begin());
|
---|
[25178] | 65 | }
|
---|
| 66 |
|
---|
[71948] | 67 | /* Notify listeners about active item changed. */
|
---|
| 68 | emit activated(currentIndex());
|
---|
[25178] | 69 | }
|
---|
| 70 |
|
---|
[71948] | 71 | void UIMediaComboBox::repopulate()
|
---|
[25178] | 72 | {
|
---|
[80932] | 73 | /* Start medium-enumeration for optical drives/images (if necessary): */
|
---|
[80900] | 74 | if ( m_enmMediaType == UIMediumDeviceType_DVD
|
---|
| 75 | && !uiCommon().isFullMediumEnumerationRequested())
|
---|
[80899] | 76 | {
|
---|
| 77 | CMediumVector comMedia;
|
---|
[103771] | 78 | comMedia << gpGlobalSession->host().GetDVDDrives();
|
---|
| 79 | comMedia << gpGlobalSession->virtualBox().GetDVDImages();
|
---|
[80926] | 80 | uiCommon().enumerateMedia(comMedia);
|
---|
[80899] | 81 | }
|
---|
| 82 | refresh();
|
---|
[25178] | 83 | }
|
---|
| 84 |
|
---|
[74942] | 85 | void UIMediaComboBox::setCurrentItem(const QUuid &uItemId)
|
---|
[25178] | 86 | {
|
---|
[74942] | 87 | m_uLastItemId = uItemId;
|
---|
[25178] | 88 |
|
---|
[71948] | 89 | int iIndex;
|
---|
| 90 | // WORKAROUND:
|
---|
| 91 | // Note that the media combo-box may be not populated here yet,
|
---|
| 92 | // so we don't assert..
|
---|
[74942] | 93 | if (findMediaIndex(uItemId, iIndex))
|
---|
[25178] | 94 | {
|
---|
[71948] | 95 | QComboBox::setCurrentIndex(iIndex);
|
---|
| 96 | emit activated(iIndex);
|
---|
[25178] | 97 | }
|
---|
| 98 | }
|
---|
| 99 |
|
---|
[74878] | 100 | QUuid UIMediaComboBox::id(int iIndex /* = -1 */) const
|
---|
[25178] | 101 | {
|
---|
[71948] | 102 | AssertReturn(iIndex == -1 ||
|
---|
| 103 | (iIndex >= 0 && iIndex < m_media.size()),
|
---|
[74878] | 104 | QUuid());
|
---|
[25178] | 105 |
|
---|
[71948] | 106 | if (iIndex == -1)
|
---|
| 107 | iIndex = currentIndex();
|
---|
[74878] | 108 | return iIndex == -1 ? QUuid() : m_media.at(iIndex).id;
|
---|
[25178] | 109 | }
|
---|
| 110 |
|
---|
[71948] | 111 | QString UIMediaComboBox::location(int iIndex /* = -1 */) const
|
---|
[25178] | 112 | {
|
---|
[71948] | 113 | AssertReturn(iIndex == -1 ||
|
---|
| 114 | (iIndex >= 0 && iIndex < m_media.size()),
|
---|
| 115 | QString());
|
---|
[25178] | 116 |
|
---|
[71948] | 117 | if (iIndex == -1)
|
---|
| 118 | iIndex = currentIndex();
|
---|
| 119 | return iIndex == -1 ? QString() : m_media.at(iIndex).location;
|
---|
[25178] | 120 | }
|
---|
| 121 |
|
---|
[74942] | 122 | void UIMediaComboBox::sltHandleMediumCreated(const QUuid &uMediumId)
|
---|
[25178] | 123 | {
|
---|
[48264] | 124 | /* Search for corresponding medium: */
|
---|
[79365] | 125 | UIMedium guiMedium = uiCommon().medium(uMediumId);
|
---|
[25178] | 126 |
|
---|
[73926] | 127 | /* Ignore media (and their children) which are
|
---|
[50985] | 128 | * marked as hidden or attached to hidden machines only: */
|
---|
[71948] | 129 | if (UIMedium::isMediumAttachedToHiddenMachinesOnly(guiMedium))
|
---|
[50985] | 130 | return;
|
---|
| 131 |
|
---|
[73926] | 132 | /* Add only 1. NULL medium and 2. media of required type: */
|
---|
[71948] | 133 | if (!guiMedium.isNull() && guiMedium.type() != m_enmMediaType)
|
---|
[48265] | 134 | return;
|
---|
[25178] | 135 |
|
---|
[71948] | 136 | /* Ignore all diffs: */
|
---|
[73953] | 137 | if (guiMedium.type() == UIMediumDeviceType_HardDisk && guiMedium.parentID() != UIMedium::nullID())
|
---|
[48265] | 138 | return;
|
---|
[25178] | 139 |
|
---|
[48265] | 140 | /* Append medium into combo-box: */
|
---|
[71948] | 141 | appendItem(guiMedium);
|
---|
[48265] | 142 |
|
---|
| 143 | /* Activate the required item if any: */
|
---|
[74878] | 144 | if (guiMedium.id() == m_uLastItemId)
|
---|
[71948] | 145 | setCurrentItem(guiMedium.id());
|
---|
[48265] | 146 | /* Select last added item if there is no item selected: */
|
---|
| 147 | else if (currentText().isEmpty())
|
---|
| 148 | QComboBox::setCurrentIndex(count() - 1);
|
---|
[25178] | 149 | }
|
---|
| 150 |
|
---|
[74942] | 151 | void UIMediaComboBox::sltHandleMediumEnumerated(const QUuid &uMediumId)
|
---|
[25178] | 152 | {
|
---|
[48264] | 153 | /* Search for corresponding medium: */
|
---|
[79365] | 154 | UIMedium guiMedium = uiCommon().medium(uMediumId);
|
---|
[48264] | 155 |
|
---|
[73926] | 156 | /* Add only 1. NULL medium and 2. media of required type: */
|
---|
[71948] | 157 | if (!guiMedium.isNull() && guiMedium.type() != m_enmMediaType)
|
---|
[48265] | 158 | return;
|
---|
[25178] | 159 |
|
---|
[48265] | 160 | /* Search for corresponding item index: */
|
---|
[71948] | 161 | int iIndex;
|
---|
| 162 | if (!findMediaIndex(guiMedium.id(), iIndex))
|
---|
[48265] | 163 | return;
|
---|
[25178] | 164 |
|
---|
[48265] | 165 | /* Replace medium in combo-box: */
|
---|
[71948] | 166 | replaceItem(iIndex, guiMedium);
|
---|
[48265] | 167 |
|
---|
[71948] | 168 | /* Ensure the parent dialog handles the change of the selected item's data: */
|
---|
[48265] | 169 | emit activated(currentIndex());
|
---|
[25178] | 170 | }
|
---|
| 171 |
|
---|
[74942] | 172 | void UIMediaComboBox::sltHandleMediumDeleted(const QUuid &uMediumId)
|
---|
[25178] | 173 | {
|
---|
[48265] | 174 | /* Search for corresponding item index: */
|
---|
[71948] | 175 | int iIndex;
|
---|
[74942] | 176 | if (!findMediaIndex(uMediumId, iIndex))
|
---|
[25178] | 177 | return;
|
---|
| 178 |
|
---|
[48265] | 179 | /* Replace medium from combo-box: */
|
---|
[71948] | 180 | removeItem(iIndex);
|
---|
[80445] | 181 | m_media.erase(m_media.begin() + iIndex);
|
---|
[25178] | 182 |
|
---|
[48264] | 183 | /* If no real medium left, add the NULL medium: */
|
---|
[25178] | 184 | if (count() == 0)
|
---|
[48301] | 185 | sltHandleMediumCreated(UIMedium::nullID());
|
---|
[25178] | 186 |
|
---|
[71948] | 187 | /* Ensure the parent dialog handles the change of the selected item: */
|
---|
[48260] | 188 | emit activated(currentIndex());
|
---|
[25178] | 189 | }
|
---|
| 190 |
|
---|
[71948] | 191 | void UIMediaComboBox::sltHandleMediumEnumerationStart()
|
---|
[48264] | 192 | {
|
---|
| 193 | refresh();
|
---|
| 194 | }
|
---|
[25178] | 195 |
|
---|
[71948] | 196 | void UIMediaComboBox::sltHandleComboActivated(int iIndex)
|
---|
[25178] | 197 | {
|
---|
[71948] | 198 | AssertReturnVoid(iIndex >= 0 && iIndex < m_media.size());
|
---|
[25178] | 199 |
|
---|
[74878] | 200 | m_uLastItemId = m_media.at(iIndex).id;
|
---|
[25178] | 201 |
|
---|
[71948] | 202 | updateToolTip(iIndex);
|
---|
[25178] | 203 | }
|
---|
| 204 |
|
---|
[71948] | 205 | void UIMediaComboBox::sltHandleComboHovered(const QModelIndex &index)
|
---|
[25178] | 206 | {
|
---|
[71948] | 207 | /* Set the combo-box item's tooltip: */
|
---|
| 208 | const int iIndex = index.row();
|
---|
| 209 | view()->viewport()->setToolTip(QString());
|
---|
| 210 | view()->viewport()->setToolTip(m_media.at(iIndex).toolTip);
|
---|
[25178] | 211 | }
|
---|
| 212 |
|
---|
[71948] | 213 | void UIMediaComboBox::prepare()
|
---|
[25178] | 214 | {
|
---|
[71948] | 215 | /* Setup the elide mode: */
|
---|
| 216 | view()->setTextElideMode(Qt::ElideRight);
|
---|
| 217 | QSizePolicy sp1(QSizePolicy::Ignored, QSizePolicy::Fixed, QSizePolicy::ComboBox);
|
---|
| 218 | sp1.setHorizontalStretch(2);
|
---|
| 219 | setSizePolicy(sp1);
|
---|
| 220 |
|
---|
| 221 | /* Setup medium-processing handlers: */
|
---|
[79365] | 222 | connect(&uiCommon(), &UICommon::sigMediumCreated,
|
---|
[71948] | 223 | this, &UIMediaComboBox::sltHandleMediumCreated);
|
---|
[79365] | 224 | connect(&uiCommon(), &UICommon::sigMediumDeleted,
|
---|
[71948] | 225 | this, &UIMediaComboBox::sltHandleMediumDeleted);
|
---|
| 226 |
|
---|
[78722] | 227 | /* Setup medium-enumeration handlers: */
|
---|
[79365] | 228 | connect(&uiCommon(), &UICommon::sigMediumEnumerationStarted,
|
---|
[71948] | 229 | this, &UIMediaComboBox::sltHandleMediumEnumerationStart);
|
---|
[79365] | 230 | connect(&uiCommon(), &UICommon::sigMediumEnumerated,
|
---|
[71948] | 231 | this, &UIMediaComboBox::sltHandleMediumEnumerated);
|
---|
| 232 |
|
---|
| 233 | /* Setup other connections: */
|
---|
[101563] | 234 | connect(this, &UIMediaComboBox::activated,
|
---|
[71948] | 235 | this, &UIMediaComboBox::sltHandleComboActivated);
|
---|
| 236 | connect(view(), &QAbstractItemView::entered,
|
---|
| 237 | this, &UIMediaComboBox::sltHandleComboHovered);
|
---|
[25178] | 238 | }
|
---|
| 239 |
|
---|
[71948] | 240 | void UIMediaComboBox::updateToolTip(int iIndex)
|
---|
| 241 | {
|
---|
| 242 | /* Set the combo-box tooltip: */
|
---|
| 243 | setToolTip(QString());
|
---|
| 244 | if (iIndex >= 0 && iIndex < m_media.size())
|
---|
| 245 | setToolTip(m_media.at(iIndex).toolTip);
|
---|
| 246 | }
|
---|
[25178] | 247 |
|
---|
[71948] | 248 | void UIMediaComboBox::appendItem(const UIMedium &guiMedium)
|
---|
[25178] | 249 | {
|
---|
[71948] | 250 | m_media.append(Medium(guiMedium.id(), guiMedium.location(),
|
---|
| 251 | guiMedium.toolTipCheckRO(true, false)));
|
---|
[25178] | 252 |
|
---|
[71948] | 253 | insertItem(count(), guiMedium.iconCheckRO(true), guiMedium.details(true));
|
---|
[25178] | 254 | }
|
---|
| 255 |
|
---|
[71948] | 256 | void UIMediaComboBox::replaceItem(int iIndex, const UIMedium &guiMedium)
|
---|
[25178] | 257 | {
|
---|
[71948] | 258 | AssertReturnVoid(iIndex >= 0 && iIndex < m_media.size());
|
---|
[25178] | 259 |
|
---|
[71948] | 260 | m_media[iIndex].id = guiMedium.id();
|
---|
| 261 | m_media[iIndex].location = guiMedium.location();
|
---|
| 262 | m_media[iIndex].toolTip = guiMedium.toolTipCheckRO(true, false);
|
---|
[25178] | 263 |
|
---|
[71948] | 264 | setItemText(iIndex, guiMedium.details(true));
|
---|
| 265 | setItemIcon(iIndex, guiMedium.iconCheckRO(true));
|
---|
[25178] | 266 |
|
---|
[71948] | 267 | if (iIndex == currentIndex())
|
---|
| 268 | updateToolTip(iIndex);
|
---|
[25178] | 269 | }
|
---|
| 270 |
|
---|
[74942] | 271 | bool UIMediaComboBox::findMediaIndex(const QUuid &uId, int &iIndex)
|
---|
[25178] | 272 | {
|
---|
[71948] | 273 | iIndex = 0;
|
---|
[25178] | 274 |
|
---|
[71948] | 275 | for (; iIndex < m_media.size(); ++ iIndex)
|
---|
[74942] | 276 | if (m_media.at(iIndex).id == uId)
|
---|
[25178] | 277 | break;
|
---|
| 278 |
|
---|
[71948] | 279 | return iIndex < m_media.size();
|
---|
[25178] | 280 | }
|
---|