~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/wizards/newhd/VBoxNewHDWzd.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 *
 
3
 * VBox frontends: Qt4 GUI ("VirtualBox"):
 
4
 * VBoxNewHDWzd class implementation
 
5
 */
 
6
 
 
7
/*
 
8
 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
 
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 (GPL) as published by the Free Software
 
14
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
15
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
16
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
17
 *
 
18
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 
19
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 
20
 * additional information or have any questions.
 
21
 */
 
22
 
 
23
#include "VBoxNewHDWzd.h"
 
24
#include "VBoxGlobal.h"
 
25
#include "VBoxProblemReporter.h"
 
26
#include "iprt/path.h"
 
27
 
 
28
/* Qt includes */
 
29
#include <QFileDialog>
 
30
#include <QToolTip>
 
31
 
 
32
/** Minimum VDI size in MB */
 
33
static const quint64 MinVDISize = 4;
 
34
 
 
35
/** Initial VDI size in MB */
 
36
static const quint64 InitialVDISize = 2 * _1K;
 
37
 
 
38
/**
 
39
 * Composes a file name from the given relative or full file name based on the
 
40
 * home directory and the default VDI directory. See IMedum::location for
 
41
 * details.
 
42
 */
 
43
static QString composeFullFileName (const QString &aName)
 
44
{
 
45
    CVirtualBox vbox = vboxGlobal().virtualBox();
 
46
    QString homeFolder = vbox.GetHomeFolder();
 
47
    QString defaultFolder = vbox.GetSystemProperties().GetDefaultHardDiskFolder();
 
48
 
 
49
    /* Note: the logic below must match the logic of the IMedum::location
 
50
     * setter, otherwise the returned path may differ from the path actually
 
51
     * set for the hard disk by the VirtualBox API */
 
52
 
 
53
    QFileInfo fi (aName);
 
54
    if (fi.fileName() == aName)
 
55
    {
 
56
        /* no path info at all, use defaultFolder */
 
57
        fi = QFileInfo (defaultFolder, aName);
 
58
    }
 
59
    else if (fi.isRelative())
 
60
    {
 
61
        /* resolve relatively to homeFolder */
 
62
        fi = QFileInfo (homeFolder, aName);
 
63
    }
 
64
 
 
65
    return QDir::toNativeSeparators (fi.absoluteFilePath());
 
66
}
 
67
 
 
68
static inline int log2i (quint64 val)
 
69
{
 
70
    quint64 n = val;
 
71
    int pow = -1;
 
72
    while (n)
 
73
    {
 
74
        ++ pow;
 
75
        n >>= 1;
 
76
    }
 
77
    return pow;
 
78
}
 
79
 
 
80
static inline int sizeMBToSlider (quint64 val, int aSliderScale)
 
81
{
 
82
    int pow = log2i (val);
 
83
    quint64 tickMB = quint64 (1) << pow;
 
84
    quint64 tickMBNext = quint64 (1) << (pow + 1);
 
85
    int step = (val - tickMB) * aSliderScale / (tickMBNext - tickMB);
 
86
    return pow * aSliderScale + step;
 
87
}
 
88
 
 
89
static inline quint64 sliderToSizeMB (int val, int aSliderScale)
 
90
{
 
91
    int pow = val / aSliderScale;
 
92
    int step = val % aSliderScale;
 
93
    quint64 tickMB = quint64 (1) << pow;
 
94
    quint64 tickMBNext = quint64 (1) << (pow + 1);
 
95
    return tickMB + (tickMBNext - tickMB) * step / aSliderScale;
 
96
}
 
97
 
 
98
 
 
99
////////////////////////////////////////////////////////////////////////////////
 
100
 
 
101
 
 
102
VBoxNewHDWzd::VBoxNewHDWzd (QWidget *aParent)
 
103
    : QIWithRetranslateUI<QIAbstractWizard> (aParent)
 
