1
/* $Id: VBoxGLSettingsNetwork.cpp $ */
4
* VBox frontends: Qt4 GUI ("VirtualBox"):
5
* VBoxGLSettingsNetwork class implementation
9
* Copyright (C) 2009 Oracle Corporation
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.
20
#include "QIWidgetValidator.h"
21
#include "VBoxGlobal.h"
22
#include "VBoxGLSettingsNetwork.h"
23
#include "VBoxGLSettingsNetworkDetails.h"
24
#include "VBoxProblemReporter.h"
27
#include <QHeaderView>
28
#include <QHostAddress>
30
NetworkItem::NetworkItem()
33
, mName (QString::null)
34
, mDhcpClientEnabled (false)
35
, mInterfaceAddress (QString::null)
36
, mInterfaceMask (QString::null)
37
, mIpv6Supported (false)
38
, mInterfaceAddress6 (QString::null)
39
, mInterfaceMaskLength6 (QString::null)
40
, mDhcpServerEnabled (false)
41
, mDhcpServerAddress (QString::null)
42
, mDhcpServerMask (QString::null)
43
, mDhcpLowerAddress (QString::null)
44
, mDhcpUpperAddress (QString::null)
48
void NetworkItem::getFromInterface (const CHostNetworkInterface &aInterface)
51
mInterface = aInterface;
52
mName = mInterface.GetName();
53
CDHCPServer dhcp = vboxGlobal().virtualBox().FindDHCPServerByNetworkName (mInterface.GetNetworkName());
54
if (dhcp.isNull()) vboxGlobal().virtualBox().CreateDHCPServer (mInterface.GetNetworkName());
55
dhcp = vboxGlobal().virtualBox().FindDHCPServerByNetworkName (mInterface.GetNetworkName());
56
AssertMsg (!dhcp.isNull(), ("DHCP Server creation failed!\n"));
57
setText (0, VBoxGLSettingsNetwork::tr ("%1 network", "<adapter name> network").arg (mName));
59
/* Host-only Interface settings */
60
mDhcpClientEnabled = mInterface.GetDhcpEnabled();
61
mInterfaceAddress = mInterface.GetIPAddress();
62
mInterfaceMask = mInterface.GetNetworkMask();
63
mIpv6Supported = mInterface.GetIPV6Supported();
64
mInterfaceAddress6 = mInterface.GetIPV6Address();
65
mInterfaceMaskLength6 = QString ("%1").arg (mInterface.GetIPV6NetworkMaskPrefixLength());
67
/* DHCP Server settings */
68
mDhcpServerEnabled = dhcp.GetEnabled();
69
mDhcpServerAddress = dhcp.GetIPAddress();
70
mDhcpServerMask = dhcp.GetNetworkMask();
71
mDhcpLowerAddress = dhcp.GetLowerIP();
72
mDhcpUpperAddress = dhcp.GetUpperIP();
78
void NetworkItem::putBackToInterface()
80
/* Host-only Interface settings */
81
if (mDhcpClientEnabled)
83
mInterface.EnableDynamicIpConfig();
87
AssertMsg (mInterfaceAddress.isEmpty() ||
88
QHostAddress (mInterfaceAddress).protocol() == QAbstractSocket::IPv4Protocol,
89
("Interface IPv4 address must be empty or IPv4-valid!\n"));
90
AssertMsg (mInterfaceMask.isEmpty() ||
91
QHostAddress (mInterfaceMask).protocol() == QAbstractSocket::IPv4Protocol,
92
("Interface IPv4 network mask must be empty or IPv4-valid!\n"));
93
mInterface.EnableStaticIpConfig (mInterfaceAddress, mInterfaceMask);
94
if (mInterface.GetIPV6Supported())
96
AssertMsg (mInterfaceAddress6.isEmpty() ||
97
QHostAddress (mInterfaceAddress6).protocol() == QAbstractSocket::IPv6Protocol,
98
("Interface IPv6 address must be empty or IPv6-valid!\n"));
99
mInterface.EnableStaticIpConfigV6 (mInterfaceAddress6, mInterfaceMaskLength6.toULong());
103
/* DHCP Server settings */
104
CDHCPServer dhcp = vboxGlobal().virtualBox().FindDHCPServerByNetworkName (mInterface.GetNetworkName());
105
AssertMsg (!dhcp.isNull(), ("DHCP Server should be already created!\n"));
106
dhcp.SetEnabled (mDhcpServerEnabled);
107
AssertMsg (QHostAddress (mDhcpServerAddress).protocol() == QAbstractSocket::IPv4Protocol,
108
("DHCP Server IPv4 address must be IPv4-valid!\n"));
109
AssertMsg (QHostAddress (mDhcpServerMask).protocol() == QAbstractSocket::IPv4Protocol,
110
("DHCP Server IPv4 network mask must be IPv4-valid!\n"));
111
AssertMsg (QHostAddress (mDhcpLowerAddress).protocol() == QAbstractSocket::IPv4Protocol,
112
("DHCP Server IPv4 lower bound must be IPv4-valid!\n"));
113
AssertMsg (QHostAddress (mDhcpUpperAddress).protocol() == QAbstractSocket::IPv4Protocol,
114
("DHCP Server IPv4 upper bound must be IPv4-valid!\n"));
115
dhcp.SetConfiguration (mDhcpServerAddress, mDhcpServerMask, mDhcpLowerAddress, mDhcpUpperAddress);
118
bool NetworkItem::revalidate (QString &aWarning, QString & /* aTitle */)
120
/* Host-only Interface validation */
121
if (!mDhcpClientEnabled)
123
if (!mInterfaceAddress.isEmpty() &&
124
(QHostAddress (mInterfaceAddress) == QHostAddress::Any ||
125
QHostAddress (mInterfaceAddress).protocol() != QAbstractSocket::IPv4Protocol))
127
aWarning = VBoxGLSettingsNetwork::tr ("host IPv4 address of <b>%1</b> is wrong").arg (text (0));
130
if (!mInterfaceMask.isEmpty() &&
131
(QHostAddress (mInterfaceMask) == QHostAddress::Any ||
132
QHostAddress (mInterfaceMask).protocol() != QAbstractSocket::IPv4Protocol))
134
aWarning = VBoxGLSettingsNetwork::tr ("host IPv4 network mask of <b>%1</b> is wrong").arg (text (0));
139
if (!mInterfaceAddress6.isEmpty() &&
140
(QHostAddress (mInterfaceAddress6) == QHostAddress::AnyIPv6 ||
141
QHostAddress (mInterfaceAddress6).protocol() != QAbstractSocket::IPv6Protocol))
143
aWarning = VBoxGLSettingsNetwork::tr ("host IPv6 address of <b>%1</b> is wrong").arg (text (0));
149
/* DHCP Server settings */
150
if (mDhcpServerEnabled)
152
if (QHostAddress (mDhcpServerAddress) == QHostAddress::Any ||
153
QHostAddress (mDhcpServerAddress).protocol() != QAbstractSocket::IPv4Protocol)
155
aWarning = VBoxGLSettingsNetwork::tr ("DHCP server address of <b>%1</b> is wrong").arg (text (0));
158
if (QHostAddress (mDhcpServerMask) == QHostAddress::Any ||
159
QHostAddress (mDhcpServerMask).protocol() != QAbstractSocket::IPv4Protocol)
161
aWarning = VBoxGLSettingsNetwork::tr ("DHCP server network mask of <b>%1</b> is wrong").arg (text (0));
164
if (QHostAddress (mDhcpLowerAddress) == QHostAddress::Any ||
165
QHostAddress (mDhcpLowerAddress).protocol() != QAbstractSocket::IPv4Protocol)
167
aWarning = VBoxGLSettingsNetwork::tr ("DHCP lower address bound of <b>%1</b> is wrong").arg (text (0));
170
if (QHostAddress (mDhcpUpperAddress) == QHostAddress::Any ||
171
QHostAddress (mDhcpUpperAddress).protocol() != QAbstractSocket::IPv4Protocol)
173
aWarning = VBoxGLSettingsNetwork::tr ("DHCP upper address bound of <b>%1</b> is wrong").arg (text (0));
180
QString NetworkItem::updateInfo()
182
/* Update information label */
183
QString hdr ("<tr><td><nobr>%1: </nobr></td>"
184
"<td><nobr>%2</nobr></td></tr>");
185
QString sub ("<tr><td><nobr> %1: </nobr></td>"
186
"<td><nobr>%2</nobr></td></tr>");
187
QString data, tip, buffer;
189
/* Host-only Interface information */
190
buffer = hdr.arg (VBoxGLSettingsNetwork::tr ("Adapter"))
191
.arg (mDhcpClientEnabled ? VBoxGLSettingsNetwork::tr ("Automatically configured", "interface")
192
: VBoxGLSettingsNetwork::tr ("Manually configured", "interface"));
196
if (!mDhcpClientEnabled)
198
buffer = sub.arg (VBoxGLSettingsNetwork::tr ("IPv4 Address"))
199
.arg (mInterfaceAddress.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "address")
200
: mInterfaceAddress) +
201
sub.arg (VBoxGLSettingsNetwork::tr ("IPv4 Network Mask"))
202
.arg (mInterfaceMask.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "mask")
208
buffer = sub.arg (VBoxGLSettingsNetwork::tr ("IPv6 Address"))
209
.arg (mInterfaceAddress6.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "address")
210
: mInterfaceAddress6) +
211
sub.arg (VBoxGLSettingsNetwork::tr ("IPv6 Network Mask Length"))
212
.arg (mInterfaceMaskLength6.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "length")
213
: mInterfaceMaskLength6);
218
/* DHCP Server information */
219
buffer = hdr.arg (VBoxGLSettingsNetwork::tr ("DHCP Server"))
220
.arg (mDhcpServerEnabled ? VBoxGLSettingsNetwork::tr ("Enabled", "server")
221
: VBoxGLSettingsNetwork::tr ("Disabled", "server"));
225
if (mDhcpServerEnabled)
227
buffer = sub.arg (VBoxGLSettingsNetwork::tr ("Address"))
228
.arg (mDhcpServerAddress.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "address")
229
: mDhcpServerAddress) +
230
sub.arg (VBoxGLSettingsNetwork::tr ("Network Mask"))
231
.arg (mDhcpServerMask.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "mask")
233
sub.arg (VBoxGLSettingsNetwork::tr ("Lower Bound"))
234
.arg (mDhcpLowerAddress.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "bound")
235
: mDhcpLowerAddress) +
236
sub.arg (VBoxGLSettingsNetwork::tr ("Upper Bound"))
237
.arg (mDhcpUpperAddress.isEmpty() ? VBoxGLSettingsNetwork::tr ("Not set", "bound")
238
: mDhcpUpperAddress);
244
return QString ("<table>") + data + QString ("</table>");
247
VBoxGLSettingsNetwork::VBoxGLSettingsNetwork()
249
/* Apply UI decorations */
250
Ui::VBoxGLSettingsNetwork::setupUi (this);
253
/* Make shifting spacer for MAC as we have fixed-size networks list */
254
QSpacerItem *shiftSpacer =
255
new QSpacerItem (0, 1, QSizePolicy::Expanding, QSizePolicy::Preferred);
256
QGridLayout *mainLayout = static_cast <QGridLayout*> (layout());
257
mainLayout->addItem (shiftSpacer, 1, 4, 2);
258
static_cast <QHBoxLayout*> (mWtActions->layout())->addStretch();
261
/* Setup tree-widget */
262
mTwInterfaces->header()->hide();
263
mTwInterfaces->setContextMenuPolicy (Qt::CustomContextMenu);
265
/* Prepare toolbar */
266
mAddInterface = new QAction (mTwInterfaces);
267
mRemInterface = new QAction (mTwInterfaces);
268
mEditInterface = new QAction (mTwInterfaces);
270
mAddInterface->setShortcuts (QList <QKeySequence> ()
271
<< QKeySequence ("Ins")
272
<< QKeySequence ("Ctrl+N"));
273
mRemInterface->setShortcuts (QList <QKeySequence> ()
274
<< QKeySequence ("Del")
275
<< QKeySequence ("Ctrl+R"));
276
mEditInterface->setShortcuts (QList <QKeySequence> ()
277
<< QKeySequence ("Space")
278
<< QKeySequence ("F2"));
280
mAddInterface->setIcon (VBoxGlobal::iconSet (":/add_host_iface_16px.png",
281
":/add_host_iface_disabled_16px.png"));
282
mRemInterface->setIcon (VBoxGlobal::iconSet (":/remove_host_iface_16px.png",
283
":/remove_host_iface_disabled_16px.png"));
284
mEditInterface->setIcon (VBoxGlobal::iconSet (":/guesttools_16px.png",
285
":/guesttools_disabled_16px.png"));
287
mTbActions->setUsesTextLabel (false);
288
mTbActions->setIconSize (QSize (16, 16));
289
mTbActions->setOrientation (Qt::Vertical);
290
mTbActions->addAction (mAddInterface);
291
mTbActions->addAction (mRemInterface);
292
mTbActions->addAction (mEditInterface);
293
mTbActions->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::MinimumExpanding);
294
mTbActions->updateGeometry();
295
mTbActions->setMinimumHeight (mTbActions->sizeHint().height());
297
/* Setup connections */
298
connect (mAddInterface, SIGNAL (triggered (bool)), this, SLOT (addInterface()));
299
connect (mRemInterface, SIGNAL (triggered (bool)), this, SLOT (remInterface()));
300
connect (mEditInterface, SIGNAL (triggered (bool)), this, SLOT (editInterface()));
301
connect (mTwInterfaces, SIGNAL (currentItemChanged (QTreeWidgetItem *, QTreeWidgetItem *)),
302
this, SLOT (updateCurrentItem()));
303
connect (mTwInterfaces, SIGNAL (customContextMenuRequested (const QPoint &)),
304
this, SLOT (showContextMenu (const QPoint &)));
305
connect (mTwInterfaces, SIGNAL (itemDoubleClicked (QTreeWidgetItem*, int)),
306
this, SLOT (editInterface()));
308
/* Applying language settings */
312
void VBoxGLSettingsNetwork::getFrom (const CSystemProperties &, const VBoxGlobalSettings &)
314
NetworkItem *item = 0;
315
CHostNetworkInterfaceVector interfaces =
316
vboxGlobal().virtualBox().GetHost().GetNetworkInterfaces();
317
for (CHostNetworkInterfaceVector::ConstIterator it = interfaces.begin();
318
it != interfaces.end(); ++ it)
320
if (it->GetInterfaceType() == KHostNetworkInterfaceType_HostOnly)
322
item = new NetworkItem();
323
item->getFromInterface (*it);
324
mTwInterfaces->addTopLevelItem (item);
325
mTwInterfaces->sortItems (0, Qt::AscendingOrder);
329
mTwInterfaces->setCurrentItem (item);
333
int width = qMax (static_cast<QAbstractItemView*> (mTwInterfaces)
334
->sizeHintForColumn (0) + 2 * mTwInterfaces->frameWidth() +
335
QApplication::style()->pixelMetric (QStyle::PM_ScrollBarExtent),
337
mTwInterfaces->setFixedWidth (width);
338
mTwInterfaces->resizeColumnToContents (0);
339
#endif /* Q_WS_MAC */
342
void VBoxGLSettingsNetwork::putBackTo (CSystemProperties &, VBoxGlobalSettings &)
344
for (int i = 0; i < mTwInterfaces->topLevelItemCount(); ++ i)
347
static_cast <NetworkItem*> (mTwInterfaces->topLevelItem (i));
348
if (item->isChanged())
349
item->putBackToInterface();
353
void VBoxGLSettingsNetwork::setValidator (QIWidgetValidator *aValidator)
355
mValidator = aValidator;
358
bool VBoxGLSettingsNetwork::revalidate (QString &aWarning, QString &aTitle)
360
NetworkItem *item = static_cast <NetworkItem*> (mTwInterfaces->currentItem());
361
return item ? item->revalidate (aWarning, aTitle) : true;
364
void VBoxGLSettingsNetwork::setOrderAfter (QWidget *aWidget)
366
setTabOrder (aWidget, mTwInterfaces);
369
void VBoxGLSettingsNetwork::retranslateUi()
371
/* Translate uic generated strings */
372
Ui::VBoxGLSettingsNetwork::retranslateUi (this);
374
/* Translate action tool-tips */
375
mAddInterface->setText (tr ("&Add host-only network"));
376
mRemInterface->setText (tr ("&Remove host-only network"));
377
mEditInterface->setText (tr ("&Edit host-only network"));
379
mAddInterface->setToolTip (mAddInterface->text().remove ('&') +
380
QString (" (%1)").arg (mAddInterface->shortcut().toString()));
381
mRemInterface->setToolTip (mRemInterface->text().remove ('&') +
382
QString (" (%1)").arg (mRemInterface->shortcut().toString()));
383
mEditInterface->setToolTip (mEditInterface->text().remove ('&') +
384
QString (" (%1)").arg (mEditInterface->shortcut().toString()));
387
void VBoxGLSettingsNetwork::addInterface()
389
#if defined (Q_WS_WIN32)
390
/* Allow the started helper process to make itself the foreground window */
391
AllowSetForegroundWindow (ASFW_ANY);
393
/* Creating interface */
394
CHostNetworkInterface iface;
395
CHost host = vboxGlobal().virtualBox().GetHost();
396
CProgress progress = host.CreateHostOnlyNetworkInterface (iface);
399
vboxProblem().showModalProgressDialog (progress,
400
tr ("Performing", "creating/removing host-only network"), this);
401
if (progress.GetResultCode() == 0)
403
NetworkItem *item = new NetworkItem();
404
item->getFromInterface (iface);
405
mTwInterfaces->addTopLevelItem (item);
406
mTwInterfaces->sortItems (0, Qt::AscendingOrder);
407
mTwInterfaces->setCurrentItem (item);
410
vboxProblem().cannotCreateHostInterface (progress, this);
413
vboxProblem().cannotCreateHostInterface (host, this);
414
#if defined (Q_WS_WIN32)
415
/* Allow the started helper process to make itself the foreground window */
416
AllowSetForegroundWindow (ASFW_ANY);
420
void VBoxGLSettingsNetwork::remInterface()
422
#if defined (Q_WS_WIN32)
423
/* Allow the started helper process to make itself the foreground window */
424
AllowSetForegroundWindow (ASFW_ANY);
426
/* Check interface presence & name */
427
NetworkItem *item = static_cast <NetworkItem*> (mTwInterfaces->currentItem());
428
AssertMsg (item, ("Current item should be selected!\n"));
429
QString name (item->name());
431
/* Asking user about deleting selected network interface */
432
if (vboxProblem().confirmDeletingHostInterface (name, this) ==
433
QIMessageBox::Cancel) return;
435
/* Removing interface */
436
CHost host = vboxGlobal().virtualBox().GetHost();
437
CHostNetworkInterface iface = host.FindHostNetworkInterfaceByName (name);
440
/* Delete interface */
441
CProgress progress = host.RemoveHostOnlyNetworkInterface (iface.GetId());
444
vboxProblem().showModalProgressDialog (progress,
445
tr ("Performing", "creating/removing host-only network"), this);
446
if (progress.GetResultCode() == 0)
449
vboxProblem().cannotRemoveHostInterface (progress, iface, this);
453
vboxProblem().cannotRemoveHostInterface (host, iface, this);
454
#if defined (Q_WS_WIN32)
455
/* Allow the started helper process to make itself the foreground window */
456
AllowSetForegroundWindow (ASFW_ANY);
460
void VBoxGLSettingsNetwork::editInterface()
462
/* Check interface presence */
463
NetworkItem *item = static_cast <NetworkItem*> (mTwInterfaces->currentItem());
464
AssertMsg (item, ("Current item should be selected!\n"));
466
/* Edit current item data */
467
VBoxGLSettingsNetworkDetails details (this);
468
details.getFromItem (item);
469
if (details.exec() == QDialog::Accepted)
471
details.putBackToItem();
472
item->setChanged (true);
477
mValidator->revalidate();
480
void VBoxGLSettingsNetwork::updateCurrentItem()
482
/* Get current item */
483
NetworkItem *item = static_cast <NetworkItem*> (mTwInterfaces->currentItem());
484
/* Set the final label text */
485
mLbInfo->setText (item ? item->updateInfo() : QString());
486
/* Update availability */
487
mRemInterface->setEnabled (item);
488
mEditInterface->setEnabled (item);
491
void VBoxGLSettingsNetwork::showContextMenu (const QPoint &aPos)
495
if (mTwInterfaces->itemAt (aPos))
497
menu.addAction (mEditInterface);
498
menu.addAction (mRemInterface);
502
menu.addAction (mAddInterface);
505
menu.exec (mTwInterfaces->mapToGlobal (aPos));