VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox4/src/VBoxVMSettingsHD.cpp@ 11189

Last change on this file since 11189 was 11189, checked in by vboxsync, 17 years ago

Fe/Qt4: VM Settings / HD Page : restoring combo-box vertical height to 130% of font's height.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 28.8 KB
Line 
1/** @file
2 *
3 * VBox frontends: Qt4 GUI ("VirtualBox"):
4 * VBoxVMSettingsHD class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "VBoxVMSettingsHD.h"
24#include "VBoxGlobal.h"
25#include "VBoxProblemReporter.h"
26#include "QIWidgetValidator.h"
27#include "VBoxToolBar.h"
28#include "VBoxDiskImageManagerDlg.h"
29#include "VBoxNewHDWzd.h"
30
31#include <QHeaderView>
32#include <QItemEditorFactory>
33#include <QMetaProperty>
34#include <QScrollBar>
35
36/** SATA Ports count */
37static const ULONG SATAPortsCount = 30;
38
39Qt::ItemFlags HDItemsModel::flags (const QModelIndex &aIndex) const
40{
41 return aIndex.row() == rowCount() - 1 ?
42 QAbstractItemModel::flags (aIndex) ^ Qt::ItemIsSelectable :
43 QAbstractItemModel::flags (aIndex) | Qt::ItemIsEditable;
44}
45
46QVariant HDItemsModel::data (const QModelIndex &aIndex, int aRole) const
47{
48 if (!aIndex.isValid())
49 return QVariant();
50
51 if (aIndex.row() < 0 || aIndex.row() >= rowCount())
52 return QVariant();
53
54 switch (aRole)
55 {
56 case Qt::DisplayRole:
57 {
58 if (aIndex.row() == rowCount() - 1)
59 {
60 return QVariant();
61 } else
62 if (aIndex.column() == 0)
63 {
64 return QVariant (mSltList [aIndex.row()].name);
65 } else
66 if (aIndex.column() == 1)
67 {
68 return QVariant (mVdiList [aIndex.row()].name);
69 } else
70 {
71 Assert (0);
72 return QVariant();
73 }
74 break;
75 }
76 case Qt::EditRole:
77 {
78 if (aIndex.column() == 0)
79 {
80 QVariant val (mSltId, &mSltList [aIndex.row()]);
81 return val;
82 } else
83 if (aIndex.column() == 1)
84 {
85 QVariant val (mVdiId, &mVdiList [aIndex.row()]);
86 return val;
87 } else
88 {
89 Assert (0);
90 return QVariant();
91 }
92 break;
93 }
94 case Qt::ToolTipRole:
95 {
96 if (aIndex.row() == rowCount() - 1)
97 return QVariant (tr ("Double-click to add a new attachment"));
98
99 CHardDisk hd = vboxGlobal().virtualBox()
100 .GetHardDisk (mVdiList [aIndex.row()].id);
101 return QVariant (VBoxDiskImageManagerDlg::composeHdToolTip (
102 hd, VBoxMedia::Ok));
103 }
104 default:
105 {
106 return QVariant();
107 break;
108 }
109 }
110}
111
112bool HDItemsModel::setData (const QModelIndex &aIndex,
113 const QVariant &aValue,
114 int /* aRole = Qt::EditRole */)
115{
116 if (!aIndex.isValid())
117 return false;
118
119 if (aIndex.row() < 0 || aIndex.row() >= rowCount())
120 return false;
121
122 if (aIndex.column() == 0)
123 {
124 HDSltValue newSlt = aValue.isValid() ?
125 aValue.value<HDSltValue>() : HDSltValue();
126 if (mSltList [aIndex.row()] != newSlt)
127 {
128 mSltList [aIndex.row()] = newSlt;
129 emit dataChanged (aIndex, aIndex);
130 return true;
131 }
132 else
133 return false;
134 } else
135 if (aIndex.column() == 1)
136 {
137 HDVdiValue newVdi = aValue.isValid() ?
138 aValue.value<HDVdiValue>() : HDVdiValue();
139 if (mVdiList [aIndex.row()] != newVdi)
140 {
141 mVdiList [aIndex.row()] = newVdi;
142 emit dataChanged (aIndex, aIndex);
143 return true;
144 }
145 else
146 return false;
147 } else
148 {
149 Assert (0);
150 return false;
151 }
152}
153
154QVariant HDItemsModel::headerData (int aSection,
155 Qt::Orientation aOrientation,
156 int aRole) const
157{
158 if (aRole != Qt::DisplayRole)
159 return QVariant();
160
161 if (aOrientation == Qt::Horizontal)
162 return aSection ? tr ("Hard Disk") : tr ("Slot");
163 else
164 return QVariant();
165}
166
167void HDItemsModel::addItem (const HDSltValue &aSlt, const HDVdiValue &aVdi)
168{
169 beginInsertRows (QModelIndex(), rowCount() - 1, rowCount() - 1);
170 mSltList.append (aSlt);
171 mVdiList.append (aVdi);
172 endInsertRows();
173}
174
175void HDItemsModel::delItem (int aIndex)
176{
177 beginRemoveRows (QModelIndex(), aIndex, aIndex);
178 mSltList.removeAt (aIndex);
179 mVdiList.removeAt (aIndex);
180 endRemoveRows();
181}
182
183QList<HDValue> HDItemsModel::fullList (bool aSorted /* = true */)
184{
185 QList<HDValue> list;
186 QList<HDSltValue> slts = slotsList();
187 QList<HDVdiValue> vdis = vdiList();
188 for (int i = 0; i < slts.size(); ++ i)
189 list << HDValue (slts [i], vdis [i]);
190 if (aSorted)
191 qSort (list.begin(), list.end());
192 return list;
193}
194
195void HDItemsModel::removeSata()
196{
197 QList<HDSltValue>::iterator sltIt = mSltList.begin();
198 QList<HDVdiValue>::iterator vdiIt = mVdiList.begin();
199 while (sltIt != mSltList.end())
200 {
201 if ((*sltIt).bus == KStorageBus_SATA)
202 {
203 sltIt = mSltList.erase (sltIt);
204 vdiIt = mVdiList.erase (vdiIt);
205 }
206 else
207 {
208 ++ sltIt;
209 ++ vdiIt;
210 }
211 }
212}
213
214/** QComboBox class reimplementation used as editor for hd slot */
215HDSltEditor::HDSltEditor (QWidget *aParent)
216 : QComboBox (aParent)
217{
218 connect (this, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivate()));
219 connect (this, SIGNAL (readyToCommit (QWidget *)),
220 parent()->parent(), SLOT (commitData (QWidget *)));
221}
222
223QVariant HDSltEditor::slot() const
224{
225 int current = currentIndex();
226 QVariant result;
227 if (current >= 0 && current < mList.size())
228 result.setValue (mList [currentIndex()]);
229 return result;
230}
231
232void HDSltEditor::setSlot (QVariant aSlot)
233{
234 HDSltValue val (aSlot.value<HDSltValue>());
235 populate (val);
236 int cur = findText (val.name);
237 setCurrentIndex (cur == -1 ? 0 : cur);
238}
239
240void HDSltEditor::onActivate()
241{
242 emit readyToCommit (this);
243}
244
245void HDSltEditor::populate (const HDSltValue &aIncluding)
246{
247 clear();
248 mList.clear();
249 QList<HDSltValue> list = HDSlotUniquizer::instance()->list (aIncluding);
250 for (int i = 0; i < list.size() ; ++ i)
251 {
252 insertItem (i, list [i].name);
253 mList << list [i];
254 }
255}
256
257/** QComboBox class reimplementation used as editor for hd vdi */
258HDVdiEditor* HDVdiEditor::mInstance = 0;
259HDVdiEditor::HDVdiEditor (QWidget *aParent)
260 : VBoxMediaComboBox (aParent, VBoxDefs::HD)
261{
262 mInstance = this;
263 setBelongsTo (HDSlotUniquizer::instance()->machine().GetId());
264 connect (this, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivate()));
265 connect (this, SIGNAL (readyToCommit (QWidget *)),
266 parent()->parent(), SLOT (commitData (QWidget *)));
267 refresh();
268}
269HDVdiEditor::~HDVdiEditor()
270{
271 if (mInstance == this)
272 mInstance = 0;
273}
274
275QVariant HDVdiEditor::vdi() const
276{
277 int current = currentIndex();
278 QVariant result;
279 if (current >= 0 && current < count())
280 {
281 HDVdiValue val (currentText().isEmpty() ? QString::null : currentText(),
282 getId (current));
283 result.setValue (val);
284 }
285 return result;
286}
287
288void HDVdiEditor::setVdi (QVariant aVdi)
289{
290 HDVdiValue val (aVdi.value<HDVdiValue>());
291 setCurrentItem (val.id);
292}
293
294void HDVdiEditor::tryToChooseUniqueVdi (QList<HDVdiValue> &aList)
295{
296 for (int i = 0; i < count(); ++ i)
297 {
298 HDVdiValue val (itemText (i), getId (i));
299 if (!aList.contains (val))
300 {
301 setCurrentItem (getId (i));
302 break;
303 }
304 }
305}
306
307HDVdiEditor* HDVdiEditor::activeEditor()
308{
309 return mInstance;
310}
311
312void HDVdiEditor::onActivate()
313{
314 emit readyToCommit (this);
315}
316
317/** Singleton QObject class reimplementation to use for making selected IDE &
318 * SATA slots unique */
319HDSlotUniquizer* HDSlotUniquizer::mInstance = 0;
320HDSlotUniquizer* HDSlotUniquizer::instance (QWidget *aParent,
321 HDItemsModel *aWatched,
322 const CMachine &aMachine)
323{
324 if (!mInstance)
325 {
326 Assert (aParent && aWatched && !aMachine.isNull());
327 mInstance = new HDSlotUniquizer (aParent, aWatched, aMachine);
328 }
329 return mInstance;
330}
331
332HDSlotUniquizer::HDSlotUniquizer (QWidget *aParent, HDItemsModel *aWatched,
333 const CMachine &aMachine)
334 : QObject (aParent)
335 , mSataCount (SATAPortsCount)
336 , mModel (aWatched)
337 , mMachine (aMachine)
338{
339 makeIDEList();
340 makeSATAList();
341}
342
343HDSlotUniquizer::~HDSlotUniquizer()
344{
345 mInstance = 0;
346}
347
348QList<HDSltValue> HDSlotUniquizer::list (const HDSltValue &aIncluding,
349 bool aFilter /* = true */)
350{
351 QList<HDSltValue> list = mIDEList + mSATAList;
352 if (!aFilter)
353 return list;
354
355 /* Current used list */
356 QList<HDSltValue> current (mModel->slotsList());
357
358 /* Filter the list */
359 QList<HDSltValue>::iterator it = current.begin();
360 while (it != current.end())
361 {
362 if (*it != aIncluding)
363 list.removeAll (*it);
364 ++ it;
365 }
366
367 return list;
368}
369
370void HDSlotUniquizer::makeIDEList()
371{
372 mIDEList.clear();
373
374 /* IDE Primary Master */
375 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 0, 0),
376 KStorageBus_IDE, 0, 0);
377 /* IDE Primary Slave */
378 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 0, 1),
379 KStorageBus_IDE, 0, 1);
380 /* IDE Secondary Slave */
381 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 1, 1),
382 KStorageBus_IDE, 1, 1);
383}
384
385void HDSlotUniquizer::makeSATAList()
386{
387 mSATAList.clear();
388
389 for (int i = 0; i < mSataCount; ++ i)
390 mSATAList << HDSltValue (vboxGlobal().toFullString (KStorageBus_SATA, i, 0),
391 KStorageBus_SATA, i, 0);
392}
393
394
395VBoxVMSettingsHD::VBoxVMSettingsHD()
396 : mValidator (0)
397{
398 /* Apply UI decorations */
399 Ui::VBoxVMSettingsHD::setupUi (this);
400
401 /* Setup model/view factory */
402 int idHDSlt = qRegisterMetaType<HDSltValue>();
403 int idHDVdi = qRegisterMetaType<HDVdiValue>();
404 QItemEditorFactory *factory = new QItemEditorFactory;
405 QItemEditorCreatorBase *sltCreator =
406 new QStandardItemEditorCreator<HDSltEditor>();
407 QItemEditorCreatorBase *vdiCreator =
408 new QStandardItemEditorCreator<HDVdiEditor>();
409 factory->registerEditor ((QVariant::Type)idHDSlt, sltCreator);
410 factory->registerEditor ((QVariant::Type)idHDVdi, vdiCreator);
411 QItemEditorFactory::setDefaultFactory (factory);
412
413 /* Setup view-model */
414 mModel = new HDItemsModel (this, idHDSlt, idHDVdi);
415 connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
416 this, SIGNAL (hdChanged()));
417
418 /* Setup table-view */
419 mTwAts->verticalHeader()->setDefaultSectionSize (
420 (int) (mTwAts->fontMetrics().height() * 1.30 /* 130% of font height */));
421 mTwAts->verticalHeader()->hide();
422 mTwAts->horizontalHeader()->setStretchLastSection (true);
423 mTwAts->setModel (mModel);
424 mTwAts->setToolTip (mModel->data (mModel->index (mModel->rowCount() - 1, 0),
425 Qt::ToolTipRole).toString());
426
427 /* Prepare actions */
428 mNewAction = new QAction (mTwAts);
429 mDelAction = new QAction (mTwAts);
430 mVdmAction = new QAction (mTwAts);
431
432 mTwAts->addAction (mNewAction);
433 mTwAts->addAction (mDelAction);
434 mTwAts->addAction (mVdmAction);
435
436 mNewAction->setShortcut (QKeySequence ("Ins"));
437 mDelAction->setShortcut (QKeySequence ("Del"));
438 mVdmAction->setShortcut (QKeySequence ("Ctrl+Space"));
439
440 mNewAction->setIcon (VBoxGlobal::iconSet (":/vdm_add_16px.png",
441 ":/vdm_add_disabled_16px.png"));
442 mDelAction->setIcon (VBoxGlobal::iconSet (":/vdm_remove_16px.png",
443 ":/vdm_remove_disabled_16px.png"));
444 mVdmAction->setIcon (VBoxGlobal::iconSet (":/select_file_16px.png",
445 ":/select_file_dis_16px.png"));
446
447 /* Prepare toolbar */
448 VBoxToolBar *toolBar = new VBoxToolBar (mGbAts);
449 toolBar->setUsesTextLabel (false);
450 toolBar->setUsesBigPixmaps (false);
451 toolBar->setOrientation (Qt::Vertical);
452 toolBar->addAction (mNewAction);
453 toolBar->addAction (mDelAction);
454 toolBar->addAction (mVdmAction);
455 mGbAts->layout()->addWidget (toolBar);
456
457 /* Setup connections */
458 connect (mNewAction, SIGNAL (triggered (bool)),
459 this, SLOT (newClicked()));
460 connect (mDelAction, SIGNAL (triggered (bool)),
461 this, SLOT (delClicked()));
462 connect (mVdmAction, SIGNAL (triggered (bool)),
463 this, SLOT (vdmClicked()));
464 connect (mCbSATA, SIGNAL (stateChanged (int)),
465 this, SLOT (cbSATAToggled (int)));
466 connect (mTwAts, SIGNAL (currentChanged (const QModelIndex &)),
467 this, SLOT (onCurrentChanged (const QModelIndex &)));
468 connect (&vboxGlobal(),
469 SIGNAL (mediaRemoved (VBoxDefs::DiskType, const QUuid &)),
470 this, SLOT (onMediaRemoved (VBoxDefs::DiskType, const QUuid &)));
471 connect (this, SIGNAL (signalToCloseEditor (QWidget*, QAbstractItemDelegate::EndEditHint)),
472 mTwAts, SLOT (closeEditor (QWidget*, QAbstractItemDelegate::EndEditHint)));
473
474 /* Install global event filter */
475 qApp->installEventFilter (this);
476
477 /* Applying language settings */
478 retranslateUi();
479}
480
481void VBoxVMSettingsHD::getFrom (const CMachine &aMachine)
482{
483 mMachine = aMachine;
484
485 /* Setup slot uniquizer */
486 HDSlotUniquizer::instance (mTwAts, mModel, mMachine);
487
488 CSATAController ctl = mMachine.GetSATAController();
489 /* Hide the SATA check box if the SATA controller is not available
490 * (i.e. in VirtualBox OSE) */
491 if (ctl.isNull())
492 mCbSATA->setHidden (true);
493 else
494 mCbSATA->setChecked (ctl.GetEnabled());
495 cbSATAToggled (mCbSATA->checkState());
496
497 CHardDiskAttachmentEnumerator en =
498 mMachine.GetHardDiskAttachments().Enumerate();
499 while (en.HasMore())
500 {
501 CHardDiskAttachment hda = en.GetNext();
502 HDSltValue slt (vboxGlobal().toFullString (hda.GetBus(),
503 hda.GetChannel(),
504 hda.GetDevice()),
505 hda.GetBus(), hda.GetChannel(), hda.GetDevice());
506 HDVdiValue vdi (VBoxMediaComboBox::fullItemName (hda.GetHardDisk()
507 .GetLocation()),
508 hda.GetHardDisk().GetRoot().GetId());
509 mModel->addItem (slt, vdi);
510 }
511
512 mTwAts->setCurrentIndex (mModel->index (0, 1));
513 onCurrentChanged (mTwAts->currentIndex());
514
515 if (mValidator)
516 mValidator->revalidate();
517}
518
519void VBoxVMSettingsHD::putBackTo()
520{
521 CSATAController ctl = mMachine.GetSATAController();
522 if (!ctl.isNull())
523 {
524 ctl.SetEnabled (mCbSATA->isChecked());
525 }
526
527 /* Detach all attached Hard Disks */
528 CHardDiskAttachmentEnumerator en =
529 mMachine.GetHardDiskAttachments().Enumerate();
530 while (en.HasMore())
531 {
532 CHardDiskAttachment hda = en.GetNext();
533 mMachine.DetachHardDisk (hda.GetBus(), hda.GetChannel(), hda.GetDevice());
534 if (!mMachine.isOk())
535 vboxProblem().cannotDetachHardDisk (this, mMachine,
536 hda.GetBus(), hda.GetChannel(), hda.GetDevice());
537 }
538
539 /* Attach all listed Hard Disks */
540 LONG maxSATAPort = 1;
541 QList<HDValue> list (mModel->fullList());
542 for (int i = 0; i < list.size(); ++ i)
543 {
544 if (list [i].slt.bus == KStorageBus_SATA)
545 maxSATAPort = maxSATAPort < (list [i].slt.channel + 1) ?
546 (list [i].slt.channel + 1) : maxSATAPort;
547 mMachine.AttachHardDisk (list [i].vdi.id,
548 list [i].slt.bus, list [i].slt.channel, list [i].slt.device);
549 if (!mMachine.isOk())
550 vboxProblem().cannotAttachHardDisk (this, mMachine, list [i].vdi.id,
551 list [i].slt.bus, list [i].slt.channel, list [i].slt.device);
552 }
553
554 if (!ctl.isNull())
555 {
556 mMachine.GetSATAController().SetPortCount (maxSATAPort);
557 }
558}
559
560void VBoxVMSettingsHD::setValidator (QIWidgetValidator *aVal)
561{
562 mValidator = aVal;
563 connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
564 mValidator, SLOT (revalidate()));
565}
566
567bool VBoxVMSettingsHD::revalidate (QString &aWarning, QString &)
568{
569 QList<HDSltValue> sltList (mModel->slotsList());
570 QList<HDVdiValue> vdiList (mModel->vdiList());
571 for (int i = 0; i < vdiList.size(); ++ i)
572 {
573 /* Check for emptiness */
574 if (vdiList [i].name.isNull())
575 {
576 aWarning = tr ("No hard disk is selected for <i>%1</i>")
577 .arg (sltList [i].name);
578 break;
579 }
580
581 /* Check for coincidence */
582 if (vdiList.count (vdiList [i]) > 1)
583 {
584 int first = vdiList.indexOf (vdiList [i]);
585 int second = vdiList.indexOf (vdiList [i], first + 1);
586 Assert (first != -1 && second != -1);
587 aWarning = tr ("<i>%1</i> uses the hard disk that is "
588 "already attached to <i>%2</i>")
589 .arg (sltList [second].name,
590 sltList [first].name);
591 break;
592 }
593 }
594
595 return aWarning.isNull();
596}
597
598void VBoxVMSettingsHD::setOrderAfter (QWidget *aWidget)
599{
600 setTabOrder (aWidget, mCbSATA);
601 setTabOrder (mCbSATA, mTwAts);
602}
603
604void VBoxVMSettingsHD::retranslateUi()
605{
606 /* Translate uic generated strings */
607 Ui::VBoxVMSettingsHD::retranslateUi (this);
608
609 mNewAction->setText (tr ("&Add Attachment"));
610 mDelAction->setText (tr ("&Remove Attachment"));
611 mVdmAction->setText (tr ("&Select Hard Disk"));
612
613 mNewAction->setToolTip (mNewAction->text().remove ('&') +
614 QString (" (%1)").arg (mNewAction->shortcut().toString()));
615 mDelAction->setToolTip (mDelAction->text().remove ('&') +
616 QString (" (%1)").arg (mDelAction->shortcut().toString()));
617 mVdmAction->setToolTip (mVdmAction->text().remove ('&') +
618 QString (" (%1)").arg (mVdmAction->shortcut().toString()));
619
620 mNewAction->setWhatsThis (tr ("Adds a new hard disk attachment."));
621 mDelAction->setWhatsThis (tr ("Removes the highlighted hard disk attachment."));
622 mVdmAction->setWhatsThis (tr ("Invokes the Virtual Disk Manager to select "
623 "a hard disk to attach to the currently "
624 "highlighted slot."));
625}
626
627void VBoxVMSettingsHD::newClicked()
628{
629 /* Remember the current vdis list */
630 QList<HDVdiValue> vdis (mModel->vdiList());
631
632 /* Add new index */
633 mModel->addItem();
634
635 /* Set the default data into the new index for column #1 */
636 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 1));
637 /* Set the default data into the new index for column #0 */
638 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 0));
639
640 /* Set column #1 of new index to be the current */
641 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 1));
642
643 HDVdiEditor *editor = HDVdiEditor::activeEditor();
644 if (editor)
645 {
646 /* Try to select unique vdi */
647 editor->tryToChooseUniqueVdi (vdis);
648
649 /* Ask the user for method to add new vdi */
650 int result = mModel->rowCount() - 1 > editor->count() ?
651 vboxProblem().confirmRunNewHDWzdOrVDM (this) :
652 QIMessageBox::Cancel;
653 if (result == QIMessageBox::Yes)
654 {
655 /* Close the editor to avoid it's infliction to data model */
656 emit signalToCloseEditor (HDVdiEditor::activeEditor(),
657 QAbstractItemDelegate::NoHint);
658
659 /* Run new HD wizard */
660 VBoxNewHDWzd dlg (this);
661 if (dlg.exec() == QDialog::Accepted)
662 {
663 CHardDisk hd = dlg.hardDisk();
664 QVariant result;
665 HDVdiValue val (VBoxMediaComboBox::fullItemName (hd.GetLocation()),
666 hd.GetId());
667 result.setValue (val);
668 mModel->setData (mTwAts->currentIndex(), result);
669 vboxGlobal().startEnumeratingMedia();
670 }
671 }
672 else if (result == QIMessageBox::No)
673 vdmClicked();
674 }
675}
676
677void VBoxVMSettingsHD::delClicked()
678{
679 QModelIndex current = mTwAts->currentIndex();
680 if (current.isValid())
681 {
682 /* Storing current attributes */
683 int row = current.row();
684 int col = current.column();
685
686 /* Erase current index */
687 mTwAts->setCurrentIndex (QModelIndex());
688
689 /* Calculate new current index */
690 int newRow = row < mModel->rowCount() - 2 ? row :
691 row > 0 ? row - 1 : -1;
692 QModelIndex next = newRow == -1 ? mModel->index (0, col) :
693 mModel->index (newRow, col);
694
695 /* Delete current index */
696 mModel->delItem (current.row());
697
698 /* Set the new index to be the current */
699 mTwAts->setCurrentIndex (next);
700 onCurrentChanged (next);
701
702 if (mValidator)
703 mValidator->revalidate();
704 emit hdChanged();
705 }
706}
707
708void VBoxVMSettingsHD::vdmClicked()
709{
710 Assert (mTwAts->currentIndex().isValid());
711
712 /* Close the editor to avoid it's infliction to data model */
713 emit signalToCloseEditor (HDVdiEditor::activeEditor(),
714 QAbstractItemDelegate::NoHint);
715
716 HDVdiValue oldVdi (mModel->data (mTwAts->currentIndex(), Qt::EditRole)
717 .value<HDVdiValue>());
718
719 VBoxDiskImageManagerDlg dlg (this);
720 dlg.setup (VBoxDefs::HD, true, mMachine.GetId(), true, mMachine, oldVdi.id);
721
722 if (dlg.exec() == QDialog::Accepted)
723 {
724 /* Compose resulting vdi */
725 QVariant result;
726 HDVdiValue newVdi (VBoxMediaComboBox::fullItemName (dlg.selectedPath()),
727 dlg.selectedUuid());
728 result.setValue (newVdi);
729
730 /* Set the model's data */
731 mModel->setData (mTwAts->currentIndex(), result);
732 }
733
734 vboxGlobal().startEnumeratingMedia();
735}
736
737void VBoxVMSettingsHD::onCurrentChanged (const QModelIndex& /* aIndex */)
738{
739 mNewAction->setEnabled (mModel->rowCount() - 1 <
740 HDSlotUniquizer::instance()->list (HDSltValue(), false).count());
741 mDelAction->setEnabled (mTwAts->currentIndex().row() != mModel->rowCount() - 1);
742 mVdmAction->setEnabled (mTwAts->currentIndex().row() != mModel->rowCount() - 1 &&
743 mTwAts->currentIndex().column() == 1);
744}
745
746void VBoxVMSettingsHD::cbSATAToggled (int aState)
747{
748 if (aState == Qt::Unchecked)
749 {
750 /* Search the list for at least one SATA port in */
751 QList<HDSltValue> list (mModel->slotsList());
752 int firstSataPort = 0;
753 for (; firstSataPort < list.size(); ++ firstSataPort)
754 if (list [firstSataPort].bus == KStorageBus_SATA)
755 break;
756
757 /* If list contains at least one SATA port */
758 if (firstSataPort < list.size())
759 {
760 if (vboxProblem().confirmDetachSATASlots (this) != QIMessageBox::Ok)
761 {
762 /* Switch check-box back to "Qt::Checked" */
763 mCbSATA->blockSignals (true);
764 mCbSATA->setCheckState (Qt::Checked);
765 mCbSATA->blockSignals (false);
766 return;
767 }
768 else
769 {
770 /* Delete SATA items */
771 mModel->removeSata();
772
773 /* Set column #1 of first index to be the current */
774 mTwAts->setCurrentIndex (mModel->index (0, 1));
775
776 if (mValidator)
777 mValidator->revalidate();
778 }
779 }
780 }
781
782 int newSataCount = aState == Qt::Checked ? SATAPortsCount : 0;
783 if (HDSlotUniquizer::instance()->sataCount() != newSataCount)
784 HDSlotUniquizer::instance()->setSataCount (newSataCount);
785 onCurrentChanged (mTwAts->currentIndex());
786}
787
788void VBoxVMSettingsHD::onMediaRemoved (VBoxDefs::DiskType aType, const QUuid &aId)
789{
790 /* Check if it is necessary to update data-model if
791 * some media was removed */
792 if (aType == VBoxDefs::HD)
793 {
794 QList<HDVdiValue> vdis (mModel->vdiList());
795 for (int i = 0; i < vdis.size(); ++ i)
796 {
797 if (vdis [i].id == aId)
798 {
799 QVariant emptyVal;
800 emptyVal.setValue (HDVdiValue());
801 mModel->setData (mModel->index (i, 1), emptyVal);
802 }
803 }
804 }
805}
806
807bool VBoxVMSettingsHD::eventFilter (QObject *aObject, QEvent *aEvent)
808{
809 if (!aObject->isWidgetType())
810 return QWidget::eventFilter (aObject, aEvent);
811
812 QWidget *widget = static_cast<QWidget*> (aObject);
813 if (widget->inherits ("HDSltEditor") ||
814 widget->inherits ("HDVdiEditor"))
815 {
816 if (aEvent->type() == QEvent::KeyPress)
817 {
818 QKeyEvent *e = static_cast<QKeyEvent*> (aEvent);
819 QModelIndex cur = mTwAts->currentIndex();
820 switch (e->key())
821 {
822 case Qt::Key_Up:
823 {
824 if (cur.row() > 0)
825 mTwAts->setCurrentIndex (mModel->index (cur.row() - 1,
826 cur.column()));
827 return true;
828 }
829 case Qt::Key_Down:
830 {
831 if (cur.row() < mModel->rowCount() - 1)
832 mTwAts->setCurrentIndex (mModel->index (cur.row() + 1,
833 cur.column()));
834 return true;
835 }
836 case Qt::Key_Right:
837 {
838 if (cur.column() == 0)
839 mTwAts->setCurrentIndex (mModel->index (cur.row(), 1));
840 return true;
841 }
842 case Qt::Key_Left:
843 {
844 if (cur.column() == 1)
845 mTwAts->setCurrentIndex (mModel->index (cur.row(), 0));
846 return true;
847 }
848 case Qt::Key_Tab:
849 {
850 focusNextPrevChild (true);
851 return true;
852 }
853 case Qt::Key_Backtab:
854 {
855 focusNextPrevChild (false);
856 return true;
857 }
858 default:
859 break;
860 }
861 }
862 } else
863 if (widget == mTwAts->viewport() &&
864 aEvent->type() == QEvent::MouseButtonDblClick)
865 {
866 QMouseEvent *e = static_cast<QMouseEvent*> (aEvent);
867 QModelIndex index = mTwAts->indexAt (e->pos());
868 if (mNewAction->isEnabled() &&
869 (index.row() == mModel->rowCount() - 1 || !index.isValid()))
870 newClicked();
871 }
872
873 return QWidget::eventFilter (aObject, aEvent);
874}
875
876int VBoxVMSettingsHD::maxNameLength() const
877{
878 QList<HDSltValue> fullList (HDSlotUniquizer::instance()
879 ->list (HDSltValue(), false));
880 int maxLength = 0;
881 for (int i = 0; i < fullList.size(); ++ i)
882 {
883 int length = mTwAts->fontMetrics().width (fullList [i].name);
884 maxLength = length > maxLength ? length : maxLength;
885 }
886 return maxLength;
887}
888
889void VBoxVMSettingsHD::showEvent (QShowEvent *aEvent)
890{
891 /* Activate edit triggers now to restrict them during data loading */
892 mTwAts->setEditTriggers (QAbstractItemView::CurrentChanged |
893 QAbstractItemView::SelectedClicked |
894 QAbstractItemView::EditKeyPressed |
895 QAbstractItemView::DoubleClicked);
896
897 /* Temporary activating vertical scrollbar to calculate it's width */
898 mTwAts->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
899 int width = mTwAts->verticalScrollBar()->width();
900 mTwAts->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded);
901 QWidget::showEvent (aEvent);
902 mTwAts->horizontalHeader()->resizeSection (0,
903 width + maxNameLength() + 9 * 2 /* 2 margins */);
904
905 /* That little hack allows avoid one of qt4 children focusing bug */
906 QWidget *current = QApplication::focusWidget();
907 mTwAts->setFocus (Qt::TabFocusReason);
908 if (current)
909 current->setFocus (Qt::TabFocusReason);
910}
911
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette