VirtualBox

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

Last change on this file since 78121 was 78121, checked in by vboxsync, 6 years ago

FE/Qt: Make sure we always show the full media file location in the new medium wizard

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

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