104
{
 
105
    /* Apply UI decorations */
 
106
    Ui::VBoxNewHDWzd::setupUi (this);
 
107
 
 
108
    /* Initialize wizard hdr */
 
109
    initializeWizardHdr();
 
110
 
 
111
    /* Storage type page */
 
112
 
 
113
    /* Name and Size page */
 
114
    CSystemProperties sysProps = vboxGlobal().virtualBox().GetSystemProperties();
 
115
    mMaxVDISize = sysProps.GetMaxVDISize();
 
116
    /* Detect how many steps to recognize between adjacent powers of 2
 
117
     * to ensure that the last slider step is exactly mMaxVDISize */
 
118
    mSliderScale = 0;
 
119
    {
 
120
        int pow = log2i (mMaxVDISize);
 
121
        quint64 tickMB = quint64 (1) << pow;
 
122
        if (tickMB < mMaxVDISize)
 
123
        {
 
124
            quint64 tickMBNext = quint64 (1) << (pow + 1);
 
125
            quint64 gap = tickMBNext - mMaxVDISize;
 
126
            mSliderScale = (int) ((tickMBNext - tickMB) / gap);
 
127
        }
 
128
    }
 
129
    mSliderScale = qMax (mSliderScale, 8);
 
130
    mLeName->setValidator (new QRegExpValidator (QRegExp (".+"), this));
 
131
    mLeSize->setValidator (new QRegExpValidator (QRegExp (vboxGlobal().sizeRegexp()), this));
 
132
    mLeSize->setAlignment (Qt::AlignRight);
 
133
    mWValNameAndSize = new QIWidgetValidator (mPageNameAndSize, this);
 
134
    connect (mWValNameAndSize, SIGNAL (validityChanged (const QIWidgetValidator *)),
 
135
             this, SLOT (enableNext (const QIWidgetValidator *)));
 
136
    connect (mWValNameAndSize, SIGNAL (isValidRequested (QIWidgetValidator *)),
 
137
             this, SLOT (revalidate (QIWidgetValidator *)));
 
138
    connect (mLeSize, SIGNAL (textChanged (const QString &)),
 
139
             mWValNameAndSize, SLOT (revalidate()));
 
140
    connect (mTbNameSelect, SIGNAL (clicked()), this, SLOT (tbNameSelectClicked()));
 
141
    connect (mSlSize, SIGNAL (valueChanged (int)), this, SLOT (slSizeValueChanged (int)));
 
142
    connect (mLeSize, SIGNAL (textChanged (const QString&)),
 
143
             this, SLOT (leSizeTextChanged (const QString&)));
 
144
 
 
145
    /* Summary page */
 
146
 
 
147
    /* Image type page */
 
148
 
 
149
    /* Name and Size page */
 
150
    /// @todo NEWMEDIA use extension as reported by CMediumFormat
 
151
    static ulong HDNumber = 0;
 
152
    mLeName->setText (QString ("NewHardDisk%1.vdi").arg (++ HDNumber));
 
153
    mSlSize->setFocusPolicy (Qt::StrongFocus);
 
154
    mSlSize->setPageStep (mSliderScale);
 
155
    mSlSize->setSingleStep (mSliderScale / 8);
 
156
    mSlSize->setTickInterval (0);
 
157
    mSlSize->setMinimum (sizeMBToSlider (MinVDISize, mSliderScale));
 
158
    mSlSize->setMaximum (sizeMBToSlider (mMaxVDISize, mSliderScale));
 
159
    mTxSizeMin->setText (vboxGlobal().formatSize (MinVDISize * _1M));
 
160
    mTxSizeMax->setText (vboxGlobal().formatSize (mMaxVDISize * _1M));
 
161
    /* limit the max. size of QILineEdit */
 
162
    mLeSize->setFixedWidthByText ("88888.88 MB");
 
163
    setRecommendedSize (InitialVDISize);
 
164
 
 
165
    /* Summary page */
 
166
    /* Update the next button state for pages with validation
 
167
     * (validityChanged() connected to enableNext() will do the job) */
 
168
    mWValNameAndSize->revalidate();
 
169
 
 
170
    /* Initialize wizard ftr */
 
171
    initializeWizardFtr();
 
172
 
 
173
    retranslateUi();
 
174
}
 
175
 
 
176
void VBoxNewHDWzd::setRecommendedFileName (const QString &aName)
 
177
{
 
178
    mLeName->setText (aName);
 
179
}
 
180
 
 
181
void VBoxNewHDWzd::setRecommendedSize (quint64 aSize)
 
182
{
 
183
    AssertReturnVoid (aSize >= MinVDISize && aSize <= mMaxVDISize);
 
184
    mCurrentSize = aSize;
 
185
    mSlSize->setValue (sizeMBToSlider (mCurrentSize, mSliderScale));
 
186
    mLeSize->setText (vboxGlobal().formatSize (mCurrentSize * _1M));
 
187
    updateSizeToolTip (mCurrentSize * _1M);
 
188
}
 
189
 
 
190
void VBoxNewHDWzd::retranslateUi()
 
