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

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/settings/vm/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-2009 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
/* Global Includes */
 
24
#include <QHeaderView>
 
25
#include <QItemEditorFactory>
 
26
#include <QMetaProperty>
 
27
#include <QMouseEvent>
 
28
#include <QScrollBar>
 
29
#include <QStylePainter>
 
30
#include <QTimer>
 
31
 
 
32
/* Local Includes */
 
33
#include "VBoxVMSettingsHD.h"
 
34
#include "VBoxGlobal.h"
 
35
#include "VBoxProblemReporter.h"
 
36
#include "QIWidgetValidator.h"
 
37
#include "VBoxToolBar.h"
 
38
#include "VBoxMediaManagerDlg.h"
 
39
#include "VBoxNewHDWzd.h"
 
40
 
 
41
/* String Tags */
 
42
const char *firstAvailableId = "first available";
 
43
 
 
44
/* Type converters */
 
45
VBoxDefs::MediumType typeToLocal (KDeviceType aType)
 
46
{
 
47
    VBoxDefs::MediumType result = VBoxDefs::MediumType_Invalid;
 
48
    switch (aType)
 
49
    {
 
50
        case KDeviceType_HardDisk:
 
51
            result = VBoxDefs::MediumType_HardDisk;
 
52
            break;
 
53
        case KDeviceType_DVD:
 
54
            result = VBoxDefs::MediumType_DVD;
 
55
            break;
 
56
        case KDeviceType_Floppy:
 
57
            result = VBoxDefs::MediumType_Floppy;
 
58
            break;
 
59
        default:
 
60
            AssertMsgFailed (("Incorrect medium type!\n"));
 
61
            break;
 
62
    }
 
63
    return result;
 
64
}
 
65
 
 
66
 
 
67
QString compressText (const QString &aText)
 
68
{
 
69
    return QString ("<nobr><compact elipsis=\"end\">%1</compact></nobr>").arg (aText);
 
70
}
 
71
 
 
72
 
 
73
/* Pixmap Storage */
 
74
QPointer <PixmapPool> PixmapPool::mThis = 0;
 
75
 
 
76
PixmapPool* PixmapPool::pool (QObject *aParent)
 
77
{
 
78
    if (!mThis)
 
79
    {
 
80
        AssertMsg (aParent, ("This object must have parent!\n"));
 
81
        mThis = new PixmapPool (aParent);
 
82
    }
 
83
    else
 
84
    {
 
85
        AssertMsg (!aParent, ("Parent already set!\n"));
 
86
    }
 
87
    return mThis;
 
88
}
 
89
 
 
90
PixmapPool::PixmapPool (QObject *aParent)
 
91
    : QObject (aParent)
 
92
{
 
93
    mPool.resize (MaxIndex);
 
94
 
 
95
    mPool [ControllerAddEn]          = QPixmap (":/controller_add_16px.png");
 
96
    mPool [ControllerAddDis]         = QPixmap (":/controller_add_disabled_16px.png");
 
97
    mPool [ControllerDelEn]          = QPixmap (":/controller_remove_16px.png");
 
98
    mPool [ControllerDelDis]         = QPixmap (":/controller_remove_disabled_16px.png");
 
99
 
 
100
    mPool [AttachmentAddEn]          = QPixmap (":/attachment_add_16px.png");
 
101
    mPool [AttachmentAddDis]         = QPixmap (":/attachment_add_disabled_16px.png");
 
102
    mPool [AttachmentDelEn]          = QPixmap (":/attachment_remove_16px.png");
 
103
    mPool [AttachmentDelDis]         = QPixmap (":/attachment_remove_disabled_16px.png");
 
104
 
 
105
    mPool [IDEControllerNormal]      = QPixmap (":/ide_16px.png");
 
106
    mPool [IDEControllerExpand]      = QPixmap (":/ide_expand_16px.png");
 
107
    mPool [IDEControllerCollapse]    = QPixmap (":/ide_collapse_16px.png");
 
108
    mPool [SATAControllerNormal]     = QPixmap (":/sata_16px.png");
 
109
    mPool [SATAControllerExpand]     = QPixmap (":/sata_expand_16px.png");
 
110
    mPool [SATAControllerCollapse]   = QPixmap (":/sata_collapse_16px.png");
 
111
    mPool [SCSIControllerNormal]     = QPixmap (":/scsi_16px.png");
 
112
    mPool [SCSIControllerExpand]     = QPixmap (":/scsi_expand_16px.png");
 
113
    mPool [SCSIControllerCollapse]   = QPixmap (":/scsi_collapse_16px.png");
 
114
    mPool [FloppyControllerNormal]   = QPixmap (":/floppy_16px.png");
 
115
    mPool [FloppyControllerExpand]   = QPixmap (":/floppy_expand_16px.png");
 
116
    mPool [FloppyControllerCollapse] = QPixmap (":/floppy_collapse_16px.png");
 
117
 
 
118
    mPool [IDEControllerAddEn]       = QPixmap (":/ide_add_16px.png");
 
119
    mPool [IDEControllerAddDis]      = QPixmap (":/ide_add_disabled_16px.png");
 
120
    mPool [SATAControllerAddEn]      = QPixmap (":/sata_add_16px.png");
 
121
    mPool [SATAControllerAddDis]     = QPixmap (":/sata_add_disabled_16px.png");
 
122
    mPool [SCSIControllerAddEn]      = QPixmap (":/scsi_add_16px.png");
 
123
    mPool [SCSIControllerAddDis]     = QPixmap (":/scsi_add_disabled_16px.png");
 
124
    mPool [FloppyControllerAddEn]    = QPixmap (":/floppy_add_16px.png");
 
125
    mPool [FloppyControllerAddDis]   = QPixmap (":/floppy_add_disabled_16px.png");
 
126
 
 
127
    mPool [HDAttachmentNormal]       = QPixmap (":/hd_16px.png");
 
128
    mPool [CDAttachmentNormal]       = QPixmap (":/cd_16px.png");
 
129
    mPool [FDAttachmentNormal]       = QPixmap (":/fd_16px.png");
 
130
 
 
131
    mPool [HDAttachmentAddEn]        = QPixmap (":/hd_add_16px.png");
 
132
    mPool [HDAttachmentAddDis]       = QPixmap (":/hd_add_disabled_16px.png");
 
133
    mPool [CDAttachmentAddEn]        = QPixmap (":/cd_add_16px.png");
 
134
    mPool [CDAttachmentAddDis]       = QPixmap (":/cd_add_disabled_16px.png");
 
135
    mPool [FDAttachmentAddEn]        = QPixmap (":/fd_add_16px.png");
 
136
    mPool [FDAttachmentAddDis]       = QPixmap (":/fd_add_disabled_16px.png");
 
137
 
 
138
    mPool [VMMEn]                    = QPixmap (":/select_file_16px.png");
 
139
    mPool [VMMDis]                   = QPixmap (":/select_file_dis_16px.png");
 
140
}
 
141
 
 
142
QPixmap PixmapPool::pixmap (PixmapType aType) const
 
143
{
 
144
    return aType > InvalidPixmap && aType < MaxIndex ? mPool [aType] : 0;
 
145
}
 
146
 
 
147
/* Abstract Controller Type */
 
148
AbstractControllerType::AbstractControllerType (KStorageBus aBusType, KStorageControllerType aCtrType)
 
149
    : mBusType (aBusType)
 
150
    , mCtrType (aCtrType)
 
151
{
 
152
    AssertMsg (mBusType != KStorageBus_Null, ("Wrong Bus Type {%d}!\n", mBusType));
 
153
    AssertMsg (mCtrType != KStorageControllerType_Null, ("Wrong Controller Type {%d}!\n", mCtrType));
 
154
 
 
155
    for (int i = 0; i < State_MAX; ++ i)
 
156
    {
 
157
        mPixmaps << PixmapPool::InvalidPixmap;
 
158
        switch (mBusType)
 
159
        {
 
160
            case KStorageBus_IDE:
 
161
                mPixmaps [i] = (PixmapPool::PixmapType) (PixmapPool::IDEControllerNormal + i);
 
162
                break;
 
163
            case KStorageBus_SATA:
 
164
                mPixmaps [i] = (PixmapPool::PixmapType) (PixmapPool::SATAControllerNormal + i);
 
165
                break;
 
166
            case KStorageBus_SCSI:
 
167
                mPixmaps [i] = (PixmapPool::PixmapType) (PixmapPool::SCSIControllerNormal + i);
 
168
                break;
 
169
            case KStorageBus_Floppy:
 
170
                mPixmaps [i] = (PixmapPool::PixmapType) (PixmapPool::FloppyControllerNormal + i);
 
171
                break;
 
172
            default:
 
173
                break;
 
174
        }
 
175
        AssertMsg (mPixmaps [i] != PixmapPool::InvalidPixmap, ("Item state pixmap was not set!\n"));
 
176
    }
 
177
}
 
178
 
 
179
KStorageBus AbstractControllerType::busType() const
 
180
{
 
181
    return mBusType;
 
182
}
 
183
 
 
184
KStorageControllerType AbstractControllerType::ctrType() const
 
185
{
 
186
    return mCtrType;
 
187
}
 
188
 
 
189
ControllerTypeList AbstractControllerType::ctrTypes() const
 
190
{
 
191
    ControllerTypeList result;
 
192
    for (uint i = first(); i < first() + size(); ++ i)
 
193
        result << (KStorageControllerType) i;
 
194
    return result;
 
195
}
 
196
 
 
197
PixmapPool::PixmapType AbstractControllerType::pixmap (ItemState aState) const
 
198
{
 
199
    return mPixmaps [aState];
 
200
}
 
201
 
 
202
void AbstractControllerType::setCtrType (KStorageControllerType aCtrType)
 
203
{
 
204
    mCtrType = aCtrType;
 
205
}
 
206
 
 
207
DeviceTypeList AbstractControllerType::deviceTypeList() const
 
208
{
 
209
    return vboxGlobal().virtualBox().GetSystemProperties().GetDeviceTypesForStorageBus (mBusType).toList();
 
210
}
 
211
 
 
212
/* IDE Controller Type */
 
213
IDEControllerType::IDEControllerType (KStorageControllerType aSubType)
 
214
    : AbstractControllerType (KStorageBus_IDE, aSubType)
 
215
{
 
216
}
 
217
 
 
218
KStorageControllerType IDEControllerType::first() const
 
219
{
 
220
    return KStorageControllerType_PIIX3;
 
221
}
 
222
 
 
223
uint IDEControllerType::size() const
 
224
{
 
225
    return 3;
 
226
}
 
227
 
 
228
/* SATA Controller Type */
 
229
SATAControllerType::SATAControllerType (KStorageControllerType aSubType)
 
230
    : AbstractControllerType (KStorageBus_SATA, aSubType)
 
231
{
 
232
}
 
233
 
 
234
KStorageControllerType SATAControllerType::first() const
 
235
{
 
236
    return KStorageControllerType_IntelAhci;
 
237
}
 
238
 
 
239
uint SATAControllerType::size() const
 
240
{
 
241
    return 1;
 
242
}
 
243
 
 
244
/* SCSI Controller Type */
 
245
SCSIControllerType::SCSIControllerType (KStorageControllerType aSubType)
 
246
    : AbstractControllerType (KStorageBus_SCSI, aSubType)
 
247
{
 
248
}
 
249
 
 
250
KStorageControllerType SCSIControllerType::first() const
 
251
{
 
252
    return KStorageControllerType_LsiLogic;
 
253
}
 
254
 
 
255
uint SCSIControllerType::size() const
 
256
{
 
257
    return 2;
 
258
}
 
259
 
 
260
/* Floppy Controller Type */
 
261
FloppyControllerType::FloppyControllerType (KStorageControllerType aSubType)
 
262
    : AbstractControllerType (KStorageBus_Floppy, aSubType)
 
263
{
 
264
}
 
265
 
 
266
KStorageControllerType FloppyControllerType::first() const
 
267
{
 
268
    return KStorageControllerType_I82078;
 
269
}
 
270
 
 
271
uint FloppyControllerType::size() const
 
272
{
 
273
    return 1;
 
274
}
 
275
 
 
276
/* Abstract Item */
 
277
AbstractItem::AbstractItem (AbstractItem *aParent)
 
278
    : mParent (aParent)
 
279
    , mId (QUuid::createUuid())
 
280
{
 
281
    if (mParent) mParent->addChild (this);
 
282
}
 
283
 
 
284
AbstractItem::~AbstractItem()
 
285
{
 
286
    if (mParent) mParent->delChild (this);
 
287
}
 
288
 
 
289
AbstractItem* AbstractItem::parent() const
 
290
{
 
291
    return mParent;
 
292
}
 
293
 
 
294
QUuid AbstractItem::id() const
 
295
{
 
296
    return mId;
 
297
}
 
298
 
 
299
QString AbstractItem::machineId() const
 
300
{
 
301
    return mMachineId;
 
302
}
 
303
 
 
304
void AbstractItem::setMachineId (const QString &aMachineId)
 
305
{
 
306
    mMachineId = aMachineId;
 
307
}
 
308
 
 
309
/* Root Item */
 
310
RootItem::RootItem()
 
311
    : AbstractItem (0)
 
312
{
 
313
}
 
314
 
 
315
RootItem::~RootItem()
 
316
{
 
317
    while (!mControllers.isEmpty())
 
318
        delete mControllers.first();
 
319
}
 
320
 
 
321
ULONG RootItem::childCount (KStorageBus aBus) const
 
322
{
 
323
    ULONG result = 0;
 
324
    foreach (AbstractItem *item, mControllers)
 
325
    {
 
326
        ControllerItem *ctrItem = static_cast <ControllerItem*> (item);
 
327
        if (ctrItem->ctrBusType() == aBus)
 
328
            ++ result;
 
329
    }
 
330
    return result;
 
331
}
 
332
 
 
333
AbstractItem::ItemType RootItem::rtti() const
 
334
{
 
335
    return Type_RootItem;
 
336
}
 
337
 
 
338
AbstractItem* RootItem::childByPos (int aIndex)
 
339
{
 
340
    return mControllers [aIndex];
 
341
}
 
342
 
 
343
AbstractItem* RootItem::childById (const QUuid &aId)
 
344
{
 
345
    for (int i = 0; i < childCount(); ++ i)
 
346
        if (mControllers [i]->id() == aId)
 
347
            return mControllers [i];
 
348
    return 0;
 
349
}
 
350
 
 
351
int RootItem::posOfChild (AbstractItem *aItem) const
 
352
{
 
353
    return mControllers.indexOf (aItem);
 
354
}
 
355
 
 
356
int RootItem::childCount() const
 
357
{
 
358
    return mControllers.size();
 
359
}
 
360
 
 
361
QString RootItem::text() const
 
362
{
 
363
    return QString();
 
364
}
 
365
 
 
366
QString RootItem::tip() const
 
367
{
 
368
    return QString();
 
369
}
 
370
 
 
371
QPixmap RootItem::pixmap (ItemState /* aState */)
 
372
{
 
373
    return QPixmap();
 
374
}
 
375
 
 
376
void RootItem::addChild (AbstractItem *aItem)
 
377
{
 
378
    mControllers << aItem;
 
379
}
 
380
 
 
381
void RootItem::delChild (AbstractItem *aItem)
 
382
{
 
383
    mControllers.removeAll (aItem);
 
384
}
 
385
 
 
386
/* Controller Item */
 
387
ControllerItem::ControllerItem (AbstractItem *aParent, const QString &aName,
 
388
                                KStorageBus aBusType, KStorageControllerType aControllerType)
 
389
    : AbstractItem (aParent)
 
390
    , mCtrName (aName)
 
391
    , mCtrType (0)
 
392
{
 
393
    /* Check for proper parent type */
 
394
    AssertMsg (mParent->rtti() == AbstractItem::Type_RootItem, ("Incorrect parent type!\n"));
 
395
 
 
396
    /* Select default type */
 
397
    switch (aBusType)
 
398
    {
 
399
        case KStorageBus_IDE:
 
400
            mCtrType = new IDEControllerType (aControllerType);
 
401
            break;
 
402
        case KStorageBus_SATA:
 
403
            mCtrType = new SATAControllerType (aControllerType);
 
404
            break;
 
405
        case KStorageBus_SCSI:
 
406
            mCtrType = new SCSIControllerType (aControllerType);
 
407
            break;
 
408
        case KStorageBus_Floppy:
 
409
            mCtrType = new FloppyControllerType (aControllerType);
 
410
            break;
 
411
        default:
 
412
            AssertMsgFailed (("Wrong Controller Type {%d}!\n", aBusType));
 
413
            break;
 
414
    }
 
415
}
 
416
 
 
417
ControllerItem::~ControllerItem()
 
418
{
 
419
    delete mCtrType;
 
420
    while (!mAttachments.isEmpty())
 
421
        delete mAttachments.first();
 
422
}
 
423
 
 
424
KStorageBus ControllerItem::ctrBusType() const
 
425
{
 
426
    return mCtrType->busType();
 
427
}
 
428
 
 
429
QString ControllerItem::ctrName() const
 
430
{
 
431
    return mCtrName;
 
432
}
 
433
 
 
434
KStorageControllerType ControllerItem::ctrType() const
 
435
{
 
436
    return mCtrType->ctrType();
 
437
}
 
438
 
 
439
ControllerTypeList ControllerItem::ctrTypes() const
 
440
{
 
441
    return mCtrType->ctrTypes();
 
442
}
 
443
 
 
444
void ControllerItem::setCtrName (const QString &aCtrName)
 
445
{
 
446
    mCtrName = aCtrName;
 
447
}
 
448
 
 
449
void ControllerItem::setCtrType (KStorageControllerType aCtrType)
 
450
{
 
451
    mCtrType->setCtrType (aCtrType);
 
452
}
 
453
 
 
454
SlotsList ControllerItem::ctrAllSlots() const
 
455
{
 
456
    SlotsList allSlots;
 
457
    CSystemProperties sp = vboxGlobal().virtualBox().GetSystemProperties();
 
458
    for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus (mCtrType->busType()); ++ i)
 
459
        for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus (mCtrType->busType()); ++ j)
 
460
            allSlots << StorageSlot (mCtrType->busType(), i, j);
 
461
    return allSlots;
 
462
}
 
463
 
 
464
SlotsList ControllerItem::ctrUsedSlots() const
 
465
{
 
466
    SlotsList usedSlots;
 
467
    for (int i = 0; i < mAttachments.size(); ++ i)
 
468
        usedSlots << static_cast <AttachmentItem*> (mAttachments [i])->attSlot();
 
469
    return usedSlots;
 
470
}
 
471
 
 
472
DeviceTypeList ControllerItem::ctrDeviceTypeList() const
 
473
{
 
474
     return mCtrType->deviceTypeList();
 
475
}
 
476
 
 
477
QStringList ControllerItem::ctrAllMediumIds (bool aShowDiffs) const
 
478
{
 
479
    QStringList allMediums;
 
480
    foreach (const VBoxMedium &medium, vboxGlobal().currentMediaList())
 
481
    {
 
482
         foreach (const KDeviceType &deviceType, mCtrType->deviceTypeList())
 
483
         {
 
484
             if (medium.isNull() || medium.medium().GetDeviceType() == deviceType)
 
485
             {
 
486
                 /* In 'don't show diffs' mode we should only show hard-disks which are:
 
487
                  * 1. Attached to 'current state' of this VM even if these are differencing disks.
 
488
                  * 2. Not attached to this VM at all only if they are not differencing disks. */
 
489
                 if (!aShowDiffs && medium.type() == VBoxDefs::MediumType_HardDisk)
 
490
                 {
 
491
                     if (medium.isAttachedInCurStateTo (parent()->machineId()) ||
 
492
                         (!medium.medium().GetMachineIds().contains (parent()->machineId()) && !medium.parent()))
 
493
                         allMediums << medium.id();
 
494
                 }
 
495
                 else allMediums << medium.id();
 
496
                 break;
 
497
             }
 
498
         }
 
499
    }
 
500
    return allMediums;
 
501
}
 
502
 
 
503
QStringList ControllerItem::ctrUsedMediumIds() const
 
504
{
 
505
    QStringList usedImages;
 
506
    for (int i = 0; i < mAttachments.size(); ++ i)
 
507
    {
 
508
        QString usedMediumId = static_cast <AttachmentItem*> (mAttachments [i])->attMediumId();
 
509
        if (!vboxGlobal().findMedium (usedMediumId).isNull())
 
510
            usedImages << usedMediumId;
 
511
    }
 
512
    return usedImages;
 
513
}
 
514
 
 
515
AbstractItem::ItemType ControllerItem::rtti() const
 
516
{
 
517
    return Type_ControllerItem;
 
518
}
 
519
 
 
520
AbstractItem* ControllerItem::childByPos (int aIndex)
 
521
{
 
522
    return mAttachments [aIndex];
 
523
}
 
524
 
 
525
AbstractItem* ControllerItem::childById (const QUuid &aId)
 
526
{
 
527
    for (int i = 0; i < childCount(); ++ i)
 
528
        if (mAttachments [i]->id() == aId)
 
529
            return mAttachments [i];
 
530
    return 0;
 
531
}
 
532
 
 
533
int ControllerItem::posOfChild (AbstractItem *aItem) const
 
534
{
 
535
    return mAttachments.indexOf (aItem);
 
536
}
 
537
 
 
538
int ControllerItem::childCount() const
 
539
{
 
540
    return mAttachments.size();
 
541
}
 
542
 
 
543
QString ControllerItem::text() const
 
544
{
 
545
    return ctrName();
 
546
}
 
547
 
 
548
QString ControllerItem::tip() const
 
549
{
 
550
    return VBoxVMSettingsHD::tr ("<nobr><b>%1</b></nobr><br>"
 
551
                                 "<nobr>Bus:&nbsp;&nbsp;%2</nobr><br>"
 
552
                                 "<nobr>Type:&nbsp;&nbsp;%3</nobr>")
 
553
                                 .arg (mCtrName)
 
554
                                 .arg (vboxGlobal().toString (mCtrType->busType()))
 
555
                                 .arg (vboxGlobal().toString (mCtrType->ctrType()));
 
556
}
 
557
 
 
558
QPixmap ControllerItem::pixmap (ItemState aState)
 
559
{
 
560
    return PixmapPool::pool()->pixmap (mCtrType->pixmap (aState));
 
561
}
 
562
 
 
563
void ControllerItem::addChild (AbstractItem *aItem)
 
564
{
 
565
    mAttachments << aItem;
 
566
}
 
567
 
 
568
void ControllerItem::delChild (AbstractItem *aItem)
 
569
{
 
570
    mAttachments.removeAll (aItem);
 
571
}
 
572
 
 
573
/* Attachment Item */
 
574
AttachmentItem::AttachmentItem (AbstractItem *aParent, KDeviceType aDeviceType, bool aVerbose)
 
575
    : AbstractItem (aParent)
 
576
    , mAttDeviceType (aDeviceType)
 
577
    , mAttIsShowDiffs (false)
 
578
    , mAttIsHostDrive (false)
 
579
    , mAttIsPassthrough (false)
 
580
{
 
581
    /* Check for proper parent type */
 
582
    AssertMsg (mParent->rtti() == AbstractItem::Type_ControllerItem, ("Incorrect parent type!\n"));
 
583
 
 
584
    /* Select default slot */
 
585
    AssertMsg (!attSlots().isEmpty(), ("There should be at least one available slot!\n"));
 
586
    mAttSlot = attSlots() [0];
 
587
 
 
588
    /* Try to select unique medium */
 
589
    QStringList freeMediumIds (attMediumIds());
 
590
    switch (mAttDeviceType)
 
591
    {
 
592
        case KDeviceType_HardDisk:
 
593
            if (freeMediumIds.size() > 0)
 
594
                setAttMediumId (freeMediumIds [0]);
 
595
            break;
 
596
        case KDeviceType_DVD:
 
597
        case KDeviceType_Floppy:
 
598
            if (freeMediumIds.size() > 1)
 
599
                setAttMediumId (freeMediumIds [1]);
 
600
            else if (!aVerbose && freeMediumIds.size() > 0)
 
601
                setAttMediumId (freeMediumIds [0]);
 
602
            break;
 
603
        default:
 
604
            break;
 
605
    }
 
606
}
 
607
 
 
608
StorageSlot AttachmentItem::attSlot() const
 
609
{
 
610
    return mAttSlot;
 
611
}
 
612
 
 
613
SlotsList AttachmentItem::attSlots() const
 
614
{
 
615
    ControllerItem *ctr = static_cast <ControllerItem*> (mParent);
 
616
 
 
617
    /* Filter list from used slots */
 
618
    SlotsList allSlots (ctr->ctrAllSlots());
 
619
    SlotsList usedSlots (ctr->ctrUsedSlots());
 
620
    foreach (StorageSlot usedSlot, usedSlots)
 
621
        if (usedSlot != mAttSlot)
 
622
            allSlots.removeAll (usedSlot);
 
623
 
 
624
    return allSlots;
 
625
}
 
626
 
 
627
KDeviceType AttachmentItem::attDeviceType() const
 
628
{
 
629
    return mAttDeviceType;
 
630
}
 
631
 
 
632
DeviceTypeList AttachmentItem::attDeviceTypes() const
 
633
{
 
634
    return static_cast <ControllerItem*> (mParent)->ctrDeviceTypeList();
 
635
}
 
636
 
 
637
QString AttachmentItem::attMediumId() const
 
638
{
 
639
    return mAttMediumId;
 
640
}
 
641
 
 
642
QStringList AttachmentItem::attMediumIds (bool aFilter) const
 
643
{
 
644
    ControllerItem *ctr = static_cast <ControllerItem*> (mParent);
 
645
    QStringList allMediumIds;
 
646
 
 
647
    /* Populate list of suitable medium ids */
 
648
    foreach (QString mediumId, ctr->ctrAllMediumIds (mAttIsShowDiffs))
 
649
    {
 
650
        VBoxMedium medium = vboxGlobal().findMedium (mediumId);
 
651
        if ((medium.isNull() && mAttDeviceType != KDeviceType_HardDisk) ||
 
652
            (!medium.isNull() && medium.medium().GetDeviceType() == mAttDeviceType))
 
653
            allMediumIds << mediumId;
 
654
    }
 
655
 
 
656
    if (aFilter)
 
657
    {
 
658
        /* Filter list from used medium ids */
 
659
        QStringList usedMediumIds (ctr->ctrUsedMediumIds());
 
660
        foreach (QString usedMediumId, usedMediumIds)
 
661
            if (usedMediumId != mAttMediumId)
 
662
                allMediumIds.removeAll (usedMediumId);
 
663
    }
 
664
 
 
665
    return allMediumIds;
 
666
}
 
667
 
 
668
bool AttachmentItem::attIsShowDiffs() const
 
669
{
 
670
    return mAttIsShowDiffs;
 
671
}
 
672
 
 
673
bool AttachmentItem::attIsHostDrive() const
 
674
{
 
675
    return mAttIsHostDrive;
 
676
}
 
677
 
 
678
bool AttachmentItem::attIsPassthrough() const
 
679
{
 
680
    return mAttIsPassthrough;
 
681
}
 
682
 
 
683
void AttachmentItem::setAttSlot (const StorageSlot &aAttSlot)
 
684
{
 
685
    mAttSlot = aAttSlot;
 
686
}
 
687
 
 
688
void AttachmentItem::setAttDevice (KDeviceType aAttDeviceType)
 
689
{
 
690
    mAttDeviceType = aAttDeviceType;
 
691
}
 
692
 
 
693
void AttachmentItem::setAttMediumId (const QString &aAttMediumId)
 
694
{
 
695
    VBoxMedium medium;
 
696
 
 
697
    /* Caching first available medium */
 
698
    if (aAttMediumId == firstAvailableId && !attMediumIds (false).isEmpty())
 
699
        medium = vboxGlobal().findMedium (attMediumIds (false) [0]);
 
700
    /* Caching passed medium */
 
701
    else if (!aAttMediumId.isEmpty())
 
702
        medium = vboxGlobal().findMedium (aAttMediumId);
 
703
 
 
704
    mAttMediumId = medium.id();
 
705
    cache();
 
706
}
 
707
 
 
708
void AttachmentItem::setAttIsShowDiffs (bool aAttIsShowDiffs)
 
709
{
 
710
    mAttIsShowDiffs = aAttIsShowDiffs;
 
711
    cache();
 
712
}
 
713
 
 
714
void AttachmentItem::setAttIsPassthrough (bool aIsAttPassthrough)
 
715
{
 
716
    mAttIsPassthrough = aIsAttPassthrough;
 
717
}
 
718
 
 
719
QString AttachmentItem::attSize() const
 
720
{
 
721
    return mAttSize;
 
722
}
 
723
 
 
724
QString AttachmentItem::attLogicalSize() const
 
725
{
 
726
    return mAttLogicalSize;
 
727
}
 
728
 
 
729
QString AttachmentItem::attLocation() const
 
730
{
 
731
    return mAttLocation;
 
732
}
 
733
 
 
734
QString AttachmentItem::attFormat() const
 
735
{
 
736
    return mAttFormat;
 
737
}
 
738
 
 
739
QString AttachmentItem::attUsage() const
 
740
{
 
741
    return mAttUsage;
 
742
}
 
743
 
 
744
void AttachmentItem::cache()
 
745
{
 
746
    VBoxMedium medium = vboxGlobal().findMedium (mAttMediumId);
 
747
 
 
748
    /* Cache medium information */
 
749
    mAttName = medium.name (!mAttIsShowDiffs);
 
750
    mAttTip = medium.toolTipCheckRO (!mAttIsShowDiffs, mAttDeviceType != KDeviceType_HardDisk);
 
751
    mAttPixmap = medium.iconCheckRO (!mAttIsShowDiffs);
 
752
    mAttIsHostDrive = medium.isHostDrive();
 
753
 
 
754
    /* Cache additional information */
 
755
    mAttSize = medium.size (!mAttIsShowDiffs);
 
756
    mAttLogicalSize = medium.logicalSize (!mAttIsShowDiffs);
 
757
    mAttLocation = medium.location (!mAttIsShowDiffs);
 
758
    mAttFormat = medium.isNull() ? QString ("--") :
 
759
        QString ("%1 (%2)").arg (medium.hardDiskType (!mAttIsShowDiffs))
 
760
                           .arg (medium.hardDiskFormat (!mAttIsShowDiffs));
 
761
    mAttUsage = medium.usage (!mAttIsShowDiffs);
 
762
 
 
763
    /* Fill empty attributes */
 
764
    if (mAttUsage.isEmpty())
 
765
        mAttUsage = QString ("--");
 
766
}
 
767
 
 
768
AbstractItem::ItemType AttachmentItem::rtti() const
 
769
{
 
770
    return Type_AttachmentItem;
 
771
}
 
772
 
 
773
AbstractItem* AttachmentItem::childByPos (int /* aIndex */)
 
774
{
 
775
    return 0;
 
776
}
 
777
 
 
778
AbstractItem* AttachmentItem::childById (const QUuid& /* aId */)
 
779
{
 
780
    return 0;
 
781
}
 
782
 
 
783
int AttachmentItem::posOfChild (AbstractItem* /* aItem */) const
 
784
{
 
785
    return 0;
 
786
}
 
787
 
 
788
int AttachmentItem::childCount() const
 
789
{
 
790
    return 0;
 
791
}
 
792
 
 
793
QString AttachmentItem::text() const
 
794
{
 
795
    return mAttName;
 
796
}
 
797
 
 
798
QString AttachmentItem::tip() const
 
799
{
 
800
    return mAttTip;
 
801
}
 
802
 
 
803
QPixmap AttachmentItem::pixmap (ItemState /* aState */)
 
804
{
 
805
    if (mAttPixmap.isNull())
 
806
    {
 
807
        switch (mAttDeviceType)
 
808
        {
 
809
            case KDeviceType_HardDisk:
 
810
                mAttPixmap = PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentNormal);
 
811
                break;
 
812
            case KDeviceType_DVD:
 
813
                mAttPixmap = PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentNormal);
 
814
                break;
 
815
            case KDeviceType_Floppy:
 
816
                mAttPixmap = PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentNormal);
 
817
                break;
 
818
            default:
 
819
                break;
 
820
        }
 
821
    }
 
822
    return mAttPixmap;
 
823
}
 
824
 
 
825
void AttachmentItem::addChild (AbstractItem* /* aItem */)
 
826
{
 
827
}
 
828
 
 
829
void AttachmentItem::delChild (AbstractItem* /* aItem */)
 
830
{
 
831
}
 
832
 
 
833
/* Storage model */
 
834
StorageModel::StorageModel (QObject *aParent)
 
835
    : QAbstractItemModel (aParent)
 
836
    , mRootItem (new RootItem)
 
837
    , mToolTipType (DefaultToolTip)
 
838
{
 
839
}
 
840
 
 
841
StorageModel::~StorageModel()
 
842
{
 
843
    delete mRootItem;
 
844
}
 
845
 
 
846
int StorageModel::rowCount (const QModelIndex &aParent) const
 
847
{
 
848
    return !aParent.isValid() ? 1 /* only root item has invalid parent */ :
 
849
           static_cast <AbstractItem*> (aParent.internalPointer())->childCount();
 
850
}
 
851
 
 
852
int StorageModel::columnCount (const QModelIndex & /* aParent */) const
 
853
{
 
854
    return 1;
 
855
}
 
856
 
 
857
QModelIndex StorageModel::root() const
 
858
{
 
859
    return index (0, 0);
 
860
}
 
861
 
 
862
QModelIndex StorageModel::index (int aRow, int aColumn, const QModelIndex &aParent) const
 
863
{
 
864
    if (!hasIndex (aRow, aColumn, aParent))
 
865
        return QModelIndex();
 
866
 
 
867
    AbstractItem *item = !aParent.isValid() ? mRootItem :
 
868
                         static_cast <AbstractItem*> (aParent.internalPointer())->childByPos (aRow);
 
869
 
 
870
    return item ? createIndex (aRow, aColumn, item) : QModelIndex();
 
871
}
 
872
 
 
873
QModelIndex StorageModel::parent (const QModelIndex &aIndex) const
 
874
{
 
875
    if (!aIndex.isValid())
 
876
        return QModelIndex();
 
877
 
 
878
    AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer());
 
879
    AbstractItem *parentOfItem = item->parent();
 
880
    AbstractItem *parentOfParent = parentOfItem ? parentOfItem->parent() : 0;
 
881
    int position = parentOfParent ? parentOfParent->posOfChild (parentOfItem) : 0;
 
882
 
 
883
    if (parentOfItem)
 
884
        return createIndex (position, 0, parentOfItem);
 
885
    else
 
886
        return QModelIndex();
 
887
}
 
888
 
 
889
QVariant StorageModel::data (const QModelIndex &aIndex, int aRole) const
 
890
{
 
891
    if (!aIndex.isValid())
 
892
        return QVariant();
 
893
 
 
894
    switch (aRole)
 
895
    {
 
896
        /* Basic Attributes: */
 
897
        case Qt::FontRole:
 
898
        {
 
899
            return QVariant (qApp->font());
 
900
        }
 
901
        case Qt::SizeHintRole:
 
902
        {
 
903
            QFontMetrics fm (data (aIndex, Qt::FontRole).value <QFont>());
 
904
            int minimumHeight = qMax (fm.height(), data (aIndex, R_IconSize).toInt());
 
905
            int margin = data (aIndex, R_Margin).toInt();
 
906
            return QSize (1 /* ignoring width */, 2 * margin + minimumHeight);
 
907
        }
 
908
        case Qt::ToolTipRole:
 
909
        {
 
910
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
911
            {
 
912
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
913
                {
 
914
                    QString tip (item->tip());
 
915
                    switch (mToolTipType)
 
916
                    {
 
917
                        case ExpanderToolTip:
 
918
                            if (aIndex.child (0, 0).isValid())
 
919
                                tip = VBoxVMSettingsHD::tr ("<nobr>Expand/Collapse&nbsp;Item</nobr>");
 
920
                            break;
 
921
                        case HDAdderToolTip:
 
922
                            tip = VBoxVMSettingsHD::tr ("<nobr>Add&nbsp;Hard&nbsp;Disk</nobr>");
 
923
                            break;
 
924
                        case CDAdderToolTip:
 
925
                            tip = VBoxVMSettingsHD::tr ("<nobr>Add&nbsp;CD/DVD&nbsp;Device</nobr>");
 
926
                            break;
 
927
                        case FDAdderToolTip:
 
928
                            tip = VBoxVMSettingsHD::tr ("<nobr>Add&nbsp;Floppy&nbsp;Device</nobr>");
 
929
                            break;
 
930
                        default:
 
931
                            break;
 
932
                    }
 
933
                    return tip;
 
934
                }
 
935
                return item->tip();
 
936
            }
 
937
            return QString();
 
938
        }
 
939
 
 
940
        /* Advanced Attributes: */
 
941
        case R_ItemId:
 
942
        {
 
943
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
944
                return item->id().toString();
 
945
            return QUuid().toString();
 
946
        }
 
947
        case R_ItemPixmap:
 
948
        {
 
949
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
950
            {
 
951
                ItemState state = State_DefaultItem;
 
952
                if (hasChildren (aIndex))
 
953
                    if (QTreeView *view = qobject_cast <QTreeView*> (QObject::parent()))
 
954
                        state = view->isExpanded (aIndex) ? State_ExpandedItem : State_CollapsedItem;
 
955
                return item->pixmap (state);
 
956
            }
 
957
            return QPixmap();
 
958
        }
 
959
        case R_ItemPixmapRect:
 
960
        {
 
961
            int margin = data (aIndex, R_Margin).toInt();
 
962
            int width = data (aIndex, R_IconSize).toInt();
 
963
            return QRect (margin, margin, width, width);
 
964
        }
 
965
        case R_ItemName:
 
966
        {
 
967
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
968
                return item->text();
 
969
            return QString();
 
970
        }
 
971
        case R_ItemNamePoint:
 
972
        {
 
973
            int margin = data (aIndex, R_Margin).toInt();
 
974
            int spacing = data (aIndex, R_Spacing).toInt();
 
975
            int width = data (aIndex, R_IconSize).toInt();
 
976
            QFontMetrics fm (data (aIndex, Qt::FontRole).value <QFont>());
 
977
            QSize sizeHint = data (aIndex, Qt::SizeHintRole).toSize();
 
978
            return QPoint (margin + width + 2 * spacing,
 
979
                           sizeHint.height() / 2 + fm.ascent() / 2 - 1 /* base line */);
 
980
        }
 
981
        case R_ItemType:
 
982
        {
 
983
            QVariant result (QVariant::fromValue (AbstractItem::Type_InvalidItem));
 
984
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
985
                result.setValue (item->rtti());
 
986
            return result;
 
987
        }
 
988
        case R_IsController:
 
989
        {
 
990
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
991
                return item->rtti() == AbstractItem::Type_ControllerItem;
 
992
            return false;
 
993
        }
 
994
        case R_IsAttachment:
 
995
        {
 
996
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
997
                return item->rtti() == AbstractItem::Type_AttachmentItem;
 
998
            return false;
 
999
        }
 
1000
 
 
1001
        case R_ToolTipType:
 
1002
        {
 
1003
            return QVariant::fromValue (mToolTipType);
 
1004
        }
 
1005
        case R_IsMoreIDEControllersPossible:
 
1006
        {
 
1007
            return static_cast <RootItem*> (mRootItem)->childCount (KStorageBus_IDE) <
 
1008
                   vboxGlobal().virtualBox().GetSystemProperties().GetMaxInstancesOfStorageBus (KStorageBus_IDE);
 
1009
        }
 
1010
        case R_IsMoreSATAControllersPossible:
 
1011
        {
 
1012
            return static_cast <RootItem*> (mRootItem)->childCount (KStorageBus_SATA) <
 
1013
                   vboxGlobal().virtualBox().GetSystemProperties().GetMaxInstancesOfStorageBus (KStorageBus_SATA);
 
1014
        }
 
1015
        case R_IsMoreSCSIControllersPossible:
 
1016
        {
 
1017
            return static_cast <RootItem*> (mRootItem)->childCount (KStorageBus_SCSI) <
 
1018
                   vboxGlobal().virtualBox().GetSystemProperties().GetMaxInstancesOfStorageBus (KStorageBus_SCSI);
 
1019
        }
 
1020
        case R_IsMoreFloppyControllersPossible:
 
1021
        {
 
1022
            return static_cast <RootItem*> (mRootItem)->childCount (KStorageBus_Floppy) <
 
1023
                   vboxGlobal().virtualBox().GetSystemProperties().GetMaxInstancesOfStorageBus (KStorageBus_Floppy);
 
1024
        }
 
1025
        case R_IsMoreAttachmentsPossible:
 
1026
        {
 
1027
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1028
            {
 
1029
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1030
                {
 
1031
                    ControllerItem *ctr = static_cast <ControllerItem*> (item);
 
1032
                    CSystemProperties sp = vboxGlobal().virtualBox().GetSystemProperties();
 
1033
                    return (uint) rowCount (aIndex) < sp.GetMaxPortCountForStorageBus (ctr->ctrBusType()) *
 
1034
                                                      sp.GetMaxDevicesPerPortForStorageBus (ctr->ctrBusType());
 
1035
                }
 
1036
            }
 
1037
            return false;
 
1038
        }
 
1039
 
 
1040
        case R_CtrName:
 
1041
        {
 
1042
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1043
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1044
                    return static_cast <ControllerItem*> (item)->ctrName();
 
1045
            return QString();
 
1046
        }
 
1047
        case R_CtrType:
 
1048
        {
 
1049
            QVariant result (QVariant::fromValue (KStorageControllerType_Null));
 
1050
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1051
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1052
                    result.setValue (static_cast <ControllerItem*> (item)->ctrType());
 
1053
            return result;
 
1054
        }
 
1055
        case R_CtrTypes:
 
1056
        {
 
1057
            QVariant result (QVariant::fromValue (ControllerTypeList()));
 
1058
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1059
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1060
                    result.setValue (static_cast <ControllerItem*> (item)->ctrTypes());
 
1061
            return result;
 
1062
        }
 
1063
        case R_CtrDevices:
 
1064
        {
 
1065
            QVariant result (QVariant::fromValue (DeviceTypeList()));
 
1066
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1067
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1068
                    result.setValue (static_cast <ControllerItem*> (item)->ctrDeviceTypeList());
 
1069
            return result;
 
1070
        }
 
1071
        case R_CtrBusType:
 
1072
        {
 
1073
            QVariant result (QVariant::fromValue (KStorageBus_Null));
 
1074
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1075
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1076
                    result.setValue (static_cast <ControllerItem*> (item)->ctrBusType());
 
1077
            return result;
 
1078
        }
 
1079
 
 
1080
        case R_AttSlot:
 
1081
        {
 
1082
            QVariant result (QVariant::fromValue (StorageSlot()));
 
1083
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1084
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1085
                    result.setValue (static_cast <AttachmentItem*> (item)->attSlot());
 
1086
            return result;
 
1087
        }
 
1088
        case R_AttSlots:
 
1089
        {
 
1090
            QVariant result (QVariant::fromValue (SlotsList()));
 
1091
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1092
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1093
                    result.setValue (static_cast <AttachmentItem*> (item)->attSlots());
 
1094
            return result;
 
1095
        }
 
1096
        case R_AttDevice:
 
1097
        {
 
1098
            QVariant result (QVariant::fromValue (KDeviceType_Null));
 
1099
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1100
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1101
                    result.setValue (static_cast <AttachmentItem*> (item)->attDeviceType());
 
1102
            return result;
 
1103
        }
 
1104
        case R_AttMediumId:
 
1105
        {
 
1106
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1107
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1108
                    return static_cast <AttachmentItem*> (item)->attMediumId();
 
1109
            return QString();
 
1110
        }
 
1111
        case R_AttIsShowDiffs:
 
1112
        {
 
1113
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1114
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1115
                    return static_cast <AttachmentItem*> (item)->attIsShowDiffs();
 
1116
            return false;
 
1117
        }
 
1118
        case R_AttIsHostDrive:
 
1119
        {
 
1120
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1121
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1122
                    return static_cast <AttachmentItem*> (item)->attIsHostDrive();
 
1123
            return false;
 
1124
        }
 
1125
        case R_AttIsPassthrough:
 
1126
        {
 
1127
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1128
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1129
                    return static_cast <AttachmentItem*> (item)->attIsPassthrough();
 
1130
            return false;
 
1131
        }
 
1132
        case R_AttSize:
 
1133
        {
 
1134
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1135
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1136
                    return static_cast <AttachmentItem*> (item)->attSize();
 
1137
            return QString();
 
1138
        }
 
1139
        case R_AttLogicalSize:
 
1140
        {
 
1141
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1142
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1143
                    return static_cast <AttachmentItem*> (item)->attLogicalSize();
 
1144
            return QString();
 
1145
        }
 
1146
        case R_AttLocation:
 
1147
        {
 
1148
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1149
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1150
                    return static_cast <AttachmentItem*> (item)->attLocation();
 
1151
            return QString();
 
1152
        }
 
1153
        case R_AttFormat:
 
1154
        {
 
1155
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1156
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1157
                    return static_cast <AttachmentItem*> (item)->attFormat();
 
1158
            return QString();
 
1159
        }
 
1160
        case R_AttUsage:
 
1161
        {
 
1162
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1163
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1164
                    return static_cast <AttachmentItem*> (item)->attUsage();
 
1165
            return QString();
 
1166
        }
 
1167
        case R_Margin:
 
1168
        {
 
1169
            return 4;
 
1170
        }
 
1171
        case R_Spacing:
 
1172
        {
 
1173
            return 4;
 
1174
        }
 
1175
        case R_IconSize:
 
1176
        {
 
1177
            return 16;
 
1178
        }
 
1179
 
 
1180
        case R_HDPixmapEn:
 
1181
        {
 
1182
            return PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentNormal);
 
1183
        }
 
1184
        case R_CDPixmapEn:
 
1185
        {
 
1186
            return PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentNormal);
 
1187
        }
 
1188
        case R_FDPixmapEn:
 
1189
        {
 
1190
            return PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentNormal);
 
1191
        }
 
1192
 
 
1193
        case R_HDPixmapAddEn:
 
1194
        {
 
1195
            return PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentAddEn);
 
1196
        }
 
1197
        case R_HDPixmapAddDis:
 
1198
        {
 
1199
            return PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentAddDis);
 
1200
        }
 
1201
        case R_CDPixmapAddEn:
 
1202
        {
 
1203
            return PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentAddEn);
 
1204
        }
 
1205
        case R_CDPixmapAddDis:
 
1206
        {
 
1207
            return PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentAddDis);
 
1208
        }
 
1209
        case R_FDPixmapAddEn:
 
1210
        {
 
1211
            return PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentAddEn);
 
1212
        }
 
1213
        case R_FDPixmapAddDis:
 
1214
        {
 
1215
            return PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentAddDis);
 
1216
        }
 
1217
        case R_HDPixmapRect:
 
1218
        {
 
1219
            int margin = data (aIndex, R_Margin).toInt();
 
1220
            int width = data (aIndex, R_IconSize).toInt();
 
1221
            return QRect (0 - width - margin, margin, width, width);
 
1222
        }
 
1223
        case R_CDPixmapRect:
 
1224
        {
 
1225
            int margin = data (aIndex, R_Margin).toInt();
 
1226
            int spacing = data (aIndex, R_Spacing).toInt();
 
1227
            int width = data (aIndex, R_IconSize).toInt();
 
1228
            return QRect (0 - width - spacing - width - margin, margin, width, width);
 
1229
        }
 
1230
        case R_FDPixmapRect:
 
1231
        {
 
1232
            int margin = data (aIndex, R_Margin).toInt();
 
1233
            int width = data (aIndex, R_IconSize).toInt();
 
1234
            return QRect (0 - width - margin, margin, width, width);
 
1235
        }
 
1236
 
 
1237
        default:
 
1238
            break;
 
1239
    }
 
1240
    return QVariant();
 
1241
}
 
1242
 
 
1243
bool StorageModel::setData (const QModelIndex &aIndex, const QVariant &aValue, int aRole)
 
1244
{
 
1245
    if (!aIndex.isValid())
 
1246
        return QAbstractItemModel::setData (aIndex, aValue, aRole);
 
1247
 
 
1248
    switch (aRole)
 
1249
    {
 
1250
        case R_ToolTipType:
 
1251
        {
 
1252
            mToolTipType = aValue.value <ToolTipType>();
 
1253
            emit dataChanged (aIndex, aIndex);
 
1254
            return true;
 
1255
        }
 
1256
        case R_CtrName:
 
1257
        {
 
1258
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1259
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1260
                {
 
1261
                    static_cast <ControllerItem*> (item)->setCtrName (aValue.toString());
 
1262
                    emit dataChanged (aIndex, aIndex);
 
1263
                    return true;
 
1264
                }
 
1265
            return false;
 
1266
        }
 
1267
        case R_CtrType:
 
1268
        {
 
1269
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1270
                if (item->rtti() == AbstractItem::Type_ControllerItem)
 
1271
                {
 
1272
                    static_cast <ControllerItem*> (item)->setCtrType (aValue.value <KStorageControllerType>());
 
1273
                    emit dataChanged (aIndex, aIndex);
 
1274
                    return true;
 
1275
                }
 
1276
            return false;
 
1277
        }
 
1278
        case R_AttSlot:
 
1279
        {
 
1280
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1281
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1282
                {
 
1283
                    static_cast <AttachmentItem*> (item)->setAttSlot (aValue.value <StorageSlot>());
 
1284
                    emit dataChanged (aIndex, aIndex);
 
1285
                    return true;
 
1286
                }
 
1287
            return false;
 
1288
        }
 
1289
        case R_AttDevice:
 
1290
        {
 
1291
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1292
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1293
                {
 
1294
                    static_cast <AttachmentItem*> (item)->setAttDevice (aValue.value <KDeviceType>());
 
1295
                    emit dataChanged (aIndex, aIndex);
 
1296
                    return true;
 
1297
                }
 
1298
            return false;
 
1299
        }
 
1300
        case R_AttMediumId:
 
1301
        {
 
1302
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1303
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1304
                {
 
1305
                    static_cast <AttachmentItem*> (item)->setAttMediumId (aValue.toString());
 
1306
                    emit dataChanged (aIndex, aIndex);
 
1307
                    return true;
 
1308
                }
 
1309
            return false;
 
1310
        }
 
1311
        case R_AttIsShowDiffs:
 
1312
        {
 
1313
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1314
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1315
                {
 
1316
                    static_cast <AttachmentItem*> (item)->setAttIsShowDiffs (aValue.toBool());
 
1317
                    emit dataChanged (aIndex, aIndex);
 
1318
                    return true;
 
1319
                }
 
1320
            return false;
 
1321
        }
 
1322
        case R_AttIsPassthrough:
 
1323
        {
 
1324
            if (AbstractItem *item = static_cast <AbstractItem*> (aIndex.internalPointer()))
 
1325
                if (item->rtti() == AbstractItem::Type_AttachmentItem)
 
1326
                {
 
1327
                    static_cast <AttachmentItem*> (item)->setAttIsPassthrough (aValue.toBool());
 
1328
                    emit dataChanged (aIndex, aIndex);
 
1329
                    return true;
 
1330
                }
 
1331
            return false;
 
1332
        }
 
1333
        default:
 
1334
            break;
 
1335
    }
 
1336
 
 
1337
    return false;
 
1338
}
 
1339
 
 
1340
QModelIndex StorageModel::addController (const QString &aCtrName, KStorageBus aBusType, KStorageControllerType aCtrType)
 
1341
{
 
1342
    beginInsertRows (root(), mRootItem->childCount(), mRootItem->childCount());
 
1343
    new ControllerItem (mRootItem, aCtrName, aBusType, aCtrType);
 
1344
    endInsertRows();
 
1345
    return index (mRootItem->childCount() - 1, 0, root());
 
1346
}
 
1347
 
 
1348
void StorageModel::delController (const QUuid &aCtrId)
 
1349
{
 
1350
    if (AbstractItem *item = mRootItem->childById (aCtrId))
 
1351
    {
 
1352
        int itemPosition = mRootItem->posOfChild (item);
 
1353
        beginRemoveRows (root(), itemPosition, itemPosition);
 
1354
        delete item;
 
1355
        endRemoveRows();
 
1356
    }
 
1357
}
 
1358
 
 
1359
QModelIndex StorageModel::addAttachment (const QUuid &aCtrId, KDeviceType aDeviceType, bool aVerbose)
 
1360
{
 
1361
    if (AbstractItem *parent = mRootItem->childById (aCtrId))
 
1362
    {
 
1363
        int parentPosition = mRootItem->posOfChild (parent);
 
1364
        QModelIndex parentIndex = index (parentPosition, 0, root());
 
1365
        beginInsertRows (parentIndex, parent->childCount(), parent->childCount());
 
1366
        new AttachmentItem (parent, aDeviceType, aVerbose);
 
1367
        endInsertRows();
 
1368
        return index (parent->childCount() - 1, 0, parentIndex);
 
1369
    }
 
1370
    return QModelIndex();
 
1371
}
 
1372
 
 
1373
void StorageModel::delAttachment (const QUuid &aCtrId, const QUuid &aAttId)
 
1374
{
 
1375
    if (AbstractItem *parent = mRootItem->childById (aCtrId))
 
1376
    {
 
1377
        int parentPosition = mRootItem->posOfChild (parent);
 
1378
        if (AbstractItem *item = parent->childById (aAttId))
 
1379
        {
 
1380
            int itemPosition = parent->posOfChild (item);
 
1381
            beginRemoveRows (index (parentPosition, 0, root()), itemPosition, itemPosition);
 
1382
            delete item;
 
1383
            endRemoveRows();
 
1384
        }
 
1385
    }
 
1386
}
 
1387
 
 
1388
void StorageModel::setMachineId (const QString &aMachineId)
 
1389
{
 
1390
    mRootItem->setMachineId (aMachineId);
 
1391
}
 
1392
 
 
1393
Qt::ItemFlags StorageModel::flags (const QModelIndex &aIndex) const
 
1394
{
 
1395
    return !aIndex.isValid() ? QAbstractItemModel::flags (aIndex) :
 
1396
           Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 
1397
}
 
1398
 
 
1399
/* Storage Delegate */
 
1400
StorageDelegate::StorageDelegate (QObject *aParent)
 
1401
    : QItemDelegate (aParent)
 
1402
{
 
1403
}
 
1404
 
 
1405
void StorageDelegate::paint (QPainter *aPainter, const QStyleOptionViewItem &aOption, const QModelIndex &aIndex) const
 
1406
{
 
1407
    if (!aIndex.isValid()) return;
 
1408
 
 
1409
    /* Initialize variables */
 
1410
    QStyle::State state = aOption.state;
 
1411
    QRect rect = aOption.rect;
 
1412
    const StorageModel *model = qobject_cast <const StorageModel*> (aIndex.model());
 
1413
    Assert (model);
 
1414
 
 
1415
    aPainter->save();
 
1416
 
 
1417
    /* Draw item background */
 
1418
    QItemDelegate::drawBackground (aPainter, aOption, aIndex);
 
1419
 
 
1420
    /* Setup foregroung settings */
 
1421
    QPalette::ColorGroup cg = state & QStyle::State_Active ? QPalette::Active : QPalette::Inactive;
 
1422
    bool isSelected = state & QStyle::State_Selected;
 
1423
    bool isFocused = state & QStyle::State_HasFocus;
 
1424
    bool isGrayOnLoosingFocus = QApplication::style()->styleHint (QStyle::SH_ItemView_ChangeHighlightOnFocus, &aOption) != 0;
 
1425
    aPainter->setPen (aOption.palette.color (cg, isSelected && (isFocused || !isGrayOnLoosingFocus) ?
 
1426
                                             QPalette::HighlightedText : QPalette::Text));
 
1427
 
 
1428
    aPainter->translate (rect.x(), rect.y());
 
1429
 
 
1430
    /* Draw Item Pixmap */
 
1431
    aPainter->drawPixmap (model->data (aIndex, StorageModel::R_ItemPixmapRect).toRect().topLeft(),
 
1432
                          model->data (aIndex, StorageModel::R_ItemPixmap).value <QPixmap>());
 
1433
 
 
1434
    /* Draw compressed item name */
 
1435
    int margin = model->data (aIndex, StorageModel::R_Margin).toInt();
 
1436
    int iconWidth = model->data (aIndex, StorageModel::R_IconSize).toInt();
 
1437
    int spacing = model->data (aIndex, StorageModel::R_Spacing).toInt();
 
1438
    QPoint textPosition = model->data (aIndex, StorageModel::R_ItemNamePoint).toPoint();
 
1439
    int textWidth = rect.width() - textPosition.x();
 
1440
    if (model->data (aIndex, StorageModel::R_IsController).toBool() && state & QStyle::State_Selected)
 
1441
    {
 
1442
        textWidth -= (2 * spacing + iconWidth + margin);
 
1443
        if (model->data (aIndex, StorageModel::R_CtrBusType).value <KStorageBus>() != KStorageBus_Floppy)
 
1444
            textWidth -= (spacing + iconWidth);
 
1445
    }
 
1446
    QString text (model->data (aIndex, StorageModel::R_ItemName).toString());
 
1447
    QString shortText (text);
 
1448
    QFont font = model->data (aIndex, Qt::FontRole).value <QFont>();
 
1449
    QFontMetrics fm (font);
 
1450
    while ((shortText.size() > 1) && (fm.width (shortText) + fm.width ("...") > textWidth))
 
1451
        shortText.truncate (shortText.size() - 1);
 
1452
    if (shortText != text)
 
1453
        shortText += "...";
 
1454
    aPainter->setFont (font);
 
1455
    aPainter->drawText (textPosition, shortText);
 
1456
 
 
1457
    /* Draw Controller Additions */
 
1458
    if (model->data (aIndex, StorageModel::R_IsController).toBool() && state & QStyle::State_Selected)
 
1459
    {
 
1460
        DeviceTypeList devicesList (model->data (aIndex, StorageModel::R_CtrDevices).value <DeviceTypeList>());
 
1461
        for (int i = 0; i < devicesList.size(); ++ i)
 
1462
        {
 
1463
            KDeviceType deviceType = devicesList [i];
 
1464
 
 
1465
            QRect deviceRect;
 
1466
            QPixmap devicePixmap;
 
1467
            switch (deviceType)
 
1468
            {
 
1469
                case KDeviceType_HardDisk:
 
1470
                {
 
1471
                    deviceRect = model->data (aIndex, StorageModel::R_HDPixmapRect).value <QRect>();
 
1472
                    devicePixmap = model->data (aIndex, StorageModel::R_IsMoreAttachmentsPossible).toBool() ?
 
1473
                                   model->data (aIndex, StorageModel::R_HDPixmapAddEn).value <QPixmap>() :
 
1474
                                   model->data (aIndex, StorageModel::R_HDPixmapAddDis).value <QPixmap>();
 
1475
                    break;
 
1476
                }
 
1477
                case KDeviceType_DVD:
 
1478
                {
 
1479
                    deviceRect = model->data (aIndex, StorageModel::R_CDPixmapRect).value <QRect>();
 
1480
                    devicePixmap = model->data (aIndex, StorageModel::R_IsMoreAttachmentsPossible).toBool() ?
 
1481
                                   model->data (aIndex, StorageModel::R_CDPixmapAddEn).value <QPixmap>() :
 
1482
                                   model->data (aIndex, StorageModel::R_CDPixmapAddDis).value <QPixmap>();
 
1483
                    break;
 
1484
                }
 
1485
                case KDeviceType_Floppy:
 
1486
                {
 
1487
                    deviceRect = model->data (aIndex, StorageModel::R_FDPixmapRect).value <QRect>();
 
1488
                    devicePixmap = model->data (aIndex, StorageModel::R_IsMoreAttachmentsPossible).toBool() ?
 
1489
                                   model->data (aIndex, StorageModel::R_FDPixmapAddEn).value <QPixmap>() :
 
1490
                                   model->data (aIndex, StorageModel::R_FDPixmapAddDis).value <QPixmap>();
 
1491
                    break;
 
1492
                }
 
1493
                default:
 
1494
                    break;
 
1495
            }
 
1496
 
 
1497
            aPainter->drawPixmap (QPoint (rect.width() + deviceRect.x(), deviceRect.y()), devicePixmap);
 
1498
        }
 
1499
    }
 
1500
 
 
1501
    aPainter->restore();
 
1502
 
 
1503
    drawFocus (aPainter, aOption, rect);
 
1504
}
 
1505
 
 
1506
/**
 
1507
 * QWidget class reimplementation.
 
1508
 * Used as HD Settings widget.
 
1509
 */
 
1510
VBoxVMSettingsHD::VBoxVMSettingsHD()
 
1511
    : mValidator (0)
 
1512
    , mIsPolished (false)
 
1513
{
 
1514
    /* Apply UI decorations */
 
1515
    Ui::VBoxVMSettingsHD::setupUi (this);
 
1516
 
 
1517
    /* Enumerate Mediums */
 
1518
    vboxGlobal().startEnumeratingMedia();
 
1519
 
 
1520
    /* Initialize pixmap pool */
 
1521
    PixmapPool::pool (this);
 
1522
 
 
1523
    /* Controller Actions */
 
1524
    mAddCtrAction = new QAction (this);
 
1525
    mAddCtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::ControllerAddEn),
 
1526
                                                 PixmapPool::pool()->pixmap (PixmapPool::ControllerAddDis)));
 
1527
 
 
1528
    mAddIDECtrAction = new QAction (this);
 
1529
    mAddIDECtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::IDEControllerAddEn),
 
1530
                                                    PixmapPool::pool()->pixmap (PixmapPool::IDEControllerAddDis)));
 
1531
 
 
1532
    mAddSATACtrAction = new QAction (this);
 
1533
    mAddSATACtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::SATAControllerAddEn),
 
1534
                                                     PixmapPool::pool()->pixmap (PixmapPool::SATAControllerAddDis)));
 
1535
 
 
1536
    mAddSCSICtrAction = new QAction (this);
 
1537
    mAddSCSICtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::SCSIControllerAddEn),
 
1538
                                                     PixmapPool::pool()->pixmap (PixmapPool::SCSIControllerAddDis)));
 
1539
 
 
1540
    mAddFloppyCtrAction = new QAction (this);
 
1541
    mAddFloppyCtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::FloppyControllerAddEn),
 
1542
                                                       PixmapPool::pool()->pixmap (PixmapPool::FloppyControllerAddDis)));
 
1543
 
 
1544
    mDelCtrAction = new QAction (this);
 
1545
    mDelCtrAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::ControllerDelEn),
 
1546
                                                 PixmapPool::pool()->pixmap (PixmapPool::ControllerDelDis)));
 
1547
 
 
1548
    /* Attachment Actions */
 
1549
    mAddAttAction = new QAction (this);
 
1550
    mAddAttAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::AttachmentAddEn),
 
1551
                                                 PixmapPool::pool()->pixmap (PixmapPool::AttachmentAddDis)));
 
1552
 
 
1553
    mAddHDAttAction = new QAction (this);
 
1554
    mAddHDAttAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentAddEn),
 
1555
                                                   PixmapPool::pool()->pixmap (PixmapPool::HDAttachmentAddDis)));
 
1556
 
 
1557
    mAddCDAttAction = new QAction (this);
 
1558
    mAddCDAttAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentAddEn),
 
1559
                                                   PixmapPool::pool()->pixmap (PixmapPool::CDAttachmentAddDis)));
 
1560
 
 
1561
    mAddFDAttAction = new QAction (this);
 
1562
    mAddFDAttAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentAddEn),
 
1563
                                                   PixmapPool::pool()->pixmap (PixmapPool::FDAttachmentAddDis)));
 
1564
 
 
1565
    mDelAttAction = new QAction (this);
 
1566
    mDelAttAction->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::AttachmentDelEn),
 
1567
                                                 PixmapPool::pool()->pixmap (PixmapPool::AttachmentDelDis)));
 
1568
 
 
1569
    /* Storage Model/View */
 
1570
    mStorageModel = new StorageModel (mTwStorageTree);
 
1571
    StorageDelegate *storageDelegate = new StorageDelegate (mTwStorageTree);
 
1572
    mTwStorageTree->setMouseTracking (true);
 
1573
    mTwStorageTree->setContextMenuPolicy (Qt::CustomContextMenu);
 
1574
    mTwStorageTree->setModel (mStorageModel);
 
1575
    mTwStorageTree->setItemDelegate (storageDelegate);
 
1576
    mTwStorageTree->setRootIndex (mStorageModel->root());
 
1577
    mTwStorageTree->setCurrentIndex (mStorageModel->root());
 
1578
 
 
1579
    /* Storage ToolBar */
 
1580
    mTbStorageBar->setIconSize (QSize (16, 16));
 
1581
    mTbStorageBar->addAction (mAddAttAction);
 
1582
    mTbStorageBar->addAction (mDelAttAction);
 
1583
    mTbStorageBar->addAction (mAddCtrAction);
 
1584
    mTbStorageBar->addAction (mDelCtrAction);
 
1585
 
 
1586
#ifdef Q_WS_MAC
 
1587
    /* We need a little more space for the focus rect. */
 
1588
    mLtStorage->setContentsMargins (3, 0, 3, 0);
 
1589
    mLtStorage->setSpacing (3);
 
1590
#endif /* Q_WS_MAC */
 
1591
 
 
1592
    /* Vdi Combo */
 
1593
    mCbVdi->setNullItemPresent (true);
 
1594
    mCbVdi->refresh();
 
1595
 
 
1596
    /* Vmm Button */
 
1597
    mTbVmm->setIcon (VBoxGlobal::iconSet (PixmapPool::pool()->pixmap (PixmapPool::VMMEn),
 
1598
                                          PixmapPool::pool()->pixmap (PixmapPool::VMMDis)));
 
1599
 
 
1600
    /* Info Pane initialization */
 
1601
    mLbHDVirtualSizeValue->setFullSizeSelection (true);
 
1602
    mLbHDActualSizeValue->setFullSizeSelection (true);
 
1603
    mLbSizeValue->setFullSizeSelection (true);
 
1604
    mLbLocationValue->setFullSizeSelection (true);
 
1605
    mLbHDFormatValue->setFullSizeSelection (true);
 
1606
    mLbUsageValue->setFullSizeSelection (true);
 
1607
 
 
1608
    /* Setup connections */
 
1609
    connect (&vboxGlobal(), SIGNAL (mediumEnumerated (const VBoxMedium &)),
 
1610
             this, SLOT (mediumUpdated (const VBoxMedium &)));
 
1611
    connect (&vboxGlobal(), SIGNAL (mediumUpdated (const VBoxMedium &)),
 
1612
             this, SLOT (mediumUpdated (const VBoxMedium &)));
 
1613
    connect (&vboxGlobal(), SIGNAL (mediumRemoved (VBoxDefs::MediumType, const QString &)),
 
1614
             this, SLOT (mediumRemoved (VBoxDefs::MediumType, const QString &)));
 
1615
    connect (mAddCtrAction, SIGNAL (triggered (bool)), this, SLOT (addController()));
 
1616
    connect (mAddIDECtrAction, SIGNAL (triggered (bool)), this, SLOT (addIDEController()));
 
1617
    connect (mAddSATACtrAction, SIGNAL (triggered (bool)), this, SLOT (addSATAController()));
 
1618
    connect (mAddSCSICtrAction, SIGNAL (triggered (bool)), this, SLOT (addSCSIController()));
 
1619
    connect (mAddFloppyCtrAction, SIGNAL (triggered (bool)), this, SLOT (addFloppyController()));
 
1620
    connect (mDelCtrAction, SIGNAL (triggered (bool)), this, SLOT (delController()));
 
1621
    connect (mAddAttAction, SIGNAL (triggered (bool)), this, SLOT (addAttachment()));
 
1622
    connect (mAddHDAttAction, SIGNAL (triggered (bool)), this, SLOT (addHDAttachment()));
 
1623
    connect (mAddCDAttAction, SIGNAL (triggered (bool)), this, SLOT (addCDAttachment()));
 
1624
    connect (mAddFDAttAction, SIGNAL (triggered (bool)), this, SLOT (addFDAttachment()));
 
1625
    connect (mDelAttAction, SIGNAL (triggered (bool)), this, SLOT (delAttachment()));
 
1626
    connect (mStorageModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
 
1627
             this, SLOT (onRowInserted (const QModelIndex&, int)));
 
1628
    connect (mStorageModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
 
1629
             this, SLOT (onRowRemoved()));
 
1630
    connect (mTwStorageTree, SIGNAL (currentItemChanged (const QModelIndex&, const QModelIndex&)),
 
1631
             this, SLOT (onCurrentItemChanged()));
 
1632
    connect (mTwStorageTree, SIGNAL (customContextMenuRequested (const QPoint&)),
 
1633
             this, SLOT (onContextMenuRequested (const QPoint&)));
 
1634
    connect (mTwStorageTree, SIGNAL (drawItemBranches (QPainter*, const QRect&, const QModelIndex&)),
 
1635
             this, SLOT (onDrawItemBranches (QPainter *, const QRect &, const QModelIndex &)));
 
1636
    connect (mTwStorageTree, SIGNAL (mouseMoved (QMouseEvent*)),
 
1637
             this, SLOT (onMouseMoved (QMouseEvent*)));
 
1638
    connect (mTwStorageTree, SIGNAL (mousePressed (QMouseEvent*)),
 
1639
             this, SLOT (onMouseClicked (QMouseEvent*)));
 
1640
    connect (mTwStorageTree, SIGNAL (mouseDoubleClicked (QMouseEvent*)),
 
1641
             this, SLOT (onMouseClicked (QMouseEvent*)));
 
1642
    connect (mLeName, SIGNAL (textEdited (const QString&)), this, SLOT (setInformation()));
 
1643
    connect (mCbType, SIGNAL (activated (int)), this, SLOT (setInformation()));
 
1644
    connect (mCbSlot, SIGNAL (activated (int)), this, SLOT (setInformation()));
 
1645
    connect (mCbVdi, SIGNAL (activated (int)), this, SLOT (setInformation()));
 
1646
    connect (mTbVmm, SIGNAL (clicked (bool)), this, SLOT (onVmmInvoked()));
 
1647
    connect (mCbShowDiffs, SIGNAL (stateChanged (int)), this, SLOT (setInformation()));
 
1648
    connect (mCbPassthrough, SIGNAL (stateChanged (int)), this, SLOT (setInformation()));
 
1649
 
 
1650
    /* Update actions */
 
1651
    updateActionsState();
 
1652
 
 
1653
    /* Applying language settings */
 
1654
    retranslateUi();
 
1655
 
 
1656
    /* Initial setup */
 
1657
    setMinimumWidth (500);
 
1658
    mSplitter->setSizes (QList<int>() << (int) (0.45 * minimumWidth()) << (int) (0.55 * minimumWidth()));
 
1659
}
 
1660
 
 
1661
void VBoxVMSettingsHD::getFrom (const CMachine &aMachine)
 
1662
{
 
1663
    mMachine = aMachine;
 
1664
 
 
1665
    /* Set the machine id for the media-combo */
 
1666
    mCbVdi->setMachineId (mMachine.GetId());
 
1667
    mStorageModel->setMachineId (mMachine.GetId());
 
1668
 
 
1669
    /* Load currently present controllers & attachments */
 
1670
    CStorageControllerVector controllers = mMachine.GetStorageControllers();
 
1671
    foreach (const CStorageController &controller, controllers)
 
1672
    {
 
1673
        QString controllerName = controller.GetName();
 
1674
        QModelIndex ctrIndex = mStorageModel->addController (controllerName, controller.GetBus(), controller.GetControllerType());
 
1675
        QUuid ctrId = QUuid (mStorageModel->data (ctrIndex, StorageModel::R_ItemId).toString());
 
1676
 
 
1677
        CMediumAttachmentVector attachments = mMachine.GetMediumAttachmentsOfController (controllerName);
 
1678
        foreach (const CMediumAttachment &attachment, attachments)
 
1679
        {
 
1680
            QModelIndex attIndex = mStorageModel->addAttachment (ctrId, attachment.GetType(), false);
 
1681
            mStorageModel->setData (attIndex, QVariant::fromValue (StorageSlot (controller.GetBus(), attachment.GetPort(), attachment.GetDevice())), StorageModel::R_AttSlot);
 
1682
            CMedium medium (attachment.GetMedium());
 
1683
            VBoxMedium vboxMedium;
 
1684
            vboxGlobal().findMedium (medium, vboxMedium);
 
1685
            mStorageModel->setData (attIndex, vboxMedium.id(), StorageModel::R_AttMediumId);
 
1686
            mStorageModel->setData (attIndex, attachment.GetPassthrough(), StorageModel::R_AttIsPassthrough);
 
1687
        }
 
1688
    }
 
1689
 
 
1690
    /* Set the first controller as current if present */
 
1691
    if (mStorageModel->rowCount (mStorageModel->root()) > 0)
 
1692
        mTwStorageTree->setCurrentIndex (mStorageModel->index (0, 0, mStorageModel->root()));
 
1693
}
 
1694
 
 
1695
void VBoxVMSettingsHD::putBackTo()
 
1696
{
 
1697
    /* Remove currently present controllers & attachments */
 
1698
    CStorageControllerVector controllers = mMachine.GetStorageControllers();
 
1699
    foreach (const CStorageController &controller, controllers)
 
1700
    {
 
1701
        QString controllerName (controller.GetName());
 
1702
        CMediumAttachmentVector attachments = mMachine.GetMediumAttachmentsOfController (controllerName);
 
1703
        foreach (const CMediumAttachment &attachment, attachments)
 
1704
            mMachine.DetachDevice (controllerName, attachment.GetPort(), attachment.GetDevice());
 
1705
        mMachine.RemoveStorageController (controllerName);
 
1706
    }
 
1707
 
 
1708
    /* Save created controllers & attachments */
 
1709
    QModelIndex rootIndex = mStorageModel->root();
 
1710
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
1711
    {
 
1712
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
1713
        QString ctrName = mStorageModel->data (ctrIndex, StorageModel::R_CtrName).toString();
 
1714
        KStorageBus ctrBusType = mStorageModel->data (ctrIndex, StorageModel::R_CtrBusType).value <KStorageBus>();
 
1715
        KStorageControllerType ctrType = mStorageModel->data (ctrIndex, StorageModel::R_CtrType).value <KStorageControllerType>();
 
1716
        CStorageController ctr = mMachine.AddStorageController (ctrName, ctrBusType);
 
1717
        ctr.SetControllerType (ctrType);
 
1718
        int maxUsedPort = -1;
 
1719
        for (int j = 0; j < mStorageModel->rowCount (ctrIndex); ++ j)
 
1720
        {
 
1721
            QModelIndex attIndex = ctrIndex.child (j, 0);
 
1722
            StorageSlot attStorageSlot = mStorageModel->data (attIndex, StorageModel::R_AttSlot).value <StorageSlot>();
 
1723
            KDeviceType attDeviceType = mStorageModel->data (attIndex, StorageModel::R_AttDevice).value <KDeviceType>();
 
1724
            QString attMediumId = mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString();
 
1725
            mMachine.AttachDevice (ctrName, attStorageSlot.port, attStorageSlot.device, attDeviceType, attMediumId);
 
1726
            if (attDeviceType == KDeviceType_DVD)
 
1727
                mMachine.PassthroughDevice (ctrName, attStorageSlot.port, attStorageSlot.device,
 
1728
                                            mStorageModel->data (attIndex, StorageModel::R_AttIsPassthrough).toBool());
 
1729
            maxUsedPort = attStorageSlot.port > maxUsedPort ? attStorageSlot.port : maxUsedPort;
 
1730
        }
 
1731
        if (ctrBusType == KStorageBus_SATA)
 
1732
        {
 
1733
            ULONG sataPortsCount = maxUsedPort + 1;
 
1734
            sataPortsCount = qMax (sataPortsCount, ctr.GetMinPortCount());
 
1735
            sataPortsCount = qMin (sataPortsCount, ctr.GetMaxPortCount());
 
1736
            ctr.SetPortCount (sataPortsCount);
 
1737
        }
 
1738
    }
 
1739
}
 
