~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsHD.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
 
 * VBoxVMSettingsHD 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
 
 
24
 
#include "VBoxVMSettingsHD.h"
25
 
#include "VBoxGlobal.h"
26
 
#include "VBoxProblemReporter.h"
27
 
#include "QIWidgetValidator.h"
28
 
#include "VBoxToolBar.h"
29
 
#include "VBoxMediaManagerDlg.h"
30
 
#include "VBoxNewHDWzd.h"
31
 
 
32
 
/* Qt includes */
33
 
#include <QHeaderView>
34
 
#include <QItemEditorFactory>
35
 
#include <QMetaProperty>
36
 
#include <QScrollBar>
37
 
#include <QStylePainter>
38
 
 
39
 
/**
40
 
 * Clear the focus from the current focus owner on guard creation.
41
 
 * And put it into the desired object on guard deletion.
42
 
 *
43
 
 * Here this is used to temporary remove the focus from the attachments
44
 
 * table to close the temporary editor of this table to prevent
45
 
 * any side-process (enumeration) influencing model's data.
46
 
 */
47
 
class FocusGuardBlock
48
 
{
49
 
public:
50
 
    FocusGuardBlock (QWidget *aReturnTo) : mReturnTo (aReturnTo)
51
 
    {
52
 
        if (QApplication::focusWidget())
53
 
        {
54
 
            QApplication::focusWidget()->clearFocus();
55
 
            qApp->processEvents();
56
 
        }
57
 
    }
58
 
   ~FocusGuardBlock()
59
 
    {
60
 
        mReturnTo->setFocus();
61
 
        qApp->processEvents();
62
 
    }
63
 
 
64
 
private:
65
 
    QWidget *mReturnTo;
66
 
};
67
 
 
68
 
/** Type to store disk data */
69
 
DiskValue::DiskValue (const QString &aId)
70
 
    : id (aId)
71
 
    , name (QString::null), tip (QString::null), pix (QPixmap())
72
 
{
73
 
    if (aId.isNull())
74
 
        return;
75
 
 
76
 
    VBoxMedium medium = vboxGlobal().getMedium (
77
 
        CMedium (vboxGlobal().virtualBox().GetHardDisk(aId)));
78
 
    medium.refresh();
79
 
    bool noDiffs = !HDSettings::instance()->showDiffs();
80
 
    name = medium.details (noDiffs);
81
 
    tip = medium.toolTipCheckRO (noDiffs);
82
 
    pix = medium.iconCheckRO (noDiffs);
83
 
}
84
 
 
85
 
/**
86
 
 * QAbstractTableModel class reimplementation.
87
 
 * Used to feat slot/disk selection mechanism.
88
 
 */
89
 
Qt::ItemFlags AttachmentsModel::flags (const QModelIndex &aIndex) const
90
 
{
91
 
    return aIndex.row() == rowCount() - 1 ?
92
 
        QAbstractItemModel::flags (aIndex) ^ Qt::ItemIsSelectable :
93
 
        QAbstractItemModel::flags (aIndex) | Qt::ItemIsEditable;
94
 
}
95
 
 
96
 
QVariant AttachmentsModel::data (const QModelIndex &aIndex, int aRole) const
97
 
{
98
 
    if (!aIndex.isValid())
99
 
        return QVariant();
100
 
 
101
 
    if (aIndex.row() < 0 || aIndex.row() >= rowCount())
102
 
        return QVariant();
103
 
 
104
 
    switch (aRole)
105
 
    {
106
 
        case Qt::DisplayRole:
107
 
        {
108
 
            if (aIndex.row() == rowCount() - 1)
109
 
                return QVariant();
110
 
            else if (aIndex.column() == 0)
111
 
                return QVariant (mUsedSlotsList [aIndex.row()].name);
112
 
            else if (aIndex.column() == 1)
113
 
                return QVariant (mUsedDisksList [aIndex.row()].name);
114
 
 
115
 
            Assert (0);
116
 
            return QVariant();
117
 
        }
118
 
        case Qt::DecorationRole:
119
 
        {
120
 
            return aIndex.row() != rowCount() - 1 &&
121
 
                   aIndex.column() == 1 &&
122
 
                   (aIndex != mParent->currentIndex() ||
123
 
                    !DiskEditor::activeEditor())
124
 
                   ? QVariant (mUsedDisksList [aIndex.row()].pix) : QVariant();
125
 
        }
126
 
        case Qt::EditRole:
127
 
        {
128
 
            if (aIndex.column() == 0)
129
 
                return QVariant (mSlotId, &mUsedSlotsList [aIndex.row()]);
130
 
            else if (aIndex.column() == 1)
131
 
                return QVariant (mDiskId, &mUsedDisksList [aIndex.row()]);
132
 
 
133
 
            Assert (0);
134
 
            return QVariant();
135
 
        }
136
 
        case Qt::ToolTipRole:
137
 
        {
138
 
            if (aIndex.row() == rowCount() - 1)
139
 
                return QVariant (tr ("Double-click to add a new attachment"));
140
 
 
141
 
            return QVariant (mUsedDisksList [aIndex.row()].tip);
142
 
        }
143
 
        default:
144
 
        {
145
 
            return QVariant();
146
 
        }
147
 
    }
148
 
}
149
 
 
150
 
bool AttachmentsModel::setData (const QModelIndex &aIndex,
151
 
                                const QVariant &aValue,
152
 
                                int /* aRole = Qt::EditRole */)
153
 
{
154
 
    if (!aIndex.isValid())
155
 
        return false;
156
 
 
157
 
    if (aIndex.row() < 0 || aIndex.row() >= rowCount())
158
 
        return false;
159
 
 
160
 
    if (aIndex.column() == 0)
161
 
    {
162
 
        SlotValue newSlot = aValue.isValid() ?
163
 
            aValue.value <SlotValue>() : SlotValue();
164
 
        if (mUsedSlotsList [aIndex.row()] != newSlot)
165
 
        {
166
 
            mUsedSlotsList [aIndex.row()] = newSlot;
167
 
            emit dataChanged (aIndex, aIndex);
168
 
            return true;
169
 
        }
170
 
        return false;
171
 
    } else
172
 
    if (aIndex.column() == 1)
173
 
    {
174
 
        DiskValue newDisk = aValue.isValid() ?
175
 
            aValue.value <DiskValue>() : DiskValue();
176
 
        if (mUsedDisksList [aIndex.row()] != newDisk)
177
 
        {
178
 
            mUsedDisksList [aIndex.row()] = newDisk;
179
 
            emit dataChanged (aIndex, aIndex);
180
 
            return true;
181
 
        }
182
 
        return false;
183
 
    }
184
 
    Assert (0);
185
 
    return false;
186
 
}
187
 
 
188
 
QVariant AttachmentsModel::headerData (int aSection,
189
 
                                       Qt::Orientation aOrientation,
190
 
                                       int aRole) const
191
 