191
{
 
192
   /* Translate uic generated strings */
 
193
    Ui::VBoxNewHDWzd::retranslateUi (this);
 
194
 
 
195
    QWidget *page = mPageStack->currentWidget();
 
196
 
 
197
    if (page == mPageSummary)
 
198
    {
 
199
        QString type = mRbDynamicType->isChecked() ? mRbDynamicType->text()
 
200
                                                   : mRbFixedType->text();
 
201
        type = VBoxGlobal::removeAccelMark (type);
 
202
 
 
203
        quint64 sizeB = mCurrentSize * _1M;
 
204
 
 
205
        /* compose summary */
 
206
        QString summary = QString (
 
207
            "<table>"
 
208
            "<tr><td><nobr>%1:&nbsp;</nobr></td><td><nobr>%2</nobr></td></tr>"
 
209
            "<tr><td><nobr>%3:&nbsp;</nobr></td><td><nobr>%4</nobr></td></tr>"
 
210
            "<tr><td><nobr>%5:&nbsp;</nobr></td><td><nobr>%6&nbsp;(%7&nbsp;%8)</nobr></td></tr>"
 
211
            "</table>"
 
212
        )
 
213
            .arg (tr ("Type", "summary")).arg (type)
 
214
            .arg (tr ("Location", "summary")).arg (composeFullFileName (location()))
 
215
            .arg (tr ("Size", "summary")).arg (VBoxGlobal::formatSize (sizeB))
 
216
            .arg (sizeB).arg (tr ("Bytes", "summary"));
 
217
 
 
218
        mTeSummary->setText (summary);
 
219
    }
 
220
}
 
221
 
 
222
void VBoxNewHDWzd::accept()
 
223
{
 
224
    /* Try to create the hard disk when the Finish button is pressed.
 
225
     * On failure, the wisard will remain open to give it another try. */
 
226
    if (createHardDisk())
 
227
        QIAbstractWizard::accept();
 
228
}
 
229
 
 
230
void VBoxNewHDWzd::slSizeValueChanged (int aVal)
 
231
{
 
232
    if (focusWidget() == mSlSize)
 
233
    {
 
234
        mCurrentSize = sliderToSizeMB (aVal, mSliderScale);
 
235
        mLeSize->setText (vboxGlobal().formatSize (mCurrentSize * _1M));
 
236
        updateSizeToolTip (mCurrentSize * _1M);
 
237
    }
 
238
}
 
239
 
 
240
void VBoxNewHDWzd::leSizeTextChanged (const QString &aText)
 
241
{
 
242
    if (focusWidget() == mLeSize)
 
243
    {
 
244
        mCurrentSize = vboxGlobal().parseSize (aText);
 
245
        updateSizeToolTip (mCurrentSize);
 
246
        mCurrentSize /= _1M;
 
247
        mSlSize->setValue (sizeMBToSlider (mCurrentSize, mSliderScale));
 
248
    }
 
249
}
 
250
 
 
251
void VBoxNewHDWzd::tbNameSelectClicked()
 
252
{
 
253
    /* set the first parent directory that exists as the current */
 
254
    QFileInfo fld (composeFullFileName (mLeName->text()));
 
255
    do
 
256
    {
 
257
        QString dp = fld.path ();
 
258
        fld = QFileInfo (dp);
 
259
    }
 
260
    while (!fld.exists() && !QDir (fld.absoluteFilePath()).isRoot());
 
261
 
 
262
    if (!fld.exists())
 
263
    {
 
264
        CVirtualBox vbox = vboxGlobal().virtualBox();
 
265
        fld = QFileInfo (vbox.GetSystemProperties().GetDefaultHardDiskFolder());
 
266
        if (!fld.exists())
 
267
            fld = vbox.GetHomeFolder();
 
268
    }
 
269
 
 
270
    QString selected = QFileDialog::getSaveFileName (
 
271
        this,
 
272
        tr ("Select a file for the new hard disk image file"),
 
273
        fld.absoluteFilePath(),
 
274
        tr ("Hard disk images (*.vdi)"));
 
275
 
 
276
    if (!selected.isEmpty())
 
277
    {
 
278
        if (QFileInfo (selected).completeSuffix().isEmpty())
 
279
            selected += ".vdi";
 
280
        mLeName->setText (QDir::toNativeSeparators (selected));
 
281
        mLeName->selectAll();
 
282
        mLeName->setFocus();
 
283
    }
 
284
}
 
285
 
 
286
void VBoxNewHDWzd::revalidate (QIWidgetValidator *aWval)
 
287
{
 
288
    /* do individual validations for pages */
 
289
    bool valid = aWval->isOtherValid();
 
290
 
 
291
    if (aWval == mWValNameAndSize)
 
292
        valid = mCurrentSize >= MinVDISize && mCurrentSize <= mMaxVDISize;
 
293
 
 
294
    aWval->setOtherValid (valid);
 
295
}
 
296
 
 
297
void VBoxNewHDWzd::enableNext (const QIWidgetValidator *aWval)
 
298
{
 
299
    nextButton (aWval->widget())->setEnabled (aWval->isValid());
 
300
}
 
301
 
 
302
void VBoxNewHDWzd::onPageShow()
 
