VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/wizards/newvd/UIWizardNewVDPageBasic3.cpp@ 87859

Last change on this file since 87859 was 87859, checked in by vboxsync, 4 years ago

FE/Qt: bugref:9950. Further refactoring

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1/* $Id: UIWizardNewVDPageBasic3.cpp 87859 2021-02-24 13:01:12Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIWizardNewVDPageBasic3 class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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 <QDir>
20#include <QRegExpValidator>
21#include <QVBoxLayout>
22#include <QHBoxLayout>
23#include <QLineEdit>
24#include <QSlider>
25#include <QLabel>
26#include <QSpacerItem>
27
28/* GUI includes: */
29#include "UIWizardNewVDPageBasic3.h"
30#include "UIWizardNewVD.h"
31#include "UICommon.h"
32#include "UIMessageCenter.h"
33#include "UIIconPool.h"
34#include "QIFileDialog.h"
35#include "QIRichTextLabel.h"
36#include "QIToolButton.h"
37#include "QILineEdit.h"
38#include "UIMediumSizeEditor.h"
39
40/* COM includes: */
41#include "CSystemProperties.h"
42#include "CMediumFormat.h"
43
44/* Other VBox includes: */
45#include <iprt/cdefs.h>
46#include <iprt/path.h>
47
48
49UIWizardNewVDPage3::UIWizardNewVDPage3(const QString &strDefaultName, const QString &strDefaultPath)
50 : m_strDefaultName(strDefaultName.isEmpty() ? QString("NewVirtualDisk1") : strDefaultName)
51 , m_strDefaultPath(strDefaultPath)
52 , m_uMediumSizeMin(_4M)
53 , m_uMediumSizeMax(uiCommon().virtualBox().GetSystemProperties().GetInfoVDSize())
54 , m_pLocationEditor(0)
55 , m_pLocationOpenButton(0)
56 , m_pEditorSize(0)
57
58{
59}
60
61void UIWizardNewVDPage3::onSelectLocationButtonClicked()
62{
63 /* Get current folder and filename: */
64 QFileInfo fullFilePath(mediumPath());
65 QDir folder = fullFilePath.path();
66 QString strFileName = fullFilePath.fileName();
67
68 /* Set the first parent folder that exists as the current: */
69 while (!folder.exists() && !folder.isRoot())
70 {
71 QFileInfo folderInfo(folder.absolutePath());
72 if (folder == QDir(folderInfo.absolutePath()))
73 break;
74 folder = folderInfo.absolutePath();
75 }
76
77 /* But if it doesn't exists at all: */
78 if (!folder.exists() || folder.isRoot())
79 {
80 /* Use recommended one folder: */
81 QFileInfo defaultFilePath(absoluteFilePath(strFileName, m_strDefaultPath));
82 folder = defaultFilePath.path();
83 }
84
85 /* Prepare backends list: */
86 QVector<QString> fileExtensions;
87 QVector<KDeviceType> deviceTypes;
88 CMediumFormat mediumFormat = fieldImp("mediumFormat").value<CMediumFormat>();
89 mediumFormat.DescribeFileExtensions(fileExtensions, deviceTypes);
90 QStringList validExtensionList;
91 for (int i = 0; i < fileExtensions.size(); ++i)
92 if (deviceTypes[i] == KDeviceType_HardDisk)
93 validExtensionList << QString("*.%1").arg(fileExtensions[i]);
94 /* Compose full filter list: */
95 QString strBackendsList = QString("%1 (%2)").arg(mediumFormat.GetName()).arg(validExtensionList.join(" "));
96
97 /* Open corresponding file-dialog: */
98 QString strChosenFilePath = QIFileDialog::getSaveFileName(folder.absoluteFilePath(strFileName),
99 strBackendsList, thisImp(),
100 UICommon::tr("Please choose a location for new virtual hard disk file"));
101
102 /* If there was something really chosen: */
103 if (!strChosenFilePath.isEmpty())
104 {
105 /* If valid file extension is missed, append it: */
106 if (QFileInfo(strChosenFilePath).suffix().isEmpty())
107 strChosenFilePath += QString(".%1").arg(m_strDefaultExtension);
108 if (m_pLocationEditor)
109 {
110 m_pLocationEditor->setText(QDir::toNativeSeparators(strChosenFilePath));
111 m_pLocationEditor->selectAll();
112 m_pLocationEditor->setFocus();
113 }
114 }
115}
116
117/* static */
118QString UIWizardNewVDPage3::toFileName(const QString &strName, const QString &strExtension)
119{
120 /* Convert passed name to native separators (it can be full, actually): */
121 QString strFileName = QDir::toNativeSeparators(strName);
122
123 /* Remove all trailing dots to avoid multiple dots before extension: */
124 int iLen;
125 while (iLen = strFileName.length(), iLen > 0 && strFileName[iLen - 1] == '.')
126 strFileName.truncate(iLen - 1);
127
128 /* Add passed extension if its not done yet: */
129 if (QFileInfo(strFileName).suffix().toLower() != strExtension)
130 strFileName += QString(".%1").arg(strExtension);
131
132 /* Return result: */
133 return strFileName;
134}
135
136/* static */
137QString UIWizardNewVDPage3::absoluteFilePath(const QString &strFileName, const QString &strPath)
138{
139 /* Wrap file-info around received file name: */
140 QFileInfo fileInfo(strFileName);
141 /* If path-info is relative or there is no path-info at all: */
142 if (fileInfo.fileName() == strFileName || fileInfo.isRelative())
143 {
144 /* Resolve path on the basis of path we have: */
145 fileInfo = QFileInfo(strPath, strFileName);
146 }
147 /* Return full absolute hard disk file path: */
148 return QDir::toNativeSeparators(fileInfo.absoluteFilePath());
149}
150
151/*static */
152QString UIWizardNewVDPage3::absoluteFilePath(const QString &strFileName, const QString &strPath, const QString &strExtension)
153{
154 QString strFilePath = absoluteFilePath(strFileName, strPath);
155 if (QFileInfo(strFilePath).suffix().isEmpty())
156 strFilePath += QString(".%1").arg(strExtension);
157 return strFilePath;
158}
159
160/* static */
161QString UIWizardNewVDPage3::defaultExtension(const CMediumFormat &mediumFormatRef)
162{
163 if (!mediumFormatRef.isNull())
164 {
165 /* Load extension / device list: */
166 QVector<QString> fileExtensions;
167 QVector<KDeviceType> deviceTypes;
168 CMediumFormat mediumFormat(mediumFormatRef);
169 mediumFormat.DescribeFileExtensions(fileExtensions, deviceTypes);
170 for (int i = 0; i < fileExtensions.size(); ++i)
171 if (deviceTypes[i] == KDeviceType_HardDisk)
172 return fileExtensions[i].toLower();
173 }
174 AssertMsgFailed(("Extension can't be NULL!\n"));
175 return QString();
176}
177
178bool UIWizardNewVDPage3::checkFATSizeLimitation() const
179{
180 /* Acquire medium variant: */
181 const qulonglong uVariant = fieldImp("mediumVariant").toULongLong();
182
183 /* If the hard disk is split into 2GB parts then no need to make further checks: */
184 if (uVariant & KMediumVariant_VmdkSplit2G)
185 return true;
186
187 /* Acquire medium path and size: */
188 const QString strMediumPath = fieldImp("mediumPath").toString();
189 const qulonglong uSize = fieldImp("mediumSize").toULongLong();
190
191 RTFSTYPE enmType;
192 int rc = RTFsQueryType(QFileInfo(strMediumPath).absolutePath().toLatin1().constData(), &enmType);
193 if (RT_SUCCESS(rc))
194 {
195 if (enmType == RTFSTYPE_FAT)
196 {
197 /* Limit the medium size to 4GB. minus 128 MB for file overhead: */
198 qulonglong fatLimit = _4G - _128M;
199 if (uSize >= fatLimit)
200 return false;
201 }
202 }
203
204 return true;
205}
206
207QString UIWizardNewVDPage3::mediumPath() const
208{
209 if (!m_pLocationEditor)
210 return QString();
211 return absoluteFilePath(toFileName(m_pLocationEditor->text(), m_strDefaultExtension), m_strDefaultPath);
212}
213
214qulonglong UIWizardNewVDPage3::mediumSize() const
215{
216 return m_pEditorSize ? m_pEditorSize->mediumSize() : 0;
217}
218
219void UIWizardNewVDPage3::setMediumSize(qulonglong uMediumSize)
220{
221 if (m_pEditorSize)
222 m_pEditorSize->setMediumSize(uMediumSize);
223}
224
225void UIWizardNewVDPage3::retranslateWidgets()
226{
227 if (m_pLocationOpenButton)
228 m_pLocationOpenButton->setToolTip(UIWizardNewVD::tr("Choose a location for new virtual hard disk file..."));
229}
230
231UIWizardNewVDPageBasic3::UIWizardNewVDPageBasic3(const QString &strDefaultName, const QString &strDefaultPath, qulonglong uDefaultSize)
232 : UIWizardNewVDPage3(strDefaultName, strDefaultPath)
233{
234 /* Create widgets: */
235 QVBoxLayout *pMainLayout = new QVBoxLayout(this);
236 {
237 m_pLocationLabel = new QIRichTextLabel(this);
238 QHBoxLayout *pLocationLayout = new QHBoxLayout;
239 {
240 m_pLocationEditor = new QLineEdit(this);
241 m_pLocationOpenButton = new QIToolButton(this);
242 {
243 m_pLocationOpenButton->setAutoRaise(true);
244 m_pLocationOpenButton->setIcon(UIIconPool::iconSet(":/select_file_16px.png", "select_file_disabled_16px.png"));
245 }
246 pLocationLayout->addWidget(m_pLocationEditor);
247 pLocationLayout->addWidget(m_pLocationOpenButton);
248 }
249 m_pSizeLabel = new QIRichTextLabel(this);
250 m_pEditorSize = new UIMediumSizeEditor;
251 setMediumSize(uDefaultSize);
252 pMainLayout->addWidget(m_pLocationLabel);
253 pMainLayout->addLayout(pLocationLayout);
254 pMainLayout->addWidget(m_pSizeLabel);
255 pMainLayout->addWidget(m_pEditorSize);
256 pMainLayout->addStretch();
257 }
258
259 /* Setup connections: */
260 connect(m_pLocationEditor, &QLineEdit::textChanged, this, &UIWizardNewVDPageBasic3::completeChanged);
261 connect(m_pLocationOpenButton, &QIToolButton::clicked, this, &UIWizardNewVDPageBasic3::sltSelectLocationButtonClicked);
262 connect(m_pEditorSize, &UIMediumSizeEditor::sigSizeChanged, this, &UIWizardNewVDPageBasic3::completeChanged);
263
264 /* Register fields: */
265 registerField("mediumPath", this, "mediumPath");
266 registerField("mediumSize", this, "mediumSize");
267}
268
269void UIWizardNewVDPageBasic3::sltSelectLocationButtonClicked()
270{
271 /* Call to base-class: */
272 onSelectLocationButtonClicked();
273}
274
275void UIWizardNewVDPageBasic3::retranslateUi()
276{
277 retranslateWidgets();
278 /* Translate page: */
279 setTitle(UIWizardNewVD::tr("File location and size"));
280
281 /* Translate widgets: */
282 m_pLocationLabel->setText(UIWizardNewVD::tr("Please type the name of the new virtual hard disk file into the box below or "
283 "click on the folder icon to select a different folder to create the file in."));
284 if (m_pSizeLabel)
285 m_pSizeLabel->setText(UIWizardNewVD::tr("Select the size of the virtual hard disk in megabytes. "
286 "This size is the limit on the amount of file data "
287 "that a virtual machine will be able to store on the hard disk."));
288}
289
290void UIWizardNewVDPageBasic3::initializePage()
291{
292 /* Translate page: */
293 retranslateUi();
294
295 /* Get default extension for new virtual-disk: */
296 m_strDefaultExtension = defaultExtension(field("mediumFormat").value<CMediumFormat>());
297 /* Set default name as text for location editor: */
298 if (m_pLocationEditor)
299 m_pLocationEditor->setText(absoluteFilePath(m_strDefaultName, m_strDefaultPath, m_strDefaultExtension));
300}
301
302bool UIWizardNewVDPageBasic3::isComplete() const
303{
304 if (!m_pLocationEditor)
305 return false;
306 /* Make sure current name is not empty and current size feats the bounds: */
307 return !m_pLocationEditor->text().trimmed().isEmpty() &&
308 mediumSize() >= m_uMediumSizeMin && mediumSize() <= m_uMediumSizeMax;
309}
310
311bool UIWizardNewVDPageBasic3::validatePage()
312{
313 /* Initial result: */
314 bool fResult = true;
315
316 /* Make sure such file doesn't exist already: */
317 const QString strMediumPath(mediumPath());
318 fResult = !QFileInfo(strMediumPath).exists();
319 if (!fResult)
320 {
321 msgCenter().cannotOverwriteHardDiskStorage(strMediumPath, this);
322 return fResult;
323 }
324
325 /* Make sure we are passing FAT size limitation: */
326 fResult = checkFATSizeLimitation();
327 if (!fResult)
328 {
329 msgCenter().cannotCreateHardDiskStorageInFAT(strMediumPath, this);
330 return fResult;
331 }
332
333 /* Lock finish button: */
334 startProcessing();
335 /* Try to create virtual-disk: */
336 fResult = qobject_cast<UIWizardNewVD*>(wizard())->createVirtualDisk();
337 /* Unlock finish button: */
338 endProcessing();
339
340 /* Return result: */
341 return fResult;
342}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette