VirtualBox

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

Last change on this file since 3460 was 3349, checked in by vboxsync, 18 years ago

FE/Qt: Fixed focus traversal order on the Network page of the VM settings dialog.

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