VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/ui/VBoxNewHDWzd.ui.h@ 2597

Last change on this file since 2597 was 2593, checked in by vboxsync, 18 years ago

1764: Better default size in "Create VDI" wizard when called from "Create VM" wizard:

Rollback NewVM & NewHD Wizards QLabels to old *.ui version.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.3 KB
Line 
1/**
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * "New hard disk" wizard UI include (Qt Designer)
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23/****************************************************************************
24** ui.h extension file, included from the uic-generated form implementation.
25**
26** If you want to add, delete, or rename functions or slots, use
27** Qt Designer to update this file, preserving your code.
28**
29** You should not define a constructor or destructor in this file.
30** Instead, write your code in functions called init() and destroy().
31** These will automatically be called by the form's constructor and
32** destructor.
33*****************************************************************************/
34
35/** Minimum VDI size in MB */
36static const Q_UINT64 MinVDISize = 4;
37
38/** Initial VDI size in MB */
39static const Q_UINT64 InitialVDISize = 2 * _1K;
40
41/**
42 * Composes a file name from the given relative or full file name
43 * based on the home directory and the default VDI directory.
44 */
45static QString composeFullFileName (const QString file)
46{
47 CVirtualBox vbox = vboxGlobal().virtualBox();
48 QString homeFolder = vbox.GetHomeFolder();
49 QString defaultFolder = vbox.GetSystemProperties().GetDefaultVDIFolder();
50
51 QFileInfo fi = QFileInfo (file);
52 if (fi.fileName() == file)
53 {
54 /* no path info at all, use defaultFolder */
55 fi = QFileInfo (defaultFolder, file);
56 }
57 else if (fi.isRelative())
58 {
59 /* resolve relatively to homeFolder */
60 fi = QFileInfo (homeFolder, file);
61 }
62
63 return QDir::convertSeparators (fi.absFilePath());
64}
65
66/// @todo (r=dmik) not currently used
67#if 0
68class QISizeValidator : public QValidator
69{
70public:
71
72 QISizeValidator (QObject * aParent,
73 Q_UINT64 aMinSize, Q_UINT64 aMaxSize,
74 const char * aName = 0) :
75 QValidator (aParent, aName), mMinSize (aMinSize), mMaxSize (aMaxSize) {}
76
77 ~QISizeValidator() {}
78
79 State validate (QString &input, int &/*pos*/) const
80 {
81 QRegExp regexp ("^([^M^G^T^P^\\d\\s]*)(\\d+(([^\\s^\\d^M^G^T^P]+)(\\d*))?)?(\\s*)([MGTP]B?)?$");
82 int position = regexp.search (input);
83 if (position == -1)
84 return Invalid;
85 else
86 {
87 if (!regexp.cap (1).isEmpty() ||
88 regexp.cap (4).length() > 1 ||
89 regexp.cap (5).length() > 2 ||
90 regexp.cap (6).length() > 1)
91 return Invalid;
92
93 if (regexp.cap (7).length() == 1)
94 return Intermediate;
95
96 QString size = regexp.cap (2);
97 if (size.isEmpty())
98 return Intermediate;
99
100 bool result = false;
101 bool warning = false;
102 if (!regexp.cap (4).isEmpty() && regexp.cap (5).isEmpty())
103 {
104 size += "0";
105 warning = true;
106 }
107 QLocale::system().toDouble (size, &result);
108
109 Q_UINT64 sizeB = vboxGlobal().parseSize (input);
110 if (sizeB > mMaxSize || sizeB < mMinSize)
111 warning = true;
112
113 if (result)
114 return warning ? Intermediate : Acceptable;
115 else
116 return Invalid;
117 }
118 }
119
120protected:
121
122 Q_UINT64 mMinSize;
123 Q_UINT64 mMaxSize;
124};
125#endif
126
127static inline int log2i (Q_UINT64 val)
128{
129 Q_UINT64 n = val;
130 int pow = -1;
131 while (n)
132 {
133 ++ pow;
134 n >>= 1;
135 }
136 return pow;
137}
138
139static inline int sizeMBToSlider (Q_UINT64 val, int sliderScale)
140{
141 int pow = log2i (val);
142 Q_UINT64 tickMB = Q_UINT64 (1) << pow;
143 Q_UINT64 tickMBNext = Q_UINT64 (1) << (pow + 1);
144 int step = (val - tickMB) * sliderScale / (tickMBNext - tickMB);
145 return pow * sliderScale + step;
146}
147
148static inline Q_UINT64 sliderToSizeMB (int val, int sliderScale)
149{
150 int pow = val / sliderScale;
151 int step = val % sliderScale;
152 Q_UINT64 tickMB = Q_UINT64 (1) << pow;
153 Q_UINT64 tickMBNext = Q_UINT64 (1) << (pow + 1);
154 return tickMB + (tickMBNext - tickMB) * step / sliderScale;
155}
156
157void VBoxNewHDWzd::init()
158{
159 /* disable help buttons */
160 helpButton()->setShown (false);
161
162 /* fix tab order to get the proper direction
163 * (originally the focus goes Next/Finish -> Back -> Cancel -> page) */
164 QWidget::setTabOrder (backButton(), nextButton());
165 QWidget::setTabOrder (nextButton(), finishButton());
166 QWidget::setTabOrder (finishButton(), cancelButton());
167
168 /* setup connections and set validation for pages
169 * ---------------------------------------------------------------------- */
170
171 /* setup the label clolors for nice scaling */
172 VBoxGlobal::adoptLabelPixmap (pmWelcome);
173 VBoxGlobal::adoptLabelPixmap (pmType);
174 VBoxGlobal::adoptLabelPixmap (pmNameAndSize);
175 VBoxGlobal::adoptLabelPixmap (pmSummary);
176
177 /* Image type page */
178
179 /* Name and Size page */
180
181 CSystemProperties sysProps = vboxGlobal().virtualBox().GetSystemProperties();
182
183 maxVDISize = sysProps.GetMaxVDISize();
184
185 /* Detect how many steps to recognize between adjacent powers of 2
186 * to ensure that the last slider step is exactly maxVDISize */
187 sliderScale = 0;
188 {
189 int pow = log2i (maxVDISize);
190 Q_UINT64 tickMB = Q_UINT64 (1) << pow;
191 if (tickMB < maxVDISize)
192 {
193 Q_UINT64 tickMBNext = Q_UINT64 (1) << (pow + 1);
194 Q_UINT64 gap = tickMBNext - maxVDISize;
195 /// @todo (r=dmik) overflow may happen if maxVDISize is TOO big
196 sliderScale = (int) ((tickMBNext - tickMB) / gap);
197 }
198 }
199 sliderScale = QMAX (sliderScale, 8);
200
201 leName->setValidator (new QRegExpValidator (QRegExp( ".+" ), this));
202
203 leSize->setValidator (new QRegExpValidator (vboxGlobal().sizeRegexp(), this));
204 leSize->setAlignment (Qt::AlignRight);
205
206 wvalNameAndSize = new QIWidgetValidator (pageNameAndSize, this);
207 connect (wvalNameAndSize, SIGNAL (validityChanged (const QIWidgetValidator *)),
208 this, SLOT (enableNext (const QIWidgetValidator *)));
209 connect (wvalNameAndSize, SIGNAL (isValidRequested (QIWidgetValidator *)),
210 this, SLOT (revalidate (QIWidgetValidator *)));
211 /* we ask revalidate only when currentSize is changed after manually
212 * editing the line edit field; the slider cannot produce invalid values */
213 connect (leSize, SIGNAL (textChanged (const QString &)),
214 wvalNameAndSize, SLOT (revalidate()));
215
216 /* Summary page */
217
218 teSummary = new QITextEdit (pageSummary);
219 teSummary->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
220 teSummary->setFrameShape (QTextEdit::NoFrame);
221 teSummary->setReadOnly (TRUE);
222 summaryLayout->insertWidget (1, teSummary);
223
224 /* filter out Enter keys in order to direct them to the default dlg button */
225 QIKeyFilter *ef = new QIKeyFilter (this, Key_Enter);
226 ef->watchOn (teSummary);
227
228 /* set initial values
229 * ---------------------------------------------------------------------- */
230
231 /* Image type page */
232
233 /* Name and Size page */
234
235 static ulong HDNumber = 0;
236 leName->setText (QString ("NewHardDisk%1.vdi").arg (++ HDNumber));
237
238 slSize->setFocusPolicy (QWidget::StrongFocus);
239 slSize->setPageStep (sliderScale);
240 slSize->setLineStep (sliderScale / 8);
241 slSize->setTickInterval (0);
242 slSize->setMinValue (sizeMBToSlider (MinVDISize, sliderScale));
243 slSize->setMaxValue (sizeMBToSlider (maxVDISize, sliderScale));
244
245 txSizeMin->setText (vboxGlobal().formatSize (MinVDISize * _1M));
246 txSizeMax->setText (vboxGlobal().formatSize (maxVDISize * _1M));
247
248 /* limit the max. size of QLineEdit (STUPID Qt has NO correct means for that) */
249 leSize->setMaximumSize (
250 leSize->fontMetrics().width ("88888.88 MB") + leSize->frameWidth() * 2,
251 leSize->height());
252
253 setRecommendedSize (InitialVDISize);
254
255 /* Summary page */
256
257 teSummary->setPaper (pageSummary->backgroundBrush());
258
259 /* update the next button state for pages with validation
260 * (validityChanged() connected to enableNext() will do the job) */
261 wvalNameAndSize->revalidate();
262
263 /* the finish button on the Summary page is always enabled */
264 setFinishEnabled (pageSummary, true);
265
266 /* setup minimum width for the sizeHint to be calculated correctly */
267 int wid = widthSpacer->minimumSize().width();
268 txWelcome->setMinimumWidth (wid);
269 textLabel1_2->setMinimumWidth (wid);
270 txNameComment->setMinimumWidth (wid);
271 txSizeComment->setMinimumWidth (wid);
272 txSummaryHdr->setMinimumWidth (wid);
273 txSummaryFtr->setMinimumWidth (wid);
274}
275
276
277void VBoxNewHDWzd::showEvent (QShowEvent *e)
278{
279 QDialog::showEvent (e);
280
281 /* one may think that QWidget::polish() is the right place to do things
282 * below, but apparently, by the time when QWidget::polish() is called,
283 * the widget style & layout are not fully done, at least the minimum
284 * size hint is not properly calculated. Since this is sometimes necessary,
285 * we provide our own "polish" implementation. */
286
287 layout()->activate();
288
289 /* resize to the miminum possible size */
290 resize (minimumSize());
291
292 VBoxGlobal::centerWidget (this, parentWidget());
293}
294
295
296void VBoxNewHDWzd::setRecommendedFileName (const QString &aName)
297{
298 leName->setText (aName);
299}
300
301
302void VBoxNewHDWzd::setRecommendedSize (Q_UINT64 aSize)
303{
304 AssertReturnVoid (aSize >= MinVDISize && aSize <= maxVDISize);
305 currentSize = aSize;
306 slSize->setValue (sizeMBToSlider (currentSize, sliderScale));
307 leSize->setText (vboxGlobal().formatSize (currentSize * _1M));
308 updateSizeToolTip (currentSize * _1M);
309}
310
311
312QString VBoxNewHDWzd::imageFileName()
313{
314 QString name = QDir::convertSeparators (leName->text());
315
316 /* remove all trailing dots to avoid multiple dots before .vdi */
317 int len;
318 while (len = name.length(), len > 0 && name [len - 1] == '.')
319 name.truncate (len - 1);
320
321 QString ext = QFileInfo (name).extension();
322 /* compare against the proper case */
323#if defined (Q_OS_LINUX)
324#elif defined (Q_OS_WIN) || defined (Q_OS_OS2) || defined (Q_OS_MACX)
325 ext = ext.lower();
326#else
327 #error Port me!
328#endif
329
330 if (ext != "vdi")
331 name += ".vdi";
332
333 return name;
334}
335
336
337Q_UINT64 VBoxNewHDWzd::imageSize()
338{
339 return currentSize;
340}
341
342
343bool VBoxNewHDWzd::isDynamicImage()
344{
345 return rbDynamicType->isOn();
346}
347
348
349void VBoxNewHDWzd::enableNext (const QIWidgetValidator *wval)
350{
351 setNextEnabled (wval->widget(), wval->isValid());
352}
353
354
355void VBoxNewHDWzd::revalidate (QIWidgetValidator *wval)
356{
357 /* do individual validations for pages */
358
359 QWidget *pg = wval->widget();
360 bool valid = wval->isOtherValid();
361
362 if (pg == pageNameAndSize)
363 {
364 valid = currentSize >= MinVDISize && currentSize <= maxVDISize;
365 }
366
367 wval->setOtherValid (valid);
368}
369
370
371void VBoxNewHDWzd::updateSizeToolTip (Q_UINT64 sizeB)
372{
373 QString tip = tr ("<nobr>%1 Bytes</nobr>").arg (sizeB);
374 QToolTip::add (slSize, tip);
375 QToolTip::add (leSize, tip);
376}
377
378void VBoxNewHDWzd::showPage( QWidget *page )
379{
380 if (currentPage() == pageNameAndSize)
381 {
382 if (QFileInfo (imageFileName()).exists())
383 {
384 vboxProblem().sayCannotOverwriteHardDiskImage (this, imageFileName());
385 return;
386 }
387 }
388
389 if (page == pageSummary)
390 {
391 QString type = rbDynamicType->isOn() ? rbDynamicType->text()
392 : rbFixedType->text();
393 type.remove ('&');
394
395 Q_UINT64 sizeB = imageSize() * _1M;
396
397 // compose summary
398 QString summary = QString (tr(
399 "<table>"
400 "<tr><td>Type:</td><td>%1</td></tr>"
401 "<tr><td>Location:</td><td>%2</td></tr>"
402 "<tr><td>Size:</td><td>%3&nbsp;(%4&nbsp;Bytes)</td></tr>"
403 "</table>"
404 ))
405 .arg (type)
406 .arg (composeFullFileName (imageFileName()))
407 .arg (VBoxGlobal::formatSize (sizeB))
408 .arg (sizeB);
409 teSummary->setText (summary);
410 /* set Finish to default */
411 finishButton()->setDefault (true);
412 }
413 else
414 {
415 /* always set Next to default */
416 nextButton()->setDefault (true);
417 }
418
419 QWizard::showPage (page);
420
421 /* fix focus on the last page. when we go to the last page
422 * having the Next in focus the focus goes to the Cancel
423 * button because when the Next hides Finish is not yet shown. */
424 if (page == pageSummary && focusWidget() == cancelButton())
425 finishButton()->setFocus();
426
427 /* setup focus for individual pages */
428 if (page == pageType)
429 {
430 bgType->setFocus();
431 }
432 else if (page == pageNameAndSize)
433 {
434 leName->setFocus();
435 }
436 else if (page == pageSummary)
437 {
438 teSummary->setFocus();
439 }
440
441 page->layout()->activate();
442}
443
444
445void VBoxNewHDWzd::accept()
446{
447 /*
448 * Try to create the hard disk when the Finish button is pressed.
449 * On failure, the wisard will remain open to give it another try.
450 */
451 if (createHardDisk())
452 QWizard::accept();
453}
454
455/**
456 * Performs steps necessary to create a hard disk. This method handles all
457 * errors and shows the corresponding messages when appropriate.
458 *
459 * @return wheter the creation was successful or not
460 */
461bool VBoxNewHDWzd::createHardDisk()
462{
463 QString src = imageFileName();
464 Q_UINT64 size = imageSize();
465
466 AssertReturn (!src.isEmpty(), false);
467 AssertReturn (size > 0, false);
468
469 CVirtualBox vbox = vboxGlobal().virtualBox();
470
471 CProgress progress;
472 CHardDisk hd = vbox.CreateHardDisk (CEnums::VirtualDiskImage);
473
474 /// @todo (dmik) later, change wrappers so that converting
475 // to CUnknown is not necessary for cross-assignments
476 CVirtualDiskImage vdi = CUnknown (hd);
477
478 if (!vbox.isOk())
479 {
480 vboxProblem().cannotCreateHardDiskImage (this,
481 vbox, src, vdi, progress);
482 return false;
483 }
484
485 vdi.SetFilePath (src);
486
487 if (isDynamicImage())
488 progress = vdi.CreateDynamicImage (size);
489 else
490 progress = vdi.CreateFixedImage (size);
491
492 if (!vdi.isOk())
493 {
494 vboxProblem().cannotCreateHardDiskImage (this,
495 vbox, src, vdi, progress);
496 return false;
497 }
498
499 vboxProblem().showModalProgressDialog (progress, caption(), parentWidget());
500
501 if (progress.GetResultCode() != 0)
502 {
503 vboxProblem().cannotCreateHardDiskImage (this,
504 vbox, src, vdi, progress);
505 return false;
506 }
507
508 vbox.RegisterHardDisk (hd);
509 if (!vbox.isOk())
510 {
511 vboxProblem().cannotRegisterMedia (this, vbox, VBoxDefs::HD,
512 vdi.GetFilePath());
513 /* delete the image file on failure */
514 vdi.DeleteImage();
515 return false;
516 }
517
518 chd = hd;
519 return true;
520}
521
522
523void VBoxNewHDWzd::slSize_valueChanged( int val )
524{
525 if (focusWidget() == slSize)
526 {
527 currentSize = sliderToSizeMB (val, sliderScale);
528 leSize->setText (vboxGlobal().formatSize (currentSize * _1M));
529 updateSizeToolTip (currentSize * _1M);
530 }
531}
532
533
534void VBoxNewHDWzd::leSize_textChanged( const QString &text )
535{
536 if (focusWidget() == leSize)
537 {
538 currentSize = vboxGlobal().parseSize (text);
539 updateSizeToolTip (currentSize);
540 currentSize /= _1M;
541 slSize->setValue (sizeMBToSlider (currentSize, sliderScale));
542 }
543}
544
545
546void VBoxNewHDWzd::tbNameSelect_clicked()
547{
548 /* set the first parent directory that exists as the current */
549 QFileInfo fld (composeFullFileName (leName->text()));
550 do
551 {
552 QString dp = fld.dirPath (false);
553 fld = QFileInfo (dp);
554 }
555 while (!fld.exists() && !QDir (fld.absFilePath()).isRoot());
556
557 if (!fld.exists())
558 {
559 CVirtualBox vbox = vboxGlobal().virtualBox();
560 fld = QFileInfo (vbox.GetSystemProperties().GetDefaultVDIFolder());
561 if (!fld.exists())
562 fld = vbox.GetHomeFolder();
563 }
564
565// QFileDialog fd (this, "NewDiskImageDialog", TRUE);
566// fd.setMode (QFileDialog::AnyFile);
567// fd.setViewMode (QFileDialog::List);
568// fd.addFilter (tr( "Hard disk images (*.vdi)" ));
569// fd.setCaption (tr( "Select a file for the new hard disk image file" ));
570// fd.setDir (d);
571
572 QString selected = QFileDialog::getSaveFileName (
573 fld.absFilePath(),
574 tr ("Hard disk images (*.vdi)"),
575 this,
576 "NewDiskImageDialog",
577 tr ("Select a file for the new hard disk image file"));
578
579// if ( fd.exec() == QDialog::Accepted ) {
580// leName->setText (QDir::convertSeparators (fd.selectedFile()));
581 if (selected)
582 {
583 if (QFileInfo (selected).extension().isEmpty())
584 selected += ".vdi";
585 leName->setText (QDir::convertSeparators (selected));
586 leName->selectAll();
587 leName->setFocus();
588 }
589}
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