VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.cpp

Last change on this file was 104313, checked in by vboxsync, 7 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the settings related GUI classes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.8 KB
Line 
1/* $Id: UIMachineSettingsGeneral.cpp 104313 2024-04-12 13:10:30Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMachineSettingsGeneral 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 <QFileInfo>
30#include <QVBoxLayout>
31
32/* GUI includes: */
33#include "QITabWidget.h"
34#include "UIAddDiskEncryptionPasswordDialog.h"
35#include "UIConverter.h"
36#include "UIDefs.h"
37#include "UIDescriptionEditor.h"
38#include "UIDiskEncryptionSettingsEditor.h"
39#include "UIDragAndDropEditor.h"
40#include "UIErrorString.h"
41#include "UIGlobalSession.h"
42#include "UIMachineSettingsGeneral.h"
43#include "UIModalWindowManager.h"
44#include "UINameAndSystemEditor.h"
45#include "UIProgressObject.h"
46#include "UISharedClipboardEditor.h"
47#include "UISnapshotFolderEditor.h"
48#include "UITranslator.h"
49
50/* COM includes: */
51#include "CExtPack.h"
52#include "CExtPackManager.h"
53#include "CMedium.h"
54#include "CMediumAttachment.h"
55#include "CPlatform.h"
56#include "CPlatformX86.h"
57#include "CProgress.h"
58
59
60/** Machine settings: General page data structure. */
61struct UIDataSettingsMachineGeneral
62{
63 /** Constructs data. */
64 UIDataSettingsMachineGeneral()
65 : m_strName(QString())
66 , m_strGuestOsTypeId(QString())
67 , m_strSnapshotsFolder(QString())
68 , m_strSnapshotsHomeDir(QString())
69 , m_clipboardMode(KClipboardMode_Disabled)
70 , m_dndMode(KDnDMode_Disabled)
71 , m_strDescription(QString())
72 , m_fEncryptionEnabled(false)
73 , m_fEncryptionCipherChanged(false)
74 , m_fEncryptionPasswordChanged(false)
75 , m_enmEncryptionCipherType(UIDiskEncryptionCipherType_Max)
76 , m_strEncryptionPassword(QString())
77 {}
78
79 /** Returns whether the @a other passed data is equal to this one. */
80 bool equal(const UIDataSettingsMachineGeneral &other) const
81 {
82 return true
83 && (m_strName == other.m_strName)
84 && (m_strGuestOsTypeId == other.m_strGuestOsTypeId)
85 && (m_strSnapshotsFolder == other.m_strSnapshotsFolder)
86 && (m_clipboardMode == other.m_clipboardMode)
87 && (m_dndMode == other.m_dndMode)
88 && (m_strDescription == other.m_strDescription)
89 && (m_fEncryptionEnabled == other.m_fEncryptionEnabled)
90 && (m_fEncryptionCipherChanged == other.m_fEncryptionCipherChanged)
91 && (m_fEncryptionPasswordChanged == other.m_fEncryptionPasswordChanged)
92 ;
93 }
94
95 /** Returns whether the @a other passed data is equal to this one. */
96 bool operator==(const UIDataSettingsMachineGeneral &other) const { return equal(other); }
97 /** Returns whether the @a other passed data is different from this one. */
98 bool operator!=(const UIDataSettingsMachineGeneral &other) const { return !equal(other); }
99
100 /** Holds the VM name. */
101 QString m_strName;
102 /** Holds the VM OS type ID. */
103 QString m_strGuestOsTypeId;
104
105 /** Holds the VM snapshot folder. */
106 QString m_strSnapshotsFolder;
107 /** Holds the default VM snapshot folder. */
108 QString m_strSnapshotsHomeDir;
109 /** Holds the VM clipboard mode. */
110 KClipboardMode m_clipboardMode;
111 /** Holds the VM drag&drop mode. */
112 KDnDMode m_dndMode;
113
114 /** Holds the VM description. */
115 QString m_strDescription;
116
117 /** Holds whether the encryption is enabled. */
118 bool m_fEncryptionEnabled;
119 /** Holds whether the encryption cipher was changed. */
120 bool m_fEncryptionCipherChanged;
121 /** Holds whether the encryption password was changed. */
122 bool m_fEncryptionPasswordChanged;
123 /** Holds the encryption cipher index. */
124 UIDiskEncryptionCipherType m_enmEncryptionCipherType;
125 /** Holds the encryption password. */
126 QString m_strEncryptionPassword;
127 /** Holds the encrypted medium ids. */
128 EncryptedMediumMap m_encryptedMedia;
129 /** Holds the encryption passwords. */
130 EncryptionPasswordMap m_encryptionPasswords;
131};
132
133
134UIMachineSettingsGeneral::UIMachineSettingsGeneral()
135 : m_fEncryptionCipherChanged(false)
136 , m_fEncryptionPasswordChanged(false)
137 , m_pCache(0)
138 , m_pTabWidget(0)
139 , m_pTabBasic(0)
140 , m_pEditorNameAndSystem(0)
141 , m_pTabAdvanced(0)
142 , m_pEditorSnapshotFolder(0)
143 , m_pEditorClipboard(0)
144 , m_pEditorDragAndDrop(0)
145 , m_pTabDescription(0)
146 , m_pEditorDescription(0)
147 , m_pTabEncryption(0)
148 , m_pEditorDiskEncryptionSettings(0)
149{
150 prepare();
151}
152
153UIMachineSettingsGeneral::~UIMachineSettingsGeneral()
154{
155 cleanup();
156}
157
158QString UIMachineSettingsGeneral::guestOSTypeId() const
159{
160 AssertPtrReturn(m_pEditorNameAndSystem, QString());
161 return m_pEditorNameAndSystem->typeId();
162}
163
164bool UIMachineSettingsGeneral::changed() const
165{
166 return m_pCache ? m_pCache->wasChanged() : false;
167}
168
169void UIMachineSettingsGeneral::loadToCacheFrom(QVariant &data)
170{
171 /* Sanity check: */
172 if (!m_pCache)
173 return;
174
175 /* Fetch data to machine: */
176 UISettingsPageMachine::fetchData(data);
177
178 /* Clear cache initially: */
179 m_pCache->clear();
180
181 /* Prepare old data: */
182 UIDataSettingsMachineGeneral oldGeneralData;
183
184 /* Gather old 'Basic' data: */
185 oldGeneralData.m_strName = m_machine.GetName();
186 oldGeneralData.m_strGuestOsTypeId = m_machine.GetOSTypeId();
187
188 /* Gather old 'Advanced' data: */
189 oldGeneralData.m_strSnapshotsFolder = m_machine.GetSnapshotFolder();
190 oldGeneralData.m_strSnapshotsHomeDir = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath();
191 oldGeneralData.m_clipboardMode = m_machine.GetClipboardMode();
192 oldGeneralData.m_dndMode = m_machine.GetDnDMode();
193
194 /* Gather old 'Description' data: */
195 oldGeneralData.m_strDescription = m_machine.GetDescription();
196
197 /* Gather old 'Encryption' data: */
198 QString strCipher;
199 bool fEncryptionCipherCommon = true;
200 /* Prepare the map of the encrypted media: */
201 EncryptedMediumMap encryptedMedia;
202 foreach (const CMediumAttachment &attachment, m_machine.GetMediumAttachments())
203 {
204 /* Check hard-drive attachments only: */
205 if (attachment.GetType() == KDeviceType_HardDisk)
206 {
207 /* Get the attachment medium base: */
208 const CMedium comMedium = attachment.GetMedium();
209 /* Check medium encryption attributes: */
210 QString strCurrentCipher;
211 const QString strCurrentPasswordId = comMedium.GetEncryptionSettings(strCurrentCipher);
212 if (comMedium.isOk())
213 {
214 encryptedMedia.insert(strCurrentPasswordId, comMedium.GetId());
215 if (strCurrentCipher != strCipher)
216 {
217 if (strCipher.isNull())
218 strCipher = strCurrentCipher;
219 else
220 fEncryptionCipherCommon = false;
221 }
222 }
223 }
224 }
225 oldGeneralData.m_fEncryptionEnabled = !encryptedMedia.isEmpty();
226 oldGeneralData.m_fEncryptionCipherChanged = false;
227 oldGeneralData.m_fEncryptionPasswordChanged = false;
228 if (fEncryptionCipherCommon)
229 oldGeneralData.m_enmEncryptionCipherType = gpConverter->fromInternalString<UIDiskEncryptionCipherType>(strCipher);
230 oldGeneralData.m_encryptedMedia = encryptedMedia;
231
232 /* Cache old data: */
233 m_pCache->cacheInitialData(oldGeneralData);
234
235 /* Upload machine to data: */
236 UISettingsPageMachine::uploadData(data);
237}
238
239void UIMachineSettingsGeneral::getFromCache()
240{
241 /* Sanity check: */
242 if (!m_pCache)
243 return;
244
245 /* Get old data from cache: */
246 const UIDataSettingsMachineGeneral &oldGeneralData = m_pCache->base();
247
248 /* Load old 'Basic' data from cache: */
249 if (m_pEditorNameAndSystem)
250 {
251 m_pEditorNameAndSystem->setName(oldGeneralData.m_strName);
252 m_pEditorNameAndSystem->setGuestOSTypeByTypeId(oldGeneralData.m_strGuestOsTypeId);
253 }
254
255 /* Load old 'Advanced' data from cache: */
256 if (m_pEditorSnapshotFolder)
257 {
258 m_pEditorSnapshotFolder->setPath(oldGeneralData.m_strSnapshotsFolder);
259 m_pEditorSnapshotFolder->setInitialPath(oldGeneralData.m_strSnapshotsHomeDir);
260 }
261 if (m_pEditorClipboard)
262 m_pEditorClipboard->setValue(oldGeneralData.m_clipboardMode);
263 if (m_pEditorDragAndDrop)
264 m_pEditorDragAndDrop->setValue(oldGeneralData.m_dndMode);
265
266 /* Load old 'Description' data from cache: */
267 if (m_pEditorDescription)
268 m_pEditorDescription->setValue(oldGeneralData.m_strDescription);
269
270 /* Load old 'Encryption' data from cache: */
271 if (m_pEditorDiskEncryptionSettings)
272 {
273 m_pEditorDiskEncryptionSettings->setFeatureEnabled(oldGeneralData.m_fEncryptionEnabled);
274 m_pEditorDiskEncryptionSettings->setCipherType(oldGeneralData.m_enmEncryptionCipherType);
275 }
276 if (m_fEncryptionCipherChanged)
277 m_fEncryptionCipherChanged = oldGeneralData.m_fEncryptionCipherChanged;
278 if (m_fEncryptionPasswordChanged)
279 m_fEncryptionPasswordChanged = oldGeneralData.m_fEncryptionPasswordChanged;
280
281 /* Polish page finally: */
282 polishPage();
283
284 /* Revalidate: */
285 revalidate();
286}
287
288void UIMachineSettingsGeneral::putToCache()
289{
290 /* Sanity check: */
291 if (!m_pCache)
292 return;
293
294 /* Prepare new data: */
295 UIDataSettingsMachineGeneral newGeneralData;
296
297 /* Gather new 'Basic' data: */
298 if (m_pEditorNameAndSystem)
299 {
300 newGeneralData.m_strName = m_pEditorNameAndSystem->name();
301 newGeneralData.m_strGuestOsTypeId = m_pEditorNameAndSystem->typeId();
302 }
303
304 /* Gather new 'Advanced' data: */
305 if (m_pEditorSnapshotFolder)
306 newGeneralData.m_strSnapshotsFolder = m_pEditorSnapshotFolder->path();
307 if (m_pEditorClipboard)
308 newGeneralData.m_clipboardMode = m_pEditorClipboard->value();
309 if (m_pEditorDragAndDrop)
310 newGeneralData.m_dndMode = m_pEditorDragAndDrop->value();
311
312 /* Gather new 'Description' data: */
313 if (m_pEditorDescription)
314 newGeneralData.m_strDescription = m_pEditorDescription->value().isEmpty()
315 ? QString() : m_pEditorDescription->value();
316
317 /* Gather new 'Encryption' data: */
318 if (m_pEditorDiskEncryptionSettings)
319 {
320 newGeneralData.m_fEncryptionEnabled = m_pEditorDiskEncryptionSettings->isFeatureEnabled();
321 newGeneralData.m_fEncryptionCipherChanged = m_fEncryptionCipherChanged;
322 newGeneralData.m_fEncryptionPasswordChanged = m_fEncryptionPasswordChanged;
323 newGeneralData.m_enmEncryptionCipherType = m_pEditorDiskEncryptionSettings->cipherType();
324 newGeneralData.m_strEncryptionPassword = m_pEditorDiskEncryptionSettings->password1();
325 newGeneralData.m_encryptedMedia = m_pCache->base().m_encryptedMedia;
326 /* If encryption status, cipher or password is changed: */
327 if (newGeneralData.m_fEncryptionEnabled != m_pCache->base().m_fEncryptionEnabled ||
328 newGeneralData.m_fEncryptionCipherChanged != m_pCache->base().m_fEncryptionCipherChanged ||
329 newGeneralData.m_fEncryptionPasswordChanged != m_pCache->base().m_fEncryptionPasswordChanged)
330 {
331 /* Ask for the disk encryption passwords if necessary: */
332 if (!m_pCache->base().m_encryptedMedia.isEmpty())
333 {
334 /* Create corresponding dialog: */
335 QWidget *pDlgParent = windowManager().realParentWindow(window());
336 QPointer<UIAddDiskEncryptionPasswordDialog> pDlg =
337 new UIAddDiskEncryptionPasswordDialog(pDlgParent,
338 newGeneralData.m_strName,
339 newGeneralData.m_encryptedMedia);
340 /* Execute it and acquire the result: */
341 if (pDlg->exec() == QDialog::Accepted)
342 newGeneralData.m_encryptionPasswords = pDlg->encryptionPasswords();
343 /* Delete dialog if still valid: */
344 if (pDlg)
345 delete pDlg;
346 }
347 }
348 }
349
350 /* Cache new data: */
351 m_pCache->cacheCurrentData(newGeneralData);
352}
353
354void UIMachineSettingsGeneral::saveFromCacheTo(QVariant &data)
355{
356 /* Fetch data to machine: */
357 UISettingsPageMachine::fetchData(data);
358
359 /* Update data and failing state: */
360 setFailed(!saveData());
361
362 /* Upload machine to data: */
363 UISettingsPageMachine::uploadData(data);
364}
365
366bool UIMachineSettingsGeneral::validate(QList<UIValidationMessage> &messages)
367{
368 /* Pass by default: */
369 bool fPass = true;
370
371 /* Prepare message: */
372 UIValidationMessage message;
373
374 /* 'Basic' tab validations: */
375 message.first = UITranslator::removeAccelMark(m_pTabWidget->tabText(0));
376 message.second.clear();
377
378 /* VM name validation: */
379 AssertPtrReturn(m_pEditorNameAndSystem, false);
380 if (m_pEditorNameAndSystem->name().trimmed().isEmpty())
381 {
382 message.second << tr("No name specified for the virtual machine.");
383 fPass = false;
384 }
385
386 /* Serialize message: */
387 if (!message.second.isEmpty())
388 messages << message;
389
390 /* 'Encryption' tab validations: */
391 message.first = UITranslator::removeAccelMark(m_pTabWidget->tabText(3));
392 message.second.clear();
393
394 /* Encryption validation: */
395 AssertPtrReturn(m_pEditorDiskEncryptionSettings, false);
396 if (m_pEditorDiskEncryptionSettings->isFeatureEnabled())
397 {
398 /* Encryption Extension Pack presence test: */
399 CExtPackManager extPackManager = gpGlobalSession->virtualBox().GetExtensionPackManager();
400 if (!extPackManager.isNull() && !extPackManager.IsExtPackUsable(GUI_ExtPackName))
401 {
402 message.second << tr("You are trying to enable disk encryption for this virtual machine. "
403 "However, this requires the <i>%1</i> to be installed. "
404 "Please install the Extension Pack from the VirtualBox download site.")
405 .arg(GUI_ExtPackName);
406 fPass = false;
407 }
408
409 /* Cipher should be chosen if once changed: */
410 if ( !m_pCache->base().m_fEncryptionEnabled
411 || m_fEncryptionCipherChanged)
412 {
413 if (m_pEditorDiskEncryptionSettings->cipherType() == UIDiskEncryptionCipherType_Unchanged)
414 message.second << tr("Disk encryption cipher type not specified.");
415 fPass = false;
416 }
417
418 /* Password should be entered and confirmed if once changed: */
419 if (!m_pCache->base().m_fEncryptionEnabled ||
420 m_fEncryptionPasswordChanged)
421 {
422 if (m_pEditorDiskEncryptionSettings->password1().isEmpty())
423 message.second << tr("Disk encryption password empty.");
424 else
425 if (m_pEditorDiskEncryptionSettings->password1() !=
426 m_pEditorDiskEncryptionSettings->password2())
427 message.second << tr("Disk encryption passwords do not match.");
428 fPass = false;
429 }
430 }
431
432 /* Serialize message: */
433 if (!message.second.isEmpty())
434 messages << message;
435
436 /* Return result: */
437 return fPass;
438}
439
440void UIMachineSettingsGeneral::setOrderAfter(QWidget *pWidget)
441{
442 /* 'Basic' tab: */
443 if (pWidget && m_pTabWidget && m_pTabWidget->focusProxy())
444 setTabOrder(pWidget, m_pTabWidget->focusProxy());
445 if (m_pTabWidget && m_pTabWidget->focusProxy() && m_pEditorNameAndSystem)
446 setTabOrder(m_pTabWidget->focusProxy(), m_pEditorNameAndSystem);
447
448 /* 'Advanced' tab: */
449 if (m_pEditorNameAndSystem && m_pEditorSnapshotFolder)
450 setTabOrder(m_pEditorNameAndSystem, m_pEditorSnapshotFolder);
451 if (m_pEditorSnapshotFolder && m_pEditorClipboard)
452 setTabOrder(m_pEditorSnapshotFolder, m_pEditorClipboard);
453 if (m_pEditorClipboard && m_pEditorDragAndDrop)
454 setTabOrder(m_pEditorClipboard, m_pEditorDragAndDrop);
455
456 /* 'Description' tab: */
457 if (m_pEditorDragAndDrop && m_pEditorDescription)
458 setTabOrder(m_pEditorDragAndDrop, m_pEditorDescription);
459}
460
461void UIMachineSettingsGeneral::sltRetranslateUI()
462{
463 m_pTabWidget->setTabText(m_pTabWidget->indexOf(m_pTabBasic), tr("Basi&c"));
464 m_pTabWidget->setTabText(m_pTabWidget->indexOf(m_pTabAdvanced), tr("A&dvanced"));
465 m_pTabWidget->setTabText(m_pTabWidget->indexOf(m_pTabDescription), tr("D&escription"));
466 m_pTabWidget->setTabText(m_pTabWidget->indexOf(m_pTabEncryption), tr("Disk Enc&ryption"));
467
468 updateMinimumLayoutHint();
469}
470
471void UIMachineSettingsGeneral::handleFilterChange()
472{
473 updateMinimumLayoutHint();
474}
475
476void UIMachineSettingsGeneral::polishPage()
477{
478 /* Polish 'Basic' availability: */
479 if (m_pEditorNameAndSystem)
480 {
481 m_pEditorNameAndSystem->setNameStuffEnabled(isMachineOffline() || isMachineSaved());
482 m_pEditorNameAndSystem->setPathStuffEnabled(isMachineOffline());
483 m_pEditorNameAndSystem->setOSTypeStuffEnabled(isMachineOffline());
484 }
485
486 /* Polish 'Advanced' availability: */
487 if (m_pEditorSnapshotFolder)
488 m_pEditorSnapshotFolder->setEnabled(isMachineOffline());
489 if (m_pEditorClipboard)
490 m_pEditorClipboard->setEnabled(isMachineInValidMode());
491 if (m_pEditorDragAndDrop)
492 m_pEditorDragAndDrop->setEnabled(isMachineInValidMode());
493
494 /* Polish 'Description' availability: */
495 if (m_pEditorDescription)
496 m_pEditorDescription->setEnabled(isMachineInValidMode());
497
498 /* Polish 'Encryption' availability: */
499 if (m_pEditorDiskEncryptionSettings)
500 m_pEditorDiskEncryptionSettings->setEnabled(isMachineOffline());
501}
502
503void UIMachineSettingsGeneral::sltHandleEncryptionCipherChanged()
504{
505 m_fEncryptionCipherChanged = true;
506 revalidate();
507}
508
509void UIMachineSettingsGeneral::sltHandleEncryptionPasswordChanged()
510{
511 m_fEncryptionCipherChanged = true;
512 m_fEncryptionPasswordChanged = true;
513 revalidate();
514}
515
516void UIMachineSettingsGeneral::prepare()
517{
518 /* Prepare cache: */
519 m_pCache = new UISettingsCacheMachineGeneral;
520 AssertPtrReturnVoid(m_pCache);
521
522 /* Prepare everything: */
523 prepareWidgets();
524 prepareConnections();
525
526 /* Apply language settings: */
527 sltRetranslateUI();
528}
529
530void UIMachineSettingsGeneral::prepareWidgets()
531{
532 /* Prepare main layout: */
533 QHBoxLayout *pLayoutMain = new QHBoxLayout(this);
534 if (pLayoutMain)
535 {
536 /* Prepare tab-widget: */
537 m_pTabWidget = new QITabWidget(this);
538 if (m_pTabWidget)
539 {
540 /* Prepare each tab separately: */
541 prepareTabBasic();
542 prepareTabAdvanced();
543 prepareTabDescription();
544 prepareTabEncryption();
545
546 pLayoutMain->addWidget(m_pTabWidget);
547 }
548 }
549}
550
551void UIMachineSettingsGeneral::prepareTabBasic()
552{
553 /* Prepare 'Basic' tab: */
554 m_pTabBasic = new UIEditor(m_pTabWidget);
555 if (m_pTabBasic)
556 {
557 /* Prepare 'Basic' tab layout: */
558 QVBoxLayout *pLayoutBasic = new QVBoxLayout(m_pTabBasic);
559 if (pLayoutBasic)
560 {
561#ifdef VBOX_WS_MAC
562 /* On Mac OS X we can do a bit of smoothness: */
563 int iLeft, iTop, iRight, iBottom;
564 pLayoutBasic->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
565 pLayoutBasic->setContentsMargins(iLeft / 2, iTop / 2, iRight / 2, iBottom / 2);
566#endif
567
568 /* Prepare name and system editor: */
569 m_pEditorNameAndSystem = new UINameAndSystemEditor(m_pTabBasic);
570 if (m_pEditorNameAndSystem)
571 {
572 m_pTabBasic->addEditor(m_pEditorNameAndSystem);
573 pLayoutBasic->addWidget(m_pEditorNameAndSystem);
574 }
575
576 pLayoutBasic->addStretch();
577 }
578
579 addEditor(m_pTabBasic);
580 m_pTabWidget->addTab(m_pTabBasic, QString());
581 }
582}
583
584void UIMachineSettingsGeneral::prepareTabAdvanced()
585{
586 /* Prepare 'Advanced' tab: */
587 m_pTabAdvanced = new UIEditor(m_pTabWidget);
588 if (m_pTabAdvanced)
589 {
590 /* Prepare 'Advanced' tab layout: */
591 QVBoxLayout *pLayoutAdvanced = new QVBoxLayout(m_pTabAdvanced);
592 if (pLayoutAdvanced)
593 {
594#ifdef VBOX_WS_MAC
595 /* On Mac OS X we can do a bit of smoothness: */
596 int iLeft, iTop, iRight, iBottom;
597 pLayoutAdvanced->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
598 pLayoutAdvanced->setContentsMargins(iLeft / 2, iTop / 2, iRight / 2, iBottom / 2);
599#endif
600
601 /* Prepare snapshot folder editor: */
602 m_pEditorSnapshotFolder = new UISnapshotFolderEditor(m_pTabAdvanced);
603 if (m_pEditorSnapshotFolder)
604 {
605 m_pTabAdvanced->addEditor(m_pEditorSnapshotFolder);
606 pLayoutAdvanced->addWidget(m_pEditorSnapshotFolder);
607 }
608
609 /* Prepare clipboard editor: */
610 m_pEditorClipboard = new UISharedClipboardEditor(m_pTabAdvanced);
611 if (m_pEditorClipboard)
612 {
613 m_pTabAdvanced->addEditor(m_pEditorClipboard);
614 pLayoutAdvanced->addWidget(m_pEditorClipboard);
615 }
616
617 /* Prepare drag&drop editor: */
618 m_pEditorDragAndDrop = new UIDragAndDropEditor(m_pTabAdvanced);
619 if (m_pEditorDragAndDrop)
620 {
621 m_pTabAdvanced->addEditor(m_pEditorDragAndDrop);
622 pLayoutAdvanced->addWidget(m_pEditorDragAndDrop);
623 }
624
625 pLayoutAdvanced->addStretch();
626 }
627
628 addEditor(m_pTabAdvanced);
629 m_pTabWidget->addTab(m_pTabAdvanced, QString());
630 }
631}
632
633void UIMachineSettingsGeneral::prepareTabDescription()
634{
635 /* Prepare 'Description' tab: */
636 m_pTabDescription = new UIEditor(m_pTabWidget);
637 if (m_pTabDescription)
638 {
639 /* Prepare 'Description' tab layout: */
640 QVBoxLayout *pLayoutDescription = new QVBoxLayout(m_pTabDescription);
641 if (pLayoutDescription)
642 {
643#ifdef VBOX_WS_MAC
644 /* On Mac OS X we can do a bit of smoothness: */
645 int iLeft, iTop, iRight, iBottom;
646 pLayoutDescription->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
647 pLayoutDescription->setContentsMargins(iLeft / 2, iTop / 2, iRight / 2, iBottom / 2);
648#endif
649
650 /* Prepare description editor: */
651 m_pEditorDescription = new UIDescriptionEditor(m_pTabDescription);
652 if (m_pEditorDescription)
653 {
654 m_pEditorDescription->setObjectName(QStringLiteral("m_pEditorDescription"));
655 m_pTabDescription->addEditor(m_pEditorDescription);
656 pLayoutDescription->addWidget(m_pEditorDescription);
657 }
658 }
659
660 addEditor(m_pTabDescription);
661 m_pTabWidget->addTab(m_pTabDescription, QString());
662 }
663}
664
665void UIMachineSettingsGeneral::prepareTabEncryption()
666{
667 /* Prepare 'Encryption' tab: */
668 m_pTabEncryption = new UIEditor(m_pTabWidget);
669 if (m_pTabEncryption)
670 {
671 /* Prepare 'Encryption' tab layout: */
672 QVBoxLayout *pLayoutEncryption = new QVBoxLayout(m_pTabEncryption);
673 if (pLayoutEncryption)
674 {
675#ifdef VBOX_WS_MAC
676 /* On Mac OS X we can do a bit of smoothness: */
677 int iLeft, iTop, iRight, iBottom;
678 pLayoutEncryption->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
679 pLayoutEncryption->setContentsMargins(iLeft / 2, iTop / 2, iRight / 2, iBottom / 2);
680#endif
681
682 /* Prepare disk encryption settings editor: */
683 m_pEditorDiskEncryptionSettings = new UIDiskEncryptionSettingsEditor(m_pTabEncryption);
684 if (m_pEditorDiskEncryptionSettings)
685 {
686 m_pTabEncryption->addEditor(m_pEditorDiskEncryptionSettings);
687 pLayoutEncryption->addWidget(m_pEditorDiskEncryptionSettings);
688 }
689
690 pLayoutEncryption->addStretch();
691 }
692
693 addEditor(m_pTabEncryption);
694 m_pTabWidget->addTab(m_pTabEncryption, QString());
695 }
696}
697
698void UIMachineSettingsGeneral::prepareConnections()
699{
700 /* Configure 'Basic' connections: */
701 connect(m_pEditorNameAndSystem, &UINameAndSystemEditor::sigOsTypeChanged,
702 this, &UIMachineSettingsGeneral::revalidate);
703 connect(m_pEditorNameAndSystem, &UINameAndSystemEditor::sigNameChanged,
704 this, &UIMachineSettingsGeneral::revalidate);
705
706 /* Configure 'Encryption' connections: */
707 connect(m_pEditorDiskEncryptionSettings, &UIDiskEncryptionSettingsEditor::sigStatusChanged,
708 this, &UIMachineSettingsGeneral::revalidate);
709 connect(m_pEditorDiskEncryptionSettings, &UIDiskEncryptionSettingsEditor::sigCipherChanged,
710 this, &UIMachineSettingsGeneral::sltHandleEncryptionCipherChanged);
711 connect(m_pEditorDiskEncryptionSettings, &UIDiskEncryptionSettingsEditor::sigPasswordChanged,
712 this, &UIMachineSettingsGeneral::sltHandleEncryptionPasswordChanged);
713}
714
715void UIMachineSettingsGeneral::cleanup()
716{
717 /* Cleanup cache: */
718 delete m_pCache;
719 m_pCache = 0;
720}
721
722bool UIMachineSettingsGeneral::saveData()
723{
724 /* Sanity check: */
725 if (!m_pCache)
726 return false;
727
728 /* Prepare result: */
729 bool fSuccess = true;
730 /* Save general settings from cache: */
731 if (fSuccess && isMachineInValidMode() && m_pCache->wasChanged())
732 {
733 /* Save 'Basic' data from cache: */
734 if (fSuccess)
735 fSuccess = saveBasicData();
736 /* Save 'Advanced' data from cache: */
737 if (fSuccess)
738 fSuccess = saveAdvancedData();
739 /* Save 'Description' data from cache: */
740 if (fSuccess)
741 fSuccess = saveDescriptionData();
742 /* Save 'Encryption' data from cache: */
743 if (fSuccess)
744 fSuccess = saveEncryptionData();
745 }
746 /* Return result: */
747 return fSuccess;
748}
749
750bool UIMachineSettingsGeneral::saveBasicData()
751{
752 /* Sanity check: */
753 if (!m_pCache)
754 return false;
755
756 /* Prepare result: */
757 bool fSuccess = true;
758 /* Save 'Basic' data from cache: */
759 if (fSuccess)
760 {
761 /* Get old data from cache: */
762 const UIDataSettingsMachineGeneral &oldGeneralData = m_pCache->base();
763 /* Get new data from cache: */
764 const UIDataSettingsMachineGeneral &newGeneralData = m_pCache->data();
765
766 /* Save machine OS type ID: */
767 if (isMachineOffline() && newGeneralData.m_strGuestOsTypeId != oldGeneralData.m_strGuestOsTypeId)
768 {
769 if (fSuccess)
770 {
771 m_machine.SetOSTypeId(newGeneralData.m_strGuestOsTypeId);
772 fSuccess = m_machine.isOk();
773 }
774 if (fSuccess)
775 {
776 /* Update long mode CPU feature bit when OS type changed: */
777 const KPlatformArchitecture enmArch = optionalFlags().contains("arch")
778 ? optionalFlags().value("arch").value<KPlatformArchitecture>()
779 : KPlatformArchitecture_x86;
780 switch (enmArch)
781 {
782 case KPlatformArchitecture_x86:
783 {
784 const CPlatform comPlatform = m_machine.GetPlatform();
785 CPlatformX86 comPlatformX86 = comPlatform.GetX86();
786 const CGuestOSType comNewType = gpGlobalSession->virtualBox().GetGuestOSType(newGeneralData.m_strGuestOsTypeId);
787 comPlatformX86.SetCPUProperty(KCPUPropertyTypeX86_LongMode, comNewType.GetIs64Bit());
788 fSuccess = comPlatformX86.isOk();
789 /// @todo convey error info ..
790 break;
791 }
792 default:
793 break;
794 }
795 }
796 }
797
798 /* Show error message if necessary: */
799 if (!fSuccess)
800 notifyOperationProgressError(UIErrorString::formatErrorInfo(m_machine));
801 }
802 /* Return result: */
803 return fSuccess;
804}
805
806bool UIMachineSettingsGeneral::saveAdvancedData()
807{
808 /* Sanity check: */
809 if (!m_pCache)
810 return false;
811
812 /* Prepare result: */
813 bool fSuccess = true;
814 /* Save 'Advanced' data from cache: */
815 if (fSuccess)
816 {
817 /* Get old data from cache: */
818 const UIDataSettingsMachineGeneral &oldGeneralData = m_pCache->base();
819 /* Get new data from cache: */
820 const UIDataSettingsMachineGeneral &newGeneralData = m_pCache->data();
821
822 /* Save machine clipboard mode: */
823 if (fSuccess && newGeneralData.m_clipboardMode != oldGeneralData.m_clipboardMode)
824 {
825 m_machine.SetClipboardMode(newGeneralData.m_clipboardMode);
826 fSuccess = m_machine.isOk();
827 }
828 /* Save machine D&D mode: */
829 if (fSuccess && newGeneralData.m_dndMode != oldGeneralData.m_dndMode)
830 {
831 m_machine.SetDnDMode(newGeneralData.m_dndMode);
832 fSuccess = m_machine.isOk();
833 }
834 /* Save machine snapshot folder: */
835 if (fSuccess && isMachineOffline() && newGeneralData.m_strSnapshotsFolder != oldGeneralData.m_strSnapshotsFolder)
836 {
837 m_machine.SetSnapshotFolder(newGeneralData.m_strSnapshotsFolder);
838 fSuccess = m_machine.isOk();
839 }
840 // VM name from 'Basic' data should go after the snapshot folder from the 'Advanced' data
841 // as otherwise VM rename magic can collide with the snapshot folder one.
842 /* Save machine name: */
843 if (fSuccess && (isMachineOffline() || isMachineSaved()) && newGeneralData.m_strName != oldGeneralData.m_strName)
844 {
845 m_machine.SetName(newGeneralData.m_strName);
846 fSuccess = m_machine.isOk();
847 }
848
849 /* Show error message if necessary: */
850 if (!fSuccess)
851 notifyOperationProgressError(UIErrorString::formatErrorInfo(m_machine));
852 }
853 /* Return result: */
854 return fSuccess;
855}
856
857bool UIMachineSettingsGeneral::saveDescriptionData()
858{
859 /* Sanity check: */
860 if (!m_pCache)
861 return false;
862
863 /* Prepare result: */
864 bool fSuccess = true;
865 /* Save 'Description' data from cache: */
866 if (fSuccess)
867 {
868 /* Get old data from cache: */
869 const UIDataSettingsMachineGeneral &oldGeneralData = m_pCache->base();
870 /* Get new data from cache: */
871 const UIDataSettingsMachineGeneral &newGeneralData = m_pCache->data();
872
873 /* Save machine description: */
874 if (fSuccess && newGeneralData.m_strDescription != oldGeneralData.m_strDescription)
875 {
876 m_machine.SetDescription(newGeneralData.m_strDescription);
877 fSuccess = m_machine.isOk();
878 }
879
880 /* Show error message if necessary: */
881 if (!fSuccess)
882 notifyOperationProgressError(UIErrorString::formatErrorInfo(m_machine));
883 }
884 /* Return result: */
885 return fSuccess;
886}
887
888bool UIMachineSettingsGeneral::saveEncryptionData()
889{
890 /* Sanity check: */
891 if (!m_pCache)
892 return false;
893
894 /* Prepare result: */
895 bool fSuccess = true;
896 /* Save 'Encryption' data from cache: */
897 if (fSuccess)
898 {
899 /* Get old data from cache: */
900 const UIDataSettingsMachineGeneral &oldGeneralData = m_pCache->base();
901 /* Get new data from cache: */
902 const UIDataSettingsMachineGeneral &newGeneralData = m_pCache->data();
903
904 /* Make sure it either encryption state is changed itself,
905 * or the encryption was already enabled and either cipher or password is changed. */
906 if ( isMachineOffline()
907 && ( newGeneralData.m_fEncryptionEnabled != oldGeneralData.m_fEncryptionEnabled
908 || ( oldGeneralData.m_fEncryptionEnabled
909 && ( newGeneralData.m_fEncryptionCipherChanged != oldGeneralData.m_fEncryptionCipherChanged
910 || newGeneralData.m_fEncryptionPasswordChanged != oldGeneralData.m_fEncryptionPasswordChanged))))
911 {
912 /* Get machine name for further activities: */
913 QString strMachineName;
914 if (fSuccess)
915 {
916 strMachineName = m_machine.GetName();
917 fSuccess = m_machine.isOk();
918 }
919 /* Get machine attachments for further activities: */
920 CMediumAttachmentVector attachments;
921 if (fSuccess)
922 {
923 attachments = m_machine.GetMediumAttachments();
924 fSuccess = m_machine.isOk();
925 }
926
927 /* Show error message if necessary: */
928 if (!fSuccess)
929 notifyOperationProgressError(UIErrorString::formatErrorInfo(m_machine));
930
931 /* For each attachment: */
932 for (int iIndex = 0; fSuccess && iIndex < attachments.size(); ++iIndex)
933 {
934 /* Get current attachment: */
935 const CMediumAttachment &comAttachment = attachments.at(iIndex);
936
937 /* Get attachment type for further activities: */
938 KDeviceType enmType = KDeviceType_Null;
939 if (fSuccess)
940 {
941 enmType = comAttachment.GetType();
942 fSuccess = comAttachment.isOk();
943 }
944 /* Get attachment medium for further activities: */
945 CMedium comMedium;
946 if (fSuccess)
947 {
948 comMedium = comAttachment.GetMedium();
949 fSuccess = comAttachment.isOk();
950 }
951
952 /* Show error message if necessary: */
953 if (!fSuccess)
954 notifyOperationProgressError(UIErrorString::formatErrorInfo(comAttachment));
955 else
956 {
957 /* Pass hard-drives only: */
958 if (enmType != KDeviceType_HardDisk)
959 continue;
960
961 /* Get medium id for further activities: */
962 QUuid uMediumId;
963 if (fSuccess)
964 {
965 uMediumId = comMedium.GetId();
966 fSuccess = comMedium.isOk();
967 }
968
969 /* Create encryption update progress: */
970 CProgress comProgress;
971 if (fSuccess)
972 {
973 /* Cipher attribute changed? */
974 const QString strNewCipher
975 = newGeneralData.m_fEncryptionCipherChanged && newGeneralData.m_fEncryptionEnabled
976 ? gpConverter->toInternalString(newGeneralData.m_enmEncryptionCipherType)
977 : QString();
978
979 /* Password attribute changed? */
980 QString strNewPassword;
981 QString strNewPasswordId;
982 if (newGeneralData.m_fEncryptionPasswordChanged)
983 {
984 strNewPassword = newGeneralData.m_fEncryptionEnabled ?
985 newGeneralData.m_strEncryptionPassword : QString();
986 strNewPasswordId = newGeneralData.m_fEncryptionEnabled ?
987 strMachineName : QString();
988 }
989
990 /* Get the maps of encrypted media and their passwords: */
991 const EncryptedMediumMap &encryptedMedium = newGeneralData.m_encryptedMedia;
992 const EncryptionPasswordMap &encryptionPasswords = newGeneralData.m_encryptionPasswords;
993
994 /* Check if old password exists/provided: */
995 const QString strOldPasswordId = encryptedMedium.key(uMediumId);
996 const QString strOldPassword = encryptionPasswords.value(strOldPasswordId);
997
998 /* Create encryption progress: */
999 comProgress = comMedium.ChangeEncryption(strOldPassword,
1000 strNewCipher,
1001 strNewPassword,
1002 strNewPasswordId);
1003 fSuccess = comMedium.isOk();
1004 }
1005
1006 /* Create encryption update progress object: */
1007 QPointer<UIProgressObject> pObject;
1008 if (fSuccess)
1009 {
1010 pObject = new UIProgressObject(comProgress);
1011 if (pObject)
1012 {
1013 connect(pObject.data(), &UIProgressObject::sigProgressChange,
1014 this, &UIMachineSettingsGeneral::sigOperationProgressChange,
1015 Qt::QueuedConnection);
1016 connect(pObject.data(), &UIProgressObject::sigProgressError,
1017 this, &UIMachineSettingsGeneral::sigOperationProgressError,
1018 Qt::BlockingQueuedConnection);
1019 pObject->exec();
1020 if (pObject)
1021 delete pObject;
1022 else
1023 {
1024 // Premature application shutdown,
1025 // exit immediately:
1026 return true;
1027 }
1028 }
1029 }
1030
1031 /* Show error message if necessary: */
1032 if (!fSuccess)
1033 notifyOperationProgressError(UIErrorString::formatErrorInfo(comMedium));
1034 }
1035 }
1036 }
1037 }
1038 /* Return result: */
1039 return fSuccess;
1040}
1041
1042void UIMachineSettingsGeneral::updateMinimumLayoutHint()
1043{
1044 /* These editors have own labels, but we want them to be properly layouted according to each other: */
1045 int iMinimumLayoutHint = 0;
1046 if (m_pEditorSnapshotFolder && !m_pEditorSnapshotFolder->isHidden())
1047 iMinimumLayoutHint = qMax(iMinimumLayoutHint, m_pEditorSnapshotFolder->minimumLabelHorizontalHint());
1048 if (m_pEditorClipboard && !m_pEditorClipboard->isHidden())
1049 iMinimumLayoutHint = qMax(iMinimumLayoutHint, m_pEditorClipboard->minimumLabelHorizontalHint());
1050 if (m_pEditorDragAndDrop && !m_pEditorDragAndDrop->isHidden())
1051 iMinimumLayoutHint = qMax(iMinimumLayoutHint, m_pEditorDragAndDrop->minimumLabelHorizontalHint());
1052 if (m_pEditorSnapshotFolder)
1053 m_pEditorSnapshotFolder->setMinimumLayoutIndent(iMinimumLayoutHint);
1054 if (m_pEditorClipboard)
1055 m_pEditorClipboard->setMinimumLayoutIndent(iMinimumLayoutHint);
1056 if (m_pEditorDragAndDrop)
1057 m_pEditorDragAndDrop->setMinimumLayoutIndent(iMinimumLayoutHint);
1058}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use