{
192
 
    if (aRole != Qt::DisplayRole)
193
 
        return QVariant();
194
 
 
195
 
    if (aOrientation == Qt::Horizontal)
196
 
        return aSection ? tr ("Hard Disk") : tr ("Slot");
197
 
    else
198
 
        return QVariant();
199
 
}
200
 
 
201
 
void AttachmentsModel::addItem (const SlotValue &aSlot, const DiskValue &aDisk)
202
 
{
203
 
    beginInsertRows (QModelIndex(), rowCount() - 1, rowCount() - 1);
204
 
    mUsedSlotsList.append (aSlot);
205
 
    mUsedDisksList.append (aDisk);
206
 
    endInsertRows();
207
 
}
208
 
 
209
 
void AttachmentsModel::delItem (int aIndex)
210
 
{
211
 
    beginRemoveRows (QModelIndex(), aIndex, aIndex);
212
 
    mUsedSlotsList.removeAt (aIndex);
213
 
    mUsedDisksList.removeAt (aIndex);
214
 
    endRemoveRows();
215
 
}
216
 
 
217
 
QList <Attachment> AttachmentsModel::fullUsedList()
218
 
{
219
 
    QList <Attachment> list;
220
 
    QList <SlotValue> slts = usedSlotsList();
221
 
    QList <DiskValue> dsks = usedDisksList();
222
 
    for (int i = 0; i < slts.size(); ++ i)
223
 
        list << Attachment (slts [i], dsks [i]);
224
 
    qSort (list.begin(), list.end());
225
 
    return list;
226
 
}
227
 
 
228
 
void AttachmentsModel::removeAddController()
229
 
{
230
 
    int i=0;
231
 
    while (i < mUsedSlotsList.size())
232
 
    {
233
 
        if (mUsedSlotsList.at (i).bus == KStorageBus_SATA ||
234
 
            mUsedSlotsList.at (i).bus == KStorageBus_SCSI)
235
 
            /* We have to use delItem cause then all views are informed about
236
 
               the update */
237
 
            delItem (i);
238
 
        else
239
 
            ++i;
240
 
    }
241
 
}
242
 
 
243
 
void AttachmentsModel::updateDisks()
244
 
{
245
 
    QList <DiskValue> newDisks (HDSettings::instance()->disksList());
246
 
    for (int i = 0; i < mUsedDisksList.size(); ++ i)
247
 
    {
248
 
        if (newDisks.isEmpty())
249
 
            mUsedDisksList [i] = DiskValue();
250
 
        else if (newDisks.contains (mUsedDisksList [i]))
251
 
            mUsedDisksList [i] = DiskValue (mUsedDisksList [i].id);
252
 
        else
253
 
            mUsedDisksList [i] = DiskValue (newDisks [0].id);
254
 
    }
255
 
    emit dataChanged (index (0, 1), index (rowCount() - 1, 1));
256
 
}
257
 
 
258
 
/**
259
 
 * QComboBox class reimplementation.
260
 
 * Used as editor for HD Attachment SLOT field.
261
 
 */
262
 
SlotEditor::SlotEditor (QWidget *aParent)
263
 
    : QComboBox (aParent)
264
 
{
265
 
    connect (this, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivate()));
266
 
    connect (this, SIGNAL (readyToCommit (QWidget*)),
267
 
             parent()->parent(), SLOT (commitData (QWidget*)));
268
 
}
269
 
 
270
 
QVariant SlotEditor::slot() const
271
 
{
272
 
    int current = currentIndex();
273
 
    QVariant result;
274
 
    if (current >= 0 && current < mList.size())
275
 
        result.setValue (mList [current]);
276
 
    return result;
277
 
}
278
 
 
279
 
void SlotEditor::setSlot (QVariant aSlot)
280
 
{
281
 
    SlotValue val (aSlot.value <SlotValue>());
282
 
    populate (val);
283
 
    int current = findText (val.name);
284
 
    setCurrentIndex (current == -1 ? 0 : current);
285
 
}
286
 
 
287
 
void SlotEditor::onActivate()
288
 
{
289
 
    emit readyToCommit (this);
290
 
}
291
 
 
292
 
#if 0 /* F2 key binding left for future releases... */
293
 
void SlotEditor::keyPressEvent (QKeyEvent *aEvent)
294
 
{
295
 
    /* Make F2 key to show the popup. */
296
 
    if (aEvent->key() == Qt::Key_F2)
297
 
    {
298
 
        aEvent->accept();
299
 
        showPopup();
300
 
    }
301
 
    else
302
 
        aEvent->ignore();
303
 
    QComboBox::keyPressEvent (aEvent);
304
 
}
305
 
#endif
306
 
 
307
 
void SlotEditor::populate (const SlotValue &aIncluding)
308
 
{
309
 
    clear(), mList.clear();
310
 
    QList <SlotValue> list (HDSettings::instance()->slotsList (aIncluding, true));
311
 
    for (int i = 0; i < list.size() ; ++ i)
312
 
    {
313
 
        insertItem (i, list [i].name);
314
 
        mList << list [i];
315
 
    }
316
 
}
317
 
 
318
 
/**
319
 
 * VBoxMediaComboBox class reimplementation.
320
 
 * Used as editor for HD Attachment DISK field.
321
 
 */
322
 
DiskEditor* DiskEditor::mInstance = 0;
323
 
DiskEditor* DiskEditor::activeEditor()
324
 
{
325
 
    return mInstance;
326
 
}
327
 
 
328
 
DiskEditor::DiskEditor (QWidget *aParent)
329
 
    : VBoxMediaComboBox (aParent)
330
 
{
331
 
    mInstance = this;
332
 
    setIconSize (QSize (iconSize().width() * 2 + 2, iconSize().height()));
333
 
    Assert (!HDSettings::instance()->machine().isNull());
334
 
    setType (VBoxDefs::MediaType_HardDisk);
335
 
    setMachineId (HDSettings::instance()->machine().GetId());
336
 
    setShowDiffs (HDSettings::instance()->showDiffs());
337
 
    connect (this, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivate()));
338
 
    connect (this, SIGNAL (readyToCommit (QWidget *)),
339
 
             parent()->parent(), SLOT (commitData (QWidget *)));
340
 
    refresh();
341
 
}
342
 
DiskEditor::~DiskEditor()
343
 
{
344
 
    if (mInstance == this)
345
 
        mInstance = 0;
346
 
}
347
 
 
348
 
QVariant DiskEditor::disk() const
349
 
{
350
 
    int current = currentIndex();
351
 
    QVariant result;
352
 
    if (current >= 0 && current < count())
353
 
        result.setValue (DiskValue (id (current)));
354
 
    return result;
355
 
}
356
 
 
357
 
void DiskEditor::setDisk (QVariant aDisk)
358
 
{
359
 
    setCurrentItem (DiskValue (aDisk.value <DiskValue>()).id);
360
 
}
361
 
 
362
 
void DiskEditor::paintEvent (QPaintEvent*)
363
 
{
364
 
    /* Create the style painter to paint the elements. */
365
 
    QStylePainter painter (this);
366
 
    painter.setPen (palette().color (QPalette::Text));
367
 
    /* Initialize combo-box options and draw the elements. */
368
 
    QStyleOptionComboBox options;
369
 
    initStyleOption (&options);
370
 
    painter.drawComplexControl (QStyle::CC_ComboBox, options);
371
 
    painter.drawControl (QStyle::CE_ComboBoxLabel, options);
372
 
}
373
 
 
374
 
void DiskEditor::initStyleOption (QStyleOptionComboBox *aOption) const
375
 
{
376
 
    /* The base version of Qt4::QComboBox ignores the fact what each
377
 
     * combo-box item can have the icon of different size and uses the
378
 
     * maximum possible icon-size to draw the icon then performing
379
 
     * paintEvent(). As a result, stand-alone icons are painted using
380
 
     * the same huge region as the merged paired icons, so we have to
381
 
     * perform the size calculation ourself... */
382
 
 
383
 
    /* Init all style option by default... */
384
 
    VBoxMediaComboBox::initStyleOption (aOption);
385
 
    /* But calculate the icon size ourself. */
386
 
    QIcon currentItemIcon (itemIcon (currentIndex()));
387
 
    QPixmap realPixmap (currentItemIcon.pixmap (iconSize()));
388
 
    aOption->iconSize = realPixmap.size();
389
 
}
390
 
 
391
 
void DiskEditor::onActivate()
392
 
{
393
 
    emit readyToCommit (this);
394
 
}
395
 
 
396
 
#if 0 /* F2 key binding left for future releases... */
397
 
void DiskEditor::keyPressEvent (QKeyEvent *aEvent)
398
 
{
399
 
    /* Make F2 key to show the popup. */
400
 
    if (aEvent->key() == Qt::Key_F2)
401
 
    {
402
 
        aEvent->accept();
403
 
        showPopup();
404
 
    }
405
 
    else
406
 
        aEvent->ignore();
407
 
    VBoxMediaComboBox::keyPressEvent (aEvent);
408
 
}
409
 
#endif
410
 
 
411
 
/**
412
 
 * Singleton QObject class reimplementation.
413
 
 * Used to make selected HD Attachments slots unique &
414
 
 * stores some local data used for HD Settings.
415
 
 */
416
 
HDSettings* HDSettings::mInstance = 0;
417
 
HDSettings* HDSettings::instance (QWidget *aParent,
418
 
                                  AttachmentsModel *aWatched)
419
 
{
420
 
    if (!mInstance)
421
 
    {
422
 
        Assert (aParent && aWatched);
423
 
        mInstance = new HDSettings (aParent, aWatched);
424
 
    }
425
 
    return mInstance;
426
 
}
427
 
 
428
 
HDSettings::HDSettings (QWidget *aParent, AttachmentsModel *aWatched)
429
 
    : QObject (aParent)
430
 
    , mModel (aWatched)
431
 
    , mAddCount (0)
432
 
    , mAddBus (KStorageBus_Null)
433
 
    , mShowDiffs (false)
434
 
{
435
 
    makeIDEList();
436
 
    makeAddControllerList();
437
 
}
438
 
 
439
 
HDSettings::~HDSettings()
440
 
{
441
 
    mInstance = 0;
442
 
}
443
 
 
444
 
QList <SlotValue> HDSettings::slotsList (const SlotValue &aIncluding,
445
 
                                         bool aFilter /* = false */) const
446
 
{
447
 
    /* Compose the full slots list */
448
 
    QList <SlotValue> list (mIDEList + mAddControllerList);
449
 
    if (!aFilter)
450
 
        return list;
451
 
 
452
 
    /* Current used list */
453
 
    QList <SlotValue> usedList (mModel->usedSlotsList());
454
 
 
455
 
    /* Filter the list */
456
 
    foreach (SlotValue value, usedList)
457
 
        if (value != aIncluding)
458
 
            list.removeAll (value);
459
 
 
460
 
    return list;
461
 
}
462
 
 
463
 
QList <DiskValue> HDSettings::disksList() const
464
 
{
465
 
    return mDisksList;
466
 
}
467
 
 
468
 
bool HDSettings::tryToChooseUniqueDisk (DiskValue &aResult) const
469
 
{
470
 
    bool status = false;
471
 
 
472
 
    /* Current used list */
473
 
    QList <DiskValue> usedList (mModel->usedDisksList());
474
 
 
475
 
    /* Select the first available disk initially */
476
 
    aResult = mDisksList.isEmpty() ? DiskValue() : mDisksList [0];
477
 
 
478
 
    /* Search for first not busy disk */
479
 
    for (int i = 0; i < mDisksList.size(); ++ i)
480
 
        if (!usedList.contains (mDisksList [i]))
481
 
        {
482
 
            aResult = mDisksList [i];
483
 
            status = true;
484
 
            break;
485
 
        }
486
 
 
487
 
    return status;
488
 
}
489
 
 
490
 
void HDSettings::makeIDEList()
491
 
{
492
 
    mIDEList.clear();
493
 
 
494
 
    /* IDE Primary Master */
495
 
    mIDEList << SlotValue (KStorageBus_IDE, 0, 0);
496
 
    /* IDE Primary Slave */
497
 
    mIDEList << SlotValue (KStorageBus_IDE, 0, 1);
498
 
    /* IDE Secondary Slave */
499
 
    mIDEList << SlotValue (KStorageBus_IDE, 1, 1);
500
 
}
501
 
 
502
 
void HDSettings::makeAddControllerList()
503
 
{
504
 
    mAddControllerList.clear();
505
 
 
506
 
    for (int i = 0; i < mAddCount; ++ i)
507
 
        mAddControllerList << SlotValue (mAddBus, i, 0);
508
 
}
509
 
 
510
 
void HDSettings::makeMediumList()
511
 
{
512
 
    mDisksList.clear();
513
 
    VBoxMediaList list (vboxGlobal().currentMediaList());
514
 
    foreach (VBoxMedium medium, list)
515
 
    {
516
 
        /* Filter out unnecessary mediums */
517
 
        if (medium.type() != VBoxDefs::MediaType_HardDisk)
518
 
            continue;
519
 
 
520
 
        /* If !mShowDiffs we ignore all diffs except ones that are
521
 
         * directly attached to the related VM in the current state */
522
 
        if (!mShowDiffs && medium.parent() &&
523
 
            !medium.isAttachedInCurStateTo (mMachine.GetId()))
524
 
            continue;
525
 
 
526
 
        /* If !mShowDiffs we have to replace the root medium with his
527
 
         * differencing child which is directly used if the parent is found. */
528
 
        if (!mShowDiffs && medium.parent())
529
 
        {
530
 
            int index = mDisksList.indexOf (DiskValue (medium.root().id()));
531
 
            if (index != -1)
532
 
            {
533
 
                mDisksList.replace (index, DiskValue (medium.id()));
534
 
                continue;
535
 
            }
536
 
        }
537
 
 
538
 
        mDisksList.append (DiskValue (medium.id()));
539
 
    }
540
 
}
541
 
 
542
 
/**
543
 
 * QWidget class reimplementation.
544
 
 * Used as HD Settings widget.
545
 
 */
546
 
VBoxVMSettingsHD::VBoxVMSettingsHD()
547
 
    : mValidator (0)
548
 
    , mWasTableSelected (false)
549
 
    , mPolished (false)
550
 
    , mLastSelAddControllerIndex (0)
551
 
{
552
 
    /* Apply UI decorations */
553
 
    Ui::VBoxVMSettingsHD::setupUi (this);
554
 
 
555
 
    /* Setup model/view factory */
556
 
    int idHDSlot = qRegisterMetaType <SlotValue>();
557
 
    int idHDDisk = qRegisterMetaType <DiskValue>();
558
 
    QItemEditorFactory *factory = new QItemEditorFactory;
559
 
    QItemEditorCreatorBase *slotCreator =
560
 
        new QStandardItemEditorCreator <SlotEditor>();
561
 
    QItemEditorCreatorBase *diskCreator =
562
 
        new QStandardItemEditorCreator <DiskEditor>();
563
 
    factory->registerEditor ((QVariant::Type)idHDSlot, slotCreator);
564
 
    factory->registerEditor ((QVariant::Type)idHDDisk, diskCreator);
565
 
    QItemEditorFactory::setDefaultFactory (factory);
566
 
 
567
 
    /* Setup view-model */
568
 
    mModel = new AttachmentsModel (mTwAts, idHDSlot, idHDDisk);
569
 
    connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
570
 
             this, SIGNAL (hdChanged()));
571
 
 
572
 
    /* Initialize HD Settings */
573
 
    HDSettings::instance (mTwAts, mModel);
574
 
 
575
 
    /* Setup table-view */
576
 
    mTwAts->setMinimumHeight (100);
577
 
    mTwAts->verticalHeader()->setDefaultSectionSize (
578
 
        (int) (mTwAts->fontMetrics().height() * 1.30 /* 130% of font height */));
579
 
    mTwAts->verticalHeader()->hide();
580
 
    mTwAts->horizontalHeader()->setStretchLastSection (true);
581
 
    mTwAts->setModel (mModel);
582
 
    mTwAts->setToolTip (mModel->data (mModel->index (mModel->rowCount() - 1, 0),
583
 
                                      Qt::ToolTipRole).toString());
584
 
 
585
 
    /* Prepare actions */
586
 
    mNewAction = new QAction (mTwAts);
587
 
    mDelAction = new QAction (mTwAts);
588
 
    mVdmAction = new QAction (mTwAts);
589
 
 
590
 
    mTwAts->addAction (mNewAction);
591
 
    mTwAts->addAction (mDelAction);
592
 
    mTwAts->addAction (mVdmAction);
593
 
 
594
 
    mNewAction->setShortcut (QKeySequence ("Ins"));
595
 
    mDelAction->setShortcut (QKeySequence ("Del"));
596
 
    mVdmAction->setShortcut (QKeySequence ("Ctrl+Space"));
597
 
 
598
 
    mNewAction->setIcon (VBoxGlobal::iconSet (":/vdm_add_16px.png",
599
 
                                              ":/vdm_add_disabled_16px.png"));
600
 
    mDelAction->setIcon (VBoxGlobal::iconSet (":/vdm_remove_16px.png",
601
 
                                              ":/vdm_remove_disabled_16px.png"));
602
 
    mVdmAction->setIcon (VBoxGlobal::iconSet (":/select_file_16px.png",
603
 
                                              ":/select_file_dis_16px.png"));
604
 
 
605
 
    /* Prepare toolbar */
606
 
    VBoxToolBar *toolBar = new VBoxToolBar (mGbAts);
607
 
    toolBar->setUsesTextLabel (false);
608
 
    toolBar->setIconSize (QSize (16, 16));
609
 
    toolBar->setOrientation (Qt::Vertical);
610
 
    toolBar->addAction (mNewAction);
611
 
    toolBar->addAction (mDelAction);
612
 
    toolBar->addAction (mVdmAction);
613
 
    mGbAts->layout()->addWidget (toolBar);
614
 
 
615
 
    /* Setup connections */
616
 
    connect (mNewAction, SIGNAL (triggered (bool)),
617
 
             this, SLOT (addAttachment()));
618
 
    connect (mDelAction, SIGNAL (triggered (bool)),
619
 
             this, SLOT (delAttachment()));
620
 
    connect (mVdmAction, SIGNAL (triggered (bool)),
621
 
             this, SLOT (showMediaManager()));
622
 
 
623
 
    connect (mAddControllerCheck, SIGNAL (stateChanged (int)),
624
 
             this, SLOT (onAddControllerCheckToggled (int)));
625
 
    connect (mCbControllerType, SIGNAL (currentIndexChanged (int)),
626
 
             this, SLOT (onAddControllerTypeChanged (int)));
627
 
    connect (mShowDiffsCheck, SIGNAL (stateChanged (int)),
628
 
             this, SLOT (onShowDiffsCheckToggled (int)));
629
 
 
630
 
    connect (mTwAts, SIGNAL (currentChanged (const QModelIndex &)),
631
 
             this, SLOT (updateActions (const QModelIndex &)));
632
 
 
633
 
    connect (&vboxGlobal(), SIGNAL (mediumAdded (const VBoxMedium &)),
634
 
             HDSettings::instance(), SLOT (update()));
635
 
    connect (&vboxGlobal(), SIGNAL (mediumUpdated (const VBoxMedium &)),
636
 
             HDSettings::instance(), SLOT (update()));
637
 
    connect (&vboxGlobal(), SIGNAL (mediumRemoved (VBoxDefs::MediaType, const QString &)),
638
 
             HDSettings::instance(), SLOT (update()));
639
 
 
640
 
    /* IDE Controller Type */
641
 
    mCbIDEController->addItem (""); /* KIDEControllerType_PIIX3 */
642
 
    mCbIDEController->addItem (""); /* KIDEControllerType_PIIX4 */
643
 
    mCbIDEController->addItem (""); /* KIDEControllerType_ICH6  */
644
 
 
645
 
 
646
 
    /* Additional Controller Type */
647
 
    mCbControllerType->addItem ("", KStorageControllerType_IntelAhci);
648
 
    mCbControllerType->addItem ("", KStorageControllerType_LsiLogic);
649
 
    mCbControllerType->addItem ("", KStorageControllerType_BusLogic);
650
 
 
651
 
    /* Install global event filter */
652
 
    qApp->installEventFilter (this);
653
 
 
654
 
    /* Applying language settings */
655
 
    retranslateUi();
656
 
}
657
 
 
658
 
void VBoxVMSettingsHD::getFrom (const CMachine &aMachine)
659
 
{
660
 
    mMachine = aMachine;
661
 
    HDSettings::instance()->setMachine (mMachine);
662
 
 
663
 
    /* IDE controller type */
664
 
    const QString ideName = QString ("IDE");
665
 
    CStorageController ideCtl = aMachine.GetStorageControllerByName (ideName);
666
 
    mCbIDEController->setCurrentIndex (mCbIDEController->
667
 
        findText (vboxGlobal().toString (ideCtl.GetControllerType())));
668
 
 
669
 
    /* For now we search for the first one which isn't IDE */
670
 
    CStorageController addController;
671
 
    QVector<CStorageController> scs = mMachine.GetStorageControllers();
672
 
    foreach (const CStorageController &sc, scs)
673
 
        if (sc.GetBus() != KStorageBus_IDE)
674
 
        {
675
 
            addController = sc;
676
 
            break;
677
 
        }
678
 
    if (!addController.isNull())
679
 
        mCbControllerType->setCurrentIndex (mCbControllerType->findData (addController.GetControllerType()));
680
 
    else
681
 
        mCbControllerType->setCurrentIndex (0);
682
 
 
683
 
    mAddControllerCheck->setChecked (!addController.isNull());
684
 
 
685
 
    onAddControllerCheckToggled (mAddControllerCheck->checkState());
686
 
    onShowDiffsCheckToggled (mShowDiffsCheck->checkState());
687
 
 
688
 
    /* Load attachments list */
689
 
    CHardDiskAttachmentVector vec = mMachine.GetHardDiskAttachments();
690
 
    for (int i = 0; i < vec.size(); ++ i)
691
 
    {
692
 
        CHardDiskAttachment hda = vec [i];
693
 
        CStorageController  ctl = mMachine.GetStorageControllerByName(hda.GetController());
694
 
 
695
 
        SlotValue slot (ctl.GetBus(), hda.GetPort(), hda.GetDevice());
696
 
        DiskValue disk (hda.GetHardDisk().GetId());
697
 
        mModel->addItem (slot, disk);
698
 
    }
699
 
 
700
 
    /* Initially select the first table item & update the actions */
701
 
    mTwAts->setCurrentIndex (mModel->index (0, 1));
702
 
    updateActions (mTwAts->currentIndex());
703
 
 
704
 
    /* Validate if possible */
705
 
    if (mValidator)
706
 
        mValidator->revalidate();
707
 
}
708
 
 
709
 
void VBoxVMSettingsHD::putBackTo()
710
 
{
711
 
    /* IDE controller type */
712
 
    const QString ideName = QString ("IDE");
713
 
    CStorageController ideCtl = mMachine.GetStorageControllerByName(ideName);
714
 
    ideCtl.SetControllerType (vboxGlobal().toIDEControllerType (mCbIDEController->currentText()));
715
 
 
716
 
    /* Detach all attached Hard Disks */
717
 
    CHardDiskAttachmentVector vec = mMachine.GetHardDiskAttachments();
718
 
    for (int i = 0; i < vec.size(); ++ i)
719
 
    {
720
 
        CHardDiskAttachment hda = vec [i];
721
 
 
722
 
        mMachine.DetachHardDisk(hda.GetController(), hda.GetPort(), hda.GetDevice());
723
 
 
724
 
        /* [dsen] check this */
725
 
        if (!mMachine.isOk())
726
 
        {
727
 
            CStorageController ctl = mMachine.GetStorageControllerByName (hda.GetController());
728
 
            vboxProblem().cannotDetachHardDisk (this, mMachine,
729
 
                vboxGlobal().getMedium (CMedium (hda.GetHardDisk())).location(),
730
 
                ctl.GetBus(), hda.GetPort(), hda.GetDevice());
731
 
        }
732
 
    }
733
 
 
734
 
    /* Clear all storage controllers beside the IDE one */
735
 
    CStorageController addController;
736
 
    QVector <CStorageController> scs = mMachine.GetStorageControllers();
737
 
    foreach (const CStorageController &sc, scs)
738
 
        if (sc.GetBus() != KStorageBus_IDE)
739
 
            mMachine.RemoveStorageController (sc.GetName());
740
 
 
741
 
    /* Now add an additional controller if the user has enabled this */
742
 
    CStorageController addCtl;
743
 
    if (mAddControllerCheck->isChecked())
744
 
    {
745
 
        KStorageControllerType sct = currentControllerType();
746
 
        KStorageBus sv = currentBusType();
747
 
        addCtl = mMachine.AddStorageController (vboxGlobal().toString (sv), sv);
748
 
        addCtl.SetControllerType (sct);
749
 
    }
750
 
 
751
 
    /* On SATA it is possible to set the max port count. We want not wasting resources
752
 
     * so we try to find the port with the highest number & set it as max port count.
753
 
     * But first set it to the maximum because we get errors if there are more hard
754
 
     * disks than currently activated ports. */
755
 
    if (!addCtl.isNull() &&
756
 
        addCtl.GetBus() == KStorageBus_SATA)
757
 
        addCtl.SetPortCount (30);
758
 
 
759
 
    /* Attach all listed Hard Disks */
760
 
    LONG maxSATAPort = 1;
761
 
    QString ctrlName;
762
 
    QList <Attachment> list (mModel->fullUsedList());
763
 
    for (int i = 0; i < list.size(); ++ i)
764
 
    {
765
 
        ctrlName = vboxGlobal().toString (list [i].slot.bus);
766
 
        if (list [i].slot.bus == KStorageBus_SATA)
767
 
        {
768
 
            maxSATAPort = maxSATAPort < (list [i].slot.channel + 1) ?
769
 
                          (list [i].slot.channel + 1) : maxSATAPort;
770
 
        }
771
 
 
772
 
        mMachine.AttachHardDisk (list [i].disk.id,
773
 
                                 ctrlName, list [i].slot.channel, list [i].slot.device);
774
 
        /* [dsen] check this */
775
 
        if (!mMachine.isOk())
776
 
            vboxProblem().cannotAttachHardDisk (this, mMachine,
777
 
                vboxGlobal().getMedium (CMedium (vboxGlobal().virtualBox()
778
 
                .GetHardDisk (list [i].disk.id))).location(),
779
 
                list [i].slot.bus, list [i].slot.channel, list [i].slot.device);
780
 
    }
781
 
 
782
 
    /* Set the maximum port count if the additional controller is a SATA controller. */
783
 
    if (!addCtl.isNull() &&
784
 
        addCtl.GetBus() == KStorageBus_SATA)
785
 
        addCtl.SetPortCount (maxSATAPort);
786
 
}
787
 
 
788
 
void VBoxVMSettingsHD::setValidator (QIWidgetValidator *aVal)
789
 
{
790
 
    mValidator = aVal;
791
 
    connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
792
 
             mValidator, SLOT (revalidate()));
