VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui.h@ 7442

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

Main: Applied SATA changes from #2406. Increased XML settings version format from 1.2 to 1.3.pre.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 96.8 KB
Line 
1/**
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * "VM settings" dialog UI include (Qt Designer)
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
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
19/****************************************************************************
20** ui.h extension file, included from the uic-generated form implementation.
21**
22** If you wish to add, delete or rename functions or slots use
23** Qt Designer which will update this file, preserving your code. Create an
24** init() function in place of a constructor, and a destroy() function in
25** place of a destructor.
26*****************************************************************************/
27
28
29/**
30 * QDialog class reimplementation to use for adding network interface.
31 * It has one line-edit field for entering network interface's name and
32 * common dialog's ok/cancel buttons.
33 */
34class VBoxAddNIDialog : public QDialog
35{
36 Q_OBJECT
37
38public:
39
40 VBoxAddNIDialog (QWidget *aParent, const QString &aIfaceName) :
41 QDialog (aParent, "VBoxAddNIDialog", true /* modal */),
42 mLeName (0)
43 {
44 setCaption (tr ("Add Host Interface"));
45 QVBoxLayout *mainLayout = new QVBoxLayout (this, 10, 10, "mainLayout");
46
47 /* Setup Input layout */
48 QHBoxLayout *inputLayout = new QHBoxLayout (mainLayout, 10, "inputLayout");
49 QLabel *lbName = new QLabel (tr ("Interface Name"), this);
50 mLeName = new QLineEdit (aIfaceName, this);
51 QWhatsThis::add (mLeName, tr ("Descriptive name of the new network interface"));
52 inputLayout->addWidget (lbName);
53 inputLayout->addWidget (mLeName);
54 connect (mLeName, SIGNAL (textChanged (const QString &)),
55 this, SLOT (validate()));
56
57 /* Setup Button layout */
58 QHBoxLayout *buttonLayout = new QHBoxLayout (mainLayout, 10, "buttonLayout");
59 mBtOk = new QPushButton (tr ("&OK"), this, "mBtOk");
60 QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
61 QPushButton *btCancel = new QPushButton (tr ("Cancel"), this, "btCancel");
62 connect (mBtOk, SIGNAL (clicked()), this, SLOT (accept()));
63 connect (btCancel, SIGNAL (clicked()), this, SLOT (reject()));
64 buttonLayout->addWidget (mBtOk);
65 buttonLayout->addItem (spacer);
66 buttonLayout->addWidget (btCancel);
67
68 /* resize to fit the aIfaceName in one string */
69 int requiredWidth = mLeName->fontMetrics().width (aIfaceName) +
70 mLeName->frameWidth() * 2 +
71 mLeName->lineWidth() * 2 +
72 inputLayout->spacing() +
73 lbName->fontMetrics().width (lbName->text()) +
74 lbName->frameWidth() * 2 +
75 lbName->lineWidth() * 2 +
76 mainLayout->margin() * 2;
77 resize (requiredWidth, minimumHeight());
78
79 /* Validate interface name field */
80 validate();
81 }
82
83 ~VBoxAddNIDialog() {}
84
85 QString getName() { return mLeName->text(); }
86
87private slots:
88
89 void validate()
90 {
91 mBtOk->setEnabled (!mLeName->text().isEmpty());
92 }
93
94private:
95
96 void showEvent (QShowEvent *aEvent)
97 {
98 setFixedHeight (height());
99 QDialog::showEvent (aEvent);
100 }
101
102 QPushButton *mBtOk;
103 QLineEdit *mLeName;
104};
105
106
107/**
108 * Calculates a suitable page step size for the given max value.
109 * The returned size is so that there will be no more than 32 pages.
110 * The minimum returned page size is 4.
111 */
112static int calcPageStep (int aMax)
113{
114 /* reasonable max. number of page steps is 32 */
115 uint page = ((uint) aMax + 31) / 32;
116 /* make it a power of 2 */
117 uint p = page, p2 = 0x1;
118 while ((p >>= 1))
119 p2 <<= 1;
120 if (page != p2)
121 p2 <<= 1;
122 if (p2 < 4)
123 p2 = 4;
124 return (int) p2;
125}
126
127
128/**
129 * QListView class reimplementation to use as boot items table.
130 * It has one unsorted column without header with automated width
131 * resize management.
132 * Keymapping handlers for ctrl-up & ctrl-down are translated into
133 * boot-items up/down moving.
134 */
135class BootItemsTable : public QListView
136{
137 Q_OBJECT
138
139public:
140
141 BootItemsTable (QWidget *aParent, const char *aName)
142 : QListView (aParent, aName)
143 {
144 addColumn (QString::null);
145 header()->hide();
146 setSorting (-1);
147 setColumnWidthMode (0, Maximum);
148 setResizeMode (AllColumns);
149 QWhatsThis::add (this, tr ("Defines the boot device order. "
150 "Use checkboxes to the left to enable or disable "
151 "individual boot devices. Move items up and down to "
152 "change the device order."));
153 setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred);
154 connect (this, SIGNAL (pressed (QListViewItem*)),
155 this, SLOT (processPressed (QListViewItem*)));
156 }
157
158 ~BootItemsTable() {}
159
160 void emitItemToggled() { emit itemToggled(); }
161
162signals:
163
164 void moveItemUp();
165 void moveItemDown();
166 void itemToggled();
167
168private slots:
169
170 void processPressed (QListViewItem *aItem)
171 {
172 if (!aItem)
173 setSelected (currentItem(), true);
174 }
175
176 void keyPressEvent (QKeyEvent *aEvent)
177 {
178 if (aEvent->state() == Qt::ControlButton)
179 {
180 switch (aEvent->key())
181 {
182 case Qt::Key_Up:
183 emit moveItemUp();
184 return;
185 case Qt::Key_Down:
186 emit moveItemDown();
187 return;
188 default:
189 break;
190 }
191 }
192 QListView::keyPressEvent (aEvent);
193 }
194};
195
196
197/**
198 * QWidget class reimplementation to use as boot items widget.
199 * It contains BootItemsTable and two tool-buttons for moving
200 * boot-items up/down.
201 * This widget handles saving/loading CMachine information related
202 * to boot sequience.
203 */
204class BootItemsList : public QWidget
205{
206 Q_OBJECT
207
208 class BootItem : public QCheckListItem
209 {
210 public:
211
212 BootItem (BootItemsTable *aParent, QListViewItem *aAfter,
213 const QString &aName, Type aType)
214 : QCheckListItem (aParent, aAfter, aName, aType) {}
215
216 private:
217
218 void stateChange (bool)
219 {
220 BootItemsTable *table = static_cast<BootItemsTable*> (listView());
221 table->emitItemToggled();
222 }
223 };
224
225public:
226
227 BootItemsList (QWidget *aParent, const char *aName)
228 : QWidget (aParent, aName), mBootTable (0)
229 {
230 /* Setup main widget layout */
231 QHBoxLayout *mainLayout = new QHBoxLayout (this, 0, 6, "mainLayout");
232
233 /* Setup settings layout */
234 mBootTable = new BootItemsTable (this, "mBootTable");
235 connect (mBootTable, SIGNAL (currentChanged (QListViewItem*)),
236 this, SLOT (processCurrentChanged (QListViewItem*)));
237 mainLayout->addWidget (mBootTable);
238
239 /* Setup button's layout */
240 QVBoxLayout *buttonLayout = new QVBoxLayout (mainLayout, 0, "buttonLayout");
241 mBtnUp = new QToolButton (this, "mBtnUp");
242 mBtnDown = new QToolButton (this, "mBtnDown");
243 mBtnUp->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
244 mBtnDown->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
245 QWhatsThis::add (mBtnUp, tr ("Moves the selected boot device up."));
246 QWhatsThis::add (mBtnDown, tr ("Moves the selected boot device down."));
247 QToolTip::add (mBtnUp, tr ("Move Up (Ctrl-Up)"));
248 QToolTip::add (mBtnDown, tr ("Move Down (Ctrl-Down)"));
249 mBtnUp->setAutoRaise (true);
250 mBtnDown->setAutoRaise (true);
251 mBtnUp->setFocusPolicy (QWidget::StrongFocus);
252 mBtnDown->setFocusPolicy (QWidget::StrongFocus);
253 mBtnUp->setIconSet (VBoxGlobal::iconSet ("list_moveup_16px.png",
254 "list_moveup_disabled_16px.png"));
255 mBtnDown->setIconSet (VBoxGlobal::iconSet ("list_movedown_16px.png",
256 "list_movedown_disabled_16px.png"));
257 QSpacerItem *spacer = new QSpacerItem (0, 0, QSizePolicy::Minimum,
258 QSizePolicy::Minimum);
259 connect (mBtnUp, SIGNAL (clicked()), this, SLOT (moveItemUp()));
260 connect (mBtnDown, SIGNAL (clicked()), this, SLOT (moveItemDown()));
261 connect (mBootTable, SIGNAL (moveItemUp()), this, SLOT (moveItemUp()));
262 connect (mBootTable, SIGNAL (moveItemDown()), this, SLOT (moveItemDown()));
263 connect (mBootTable, SIGNAL (itemToggled()), this, SLOT (onItemToggled()));
264 buttonLayout->addWidget (mBtnUp);
265 buttonLayout->addWidget (mBtnDown);
266 buttonLayout->addItem (spacer);
267
268 /* Setup focus proxy for BootItemsList */
269 setFocusProxy (mBootTable);
270 }
271
272 ~BootItemsList() {}
273
274 void fixTabStops()
275 {
276 /* fix focus order for BootItemsList */
277 setTabOrder (mBootTable, mBtnUp);
278 setTabOrder (mBtnUp, mBtnDown);
279 }
280
281 void getFromMachine (const CMachine &aMachine)
282 {
283 /* Load boot-items of current VM */
284 QStringList uniqueList;
285 int minimumWidth = 0;
286 for (int i = 1; i <= 4; ++ i)
287 {
288 KDeviceType type = aMachine.GetBootOrder (i);
289 if (type != KDeviceType_Null)
290 {
291 QString name = vboxGlobal().toString (type);
292 QCheckListItem *item = new BootItem (mBootTable,
293 mBootTable->lastItem(), name, QCheckListItem::CheckBox);
294 item->setOn (true);
295 uniqueList << name;
296 int width = item->width (mBootTable->fontMetrics(), mBootTable, 0);
297 if (width > minimumWidth) minimumWidth = width;
298 }
299 }
300 /* Load other unique boot-items */
301 for (int i = KDeviceType_Floppy; i < KDeviceType_USB; ++ i)
302 {
303 QString name = vboxGlobal().toString ((KDeviceType) i);
304 if (!uniqueList.contains (name))
305 {
306 QCheckListItem *item = new BootItem (mBootTable,
307 mBootTable->lastItem(), name, QCheckListItem::CheckBox);
308 uniqueList << name;
309 int width = item->width (mBootTable->fontMetrics(), mBootTable, 0);
310 if (width > minimumWidth) minimumWidth = width;
311 }
312 }
313 processCurrentChanged (mBootTable->firstChild());
314 mBootTable->setFixedWidth (minimumWidth +
315 4 /* viewport margin */);
316 mBootTable->setFixedHeight (mBootTable->childCount() *
317 mBootTable->firstChild()->totalHeight() +
318 4 /* viewport margin */);
319 }
320
321 void putBackToMachine (CMachine &aMachine)
322 {
323 QCheckListItem *item = 0;
324 /* Search for checked items */
325 int index = 1;
326 item = static_cast<QCheckListItem*> (mBootTable->firstChild());
327 while (item)
328 {
329 if (item->isOn())
330 {
331 KDeviceType type =
332 vboxGlobal().toDeviceType (item->text (0));
333 aMachine.SetBootOrder (index++, type);
334 }
335 item = static_cast<QCheckListItem*> (item->nextSibling());
336 }
337 /* Search for non-checked items */
338 item = static_cast<QCheckListItem*> (mBootTable->firstChild());
339 while (item)
340 {
341 if (!item->isOn())
342 aMachine.SetBootOrder (index++, KDeviceType_Null);
343 item = static_cast<QCheckListItem*> (item->nextSibling());
344 }
345 }
346
347 void processFocusIn (QWidget *aWidget)
348 {
349 if (aWidget == mBootTable)
350 {
351 mBootTable->setSelected (mBootTable->currentItem(), true);
352 processCurrentChanged (mBootTable->currentItem());
353 }
354 else if (aWidget != mBtnUp && aWidget != mBtnDown)
355 {
356 mBootTable->setSelected (mBootTable->currentItem(), false);
357 processCurrentChanged (mBootTable->currentItem());
358 }
359 }
360
361signals:
362
363 void bootSequenceChanged();
364
365private slots:
366
367 void moveItemUp()
368 {
369 QListViewItem *item = mBootTable->currentItem();
370 Assert (item);
371 QListViewItem *itemAbove = item->itemAbove();
372 if (!itemAbove) return;
373 itemAbove->moveItem (item);
374 processCurrentChanged (item);
375 emit bootSequenceChanged();
376 }
377
378 void moveItemDown()
379 {
380 QListViewItem *item = mBootTable->currentItem();
381 Assert (item);
382 QListViewItem *itemBelow = item->itemBelow();
383 if (!itemBelow) return;
384 item->moveItem (itemBelow);
385 processCurrentChanged (item);
386 emit bootSequenceChanged();
387 }
388
389 void onItemToggled()
390 {
391 emit bootSequenceChanged();
392 }
393
394 void processCurrentChanged (QListViewItem *aItem)
395 {
396 bool upEnabled = aItem && aItem->isSelected() && aItem->itemAbove();
397 bool downEnabled = aItem && aItem->isSelected() && aItem->itemBelow();
398 if ((mBtnUp->hasFocus() && !upEnabled) ||
399 (mBtnDown->hasFocus() && !downEnabled))
400 mBootTable->setFocus();
401 mBtnUp->setEnabled (upEnabled);
402 mBtnDown->setEnabled (downEnabled);
403 }
404
405private:
406
407 BootItemsTable *mBootTable;
408 QToolButton *mBtnUp;
409 QToolButton *mBtnDown;
410};
411
412
413/// @todo (dmik) remove?
414///**
415// * Returns the through position of the item in the list view.
416// */
417//static int pos (QListView *lv, QListViewItem *li)
418//{
419// QListViewItemIterator it (lv);
420// int p = -1, c = 0;
421// while (it.current() && p < 0)
422// {
423// if (it.current() == li)
424// p = c;
425// ++ it;
426// ++ c;
427// }
428// return p;
429//}
430
431class USBListItem : public QCheckListItem
432{
433public:
434
435 USBListItem (QListView *aParent, QListViewItem *aAfter)
436 : QCheckListItem (aParent, aAfter, QString::null, CheckBox)
437 , mId (-1) {}
438
439 int mId;
440};
441
442/**
443 * Returns the path to the item in the form of 'grandparent > parent > item'
444 * using the text of the first column of every item.
445 */
446static QString path (QListViewItem *li)
447{
448 static QString sep = ": ";
449 QString p;
450 QListViewItem *cur = li;
451 while (cur)
452 {
453 if (!p.isNull())
454 p = sep + p;
455 p = cur->text (0).simplifyWhiteSpace() + p;
456 cur = cur->parent();
457 }
458 return p;
459}
460
461enum
462{
463 /* listView column numbers */
464 listView_Category = 0,
465 listView_Id = 1,
466 listView_Link = 2,
467 /* lvUSBFilters column numbers */
468 lvUSBFilters_Name = 0,
469};
470
471
472void VBoxVMSettingsDlg::init()
473{
474 polished = false;
475
476 /* disallow resetting First Run Wizard flag until media enumeration
477 * process is finished and all data is finally loaded into ui */
478 mAllowResetFirstRunFlag = false;
479 connect (&vboxGlobal(), SIGNAL (mediaEnumFinished (const VBoxMediaList &)),
480 this, SLOT (onMediaEnumerationDone()));
481
482 setIcon (QPixmap::fromMimeSource ("settings_16px.png"));
483
484 /* all pages are initially valid */
485 valid = true;
486 buttonOk->setEnabled( true );
487
488 /* disable unselecting items by clicking in the unused area of the list */
489 new QIListViewSelectionPreserver (this, listView);
490 /* hide the header and internal columns */
491 listView->header()->hide();
492 listView->setColumnWidthMode (listView_Id, QListView::Manual);
493 listView->setColumnWidthMode (listView_Link, QListView::Manual);
494 listView->hideColumn (listView_Id);
495 listView->hideColumn (listView_Link);
496 /* sort by the id column (to have pages in the desired order) */
497 listView->setSorting (listView_Id);
498 listView->sort();
499 /* disable further sorting (important for network adapters) */
500 listView->setSorting (-1);
501 /* set the first item selected */
502 listView->setSelected (listView->firstChild(), true);
503 listView_currentChanged (listView->firstChild());
504 /* setup status bar icon */
505 warningPixmap->setMaximumSize( 16, 16 );
506 warningPixmap->setPixmap( QMessageBox::standardIcon( QMessageBox::Warning ) );
507
508 /* page title font is derived from the system font */
509 QFont f = font();
510 f.setBold (true);
511 f.setPointSize (f.pointSize() + 2);
512 titleLabel->setFont (f);
513
514 /* setup the what's this label */
515 QApplication::setGlobalMouseTracking (true);
516 qApp->installEventFilter (this);
517 whatsThisTimer = new QTimer (this);
518 connect (whatsThisTimer, SIGNAL (timeout()), this, SLOT (updateWhatsThis()));
519 whatsThisCandidate = NULL;
520
521 whatsThisLabel = new QIRichLabel (this, "whatsThisLabel");
522 VBoxVMSettingsDlgLayout->addWidget (whatsThisLabel, 2, 1);
523
524#ifndef DEBUG
525 /* Enforce rich text format to avoid jumping margins (margins of plain
526 * text labels seem to be smaller). We don't do it in the DEBUG builds to
527 * be able to immediately catch badly formatted text (i.e. text that
528 * contains HTML tags but doesn't start with <qt> so that Qt isn't able to
529 * recognize it as rich text and draws all tags as is instead of doing
530 * formatting). We want to catch this text because this is how it will look
531 * in the whatsthis balloon where we cannot enforce rich text. */
532 whatsThisLabel->setTextFormat (Qt::RichText);
533#endif
534
535 whatsThisLabel->setMaxHeightMode (true);
536 whatsThisLabel->setFocusPolicy (QWidget::NoFocus);
537 whatsThisLabel->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);
538 whatsThisLabel->setBackgroundMode (QLabel::PaletteMidlight);
539 whatsThisLabel->setFrameShape (QLabel::Box);
540 whatsThisLabel->setFrameShadow (QLabel::Sunken);
541 whatsThisLabel->setMargin (7);
542 whatsThisLabel->setScaledContents (FALSE);
543 whatsThisLabel->setAlignment (int (QLabel::WordBreak |
544 QLabel::AlignJustify |
545 QLabel::AlignTop));
546
547 whatsThisLabel->setFixedHeight (whatsThisLabel->frameWidth() * 2 +
548 6 /* seems that RichText adds some margin */ +
549 whatsThisLabel->fontMetrics().lineSpacing() * 4);
550 whatsThisLabel->setMinimumWidth (whatsThisLabel->frameWidth() * 2 +
551 6 /* seems that RichText adds some margin */ +
552 whatsThisLabel->fontMetrics().width ('m') * 40);
553
554 /*
555 * setup connections and set validation for pages
556 * ----------------------------------------------------------------------
557 */
558
559 /* General page */
560
561 CSystemProperties sysProps = vboxGlobal().virtualBox().GetSystemProperties();
562
563 const uint MinRAM = sysProps.GetMinGuestRAM();
564 const uint MaxRAM = sysProps.GetMaxGuestRAM();
565 const uint MinVRAM = sysProps.GetMinGuestVRAM();
566 const uint MaxVRAM = sysProps.GetMaxGuestVRAM();
567
568 leName->setValidator (new QRegExpValidator (QRegExp (".+"), this));
569
570 leRAM->setValidator (new QIntValidator (MinRAM, MaxRAM, this));
571 leVRAM->setValidator (new QIntValidator (MinVRAM, MaxVRAM, this));
572
573 wvalGeneral = new QIWidgetValidator (pagePath (pageGeneral), pageGeneral, this);
574 connect (wvalGeneral, SIGNAL (validityChanged (const QIWidgetValidator *)),
575 this, SLOT(enableOk (const QIWidgetValidator *)));
576
577 tbSelectSavedStateFolder->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
578 "select_file_dis_16px.png"));
579 tbResetSavedStateFolder->setIconSet (VBoxGlobal::iconSet ("eraser_16px.png",
580 "eraser_disabled_16px.png"));
581
582 teDescription->setTextFormat (Qt::PlainText);
583
584 /* HDD Images page */
585
586 QWhatsThis::add (static_cast <QWidget *> (grbHDA->child ("qt_groupbox_checkbox")),
587 tr ("When checked, attaches the specified virtual hard disk to the "
588 "Master slot of the Primary IDE controller."));
589 QWhatsThis::add (static_cast <QWidget *> (grbHDB->child ("qt_groupbox_checkbox")),
590 tr ("When checked, attaches the specified virtual hard disk to the "
591 "Slave slot of the Primary IDE controller."));
592 QWhatsThis::add (static_cast <QWidget *> (grbHDD->child ("qt_groupbox_checkbox")),
593 tr ("When checked, attaches the specified virtual hard disk to the "
594 "Slave slot of the Secondary IDE controller."));
595 cbHDA = new VBoxMediaComboBox (grbHDA, "cbHDA", VBoxDefs::HD);
596 cbHDB = new VBoxMediaComboBox (grbHDB, "cbHDB", VBoxDefs::HD);
597 cbHDD = new VBoxMediaComboBox (grbHDD, "cbHDD", VBoxDefs::HD);
598 hdaLayout->insertWidget (0, cbHDA);
599 hdbLayout->insertWidget (0, cbHDB);
600 hddLayout->insertWidget (0, cbHDD);
601 /* sometimes the weirdness of Qt just kills... */
602 setTabOrder (static_cast <QWidget *> (grbHDA->child ("qt_groupbox_checkbox")),
603 cbHDA);
604 setTabOrder (static_cast <QWidget *> (grbHDB->child ("qt_groupbox_checkbox")),
605 cbHDB);
606 setTabOrder (static_cast <QWidget *> (grbHDD->child ("qt_groupbox_checkbox")),
607 cbHDD);
608
609 QWhatsThis::add (cbHDB, tr ("Displays the virtual hard disk to attach to this IDE slot "
610 "and allows to quickly select a different hard disk."));
611 QWhatsThis::add (cbHDD, tr ("Displays the virtual hard disk to attach to this IDE slot "
612 "and allows to quickly select a different hard disk."));
613 QWhatsThis::add (cbHDA, tr ("Displays the virtual hard disk to attach to this IDE slot "
614 "and allows to quickly select a different hard disk."));
615 QWhatsThis::add (cbHDB, tr ("Displays the virtual hard disk to attach to this IDE slot "
616 "and allows to quickly select a different hard disk."));
617 QWhatsThis::add (cbHDD, tr ("Displays the virtual hard disk to attach to this IDE slot "
618 "and allows to quickly select a different hard disk."));
619
620 wvalHDD = new QIWidgetValidator (pagePath (pageHDD), pageHDD, this);
621 connect (wvalHDD, SIGNAL (validityChanged (const QIWidgetValidator *)),
622 this, SLOT (enableOk (const QIWidgetValidator *)));
623 connect (wvalHDD, SIGNAL (isValidRequested (QIWidgetValidator *)),
624 this, SLOT (revalidate (QIWidgetValidator *)));
625
626 connect (grbHDA, SIGNAL (toggled (bool)), this, SLOT (hdaMediaChanged()));
627 connect (grbHDB, SIGNAL (toggled (bool)), this, SLOT (hdbMediaChanged()));
628 connect (grbHDD, SIGNAL (toggled (bool)), this, SLOT (hddMediaChanged()));
629 connect (cbHDA, SIGNAL (activated (int)), this, SLOT (hdaMediaChanged()));
630 connect (cbHDB, SIGNAL (activated (int)), this, SLOT (hdbMediaChanged()));
631 connect (cbHDD, SIGNAL (activated (int)), this, SLOT (hddMediaChanged()));
632 connect (tbHDA, SIGNAL (clicked()), this, SLOT (showImageManagerHDA()));
633 connect (tbHDB, SIGNAL (clicked()), this, SLOT (showImageManagerHDB()));
634 connect (tbHDD, SIGNAL (clicked()), this, SLOT (showImageManagerHDD()));
635
636 /* setup iconsets -- qdesigner is not capable... */
637 tbHDA->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
638 "select_file_dis_16px.png"));
639 tbHDB->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
640 "select_file_dis_16px.png"));
641 tbHDD->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
642 "select_file_dis_16px.png"));
643
644 /* CD/DVD-ROM Drive Page */
645
646 QWhatsThis::add (static_cast <QWidget *> (bgDVD->child ("qt_groupbox_checkbox")),
647 tr ("When checked, mounts the specified media to the CD/DVD drive of the "
648 "virtual machine. Note that the CD/DVD drive is always connected to the "
649 "Secondary Master IDE controller of the machine."));
650 cbISODVD = new VBoxMediaComboBox (bgDVD, "cbISODVD", VBoxDefs::CD);
651 cdLayout->insertWidget(0, cbISODVD);
652 QWhatsThis::add (cbISODVD, tr ("Displays the image file to mount to the virtual CD/DVD "
653 "drive and allows to quickly select a different image."));
654
655 wvalDVD = new QIWidgetValidator (pagePath (pageDVD), pageDVD, this);
656 connect (wvalDVD, SIGNAL (validityChanged (const QIWidgetValidator *)),
657 this, SLOT (enableOk (const QIWidgetValidator *)));
658 connect (wvalDVD, SIGNAL (isValidRequested (QIWidgetValidator *)),
659 this, SLOT (revalidate( QIWidgetValidator *)));
660
661 connect (bgDVD, SIGNAL (toggled (bool)), this, SLOT (cdMediaChanged()));
662 connect (rbHostDVD, SIGNAL (stateChanged (int)), wvalDVD, SLOT (revalidate()));
663 connect (rbISODVD, SIGNAL (stateChanged (int)), wvalDVD, SLOT (revalidate()));
664 connect (cbISODVD, SIGNAL (activated (int)), this, SLOT (cdMediaChanged()));
665 connect (tbISODVD, SIGNAL (clicked()), this, SLOT (showImageManagerISODVD()));
666
667 /* setup iconsets -- qdesigner is not capable... */
668 tbISODVD->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
669 "select_file_dis_16px.png"));
670
671 /* Floppy Drive Page */
672
673 QWhatsThis::add (static_cast <QWidget *> (bgFloppy->child ("qt_groupbox_checkbox")),
674 tr ("When checked, mounts the specified media to the Floppy drive of the "
675 "virtual machine."));
676 cbISOFloppy = new VBoxMediaComboBox (bgFloppy, "cbISOFloppy", VBoxDefs::FD);
677 fdLayout->insertWidget(0, cbISOFloppy);
678 QWhatsThis::add (cbISOFloppy, tr ("Displays the image file to mount to the virtual Floppy "
679 "drive and allows to quickly select a different image."));
680
681 wvalFloppy = new QIWidgetValidator (pagePath (pageFloppy), pageFloppy, this);
682 connect (wvalFloppy, SIGNAL (validityChanged (const QIWidgetValidator *)),
683 this, SLOT (enableOk (const QIWidgetValidator *)));
684 connect (wvalFloppy, SIGNAL (isValidRequested (QIWidgetValidator *)),
685 this, SLOT (revalidate( QIWidgetValidator *)));
686
687 connect (bgFloppy, SIGNAL (toggled (bool)), this, SLOT (fdMediaChanged()));
688 connect (rbHostFloppy, SIGNAL (stateChanged (int)), wvalFloppy, SLOT (revalidate()));
689 connect (rbISOFloppy, SIGNAL (stateChanged (int)), wvalFloppy, SLOT (revalidate()));
690 connect (cbISOFloppy, SIGNAL (activated (int)), this, SLOT (fdMediaChanged()));
691 connect (tbISOFloppy, SIGNAL (clicked()), this, SLOT (showImageManagerISOFloppy()));
692
693 /* setup iconsets -- qdesigner is not capable... */
694 tbISOFloppy->setIconSet (VBoxGlobal::iconSet ("select_file_16px.png",
695 "select_file_dis_16px.png"));
696
697 /* Audio Page */
698
699 QWhatsThis::add (static_cast <QWidget *> (grbAudio->child ("qt_groupbox_checkbox")),
700 tr ("When checked, the virtual PCI audio card is plugged into the "
701 "virtual machine that uses the specified driver to communicate "
702 "to the host audio card."));
703
704 /* Network Page */
705
706#ifndef Q_WS_WIN
707 gbInterfaceList->setHidden (true);
708#endif
709 /* setup tab widget */
710 mNoInterfaces = tr ("<No suitable interfaces>");
711 /* setup iconsets */
712 pbHostAdd->setIconSet (VBoxGlobal::iconSet ("add_host_iface_16px.png",
713 "add_host_iface_disabled_16px.png"));
714 pbHostRemove->setIconSet (VBoxGlobal::iconSet ("remove_host_iface_16px.png",
715 "remove_host_iface_disabled_16px.png"));
716 /* setup languages */
717 QToolTip::add (pbHostAdd, tr ("Add"));
718 QToolTip::add (pbHostRemove, tr ("Remove"));
719
720 /* Serial Port Page */
721
722 /* Parallel Port Page (currently disabled) */
723 QListViewItem *item = listView->findItem ("#parallelPorts", listView_Link);
724 if (item) item->setVisible (false);
725
726 /* USB Page */
727
728 connect (cbEnableUSBController, SIGNAL (toggled (bool)),
729 this, SLOT (usbAdapterToggled (bool)));
730
731 lvUSBFilters->header()->hide();
732 /* disable sorting */
733 lvUSBFilters->setSorting (-1);
734 /* disable unselecting items by clicking in the unused area of the list */
735 new QIListViewSelectionPreserver (this, lvUSBFilters);
736 /* create the widget stack for filter settings */
737 /// @todo (r=dmik) having a separate settings widget for every USB filter
738 // is not that smart if there are lots of USB filters. The reason for
739 // stacking here is that the stacked widget is used to temporarily store
740 // data of the associated USB filter until the dialog window is accepted.
741 // If we remove stacking, we will have to create a structure to store
742 // editable data of all USB filters while the dialog is open.
743 wstUSBFilters = new QWidgetStack (grbUSBFilters, "wstUSBFilters");
744 grbUSBFiltersLayout->addWidget (wstUSBFilters);
745 /* create a default (disabled) filter settings widget at index 0 */
746 VBoxUSBFilterSettings *settings = new VBoxUSBFilterSettings (wstUSBFilters);
747 settings->setup (VBoxUSBFilterSettings::MachineType);
748 wstUSBFilters->addWidget (settings, 0);
749 lvUSBFilters_currentChanged (NULL);
750
751 /* setup iconsets -- qdesigner is not capable... */
752 tbAddUSBFilter->setIconSet (VBoxGlobal::iconSet ("usb_new_16px.png",
753 "usb_new_disabled_16px.png"));
754 tbAddUSBFilterFrom->setIconSet (VBoxGlobal::iconSet ("usb_add_16px.png",
755 "usb_add_disabled_16px.png"));
756 tbRemoveUSBFilter->setIconSet (VBoxGlobal::iconSet ("usb_remove_16px.png",
757 "usb_remove_disabled_16px.png"));
758 tbUSBFilterUp->setIconSet (VBoxGlobal::iconSet ("usb_moveup_16px.png",
759 "usb_moveup_disabled_16px.png"));
760 tbUSBFilterDown->setIconSet (VBoxGlobal::iconSet ("usb_movedown_16px.png",
761 "usb_movedown_disabled_16px.png"));
762 usbDevicesMenu = new VBoxUSBMenu (this);
763 connect (usbDevicesMenu, SIGNAL(activated(int)), this, SLOT(menuAddUSBFilterFrom_activated(int)));
764 mUSBFilterListModified = false;
765
766 /* VRDP Page */
767
768 QWhatsThis::add (static_cast <QWidget *> (grbVRDP->child ("qt_groupbox_checkbox")),
769 tr ("When checked, the VM will act as a Remote Desktop "
770 "Protocol (RDP) server, allowing remote clients to connect "
771 "and operate the VM (when it is running) "
772 "using a standard RDP client."));
773
774 leVRDPPort->setValidator (new QIntValidator (0, 0xFFFF, this));
775 leVRDPTimeout->setValidator (new QIntValidator (this));
776 wvalVRDP = new QIWidgetValidator (pagePath (pageVRDP), pageVRDP, this);
777 connect (wvalVRDP, SIGNAL (validityChanged (const QIWidgetValidator *)),
778 this, SLOT (enableOk (const QIWidgetValidator *)));
779 connect (wvalVRDP, SIGNAL (isValidRequested (QIWidgetValidator *)),
780 this, SLOT (revalidate( QIWidgetValidator *)));
781
782 connect (grbVRDP, SIGNAL (toggled (bool)), wvalFloppy, SLOT (revalidate()));
783 connect (leVRDPPort, SIGNAL (textChanged (const QString&)), wvalFloppy, SLOT (revalidate()));
784 connect (leVRDPTimeout, SIGNAL (textChanged (const QString&)), wvalFloppy, SLOT (revalidate()));
785
786 /* Shared Folders Page */
787
788 QVBoxLayout* pageFoldersLayout = new QVBoxLayout (pageFolders, 0, 10, "pageFoldersLayout");
789 mSharedFolders = new VBoxSharedFoldersSettings (pageFolders, "sharedFolders");
790 mSharedFolders->setDialogType (VBoxSharedFoldersSettings::MachineType);
791 pageFoldersLayout->addWidget (mSharedFolders);
792
793 /*
794 * set initial values
795 * ----------------------------------------------------------------------
796 */
797
798 /* General page */
799
800 cbOS->insertStringList (vboxGlobal().vmGuestOSTypeDescriptions());
801
802 slRAM->setPageStep (calcPageStep (MaxRAM));
803 slRAM->setLineStep (slRAM->pageStep() / 4);
804 slRAM->setTickInterval (slRAM->pageStep());
805 /* setup the scale so that ticks are at page step boundaries */
806 slRAM->setMinValue ((MinRAM / slRAM->pageStep()) * slRAM->pageStep());
807 slRAM->setMaxValue (MaxRAM);
808 txRAMMin->setText (tr ("<qt>%1&nbsp;MB</qt>").arg (MinRAM));
809 txRAMMax->setText (tr ("<qt>%1&nbsp;MB</qt>").arg (MaxRAM));
810 /* limit min/max. size of QLineEdit */
811 leRAM->setMaximumSize (leRAM->fontMetrics().width ("99999")
812 + leRAM->frameWidth() * 2,
813 leRAM->minimumSizeHint().height());
814 leRAM->setMinimumSize (leRAM->maximumSize());
815 /* ensure leRAM value and validation is updated */
816 slRAM_valueChanged (slRAM->value());
817
818 slVRAM->setPageStep (calcPageStep (MaxVRAM));
819 slVRAM->setLineStep (slVRAM->pageStep() / 4);
820 slVRAM->setTickInterval (slVRAM->pageStep());
821 /* setup the scale so that ticks are at page step boundaries */
822 slVRAM->setMinValue ((MinVRAM / slVRAM->pageStep()) * slVRAM->pageStep());
823 slVRAM->setMaxValue (MaxVRAM);
824 txVRAMMin->setText (tr ("<qt>%1&nbsp;MB</qt>").arg (MinVRAM));
825 txVRAMMax->setText (tr ("<qt>%1&nbsp;MB</qt>").arg (MaxVRAM));
826 /* limit min/max. size of QLineEdit */
827 leVRAM->setMaximumSize (leVRAM->fontMetrics().width ("99999")
828 + leVRAM->frameWidth() * 2,
829 leVRAM->minimumSizeHint().height());
830 leVRAM->setMinimumSize (leVRAM->maximumSize());
831 /* ensure leVRAM value and validation is updated */
832 slVRAM_valueChanged (slVRAM->value());
833
834 /* Boot-order table */
835 tblBootOrder = new BootItemsList (groupBox12, "tblBootOrder");
836 connect (tblBootOrder, SIGNAL (bootSequenceChanged()),
837 this, SLOT (resetFirstRunFlag()));
838
839 /* Fixing focus order for BootItemsList */
840 setTabOrder (tbwGeneral, tblBootOrder);
841 setTabOrder (tblBootOrder->focusProxy(), chbEnableACPI);
842 groupBox12Layout->addWidget (tblBootOrder);
843 tblBootOrder->fixTabStops();
844 /* Shared Clipboard mode */
845 cbSharedClipboard->insertItem (vboxGlobal().toString (KClipboardMode_Disabled));
846 cbSharedClipboard->insertItem (vboxGlobal().toString (KClipboardMode_HostToGuest));
847 cbSharedClipboard->insertItem (vboxGlobal().toString (KClipboardMode_GuestToHost));
848 cbSharedClipboard->insertItem (vboxGlobal().toString (KClipboardMode_Bidirectional));
849 /* IDE Controller Type */
850 cbIdeController->insertItem (vboxGlobal().toString (KIDEControllerType_PIIX3));
851 cbIdeController->insertItem (vboxGlobal().toString (KIDEControllerType_PIIX4));
852
853 /* HDD Images page */
854
855 /* CD-ROM Drive Page */
856
857 /* Audio Page */
858
859 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_Null));
860#if defined Q_WS_WIN32
861 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_DSOUND));
862# ifdef VBOX_WITH_WINMM
863 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_WINMM));
864# endif
865#elif defined Q_OS_LINUX
866 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_OSS));
867# ifdef VBOX_WITH_ALSA
868 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_ALSA));
869# endif
870# ifdef VBOX_WITH_PULSE
871 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_Pulse));
872# endif
873#elif defined Q_OS_MACX
874 cbAudioDriver->insertItem (vboxGlobal().toString (KAudioDriverType_Core));
875#endif
876
877 cbAudioController->insertItem (vboxGlobal().toString (KAudioControllerType_AC97));
878 cbAudioController->insertItem (vboxGlobal().toString (KAudioControllerType_SB16));
879
880 /* Network Page */
881
882 loadInterfacesList();
883 loadNetworksList();
884
885 /*
886 * update the Ok button state for pages with validation
887 * (validityChanged() connected to enableNext() will do the job)
888 */
889 wvalGeneral->revalidate();
890 wvalHDD->revalidate();
891 wvalDVD->revalidate();
892 wvalFloppy->revalidate();
893
894 /* VRDP Page */
895
896 cbVRDPAuthType->insertItem (vboxGlobal().toString (KVRDPAuthType_Null));
897 cbVRDPAuthType->insertItem (vboxGlobal().toString (KVRDPAuthType_External));
898 cbVRDPAuthType->insertItem (vboxGlobal().toString (KVRDPAuthType_Guest));
899}
900
901/**
902 * Returns a path to the given page of this settings dialog. See ::path() for
903 * details.
904 */
905QString VBoxVMSettingsDlg::pagePath (QWidget *aPage)
906{
907 QListViewItem *li = listView->
908 findItem (QString::number (widgetStack->id (aPage)), 1);
909 return ::path (li);
910}
911
912bool VBoxVMSettingsDlg::eventFilter (QObject *object, QEvent *event)
913{
914 if (!object->isWidgetType())
915 return QDialog::eventFilter (object, event);
916
917 QWidget *widget = static_cast <QWidget *> (object);
918 if (widget->topLevelWidget() != this)
919 return QDialog::eventFilter (object, event);
920
921 switch (event->type())
922 {
923 case QEvent::Enter:
924 case QEvent::Leave:
925 {
926 if (event->type() == QEvent::Enter)
927 whatsThisCandidate = widget;
928 else
929 whatsThisCandidate = NULL;
930 whatsThisTimer->start (100, true /* sshot */);
931 break;
932 }
933 case QEvent::FocusIn:
934 {
935 updateWhatsThis (true /* gotFocus */);
936 tblBootOrder->processFocusIn (widget);
937 break;
938 }
939 default:
940 break;
941 }
942
943 return QDialog::eventFilter (object, event);
944}
945
946void VBoxVMSettingsDlg::showEvent (QShowEvent *e)
947{
948 QDialog::showEvent (e);
949
950 /* one may think that QWidget::polish() is the right place to do things
951 * below, but apparently, by the time when QWidget::polish() is called,
952 * the widget style & layout are not fully done, at least the minimum
953 * size hint is not properly calculated. Since this is sometimes necessary,
954 * we provide our own "polish" implementation. */
955
956 if (polished)
957 return;
958
959 polished = true;
960
961 /* update geometry for the dynamically added usb-page to ensure proper
962 * sizeHint calculation by the Qt layout manager */
963 wstUSBFilters->updateGeometry();
964 /* let our toplevel widget calculate its sizeHint properly */
965 QApplication::sendPostedEvents (0, 0);
966
967 layout()->activate();
968
969 /* resize to the miminum possible size */
970 resize (minimumSize());
971
972 VBoxGlobal::centerWidget (this, parentWidget());
973}
974
975void VBoxVMSettingsDlg::updateShortcuts()
976{
977 /* setup necessary combobox item */
978 cbHDA->setCurrentItem (uuidHDA);
979 cbHDB->setCurrentItem (uuidHDB);
980 cbHDD->setCurrentItem (uuidHDD);
981 cbISODVD->setCurrentItem (uuidISODVD);
982 cbISOFloppy->setCurrentItem (uuidISOFloppy);
983 /* check if the enumeration process has been started yet */
984 if (!vboxGlobal().isMediaEnumerationStarted())
985 vboxGlobal().startEnumeratingMedia();
986 else
987 {
988 cbHDA->refresh();
989 cbHDB->refresh();
990 cbHDD->refresh();
991 cbISODVD->refresh();
992 cbISOFloppy->refresh();
993 }
994}
995
996void VBoxVMSettingsDlg::loadInterfacesList()
997{
998#if defined Q_WS_WIN
999 /* clear inner list */
1000 mInterfaceList.clear();
1001 /* load current inner list */
1002 CHostNetworkInterfaceEnumerator en =
1003 vboxGlobal().virtualBox().GetHost().GetNetworkInterfaces().Enumerate();
1004 while (en.HasMore())
1005 mInterfaceList += en.GetNext().GetName();
1006 /* save current list item name */
1007 QString currentListItemName = lbHostInterface->currentText();
1008 /* load current list items */
1009 lbHostInterface->clear();
1010 if (mInterfaceList.count())
1011 lbHostInterface->insertStringList (mInterfaceList);
1012 else
1013 lbHostInterface->insertItem (mNoInterfaces);
1014 /* select current list item */
1015 int index = lbHostInterface->index (
1016 lbHostInterface->findItem (currentListItemName));
1017 if (index == -1)
1018 index = 0;
1019 lbHostInterface->setCurrentItem (index);
1020 lbHostInterface->setSelected (index, true);
1021 /* enable/disable interface delete button */
1022 pbHostRemove->setEnabled (!mInterfaceList.isEmpty());
1023#endif
1024}
1025
1026void VBoxVMSettingsDlg::loadNetworksList()
1027{
1028 /* clear inner list */
1029 mNetworksList.clear();
1030
1031 /* load internal network list */
1032 CVirtualBox vbox = vboxGlobal().virtualBox();
1033 ulong count = vbox.GetSystemProperties().GetNetworkAdapterCount();
1034 CMachineVector vec = vbox.GetMachines2();
1035 for (CMachineVector::ConstIterator m = vec.begin();
1036 m != vec.end(); ++ m)
1037 {
1038 if (m->GetAccessible())
1039 {
1040 for (ulong slot = 0; slot < count; ++ slot)
1041 {
1042 CNetworkAdapter adapter = m->GetNetworkAdapter (slot);
1043 if (adapter.GetAttachmentType() == KNetworkAttachmentType_Internal &&
1044 !mNetworksList.contains (adapter.GetInternalNetwork()))
1045 mNetworksList << adapter.GetInternalNetwork();
1046 }
1047 }
1048 }
1049
1050 mLockNetworkListUpdate = false;
1051}
1052
1053void VBoxVMSettingsDlg::hostInterfaceAdd()
1054{
1055#if defined Q_WS_WIN
1056
1057 /* allow the started helper process to make itself the foreground window */
1058 AllowSetForegroundWindow (ASFW_ANY);
1059
1060 /* search for the max available interface index */
1061 int ifaceNumber = 0;
1062 QString ifaceName = tr ("VirtualBox Host Interface %1");
1063 QRegExp regExp (QString ("^") + ifaceName.arg ("([0-9]+)") + QString ("$"));
1064 for (uint index = 0; index < lbHostInterface->count(); ++ index)
1065 {
1066 QString iface = lbHostInterface->text (index);
1067 int pos = regExp.search (iface);
1068 if (pos != -1)
1069 ifaceNumber = regExp.cap (1).toInt() > ifaceNumber ?
1070 regExp.cap (1).toInt() : ifaceNumber;
1071 }
1072
1073 /* creating add host interface dialog */
1074 VBoxAddNIDialog dlg (this, ifaceName.arg (++ ifaceNumber));
1075 if (dlg.exec() != QDialog::Accepted)
1076 return;
1077 QString iName = dlg.getName();
1078
1079 /* create interface */
1080 CHost host = vboxGlobal().virtualBox().GetHost();
1081 CHostNetworkInterface iFace;
1082 CProgress progress = host.CreateHostNetworkInterface (iName, iFace);
1083 if (host.isOk())
1084 {
1085 vboxProblem().showModalProgressDialog (progress, iName, this);
1086 if (progress.GetResultCode() == 0)
1087 {
1088 /* add&select newly created interface */
1089 delete lbHostInterface->findItem (mNoInterfaces);
1090 lbHostInterface->insertItem (iName);
1091 mInterfaceList += iName;
1092 lbHostInterface->setCurrentItem (lbHostInterface->count() - 1);
1093 lbHostInterface->setSelected (lbHostInterface->count() - 1, true);
1094 for (int index = 0; index < tbwNetwork->count(); ++ index)
1095 networkPageUpdate (tbwNetwork->page (index));
1096 /* enable interface delete button */
1097 pbHostRemove->setEnabled (true);
1098 }
1099 else
1100 vboxProblem().cannotCreateHostInterface (progress, iName, this);
1101 }
1102 else
1103 vboxProblem().cannotCreateHostInterface (host, iName, this);
1104
1105 /* allow the started helper process to make itself the foreground window */
1106 AllowSetForegroundWindow (ASFW_ANY);
1107
1108#endif
1109}
1110
1111void VBoxVMSettingsDlg::hostInterfaceRemove()
1112{
1113#if defined Q_WS_WIN
1114
1115 /* allow the started helper process to make itself the foreground window */
1116 AllowSetForegroundWindow (ASFW_ANY);
1117
1118 /* check interface name */
1119 QString iName = lbHostInterface->currentText();
1120 if (iName.isEmpty())
1121 return;
1122
1123 /* asking user about deleting selected network interface */
1124 int delNetIface = vboxProblem().message (this, VBoxProblemReporter::Question,
1125 tr ("<p>Do you want to remove the selected host network interface "
1126 "<nobr><b>%1</b>?</nobr></p>"
1127 "<p><b>Note:</b> This interface may be in use by one or more "
1128 "network adapters of this or another VM. After it is removed, these "
1129 "adapters will no longer work until you correct their settings by "
1130 "either choosing a different interface name or a different adapter "
1131 "attachment type.</p>").arg (iName),
1132 0, /* autoConfirmId */
1133 QIMessageBox::Ok | QIMessageBox::Default,
1134 QIMessageBox::Cancel | QIMessageBox::Escape);
1135 if (delNetIface == QIMessageBox::Cancel)
1136 return;
1137
1138 CHost host = vboxGlobal().virtualBox().GetHost();
1139 CHostNetworkInterface iFace = host.GetNetworkInterfaces().FindByName (iName);
1140 if (host.isOk())
1141 {
1142 /* delete interface */
1143 CProgress progress = host.RemoveHostNetworkInterface (iFace.GetId(), iFace);
1144 if (host.isOk())
1145 {
1146 vboxProblem().showModalProgressDialog (progress, iName, this);
1147 if (progress.GetResultCode() == 0)
1148 {
1149 if (lbHostInterface->count() == 1)
1150 {
1151 lbHostInterface->insertItem (mNoInterfaces);
1152 /* disable interface delete button */
1153 pbHostRemove->setEnabled (false);
1154 }
1155 delete lbHostInterface->findItem (iName);
1156 lbHostInterface->setSelected (lbHostInterface->currentItem(), true);
1157 mInterfaceList.erase (mInterfaceList.find (iName));
1158 for (int index = 0; index < tbwNetwork->count(); ++ index)
1159 networkPageUpdate (tbwNetwork->page (index));
1160 }
1161 else
1162 vboxProblem().cannotRemoveHostInterface (progress, iFace, this);
1163 }
1164 }
1165
1166 if (!host.isOk())
1167 vboxProblem().cannotRemoveHostInterface (host, iFace, this);
1168#endif
1169}
1170
1171void VBoxVMSettingsDlg::networkPageUpdate (QWidget *aWidget)
1172{
1173 if (!aWidget) return;
1174#if defined Q_WS_WIN
1175 VBoxVMNetworkSettings *set = static_cast<VBoxVMNetworkSettings*> (aWidget);
1176 set->loadInterfaceList (mInterfaceList, mNoInterfaces);
1177 set->revalidate();
1178#endif
1179}
1180
1181
1182void VBoxVMSettingsDlg::onMediaEnumerationDone()
1183{
1184 mAllowResetFirstRunFlag = true;
1185}
1186
1187
1188void VBoxVMSettingsDlg::resetFirstRunFlag()
1189{
1190 if (mAllowResetFirstRunFlag)
1191 mResetFirstRunFlag = true;
1192}
1193
1194
1195void VBoxVMSettingsDlg::hdaMediaChanged()
1196{
1197 resetFirstRunFlag();
1198 uuidHDA = grbHDA->isChecked() ? cbHDA->getId() : QUuid();
1199 txHDA->setText (getHdInfo (grbHDA, uuidHDA));
1200 /* revailidate */
1201 wvalHDD->revalidate();
1202}
1203
1204
1205void VBoxVMSettingsDlg::hdbMediaChanged()
1206{
1207 resetFirstRunFlag();
1208 uuidHDB = grbHDB->isChecked() ? cbHDB->getId() : QUuid();
1209 txHDB->setText (getHdInfo (grbHDB, uuidHDB));
1210 /* revailidate */
1211 wvalHDD->revalidate();
1212}
1213
1214
1215void VBoxVMSettingsDlg::hddMediaChanged()
1216{
1217 resetFirstRunFlag();
1218 uuidHDD = grbHDD->isChecked() ? cbHDD->getId() : QUuid();
1219 txHDD->setText (getHdInfo (grbHDD, uuidHDD));
1220 /* revailidate */
1221 wvalHDD->revalidate();
1222}
1223
1224
1225void VBoxVMSettingsDlg::cdMediaChanged()
1226{
1227 resetFirstRunFlag();
1228 uuidISODVD = bgDVD->isChecked() ? cbISODVD->getId() : QUuid();
1229 /* revailidate */
1230 wvalDVD->revalidate();
1231}
1232
1233
1234void VBoxVMSettingsDlg::fdMediaChanged()
1235{
1236 resetFirstRunFlag();
1237 uuidISOFloppy = bgFloppy->isChecked() ? cbISOFloppy->getId() : QUuid();
1238 /* revailidate */
1239 wvalFloppy->revalidate();
1240}
1241
1242
1243QString VBoxVMSettingsDlg::getHdInfo (QGroupBox *aGroupBox, QUuid aId)
1244{
1245 QString notAttached = tr ("<not attached>", "hard disk");
1246 if (aId.isNull())
1247 return notAttached;
1248 return aGroupBox->isChecked() ?
1249 vboxGlobal().details (vboxGlobal().virtualBox().GetHardDisk (aId), true) :
1250 notAttached;
1251}
1252
1253void VBoxVMSettingsDlg::updateWhatsThis (bool gotFocus /* = false */)
1254{
1255 QString text;
1256
1257 QWidget *widget = NULL;
1258 if (!gotFocus)
1259 {
1260 if (whatsThisCandidate != NULL && whatsThisCandidate != this)
1261 widget = whatsThisCandidate;
1262 }
1263 else
1264 {
1265 widget = focusData()->focusWidget();
1266 }
1267 /* if the given widget lacks the whats'this text, look at its parent */
1268 while (widget && widget != this)
1269 {
1270 text = QWhatsThis::textFor (widget);
1271 if (!text.isEmpty())
1272 break;
1273 widget = widget->parentWidget();
1274 }
1275
1276 if (text.isEmpty() && !warningString.isEmpty())
1277 text = warningString;
1278 if (text.isEmpty())
1279 text = QWhatsThis::textFor (this);
1280
1281 whatsThisLabel->setText (text);
1282}
1283
1284void VBoxVMSettingsDlg::setWarning (const QString &warning)
1285{
1286 warningString = warning;
1287 if (!warning.isEmpty())
1288 warningString = QString ("<font color=red>%1</font>").arg (warning);
1289
1290 if (!warningString.isEmpty())
1291 whatsThisLabel->setText (warningString);
1292 else
1293 updateWhatsThis (true);
1294}
1295
1296/**
1297 * Sets up this dialog.
1298 *
1299 * If @a aCategory is non-null, it should be one of values from the hidden
1300 * '[cat]' column of #listView (see VBoxVMSettingsDlg.ui in qdesigner)
1301 * prepended with the '#' sign. In this case, the specified category page
1302 * will be activated when the dialog is open.
1303 *
1304 * If @a aWidget is non-null, it should be a name of one of widgets
1305 * from the given category page. In this case, the specified widget
1306 * will get focus when the dialog is open.
1307 *
1308 * @note Calling this method after the dialog is open has no sense.
1309 *
1310 * @param aCategory Category to select when the dialog is open or null.
1311 * @param aWidget Category to select when the dialog is open or null.
1312 */
1313void VBoxVMSettingsDlg::setup (const QString &aCategory, const QString &aControl)
1314{
1315 if (!aCategory.isNull())
1316 {
1317 /* search for a list view item corresponding to the category */
1318 QListViewItem *item = listView->findItem (aCategory, listView_Link);
1319 if (item)
1320 {
1321 listView->setSelected (item, true);
1322
1323 /* search for a widget with the given name */
1324 if (!aControl.isNull())
1325 {
1326 QObject *obj = widgetStack->visibleWidget()->child (aControl);
1327 if (obj && obj->isWidgetType())
1328 {
1329 QWidget *w = static_cast <QWidget *> (obj);
1330 QWidgetList parents;
1331 QWidget *p = w;
1332 while ((p = p->parentWidget()) != NULL)
1333 {
1334 if (!strcmp (p->className(), "QTabWidget"))
1335 {
1336 /* the tab contents widget is two steps down
1337 * (QTabWidget -> QWidgetStack -> QWidget) */
1338 QWidget *c = parents.last();
1339 if (c)
1340 c = parents.prev();
1341 if (c)
1342 static_cast <QTabWidget *> (p)->showPage (c);
1343 }
1344 parents.append (p);
1345 }
1346
1347 w->setFocus();
1348 }
1349 }
1350 }
1351 }
1352}
1353
1354void VBoxVMSettingsDlg::listView_currentChanged (QListViewItem *item)
1355{
1356 Assert (item);
1357 int id = item->text (1).toInt();
1358 Assert (id >= 0);
1359 titleLabel->setText (::path (item));
1360 widgetStack->raiseWidget (id);
1361}
1362
1363
1364void VBoxVMSettingsDlg::enableOk (const QIWidgetValidator *wval)
1365{
1366 Q_UNUSED (wval);
1367
1368 /* reset the warning text; interested parties will set it during
1369 * validation */
1370 setWarning (QString::null);
1371
1372 QString wvalWarning;
1373
1374 /* detect the overall validity */
1375 bool newValid = true;
1376 {
1377 QObjectList *l = this->queryList ("QIWidgetValidator");
1378 QObjectListIt it (*l);
1379 QObject *obj;
1380 while ((obj = it.current()) != 0)
1381 {
1382 QIWidgetValidator *wval = (QIWidgetValidator *) obj;
1383 newValid = wval->isValid();
1384 if (!newValid)
1385 {
1386 wvalWarning = wval->warningText();
1387 break;
1388 }
1389 ++ it;
1390 }
1391 delete l;
1392 }
1393
1394 if (warningString.isNull() && !wvalWarning.isNull())
1395 {
1396 /* try to set the generic error message when invalid but no specific
1397 * message is provided */
1398 setWarning (wvalWarning);
1399 }
1400
1401 if (valid != newValid)
1402 {
1403 valid = newValid;
1404 buttonOk->setEnabled (valid);
1405 warningLabel->setHidden (valid);
1406 warningPixmap->setHidden (valid);
1407 }
1408}
1409
1410
1411void VBoxVMSettingsDlg::revalidate (QIWidgetValidator *wval)
1412{
1413 /* do individual validations for pages */
1414 QWidget *pg = wval->widget();
1415 bool valid = wval->isOtherValid();
1416
1417 QString warningText;
1418 QString pageTitle = pagePath (pg);
1419
1420 if (pg == pageHDD)
1421 {
1422 CVirtualBox vbox = vboxGlobal().virtualBox();
1423 valid = true;
1424
1425 QValueList <QUuid> uuids;
1426
1427 if (valid && grbHDA->isChecked())
1428 {
1429 if (uuidHDA.isNull())
1430 {
1431 valid = false;
1432 warningText = tr ("Primary Master hard disk is not selected");
1433 }
1434 else uuids << uuidHDA;
1435 }
1436
1437 if (valid && grbHDB->isChecked())
1438 {
1439 if (uuidHDB.isNull())
1440 {
1441 valid = false;
1442 warningText = tr ("Primary Slave hard disk is not selected");
1443 }
1444 else
1445 {
1446 bool found = uuids.findIndex (uuidHDB) >= 0;
1447 if (found)
1448 {
1449 CHardDisk hd = vbox.GetHardDisk (uuidHDB);
1450 valid = hd.GetType() == KHardDiskType_Immutable;
1451 }
1452 if (valid)
1453 uuids << uuidHDB;
1454 else
1455 warningText = tr ("Primary Slave hard disk is already attached "
1456 "to a different slot");
1457 }
1458 }
1459
1460 if (valid && grbHDD->isChecked())
1461 {
1462 if (uuidHDD.isNull())
1463 {
1464 valid = false;
1465 warningText = tr ("Secondary Slave hard disk is not selected");
1466 }
1467 else
1468 {
1469 bool found = uuids.findIndex (uuidHDD) >= 0;
1470 if (found)
1471 {
1472 CHardDisk hd = vbox.GetHardDisk (uuidHDD);
1473 valid = hd.GetType() == KHardDiskType_Immutable;
1474 }
1475 if (valid)
1476 uuids << uuidHDB;
1477 else
1478 warningText = tr ("Secondary Slave hard disk is already attached "
1479 "to a different slot");
1480 }
1481 }
1482
1483 cbHDA->setEnabled (grbHDA->isChecked());
1484 cbHDB->setEnabled (grbHDB->isChecked());
1485 cbHDD->setEnabled (grbHDD->isChecked());
1486 tbHDA->setEnabled (grbHDA->isChecked());
1487 tbHDB->setEnabled (grbHDB->isChecked());
1488 tbHDD->setEnabled (grbHDD->isChecked());
1489 }
1490 else if (pg == pageDVD)
1491 {
1492 if (!bgDVD->isChecked())
1493 rbHostDVD->setChecked(false), rbISODVD->setChecked(false);
1494 else if (!rbHostDVD->isChecked() && !rbISODVD->isChecked())
1495 rbHostDVD->setChecked(true);
1496
1497 valid = !(rbISODVD->isChecked() && uuidISODVD.isNull());
1498
1499 cbHostDVD->setEnabled (rbHostDVD->isChecked());
1500 cbPassthrough->setEnabled (rbHostDVD->isChecked());
1501
1502 cbISODVD->setEnabled (rbISODVD->isChecked());
1503 tbISODVD->setEnabled (rbISODVD->isChecked());
1504
1505 if (!valid)
1506 warningText = tr ("CD/DVD image file is not selected");
1507 }
1508 else if (pg == pageFloppy)
1509 {
1510 if (!bgFloppy->isChecked())
1511 rbHostFloppy->setChecked(false), rbISOFloppy->setChecked(false);
1512 else if (!rbHostFloppy->isChecked() && !rbISOFloppy->isChecked())
1513 rbHostFloppy->setChecked(true);
1514
1515 valid = !(rbISOFloppy->isChecked() && uuidISOFloppy.isNull());
1516
1517 cbHostFloppy->setEnabled (rbHostFloppy->isChecked());
1518
1519 cbISOFloppy->setEnabled (rbISOFloppy->isChecked());
1520 tbISOFloppy->setEnabled (rbISOFloppy->isChecked());
1521
1522 if (!valid)
1523 warningText = tr ("Floppy image file is not selected");
1524 }
1525 else if (pg == pageNetwork)
1526 {
1527 QWidget *tab = NULL;
1528 VBoxVMNetworkSettings::CheckPageResult error =
1529 VBoxVMNetworkSettings::CheckPage_Ok;
1530 for (int index = 0; index < tbwNetwork->count(); ++ index)
1531 {
1532 tab = tbwNetwork->page (index);
1533 VBoxVMNetworkSettings *page =
1534 static_cast <VBoxVMNetworkSettings *> (tab);
1535 error = page->checkPage (mInterfaceList);
1536 valid = !error;
1537 if (!valid) break;
1538 }
1539 if (!valid)
1540 {
1541 Assert (tab);
1542 warningText =
1543 error == VBoxVMNetworkSettings::CheckPage_InvalidInterface ?
1544 tr ("Incorrect host network interface is selected") :
1545 error == VBoxVMNetworkSettings::CheckPage_NoNetworkName ?
1546 tr ("Internal network name is not set") :
1547 QString::null;
1548 pageTitle += ": " + tbwNetwork->tabLabel (tab);
1549 }
1550 }
1551 else if (pg == pageSerial)
1552 {
1553 valid = true;
1554 QValueList <QString> ports;
1555 QValueList <QString> paths;
1556
1557 int index = 0;
1558 for (; index < tbwSerialPorts->count(); ++ index)
1559 {
1560 QWidget *tab = tbwSerialPorts->page (index);
1561 VBoxVMSerialPortSettings *page =
1562 static_cast <VBoxVMSerialPortSettings *> (tab);
1563
1564 /* check the predefined port number unicity */
1565 if (page->mSerialPortBox->isChecked() && !page->isUserDefined())
1566 {
1567 QString port = page->mPortNumCombo->currentText();
1568 valid = !ports.contains (port);
1569 if (!valid)
1570 {
1571 warningText = tr ("Duplicate port number is selected ");
1572 pageTitle += ": " + tbwSerialPorts->tabLabel (tab);
1573 break;
1574 }
1575 ports << port;
1576 }
1577 /* check the port path emptiness & unicity */
1578 KPortMode mode =
1579 vboxGlobal().toPortMode (page->mHostModeCombo->currentText());
1580 if (mode != KPortMode_Disconnected)
1581 {
1582 QString path = page->mPortPathLine->text();
1583 valid = !path.isEmpty() && !paths.contains (path);
1584 if (!valid)
1585 {
1586 warningText = path.isEmpty() ?
1587 tr ("Port path is not specified ") :
1588 tr ("Duplicate port path is entered ");
1589 pageTitle += ": " + tbwSerialPorts->tabLabel (tab);
1590 break;
1591 }
1592 paths << path;
1593 }
1594 }
1595 }
1596 else if (pg == pageParallel)
1597 {
1598 valid = true;
1599 QValueList <QString> ports;
1600 QValueList <QString> paths;
1601
1602 int index = 0;
1603 for (; index < tbwParallelPorts->count(); ++ index)
1604 {
1605 QWidget *tab = tbwParallelPorts->page (index);
1606 VBoxVMParallelPortSettings *page =
1607 static_cast <VBoxVMParallelPortSettings *> (tab);
1608
1609 /* check the predefined port number unicity */
1610 if (page->mParallelPortBox->isChecked() && !page->isUserDefined())
1611 {
1612 QString port = page->mPortNumCombo->currentText();
1613 valid = !ports.contains (port);
1614 if (!valid)
1615 {
1616 warningText = tr ("Duplicate port number is selected ");
1617 pageTitle += ": " + tbwParallelPorts->tabLabel (tab);
1618 break;
1619 }
1620 ports << port;
1621 }
1622 /* check the port path emptiness & unicity */
1623 if (page->mParallelPortBox->isChecked())
1624 {
1625 QString path = page->mPortPathLine->text();
1626 valid = !path.isEmpty() && !paths.contains (path);
1627 if (!valid)
1628 {
1629 warningText = path.isEmpty() ?
1630 tr ("Port path is not specified ") :
1631 tr ("Duplicate port path is entered ");
1632 pageTitle += ": " + tbwParallelPorts->tabLabel (tab);
1633 break;
1634 }
1635 paths << path;
1636 }
1637 }
1638 }
1639
1640 if (!valid)
1641 setWarning (tr ("%1 on the <b>%2</b> page.")
1642 .arg (warningText, pageTitle));
1643
1644 wval->setOtherValid (valid);
1645}
1646
1647
1648void VBoxVMSettingsDlg::getFromMachine (const CMachine &machine)
1649{
1650 cmachine = machine;
1651
1652 setCaption (machine.GetName() + tr (" - Settings"));
1653
1654 CVirtualBox vbox = vboxGlobal().virtualBox();
1655 CBIOSSettings biosSettings = cmachine.GetBIOSSettings();
1656
1657 /* name */
1658 leName->setText (machine.GetName());
1659
1660 /* OS type */
1661 QString typeId = machine.GetOSTypeId();
1662 cbOS->setCurrentItem (vboxGlobal().vmGuestOSTypeIndex (typeId));
1663 cbOS_activated (cbOS->currentItem());
1664
1665 /* RAM size */
1666 slRAM->setValue (machine.GetMemorySize());
1667
1668 /* VRAM size */
1669 slVRAM->setValue (machine.GetVRAMSize());
1670
1671 /* Boot-order */
1672 tblBootOrder->getFromMachine (machine);
1673
1674 /* ACPI */
1675 chbEnableACPI->setChecked (biosSettings.GetACPIEnabled());
1676
1677 /* IO APIC */
1678 chbEnableIOAPIC->setChecked (biosSettings.GetIOAPICEnabled());
1679
1680 /* VT-x/AMD-V */
1681 machine.GetHWVirtExEnabled() == KTSBool_False ? chbVTX->setChecked (false) :
1682 machine.GetHWVirtExEnabled() == KTSBool_True ? chbVTX->setChecked (true) :
1683 chbVTX->setNoChange();
1684
1685 /* Saved state folder */
1686 leSnapshotFolder->setText (machine.GetSnapshotFolder());
1687
1688 /* Description */
1689 teDescription->setText (machine.GetDescription());
1690
1691 /* Shared clipboard mode */
1692 cbSharedClipboard->setCurrentItem (machine.GetClipboardMode());
1693
1694 /* IDE controller type */
1695 cbIdeController->setCurrentText (vboxGlobal().toString (biosSettings.GetIDEControllerType()));
1696
1697 /* other features */
1698 QString saveRtimeImages = cmachine.GetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime);
1699 chbRememberMedia->setChecked (saveRtimeImages != "no");
1700
1701 /* hard disk images */
1702 {
1703 struct
1704 {
1705 KStorageBus bus;
1706 LONG channel;
1707 LONG dev;
1708 struct {
1709 QGroupBox *grb;
1710 QComboBox *cbb;
1711 QLabel *tx;
1712 QUuid *uuid;
1713 } data;
1714 }
1715 diskSet[] =
1716 {
1717 { KStorageBus_IDE, 0, 0, {grbHDA, cbHDA, txHDA, &uuidHDA} },
1718 { KStorageBus_IDE, 0, 1, {grbHDB, cbHDB, txHDB, &uuidHDB} },
1719 { KStorageBus_IDE, 1, 1, {grbHDD, cbHDD, txHDD, &uuidHDD} },
1720 };
1721
1722 grbHDA->setChecked (false);
1723 grbHDB->setChecked (false);
1724 grbHDD->setChecked (false);
1725
1726 CHardDiskAttachmentEnumerator en =
1727 machine.GetHardDiskAttachments().Enumerate();
1728 while (en.HasMore())
1729 {
1730 CHardDiskAttachment hda = en.GetNext();
1731 for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
1732 {
1733 if (diskSet [i].bus == hda.GetBus() &&
1734 diskSet [i].channel == hda.GetChannel() &&
1735 diskSet [i].dev == hda.GetDevice())
1736 {
1737 CHardDisk hd = hda.GetHardDisk();
1738 CHardDisk root = hd.GetRoot();
1739 QString src = root.GetLocation();
1740 if (hd.GetStorageType() == KHardDiskStorageType_VirtualDiskImage)
1741 {
1742 QFileInfo fi (src);
1743 src = fi.fileName() + " (" +
1744 QDir::convertSeparators (fi.dirPath (true)) + ")";
1745 }
1746 diskSet [i].data.grb->setChecked (true);
1747 diskSet [i].data.tx->setText (vboxGlobal().details (hd));
1748 *(diskSet [i].data.uuid) = QUuid (root.GetId());
1749 }
1750 }
1751 }
1752 }
1753
1754 /* floppy image */
1755 {
1756 /* read out the host floppy drive list and prepare the combobox */
1757 CHostFloppyDriveCollection coll =
1758 vboxGlobal().virtualBox().GetHost().GetFloppyDrives();
1759 hostFloppies.resize (coll.GetCount());
1760 cbHostFloppy->clear();
1761 int id = 0;
1762 CHostFloppyDriveEnumerator en = coll.Enumerate();
1763 while (en.HasMore())
1764 {
1765 CHostFloppyDrive hostFloppy = en.GetNext();
1766 /** @todo set icon? */
1767 QString name = hostFloppy.GetName();
1768 QString description = hostFloppy.GetDescription();
1769 QString fullName = description.isEmpty() ?
1770 name :
1771 QString ("%1 (%2)").arg (description, name);
1772 cbHostFloppy->insertItem (fullName, id);
1773 hostFloppies [id] = hostFloppy;
1774 ++ id;
1775 }
1776
1777 CFloppyDrive floppy = machine.GetFloppyDrive();
1778 switch (floppy.GetState())
1779 {
1780 case KDriveState_HostDriveCaptured:
1781 {
1782 CHostFloppyDrive drv = floppy.GetHostDrive();
1783 QString name = drv.GetName();
1784 QString description = drv.GetDescription();
1785 QString fullName = description.isEmpty() ?
1786 name :
1787 QString ("%1 (%2)").arg (description, name);
1788 if (coll.FindByName (name).isNull())
1789 {
1790 /*
1791 * if the floppy drive is not currently available,
1792 * add it to the end of the list with a special mark
1793 */
1794 cbHostFloppy->insertItem ("* " + fullName);
1795 cbHostFloppy->setCurrentItem (cbHostFloppy->count() - 1);
1796 }
1797 else
1798 {
1799 /* this will select the correct item from the prepared list */
1800 cbHostFloppy->setCurrentText (fullName);
1801 }
1802 rbHostFloppy->setChecked (true);
1803 break;
1804 }
1805 case KDriveState_ImageMounted:
1806 {
1807 CFloppyImage img = floppy.GetImage();
1808 QString src = img.GetFilePath();
1809 AssertMsg (!src.isNull(), ("Image file must not be null"));
1810 QFileInfo fi (src);
1811 rbISOFloppy->setChecked (true);
1812 uuidISOFloppy = QUuid (img.GetId());
1813 break;
1814 }
1815 case KDriveState_NotMounted:
1816 {
1817 bgFloppy->setChecked(false);
1818 break;
1819 }
1820 default:
1821 AssertMsgFailed (("invalid floppy state: %d\n", floppy.GetState()));
1822 }
1823 }
1824
1825 /* CD/DVD-ROM image */
1826 {
1827 /* read out the host DVD drive list and prepare the combobox */
1828 CHostDVDDriveCollection coll =
1829 vboxGlobal().virtualBox().GetHost().GetDVDDrives();
1830 hostDVDs.resize (coll.GetCount());
1831 cbHostDVD->clear();
1832 int id = 0;
1833 CHostDVDDriveEnumerator en = coll.Enumerate();
1834 while (en.HasMore())
1835 {
1836 CHostDVDDrive hostDVD = en.GetNext();
1837 /// @todo (r=dmik) set icon?
1838 QString name = hostDVD.GetName();
1839 QString description = hostDVD.GetDescription();
1840 QString fullName = description.isEmpty() ?
1841 name :
1842 QString ("%1 (%2)").arg (description, name);
1843 cbHostDVD->insertItem (fullName, id);
1844 hostDVDs [id] = hostDVD;
1845 ++ id;
1846 }
1847
1848 CDVDDrive dvd = machine.GetDVDDrive();
1849 switch (dvd.GetState())
1850 {
1851 case KDriveState_HostDriveCaptured:
1852 {
1853 CHostDVDDrive drv = dvd.GetHostDrive();
1854 QString name = drv.GetName();
1855 QString description = drv.GetDescription();
1856 QString fullName = description.isEmpty() ?
1857 name :
1858 QString ("%1 (%2)").arg (description, name);
1859 if (coll.FindByName (name).isNull())
1860 {
1861 /*
1862 * if the DVD drive is not currently available,
1863 * add it to the end of the list with a special mark
1864 */
1865 cbHostDVD->insertItem ("* " + fullName);
1866 cbHostDVD->setCurrentItem (cbHostDVD->count() - 1);
1867 }
1868 else
1869 {
1870 /* this will select the correct item from the prepared list */
1871 cbHostDVD->setCurrentText (fullName);
1872 }
1873 rbHostDVD->setChecked (true);
1874 cbPassthrough->setChecked (dvd.GetPassthrough());
1875 break;
1876 }
1877 case KDriveState_ImageMounted:
1878 {
1879 CDVDImage img = dvd.GetImage();
1880 QString src = img.GetFilePath();
1881 AssertMsg (!src.isNull(), ("Image file must not be null"));
1882 QFileInfo fi (src);
1883 rbISODVD->setChecked (true);
1884 uuidISODVD = QUuid (img.GetId());
1885 break;
1886 }
1887 case KDriveState_NotMounted:
1888 {
1889 bgDVD->setChecked(false);
1890 break;
1891 }
1892 default:
1893 AssertMsgFailed (("invalid DVD state: %d\n", dvd.GetState()));
1894 }
1895 }
1896
1897 /* audio */
1898 {
1899 CAudioAdapter audio = machine.GetAudioAdapter();
1900 grbAudio->setChecked (audio.GetEnabled());
1901 cbAudioDriver->setCurrentText (vboxGlobal().toString (audio.GetAudioDriver()));
1902 cbAudioController->setCurrentText (vboxGlobal().toString (audio.GetAudioController()));
1903 }
1904
1905 /* network */
1906 {
1907 ulong count = vbox.GetSystemProperties().GetNetworkAdapterCount();
1908 for (ulong slot = 0; slot < count; ++ slot)
1909 {
1910 CNetworkAdapter adapter = machine.GetNetworkAdapter (slot);
1911 addNetworkAdapter (adapter);
1912 }
1913 }
1914
1915 /* serial ports */
1916 {
1917 ulong count = vbox.GetSystemProperties().GetSerialPortCount();
1918 for (ulong slot = 0; slot < count; ++ slot)
1919 {
1920 CSerialPort port = machine.GetSerialPort (slot);
1921 addSerialPort (port);
1922 }
1923 }
1924
1925 /* parallel ports */
1926 {
1927 ulong count = vbox.GetSystemProperties().GetParallelPortCount();
1928 for (ulong slot = 0; slot < count; ++ slot)
1929 {
1930 CParallelPort port = machine.GetParallelPort (slot);
1931 addParallelPort (port);
1932 }
1933 }
1934
1935 /* USB */
1936 {
1937 CUSBController ctl = machine.GetUSBController();
1938
1939 /* Show an error message (if there is any).
1940 * Note that we don't use the generic cannotLoadMachineSettings()
1941 * call here because we want this message to be suppressable. */
1942 if (!machine.isReallyOk())
1943 vboxProblem().cannotAccessUSB (machine);
1944
1945 if (ctl.isNull())
1946 {
1947 /* disable the USB controller category if the USB controller is
1948 * not available (i.e. in VirtualBox OSE) */
1949
1950 QListViewItem *usbItem = listView->findItem ("#usb", listView_Link);
1951 Assert (usbItem);
1952 if (usbItem)
1953 usbItem->setVisible (false);
1954
1955 /* disable validators if any */
1956 pageUSB->setEnabled (false);
1957 }
1958 else
1959 {
1960 cbEnableUSBController->setChecked (ctl.GetEnabled());
1961 cbEnableUSBEhci->setChecked (ctl.GetEnabledEhci());
1962 usbAdapterToggled (cbEnableUSBController->isChecked());
1963
1964 CUSBDeviceFilterEnumerator en = ctl.GetDeviceFilters().Enumerate();
1965 while (en.HasMore())
1966 addUSBFilter (en.GetNext(), false /* isNew */);
1967
1968 lvUSBFilters->setCurrentItem (lvUSBFilters->firstChild());
1969 /* silly Qt -- doesn't emit currentChanged after adding the
1970 * first item to an empty list */
1971 lvUSBFilters_currentChanged (lvUSBFilters->firstChild());
1972 }
1973 }
1974
1975 /* vrdp */
1976 {
1977 CVRDPServer vrdp = machine.GetVRDPServer();
1978
1979 if (vrdp.isNull())
1980 {
1981 /* disable the VRDP category if VRDP is
1982 * not available (i.e. in VirtualBox OSE) */
1983
1984 QListViewItem *vrdpItem = listView->findItem ("#vrdp", listView_Link);
1985 Assert (vrdpItem);
1986 if (vrdpItem)
1987 vrdpItem->setVisible (false);
1988
1989 /* disable validators if any */
1990 pageVRDP->setEnabled (false);
1991
1992 /* if machine has something to say, show the message */
1993 vboxProblem().cannotLoadMachineSettings (machine, false /* strict */);
1994 }
1995 else
1996 {
1997 grbVRDP->setChecked (vrdp.GetEnabled());
1998 leVRDPPort->setText (QString::number (vrdp.GetPort()));
1999 cbVRDPAuthType->setCurrentText (vboxGlobal().toString (vrdp.GetAuthType()));
2000 leVRDPTimeout->setText (QString::number (vrdp.GetAuthTimeout()));
2001 }
2002 }
2003
2004 /* shared folders */
2005 {
2006 mSharedFolders->getFromMachine (machine);
2007 }
2008
2009 /* request for media shortcuts update */
2010 cbHDA->setBelongsTo (machine.GetId());
2011 cbHDB->setBelongsTo (machine.GetId());
2012 cbHDD->setBelongsTo (machine.GetId());
2013 updateShortcuts();
2014
2015 /* revalidate pages with custom validation */
2016 wvalHDD->revalidate();
2017 wvalDVD->revalidate();
2018 wvalFloppy->revalidate();
2019 wvalVRDP->revalidate();
2020
2021 /* finally set the reset First Run Wizard flag to "false" to make sure
2022 * user will see this dialog if he hasn't change the boot-order
2023 * and/or mounted images configuration */
2024 mResetFirstRunFlag = false;
2025}
2026
2027
2028COMResult VBoxVMSettingsDlg::putBackToMachine()
2029{
2030 CVirtualBox vbox = vboxGlobal().virtualBox();
2031 CBIOSSettings biosSettings = cmachine.GetBIOSSettings();
2032
2033 /* name */
2034 cmachine.SetName (leName->text());
2035
2036 /* OS type */
2037 CGuestOSType type = vboxGlobal().vmGuestOSType (cbOS->currentItem());
2038 AssertMsg (!type.isNull(), ("vmGuestOSType() must return non-null type"));
2039 cmachine.SetOSTypeId (type.GetId());
2040
2041 /* RAM size */
2042 cmachine.SetMemorySize (slRAM->value());
2043
2044 /* VRAM size */
2045 cmachine.SetVRAMSize (slVRAM->value());
2046
2047 /* boot order */
2048 tblBootOrder->putBackToMachine (cmachine);
2049
2050 /* ACPI */
2051 biosSettings.SetACPIEnabled (chbEnableACPI->isChecked());
2052
2053 /* IO APIC */
2054 biosSettings.SetIOAPICEnabled (chbEnableIOAPIC->isChecked());
2055
2056 /* VT-x/AMD-V */
2057 cmachine.SetHWVirtExEnabled (
2058 chbVTX->state() == QButton::Off ? KTSBool_False :
2059 chbVTX->state() == QButton::On ? KTSBool_True : KTSBool_Default);
2060
2061 /* Saved state folder */
2062 if (leSnapshotFolder->isModified())
2063 {
2064 cmachine.SetSnapshotFolder (leSnapshotFolder->text());
2065 if (!cmachine.isOk())
2066 vboxProblem()
2067 .cannotSetSnapshotFolder (cmachine,
2068 QDir::convertSeparators (leSnapshotFolder->text()));
2069 }
2070
2071 /* Description (set empty to null to avoid an empty <Description> node
2072 * in the settings file) */
2073 cmachine.SetDescription (teDescription->text().isEmpty() ? QString::null :
2074 teDescription->text());
2075
2076 /* Shared clipboard mode */
2077 cmachine.SetClipboardMode ((KClipboardMode) cbSharedClipboard->currentItem());
2078
2079 /* IDE controller type */
2080 biosSettings.SetIDEControllerType (vboxGlobal().toIDEControllerType (cbIdeController->currentText()));
2081
2082 /* other features */
2083 cmachine.SetExtraData (VBoxDefs::GUI_SaveMountedAtRuntime,
2084 chbRememberMedia->isChecked() ? "yes" : "no");
2085
2086 /* hard disk images */
2087 {
2088 struct
2089 {
2090 KStorageBus bus;
2091 LONG channel;
2092 LONG dev;
2093 struct {
2094 QGroupBox *grb;
2095 QUuid *uuid;
2096 } data;
2097 }
2098 diskSet[] =
2099 {
2100 { KStorageBus_IDE, 0, 0, {grbHDA, &uuidHDA} },
2101 { KStorageBus_IDE, 0, 1, {grbHDB, &uuidHDB} },
2102 { KStorageBus_IDE, 1, 1, {grbHDD, &uuidHDD} }
2103 };
2104
2105 /*
2106 * first, detach all disks (to ensure we can reattach them to different
2107 * controllers / devices, when appropriate)
2108 */
2109 CHardDiskAttachmentEnumerator en =
2110 cmachine.GetHardDiskAttachments().Enumerate();
2111 while (en.HasMore())
2112 {
2113 CHardDiskAttachment hda = en.GetNext();
2114 for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
2115 {
2116 if (diskSet [i].bus == hda.GetBus() &&
2117 diskSet [i].channel == hda.GetChannel() &&
2118 diskSet [i].dev == hda.GetDevice())
2119 {
2120 cmachine.DetachHardDisk (diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
2121 if (!cmachine.isOk())
2122 vboxProblem().cannotDetachHardDisk (
2123 this, cmachine, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
2124 }
2125 }
2126 }
2127
2128 /* now, attach new disks */
2129 for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
2130 {
2131 QUuid *newId = diskSet [i].data.uuid;
2132 if (diskSet [i].data.grb->isChecked() && !(*newId).isNull())
2133 {
2134 cmachine.AttachHardDisk (*newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
2135 if (!cmachine.isOk())
2136 vboxProblem().cannotAttachHardDisk (
2137 this, cmachine, *newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
2138 }
2139 }
2140 }
2141
2142 /* floppy image */
2143 {
2144 CFloppyDrive floppy = cmachine.GetFloppyDrive();
2145 if (!bgFloppy->isChecked())
2146 {
2147 floppy.Unmount();
2148 }
2149 else if (rbHostFloppy->isChecked())
2150 {
2151 int id = cbHostFloppy->currentItem();
2152 Assert (id >= 0);
2153 if (id < (int) hostFloppies.count())
2154 floppy.CaptureHostDrive (hostFloppies [id]);
2155 /*
2156 * otherwise the selected drive is not yet available, leave it
2157 * as is
2158 */
2159 }
2160 else if (rbISOFloppy->isChecked())
2161 {
2162 Assert (!uuidISOFloppy.isNull());
2163 floppy.MountImage (uuidISOFloppy);
2164 }
2165 }
2166
2167 /* CD/DVD-ROM image */
2168 {
2169 CDVDDrive dvd = cmachine.GetDVDDrive();
2170 if (!bgDVD->isChecked())
2171 {
2172 dvd.SetPassthrough (false);
2173 dvd.Unmount();
2174 }
2175 else if (rbHostDVD->isChecked())
2176 {
2177 dvd.SetPassthrough (cbPassthrough->isChecked());
2178 int id = cbHostDVD->currentItem();
2179 Assert (id >= 0);
2180 if (id < (int) hostDVDs.count())
2181 dvd.CaptureHostDrive (hostDVDs [id]);
2182 /*
2183 * otherwise the selected drive is not yet available, leave it
2184 * as is
2185 */
2186 }
2187 else if (rbISODVD->isChecked())
2188 {
2189 dvd.SetPassthrough (false);
2190 Assert (!uuidISODVD.isNull());
2191 dvd.MountImage (uuidISODVD);
2192 }
2193 }
2194
2195 /* Clear the "GUI_FirstRun" extra data key in case if the boot order
2196 * and/or disk configuration were changed */
2197 if (mResetFirstRunFlag)
2198 cmachine.SetExtraData (VBoxDefs::GUI_FirstRun, QString::null);
2199
2200 /* audio */
2201 {
2202 CAudioAdapter audio = cmachine.GetAudioAdapter();
2203 audio.SetAudioDriver (vboxGlobal().toAudioDriverType (cbAudioDriver->currentText()));
2204 audio.SetAudioController (vboxGlobal().toAudioControllerType (cbAudioController->currentText()));
2205 audio.SetEnabled (grbAudio->isChecked());
2206 AssertWrapperOk (audio);
2207 }
2208
2209 /* network */
2210 {
2211 for (int index = 0; index < tbwNetwork->count(); index++)
2212 {
2213 VBoxVMNetworkSettings *page =
2214 (VBoxVMNetworkSettings *) tbwNetwork->page (index);
2215 Assert (page);
2216 page->putBackToAdapter();
2217 }
2218 }
2219
2220 /* serial ports */
2221 {
2222 for (int index = 0; index < tbwSerialPorts->count(); index++)
2223 {
2224 VBoxVMSerialPortSettings *page =
2225 (VBoxVMSerialPortSettings *) tbwSerialPorts->page (index);
2226 Assert (page);
2227 page->putBackToPort();
2228 }
2229 }
2230
2231 /* parallel ports */
2232 {
2233 for (int index = 0; index < tbwParallelPorts->count(); index++)
2234 {
2235 VBoxVMParallelPortSettings *page =
2236 (VBoxVMParallelPortSettings *) tbwParallelPorts->page (index);
2237 Assert (page);
2238 page->putBackToPort();
2239 }
2240 }
2241
2242 /* usb */
2243 {
2244 CUSBController ctl = cmachine.GetUSBController();
2245
2246 if (!ctl.isNull())
2247 {
2248 /* the USB controller may be unavailable (i.e. in VirtualBox OSE) */
2249
2250 ctl.SetEnabled (cbEnableUSBController->isChecked());
2251 ctl.SetEnabledEhci (cbEnableUSBEhci->isChecked());
2252
2253 /*
2254 * first, remove all old filters (only if the list is changed,
2255 * not only individual properties of filters)
2256 */
2257 if (mUSBFilterListModified)
2258 for (ulong count = ctl.GetDeviceFilters().GetCount(); count; -- count)
2259 ctl.RemoveDeviceFilter (0);
2260
2261 /* then add all new filters */
2262 for (QListViewItem *item = lvUSBFilters->firstChild(); item;
2263 item = item->nextSibling())
2264 {
2265 USBListItem *uli = static_cast <USBListItem *> (item);
2266 VBoxUSBFilterSettings *settings =
2267 static_cast <VBoxUSBFilterSettings *>
2268 (wstUSBFilters->widget (uli->mId));
2269 Assert (settings);
2270
2271 COMResult res = settings->putBackToFilter();
2272 if (!res.isOk())
2273 return res;
2274
2275 CUSBDeviceFilter filter = settings->filter();
2276 filter.SetActive (uli->isOn());
2277
2278 if (mUSBFilterListModified)
2279 ctl.InsertDeviceFilter (~0, filter);
2280 }
2281 }
2282
2283 mUSBFilterListModified = false;
2284 }
2285
2286 /* vrdp */
2287 {
2288 CVRDPServer vrdp = cmachine.GetVRDPServer();
2289
2290 if (!vrdp.isNull())
2291 {
2292 /* VRDP may be unavailable (i.e. in VirtualBox OSE) */
2293 vrdp.SetEnabled (grbVRDP->isChecked());
2294 vrdp.SetPort (leVRDPPort->text().toULong());
2295 vrdp.SetAuthType (vboxGlobal().toVRDPAuthType (cbVRDPAuthType->currentText()));
2296 vrdp.SetAuthTimeout (leVRDPTimeout->text().toULong());
2297 }
2298 }
2299
2300 /* shared folders */
2301 {
2302 mSharedFolders->putBackToMachine();
2303 }
2304
2305 return COMResult();
2306}
2307
2308
2309void VBoxVMSettingsDlg::showImageManagerHDA() { showVDImageManager (&uuidHDA, cbHDA); }
2310void VBoxVMSettingsDlg::showImageManagerHDB() { showVDImageManager (&uuidHDB, cbHDB); }
2311void VBoxVMSettingsDlg::showImageManagerHDD() { showVDImageManager (&uuidHDD, cbHDD); }
2312void VBoxVMSettingsDlg::showImageManagerISODVD() { showVDImageManager (&uuidISODVD, cbISODVD); }
2313void VBoxVMSettingsDlg::showImageManagerISOFloppy() { showVDImageManager(&uuidISOFloppy, cbISOFloppy); }
2314
2315void VBoxVMSettingsDlg::showVDImageManager (QUuid *id, VBoxMediaComboBox *cbb, QLabel*)
2316{
2317 VBoxDefs::DiskType type = VBoxDefs::InvalidType;
2318 if (cbb == cbISODVD)
2319 type = VBoxDefs::CD;
2320 else if (cbb == cbISOFloppy)
2321 type = VBoxDefs::FD;
2322 else
2323 type = VBoxDefs::HD;
2324
2325 VBoxDiskImageManagerDlg dlg (this, "VBoxDiskImageManagerDlg",
2326 WType_Dialog | WShowModal);
2327 QUuid machineId = cmachine.GetId();
2328 QUuid hdId = type == VBoxDefs::HD ? cbb->getId() : QUuid();
2329 QUuid cdId = type == VBoxDefs::CD ? cbb->getId() : QUuid();
2330 QUuid fdId = type == VBoxDefs::FD ? cbb->getId() : QUuid();
2331 dlg.setup (type, true, &machineId, true /* aRefresh */, cmachine,
2332 hdId, cdId, fdId);
2333 if (dlg.exec() == VBoxDiskImageManagerDlg::Accepted)
2334 {
2335 *id = dlg.getSelectedUuid();
2336 resetFirstRunFlag();
2337 }
2338 else
2339 {
2340 *id = cbb->getId();
2341 }
2342
2343 cbb->setCurrentItem (*id);
2344 cbb->setFocus();
2345
2346 /* revalidate pages with custom validation */
2347 wvalHDD->revalidate();
2348 wvalDVD->revalidate();
2349 wvalFloppy->revalidate();
2350}
2351
2352void VBoxVMSettingsDlg::addNetworkAdapter (const CNetworkAdapter &aAdapter)
2353{
2354 VBoxVMNetworkSettings *page = new VBoxVMNetworkSettings();
2355 page->loadInterfaceList (mInterfaceList, mNoInterfaces);
2356 page->loadNetworksList (mNetworksList);
2357 page->getFromAdapter (aAdapter);
2358 QString pageTitle = QString (tr ("Adapter %1", "network"))
2359 .arg (aAdapter.GetSlot());
2360 tbwNetwork->addTab (page, pageTitle);
2361
2362 /* fix the tab order so that main dialog's buttons are always the last */
2363 setTabOrder (page->leTAPTerminate, buttonHelp);
2364 setTabOrder (buttonHelp, buttonOk);
2365 setTabOrder (buttonOk, buttonCancel);
2366
2367 /* setup validation */
2368 QIWidgetValidator *wval =
2369 new QIWidgetValidator (QString ("%1: %2")
2370 .arg (pagePath (pageNetwork), pageTitle),
2371 pageNetwork, this);
2372 connect (page->grbEnabled, SIGNAL (toggled (bool)), wval, SLOT (revalidate()));
2373 connect (page->cbNetworkAttachment, SIGNAL (activated (const QString &)),
2374 wval, SLOT (revalidate()));
2375 connect (page->cbInternalNetworkName, SIGNAL (activated (const QString &)),
2376 wval, SLOT (revalidate()));
2377 connect (page->cbInternalNetworkName, SIGNAL (textChanged (const QString &)),
2378 this, SLOT (updateNetworksList()));
2379 connect (page->cbInternalNetworkName, SIGNAL (textChanged (const QString &)),
2380 wval, SLOT (revalidate()));
2381 connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
2382 this, SLOT (enableOk (const QIWidgetValidator *)));
2383 connect (wval, SIGNAL (isValidRequested (QIWidgetValidator *)),
2384 this, SLOT (revalidate( QIWidgetValidator *)));
2385
2386 page->setValidator (wval);
2387 page->revalidate();
2388
2389#ifdef Q_WS_WIN
2390
2391 /* fix focus order (make sure the Host Interface list UI goes after the
2392 * last network adapter UI item) */
2393
2394 setTabOrder (page->chbCableConnected, lbHostInterface);
2395 setTabOrder (lbHostInterface, pbHostAdd);
2396 setTabOrder (pbHostAdd, pbHostRemove);
2397
2398#endif
2399}
2400
2401void VBoxVMSettingsDlg::updateNetworksList()
2402{
2403 if (mLockNetworkListUpdate)
2404 return;
2405 mLockNetworkListUpdate = true;
2406
2407 QStringList curList (mNetworksList);
2408 for (int index = 0; index < tbwNetwork->count(); ++ index)
2409 {
2410 VBoxVMNetworkSettings *pg = tbwNetwork->page (index) ?
2411 static_cast <VBoxVMNetworkSettings*> (tbwNetwork->page (index)) : 0;
2412 if (pg)
2413 {
2414 QString curText = pg->cbInternalNetworkName->currentText();
2415 if (!curText.isEmpty() && !curList.contains (curText))
2416 curList << curText;
2417 }
2418 }
2419
2420 for (int index = 0; index < tbwNetwork->count(); ++ index)
2421 {
2422 VBoxVMNetworkSettings *pg = tbwNetwork->page (index) ?
2423 static_cast <VBoxVMNetworkSettings*> (tbwNetwork->page (index)) : 0;
2424 pg->loadNetworksList (curList);
2425 }
2426
2427 mLockNetworkListUpdate = false;
2428}
2429
2430void VBoxVMSettingsDlg::addSerialPort (const CSerialPort &aPort)
2431{
2432 VBoxVMSerialPortSettings *page = new VBoxVMSerialPortSettings();
2433 page->getFromPort (aPort);
2434 QString pageTitle = QString (tr ("Port %1", "serial ports"))
2435 .arg (aPort.GetSlot());
2436 tbwSerialPorts->addTab (page, pageTitle);
2437
2438 /* fix the tab order so that main dialog's buttons are always the last */
2439 setTabOrder (page->mPortPathLine, buttonHelp);
2440 setTabOrder (buttonHelp, buttonOk);
2441 setTabOrder (buttonOk, buttonCancel);
2442
2443 /* setup validation */
2444 QIWidgetValidator *wval =
2445 new QIWidgetValidator (QString ("%1: %2")
2446 .arg (pagePath (pageSerial), pageTitle),
2447 pageSerial, this);
2448 connect (page->mSerialPortBox, SIGNAL (toggled (bool)),
2449 wval, SLOT (revalidate()));
2450 connect (page->mIRQLine, SIGNAL (textChanged (const QString &)),
2451 wval, SLOT (revalidate()));
2452 connect (page->mIOPortLine, SIGNAL (textChanged (const QString &)),
2453 wval, SLOT (revalidate()));
2454 connect (page->mHostModeCombo, SIGNAL (activated (const QString &)),
2455 wval, SLOT (revalidate()));
2456 connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
2457 this, SLOT (enableOk (const QIWidgetValidator *)));
2458 connect (wval, SIGNAL (isValidRequested (QIWidgetValidator *)),
2459 this, SLOT (revalidate (QIWidgetValidator *)));
2460
2461 wval->revalidate();
2462}
2463
2464void VBoxVMSettingsDlg::addParallelPort (const CParallelPort &aPort)
2465{
2466 VBoxVMParallelPortSettings *page = new VBoxVMParallelPortSettings();
2467 page->getFromPort (aPort);
2468 QString pageTitle = QString (tr ("Port %1", "parallel ports"))
2469 .arg (aPort.GetSlot());
2470 tbwParallelPorts->addTab (page, pageTitle);
2471
2472 /* fix the tab order so that main dialog's buttons are always the last */
2473 setTabOrder (page->mPortPathLine, buttonHelp);
2474 setTabOrder (buttonHelp, buttonOk);
2475 setTabOrder (buttonOk, buttonCancel);
2476
2477 /* setup validation */
2478 QIWidgetValidator *wval =
2479 new QIWidgetValidator (QString ("%1: %2")
2480 .arg (pagePath (pageParallel), pageTitle),
2481 pageParallel, this);
2482 connect (page->mParallelPortBox, SIGNAL (toggled (bool)),
2483 wval, SLOT (revalidate()));
2484 connect (page->mIRQLine, SIGNAL (textChanged (const QString &)),
2485 wval, SLOT (revalidate()));
2486 connect (page->mIOPortLine, SIGNAL (textChanged (const QString &)),
2487 wval, SLOT (revalidate()));
2488 connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
2489 this, SLOT (enableOk (const QIWidgetValidator *)));
2490 connect (wval, SIGNAL (isValidRequested (QIWidgetValidator *)),
2491 this, SLOT (revalidate (QIWidgetValidator *)));
2492
2493 wval->revalidate();
2494}
2495
2496void VBoxVMSettingsDlg::slRAM_valueChanged( int val )
2497{
2498 leRAM->setText( QString().setNum( val ) );
2499}
2500
2501void VBoxVMSettingsDlg::leRAM_textChanged( const QString &text )
2502{
2503 slRAM->setValue( text.toInt() );
2504}
2505
2506void VBoxVMSettingsDlg::slVRAM_valueChanged( int val )
2507{
2508 leVRAM->setText( QString().setNum( val ) );
2509}
2510
2511void VBoxVMSettingsDlg::leVRAM_textChanged( const QString &text )
2512{
2513 slVRAM->setValue( text.toInt() );
2514}
2515
2516void VBoxVMSettingsDlg::cbOS_activated (int item)
2517{
2518 Q_UNUSED (item);
2519/// @todo (dmik) remove?
2520// CGuestOSType type = vboxGlobal().vmGuestOSType (item);
2521// txRAMBest->setText (tr ("<qt>Best&nbsp;%1&nbsp;MB<qt>")
2522// .arg (type.GetRecommendedRAM()));
2523// txVRAMBest->setText (tr ("<qt>Best&nbsp;%1&nbsp;MB</qt>")
2524// .arg (type.GetRecommendedVRAM()));
2525 txRAMBest->setText (QString::null);
2526 txVRAMBest->setText (QString::null);
2527}
2528
2529void VBoxVMSettingsDlg::tbResetSavedStateFolder_clicked()
2530{
2531 /*
2532 * do this instead of le->setText (QString::null) to cause
2533 * isModified() return true
2534 */
2535 leSnapshotFolder->selectAll();
2536 leSnapshotFolder->del();
2537}
2538
2539void VBoxVMSettingsDlg::tbSelectSavedStateFolder_clicked()
2540{
2541 QString settingsFolder = VBoxGlobal::getFirstExistingDir (leSnapshotFolder->text());
2542 if (settingsFolder.isNull())
2543 settingsFolder = QFileInfo (cmachine.GetSettingsFilePath()).dirPath (true);
2544
2545 QString folder = vboxGlobal().getExistingDirectory (settingsFolder, this);
2546 if (folder.isNull())
2547 return;
2548
2549 folder = QDir::convertSeparators (folder);
2550 /* remove trailing slash if any */
2551 folder.remove (QRegExp ("[\\\\/]$"));
2552
2553 /*
2554 * do this instead of le->setText (folder) to cause
2555 * isModified() return true
2556 */
2557 leSnapshotFolder->selectAll();
2558 leSnapshotFolder->insert (folder);
2559}
2560
2561// USB Filter stuff
2562////////////////////////////////////////////////////////////////////////////////
2563
2564void VBoxVMSettingsDlg::usbAdapterToggled (bool aOn)
2565{
2566 if (!aOn)
2567 cbEnableUSBEhci->setChecked (aOn);
2568 grbUSBFilters->setEnabled (aOn);
2569}
2570
2571void VBoxVMSettingsDlg::addUSBFilter (const CUSBDeviceFilter &aFilter, bool isNew)
2572{
2573 QListViewItem *currentItem = isNew
2574 ? lvUSBFilters->currentItem()
2575 : lvUSBFilters->lastItem();
2576
2577 VBoxUSBFilterSettings *settings = new VBoxUSBFilterSettings (wstUSBFilters);
2578 settings->setup (VBoxUSBFilterSettings::MachineType);
2579 settings->getFromFilter (aFilter);
2580
2581 USBListItem *item = new USBListItem (lvUSBFilters, currentItem);
2582 item->setOn (aFilter.GetActive());
2583 item->setText (lvUSBFilters_Name, aFilter.GetName());
2584
2585 item->mId = wstUSBFilters->addWidget (settings);
2586
2587 /* fix the tab order so that main dialog's buttons are always the last */
2588 setTabOrder (settings->focusProxy(), buttonHelp);
2589 setTabOrder (buttonHelp, buttonOk);
2590 setTabOrder (buttonOk, buttonCancel);
2591
2592 if (isNew)
2593 {
2594 lvUSBFilters->setSelected (item, true);
2595 lvUSBFilters_currentChanged (item);
2596 settings->leUSBFilterName->setFocus();
2597 }
2598
2599 connect (settings->leUSBFilterName, SIGNAL (textChanged (const QString &)),
2600 this, SLOT (lvUSBFilters_setCurrentText (const QString &)));
2601
2602 /* setup validation */
2603
2604 QIWidgetValidator *wval =
2605 new QIWidgetValidator (pagePath (pageUSB), settings, settings);
2606 connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
2607 this, SLOT (enableOk (const QIWidgetValidator *)));
2608
2609 wval->revalidate();
2610}
2611
2612void VBoxVMSettingsDlg::lvUSBFilters_currentChanged (QListViewItem *item)
2613{
2614 if (item && lvUSBFilters->selectedItem() != item)
2615 lvUSBFilters->setSelected (item, true);
2616
2617 tbRemoveUSBFilter->setEnabled (!!item);
2618
2619 tbUSBFilterUp->setEnabled (!!item && item->itemAbove());
2620 tbUSBFilterDown->setEnabled (!!item && item->itemBelow());
2621
2622 if (item)
2623 {
2624 USBListItem *uli = static_cast <USBListItem *> (item);
2625 wstUSBFilters->raiseWidget (uli->mId);
2626 }
2627 else
2628 {
2629 /* raise the disabled widget */
2630 wstUSBFilters->raiseWidget (0);
2631 }
2632}
2633
2634void VBoxVMSettingsDlg::lvUSBFilters_setCurrentText (const QString &aText)
2635{
2636 QListViewItem *item = lvUSBFilters->currentItem();
2637 Assert (item);
2638
2639 item->setText (lvUSBFilters_Name, aText);
2640}
2641
2642void VBoxVMSettingsDlg::tbAddUSBFilter_clicked()
2643{
2644 /* search for the max available filter index */
2645 int maxFilterIndex = 0;
2646 QString usbFilterName = tr ("New Filter %1", "usb");
2647 QRegExp regExp (QString ("^") + usbFilterName.arg ("([0-9]+)") + QString ("$"));
2648 QListViewItemIterator iterator (lvUSBFilters);
2649 while (*iterator)
2650 {
2651 QString filterName = (*iterator)->text (lvUSBFilters_Name);
2652 int pos = regExp.search (filterName);
2653 if (pos != -1)
2654 maxFilterIndex = regExp.cap (1).toInt() > maxFilterIndex ?
2655 regExp.cap (1).toInt() : maxFilterIndex;
2656 ++ iterator;
2657 }
2658
2659 /* creating new usb filter */
2660 CUSBDeviceFilter filter = cmachine.GetUSBController()
2661 .CreateDeviceFilter (usbFilterName.arg (maxFilterIndex + 1));
2662
2663 filter.SetActive (true);
2664 addUSBFilter (filter, true /* isNew */);
2665
2666 mUSBFilterListModified = true;
2667}
2668
2669void VBoxVMSettingsDlg::tbAddUSBFilterFrom_clicked()
2670{
2671 usbDevicesMenu->exec (QCursor::pos());
2672}
2673
2674void VBoxVMSettingsDlg::menuAddUSBFilterFrom_activated (int aIndex)
2675{
2676 CUSBDevice usb = usbDevicesMenu->getUSB (aIndex);
2677 /* if null then some other item but a USB device is selected */
2678 if (usb.isNull())
2679 return;
2680
2681 CUSBDeviceFilter filter = cmachine.GetUSBController()
2682 .CreateDeviceFilter (vboxGlobal().details (usb));
2683
2684 filter.SetVendorId (QString().sprintf ("%04hX", usb.GetVendorId()));
2685 filter.SetProductId (QString().sprintf ("%04hX", usb.GetProductId()));
2686 filter.SetRevision (QString().sprintf ("%04hX", usb.GetRevision()));
2687 /* The port property depends on the host computer rather than on the USB
2688 * device itself; for this reason only a few people will want to use it in
2689 * the filter since the same device plugged into a different socket will
2690 * not match the filter in this case. */
2691#if 0
2692 /// @todo set it anyway if Alt is currently pressed
2693 filter.SetPort (QString().sprintf ("%04hX", usb.GetPort()));
2694#endif
2695 filter.SetManufacturer (usb.GetManufacturer());
2696 filter.SetProduct (usb.GetProduct());
2697 filter.SetSerialNumber (usb.GetSerialNumber());
2698 filter.SetRemote (usb.GetRemote() ? "yes" : "no");
2699
2700 filter.SetActive (true);
2701 addUSBFilter (filter, true /* isNew */);
2702
2703 mUSBFilterListModified = true;
2704}
2705
2706void VBoxVMSettingsDlg::tbRemoveUSBFilter_clicked()
2707{
2708 QListViewItem *item = lvUSBFilters->currentItem();
2709 Assert (item);
2710
2711 USBListItem *uli = static_cast <USBListItem *> (item);
2712 QWidget *settings = wstUSBFilters->widget (uli->mId);
2713 Assert (settings);
2714 wstUSBFilters->removeWidget (settings);
2715 delete settings;
2716
2717 delete item;
2718
2719 lvUSBFilters->setSelected (lvUSBFilters->currentItem(), true);
2720 mUSBFilterListModified = true;
2721}
2722
2723void VBoxVMSettingsDlg::tbUSBFilterUp_clicked()
2724{
2725 QListViewItem *item = lvUSBFilters->currentItem();
2726 Assert (item);
2727
2728 QListViewItem *itemAbove = item->itemAbove();
2729 Assert (itemAbove);
2730 itemAbove = itemAbove->itemAbove();
2731
2732 if (!itemAbove)
2733 {
2734 /* overcome Qt stupidity */
2735 item->itemAbove()->moveItem (item);
2736 }
2737 else
2738 item->moveItem (itemAbove);
2739
2740 lvUSBFilters_currentChanged (item);
2741 mUSBFilterListModified = true;
2742}
2743
2744void VBoxVMSettingsDlg::tbUSBFilterDown_clicked()
2745{
2746 QListViewItem *item = lvUSBFilters->currentItem();
2747 Assert (item);
2748
2749 QListViewItem *itemBelow = item->itemBelow();
2750 Assert (itemBelow);
2751
2752 item->moveItem (itemBelow);
2753
2754 lvUSBFilters_currentChanged (item);
2755 mUSBFilterListModified = true;
2756}
2757
2758#include "VBoxVMSettingsDlg.ui.moc"
2759
Note: See TracBrowser for help on using the repository browser.

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