VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UINameAndSystemEditor.cpp@ 82781

Last change on this file since 82781 was 79927, checked in by vboxsync, 5 years ago

FE/Qt: bugref:7720: Rework UINameAndSystemEditor to be able to set current path.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.7 KB
Line 
1/* $Id: UINameAndSystemEditor.cpp 79927 2019-07-23 08:35:25Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UINameAndSystemEditor class implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QComboBox>
20#include <QGridLayout>
21#include <QLabel>
22#include <QVBoxLayout>
23
24/* GUI includes: */
25#include "QILineEdit.h"
26#include "UICommon.h"
27#include "UIFilePathSelector.h"
28#include "UINameAndSystemEditor.h"
29
30/* COM includes: */
31#include "CSystemProperties.h"
32
33
34/** Defines the VM OS type ID. */
35enum
36{
37 TypeID = Qt::UserRole + 1
38};
39
40
41UINameAndSystemEditor::UINameAndSystemEditor(QWidget *pParent,
42 bool fChooseName /* = true */,
43 bool fChoosePath /* = false */,
44 bool fChooseType /* = true */)
45 : QIWithRetranslateUI<QWidget>(pParent)
46 , m_fChooseName(fChooseName)
47 , m_fChoosePath(fChoosePath)
48 , m_fChooseType(fChooseType)
49 , m_fSupportsHWVirtEx(false)
50 , m_fSupportsLongMode(false)
51 , m_pNameLabel(0)
52 , m_pPathLabel(0)
53 , m_pLabelFamily(0)
54 , m_pLabelType(0)
55 , m_pIconType(0)
56 , m_pNameLineEdit(0)
57 , m_pPathSelector(0)
58 , m_pComboFamily(0)
59 , m_pComboType(0)
60{
61 prepare();
62}
63
64void UINameAndSystemEditor::setName(const QString &strName)
65{
66 if (!m_pNameLineEdit)
67 return;
68 m_pNameLineEdit->setText(strName);
69}
70
71QString UINameAndSystemEditor::name() const
72{
73 if (!m_pNameLineEdit)
74 return QString();
75 return m_pNameLineEdit->text();
76}
77
78void UINameAndSystemEditor::setPath(const QString &strPath)
79{
80 if (!m_pPathSelector)
81 return;
82 m_pPathSelector->setPath(strPath);
83}
84
85QString UINameAndSystemEditor::path() const
86{
87 if (!m_pPathSelector)
88 return uiCommon().virtualBox().GetSystemProperties().GetDefaultMachineFolder();
89 return m_pPathSelector->path();
90}
91
92void UINameAndSystemEditor::setTypeId(QString strTypeId, QString strFamilyId /* = QString() */)
93{
94 if (!m_pComboType)
95 return;
96 AssertMsgReturnVoid(!strTypeId.isNull(), ("Null guest OS type ID"));
97
98 /* Initialize indexes: */
99 int iTypeIndex = -1;
100 int iFamilyIndex = -1;
101
102 /* If family ID isn't empty: */
103 if (!strFamilyId.isEmpty())
104 {
105 /* Search for corresponding family ID index: */
106 iFamilyIndex = m_pComboFamily->findData(strFamilyId, TypeID);
107
108 /* If that family ID isn't present, we have to add it: */
109 if (iFamilyIndex == -1)
110 {
111 /* Append family ID to corresponding combo: */
112 m_pComboFamily->addItem(strFamilyId);
113 m_pComboFamily->setItemData(m_pComboFamily->count() - 1, strFamilyId, TypeID);
114 /* Append family ID to type cache: */
115 m_types[strFamilyId] = QList<UIGuestOSType>();
116
117 /* Search for corresponding family ID index finally: */
118 iFamilyIndex = m_pComboFamily->findData(strFamilyId, TypeID);
119 }
120 }
121 /* If family ID is empty: */
122 else
123 {
124 /* We'll try to find it by type ID: */
125 foreach (const QString &strKnownFamilyId, m_types.keys())
126 {
127 foreach (const UIGuestOSType &guiType, m_types.value(strKnownFamilyId))
128 {
129 if (guiType.typeId == strTypeId)
130 strFamilyId = strKnownFamilyId;
131 if (!strFamilyId.isNull())
132 break;
133 }
134 if (!strFamilyId.isNull())
135 break;
136 }
137
138 /* If we were unable to find it => use "Other": */
139 if (strFamilyId.isNull())
140 strFamilyId = "Other";
141
142 /* Search for corresponding family ID index finally: */
143 iFamilyIndex = m_pComboFamily->findData(strFamilyId, TypeID);
144 }
145
146 /* To that moment family ID index should be always found: */
147 AssertReturnVoid(iFamilyIndex != -1);
148 /* So we choose it: */
149 m_pComboFamily->setCurrentIndex(iFamilyIndex);
150 sltFamilyChanged(m_pComboFamily->currentIndex());
151
152 /* Search for corresponding type ID index: */
153 iTypeIndex = m_pComboType->findData(strTypeId, TypeID);
154
155 /* If that type ID isn't present, we have to add it: */
156 if (iTypeIndex == -1)
157 {
158 /* Append type ID to type cache: */
159 UIGuestOSType guiType;
160 guiType.typeId = strTypeId;
161 guiType.typeDescription = strTypeId;
162 guiType.is64bit = false;
163 m_types[strFamilyId] << guiType;
164
165 /* So we re-choose family again: */
166 m_pComboFamily->setCurrentIndex(iFamilyIndex);
167 sltFamilyChanged(m_pComboFamily->currentIndex());
168
169 /* Search for corresponding type ID index finally: */
170 iTypeIndex = m_pComboType->findData(strTypeId, TypeID);
171 }
172
173 /* To that moment type ID index should be always found: */
174 AssertReturnVoid(iTypeIndex != -1);
175 /* So we choose it: */
176 m_pComboType->setCurrentIndex(iTypeIndex);
177 sltTypeChanged(m_pComboType->currentIndex());
178}
179
180QString UINameAndSystemEditor::typeId() const
181{
182 if (!m_pComboType)
183 return QString();
184 return m_strTypeId;
185}
186
187QString UINameAndSystemEditor::familyId() const
188{
189 if (!m_pComboFamily)
190 return QString();
191 return m_strFamilyId;
192}
193
194void UINameAndSystemEditor::setType(const CGuestOSType &enmType)
195{
196 // WORKAROUND:
197 // We're getting here with a NULL enmType when creating new VMs.
198 // Very annoying, so just workarounded for now.
199 /** @todo find out the reason and way to fix that.. */
200 if (enmType.isNull())
201 return;
202
203 /* Pass to function above: */
204 setTypeId(enmType.GetId(), enmType.GetFamilyId());
205}
206
207CGuestOSType UINameAndSystemEditor::type() const
208{
209 return uiCommon().vmGuestOSType(typeId(), familyId());
210}
211
212void UINameAndSystemEditor::setNameFieldValidator(const QString &strValidator)
213{
214 if (!m_pNameLineEdit)
215 return;
216 m_pNameLineEdit->setValidator(new QRegExpValidator(QRegExp(strValidator), this));
217}
218
219void UINameAndSystemEditor::retranslateUi()
220{
221 if (m_pNameLabel)
222 m_pNameLabel->setText(tr("Name:"));
223 if (m_pPathLabel)
224 m_pPathLabel->setText(tr("Machine Folder:"));
225 if (m_pLabelFamily)
226 m_pLabelFamily->setText(tr("&Type:"));
227 if (m_pLabelType)
228 m_pLabelType->setText(tr("&Version:"));
229
230 if (m_pComboFamily)
231 m_pComboFamily->setWhatsThis(tr("Selects the operating system family that "
232 "you plan to install into this virtual machine."));
233 if (m_pComboType)
234 m_pComboType->setWhatsThis(tr("Selects the operating system type that "
235 "you plan to install into this virtual machine "
236 "(called a guest operating system)."));
237}
238
239void UINameAndSystemEditor::sltFamilyChanged(int iIndex)
240{
241 AssertPtrReturnVoid(m_pComboFamily);
242
243 /* Lock the signals of m_pComboType to prevent it's reaction on clearing: */
244 m_pComboType->blockSignals(true);
245 m_pComboType->clear();
246
247 /* Acquire family ID: */
248 m_strFamilyId = m_pComboFamily->itemData(iIndex, TypeID).toString();
249
250 /* Populate combo-box with OS types related to currently selected family id: */
251 foreach (const UIGuestOSType &guiType, m_types.value(m_strFamilyId))
252 {
253 /* Skip 64bit OS types if hardware virtualization or long mode is not supported: */
254 if (guiType.is64bit && (!m_fSupportsHWVirtEx || !m_fSupportsLongMode))
255 continue;
256 const int iIndex = m_pComboType->count();
257 m_pComboType->insertItem(iIndex, guiType.typeDescription);
258 m_pComboType->setItemData(iIndex, guiType.typeId, TypeID);
259 }
260
261 /* Select the most recently chosen item: */
262 if (m_currentIds.contains(m_strFamilyId))
263 {
264 const QString strTypeId = m_currentIds.value(m_strFamilyId);
265 const int iTypeIndex = m_pComboType->findData(strTypeId, TypeID);
266 if (iTypeIndex != -1)
267 m_pComboType->setCurrentIndex(iTypeIndex);
268 }
269 /* Or select Windows 7 item for Windows family as default: */
270 else if (m_strFamilyId == "Windows")
271 {
272 QString strDefaultID = "Windows7";
273 if (ARCH_BITS == 64 && m_fSupportsHWVirtEx && m_fSupportsLongMode)
274 strDefaultID += "_64";
275 const int iIndexWin7 = m_pComboType->findData(strDefaultID, TypeID);
276 if (iIndexWin7 != -1)
277 m_pComboType->setCurrentIndex(iIndexWin7);
278 }
279 /* Or select Oracle Linux item for Linux family as default: */
280 else if (m_strFamilyId == "Linux")
281 {
282 QString strDefaultID = "Oracle";
283 if (ARCH_BITS == 64 && m_fSupportsHWVirtEx && m_fSupportsLongMode)
284 strDefaultID += "_64";
285 const int iIndexUbuntu = m_pComboType->findData(strDefaultID, TypeID);
286 if (iIndexUbuntu != -1)
287 m_pComboType->setCurrentIndex(iIndexUbuntu);
288 }
289 /* Else simply select the first one present: */
290 else
291 m_pComboType->setCurrentIndex(0);
292
293 /* Update all the stuff: */
294 sltTypeChanged(m_pComboType->currentIndex());
295
296 /* Unlock the signals of m_pComboType: */
297 m_pComboType->blockSignals(false);
298}
299
300void UINameAndSystemEditor::sltTypeChanged(int iIndex)
301{
302 AssertPtrReturnVoid(m_pComboType);
303
304 /* Acquire type ID: */
305 m_strTypeId = m_pComboType->itemData(iIndex, TypeID).toString();
306
307 /* Update selected type pixmap: */
308 m_pIconType->setPixmap(uiCommon().vmGuestOSTypePixmapDefault(m_strTypeId));
309
310 /* Save the most recently used item: */
311 m_currentIds[m_strFamilyId] = m_strTypeId;
312
313 /* Notifies listeners about OS type change: */
314 emit sigOsTypeChanged();
315}
316
317void UINameAndSystemEditor::prepare()
318{
319 prepareThis();
320 prepareWidgets();
321 prepareConnections();
322 retranslateUi();
323}
324
325void UINameAndSystemEditor::prepareThis()
326{
327 if (m_fChooseType)
328 {
329 /* Check if host supports (AMD-V or VT-x) and long mode: */
330 CHost comHost = uiCommon().host();
331 m_fSupportsHWVirtEx = comHost.GetProcessorFeature(KProcessorFeature_HWVirtEx);
332 m_fSupportsLongMode = comHost.GetProcessorFeature(KProcessorFeature_LongMode);
333 }
334}
335
336void UINameAndSystemEditor::prepareWidgets()
337{
338 /* Create main-layout: */
339 QGridLayout *pMainLayout = new QGridLayout(this);
340 if (pMainLayout)
341 {
342 pMainLayout->setContentsMargins(0, 0, 0, 0);
343 pMainLayout->setColumnStretch(0, 0);
344 pMainLayout->setColumnStretch(1, 1);
345
346 int iRow = 0;
347
348 if (m_fChooseName)
349 {
350 /* Create name label: */
351 m_pNameLabel = new QLabel;
352 if (m_pNameLabel)
353 {
354 m_pNameLabel->setAlignment(Qt::AlignRight);
355 m_pNameLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
356
357 /* Add into layout: */
358 pMainLayout->addWidget(m_pNameLabel, iRow, 0, 1, 1);
359 }
360 /* Create name editor: */
361 m_pNameLineEdit = new QILineEdit;
362 if (m_pNameLineEdit)
363 {
364 /* Add into layout: */
365 pMainLayout->addWidget(m_pNameLineEdit, iRow, 1, 1, 2);
366 }
367
368 ++iRow;
369 }
370
371 if (m_fChoosePath)
372 {
373 /* Create path label: */
374 m_pPathLabel = new QLabel;
375 if (m_pPathLabel)
376 {
377 m_pPathLabel->setAlignment(Qt::AlignRight);
378 m_pPathLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
379
380 /* Add into layout: */
381 pMainLayout->addWidget(m_pPathLabel, iRow, 0, 1, 1);
382 }
383 /* Create path selector: */
384 m_pPathSelector = new UIFilePathSelector;
385 if (m_pPathSelector)
386 {
387 QString strDefaultMachineFolder = uiCommon().virtualBox().GetSystemProperties().GetDefaultMachineFolder();
388 m_pPathSelector->setPath(strDefaultMachineFolder);
389 m_pPathSelector->setDefaultPath(strDefaultMachineFolder);
390
391 /* Add into layout: */
392 pMainLayout->addWidget(m_pPathSelector, iRow, 1, 1, 2);
393 }
394
395 ++iRow;
396 }
397
398 if (m_fChooseType)
399 {
400 /* Create VM OS family label: */
401 m_pLabelFamily = new QLabel;
402 if (m_pLabelFamily)
403 {
404 m_pLabelFamily->setAlignment(Qt::AlignRight);
405 m_pLabelFamily->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
406
407 /* Add into layout: */
408 pMainLayout->addWidget(m_pLabelFamily, iRow, 0);
409 }
410
411 int iIconRow = iRow;
412
413 /* Create VM OS family combo: */
414 m_pComboFamily = new QComboBox;
415 if (m_pComboFamily)
416 {
417 m_pComboFamily->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
418 m_pLabelFamily->setBuddy(m_pComboFamily);
419
420 /* Add into layout: */
421 pMainLayout->addWidget(m_pComboFamily, iRow, 1);
422 }
423
424 ++iRow;
425
426 /* Create VM OS type label: */
427 m_pLabelType = new QLabel;
428 if (m_pLabelType)
429 {
430 m_pLabelType->setAlignment(Qt::AlignRight);
431 m_pLabelType->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
432
433 /* Add into layout: */
434 pMainLayout->addWidget(m_pLabelType, iRow, 0);
435 }
436 /* Create VM OS type combo: */
437 m_pComboType = new QComboBox;
438 if (m_pComboType)
439 {
440 m_pComboType->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
441 m_pLabelType->setBuddy(m_pComboType);
442
443 /* Add into layout: */
444 pMainLayout->addWidget(m_pComboType, iRow, 1);
445 }
446
447 ++iRow;
448
449 /* Create sub-layout: */
450 QVBoxLayout *pLayoutIcon = new QVBoxLayout;
451 if (pLayoutIcon)
452 {
453 /* Create VM OS type icon: */
454 m_pIconType = new QLabel;
455 if (m_pIconType)
456 {
457 m_pIconType->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
458
459 /* Add into layout: */
460 pLayoutIcon->addWidget(m_pIconType);
461 }
462
463 /* Add stretch to sub-layout: */
464 pLayoutIcon->addStretch();
465
466 /* Add into layout: */
467 pMainLayout->addLayout(pLayoutIcon, iIconRow, 2, 2, 1);
468 }
469
470 /* Initialize VM OS family combo
471 * after all widgets were created: */
472 prepareFamilyCombo();
473 }
474 }
475}
476
477void UINameAndSystemEditor::prepareFamilyCombo()
478{
479 AssertPtrReturnVoid(m_pComboFamily);
480
481 /* Acquire family IDs: */
482 m_familyIDs = uiCommon().vmGuestOSFamilyIDs();
483
484 /* For each known family ID: */
485 for (int i = 0; i < m_familyIDs.size(); ++i)
486 {
487 const QString &strFamilyId = m_familyIDs.at(i);
488
489 /* Append VM OS family combo: */
490 m_pComboFamily->insertItem(i, uiCommon().vmGuestOSFamilyDescription(strFamilyId));
491 m_pComboFamily->setItemData(i, strFamilyId, TypeID);
492
493 /* Fill in the type cache: */
494 m_types[strFamilyId] = QList<UIGuestOSType>();
495 foreach (const CGuestOSType &comType, uiCommon().vmGuestOSTypeList(strFamilyId))
496 {
497 UIGuestOSType guiType;
498 guiType.typeId = comType.GetId();
499 guiType.typeDescription = comType.GetDescription();
500 guiType.is64bit = comType.GetIs64Bit();
501 m_types[strFamilyId] << guiType;
502 }
503 }
504
505 /* Choose the 1st item to be the current: */
506 m_pComboFamily->setCurrentIndex(0);
507 /* And update the linked widgets accordingly: */
508 sltFamilyChanged(m_pComboFamily->currentIndex());
509}
510
511void UINameAndSystemEditor::prepareConnections()
512{
513 /* Prepare connections: */
514 if (m_pNameLineEdit)
515 connect(m_pNameLineEdit, &QILineEdit::textChanged,
516 this, &UINameAndSystemEditor::sigNameChanged);
517 if (m_pPathSelector)
518 connect(m_pPathSelector, &UIFilePathSelector::pathChanged,
519 this, &UINameAndSystemEditor::sigPathChanged);
520 if (m_pComboFamily)
521 connect(m_pComboFamily, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
522 this, &UINameAndSystemEditor::sltFamilyChanged);
523 if (m_pComboType)
524 connect(m_pComboType, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
525 this, &UINameAndSystemEditor::sltTypeChanged);
526}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use