303
{
 
304
    /* Make sure all is properly translated & composed */
 
305
    retranslateUi();
 
306
 
 
307
    QWidget *page = mPageStack->currentWidget();
 
308
 
 
309
    if (page == mPageWelcome)
 
310
        nextButton (page)->setFocus();
 
311
    else if (page == mPageType)
 
312
        mRbDynamicType->isChecked() ? mRbDynamicType->setFocus() :
 
313
                                      mRbFixedType->setFocus();
 
314
    else if (page == mPageNameAndSize)
 
315
        mLeName->setFocus();
 
316
    else if (page == mPageSummary)
 
317
        mTeSummary->setFocus();
 
318
 
 
319
    if (page == mPageSummary)
 
320
        finishButton()->setDefault (true);
 
321
    else
 
322
        nextButton (page)->setDefault (true);
 
323
}
 
324
 
 
325
void VBoxNewHDWzd::showNextPage()
 
326
{
 
327
    /* Warn user about already present hard-disk */
 
328
    if (sender() == mBtnNext3 &&
 
329
        QFileInfo (location()).exists())
 
330
    {
 
331
        vboxProblem().sayCannotOverwriteHardDiskStorage (this, location());
 
332
        return;
 
333
    }
 
334
 
 
335
    /* Switch to the next page */
 
336
    QIAbstractWizard::showNextPage();
 
337
}
 
338
 
 
339
 
 
340
QString VBoxNewHDWzd::location()
 
341
{
 
342
    QString name = QDir::toNativeSeparators (mLeName->text());
 
343
 
 
344
    /* remove all trailing dots to avoid multiple dots before .vdi */
 
345
    int len;
 
346
    while (len = name.length(), len > 0 && name [len - 1] == '.')
 
347
        name.truncate (len - 1);
 
348
 
 
349
    QString ext = QFileInfo (name).completeSuffix();
 
350
 
 
351
    if (RTPathCompare (ext.toUtf8(), "vdi") != 0)
 
352
        name += ".vdi";
 
353
 
 
354
    return name;
 
355
}
 
356
 
 
357
bool VBoxNewHDWzd::isDynamicStorage()
 
358
{
 
359
    return mRbDynamicType->isChecked();
 
360
}
 
361
 
 
362
void VBoxNewHDWzd::updateSizeToolTip (quint64 aSizeB)
 
363
{
 
364
    QString tip = tr ("<nobr>%1 Bytes</nobr>").arg (aSizeB);
 
365
    mSlSize->setToolTip (tip);
 
366
    mLeSize->setToolTip (tip);
 
367
}
 
368
 
 
369
/**
 
370
 * Performs steps necessary to create a hard disk. This method handles all
 
371
 * errors and shows the corresponding messages when appropriate.
 
372
 *
 
373
 * @return Wheter the creation was successful or not.
 
374
 */
 
375
bool VBoxNewHDWzd::createHardDisk()
 
376
{
 
377
    KMediumVariant variant = KMediumVariant_Standard;
 
378
    QString loc = location();
 
379
 
 
380
    AssertReturn (!loc.isEmpty(), false);
 
381
    AssertReturn (mCurrentSize > 0, false);
 
382
 
 
383
    CVirtualBox vbox = vboxGlobal().virtualBox();
 
384
 
 
385
    CProgress progress;
 
386
 
 
387
    CMedium hd = vbox.CreateHardDisk(QString ("VDI"), loc);
 
388
 
 
389
    if (!vbox.isOk())
 
390
    {
 
391
        vboxProblem().cannotCreateHardDiskStorage (this, vbox, loc, hd,
 
392
                                                   progress);
 
393
        return false;
 
394
    }
 
395
 
 
396
    if (!isDynamicStorage())
 
397
        variant = (KMediumVariant)(KMediumVariant_Standard | KMediumVariant_Fixed);
 
398
 
 
399
    progress = hd.CreateBaseStorage (mCurrentSize, variant);
 
400
 
 
401
    if (!hd.isOk())
 
402
    {
 
403
        vboxProblem().cannotCreateHardDiskStorage (this, vbox, loc, hd,
 
404
                                                   progress);
 
405
        return false;
 
406
    }
 
407
 
 
408
    vboxProblem().showModalProgressDialog (progress, windowTitle(), parentWidget());
 
409
 
 
410
    if (progress.GetCanceled())
 
411
        return false;
 
412
 
 
413
    if (!progress.isOk() || progress.GetResultCode() != 0)
 
414
    {
 
415
        vboxProblem().cannotCreateHardDiskStorage (this, vbox, loc, hd,
 
416
                                                   progress);
 
417
        return false;
 
418
    }
 
419
 
 
420
    /* Inform everybody there is a new medium */
 
421
    vboxGlobal().addMedium (VBoxMedium (CMedium (hd),
 
422
                                        VBoxDefs::MediumType_HardDisk,
 
423
                                        KMediumState_Created));
 
424
 
 
425
    mHD = hd;
 
426
    return true;
 
427
}
 
428