VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsUSB.cpp@ 37764

Last change on this file since 37764 was 37764, checked in by vboxsync, 13 years ago

FE/Qt: Machine settings / USB page: Some UI fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 36.9 KB
Line 
1/* $Id: UIMachineSettingsUSB.cpp 37764 2011-07-04 13:48:03Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt4 GUI ("VirtualBox"):
5 * UIMachineSettingsUSB class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2011 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Local includes */
21#include "QIWidgetValidator.h"
22#include "UIIconPool.h"
23#include "VBoxGlobal.h"
24#include "VBoxProblemReporter.h"
25#include "UIToolBar.h"
26#include "UIMachineSettingsUSB.h"
27#include "UIMachineSettingsUSBFilterDetails.h"
28
29/* Global includes */
30#include <QHeaderView>
31
32UIMachineSettingsUSB::UIMachineSettingsUSB(UISettingsPageType type)
33 : UISettingsPage(type)
34 , mValidator(0)
35 , m_pToolBar(0)
36 , mNewAction(0), mAddAction(0), mEdtAction(0), mDelAction(0)
37 , mMupAction(0), mMdnAction(0)
38 , mUSBDevicesMenu(0)
39{
40 /* Apply UI decorations */
41 Ui::UIMachineSettingsUSB::setupUi (this);
42
43 /* Prepare actions */
44 mNewAction = new QAction (mTwFilters);
45 mAddAction = new QAction (mTwFilters);
46 mEdtAction = new QAction (mTwFilters);
47 mDelAction = new QAction (mTwFilters);
48 mMupAction = new QAction (mTwFilters);
49 mMdnAction = new QAction (mTwFilters);
50
51 mNewAction->setShortcut (QKeySequence ("Ins"));
52 mAddAction->setShortcut (QKeySequence ("Alt+Ins"));
53 mEdtAction->setShortcut (QKeySequence ("Ctrl+Return"));
54 mDelAction->setShortcut (QKeySequence ("Del"));
55 mMupAction->setShortcut (QKeySequence ("Ctrl+Up"));
56 mMdnAction->setShortcut (QKeySequence ("Ctrl+Down"));
57
58 mNewAction->setIcon(UIIconPool::iconSet(":/usb_new_16px.png",
59 ":/usb_new_disabled_16px.png"));
60 mAddAction->setIcon(UIIconPool::iconSet(":/usb_add_16px.png",
61 ":/usb_add_disabled_16px.png"));
62 mEdtAction->setIcon(UIIconPool::iconSet(":/usb_filter_edit_16px.png",
63 ":/usb_filter_edit_disabled_16px.png"));
64 mDelAction->setIcon(UIIconPool::iconSet(":/usb_remove_16px.png",
65 ":/usb_remove_disabled_16px.png"));
66 mMupAction->setIcon(UIIconPool::iconSet(":/usb_moveup_16px.png",
67 ":/usb_moveup_disabled_16px.png"));
68 mMdnAction->setIcon(UIIconPool::iconSet(":/usb_movedown_16px.png",
69 ":/usb_movedown_disabled_16px.png"));
70
71 /* Prepare toolbar */
72 m_pToolBar = new UIToolBar (mWtFilterHandler);
73 m_pToolBar->setUsesTextLabel (false);
74 m_pToolBar->setIconSize (QSize (16, 16));
75 m_pToolBar->setOrientation (Qt::Vertical);
76 m_pToolBar->addAction (mNewAction);
77 m_pToolBar->addAction (mAddAction);
78 m_pToolBar->addAction (mEdtAction);
79 m_pToolBar->addAction (mDelAction);
80 m_pToolBar->addAction (mMupAction);
81 m_pToolBar->addAction (mMdnAction);
82 m_pToolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
83 m_pToolBar->updateGeometry();
84#ifdef Q_WS_MAC
85 /* On the Mac this has to be slightly higher, than what sizeHint returned.
86 * No idea why. */
87 m_pToolBar->setMinimumHeight(m_pToolBar->sizeHint().height() + 4);
88#else
89 m_pToolBar->setMinimumHeight(m_pToolBar->sizeHint().height());
90#endif /* Q_WS_MAC */
91 mWtFilterHandler->layout()->addWidget (m_pToolBar);
92
93 /* Setup connections */
94 connect (mGbUSB, SIGNAL (toggled (bool)),
95 this, SLOT (usbAdapterToggled (bool)));
96 connect (mTwFilters, SIGNAL (currentItemChanged (QTreeWidgetItem*, QTreeWidgetItem*)),
97 this, SLOT (currentChanged (QTreeWidgetItem*)));
98 connect (mTwFilters, SIGNAL (customContextMenuRequested (const QPoint &)),
99 this, SLOT (showContextMenu (const QPoint &)));
100 connect (mTwFilters, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)),
101 this, SLOT (edtClicked()));
102 connect (mTwFilters, SIGNAL (itemChanged (QTreeWidgetItem *, int)),
103 this, SLOT (sltUpdateActivityState(QTreeWidgetItem *)));
104
105 mUSBDevicesMenu = new VBoxUSBMenu (this);
106 connect (mUSBDevicesMenu, SIGNAL (triggered (QAction*)),
107 this, SLOT (addConfirmed (QAction *)));
108 connect (mNewAction, SIGNAL (triggered (bool)),
109 this, SLOT (newClicked()));
110 connect (mAddAction, SIGNAL (triggered (bool)),
111 this, SLOT (addClicked()));
112 connect (mEdtAction, SIGNAL (triggered (bool)),
113 this, SLOT (edtClicked()));
114 connect (mDelAction, SIGNAL (triggered (bool)),
115 this, SLOT (delClicked()));
116 connect (mMupAction, SIGNAL (triggered (bool)),
117 this, SLOT (mupClicked()));
118 connect (mMdnAction, SIGNAL (triggered (bool)),
119 this, SLOT (mdnClicked()));
120
121 /* Setup dialog */
122 mTwFilters->header()->hide();
123
124 /* Applying language settings */
125 retranslateUi();
126
127#ifndef VBOX_WITH_EHCI
128 mCbUSB2->setHidden(true);
129#endif /* VBOX_WITH_EHCI */
130}
131
132bool UIMachineSettingsUSB::isOHCIEnabled() const
133{
134 return mGbUSB->isChecked();
135}
136
137/* Load data to cashe from corresponding external object(s),
138 * this task COULD be performed in other than GUI thread: */
139void UIMachineSettingsUSB::loadToCacheFrom(QVariant &data)
140{
141 /* Fetch data to properties & settings or machine: */
142 fetchData(data);
143
144 /* Clear cache initially: */
145 m_cache.clear();
146
147 /* Depending on page type: */
148 switch (pageType())
149 {
150 case UISettingsPageType_Global:
151 {
152 /* For each USB filter: */
153 const CHostUSBDeviceFilterVector &filters = vboxGlobal().virtualBox().GetHost().GetUSBDeviceFilters();
154 for (int iFilterIndex = 0; iFilterIndex < filters.size(); ++iFilterIndex)
155 {
156 /* Prepare USB filter data: */
157 UIDataSettingsMachineUSBFilter usbFilterData;
158
159 /* Check if filter is valid: */
160 const CHostUSBDeviceFilter &filter = filters[iFilterIndex];
161 if (!filter.isNull())
162 {
163 usbFilterData.m_fActive = filter.GetActive();
164 usbFilterData.m_strName = filter.GetName();
165 usbFilterData.m_strVendorId = filter.GetVendorId();
166 usbFilterData.m_strProductId = filter.GetProductId();
167 usbFilterData.m_strRevision = filter.GetRevision();
168 usbFilterData.m_strManufacturer = filter.GetManufacturer();
169 usbFilterData.m_strProduct = filter.GetProduct();
170 usbFilterData.m_strSerialNumber = filter.GetSerialNumber();
171 usbFilterData.m_strPort = filter.GetPort();
172 usbFilterData.m_strRemote = filter.GetRemote();
173 usbFilterData.m_action = filter.GetAction();
174 CHostUSBDevice hostUSBDevice(filter);
175 if (!hostUSBDevice.isNull())
176 {
177 usbFilterData.m_fHostUSBDevice = true;
178 usbFilterData.m_hostUSBDeviceState = hostUSBDevice.GetState();
179 }
180 else
181 {
182 usbFilterData.m_fHostUSBDevice = false;
183 usbFilterData.m_hostUSBDeviceState = KUSBDeviceState_NotSupported;
184 }
185 }
186
187 /* Cache USB filter data: */
188 m_cache.child(iFilterIndex).cacheInitialData(usbFilterData);
189 }
190
191 break;
192 }
193 case UISettingsPageType_Machine:
194 {
195 /* Prepare USB data: */
196 UIDataSettingsMachineUSB usbData;
197
198 /* Check if controller is valid: */
199 const CUSBController &controller = m_machine.GetUSBController();
200 if (!controller.isNull())
201 {
202 /* Gather USB values: */
203 usbData.m_fUSBEnabled = controller.GetEnabled();
204 usbData.m_fEHCIEnabled = controller.GetEnabledEhci();
205
206 /* For each USB filter: */
207 const CUSBDeviceFilterVector &filters = controller.GetDeviceFilters();
208 for (int iFilterIndex = 0; iFilterIndex < filters.size(); ++iFilterIndex)
209 {
210 /* Prepare USB filter data: */
211 UIDataSettingsMachineUSBFilter usbFilterData;
212
213 /* Check if filter is valid: */
214 const CUSBDeviceFilter &filter = filters[iFilterIndex];
215 if (!filter.isNull())
216 {
217 usbFilterData.m_fActive = filter.GetActive();
218 usbFilterData.m_strName = filter.GetName();
219 usbFilterData.m_strVendorId = filter.GetVendorId();
220 usbFilterData.m_strProductId = filter.GetProductId();
221 usbFilterData.m_strRevision = filter.GetRevision();
222 usbFilterData.m_strManufacturer = filter.GetManufacturer();
223 usbFilterData.m_strProduct = filter.GetProduct();
224 usbFilterData.m_strSerialNumber = filter.GetSerialNumber();
225 usbFilterData.m_strPort = filter.GetPort();
226 usbFilterData.m_strRemote = filter.GetRemote();
227 }
228
229 /* Cache USB filter data: */
230 m_cache.child(iFilterIndex).cacheInitialData(usbFilterData);
231 }
232 }
233
234 /* Cache USB data: */
235 m_cache.cacheInitialData(usbData);
236
237 break;
238 }
239 default:
240 break;
241 }
242
243 /* Upload properties & settings or machine to data: */
244 uploadData(data);
245}
246
247/* Load data to corresponding widgets from cache,
248 * this task SHOULD be performed in GUI thread only: */
249void UIMachineSettingsUSB::getFromCache()
250{
251 /* Clear list initially: */
252 mTwFilters->clear();
253 m_filters.clear();
254
255 /* Depending on page type: */
256 switch (pageType())
257 {
258 case UISettingsPageType_Global:
259 {
260 /* Hide unused widgets: */
261 mGbUSB->setVisible(false);
262 mCbUSB2->setVisible(false);
263 break;
264 }
265 case UISettingsPageType_Machine:
266 {
267 /* Get USB data from cache: */
268 const UIDataSettingsMachineUSB &usbData = m_cache.base();
269 /* Load USB data to page: */
270 mGbUSB->setChecked(usbData.m_fUSBEnabled);
271 mCbUSB2->setChecked(usbData.m_fEHCIEnabled);
272 break;
273 }
274 default:
275 break;
276 }
277
278 /* For each USB filter => load it to the page: */
279 for (int iFilterIndex = 0; iFilterIndex < m_cache.childCount(); ++iFilterIndex)
280 addUSBFilter(m_cache.child(iFilterIndex).base(), false /* its new? */);
281
282 /* Choose first filter as current: */
283 mTwFilters->setCurrentItem(mTwFilters->topLevelItem(0));
284
285 /* Update page: */
286 usbAdapterToggled(mGbUSB->isChecked());
287
288 /* Polish page finally: */
289 polishPage();
290
291 /* Revalidate if possible: */
292 if (mValidator)
293 mValidator->revalidate();
294}
295
296/* Save data from corresponding widgets to cache,
297 * this task SHOULD be performed in GUI thread only: */
298void UIMachineSettingsUSB::putToCache()
299{
300 /* Depending on page type: */
301 switch (pageType())
302 {
303 case UISettingsPageType_Machine:
304 {
305 /* Prepare USB data: */
306 UIDataSettingsMachineUSB usbData = m_cache.base();
307
308 /* USB 1.0 (OHCI): */
309 usbData.m_fUSBEnabled = mGbUSB->isChecked();
310 /* USB 2.0 (EHCI): */
311 QString strExtPackName = "Oracle VM VirtualBox Extension Pack";
312 CExtPack extPack = vboxGlobal().virtualBox().GetExtensionPackManager().Find(strExtPackName);
313 usbData.m_fEHCIEnabled = extPack.isNull() || !extPack.GetUsable() ? false : mCbUSB2->isChecked();
314
315 /* Update USB cache: */
316 m_cache.cacheCurrentData(usbData);
317
318 break;
319 }
320 default:
321 break;
322 }
323
324 /* For each USB filter => recache USB filter data: */
325 for (int iFilterIndex = 0; iFilterIndex < m_filters.size(); ++iFilterIndex)
326 m_cache.child(iFilterIndex).cacheCurrentData(m_filters[iFilterIndex]);
327}
328
329/* Save data from cache to corresponding external object(s),
330 * this task COULD be performed in other than GUI thread: */
331void UIMachineSettingsUSB::saveFromCacheTo(QVariant &data)
332{
333 /* Fetch data to properties & settings or machine: */
334 fetchData(data);
335
336 /* Save settings depending on page type: */
337 switch (pageType())
338 {
339 /* Here come the global USB properties: */
340 case UISettingsPageType_Global:
341 {
342 /* Check if USB data really changed: */
343 if (m_cache.wasChanged())
344 {
345 /* Store USB data: */
346 if (isMachineInValidMode())
347 {
348 /* Get host: */
349 CHost host = vboxGlobal().virtualBox().GetHost();
350 /* For each USB filter data set: */
351 for (int iFilterIndex = 0; iFilterIndex < m_cache.childCount(); ++iFilterIndex)
352 {
353 /* Check if USB filter data really changed: */
354 const UICacheSettingsMachineUSBFilter &usbFilterCache = m_cache.child(iFilterIndex);
355 if (usbFilterCache.wasChanged())
356 {
357 /* If filter was removed or updated: */
358 if (usbFilterCache.wasRemoved() || usbFilterCache.wasUpdated())
359 host.RemoveUSBDeviceFilter(iFilterIndex);
360 /* If filter was created or updated: */
361 if (usbFilterCache.wasCreated() || usbFilterCache.wasUpdated())
362 {
363 /* Get USB filter data from cache: */
364 const UIDataSettingsMachineUSBFilter &usbFilterData = usbFilterCache.data();
365
366 /* Store USB filter data: */
367 CHostUSBDeviceFilter hostFilter = host.CreateUSBDeviceFilter(usbFilterData.m_strName);
368 hostFilter.SetActive(usbFilterData.m_fActive);
369 hostFilter.SetVendorId(usbFilterData.m_strVendorId);
370 hostFilter.SetProductId(usbFilterData.m_strProductId);
371 hostFilter.SetRevision(usbFilterData.m_strRevision);
372 hostFilter.SetManufacturer(usbFilterData.m_strManufacturer);
373 hostFilter.SetProduct(usbFilterData.m_strProduct);
374 hostFilter.SetSerialNumber(usbFilterData.m_strSerialNumber);
375 hostFilter.SetPort(usbFilterData.m_strPort);
376 hostFilter.SetRemote(usbFilterData.m_strRemote);
377 hostFilter.SetAction(usbFilterData.m_action);
378 host.InsertUSBDeviceFilter(iFilterIndex, hostFilter);
379 }
380 }
381 }
382 }
383 }
384 break;
385 }
386 /* Here come VM USB properties: */
387 case UISettingsPageType_Machine:
388 {
389 /* Check if USB data really changed: */
390 if (m_cache.wasChanged())
391 {
392 /* Check if controller is valid: */
393 CUSBController controller = m_machine.GetUSBController();
394 if (!controller.isNull())
395 {
396 /* Get USB data from cache: */
397 const UIDataSettingsMachineUSB &usbData = m_cache.data();
398 /* Store USB data: */
399 if (isMachineOffline())
400 {
401 controller.SetEnabled(usbData.m_fUSBEnabled);
402 controller.SetEnabledEhci(usbData.m_fEHCIEnabled);
403 }
404 /* Store USB filters data: */
405 if (isMachineInValidMode())
406 {
407 /* For each USB filter data set: */
408 int iOperationPosition = 0;
409 for (int iFilterIndex = 0; iFilterIndex < m_cache.childCount(); ++iFilterIndex)
410 {
411 /* Check if USB filter data really changed: */
412 const UICacheSettingsMachineUSBFilter &usbFilterCache = m_cache.child(iFilterIndex);
413 if (usbFilterCache.wasChanged())
414 {
415 /* If filter was removed or updated: */
416 if (usbFilterCache.wasRemoved() || usbFilterCache.wasUpdated())
417 {
418 controller.RemoveDeviceFilter(iOperationPosition);
419 if (usbFilterCache.wasRemoved())
420 --iOperationPosition;
421 }
422
423 /* If filter was created or updated: */
424 if (usbFilterCache.wasCreated() || usbFilterCache.wasUpdated())
425 {
426 /* Get USB filter data from cache: */
427 const UIDataSettingsMachineUSBFilter &usbFilterData = usbFilterCache.data();
428 /* Store USB filter data: */
429 CUSBDeviceFilter filter = controller.CreateDeviceFilter(usbFilterData.m_strName);
430 filter.SetActive(usbFilterData.m_fActive);
431 filter.SetVendorId(usbFilterData.m_strVendorId);
432 filter.SetProductId(usbFilterData.m_strProductId);
433 filter.SetRevision(usbFilterData.m_strRevision);
434 filter.SetManufacturer(usbFilterData.m_strManufacturer);
435 filter.SetProduct(usbFilterData.m_strProduct);
436 filter.SetSerialNumber(usbFilterData.m_strSerialNumber);
437 filter.SetPort(usbFilterData.m_strPort);
438 filter.SetRemote(usbFilterData.m_strRemote);
439 controller.InsertDeviceFilter(iOperationPosition, filter);
440 }
441 }
442
443 /* Advance operation position: */
444 ++iOperationPosition;
445 }
446 }
447 }
448 }
449 break;
450 }
451 default:
452 break;
453 }
454
455 /* Upload properties & settings or machine to data: */
456 uploadData(data);
457}
458
459void UIMachineSettingsUSB::setValidator (QIWidgetValidator *aVal)
460{
461 mValidator = aVal;
462 connect (mGbUSB, SIGNAL (stateChanged (int)), mValidator, SLOT (revalidate()));
463 connect(mCbUSB2, SIGNAL(stateChanged(int)), mValidator, SLOT(revalidate()));
464}
465
466bool UIMachineSettingsUSB::revalidate(QString &strWarningText, QString& /* strTitle */)
467{
468 /* USB 2.0 Extension Pack presence test: */
469 QString strExtPackName = "Oracle VM VirtualBox Extension Pack";
470 CExtPack extPack = vboxGlobal().virtualBox().GetExtensionPackManager().Find(strExtPackName);
471 if (mGbUSB->isChecked() && mCbUSB2->isChecked() && (extPack.isNull() || !extPack.GetUsable()))
472 {
473 strWarningText = tr("USB 2.0 is currently enabled for this virtual machine. "
474 "However this requires the <b>%1</b> to be installed. "
475 "Please install the Extension Pack from the VirtualBox download site. "
476 "After this you will be able to re-enable USB 2.0. "
477 "It will be disabled in the meantime unless you cancel the current settings changes.")
478 .arg(strExtPackName);
479 vboxProblem().remindAboutUnsupportedUSB2(strExtPackName, this);
480 return true;
481 }
482 return true;
483}
484
485void UIMachineSettingsUSB::setOrderAfter (QWidget *aWidget)
486{
487 setTabOrder (aWidget, mGbUSB);
488 setTabOrder (mGbUSB, mCbUSB2);
489 setTabOrder (mCbUSB2, mTwFilters);
490}
491
492void UIMachineSettingsUSB::retranslateUi()
493{
494 /* Translate uic generated strings */
495 Ui::UIMachineSettingsUSB::retranslateUi (this);
496
497 mNewAction->setText (tr ("&Add Empty Filter"));
498 mAddAction->setText (tr ("A&dd Filter From Device"));
499 mEdtAction->setText (tr ("&Edit Filter"));
500 mDelAction->setText (tr ("&Remove Filter"));
501 mMupAction->setText (tr ("&Move Filter Up"));
502 mMdnAction->setText (tr ("M&ove Filter Down"));
503
504 mNewAction->setToolTip (mNewAction->text().remove ('&') +
505 QString (" (%1)").arg (mNewAction->shortcut().toString()));
506 mAddAction->setToolTip (mAddAction->text().remove ('&') +
507 QString (" (%1)").arg (mAddAction->shortcut().toString()));
508 mEdtAction->setToolTip (mEdtAction->text().remove ('&') +
509 QString (" (%1)").arg (mEdtAction->shortcut().toString()));
510 mDelAction->setToolTip (mDelAction->text().remove ('&') +
511 QString (" (%1)").arg (mDelAction->shortcut().toString()));
512 mMupAction->setToolTip (mMupAction->text().remove ('&') +
513 QString (" (%1)").arg (mMupAction->shortcut().toString()));
514 mMdnAction->setToolTip (mMdnAction->text().remove ('&') +
515 QString (" (%1)").arg (mMdnAction->shortcut().toString()));
516
517 mNewAction->setWhatsThis (tr ("Adds a new USB filter with all fields "
518 "initially set to empty strings. Note "
519 "that such a filter will match any "
520 "attached USB device."));
521 mAddAction->setWhatsThis (tr ("Adds a new USB filter with all fields "
522 "set to the values of the selected USB "
523 "device attached to the host PC."));
524 mEdtAction->setWhatsThis (tr ("Edits the selected USB filter."));
525 mDelAction->setWhatsThis (tr ("Removes the selected USB filter."));
526 mMupAction->setWhatsThis (tr ("Moves the selected USB filter up."));
527 mMdnAction->setWhatsThis (tr ("Moves the selected USB filter down."));
528
529 mUSBFilterName = tr ("New Filter %1", "usb");
530}
531
532void UIMachineSettingsUSB::usbAdapterToggled(bool fEnabled)
533{
534 /* Enable/disable USB children: */
535 mUSBChild->setEnabled(isMachineInValidMode() && fEnabled);
536 mCbUSB2->setEnabled(isMachineOffline() && fEnabled);
537 if (fEnabled)
538 {
539 /* If there is no chosen item but there is something to choose => choose it: */
540 if (mTwFilters->currentItem() == 0 && mTwFilters->topLevelItemCount() != 0)
541 mTwFilters->setCurrentItem(mTwFilters->topLevelItem(0));
542 }
543 /* Update current item: */
544 currentChanged(mTwFilters->currentItem());
545}
546
547void UIMachineSettingsUSB::currentChanged(QTreeWidgetItem *aItem)
548{
549 /* Get selected items: */
550 QList<QTreeWidgetItem*> selectedItems = mTwFilters->selectedItems();
551 /* Deselect all selected items first: */
552 for (int iItemIndex = 0; iItemIndex < selectedItems.size(); ++iItemIndex)
553 selectedItems[iItemIndex]->setSelected(false);
554
555 /* If tree-widget is NOT enabled => we should NOT select anything: */
556 if (!mTwFilters->isEnabled())
557 return;
558
559 /* Select item if requested: */
560 if (aItem)
561 aItem->setSelected(true);
562
563 /* Update corresponding action states: */
564 mEdtAction->setEnabled(aItem);
565 mDelAction->setEnabled(aItem);
566 mMupAction->setEnabled(aItem && mTwFilters->itemAbove(aItem));
567 mMdnAction->setEnabled(aItem && mTwFilters->itemBelow(aItem));
568}
569
570void UIMachineSettingsUSB::newClicked()
571{
572 /* Search for the max available filter index: */
573 int iMaxFilterIndex = 0;
574 QRegExp regExp(QString("^") + mUSBFilterName.arg("([0-9]+)") + QString("$"));
575 QTreeWidgetItemIterator iterator(mTwFilters);
576 while (*iterator)
577 {
578 QString filterName = (*iterator)->text(0);
579 int pos = regExp.indexIn(filterName);
580 if (pos != -1)
581 iMaxFilterIndex = regExp.cap(1).toInt() > iMaxFilterIndex ?
582 regExp.cap(1).toInt() : iMaxFilterIndex;
583 ++iterator;
584 }
585
586 /* Prepare new USB filter data: */
587 UIDataSettingsMachineUSBFilter usbFilterData;
588 switch (pageType())
589 {
590 case UISettingsPageType_Global:
591 usbFilterData.m_action = KUSBDeviceFilterAction_Hold;
592 break;
593 default:
594 break;
595 }
596 usbFilterData.m_fActive = true;
597 usbFilterData.m_strName = mUSBFilterName.arg(iMaxFilterIndex + 1);
598 usbFilterData.m_fHostUSBDevice = false;
599
600 /* Add new USB filter data: */
601 addUSBFilter(usbFilterData, true /* its new? */);
602
603 /* Revalidate if possible: */
604 if (mValidator)
605 mValidator->revalidate();
606}
607
608void UIMachineSettingsUSB::addClicked()
609{
610 mUSBDevicesMenu->exec(QCursor::pos());
611}
612
613void UIMachineSettingsUSB::addConfirmed(QAction *pAction)
614{
615 /* Get USB device: */
616 CUSBDevice usb = mUSBDevicesMenu->getUSB(pAction);
617 if (usb.isNull())
618 return;
619
620 /* Prepare new USB filter data: */
621 UIDataSettingsMachineUSBFilter usbFilterData;
622 switch (pageType())
623 {
624 case UISettingsPageType_Global:
625 usbFilterData.m_action = KUSBDeviceFilterAction_Hold;
626 break;
627 default:
628 break;
629 }
630 usbFilterData.m_fActive = true;
631 usbFilterData.m_strName = vboxGlobal().details(usb);
632 usbFilterData.m_fHostUSBDevice = false;
633 usbFilterData.m_strVendorId = QString().sprintf("%04hX", usb.GetVendorId());
634 usbFilterData.m_strProductId = QString().sprintf("%04hX", usb.GetProductId());
635 usbFilterData.m_strRevision = QString().sprintf("%04hX", usb.GetRevision());
636 /* The port property depends on the host computer rather than on the USB
637 * device itself; for this reason only a few people will want to use it
638 * in the filter since the same device plugged into a different socket
639 * will not match the filter in this case. */
640#if 0
641 usbFilterData.m_strPort = QString().sprintf("%04hX", usb.GetPort());
642#endif
643 usbFilterData.m_strManufacturer = usb.GetManufacturer();
644 usbFilterData.m_strProduct = usb.GetProduct();
645 usbFilterData.m_strSerialNumber = usb.GetSerialNumber();
646 usbFilterData.m_strRemote = QString::number(usb.GetRemote());
647
648 /* Add new USB filter data: */
649 addUSBFilter(usbFilterData, true /* its new? */);
650
651 /* Revalidate if possible: */
652 if (mValidator)
653 mValidator->revalidate();
654}
655
656void UIMachineSettingsUSB::edtClicked()
657{
658 /* Get current USB filter item: */
659 QTreeWidgetItem *pItem = mTwFilters->currentItem();
660 Assert(pItem);
661 UIDataSettingsMachineUSBFilter &usbFilterData = m_filters[mTwFilters->indexOfTopLevelItem(pItem)];
662
663 /* Configure USB filter details dialog: */
664 UIMachineSettingsUSBFilterDetails dlgFilterDetails(pageType(), this);
665 dlgFilterDetails.mLeName->setText(usbFilterData.m_strName);
666 dlgFilterDetails.mLeVendorID->setText(usbFilterData.m_strVendorId);
667 dlgFilterDetails.mLeProductID->setText(usbFilterData.m_strProductId);
668 dlgFilterDetails.mLeRevision->setText(usbFilterData.m_strRevision);
669 dlgFilterDetails.mLePort->setText(usbFilterData.m_strPort);
670 dlgFilterDetails.mLeManufacturer->setText(usbFilterData.m_strManufacturer);
671 dlgFilterDetails.mLeProduct->setText(usbFilterData.m_strProduct);
672 dlgFilterDetails.mLeSerialNo->setText(usbFilterData.m_strSerialNumber);
673 switch (pageType())
674 {
675 case UISettingsPageType_Global:
676 {
677 if (usbFilterData.m_action == KUSBDeviceFilterAction_Ignore)
678 dlgFilterDetails.mCbAction->setCurrentIndex(0);
679 else if (usbFilterData.m_action == KUSBDeviceFilterAction_Hold)
680 dlgFilterDetails.mCbAction->setCurrentIndex(1);
681 else
682 AssertMsgFailed(("Invalid USBDeviceFilterAction type"));
683 break;
684 }
685 case UISettingsPageType_Machine:
686 {
687 QString strRemote = usbFilterData.m_strRemote.toLower();
688 if (strRemote == "yes" || strRemote == "true" || strRemote == "1")
689 dlgFilterDetails.mCbRemote->setCurrentIndex(ModeOn);
690 else if (strRemote == "no" || strRemote == "false" || strRemote == "0")
691 dlgFilterDetails.mCbRemote->setCurrentIndex(ModeOff);
692 else
693 dlgFilterDetails.mCbRemote->setCurrentIndex(ModeAny);
694 break;
695 }
696 default:
697 break;
698 }
699
700 /* Run USB filter details dialog: */
701 if (dlgFilterDetails.exec() == QDialog::Accepted)
702 {
703 usbFilterData.m_strName = dlgFilterDetails.mLeName->text().isEmpty() ? QString::null : dlgFilterDetails.mLeName->text();
704 usbFilterData.m_strVendorId = dlgFilterDetails.mLeVendorID->text().isEmpty() ? QString::null : dlgFilterDetails.mLeVendorID->text();
705 usbFilterData.m_strProductId = dlgFilterDetails.mLeProductID->text().isEmpty() ? QString::null : dlgFilterDetails.mLeProductID->text();
706 usbFilterData.m_strRevision = dlgFilterDetails.mLeRevision->text().isEmpty() ? QString::null : dlgFilterDetails.mLeRevision->text();
707 usbFilterData.m_strManufacturer = dlgFilterDetails.mLeManufacturer->text().isEmpty() ? QString::null : dlgFilterDetails.mLeManufacturer->text();
708 usbFilterData.m_strProduct = dlgFilterDetails.mLeProduct->text().isEmpty() ? QString::null : dlgFilterDetails.mLeProduct->text();
709 usbFilterData.m_strSerialNumber = dlgFilterDetails.mLeSerialNo->text().isEmpty() ? QString::null : dlgFilterDetails.mLeSerialNo->text();
710 usbFilterData.m_strPort = dlgFilterDetails.mLePort->text().isEmpty() ? QString::null : dlgFilterDetails.mLePort->text();
711 switch (pageType())
712 {
713 case UISettingsPageType_Global:
714 {
715 usbFilterData.m_action = vboxGlobal().toUSBDevFilterAction(dlgFilterDetails.mCbAction->currentText());
716 break;
717 }
718 case UISettingsPageType_Machine:
719 {
720 switch (dlgFilterDetails.mCbRemote->currentIndex())
721 {
722 case ModeAny: usbFilterData.m_strRemote = QString(); break;
723 case ModeOn: usbFilterData.m_strRemote = QString::number(1); break;
724 case ModeOff: usbFilterData.m_strRemote = QString::number(0); break;
725 default: AssertMsgFailed(("Invalid combo box index"));
726 }
727 break;
728 }
729 default:
730 break;
731 }
732 pItem->setText(0, usbFilterData.m_strName);
733 pItem->setToolTip(0, toolTipFor(usbFilterData));
734 }
735}
736
737void UIMachineSettingsUSB::delClicked()
738{
739 /* Get current USB filter item: */
740 QTreeWidgetItem *pItem = mTwFilters->currentItem();
741 Assert(pItem);
742
743 /* Delete corresponding items: */
744 m_filters.removeAt(mTwFilters->indexOfTopLevelItem(pItem));
745 delete pItem;
746
747 /* Update current item: */
748 currentChanged(mTwFilters->currentItem());
749 /* Revalidate if possible: */
750 if (!mTwFilters->topLevelItemCount())
751 {
752 if (mValidator)
753 {
754 mValidator->rescan();
755 mValidator->revalidate();
756 }
757 }
758}
759
760void UIMachineSettingsUSB::mupClicked()
761{
762 QTreeWidgetItem *item = mTwFilters->currentItem();
763 Assert (item);
764
765 int index = mTwFilters->indexOfTopLevelItem (item);
766 QTreeWidgetItem *takenItem = mTwFilters->takeTopLevelItem (index);
767 Assert (item == takenItem);
768 mTwFilters->insertTopLevelItem (index - 1, takenItem);
769 m_filters.swap (index, index - 1);
770
771 mTwFilters->setCurrentItem (takenItem);
772}
773
774void UIMachineSettingsUSB::mdnClicked()
775{
776 QTreeWidgetItem *item = mTwFilters->currentItem();
777 Assert (item);
778
779 int index = mTwFilters->indexOfTopLevelItem (item);
780 QTreeWidgetItem *takenItem = mTwFilters->takeTopLevelItem (index);
781 Assert (item == takenItem);
782 mTwFilters->insertTopLevelItem (index + 1, takenItem);
783 m_filters.swap (index, index + 1);
784
785 mTwFilters->setCurrentItem (takenItem);
786}
787
788void UIMachineSettingsUSB::showContextMenu(const QPoint &pos)
789{
790 QMenu menu;
791 if (mTwFilters->isEnabled())
792 {
793 menu.addAction(mNewAction);
794 menu.addAction(mAddAction);
795 menu.addSeparator();
796 menu.addAction(mEdtAction);
797 menu.addSeparator();
798 menu.addAction(mDelAction);
799 menu.addSeparator();
800 menu.addAction(mMupAction);
801 menu.addAction(mMdnAction);
802 }
803 if (!menu.isEmpty())
804 menu.exec(mTwFilters->mapToGlobal(pos));
805}
806
807void UIMachineSettingsUSB::sltUpdateActivityState(QTreeWidgetItem *pChangedItem)
808{
809 /* Check changed USB filter item: */
810 Assert(pChangedItem);
811
812 /* Delete corresponding items: */
813 UIDataSettingsMachineUSBFilter &data = m_filters[mTwFilters->indexOfTopLevelItem(pChangedItem)];
814 data.m_fActive = pChangedItem->checkState(0) == Qt::Checked;
815}
816
817void UIMachineSettingsUSB::addUSBFilter(const UIDataSettingsMachineUSBFilter &usbFilterData, bool fIsNew)
818{
819 /* Append internal list with data: */
820 m_filters << usbFilterData;
821
822 /* Append tree-widget with item: */
823 QTreeWidgetItem *pItem = new QTreeWidgetItem;
824 pItem->setCheckState(0, usbFilterData.m_fActive ? Qt::Checked : Qt::Unchecked);
825 pItem->setText(0, usbFilterData.m_strName);
826 pItem->setToolTip(0, toolTipFor(usbFilterData));
827 mTwFilters->addTopLevelItem(pItem);
828
829 /* Select this item if its new: */
830 if (fIsNew)
831 mTwFilters->setCurrentItem(pItem);
832}
833
834/* Fetch data to m_properties & m_settings or m_machine & m_console: */
835void UIMachineSettingsUSB::fetchData(const QVariant &data)
836{
837 switch (pageType())
838 {
839 case UISettingsPageType_Global:
840 {
841 m_properties = data.value<UISettingsDataGlobal>().m_properties;
842 m_settings = data.value<UISettingsDataGlobal>().m_settings;
843 break;
844 }
845 case UISettingsPageType_Machine:
846 {
847 m_machine = data.value<UISettingsDataMachine>().m_machine;
848 m_console = data.value<UISettingsDataMachine>().m_console;
849 break;
850 }
851 default:
852 break;
853 }
854}
855
856/* Upload m_properties & m_settings or m_machine & m_console to data: */
857void UIMachineSettingsUSB::uploadData(QVariant &data) const
858{
859 switch (pageType())
860 {
861 case UISettingsPageType_Global:
862 {
863 data = QVariant::fromValue(UISettingsDataGlobal(m_properties, m_settings));
864 break;
865 }
866 case UISettingsPageType_Machine:
867 {
868 data = QVariant::fromValue(UISettingsDataMachine(m_machine, m_console));
869 break;
870 }
871 default:
872 break;
873 }
874}
875
876/* static */
877QString UIMachineSettingsUSB::toolTipFor(const UIDataSettingsMachineUSBFilter &usbFilterData)
878{
879 /* Prepare tool-tip: */
880 QString strToolTip;
881
882 QString strVendorId = usbFilterData.m_strVendorId;
883 if (!strVendorId.isEmpty())
884 strToolTip += tr("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip").arg(strVendorId);
885
886 QString strProductId = usbFilterData.m_strProductId;
887 if (!strProductId.isEmpty())
888 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product ID: %2</nobr>", "USB filter tooltip").arg(strProductId);
889
890 QString strRevision = usbFilterData.m_strRevision;
891 if (!strRevision.isEmpty())
892 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Revision: %3</nobr>", "USB filter tooltip").arg(strRevision);
893
894 QString strProduct = usbFilterData.m_strProduct;
895 if (!strProduct.isEmpty())
896 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product: %4</nobr>", "USB filter tooltip").arg(strProduct);
897
898 QString strManufacturer = usbFilterData.m_strManufacturer;
899 if (!strManufacturer.isEmpty())
900 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip").arg(strManufacturer);
901
902 QString strSerial = usbFilterData.m_strSerialNumber;
903 if (!strSerial.isEmpty())
904 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Serial No.: %1</nobr>", "USB filter tooltip").arg(strSerial);
905
906 QString strPort = usbFilterData.m_strPort;
907 if (!strPort.isEmpty())
908 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>Port: %1</nobr>", "USB filter tooltip").arg(strPort);
909
910 /* Add the state field if it's a host USB device: */
911 if (usbFilterData.m_fHostUSBDevice)
912 {
913 strToolTip += strToolTip.isEmpty() ? "":"<br/>" + tr("<nobr>State: %1</nobr>", "USB filter tooltip")
914 .arg(vboxGlobal().toString(usbFilterData.m_hostUSBDeviceState));
915 }
916
917 return strToolTip;
918}
919
920void UIMachineSettingsUSB::polishPage()
921{
922 mGbUSB->setEnabled(isMachineOffline());
923 mUSBChild->setEnabled(isMachineInValidMode() && mGbUSB->isChecked());
924 mCbUSB2->setEnabled(isMachineOffline() && mGbUSB->isChecked());
925}
926
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use