1740
 
 
1741
void VBoxVMSettingsHD::setValidator (QIWidgetValidator *aVal)
 
1742
{
 
1743
    mValidator = aVal;
 
1744
}
 
1745
 
 
1746
bool VBoxVMSettingsHD::revalidate (QString &aWarning, QString &)
 
1747
{
 
1748
    QModelIndex rootIndex = mStorageModel->root();
 
1749
    QMap <QString, QString> config;
 
1750
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
1751
    {
 
1752
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
1753
        QString ctrName = mStorageModel->data (ctrIndex, StorageModel::R_CtrName).toString();
 
1754
        for (int j = 0; j < mStorageModel->rowCount (ctrIndex); ++ j)
 
1755
        {
 
1756
            QModelIndex attIndex = ctrIndex.child (j, 0);
 
1757
            StorageSlot attSlot = mStorageModel->data (attIndex, StorageModel::R_AttSlot).value <StorageSlot>();
 
1758
            KDeviceType attDevice = mStorageModel->data (attIndex, StorageModel::R_AttDevice).value <KDeviceType>();
 
1759
            QString key (mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString());
 
1760
            QString value (QString ("%1 (%2)").arg (ctrName, vboxGlobal().toString (attSlot)));
 
1761
            /* Check for emptiness */
 
1762
            if (vboxGlobal().findMedium (key).isNull() && attDevice == KDeviceType_HardDisk)
 
1763
            {
 
1764
                aWarning = tr ("No hard disk is selected for <i>%1</i>.").arg (value);
 
1765
                return aWarning.isNull();
 
1766
            }
 
1767
            /* Check for coincidence */
 
1768
            if (!vboxGlobal().findMedium (key).isNull() && config.contains (key))
 
1769
            {
 
1770
                aWarning = tr ("<i>%1</i> uses a medium that is already attached to <i>%2</i>.")
 
1771
                              .arg (value).arg (config [key]);
 
1772
                return aWarning.isNull();
 
1773
            }
 
1774
            else config.insert (key, value);
 
1775
        }
 
1776
    }
 
1777
    return aWarning.isNull();
 
1778
}
 
1779
 
 
1780
void VBoxVMSettingsHD::retranslateUi()
 
1781
{
 
1782
    /* Translate uic generated strings */
 
1783
    Ui::VBoxVMSettingsHD::retranslateUi (this);
 
1784
 
 
1785
    mAddCtrAction->setShortcut (QKeySequence ("Ins"));
 
1786
    mDelCtrAction->setShortcut (QKeySequence ("Del"));
 
1787
    mAddAttAction->setShortcut (QKeySequence ("+"));
 
1788
    mDelAttAction->setShortcut (QKeySequence ("-"));
 
1789
 
 
1790
    mAddCtrAction->setText (tr ("Add Controller"));
 
1791
    mAddIDECtrAction->setText (tr ("Add IDE Controller"));
 
1792
    mAddSATACtrAction->setText (tr ("Add SATA Controller"));
 
1793
    mAddSCSICtrAction->setText (tr ("Add SCSI Controller"));
 
1794
    mAddFloppyCtrAction->setText (tr ("Add Floppy Controller"));
 
1795
    mDelCtrAction->setText (tr ("Remove Controller"));
 
1796
    mAddAttAction->setText (tr ("Add Attachment"));
 
1797
    mAddHDAttAction->setText (tr ("Add Hard Disk"));
 
1798
    mAddCDAttAction->setText (tr ("Add CD/DVD Device"));
 
1799
    mAddFDAttAction->setText (tr ("Add Floppy Device"));
 
1800
    mDelAttAction->setText (tr ("Remove Attachment"));
 
1801
 
 
1802
    mAddCtrAction->setWhatsThis (tr ("Adds a new controller to the end of the Storage Tree."));
 
1803
    mDelCtrAction->setWhatsThis (tr ("Removes the controller highlighted in the Storage Tree."));
 
1804
    mAddAttAction->setWhatsThis (tr ("Adds a new attachment to the Storage Tree using "
 
1805
                                     "currently selected controller as parent."));
 
1806
    mDelAttAction->setWhatsThis (tr ("Removes the attachment highlighted in the Storage Tree."));
 
1807
 
 
1808
    mAddCtrAction->setToolTip (QString ("<nobr>%1&nbsp;(%2)")
 
1809
                               .arg (mAddCtrAction->text().remove ('&'))
 
1810
                               .arg (mAddCtrAction->shortcut().toString()));
 
1811
    mDelCtrAction->setToolTip (QString ("<nobr>%1&nbsp;(%2)")
 
1812
                               .arg (mDelCtrAction->text().remove ('&'))
 
1813
                               .arg (mDelCtrAction->shortcut().toString()));
 
1814
    mAddAttAction->setToolTip (QString ("<nobr>%1&nbsp;(%2)")
 
1815
                               .arg (mAddAttAction->text().remove ('&'))
 
1816
                               .arg (mAddAttAction->shortcut().toString()));
 
1817
    mDelAttAction->setToolTip (QString ("<nobr>%1&nbsp;(%2)")
 
1818
                               .arg (mDelAttAction->text().remove ('&'))
 
1819
                               .arg (mDelAttAction->shortcut().toString()));
 
1820
}
 
1821
 
 
1822
void VBoxVMSettingsHD::showEvent (QShowEvent *aEvent)
 
1823
{
 
1824
    if (!mIsPolished)
 
1825
    {
 
1826
        mIsPolished = true;
 
1827
 
 
1828
        /* First column indent */
 
1829
        mLtEmpty->setColumnMinimumWidth (0, 10);
 
1830
        mLtController->setColumnMinimumWidth (0, 10);
 
1831
        mLtAttachment->setColumnMinimumWidth (0, 10);
 
1832
#if 0
 
1833
        /* Second column indent minimum width */
 
1834
        QList <QLabel*> labelsList;
 
1835
        labelsList << mLbSlot << mLbVdi
 
1836
                   << mLbHDVirtualSize << mLbHDActualSize << mLbSize
 
1837
                   << mLbLocation << mLbHDFormat << mLbUsage;
 
1838
        int maxWidth = 0;
 
1839
        QFontMetrics metrics (font());
 
1840
        foreach (QLabel *label, labelsList)
 
1841
        {
 
1842
            int width = metrics.width (label->text());
 
1843
            maxWidth = width > maxWidth ? width : maxWidth;
 
1844
        }
 
1845
        mLtAttachment->setColumnMinimumWidth (1, maxWidth);
 
1846
#endif
 
1847
    }
 
1848
    VBoxSettingsPage::showEvent (aEvent);
 
1849
}
 
1850
 
 
1851
void VBoxVMSettingsHD::mediumUpdated (const VBoxMedium &aMedium)
 
1852
{
 
1853
    QModelIndex rootIndex = mStorageModel->root();
 
1854
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
1855
    {
 
1856
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
1857
        for (int j = 0; j < mStorageModel->rowCount (ctrIndex); ++ j)
 
1858
        {
 
1859
            QModelIndex attIndex = ctrIndex.child (j, 0);
 
1860
            QString attMediumId = mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString();
 
1861
            if (attMediumId == aMedium.id())
 
1862
            {
 
1863
                mStorageModel->setData (attIndex, attMediumId, StorageModel::R_AttMediumId);
 
1864
                if (mValidator) mValidator->revalidate();
 
1865
            }
 
1866
        }
 
1867
    }
 
1868
}
 
1869
 
 
1870
void VBoxVMSettingsHD::mediumRemoved (VBoxDefs::MediumType /* aType */, const QString &aMediumId)
 
1871
{
 
1872
    QModelIndex rootIndex = mStorageModel->root();
 
1873
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
1874
    {
 
1875
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
1876
        for (int j = 0; j < mStorageModel->rowCount (ctrIndex); ++ j)
 
1877
        {
 
1878
            QModelIndex attIndex = ctrIndex.child (j, 0);
 
1879
            QString attMediumId = mStorageModel->data (attIndex, StorageModel::R_AttMediumId).toString();
 
1880
            if (attMediumId == aMediumId)
 
1881
            {
 
1882
                mStorageModel->setData (attIndex, firstAvailableId, StorageModel::R_AttMediumId);
 
1883
                if (mValidator) mValidator->revalidate();
 
1884
            }
 
1885
        }
 
1886
    }
 
1887
}
 
1888
 
 
1889
void VBoxVMSettingsHD::addController()
 
1890
{
 
1891
    QMenu menu;
 
1892
    menu.addAction (mAddIDECtrAction);
 
1893
    menu.addAction (mAddSATACtrAction);
 
1894
    menu.addAction (mAddSCSICtrAction);
 
1895
    menu.addAction (mAddFloppyCtrAction);
 
1896
    menu.exec (QCursor::pos());
 
1897
}
 
1898
 
 
1899
void VBoxVMSettingsHD::addIDEController()
 
1900
{
 
1901
    addControllerWrapper (generateUniqueName (tr ("IDE Controller")), KStorageBus_IDE, KStorageControllerType_PIIX4);
 
1902
}
 
1903
 
 
1904
void VBoxVMSettingsHD::addSATAController()
 
1905
{
 
1906
    addControllerWrapper (generateUniqueName (tr ("SATA Controller")), KStorageBus_SATA, KStorageControllerType_IntelAhci);
 
1907
}
 
1908
 
 
1909
void VBoxVMSettingsHD::addSCSIController()
 
1910
{
 
1911
    addControllerWrapper (generateUniqueName (tr ("SCSI Controller")), KStorageBus_SCSI, KStorageControllerType_LsiLogic);
 
1912
}
 
1913
 
 
1914
void VBoxVMSettingsHD::addFloppyController()
 
1915
{
 
1916
    addControllerWrapper (generateUniqueName (tr ("Floppy Controller")), KStorageBus_Floppy, KStorageControllerType_I82078);
 
1917
}
 
1918
 
 
1919
void VBoxVMSettingsHD::delController()
 
1920
{
 
1921
    QModelIndex index = mTwStorageTree->currentIndex();
 
1922
    if (!mStorageModel->data (index, StorageModel::R_IsController).toBool()) return;
 
1923
 
 
1924
    mStorageModel->delController (QUuid (mStorageModel->data (index, StorageModel::R_ItemId).toString()));
 
1925
    emit storageChanged();
 
1926
    if (mValidator) mValidator->revalidate();
 
1927
}
 
1928
 
 
1929
void VBoxVMSettingsHD::addAttachment()
 
1930
{
 
1931
    QModelIndex index = mTwStorageTree->currentIndex();
 
1932
    Assert (mStorageModel->data (index, StorageModel::R_IsController).toBool());
 
1933
 
 
1934
    DeviceTypeList deviceTypeList (mStorageModel->data (index, StorageModel::R_CtrDevices).value <DeviceTypeList>());
 
1935
    bool justTrigger = deviceTypeList.size() == 1;
 
1936
    bool showMenu = deviceTypeList.size() > 1;
 
1937
    QMenu menu;
 
1938
    foreach (const KDeviceType &deviceType, deviceTypeList)
 
1939
    {
 
1940
        switch (deviceType)
 
1941
        {
 
1942
            case KDeviceType_HardDisk:
 
1943
                if (justTrigger)
 
1944
                    mAddHDAttAction->trigger();
 
1945
                if (showMenu)
 
1946
                    menu.addAction (mAddHDAttAction);
 
1947
                break;
 
1948
            case KDeviceType_DVD:
 
1949
                if (justTrigger)
 
1950
                    mAddCDAttAction->trigger();
 
1951
                if (showMenu)
 
1952
                    menu.addAction (mAddCDAttAction);
 
1953
                break;
 
1954
            case KDeviceType_Floppy:
 
1955
                if (justTrigger)
 
1956
                    mAddFDAttAction->trigger();
 
1957
                if (showMenu)
 
1958
                    menu.addAction (mAddFDAttAction);
 
1959
                break;
 
1960
            default:
 
1961
                break;
 
1962
        }
 
1963
    }
 
1964
    if (showMenu)
 
1965
        menu.exec (QCursor::pos());
 
1966
}
 
1967
 
 
1968
void VBoxVMSettingsHD::addHDAttachment()
 
1969
{
 
1970
    addAttachmentWrapper (KDeviceType_HardDisk);
 
1971
}
 
1972
 
 
1973
void VBoxVMSettingsHD::addCDAttachment()
 
1974
{
 
1975
    addAttachmentWrapper (KDeviceType_DVD);
 
1976
}
 
1977
 
 
1978
void VBoxVMSettingsHD::addFDAttachment()
 
1979
{
 
1980
    addAttachmentWrapper (KDeviceType_Floppy);
 
1981
}
 
1982
 
 
1983
void VBoxVMSettingsHD::delAttachment()
 
1984
{
 
1985
    QModelIndex index = mTwStorageTree->currentIndex();
 
1986
 
 
1987
    KDeviceType device = mStorageModel->data (index, StorageModel::R_AttDevice).value <KDeviceType>();
 
1988
    /* Check if this would be the last DVD. If so let the user confirm this again. */
 
1989
    if (   device == KDeviceType_DVD
 
1990
        && deviceCount (KDeviceType_DVD) == 1)
 
1991
    {
 
1992
        if (vboxProblem().confirmRemovingOfLastDVDDevice() != QIMessageBox::Ok)
 
1993
            return;
 
1994
    }
 
1995
 
 
1996
    QModelIndex parent = index.parent();
 
1997
    if (!index.isValid() || !parent.isValid() ||
 
1998
        !mStorageModel->data (index, StorageModel::R_IsAttachment).toBool() ||
 
1999
        !mStorageModel->data (parent, StorageModel::R_IsController).toBool())
 
2000
        return;
 
2001
 
 
2002
    mStorageModel->delAttachment (QUuid (mStorageModel->data (parent, StorageModel::R_ItemId).toString()),
 
2003
                                  QUuid (mStorageModel->data (index, StorageModel::R_ItemId).toString()));
 
2004
    emit storageChanged();
 
2005
    if (mValidator) mValidator->revalidate();
 
2006
}
 