793
 
}
794
 
 
795
 
bool VBoxVMSettingsHD::revalidate (QString &aWarning, QString &)
796
 
{
797
 
    QList <SlotValue> slotList (mModel->usedSlotsList());
798
 
    QList <DiskValue> diskList (mModel->usedDisksList());
799
 
    for (int i = 0; i < diskList.size(); ++ i)
800
 
    {
801
 
        /* Check for emptiness */
802
 
        if (diskList [i].id.isNull())
803
 
        {
804
 
            aWarning = tr ("No hard disk is selected for <i>%1</i>")
805
 
                           .arg (slotList [i].name);
806
 
            break;
807
 
        }
808
 
 
809
 
        /* Check for coincidence */
810
 
        if (diskList.count (diskList [i]) > 1)
811
 
        {
812
 
            int first = diskList.indexOf (diskList [i]);
813
 
            int second = diskList.indexOf (diskList [i], first + 1);
814
 
            Assert (first != -1 && second != -1);
815
 
            aWarning = tr ("<i>%1</i> uses the hard disk that is "
816
 
                           "already attached to <i>%2</i>")
817
 
                           .arg (slotList [second].name,
818
 
                                 slotList [first].name);
819
 
            break;
820
 
        }
821
 
    }
822
 
 
823
 
    return aWarning.isNull();
824
 
}
825
 
 
826
 
void VBoxVMSettingsHD::setOrderAfter (QWidget *aWidget)
827
 
{
828
 
    setTabOrder (aWidget, mCbIDEController);
829
 
    setTabOrder (mCbIDEController, mAddControllerCheck);
830
 
    setTabOrder (mAddControllerCheck, mCbControllerType);
831
 
    setTabOrder (mCbControllerType, mTwAts);
832
 
    setTabOrder (mTwAts, mShowDiffsCheck);
833
 
}
834
 
 
835
 
void VBoxVMSettingsHD::retranslateUi()
836
 
{
837
 
    /* Translate uic generated strings */
838
 
    Ui::VBoxVMSettingsHD::retranslateUi (this);
839
 
 
840
 
    /* IDE Controller Type */
841
 
    mCbIDEController->setItemText (0, vboxGlobal().toString (KStorageControllerType_PIIX3));
842
 
    mCbIDEController->setItemText (1, vboxGlobal().toString (KStorageControllerType_PIIX4));
843
 
    mCbIDEController->setItemText (2, vboxGlobal().toString (KStorageControllerType_ICH6));
844
 
 
845
 
    /* Additional Controller Type */
846
 
    mCbControllerType->setItemText (0, QString ("%1 (%2)").arg (vboxGlobal().toString (KStorageBus_SATA))
847
 
                                                          .arg (vboxGlobal().toString (KStorageControllerType_IntelAhci)));
848
 
    mCbControllerType->setItemText (1, QString ("%1 (%2)").arg (vboxGlobal().toString (KStorageBus_SCSI))
849
 
                                                          .arg (vboxGlobal().toString (KStorageControllerType_LsiLogic)));
850
 
    mCbControllerType->setItemText (2, QString ("%1 (%2)").arg (vboxGlobal().toString (KStorageBus_SCSI))
851
 
                                                          .arg (vboxGlobal().toString (KStorageControllerType_BusLogic)));
852
 
 
853
 
    /* Attachments List */
854
 
    mNewAction->setText (tr ("&Add Attachment"));
855
 
    mDelAction->setText (tr ("&Remove Attachment"));
856
 
    mVdmAction->setText (tr ("&Select Hard Disk"));
857
 
 
858
 
    mNewAction->setToolTip (mNewAction->text().remove ('&') +
859
 
        QString (" (%1)").arg (mNewAction->shortcut().toString()));
860
 
    mDelAction->setToolTip (mDelAction->text().remove ('&') +
861
 
        QString (" (%1)").arg (mDelAction->shortcut().toString()));
862
 
    mVdmAction->setToolTip (mVdmAction->text().remove ('&') +
863
 
        QString (" (%1)").arg (mVdmAction->shortcut().toString()));
864
 
 
865
 
    mNewAction->setWhatsThis (tr ("Adds a new hard disk attachment."));
866
 
    mDelAction->setWhatsThis (tr ("Removes the highlighted hard disk attachment."));
867
 
    mVdmAction->setWhatsThis (tr ("Invokes the Virtual Media Manager to select "
868
 
                                  "a hard disk to attach to the currently "
869
 
                                  "highlighted slot."));
870
 
}
871
 
 
872
 
void VBoxVMSettingsHD::addAttachment()
873
 
{
874
 
    /* Temporary disable corresponding action now to prevent calling it again
875
 
     * before it will be disabled by current-changed processing. This can
876
 
     * happens if the user just pressed & hold the shortcut combination. */
877
 
    mNewAction->setEnabled (false);
878
 
 
879
 
    QString newId;
880
 
 
881
 
    {   /* Clear the focus */
882
 
        FocusGuardBlock guard (mTwAts);
883
 
 
884
 
        bool uniqueDiskSelected = false;
885
 
        HDSettings *hds = HDSettings::instance();
886
 
 
887
 
        {   /* Add new item with default values */
888
 
            SlotValue slot (hds->slotsList (SlotValue(), true) [0]);
889
 
            DiskValue disk;
890
 
            uniqueDiskSelected = hds->tryToChooseUniqueDisk (disk);
891
 
            mModel->addItem (slot, disk);
892
 
        }   /* Add new item with default values */
893
 
 
894
 
        /* If there are not enough unique disks */
895
 
        if (!uniqueDiskSelected)
896
 
        {
897
 
            /* Ask the user for method to add new disk */
898
 
            int confirm = vboxProblem().confirmRunNewHDWzdOrVDM (this);
899
 
            newId = confirm == QIMessageBox::Yes ? getWithNewHDWizard() :
900
 
                    confirm == QIMessageBox::No ? getWithMediaManager() : QString::null;
901
 
        }
902
 
    }   /* Clear the focus */
903
 
 
904
 
    /* Set the right column of new index to be the current */
905
 
    mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 1));
906
 
 
907
 
    if (!newId.isNull())
908
 
    {
909
 
        /* Compose & apply resulting disk */
910
 
        QVariant newValue;
911
 
        newValue.setValue (DiskValue (newId));
912
 
        mModel->setData (mTwAts->currentIndex(), newValue);
913
 
    }
914
 
 
915
 
    /* Validate if possible */
916
 
    if (mValidator)
917
 
        mValidator->revalidate();
918
 
    emit hdChanged();
919
 
}
920
 
 
921
 
void VBoxVMSettingsHD::delAttachment()
922
 
