VirtualBox

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

Last change on this file since 10604 was 10604, checked in by vboxsync, 16 years ago

FE/Qt4: Tabs as subpages in the settings dialog if the ToolBar style is used.
In the classical view nothing has changed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 28.0 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 setBelongsTo (HDSlotUniquizer::instance()->machine().GetId());
263 connect (this, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivate()));
264 connect (this, SIGNAL (readyToCommit (QWidget *)),
265 parent()->parent(), SLOT (commitData (QWidget *)));
266 refresh();
267 mInstance = this;
268}
269HDVdiEditor::~HDVdiEditor()
270{
271 mInstance = 0;
272}
273
274QVariant HDVdiEditor::vdi() const
275{
276 int current = currentIndex();
277 QVariant result;
278 if (current >= 0 && current < count())
279 {
280 HDVdiValue val (currentText().isEmpty() ? QString::null : currentText(),
281 getId (current));
282 result.setValue (val);
283 }
284 return result;
285}
286
287void HDVdiEditor::setVdi (QVariant aVdi)
288{
289 HDVdiValue val (aVdi.value<HDVdiValue>());
290 setCurrentItem (val.id);
291}
292
293void HDVdiEditor::tryToChooseUniqueVdi (QList<HDVdiValue> &aList)
294{
295 for (int i = 0; i < count(); ++ i)
296 {
297 HDVdiValue val (itemText (i), getId (i));
298 if (!aList.contains (val))
299 {
300 setCurrentItem (getId (i));
301 break;
302 }
303 }
304}
305
306HDVdiEditor* HDVdiEditor::activeEditor()
307{
308 return mInstance;
309}
310
311void HDVdiEditor::onActivate()
312{
313 emit readyToCommit (this);
314}
315
316/** Singleton QObject class reimplementation to use for making selected IDE &
317 * SATA slots unique */
318HDSlotUniquizer* HDSlotUniquizer::mInstance = 0;
319HDSlotUniquizer* HDSlotUniquizer::instance (QWidget *aParent,
320 HDItemsModel *aWatched,
321 const CMachine &aMachine)
322{
323 if (!mInstance)
324 {
325 Assert (aParent && aWatched && !aMachine.isNull());
326 mInstance = new HDSlotUniquizer (aParent, aWatched, aMachine);
327 }
328 return mInstance;
329}
330
331HDSlotUniquizer::HDSlotUniquizer (QWidget *aParent, HDItemsModel *aWatched,
332 const CMachine &aMachine)
333 : QObject (aParent)
334 , mSataCount (SATAPortsCount)
335 , mModel (aWatched)
336 , mMachine (aMachine)
337{
338 makeIDEList();
339 makeSATAList();
340}
341
342HDSlotUniquizer::~HDSlotUniquizer()
343{
344 mInstance = 0;
345}
346
347QList<HDSltValue> HDSlotUniquizer::list (const HDSltValue &aIncluding,
348 bool aFilter /* = true */)
349{
350 QList<HDSltValue> list = mIDEList + mSATAList;
351 if (!aFilter)
352 return list;
353
354 /* Current used list */
355 QList<HDSltValue> current (mModel->slotsList());
356
357 /* Filter the list */
358 QList<HDSltValue>::iterator it = current.begin();
359 while (it != current.end())
360 {
361 if (*it != aIncluding)
362 list.removeAll (*it);
363 ++ it;
364 }
365
366 return list;
367}
368
369void HDSlotUniquizer::makeIDEList()
370{
371 mIDEList.clear();
372
373 /* IDE Primary Master */
374 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 0, 0),
375 KStorageBus_IDE, 0, 0);
376 /* IDE Primary Slave */
377 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 0, 1),
378 KStorageBus_IDE, 0, 1);
379 /* IDE Secondary Slave */
380 mIDEList << HDSltValue (vboxGlobal().toFullString (KStorageBus_IDE, 1, 1),
381 KStorageBus_IDE, 1, 1);
382}
383
384void HDSlotUniquizer::makeSATAList()
385{
386 mSATAList.clear();
387
388 for (int i = 0; i < mSataCount; ++ i)
389 mSATAList << HDSltValue (vboxGlobal().toFullString (KStorageBus_SATA, i, 0),
390 KStorageBus_SATA, i, 0);
391}
392
393
394VBoxVMSettingsHD::VBoxVMSettingsHD()
395 : mValidator (0)
396{
397 /* Apply UI decorations */
398 Ui::VBoxVMSettingsHD::setupUi (this);
399
400 /* Setup model/view factory */
401 int idHDSlt = qRegisterMetaType<HDSltValue>();
402 int idHDVdi = qRegisterMetaType<HDVdiValue>();
403 QItemEditorFactory *factory = new QItemEditorFactory;
404 QItemEditorCreatorBase *sltCreator =
405 new QStandardItemEditorCreator<HDSltEditor>();
406 QItemEditorCreatorBase *vdiCreator =
407 new QStandardItemEditorCreator<HDVdiEditor>();
408 factory->registerEditor ((QVariant::Type)idHDSlt, sltCreator);
409 factory->registerEditor ((QVariant::Type)idHDVdi, vdiCreator);
410 QItemEditorFactory::setDefaultFactory (factory);
411
412 /* Setup view-model */
413 mModel = new HDItemsModel (this, idHDSlt, idHDVdi);
414 connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
415 this, SIGNAL (hdChanged()));
416
417 /* Setup table-view */
418 mTwAts->verticalHeader()->setDefaultSectionSize (
419 (int) (mTwAts->fontMetrics().height() * 1.40 /* 130% of font height */));
420 mTwAts->verticalHeader()->hide();
421 mTwAts->horizontalHeader()->setStretchLastSection (true);
422 mTwAts->setModel (mModel);
423 mTwAts->setToolTip (mModel->data (mModel->index (mModel->rowCount() - 1, 0),
424 Qt::ToolTipRole).toString());
425
426 /* Prepare actions */
427 mNewAction = new QAction (mTwAts);
428 mDelAction = new QAction (mTwAts);
429 mVdmAction = new QAction (mTwAts);
430
431 mTwAts->addAction (mNewAction);
432 mTwAts->addAction (mDelAction);
433 mTwAts->addAction (mVdmAction);
434
435 mNewAction->setShortcut (QKeySequence ("Ins"));
436 mDelAction->setShortcut (QKeySequence ("Del"));
437 mVdmAction->setShortcut (QKeySequence ("Ctrl+Space"));
438
439 mNewAction->setIcon (VBoxGlobal::iconSet (":/vdm_add_16px.png",
440 ":/vdm_add_disabled_16px.png"));
441 mDelAction->setIcon (VBoxGlobal::iconSet (":/vdm_remove_16px.png",
442 ":/vdm_remove_disabled_16px.png"));
443 mVdmAction->setIcon (VBoxGlobal::iconSet (":/select_file_16px.png",
444 ":/select_file_dis_16px.png"));
445
446 /* Prepare toolbar */
447 VBoxToolBar *toolBar = new VBoxToolBar (mGbAts);
448 toolBar->setUsesTextLabel (false);
449 toolBar->setUsesBigPixmaps (false);
450 toolBar->setOrientation (Qt::Vertical);
451 toolBar->addAction (mNewAction);
452 toolBar->addAction (mDelAction);
453 toolBar->addAction (mVdmAction);
454 mGbAts->layout()->addWidget (toolBar);
455
456 /* Setup connections */
457 connect (mNewAction, SIGNAL (triggered (bool)),
458 this, SLOT (newClicked()));
459 connect (mDelAction, SIGNAL (triggered (bool)),
460 this, SLOT (delClicked()));
461 connect (mVdmAction, SIGNAL (triggered (bool)),
462 this, SLOT (vdmClicked()));
463 connect (mCbSATA, SIGNAL (stateChanged (int)),
464 this, SLOT (cbSATAToggled (int)));
465 connect (mTwAts, SIGNAL (currentChanged (const QModelIndex &)),
466 this, SLOT (onCurrentChanged (const QModelIndex &)));
467 connect (&vboxGlobal(),
468 SIGNAL (mediaRemoved (VBoxDefs::DiskType, const QUuid &)),
469 this, SLOT (onMediaRemoved (VBoxDefs::DiskType, const QUuid &)));
470
471 /* Install global event filter */
472 qApp->installEventFilter (this);
473
474 /* Applying language settings */
475 retranslateUi();
476}
477
478void VBoxVMSettingsHD::getFrom (const CMachine &aMachine)
479{
480 mMachine = aMachine;
481
482 /* Setup slot uniquizer */
483 HDSlotUniquizer::instance (mTwAts, mModel, mMachine);
484
485 CSATAController ctl = mMachine.GetSATAController();
486 /* Hide the SATA check box if the SATA controller is not available
487 * (i.e. in VirtualBox OSE) */
488 if (ctl.isNull())
489 mCbSATA->setHidden (true);
490 else
491 mCbSATA->setChecked (ctl.GetEnabled());
492 cbSATAToggled (mCbSATA->checkState());
493
494 CHardDiskAttachmentEnumerator en =
495 mMachine.GetHardDiskAttachments().Enumerate();
496 while (en.HasMore())
497 {
498 CHardDiskAttachment hda = en.GetNext();
499 HDSltValue slt (vboxGlobal().toFullString (hda.GetBus(),
500 hda.GetChannel(),
501 hda.GetDevice()),
502 hda.GetBus(), hda.GetChannel(), hda.GetDevice());
503 HDVdiValue vdi (VBoxMediaComboBox::fullItemName (hda.GetHardDisk()
504 .GetLocation()),
505 hda.GetHardDisk().GetRoot().GetId());
506 mModel->addItem (slt, vdi);
507 }
508
509 mTwAts->setCurrentIndex (mModel->index (0, 1));
510 onCurrentChanged (mTwAts->currentIndex());
511
512 if (mValidator)
513 mValidator->revalidate();
514}
515
516void VBoxVMSettingsHD::putBackTo()
517{
518 CSATAController ctl = mMachine.GetSATAController();
519 if (!ctl.isNull())
520 {
521 ctl.SetEnabled (mCbSATA->isChecked());
522 }
523
524 /* Detach all attached Hard Disks */
525 CHardDiskAttachmentEnumerator en =
526 mMachine.GetHardDiskAttachments().Enumerate();
527 while (en.HasMore())
528 {
529 CHardDiskAttachment hda = en.GetNext();
530 mMachine.DetachHardDisk (hda.GetBus(), hda.GetChannel(), hda.GetDevice());
531 if (!mMachine.isOk())
532 vboxProblem().cannotDetachHardDisk (this, mMachine,
533 hda.GetBus(), hda.GetChannel(), hda.GetDevice());
534 }
535
536 /* Attach all listed Hard Disks */
537 LONG maxSATAPort = 1;
538 QList<HDValue> list (mModel->fullList());
539 for (int i = 0; i < list.size(); ++ i)
540 {
541 if (list [i].slt.bus == KStorageBus_SATA)
542 maxSATAPort = maxSATAPort < (list [i].slt.channel + 1) ?
543 (list [i].slt.channel + 1) : maxSATAPort;
544 mMachine.AttachHardDisk (list [i].vdi.id,
545 list [i].slt.bus, list [i].slt.channel, list [i].slt.device);
546 if (!mMachine.isOk())
547 vboxProblem().cannotAttachHardDisk (this, mMachine, list [i].vdi.id,
548 list [i].slt.bus, list [i].slt.channel, list [i].slt.device);
549 }
550
551 if (!ctl.isNull())
552 {
553 mMachine.GetSATAController().SetPortCount (maxSATAPort);
554 }
555}
556
557void VBoxVMSettingsHD::setValidator (QIWidgetValidator *aVal)
558{
559 mValidator = aVal;
560 connect (mModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
561 mValidator, SLOT (revalidate()));
562}
563
564bool VBoxVMSettingsHD::revalidate (QString &aWarning, QString &)
565{
566 QList<HDSltValue> sltList (mModel->slotsList());
567 QList<HDVdiValue> vdiList (mModel->vdiList());
568 for (int i = 0; i < vdiList.size(); ++ i)
569 {
570 /* Check for emptiness */
571 if (vdiList [i].name.isNull())
572 {
573 aWarning = tr ("No hard disk is selected for <i>%1</i>")
574 .arg (sltList [i].name);
575 break;
576 }
577
578 /* Check for coincidence */
579 if (vdiList.count (vdiList [i]) > 1)
580 {
581 int first = vdiList.indexOf (vdiList [i]);
582 int second = vdiList.indexOf (vdiList [i], first + 1);
583 Assert (first != -1 && second != -1);
584 aWarning = tr ("<i>%1</i> uses the hard disk that is "
585 "already attached to <i>%2</i>")
586 .arg (sltList [second].name,
587 sltList [first].name);
588 break;
589 }
590 }
591
592 return aWarning.isNull();
593}
594
595void VBoxVMSettingsHD::setOrderAfter (QWidget *aWidget)
596{
597 setTabOrder (aWidget, mCbSATA);
598 setTabOrder (mCbSATA, mTwAts);
599}
600
601void VBoxVMSettingsHD::retranslateUi()
602{
603 /* Translate uic generated strings */
604 Ui::VBoxVMSettingsHD::retranslateUi (this);
605
606 mNewAction->setText (tr ("&Add Attachment"));
607 mDelAction->setText (tr ("&Remove Attachment"));
608 mVdmAction->setText (tr ("&Select Hard Disk"));
609
610 mNewAction->setToolTip (mNewAction->text().remove ('&') +
611 QString (" (%1)").arg (mNewAction->shortcut().toString()));
612 mDelAction->setToolTip (mDelAction->text().remove ('&') +
613 QString (" (%1)").arg (mDelAction->shortcut().toString()));
614 mVdmAction->setToolTip (mVdmAction->text().remove ('&') +
615 QString (" (%1)").arg (mVdmAction->shortcut().toString()));
616
617 mNewAction->setWhatsThis (tr ("Adds a new hard disk attachment."));
618 mDelAction->setWhatsThis (tr ("Removes the highlighted hard disk attachment."));
619 mVdmAction->setWhatsThis (tr ("Invokes the Virtual Disk Manager to select "
620 "a hard disk to attach to the currently "
621 "highlighted slot."));
622}
623
624void VBoxVMSettingsHD::newClicked()
625{
626 /* Remember the current vdis list */
627 QList<HDVdiValue> vdis (mModel->vdiList());
628
629 /* Add new index */
630 mModel->addItem();
631
632 /* Set the default data into the new index for column #1 */
633 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 1));
634 /* Set the default data into the new index for column #0 */
635 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 0));
636
637 /* Set column #1 of new index to be the current */
638 mTwAts->setCurrentIndex (mModel->index (mModel->rowCount() - 2, 1));
639
640 HDVdiEditor *editor = HDVdiEditor::activeEditor();
641 if (editor)
642 {
643 /* Try to select unique vdi */
644 editor->tryToChooseUniqueVdi (vdis);
645
646 /* Ask the user for method to add new vdi */
647 int result = mModel->rowCount() - 1 > editor->count() ?
648 vboxProblem().confirmRunNewHDWzdOrVDM (this) :
649 QIMessageBox::Cancel;
650 if (result == QIMessageBox::Yes)
651 {
652 mTwAts->closePersistentEditor (mTwAts->currentIndex());
653 VBoxNewHDWzd dlg (this);
654 if (dlg.exec() == QDialog::Accepted)
655 {
656 CHardDisk hd = dlg.hardDisk();
657 QVariant result;
658 HDVdiValue val (VBoxMediaComboBox::fullItemName (hd.GetLocation()),
659 hd.GetId());
660 result.setValue (val);
661 mModel->setData (mTwAts->currentIndex(), result);
662 vboxGlobal().startEnumeratingMedia();
663 }
664 }
665 else if (result == QIMessageBox::No)
666 vdmClicked();
667 }
668}
669
670void VBoxVMSettingsHD::delClicked()
671{
672 QModelIndex current = mTwAts->currentIndex();
673 if (current.isValid())
674 {
675 /* Storing current attributes */
676 int row = current.row();
677 int col = current.column();
678
679 /* Erase current index */
680 mTwAts->setCurrentIndex (QModelIndex());
681
682 /* Calculate new current index */
683 int newRow = row < mModel->rowCount() - 2 ? row :
684 row > 0 ? row - 1 : -1;
685 QModelIndex next = newRow == -1 ? mModel->index (0, col) :
686 mModel->index (newRow, col);
687
688 /* Delete current index */
689 mModel->delItem (current.row());
690
691 /* Set the new index to be the current */
692 mTwAts->setCurrentIndex (next);
693 onCurrentChanged (next);
694
695 if (mValidator)
696 mValidator->revalidate();
697 emit hdChanged();
698 }
699}
700
701void VBoxVMSettingsHD::vdmClicked()
702{
703 Assert (mTwAts->currentIndex().isValid());
704
705 VBoxDiskImageManagerDlg dlg (this);
706 QUuid machineId = mMachine.GetId();
707 HDVdiValue vdiInfo (mModel->data (mTwAts->currentIndex(), Qt::EditRole)
708 .value<HDVdiValue>());
709 QUuid hdId = vdiInfo.id;
710 dlg.setup (VBoxDefs::HD, true, &machineId, true, mMachine, hdId);
711
712 if (dlg.exec() == QDialog::Accepted)
713 {
714 QVariant result;
715 HDVdiValue val (VBoxMediaComboBox::fullItemName (dlg.selectedPath()),
716 dlg.selectedUuid());
717 result.setValue (val);
718 mModel->setData (mTwAts->currentIndex(), result);
719 }
720
721 vboxGlobal().startEnumeratingMedia();
722}
723
724void VBoxVMSettingsHD::onCurrentChanged (const QModelIndex &aIndex)
725{
726 mNewAction->setEnabled (mModel->rowCount() - 1 <
727 HDSlotUniquizer::instance()->list (HDSltValue(), false).count());
728 mDelAction->setEnabled (mTwAts->currentIndex().row() != mModel->rowCount() - 1);
729 mVdmAction->setEnabled (aIndex.isValid() && aIndex.column() == 1);
730}
731
732void VBoxVMSettingsHD::cbSATAToggled (int aState)
733{
734 if (aState == Qt::Unchecked)
735 {
736 /* Search the list for at least one SATA port in */
737 QList<HDSltValue> list (mModel->slotsList());
738 int firstSataPort = 0;
739 for (; firstSataPort < list.size(); ++ firstSataPort)
740 if (list [firstSataPort].bus == KStorageBus_SATA)
741 break;
742
743 /* If list contains at least one SATA port */
744 if (firstSataPort < list.size())
745 {
746 int rc = vboxProblem().confirmDetachSATASlots (this);
747 if (rc != QIMessageBox::Ok)
748 {
749 /* Switch check-box back to "Qt::Checked" */
750 mCbSATA->blockSignals (true);
751 mCbSATA->setCheckState (Qt::Checked);
752 mCbSATA->blockSignals (false);
753 return;
754 }
755 else
756 {
757 /* Delete SATA items */
758 mModel->removeSata();
759 if (mValidator)
760 mValidator->revalidate();
761 }
762 }
763 }
764
765 int newSataCount = aState == Qt::Checked ? SATAPortsCount : 0;
766 if (HDSlotUniquizer::instance()->sataCount() != newSataCount)
767 HDSlotUniquizer::instance()->setSataCount (newSataCount);
768 onCurrentChanged (mTwAts->currentIndex());
769}
770
771void VBoxVMSettingsHD::onMediaRemoved (VBoxDefs::DiskType aType, const QUuid &aId)
772{
773 /* Check if it is necessary to update data-model if
774 * some media was removed */
775 if (aType == VBoxDefs::HD)
776 {
777 QList<HDVdiValue> vdis (mModel->vdiList());
778 for (int i = 0; i < vdis.size(); ++ i)
779 {
780 if (vdis [i].id == aId)
781 {
782 QVariant emptyVal;
783 emptyVal.setValue (HDVdiValue());
784 mModel->setData (mModel->index (i, 1), emptyVal);
785 }
786 }
787 }
788}
789
790bool VBoxVMSettingsHD::eventFilter (QObject *aObject, QEvent *aEvent)
791{
792 if (!aObject->isWidgetType())
793 return QWidget::eventFilter (aObject, aEvent);
794
795 QWidget *widget = static_cast<QWidget*> (aObject);
796 if (widget->inherits ("HDSltEditor") ||
797 widget->inherits ("HDVdiEditor"))
798 {
799 if (aEvent->type() == QEvent::KeyPress)
800 {
801 QKeyEvent *e = static_cast<QKeyEvent*> (aEvent);
802 QModelIndex cur = mTwAts->currentIndex();
803 switch (e->key())
804 {
805 case Qt::Key_Up:
806 {
807 if (cur.row() > 0)
808 mTwAts->setCurrentIndex (mModel->index (cur.row() - 1,
809 cur.column()));
810 return true;
811 }
812 case Qt::Key_Down:
813 {
814 if (cur.row() < mModel->rowCount() - 1)
815 mTwAts->setCurrentIndex (mModel->index (cur.row() + 1,
816 cur.column()));
817 return true;
818 }
819 case Qt::Key_Right:
820 {
821 if (cur.column() == 0)
822 mTwAts->setCurrentIndex (mModel->index (cur.row(), 1));
823 return true;
824 }
825 case Qt::Key_Left:
826 {
827 if (cur.column() == 1)
828 mTwAts->setCurrentIndex (mModel->index (cur.row(), 0));
829 return true;
830 }
831 case Qt::Key_Tab:
832 {
833 focusNextPrevChild (true);
834 return true;
835 }
836 case Qt::Key_Backtab:
837 {
838 focusNextPrevChild (false);
839 return true;
840 }
841 default:
842 break;
843 }
844 }
845 } else
846 if (widget == mTwAts->viewport() &&
847 aEvent->type() == QEvent::MouseButtonDblClick)
848 {
849 QMouseEvent *e = static_cast<QMouseEvent*> (aEvent);
850 QModelIndex index = mTwAts->indexAt (e->pos());
851 if (mNewAction->isEnabled() &&
852 (index.row() == mModel->rowCount() - 1 || !index.isValid()))
853 newClicked();
854 }
855
856 return QWidget::eventFilter (aObject, aEvent);
857}
858
859int VBoxVMSettingsHD::maxNameLength() const
860{
861 QList<HDSltValue> fullList (HDSlotUniquizer::instance()
862 ->list (HDSltValue(), false));
863 int maxLength = 0;
864 for (int i = 0; i < fullList.size(); ++ i)
865 {
866 int length = mTwAts->fontMetrics().width (fullList [i].name);
867 maxLength = length > maxLength ? length : maxLength;
868 }
869 return maxLength;
870}
871
872void VBoxVMSettingsHD::showEvent (QShowEvent *aEvent)
873{
874 /* Activate edit triggers now to restrict them during data loading */
875 mTwAts->setEditTriggers (QAbstractItemView::CurrentChanged |
876 QAbstractItemView::SelectedClicked |
877 QAbstractItemView::EditKeyPressed |
878 QAbstractItemView::DoubleClicked);
879
880 /* Temporary activating vertical scrollbar to calculate it's width */
881 mTwAts->setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOn);
882 int width = mTwAts->verticalScrollBar()->width();
883 mTwAts->setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded);
884 QWidget::showEvent (aEvent);
885 mTwAts->horizontalHeader()->resizeSection (0,
886 width + maxNameLength() + 9 * 2 /* 2 margins */);
887
888 /* That little hack allows avoid one of qt4 children focusing bug */
889 QWidget *current = QApplication::focusWidget();
890 mTwAts->setFocus (Qt::TabFocusReason);
891 if (current)
892 current->setFocus (Qt::TabFocusReason);
893}
894
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