2007
 
 
2008
void VBoxVMSettingsHD::getInformation()
 
2009
{
 
2010
    mIsLoadingInProgress = true;
 
2011
 
 
2012
    QModelIndex index = mTwStorageTree->currentIndex();
 
2013
    if (!index.isValid() || index == mStorageModel->root())
 
2014
    {
 
2015
        /* Showing Initial Page */
 
2016
        mSwRightPane->setCurrentIndex (0);
 
2017
    }
 
2018
    else
 
2019
    {
 
2020
        switch (mStorageModel->data (index, StorageModel::R_ItemType).value <AbstractItem::ItemType>())
 
2021
        {
 
2022
            case AbstractItem::Type_ControllerItem:
 
2023
            {
 
2024
                /* Getting Controller Name */
 
2025
                mLeName->setText (mStorageModel->data (index, StorageModel::R_CtrName).toString());
 
2026
 
 
2027
                /* Getting Controller Sub type */
 
2028
                mCbType->clear();
 
2029
                ControllerTypeList controllerTypeList (mStorageModel->data (index, StorageModel::R_CtrTypes).value <ControllerTypeList>());
 
2030
                for (int i = 0; i < controllerTypeList.size(); ++ i)
 
2031
                    mCbType->insertItem (mCbType->count(), vboxGlobal().toString (controllerTypeList [i]));
 
2032
                KStorageControllerType type = mStorageModel->data (index, StorageModel::R_CtrType).value <KStorageControllerType>();
 
2033
                int ctrPos = mCbType->findText (vboxGlobal().toString (type));
 
2034
                mCbType->setCurrentIndex (ctrPos == -1 ? 0 : ctrPos);
 
2035
 
 
2036
                /* Showing Controller Page */
 
2037
                mSwRightPane->setCurrentIndex (1);
 
2038
                break;
 
2039
            }
 
2040
            case AbstractItem::Type_AttachmentItem:
 
2041
            {
 
2042
                /* Getting Attachment Slot */
 
2043
                mCbSlot->clear();
 
2044
                SlotsList slotsList (mStorageModel->data (index, StorageModel::R_AttSlots).value <SlotsList>());
 
2045
                for (int i = 0; i < slotsList.size(); ++ i)
 
2046
                    mCbSlot->insertItem (mCbSlot->count(), vboxGlobal().toString (slotsList [i]));
 
2047
                StorageSlot slt = mStorageModel->data (index, StorageModel::R_AttSlot).value <StorageSlot>();
 
2048
                int attSlotPos = mCbSlot->findText (vboxGlobal().toString (slt));
 
2049
                mCbSlot->setCurrentIndex (attSlotPos == -1 ? 0 : attSlotPos);
 
2050
                mCbSlot->setToolTip (mCbSlot->itemText (mCbSlot->currentIndex()));
 
2051
 
 
2052
                /* Getting Show Diffs state */
 
2053
                bool isShowDiffs = mStorageModel->data (index, StorageModel::R_AttIsShowDiffs).toBool();
 
2054
                mCbShowDiffs->setChecked (isShowDiffs);
 
2055
 
 
2056
                /* Getting Attachment Medium */
 
2057
                KDeviceType device = mStorageModel->data (index, StorageModel::R_AttDevice).value <KDeviceType>();
 
2058
                switch (device)
 
2059
                {
 
2060
                    case KDeviceType_HardDisk:
 
2061
                        mLbVdi->setText (tr ("Hard &Disk:"));
 
2062
                        break;
 
2063
                    case KDeviceType_DVD:
 
2064
                        mLbVdi->setText (tr ("&CD/DVD Device:"));
 
2065
                        break;
 
2066
                    case KDeviceType_Floppy:
 
2067
                        mLbVdi->setText (tr ("&Floppy Device:"));
 
2068
                        break;
 
2069
                    default:
 
2070
                        break;
 
2071
                }
 
2072
                mCbVdi->setType (typeToLocal (device));
 
2073
                mCbVdi->setShowDiffs (isShowDiffs);
 
2074
                mCbVdi->setCurrentItem (mStorageModel->data (index, StorageModel::R_AttMediumId).toString());
 
2075
                mCbVdi->refresh();
 
2076
 
 
2077
                /* Getting Passthrough state */
 
2078
                bool isHostDrive = mStorageModel->data (index, StorageModel::R_AttIsHostDrive).toBool();
 
2079
                /* Passthrough is currently available only for the IDE controller DVD device */
 
2080
                bool isIdeCtr = mStorageModel->data (index.parent(), StorageModel::R_CtrBusType).value <KStorageBus>() == KStorageBus_IDE;
 
2081
                mCbPassthrough->setEnabled (isHostDrive && isIdeCtr);
 
2082
                mCbPassthrough->setChecked (isHostDrive && isIdeCtr && mStorageModel->data (index, StorageModel::R_AttIsPassthrough).toBool());
 
2083
 
 
2084
                /* Update optional widgets visibility */
 
2085
                updateAdditionalObjects (device);
 
2086
 
 
2087
                /* Getting Other Information */
 
2088
                mLbHDVirtualSizeValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttLogicalSize).toString()));
 
2089
                mLbHDActualSizeValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttSize).toString()));
 
2090
                mLbSizeValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttSize).toString()));
 
2091
                mLbLocationValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttLocation).toString()));
 
2092
                mLbHDFormatValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttFormat).toString()));
 
2093
                mLbUsageValue->setText (compressText (mStorageModel->data (index, StorageModel::R_AttUsage).toString()));
 
2094
 
 
2095
                /* Showing Attachment Page */
 
2096
                mSwRightPane->setCurrentIndex (2);
 
2097
                break;
 
2098
            }
 
2099
            default:
 
2100
                break;
 
2101
        }
 
2102
    }
 
2103
 
 
2104
    if (mValidator) mValidator->revalidate();
 
2105
 
 
2106
    mIsLoadingInProgress = false;
 
2107
}
 
2108
 
 
2109
void VBoxVMSettingsHD::setInformation()
 
2110
{
 
2111
    QModelIndex index = mTwStorageTree->currentIndex();
 
2112
    if (mIsLoadingInProgress || !index.isValid() || index == mStorageModel->root()) return;
 
2113
 
 
2114
    QObject *sdr = sender();
 
2115
    switch (mStorageModel->data (index, StorageModel::R_ItemType).value <AbstractItem::ItemType>())
 
2116
    {
 
2117
        case AbstractItem::Type_ControllerItem:
 
2118
        {
 
2119
            /* Setting Controller Name */
 
2120
            if (sdr == mLeName)
 
2121
                mStorageModel->setData (index, mLeName->text(), StorageModel::R_CtrName);
 
2122
            /* Setting Controller Sub-Type */
 
2123
            else if (sdr == mCbType)
 
2124
                mStorageModel->setData (index, QVariant::fromValue (vboxGlobal().toControllerType (mCbType->currentText())),
 
2125
                                        StorageModel::R_CtrType);
 
2126
            break;
 
2127
        }
 
2128
        case AbstractItem::Type_AttachmentItem:
 
2129
        {
 
2130
            /* Setting Attachment Slot */
 
2131
            if (sdr == mCbSlot)
 
2132
                mStorageModel->setData (index, QVariant::fromValue (vboxGlobal().toStorageSlot (mCbSlot->currentText())),
 
2133
                                        StorageModel::R_AttSlot);
 
2134
            /* Setting Attachment Medium */
 
2135
            else if (sdr == mCbVdi)
 
2136
                mStorageModel->setData (index, mCbVdi->id(), StorageModel::R_AttMediumId);
 
2137
            else if (sdr == mCbShowDiffs)
 
2138
                mStorageModel->setData (index, mCbShowDiffs->isChecked(), StorageModel::R_AttIsShowDiffs);
 
2139
            else if (sdr == mCbPassthrough)
 
2140
            {
 
2141
                if (mStorageModel->data (index, StorageModel::R_AttIsHostDrive).toBool())
 
2142
                    mStorageModel->setData (index, mCbPassthrough->isChecked(), StorageModel::R_AttIsPassthrough);
 
2143
            }
 
2144
            break;
 
2145
        }
 
2146
        default:
 
2147
            break;
 
2148
    }
 
2149
 
 
2150
    emit storageChanged();
 
2151
    getInformation();
 
2152
}
 
2153
 
 
2154
void VBoxVMSettingsHD::onVmmInvoked()
 
2155
{
 
2156
    QString id = getWithMediaManager (mCbVdi->type());
 
2157
    if (!id.isNull())
 
2158
        mCbVdi->setCurrentItem (id);
 
2159
}
 
2160
 
 
2161
void VBoxVMSettingsHD::updateActionsState()
 
2162
{
 
2163
    QModelIndex index = mTwStorageTree->currentIndex();
 
2164
 
 
2165
    bool isIDEPossible = mStorageModel->data (index, StorageModel::R_IsMoreIDEControllersPossible).toBool();
 
2166
    bool isSATAPossible = mStorageModel->data (index, StorageModel::R_IsMoreSATAControllersPossible).toBool();
 
2167
    bool isSCSIPossible = mStorageModel->data (index, StorageModel::R_IsMoreSCSIControllersPossible).toBool();
 
2168
    bool isFloppyPossible = mStorageModel->data (index, StorageModel::R_IsMoreFloppyControllersPossible).toBool();
 
2169
 
 
2170
    bool isController = mStorageModel->data (index, StorageModel::R_IsController).toBool();
 
2171
    bool isAttachment = mStorageModel->data (index, StorageModel::R_IsAttachment).toBool();
 
2172
    bool isAttachmentsPossible = mStorageModel->data (index, StorageModel::R_IsMoreAttachmentsPossible).toBool();
 
2173
 
 
2174
    mAddCtrAction->setEnabled (isIDEPossible || isSATAPossible || isSCSIPossible || isFloppyPossible);
 
2175
    mAddIDECtrAction->setEnabled (isIDEPossible);
 
2176
    mAddSATACtrAction->setEnabled (isSATAPossible);
 
2177
    mAddSCSICtrAction->setEnabled (isSCSIPossible);
 
2178
    mAddFloppyCtrAction->setEnabled (isFloppyPossible);
 
2179
 
 
2180
    mAddAttAction->setEnabled (isController && isAttachmentsPossible);
 
2181
    mAddHDAttAction->setEnabled (isController && isAttachmentsPossible);
 
2182
    mAddCDAttAction->setEnabled (isController && isAttachmentsPossible);
 
2183
    mAddFDAttAction->setEnabled (isController && isAttachmentsPossible);
 
2184
 
 
2185
    mDelCtrAction->setEnabled (isController);
 
2186
    mDelAttAction->setEnabled (isAttachment);
 
2187
}
 
2188
 
 
2189
void VBoxVMSettingsHD::onRowInserted (const QModelIndex &aParent, int aPosition)
 
2190
{
 
2191
    QModelIndex index = mStorageModel->index (aPosition, 0, aParent);
 
2192
 
 
2193
    switch (mStorageModel->data (index, StorageModel::R_ItemType).value <AbstractItem::ItemType>())
 
2194
    {
 
2195
        case AbstractItem::Type_ControllerItem:
 
2196
        {
 
2197
            /* Select the newly created Controller Item */
 
2198
            mTwStorageTree->setCurrentIndex (index);
 
2199
            break;
 
2200
        }
 
2201
        case AbstractItem::Type_AttachmentItem:
 
2202
        {
 
2203
            /* Expand parent if it is not expanded yet */
 
2204
            if (!mTwStorageTree->isExpanded (aParent))
 
2205
                mTwStorageTree->setExpanded (aParent, true);
 
2206
 
 
2207
            /* Check if no medium was selected for this attachment */
 
2208
            if (mStorageModel->data (index, StorageModel::R_AttMediumId).toString().isEmpty())
 
2209
            {
 
2210
                /* Ask the user for the method to select medium */
 
2211
                KDeviceType deviceType = mStorageModel->data (index, StorageModel::R_AttDevice).value <KDeviceType>();
 
2212
                int askResult = vboxProblem().confirmRunNewHDWzdOrVDM (deviceType);
 
2213
                QString mediumId = askResult == QIMessageBox::Yes ? getWithNewHDWizard() :
 
2214
                                   askResult == QIMessageBox::No ? getWithMediaManager (typeToLocal (deviceType)) : QString();
 
2215
                if (mediumId.isNull())
 
2216
                    mediumId = firstAvailableId;
 
2217
                mStorageModel->setData (index, mediumId, StorageModel::R_AttMediumId);
 
2218
            }
 
2219
            break;
 
2220
        }
 
2221
        default:
 
2222
            break;
 
2223
    }
 
2224
 
 
2225
    updateActionsState();
 
2226
    getInformation();
 
2227
}
 
2228
 
 
2229
void VBoxVMSettingsHD::onRowRemoved()
 
2230
{
 
2231
    if (mStorageModel->rowCount (mStorageModel->root()) == 0)
 
2232
        mTwStorageTree->setCurrentIndex (mStorageModel->root());
 
2233
 
 
2234
    updateActionsState();
 
2235
    getInformation();
 
2236
}
 
2237
 
 
2238
void VBoxVMSettingsHD::onCurrentItemChanged()
 
2239
{
 
2240
    updateActionsState();
 
2241
    getInformation();
 
2242
}
 
2243
 
 
2244
void VBoxVMSettingsHD::onContextMenuRequested (const QPoint &aPosition)
 
2245
{
 
2246
    QModelIndex index = mTwStorageTree->indexAt (aPosition);
 
2247
    if (!index.isValid()) return addController();
 
2248
 
 
2249
    QMenu menu;
 
2250
    switch (mStorageModel->data (index, StorageModel::R_ItemType).value <AbstractItem::ItemType>())
 
2251
    {
 
2252
        case AbstractItem::Type_ControllerItem:
 
2253
        {
 
2254
            DeviceTypeList deviceTypeList (mStorageModel->data (index, StorageModel::R_CtrDevices).value <DeviceTypeList>());
 
2255
            foreach (KDeviceType deviceType, deviceTypeList)
 
2256
            {
 
2257
                switch (deviceType)
 
2258
                {
 
2259
                    case KDeviceType_HardDisk:
 
2260
                        menu.addAction (mAddHDAttAction);
 
2261
                        break;
 
2262
                    case KDeviceType_DVD:
 
2263
                        menu.addAction (mAddCDAttAction);
 
2264
                        break;
 
2265
                    case KDeviceType_Floppy:
 
2266
                        menu.addAction (mAddFDAttAction);
 
2267
                        break;
 
2268
                    default:
 
2269
                        break;
 
2270
                }
 
2271
            }
 
2272
            menu.addAction (mDelCtrAction);
 
2273
            break;
 
2274
        }
 
2275
        case AbstractItem::Type_AttachmentItem:
 
2276
        {
 
2277
            menu.addAction (mDelAttAction);
 
2278
            break;
 
2279
        }
 
2280
        default:
 
2281
            break;
 
2282
    }
 
2283
    if (!menu.isEmpty())
 
2284
        menu.exec (mTwStorageTree->viewport()->mapToGlobal (aPosition));
 
2285
}
 
2286
 
 
2287
void VBoxVMSettingsHD::onDrawItemBranches (QPainter *aPainter, const QRect &aRect, const QModelIndex &aIndex)
 
2288
{
 
2289
    if (!aIndex.parent().isValid() || !aIndex.parent().parent().isValid()) return;
 
2290
 
 
2291
    aPainter->save();
 
2292
    QStyleOption options;
 
2293
    options.initFrom (mTwStorageTree);
 
2294
    options.rect = aRect;
 
2295
    options.state |= QStyle::State_Item;
 
2296
    if (aIndex.row() < mStorageModel->rowCount (aIndex.parent()) - 1)
 
2297
        options.state |= QStyle::State_Sibling;
 
2298
    /* This pen is commonly used by different
 
2299
     * look and feel styles to paint tree-view branches. */
 
2300
    QPen pen (QBrush (options.palette.dark().color(), Qt::Dense4Pattern), 0);
 
2301
    aPainter->setPen (pen);
 
2302
    /* If we want tree-view branches to be always painted we have to use QCommonStyle::drawPrimitive()
 
2303
     * because QCommonStyle performs branch painting as opposed to particular inherited sub-classing styles. */
 
2304
    qobject_cast <QCommonStyle*> (style())->QCommonStyle::drawPrimitive (QStyle::PE_IndicatorBranch, &options, aPainter);
 
2305
    aPainter->restore();
 
2306
}
 
2307
 
 
2308
void VBoxVMSettingsHD::onMouseMoved (QMouseEvent *aEvent)
 
2309
{
 
2310
    QModelIndex index = mTwStorageTree->indexAt (aEvent->pos());
 
2311
    QRect indexRect = mTwStorageTree->visualRect (index);
 
2312
 
 
2313
    /* Expander tool-tip */
 
2314
    if (mStorageModel->data (index, StorageModel::R_IsController).toBool())
 
2315
    {
 
2316
        QRect expanderRect = mStorageModel->data (index, StorageModel::R_ItemPixmapRect).toRect();
 
2317
        expanderRect.translate (indexRect.x(), indexRect.y());
 
2318
        if (expanderRect.contains (aEvent->pos()))
 
2319
        {
 
2320
            aEvent->setAccepted (true);
 
2321
            if (mStorageModel->data (index, StorageModel::R_ToolTipType).value <StorageModel::ToolTipType>() != StorageModel::ExpanderToolTip)
 
2322
                mStorageModel->setData (index, QVariant::fromValue (StorageModel::ExpanderToolTip), StorageModel::R_ToolTipType);
 
2323
            return;
 
2324
        }
 
2325
    }
 
2326
 
 
2327
    /* Adder tool-tip */
 
2328
    if (mStorageModel->data (index, StorageModel::R_IsController).toBool() &&
 
2329
        mTwStorageTree->currentIndex() == index)
 
2330
    {
 
2331
        DeviceTypeList devicesList (mStorageModel->data (index, StorageModel::R_CtrDevices).value <DeviceTypeList>());
 
2332
        for (int i = 0; i < devicesList.size(); ++ i)
 
2333
        {
 
2334
            KDeviceType deviceType = devicesList [i];
 
2335
 
 
2336
            QRect deviceRect;
 
2337
            switch (deviceType)
 
2338
            {
 
2339
                case KDeviceType_HardDisk:
 
2340
                {
 
2341
                    deviceRect = mStorageModel->data (index, StorageModel::R_HDPixmapRect).toRect();
 
2342
                    break;
 
2343
                }
 
2344
                case KDeviceType_DVD:
 
2345
                {
 
2346
                    deviceRect = mStorageModel->data (index, StorageModel::R_CDPixmapRect).toRect();
 
2347
                    break;
 
2348
                }
 
2349
                case KDeviceType_Floppy:
 
2350
                {
 
2351
                    deviceRect = mStorageModel->data (index, StorageModel::R_FDPixmapRect).toRect();
 
2352
                    break;
 
2353
                }
 
2354
                default:
 
2355
                    break;
 
2356
            }
 
2357
            deviceRect.translate (indexRect.x() + indexRect.width(), indexRect.y());
 
2358
 
 
2359
            if (deviceRect.contains (aEvent->pos()))
 
2360
            {
 
2361
                aEvent->setAccepted (true);
 
2362
                switch (deviceType)
 
2363
                {
 
2364
                    case KDeviceType_HardDisk:
 
2365
                    {
 
2366
                        if (mStorageModel->data (index, StorageModel::R_ToolTipType).value <StorageModel::ToolTipType>() != StorageModel::HDAdderToolTip)
 
2367
                            mStorageModel->setData (index, QVariant::fromValue (StorageModel::HDAdderToolTip), StorageModel::R_ToolTipType);
 
2368
                        break;
 
2369
                    }
 
2370
                    case KDeviceType_DVD:
 
2371
                    {
 
2372
                        if (mStorageModel->data (index, StorageModel::R_ToolTipType).value <StorageModel::ToolTipType>() != StorageModel::CDAdderToolTip)
 
2373
                            mStorageModel->setData (index, QVariant::fromValue (StorageModel::CDAdderToolTip), StorageModel::R_ToolTipType);
 
2374
                        break;
 
2375
                    }
 
2376
                    case KDeviceType_Floppy:
 
2377
                    {
 
2378
                        if (mStorageModel->data (index, StorageModel::R_ToolTipType).value <StorageModel::ToolTipType>() != StorageModel::FDAdderToolTip)
 
2379
                            mStorageModel->setData (index, QVariant::fromValue (StorageModel::FDAdderToolTip), StorageModel::R_ToolTipType);
 
2380
                        break;
 
2381
                    }
 
2382
                    default:
 
2383
                        break;
 
2384
                }
 
2385
                return;
 
2386
            }
 
2387
        }
 
2388
    }
 
2389
 
 
2390
    /* Default tool-tip */
 
2391
    if (mStorageModel->data (index, StorageModel::R_ToolTipType).value <StorageModel::ToolTipType>() != StorageModel::DefaultToolTip)
 
2392
        mStorageModel->setData (index, StorageModel::DefaultToolTip, StorageModel::R_ToolTipType);
 
2393
}
 
2394
 
 
2395
void VBoxVMSettingsHD::onMouseClicked (QMouseEvent *aEvent)
 
2396
{
 
2397
    QModelIndex index = mTwStorageTree->indexAt (aEvent->pos());
 
2398
    QRect indexRect = mTwStorageTree->visualRect (index);
 
2399
 
 
2400
    /* Expander icon */
 
2401
    if (mStorageModel->data (index, StorageModel::R_IsController).toBool())
 
2402
    {
 
2403
        QRect expanderRect = mStorageModel->data (index, StorageModel::R_ItemPixmapRect).toRect();
 
2404
        expanderRect.translate (indexRect.x(), indexRect.y());
 
2405
        if (expanderRect.contains (aEvent->pos()))
 
2406
        {
 
2407
            aEvent->setAccepted (true);
 
2408
            mTwStorageTree->setExpanded (index, !mTwStorageTree->isExpanded (index));
 
2409
            return;
 
2410
        }
 
2411
    }
 
2412
 
 
2413
    /* Adder icons */
 
2414
    if (mStorageModel->data (index, StorageModel::R_IsController).toBool() &&
 
2415
        mTwStorageTree->currentIndex() == index)
 
2416
    {
 
2417
        DeviceTypeList devicesList (mStorageModel->data (index, StorageModel::R_CtrDevices).value <DeviceTypeList>());
 
2418
        for (int i = 0; i < devicesList.size(); ++ i)
 
2419
        {
 
2420
            KDeviceType deviceType = devicesList [i];
 
2421
 
 
2422
            QRect deviceRect;
 
2423
            switch (deviceType)
 
2424
            {
 
2425
                case KDeviceType_HardDisk:
 
2426
                {
 
2427
                    deviceRect = mStorageModel->data (index, StorageModel::R_HDPixmapRect).toRect();
 
2428
                    break;
 
2429
                }
 
2430
                case KDeviceType_DVD:
 
2431
                {
 
2432
                    deviceRect = mStorageModel->data (index, StorageModel::R_CDPixmapRect).toRect();
 
2433
                    break;
 
2434
                }
 
2435
                case KDeviceType_Floppy:
 
2436
                {
 
2437
                    deviceRect = mStorageModel->data (index, StorageModel::R_FDPixmapRect).toRect();
 
2438
                    break;
 
2439
                }
 
2440
                default:
 
2441
                    break;
 
2442
            }
 
2443
            deviceRect.translate (indexRect.x() + indexRect.width(), indexRect.y());
 
2444
 
 
2445
            if (deviceRect.contains (aEvent->pos()))
 
2446
            {
 
2447
                aEvent->setAccepted (true);
 
2448
                if (mAddAttAction->isEnabled())
 
2449
                    addAttachmentWrapper (deviceType);
 
2450
                return;
 
2451
            }
 
2452
        }
 
2453
    }
 
2454
}
 
2455
 
 
2456
void VBoxVMSettingsHD::addControllerWrapper (const QString &aName, KStorageBus aBus, KStorageControllerType aType)
 
2457
{
 
2458
    QModelIndex index = mTwStorageTree->currentIndex();
 
2459
    switch (aBus)
 
2460
    {
 
2461
        case KStorageBus_IDE:
 
2462
            Assert (mStorageModel->data (index, StorageModel::R_IsMoreIDEControllersPossible).toBool());
 
2463
            break;
 
2464
        case KStorageBus_SATA:
 
2465
            Assert (mStorageModel->data (index, StorageModel::R_IsMoreSATAControllersPossible).toBool());
 
2466
            break;
 
2467
        case KStorageBus_SCSI:
 
2468
            Assert (mStorageModel->data (index, StorageModel::R_IsMoreSCSIControllersPossible).toBool());
 
2469
            break;
 
2470
        case KStorageBus_Floppy:
 
2471
            Assert (mStorageModel->data (index, StorageModel::R_IsMoreFloppyControllersPossible).toBool());
 
2472
            break;
 
2473
        default:
 
2474
            break;
 
2475
    }
 
2476
 
 
2477
    mStorageModel->addController (aName, aBus, aType);
 
2478
    emit storageChanged();
 
2479
}
 
2480
 
 
2481
void VBoxVMSettingsHD::addAttachmentWrapper (KDeviceType aDevice)
 
2482
{
 
2483
    QModelIndex index = mTwStorageTree->currentIndex();
 
2484
    Assert (mStorageModel->data (index, StorageModel::R_IsController).toBool());
 
2485
    Assert (mStorageModel->data (index, StorageModel::R_IsMoreAttachmentsPossible).toBool());
 
2486
 
 
2487
    mStorageModel->addAttachment (QUuid (mStorageModel->data (index, StorageModel::R_ItemId).toString()), aDevice, true);
 
2488
    emit storageChanged();
 
2489
    if (mValidator) mValidator->revalidate();
 
2490
}
 
2491
 
 
2492
QString VBoxVMSettingsHD::getWithNewHDWizard()
 
2493
{
 
2494
    /* Run New HD Wizard */
 
2495
    VBoxNewHDWzd dlg (this);
 
2496
 
 
2497
    return dlg.exec() == QDialog::Accepted ? dlg.hardDisk().GetId() : QString();
 
2498
}
 
2499
 
 
2500
QString VBoxVMSettingsHD::getWithMediaManager (VBoxDefs::MediumType aMediumType)
 
2501
{
 
2502
    /* Run Media Manager */
 
2503
    VBoxMediaManagerDlg dlg (this);
 
2504
    dlg.setup (aMediumType,
 
2505
               true /* do select? */,
 
2506
               false /* do refresh? */,
 
2507
               mMachine,
 
2508
               mCbVdi->id(),
 
2509
               mCbShowDiffs->isChecked());
 
2510
 
 
2511
    return dlg.exec() == QDialog::Accepted ? dlg.selectedId() : QString();
 
2512
}
 
2513
 
 
2514
void VBoxVMSettingsHD::updateAdditionalObjects (KDeviceType aType)
 
2515
{
 
2516
    mCbShowDiffs->setVisible (aType == KDeviceType_HardDisk);
 
2517
    mCbPassthrough->setVisible (aType == KDeviceType_DVD);
 
2518
 
 
2519
    mLbHDVirtualSize->setVisible (aType == KDeviceType_HardDisk);
 
2520
    mLbHDVirtualSizeValue->setVisible (aType == KDeviceType_HardDisk);
 
2521
 
 
2522
    mLbHDActualSize->setVisible (aType == KDeviceType_HardDisk);
 
2523
    mLbHDActualSizeValue->setVisible (aType == KDeviceType_HardDisk);
 
2524
 
 
2525
    mLbSize->setVisible (aType != KDeviceType_HardDisk);
 
2526
    mLbSizeValue->setVisible (aType != KDeviceType_HardDisk);
 
2527
 
 
2528
    mLbHDFormat->setVisible (aType == KDeviceType_HardDisk);
 
2529
    mLbHDFormatValue->setVisible (aType == KDeviceType_HardDisk);
 
2530
}
 
2531
 
 
2532
QString VBoxVMSettingsHD::generateUniqueName (const QString &aTemplate) const
 
2533
{
 
2534
    int maxNumber = 0;
 
2535
    QModelIndex rootIndex = mStorageModel->root();
 
2536
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
2537
    {
 
2538
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
2539
        QString ctrName = mStorageModel->data (ctrIndex, StorageModel::R_CtrName).toString();
 
2540
        if (ctrName.startsWith (aTemplate))
 
2541
        {
 
2542
            QString stringNumber (ctrName.right (ctrName.size() - aTemplate.size()));
 
2543
            bool isConverted = false;
 
2544
            int number = stringNumber.toInt (&isConverted);
 
2545
            if (isConverted && number > maxNumber)
 
2546
                maxNumber = number;
 
2547
        }
 
2548
    }
 
2549
    return maxNumber ? QString ("%1 %2").arg (aTemplate).arg (++ maxNumber) : aTemplate;
 
2550
}
 
2551
 
 
2552
uint32_t VBoxVMSettingsHD::deviceCount (KDeviceType aType) const
 
2553
{
 
2554
    uint32_t cDevices = 0;
 
2555
    QModelIndex rootIndex = mStorageModel->root();
 
2556
    for (int i = 0; i < mStorageModel->rowCount (rootIndex); ++ i)
 
2557
    {
 
2558
        QModelIndex ctrIndex = rootIndex.child (i, 0);
 
2559
        for (int j = 0; j < mStorageModel->rowCount (ctrIndex); ++ j)
 
2560
        {
 
2561
            QModelIndex attIndex = ctrIndex.child (j, 0);
 
2562
            KDeviceType attDevice = mStorageModel->data (attIndex, StorageModel::R_AttDevice).value <KDeviceType>();
 
2563
            if (attDevice == aType)
 
2564
                ++cDevices;
 
2565
        }
 
2566
    }
 
2567
 
 
2568
    return cDevices;
 
2569
}
 
2570