{
923
 
    Assert (mTwAts->currentIndex().isValid());
924
 
 
925
 
    /* Temporary disable corresponding action now to prevent calling it again
926
 
     * before it will be disabled by current-changed processing. This can
927
 
     * happens if the user just pressed & hold the shortcut combination. */
928
 
    mDelAction->setEnabled (false);
929
 
 
930
 
    /* Clear the focus */
931
 
    FocusGuardBlock guard (mTwAts);
932
 
 
933
 
    /* Storing current attributes */
934
 
    int row = mTwAts->currentIndex().row();
935
 
    int col = mTwAts->currentIndex().column();
936
 
 
937
 
    /* Erase current index */
938
 
    mTwAts->setCurrentIndex (QModelIndex());
939
 
 
940
 
    /* Calculate new current index */
941
 
    int newRow = row < mModel->rowCount() - 2 ? row :
942
 
                 row > 0 ? row - 1 : -1;
943
 
    QModelIndex next = newRow == -1 ? mModel->index (0, col) :
944
 
                                      mModel->index (newRow, col);
945
 
 
946
 
    /* Delete current index */
947
 
    mModel->delItem (row);
948
 
 
949
 
    /* Set the new index to be the current */
950
 
    mTwAts->setCurrentIndex (next);
951
 
    updateActions (next);
952
 
 
953
 
    if (mValidator)
954
 
        mValidator->revalidate();
955
 
    emit hdChanged();
956
 
}
957
 
 
958
 
void VBoxVMSettingsHD::showMediaManager()
959
 
{
960
 
    Assert (mTwAts->currentIndex().isValid());
961
 
 
962
 
    /* Clear the focus */
963
 
    FocusGuardBlock guard (mTwAts);
964
 
 
965
 
    DiskValue current (mModel->data (mTwAts->currentIndex(), Qt::EditRole)
966
 
                       .value <DiskValue>());
967
 
 
968
 
    QString id = getWithMediaManager (current.id);
969
 
 
970
 
    if (!id.isNull())
971
 
    {
972
 
        /* Compose & apply resulting disk */
973
 
        QVariant newValue;
974
 
        newValue.setValue (DiskValue (id));
975
 
        mModel->setData (mTwAts->currentIndex(), newValue);
976
 
    }
977
 
}
978
 
 
979
 
void VBoxVMSettingsHD::updateActions (const QModelIndex& /* aIndex */)
980
 
{
981
 
    mNewAction->setEnabled (mModel->rowCount() - 1 <
982
 
        HDSettings::instance()->slotsList().count());
983
 
    mDelAction->setEnabled (mTwAts->currentIndex().row() != mModel->rowCount() - 1);
984
 
    mVdmAction->setEnabled (mTwAts->currentIndex().row() != mModel->rowCount() - 1 &&
985
 
                            mTwAts->currentIndex().column() == 1);
986
 
}
987
 
 
988
 
void VBoxVMSettingsHD::onAddControllerCheckToggled (int aState)
989
 
{
990
 
    removeFocus();
991
 
    if (mAddControllerCheck->checkState() == Qt::Unchecked)
992
 
        if (checkAddControllers (0))
993
 
        {
994
 
            /* Switch check-box back to "Qt::Checked" */
995
 
            mAddControllerCheck->blockSignals (true);
996
 
            mAddControllerCheck->setCheckState (Qt::Checked);
997
 
            mAddControllerCheck->blockSignals (false);
998
 
            /* The user cancel the request so do nothing */
999
 
            return;
1000
 
        }
1001
 
 
1002
 
    mCbControllerType->setEnabled (aState == Qt::Checked);
1003
 
    HDSettings::instance()->setAddCount (mAddControllerCheck->checkState() == Qt::Checked ?
1004
 
                                         currentMaxPortCount() : 0,
1005
 
                                         currentBusType());
1006
 
    updateActions (mTwAts->currentIndex());
1007
 
}
1008
 
 
1009
 
void VBoxVMSettingsHD::onAddControllerTypeChanged (int aIndex)
1010
 
{
1011
 
    removeFocus();
1012
 
    if (checkAddControllers (1))
1013
 
    {
1014
 
        /* Switch check-box back to "Qt::Checked" */
1015
 
        mCbControllerType->blockSignals (true);
1016
 
        mCbControllerType->setCurrentIndex (mLastSelAddControllerIndex);
1017
 
        mCbControllerType->blockSignals (false);
1018
 
        /* The user cancel the request so do nothing */
1019
 
        return;
1020
 
    }
1021
 
 
1022
 
    /* Save the new index for later roll back */
1023
 
    mLastSelAddControllerIndex = aIndex;
1024
 
 
1025
 
    HDSettings::instance()->setAddCount (mAddControllerCheck->checkState() == Qt::Checked ?
1026
 
                                         currentMaxPortCount() : 0,
1027
 
                                         currentBusType());
1028
 
    updateActions (mTwAts->currentIndex());
1029
 
}
1030
 
 
1031
 
bool VBoxVMSettingsHD::checkAddControllers (int aWhat)
1032
 
{
1033
 
    /* Search the list for at least one SATA/SCSI port in */
1034
 
    QList <SlotValue> list (mModel->usedSlotsList());
1035
 
    int firstAddPort = 0;
1036
 
    for (; firstAddPort < list.size(); ++ firstAddPort)
1037
 
        if (list [firstAddPort].bus == KStorageBus_SATA ||
1038
 
            list [firstAddPort].bus == KStorageBus_SCSI)
1039
 
            break;
1040
 
 
1041
 
    /* If list contains at least one SATA/SCSI port */
1042
 
    if (firstAddPort < list.size())
1043
 
    {
1044
 
        int result = 0;
1045
 
        if (aWhat == 0)
1046
 
            result = vboxProblem().confirmDetachAddControllerSlots (this);
1047
 
        else
1048
 
            result = vboxProblem().confirmChangeAddControllerSlots (this);
1049
 
        if (result != QIMessageBox::Ok)
1050
 
            return true;
1051
 
        else
1052
 
        {
1053
 
            removeFocus();
1054
 
            /* Delete additional controller items */
1055
 
            mModel->removeAddController();
1056
 
 
1057
 
            /* Set column #1 of first index to be the current */
1058
 
            mTwAts->setCurrentIndex (mModel->index (0, 1));
1059
 
 
1060
 
            if (mValidator)
1061
 
                mValidator->revalidate();
1062
 
        }
1063
 
    }
1064
 
    return false;
1065
 
}
1066
 
 
1067
 
void VBoxVMSettingsHD::onShowDiffsCheckToggled (int aState)
1068
 
{
1069
 
    removeFocus();
1070
 
    HDSettings::instance()->setShowDiffs (aState == Qt::Checked);
1071
 
}
1072
 
 
1073
 
bool VBoxVMSettingsHD::eventFilter (QObject *aObject, QEvent *aEvent)
1074
 
