VirtualBox

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

Last change on this file since 52721 was 52721, checked in by vboxsync, 11 years ago

FE/Qt: file header cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 15.2 KB
Line 
1/* $Id: UIWizardNewVDPageBasic3.cpp 52721 2014-09-12 13:39:22Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIWizardNewVDPageBasic3 class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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
39/* COM includes: */
40#include "CSystemProperties.h"
41#include "CMediumFormat.h"
42
43UIWizardNewVDPage3::UIWizardNewVDPage3(const QString &strDefaultName, const QString &strDefaultPath)
44 : m_strDefaultName(strDefaultName.isEmpty() ? QString("NewVirtualDisk1") : strDefaultName)
45 , m_strDefaultPath(strDefaultPath)
46 , m_uMediumSizeMin(_4M)
47 , m_uMediumSizeMax(vboxGlobal().virtualBox().GetSystemProperties().GetInfoVDSize())
48 , m_iSliderScale(calculateSliderScale(m_uMediumSizeMax))
49{
50}
51
52void UIWizardNewVDPage3::onSelectLocationButtonClicked()
53{
54 /* Get current folder and filename: */
55 QFileInfo fullFilePath(mediumPath());
56 QDir folder = fullFilePath.path();
57 QString strFileName = fullFilePath.fileName();
58
59 /* Set the first parent folder that exists as the current: */
60 while (!folder.exists() && !folder.isRoot())
61 {
62 QFileInfo folderInfo(folder.absolutePath());
63 if (folder == QDir(folderInfo.absolutePath()))
64 break;
65 folder = folderInfo.absolutePath();
66 }
67
68 /* But if it doesn't exists at all: */
69 if (!folder.exists() || folder.isRoot())
70 {
71 /* Use recommended one folder: */
72 QFileInfo defaultFilePath(absoluteFilePath(strFileName, m_strDefaultPath));
73 folder = defaultFilePath.path();
74 }
75
76 /* Prepare backends list: */
77 QVector<QString> fileExtensions;
78 QVector<KDeviceType> deviceTypes;
79 CMediumFormat mediumFormat = fieldImp("mediumFormat").value<CMediumFormat>();
80 mediumFormat.DescribeFileExtensions(fileExtensions, deviceTypes);
81 QStringList validExtensionList;
82 for (int i = 0; i < fileExtensions.size(); ++i)
83 if (deviceTypes[i] == KDeviceType_HardDisk)
84 validExtensionList << QString("*.%1").arg(fileExtensions[i]);
85 /* Compose full filter list: */
86 QString strBackendsList = QString("%1 (%2)").arg(mediumFormat.GetName()).arg(validExtensionList.join(" "));
87
88 /* Open corresponding file-dialog: */
89 QString strChosenFilePath = QIFileDialog::getSaveFileName(folder.absoluteFilePath(strFileName),
90 strBackendsList, thisImp(),
91 VBoxGlobal::tr("Please choose a location for new virtual hard drive file"));
92
93 /* If there was something really chosen: */
94 if (!strChosenFilePath.isEmpty())
95 {
96 /* If valid file extension is missed, append it: */
97 if (QFileInfo(strChosenFilePath).suffix().isEmpty())
98 strChosenFilePath += QString(".%1").arg(m_strDefaultExtension);
99 m_pLocationEditor->setText(QDir::toNativeSeparators(strChosenFilePath));
100 m_pLocationEditor->selectAll();
101 m_pLocationEditor->setFocus();
102 }
103}
104
105void UIWizardNewVDPage3::onSizeSliderValueChanged(int iValue)
106{
107 /* Get full size: */
108 qulonglong uMediumSize = sliderToSizeMB(iValue, m_iSliderScale);
109 /* Update tooltips: */
110 updateSizeToolTips(uMediumSize);
111 /* Notify size-editor about size had changed (preventing callback): */
112 m_pSizeEditor->blockSignals(true);
113 m_pSizeEditor->setText(vboxGlobal().formatSize(uMediumSize));
114 m_pSizeEditor->blockSignals(false);
115}
116
117void UIWizardNewVDPage3::onSizeEditorTextChanged(const QString &strValue)
118{
119 /* Get full size: */
120 qulonglong uMediumSize = vboxGlobal().parseSize(strValue);
121 /* Update tooltips: */
122 updateSizeToolTips(uMediumSize);
123 /* Notify size-slider about size had changed (preventing callback): */
124 m_pSizeSlider->blockSignals(true);
125 m_pSizeSlider->setValue(sizeMBToSlider(uMediumSize, m_iSliderScale));
126 m_pSizeSlider->blockSignals(false);
127}
128
129/* static */
130QString UIWizardNewVDPage3::toFileName(const QString &strName, const QString &strExtension)
131{
132 /* Convert passed name to native separators (it can be full, actually): */
133 QString strFileName = QDir::toNativeSeparators(strName);
134
135 /* Remove all trailing dots to avoid multiple dots before extension: */
136 int iLen;
137 while (iLen = strFileName.length(), iLen > 0 && strFileName[iLen - 1] == '.')
138 strFileName.truncate(iLen - 1);
139
140 /* Add passed extension if its not done yet: */
141 if (QFileInfo(strFileName).suffix().toLower() != strExtension)
142 strFileName += QString(".%1").arg(strExtension);
143
144 /* Return result: */
145 return strFileName;
146}
147
148/* static */
149QString UIWizardNewVDPage3::absoluteFilePath(const QString &strFileName, const QString &strDefaultPath)
150{
151 /* Wrap file-info around received file name: */
152 QFileInfo fileInfo(strFileName);
153 /* If path-info is relative or there is no path-info at all: */
154 if (fileInfo.fileName() == strFileName || fileInfo.isRelative())
155 {
156 /* Resolve path on the basis of default path we have: */
157 fileInfo = QFileInfo(strDefaultPath, strFileName);
158 }
159 /* Return full absolute hard disk file path: */
160 return QDir::toNativeSeparators(fileInfo.absoluteFilePath());
161}
162
163/* static */
164QString UIWizardNewVDPage3::defaultExtension(const CMediumFormat &mediumFormatRef)
165{
166 /* Load extension / device list: */
167 QVector<QString> fileExtensions;
168 QVector<KDeviceType> deviceTypes;
169 CMediumFormat mediumFormat(mediumFormatRef);
170 mediumFormat.DescribeFileExtensions(fileExtensions, deviceTypes);
171 for (int i = 0; i < fileExtensions.size(); ++i)
172 if (deviceTypes[i] == KDeviceType_HardDisk)
173 return fileExtensions[i].toLower();
174 AssertMsgFailed(("Extension can't be NULL!\n"));
175 return QString();
176}
177
178/* static */
179int UIWizardNewVDPage3::calculateSliderScale(qulonglong uMaximumMediumSize)
180{
181 /* Detect how many steps to recognize between adjacent powers of 2
182 * to ensure that the last slider step is exactly that we need: */
183 int iSliderScale = 0;
184 int iPower = log2i(uMaximumMediumSize);
185 qulonglong uTickMB = (qulonglong)1 << iPower;
186 if (uTickMB < uMaximumMediumSize)
187 {
188 qulonglong uTickMBNext = (qulonglong)1 << (iPower + 1);
189 qulonglong uGap = uTickMBNext - uMaximumMediumSize;
190 iSliderScale = (int)((uTickMBNext - uTickMB) / uGap);
191 }
192 return qMax(iSliderScale, 8);
193}
194
195/* static */
196int UIWizardNewVDPage3::log2i(qulonglong uValue)
197{
198 int iPower = -1;
199 while (uValue)
200 {
201 ++iPower;
202 uValue >>= 1;
203 }
204 return iPower;
205}
206
207/* static */
208int UIWizardNewVDPage3::sizeMBToSlider(qulonglong uValue, int iSliderScale)
209{
210 int iPower = log2i(uValue);
211 qulonglong uTickMB = qulonglong (1) << iPower;
212 qulonglong uTickMBNext = qulonglong (1) << (iPower + 1);
213 int iStep = (uValue - uTickMB) * iSliderScale / (uTickMBNext - uTickMB);
214 return iPower * iSliderScale + iStep;
215}
216
217/* static */
218qulonglong UIWizardNewVDPage3::sliderToSizeMB(int uValue, int iSliderScale)
219{
220 int iPower = uValue / iSliderScale;
221 int iStep = uValue % iSliderScale;
222 qulonglong uTickMB = qulonglong (1) << iPower;
223 qulonglong uTickMBNext = qulonglong (1) << (iPower + 1);
224 return uTickMB + (uTickMBNext - uTickMB) * iStep / iSliderScale;
225}
226
227void UIWizardNewVDPage3::updateSizeToolTips(qulonglong uSize)
228{
229 QString strToolTip = UIWizardNewVD::tr("<nobr>%1 (%2 B)</nobr>").arg(vboxGlobal().formatSize(uSize)).arg(uSize);
230 m_pSizeSlider->setToolTip(strToolTip);
231 m_pSizeEditor->setToolTip(strToolTip);
232}
233
234QString UIWizardNewVDPage3::mediumPath() const
235{
236 return absoluteFilePath(toFileName(m_pLocationEditor->text(), m_strDefaultExtension), m_strDefaultPath);
237}
238
239qulonglong UIWizardNewVDPage3::mediumSize() const
240{
241 return sliderToSizeMB(m_pSizeSlider->value(), m_iSliderScale);
242}
243
244void UIWizardNewVDPage3::setMediumSize(qulonglong uMediumSize)
245{
246 /* Block signals: */
247 m_pSizeSlider->blockSignals(true);
248 m_pSizeEditor->blockSignals(true);
249 /* Set values: */
250 m_pSizeSlider->setValue(sizeMBToSlider(uMediumSize, m_iSliderScale));
251 m_pSizeEditor->setText(vboxGlobal().formatSize(uMediumSize));
252 updateSizeToolTips(uMediumSize);
253 /* Unblock signals: */
254 m_pSizeSlider->blockSignals(false);
255 m_pSizeEditor->blockSignals(false);
256}
257
258UIWizardNewVDPageBasic3::UIWizardNewVDPageBasic3(const QString &strDefaultName, const QString &strDefaultPath, qulonglong uDefaultSize)
259 : UIWizardNewVDPage3(strDefaultName, strDefaultPath)
260{
261 /* Create widgets: */
262 QVBoxLayout *pMainLayout = new QVBoxLayout(this);
263 {
264 m_pLocationLabel = new QIRichTextLabel(this);
265 QHBoxLayout *pLocationLayout = new QHBoxLayout;
266 {
267 m_pLocationEditor = new QLineEdit(this);
268 m_pLocationOpenButton = new QIToolButton(this);
269 {
270 m_pLocationOpenButton->setAutoRaise(true);
271 m_pLocationOpenButton->setIcon(UIIconPool::iconSet(":/select_file_16px.png", "select_file_disabled_16px.png"));
272 }
273 pLocationLayout->addWidget(m_pLocationEditor);
274 pLocationLayout->addWidget(m_pLocationOpenButton);
275 }
276 m_pSizeLabel = new QIRichTextLabel(this);
277 QGridLayout *m_pSizeLayout = new QGridLayout;
278 {
279 m_pSizeSlider = new QSlider(this);
280 {
281 m_pSizeSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
282 m_pSizeSlider->setOrientation(Qt::Horizontal);
283 m_pSizeSlider->setTickPosition(QSlider::TicksBelow);
284 m_pSizeSlider->setFocusPolicy(Qt::StrongFocus);
285 m_pSizeSlider->setPageStep(m_iSliderScale);
286 m_pSizeSlider->setSingleStep(m_iSliderScale / 8);
287 m_pSizeSlider->setTickInterval(0);
288 m_pSizeSlider->setMinimum(sizeMBToSlider(m_uMediumSizeMin, m_iSliderScale));
289 m_pSizeSlider->setMaximum(sizeMBToSlider(m_uMediumSizeMax, m_iSliderScale));
290 }
291 m_pSizeEditor = new QILineEdit(this);
292 {
293 m_pSizeEditor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
294 m_pSizeEditor->setFixedWidthByText("88888.88 MB");
295 m_pSizeEditor->setAlignment(Qt::AlignRight);
296 m_pSizeEditor->setValidator(new QRegExpValidator(QRegExp(vboxGlobal().sizeRegexp()), this));
297 }
298 QLabel *m_pSizeMin = new QLabel(this);
299 {
300 m_pSizeMin->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
301 m_pSizeMin->setText(vboxGlobal().formatSize(m_uMediumSizeMin));
302 }
303 QLabel *m_pSizeMax = new QLabel(this);
304 {
305 m_pSizeMax->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
306 m_pSizeMax->setText(vboxGlobal().formatSize(m_uMediumSizeMax));
307 }
308 m_pSizeLayout->addWidget(m_pSizeSlider, 0, 0, 1, 3);
309 m_pSizeLayout->addWidget(m_pSizeEditor, 0, 3);
310 m_pSizeLayout->addWidget(m_pSizeMin, 1, 0);
311 m_pSizeLayout->setColumnStretch(1, 1);
312 m_pSizeLayout->addWidget(m_pSizeMax, 1, 2);
313 }
314 setMediumSize(uDefaultSize);
315 pMainLayout->addWidget(m_pLocationLabel);
316 pMainLayout->addLayout(pLocationLayout);
317 pMainLayout->addWidget(m_pSizeLabel);
318 pMainLayout->addLayout(m_pSizeLayout);
319 pMainLayout->addStretch();
320 }
321
322 /* Setup connections: */
323 connect(m_pLocationEditor, SIGNAL(textChanged(const QString &)), this, SIGNAL(completeChanged()));
324 connect(m_pLocationOpenButton, SIGNAL(clicked()), this, SLOT(sltSelectLocationButtonClicked()));
325 connect(m_pSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(sltSizeSliderValueChanged(int)));
326 connect(m_pSizeEditor, SIGNAL(textChanged(const QString &)), this, SLOT(sltSizeEditorTextChanged(const QString &)));
327
328 /* Register fields: */
329 registerField("mediumPath", this, "mediumPath");
330 registerField("mediumSize", this, "mediumSize");
331}
332
333void UIWizardNewVDPageBasic3::sltSelectLocationButtonClicked()
334{
335 /* Call to base-class: */
336 onSelectLocationButtonClicked();
337}
338
339void UIWizardNewVDPageBasic3::sltSizeSliderValueChanged(int iValue)
340{
341 /* Call to base-class: */
342 onSizeSliderValueChanged(iValue);
343
344 /* Broadcast complete-change: */
345 emit completeChanged();
346}
347
348void UIWizardNewVDPageBasic3::sltSizeEditorTextChanged(const QString &strValue)
349{
350 /* Call to base-class: */
351 onSizeEditorTextChanged(strValue);
352
353 /* Broadcast complete-change: */
354 emit completeChanged();
355}
356
357void UIWizardNewVDPageBasic3::retranslateUi()
358{
359 /* Translate page: */
360 setTitle(UIWizardNewVD::tr("File location and size"));
361
362 /* Translate widgets: */
363 m_pLocationLabel->setText(UIWizardNewVD::tr("Please type the name of the new virtual hard drive file into the box below or "
364 "click on the folder icon to select a different folder to create the file in."));
365 m_pLocationOpenButton->setToolTip(UIWizardNewVD::tr("Choose a location for new virtual hard drive file..."));
366 m_pSizeLabel->setText(UIWizardNewVD::tr("Select the size of the virtual hard drive in megabytes. "
367 "This size is the limit on the amount of file data "
368 "that a virtual machine will be able to store on the hard drive."));
369}
370
371void UIWizardNewVDPageBasic3::initializePage()
372{
373 /* Translate page: */
374 retranslateUi();
375
376 /* Get default extension for new virtual-disk: */
377 m_strDefaultExtension = defaultExtension(field("mediumFormat").value<CMediumFormat>());
378 /* Set default name as text for location editor: */
379 m_pLocationEditor->setText(m_strDefaultName);
380}
381
382bool UIWizardNewVDPageBasic3::isComplete() const
383{
384 /* Make sure current name is not empty and current size feats the bounds: */
385 return !m_pLocationEditor->text().trimmed().isEmpty() &&
386 mediumSize() >= m_uMediumSizeMin && mediumSize() <= m_uMediumSizeMax;
387}
388
389bool UIWizardNewVDPageBasic3::validatePage()
390{
391 /* Initial result: */
392 bool fResult = true;
393
394 /* Make sure such file doesn't exists already: */
395 QString strMediumPath(mediumPath());
396 fResult = !QFileInfo(strMediumPath).exists();
397 if (!fResult)
398 msgCenter().cannotOverwriteHardDiskStorage(strMediumPath, this);
399
400 if (fResult)
401 {
402 /* Lock finish button: */
403 startProcessing();
404
405 /* Try to create virtual hard drive file: */
406 fResult = qobject_cast<UIWizardNewVD*>(wizard())->createVirtualDisk();
407
408 /* Unlock finish button: */
409 endProcessing();
410 }
411
412 /* Return result: */
413 return fResult;
414}
415
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