{
1075
 
    if (!aObject->isWidgetType())
1076
 
        return QWidget::eventFilter (aObject, aEvent);
1077
 
 
1078
 
    QWidget *widget = static_cast <QWidget*> (aObject);
1079
 
    if (widget->inherits ("SlotEditor") ||
1080
 
        widget->inherits ("DiskEditor"))
1081
 
    {
1082
 
        if (aEvent->type() == QEvent::KeyPress)
1083
 
        {
1084
 
            QKeyEvent *e = static_cast <QKeyEvent*> (aEvent);
1085
 
            QModelIndex cur = mTwAts->currentIndex();
1086
 
            switch (e->key())
1087
 
            {
1088
 
                case Qt::Key_Up:
1089
 
                {
1090
 
                    if (cur.row() > 0)
1091
 
                        mTwAts->setCurrentIndex (mModel->index (cur.row() - 1,
1092
 
                                                                cur.column()));
1093
 
                    return true;
1094
 
                }
1095
 
                case Qt::Key_Down:
1096
 
                {
1097
 
                    if (cur.row() < mModel->rowCount() - 1)
1098
 
                        mTwAts->setCurrentIndex (mModel->index (cur.row() + 1,
1099
 
                                                                cur.column()));
1100
 
                    return true;
1101
 
                }
1102
 
                case Qt::Key_Right:
1103
 
                {
1104
 
                    if (cur.column() == 0)
1105
 
                        mTwAts->setCurrentIndex (mModel->index (cur.row(), 1));
1106
 
                    return true;
1107
 
                }
1108
 
                case Qt::Key_Left:
1109
 
                {
1110
 
                    if (cur.column() == 1)
1111
 
                        mTwAts->setCurrentIndex (mModel->index (cur.row(), 0));
1112
 
                    return true;
1113
 
                }
1114
 
                case Qt::Key_Tab:
1115
 
                {
1116
 
                    focusNextPrevChild (true);
1117
 
                    return true;
1118
 
                }
1119
 
                case Qt::Key_Backtab:
1120
 
                {
1121
 
                    /* Due to table on getting focus back from the child
1122
 
                     * put it instantly to this child again, make a hack
1123
 
                     * to put focus to the real previous owner. */
1124
 
                    mAddControllerCheck->setFocus();
1125
 
                    return true;
1126
 
                }
1127
 
                default:
1128
 
                    break;
1129
 
            }
1130
 
        } else
1131
 
        if (aEvent->type() == QEvent::WindowDeactivate)
1132
 
        {
1133
 
            /* Store focus state if it is on temporary editor. */
1134
 
            if (widget->hasFocus())
1135
 
                mWasTableSelected = true;
1136
 
        }
1137
 
    } else
1138
 
    if (widget == mTwAts->viewport() &&
1139
 
        aEvent->type() == QEvent::MouseButtonDblClick)
1140
 
    {
1141
 
        QMouseEvent *e = static_cast <QMouseEvent*> (aEvent);
1142
 
        QModelIndex index = mTwAts->indexAt (e->pos());
1143
 
        if (mNewAction->isEnabled() &&
1144
 
            (index.row() == mModel->rowCount() - 1 || !index.isValid()))
1145
 
            addAttachment();
1146
 
    } else
1147
 
    if (aEvent->type() == QEvent::WindowActivate)
1148
 
    {
1149
 
        if (mWasTableSelected)
1150
 
        {
1151
 
            /* Restore focus state if it was on temporary editor. */
1152
 
            mWasTableSelected = false;
1153
 
            mTwAts->setFocus();
1154
 
        }
1155
 
    }
1156
 
 
1157
 
    return QWidget::eventFilter (aObject, aEvent);
1158
 
}
1159
 
 
1160
 
void VBoxVMSettingsHD::showEvent (QShowEvent *aEvent)
1161
 
{
1162
 
    QWidget::showEvent (aEvent);
1163
 
 
1164
 
    if (mPolished)
1165
 
        return;
1166
 
    mPolished = true;
1167
 
 
1168
 
    /* Some delayed polishing */
1169
 
    mTwAts->horizontalHeader()->resizeSection (0,
1170
 
        style()->pixelMetric (QStyle::PM_ScrollBarExtent, 0, this) +
1171
 
        maxNameLength() + 9 * 2 /* 2 margins */);
1172
 
 
1173
 
    /* Activate edit triggers only now to avoid influencing
1174
 
     * HD Attachments table during data loading. */
1175
 
    mTwAts->setEditTriggers (QAbstractItemView::CurrentChanged |
1176
 
                             QAbstractItemView::SelectedClicked |
1177
 
                             QAbstractItemView::EditKeyPressed);
1178
 
 
1179
 
    /* That little hack allows avoid one of qt4 children focusing bug */
1180
 
    QWidget *current = QApplication::focusWidget();
1181
 
    mTwAts->setFocus (Qt::TabFocusReason);
1182
 
    if (current)
1183
 
        current->setFocus (Qt::TabFocusReason);
1184
 
}
1185
 
 
1186
 
QString VBoxVMSettingsHD::getWithMediaManager (const QString &aInitialId)
1187
 
{
1188
 
    /* Run Media Manager */
1189
 
    VBoxMediaManagerDlg dlg (this);
1190
 
    dlg.setup (VBoxDefs::MediaType_HardDisk,
1191
 
               true /* do select? */,
1192
 
               false /* do refresh? */,
1193
 
               mMachine,
1194
 
               aInitialId,
1195
 
               HDSettings::instance()->showDiffs());
1196
 
 
1197
 
    return dlg.exec() == QDialog::Accepted ? dlg.selectedId() : QString::null;
1198
 
}
1199
 
 
1200
 
QString VBoxVMSettingsHD::getWithNewHDWizard()
1201
 
{
1202
 
    /* Run New HD Wizard */
1203
 
    VBoxNewHDWzd dlg (this);
1204
 
 
1205
 
    return dlg.exec() == QDialog::Accepted ? dlg.hardDisk().GetId() : QString::null;
1206
 
}
1207
 
 
1208
 
int VBoxVMSettingsHD::maxNameLength() const
1209
 
{
1210
 
    QList <SlotValue> slts (HDSettings::instance()->slotsList());
1211
 
    int nameLength = 0;
1212
 
    for (int i = 0; i < slts.size(); ++ i)
1213
 
    {
1214
 
        int length = mTwAts->fontMetrics().width (slts [i].name);
1215
 
        nameLength = length > nameLength ? length : nameLength;
1216
 
    }
1217
 
    return nameLength;
1218
 
}
1219
 
 
1220
 
void VBoxVMSettingsHD::removeFocus()
1221
 
{
1222
 
#ifdef Q_WS_MAC
1223
 
    /* On the Mac checkboxes aren't focus aware. Therewith a editor widget get
1224
 
     * not closed by clicking on the checkbox. As a result the content of the
1225
 
     * currently used editor (QComboBox) isn't updated. So manually remove the
1226
 
     * focus to force the closing of any open editor widget. */
1227
 
    QWidget *focusWidget = qApp->focusWidget();
1228
 
    if (focusWidget)
1229
 
        focusWidget->clearFocus();
1230
 
#endif /* Q_WS_MAC */
1231
 
}
1232