VirtualBox

Changeset 87276 in vbox


Ignore:
Timestamp:
Jan 15, 2021 1:57:42 PM (4 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9871: Network Manager: Implementing NAT Network configuration support (initial version, no validation for now).

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r87251 r87276  
    620620        src/monitor/resource/UIResourceMonitor.h \
    621621        src/networkmanager/UIDetailsWidgetHostNetwork.h \
     622        src/networkmanager/UIDetailsWidgetNATNetwork.h \
    622623        src/networkmanager/UINetworkManager.h \
    623624        src/snapshots/UISnapshotDetailsWidget.h \
     
    11011102        src/monitor/resource/UIResourceMonitor.cpp \
    11021103        src/networkmanager/UIDetailsWidgetHostNetwork.cpp \
     1104        src/networkmanager/UIDetailsWidgetNATNetwork.cpp \
    11031105        src/networkmanager/UINetworkManager.cpp \
    11041106        src/networkmanager/UINetworkManagerUtils.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp

    r87104 r87276  
    18661866}
    18671867
     1868void UIMessageCenter::cannotAcquireNATNetworks(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */) const
     1869{
     1870    error(pParent, MessageType_Error,
     1871          tr("Failed to acquire NAT networks."),
     1872          UIErrorString::formatErrorInfo(comVBox));
     1873}
     1874
     1875void UIMessageCenter::cannotAcquireNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent /* = 0 */) const
     1876{
     1877    error(pParent, MessageType_Error,
     1878          tr("Failed to acquire NAT network parameter."),
     1879          UIErrorString::formatErrorInfo(comNetwork));
     1880}
     1881
     1882void UIMessageCenter::cannotCreateNATNetwork(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */)
     1883{
     1884    error(pParent, MessageType_Error,
     1885          tr("Failed to create a NAT network."),
     1886          UIErrorString::formatErrorInfo(comVBox));
     1887}
     1888
     1889void UIMessageCenter::cannotSaveNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent /* = 0 */) const
     1890{
     1891    error(pParent, MessageType_Error,
     1892          tr("Failed to save NAT network parameter."),
     1893          UIErrorString::formatErrorInfo(comNetwork));
     1894}
     1895
     1896void UIMessageCenter::cannotFindNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent /* = 0 */) const
     1897{
     1898    error(pParent, MessageType_Error,
     1899          tr("Unable to find the NAT network <b>%1</b>.")
     1900             .arg(strNetworkName),
     1901          UIErrorString::formatErrorInfo(comVBox));
     1902}
     1903
     1904void UIMessageCenter::cannotRemoveNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent /* = 0 */) const
     1905{
     1906    error(pParent, MessageType_Error,
     1907          tr("Failed to remove the NAT network <b>%1</b>.")
     1908             .arg(strNetworkName),
     1909          UIErrorString::formatErrorInfo(comVBox));
     1910}
     1911
    18681912void UIMessageCenter::cannotAcquireCloudProviderManager(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */) const
    18691913{
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h

    r87024 r87276  
    380380    void cannotCloseMedium(const UIMedium &medium, const COMResult &rc, QWidget *pParent = 0) const;
    381381
    382     /* API: Host Network Manager warnings: */
     382    /* API: Network Manager warnings: */
    383383    bool confirmHostOnlyInterfaceRemoval(const QString &strName, QWidget *pParent = 0) const;
    384384    void cannotAcquireHostNetworkInterfaces(const CHost &comHost, QWidget *pParent = 0) const;
     
    394394    void cannotAcquireDHCPServerParameter(const CDHCPServer &comServer, QWidget *pParent = 0) const;
    395395    void cannotSaveDHCPServerParameter(const CDHCPServer &comServer, QWidget *pParent = 0) const;
     396    void cannotAcquireNATNetworks(const CVirtualBox &comVBox, QWidget *pParent = 0) const;
     397    void cannotAcquireNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent = 0) const;
     398    void cannotCreateNATNetwork(const CVirtualBox &comVBox, QWidget *pParent = 0);
     399    void cannotSaveNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent = 0) const;
     400    void cannotFindNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent = 0) const;
     401    void cannotRemoveNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent = 0) const;
    396402
    397403    /* API: Cloud Profile Manager warnings: */
  • trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.cpp

    r87207 r87276  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UINetworkDetailsWidget class implementation.
     3 * VBox Qt GUI - UIDetailsWidgetNATNetwork class implementation.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2020 Oracle Corporation
     7 * Copyright (C) 2009-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3030#include "QITabWidget.h"
    3131#include "UIIconPool.h"
    32 #include "UINetworkDetailsWidget.h"
     32#include "UIDetailsWidgetNATNetwork.h"
    3333#include "UINetworkManagerUtils.h"
    3434
     
    3838
    3939
    40 UINetworkDetailsWidget::UINetworkDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */)
     40UIDetailsWidgetNATNetwork::UIDetailsWidgetNATNetwork(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */)
    4141    : QIWithRetranslateUI<QWidget>(pParent)
    4242    , m_enmEmbedding(enmEmbedding)
    4343    , m_pTabWidget(0)
    44     , m_pButtonAutomatic(0), m_pErrorPaneAutomatic(0)
    45     , m_pButtonManual(0), m_pErrorPaneManual(0)
    46     , m_pLabelIPv4(0), m_pEditorIPv4(0), m_pErrorPaneIPv4(0)
    47     , m_pLabelNMv4(0), m_pEditorNMv4(0), m_pErrorPaneNMv4(0)
    48     , m_pLabelIPv6(0), m_pEditorIPv6(0), m_pErrorPaneIPv6(0)
    49     , m_pLabelNMv6(0), m_pEditorNMv6(0), m_pErrorPaneNMv6(0)
    50     , m_pButtonBoxInterface(0)
    51     , m_pCheckBoxDHCP(0)
    52     , m_pLabelDHCPAddress(0), m_pEditorDHCPAddress(0), m_pErrorPaneDHCPAddress(0)
    53     , m_pLabelDHCPMask(0), m_pEditorDHCPMask(0), m_pErrorPaneDHCPMask(0)
    54     , m_pLabelDHCPLowerAddress(0), m_pEditorDHCPLowerAddress(0), m_pErrorPaneDHCPLowerAddress(0)
    55     , m_pLabelDHCPUpperAddress(0), m_pEditorDHCPUpperAddress(0), m_pErrorPaneDHCPUpperAddress(0)
    56     , m_pButtonBoxServer(0)
    57 {
    58     /* Prepare: */
     44    , m_pCheckboxNetworkAvailable(0)
     45    , m_pLabelNetworkName(0)
     46    , m_pEditorNetworkName(0)
     47    , m_pLabelNetworkCIDR(0)
     48    , m_pEditorNetworkCIDR(0)
     49    , m_pLabelExtended(0)
     50    , m_pCheckboxSupportsDHCP(0)
     51    , m_pCheckboxSupportsIPv6(0)
     52    , m_pCheckboxAdvertiseDefaultIPv6Route(0)
     53    , m_pButtonBoxOptions(0)
     54    , m_pTabWidgetForwarding(0)
     55    , m_pForwardingTableIPv4(0)
     56    , m_pForwardingTableIPv6(0)
     57    , m_pButtonBoxForwarding(0)
     58{
    5959    prepare();
    6060}
    6161
    62 void UINetworkDetailsWidget::setData(const UIDataHostNetwork &data)
     62void UIDetailsWidgetNATNetwork::setData(const UIDataNATNetwork &data)
    6363{
    6464    /* Cache old/new data: */
     
    6666    m_newData = m_oldData;
    6767
    68     /* Load 'Interface' data: */
    69     loadDataForInterface();
    70     /* Load 'DHCP server' data: */
    71     loadDataForDHCPServer();
    72 }
    73 
    74 void UINetworkDetailsWidget::retranslateUi()
     68    /* Load 'Options' data: */
     69    loadDataForOptions();
     70    /* Load 'Forwarding' data: */
     71    loadDataForForwarding();
     72}
     73
     74void UIDetailsWidgetNATNetwork::retranslateUi()
    7575{
    7676    /* Translate tab-widget: */
    77     m_pTabWidget->setTabText(0, tr("&Adapter"));
    78     m_pTabWidget->setTabText(1, tr("&DHCP Server"));
    79 
    80     /* Translate 'Interface' tab content: */
    81     m_pButtonAutomatic->setText(tr("Configure Adapter &Automatically"));
    82     m_pButtonManual->setText(tr("Configure Adapter &Manually"));
    83     m_pLabelIPv4->setText(tr("&IPv4 Address:"));
    84     m_pEditorIPv4->setToolTip(tr("Holds the host IPv4 address for this adapter."));
    85     m_pLabelNMv4->setText(tr("IPv4 Network &Mask:"));
    86     m_pEditorNMv4->setToolTip(tr("Holds the host IPv4 network mask for this adapter."));
    87     m_pLabelIPv6->setText(tr("I&Pv6 Address:"));
    88     m_pEditorIPv6->setToolTip(tr("Holds the host IPv6 address for this adapter if IPv6 is supported."));
    89     m_pLabelNMv6->setText(tr("IPv6 Prefix &Length:"));
    90     m_pEditorNMv6->setToolTip(tr("Holds the host IPv6 prefix length for this adapter if IPv6 is supported."));
    91     if (m_pButtonBoxInterface)
    92     {
    93         m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
    94         m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
    95         m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
    96         m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
    97         m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current interface details"));
    98         m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current interface details"));
    99         m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->
    100             setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->shortcut().toString()));
    101         m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->
    102             setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->shortcut().toString()));
    103     }
    104 
    105     /* Translate 'DHCP server' tab content: */
    106     m_pCheckBoxDHCP->setText(tr("&Enable Server"));
    107     m_pCheckBoxDHCP->setToolTip(tr("When checked, the DHCP Server will be enabled for this network on machine start-up."));
    108     m_pLabelDHCPAddress->setText(tr("Server Add&ress:"));
    109     m_pEditorDHCPAddress->setToolTip(tr("Holds the address of the DHCP server servicing the network associated with this host-only adapter."));
    110     m_pLabelDHCPMask->setText(tr("Server &Mask:"));
    111     m_pEditorDHCPMask->setToolTip(tr("Holds the network mask of the DHCP server servicing the network associated with this host-only adapter."));
    112     m_pLabelDHCPLowerAddress->setText(tr("&Lower Address Bound:"));
    113     m_pEditorDHCPLowerAddress->setToolTip(tr("Holds the lower address bound offered by the DHCP server servicing the network associated with this host-only adapter."));
    114     m_pLabelDHCPUpperAddress->setText(tr("&Upper Address Bound:"));
    115     m_pEditorDHCPUpperAddress->setToolTip(tr("Holds the upper address bound offered by the DHCP server servicing the network associated with this host-only adapter."));
    116     if (m_pButtonBoxServer)
    117     {
    118         m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
    119         m_pButtonBoxServer->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
    120         m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
    121         m_pButtonBoxServer->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
    122         m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current DHCP server details"));
    123         m_pButtonBoxServer->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current DHCP server details"));
    124         m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->
    125             setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->shortcut().toString()));
    126         m_pButtonBoxServer->button(QDialogButtonBox::Ok)->
    127             setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxServer->button(QDialogButtonBox::Ok)->shortcut().toString()));
     77    if (m_pTabWidget)
     78    {
     79        m_pTabWidget->setTabText(0, tr("&General Options"));
     80        m_pTabWidget->setTabText(1, tr("&Port Forwarding"));
     81    }
     82
     83    /* Translate 'Options' tab content: */
     84    if (m_pCheckboxNetworkAvailable)
     85    {
     86        m_pCheckboxNetworkAvailable->setText(tr("&Enable Network"));
     87        m_pCheckboxNetworkAvailable->setToolTip(tr("When checked, this network will be enabled."));
     88    }
     89    if (m_pLabelNetworkName)
     90        m_pLabelNetworkName->setText(tr("Network &Name:"));
     91    if (m_pEditorNetworkName)
     92        m_pEditorNetworkName->setToolTip(tr("Holds the name for this network."));
     93    if (m_pLabelNetworkCIDR)
     94        m_pLabelNetworkCIDR->setText(tr("Network &CIDR:"));
     95    if (m_pEditorNetworkCIDR)
     96        m_pEditorNetworkCIDR->setToolTip(tr("Holds the CIDR for this network."));
     97    if (m_pLabelExtended)
     98        m_pLabelExtended->setText(tr("Extended Features:"));
     99    if (m_pCheckboxSupportsDHCP)
     100    {
     101        m_pCheckboxSupportsDHCP->setText(tr("Supports &DHCP"));
     102        m_pCheckboxSupportsDHCP->setToolTip(tr("When checked, this network will support DHCP."));
     103    }
     104    if (m_pCheckboxSupportsIPv6)
     105    {
     106        m_pCheckboxSupportsIPv6->setText(tr("Supports &IPv6"));
     107        m_pCheckboxSupportsIPv6->setToolTip(tr("When checked, this network will support IPv6."));
     108    }
     109    if (m_pCheckboxAdvertiseDefaultIPv6Route)
     110    {
     111        m_pCheckboxAdvertiseDefaultIPv6Route->setText(tr("Advertise Default IPv6 &Route"));
     112        m_pCheckboxAdvertiseDefaultIPv6Route->setToolTip(tr("When checked, this network will be advertised as the default IPv6 route."));
     113    }
     114    if (m_pButtonBoxOptions)
     115    {
     116        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
     117        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
     118        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
     119        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
     120        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current interface details"));
     121        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current interface details"));
     122        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->
     123            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->shortcut().toString()));
     124        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->
     125            setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->shortcut().toString()));
     126    }
     127
     128    /* Translate 'Forwarding' tab content: */
     129    if (m_pTabWidgetForwarding)
     130    {
     131        m_pTabWidgetForwarding->setTabText(0, tr("&IPv4"));
     132        m_pTabWidgetForwarding->setTabText(1, tr("&IPv6"));
     133    }
     134    if (m_pButtonBoxForwarding)
     135    {
     136        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
     137        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
     138        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
     139        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
     140        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current interface details"));
     141        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current interface details"));
     142        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->
     143            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->shortcut().toString()));
     144        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->
     145            setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->shortcut().toString()));
    128146    }
    129147
     
    132150}
    133151
    134 void UINetworkDetailsWidget::sltToggledButtonAutomatic(bool fChecked)
    135 {
    136     m_newData.m_interface.m_fDHCPEnabled = fChecked;
    137     loadDataForInterface();
    138     revalidate();
    139     updateButtonStates();
    140 }
    141 
    142 void UINetworkDetailsWidget::sltToggledButtonManual(bool fChecked)
    143 {
    144     m_newData.m_interface.m_fDHCPEnabled = !fChecked;
    145     loadDataForInterface();
    146     revalidate();
    147     updateButtonStates();
    148 }
    149 
    150 void UINetworkDetailsWidget::sltTextChangedIPv4(const QString &strText)
    151 {
    152     m_newData.m_interface.m_strAddress = strText;
    153     revalidate(m_pErrorPaneIPv4);
    154     updateButtonStates();
    155 }
    156 
    157 void UINetworkDetailsWidget::sltTextChangedNMv4(const QString &strText)
    158 {
    159     m_newData.m_interface.m_strMask = strText;
    160     revalidate(m_pErrorPaneNMv4);
    161     updateButtonStates();
    162 }
    163 
    164 void UINetworkDetailsWidget::sltTextChangedIPv6(const QString &strText)
    165 {
    166     m_newData.m_interface.m_strAddress6 = strText;
    167     revalidate(m_pErrorPaneIPv6);
    168     updateButtonStates();
    169 }
    170 
    171 void UINetworkDetailsWidget::sltTextChangedNMv6(const QString &strText)
    172 {
    173     m_newData.m_interface.m_strPrefixLength6 = strText;
    174     revalidate(m_pErrorPaneNMv6);
    175     updateButtonStates();
    176 }
    177 
    178 void UINetworkDetailsWidget::sltStatusChangedServer(int iChecked)
    179 {
    180     m_newData.m_dhcpserver.m_fEnabled = (bool)iChecked;
    181     loadDataForDHCPServer();
    182     revalidate();
    183     updateButtonStates();
    184 }
    185 
    186 void UINetworkDetailsWidget::sltTextChangedAddress(const QString &strText)
    187 {
    188     m_newData.m_dhcpserver.m_strAddress = strText;
    189     revalidate(m_pErrorPaneDHCPAddress);
    190     updateButtonStates();
    191 }
    192 
    193 void UINetworkDetailsWidget::sltTextChangedMask(const QString &strText)
    194 {
    195     m_newData.m_dhcpserver.m_strMask = strText;
    196     revalidate(m_pErrorPaneDHCPMask);
    197     updateButtonStates();
    198 }
    199 
    200 void UINetworkDetailsWidget::sltTextChangedLowerAddress(const QString &strText)
    201 {
    202     m_newData.m_dhcpserver.m_strLowerAddress = strText;
    203     revalidate(m_pErrorPaneDHCPLowerAddress);
    204     updateButtonStates();
    205 }
    206 
    207 void UINetworkDetailsWidget::sltTextChangedUpperAddress(const QString &strText)
    208 {
    209     m_newData.m_dhcpserver.m_strUpperAddress = strText;
    210     revalidate(m_pErrorPaneDHCPUpperAddress);
    211     updateButtonStates();
    212 }
    213 
    214 void UINetworkDetailsWidget::sltHandleButtonBoxClick(QAbstractButton *pButton)
    215 {
    216     /* Make sure button-box exists: */
    217     AssertPtrReturnVoid(m_pButtonBoxInterface);
    218     AssertPtrReturnVoid(m_pButtonBoxServer);
     152void UIDetailsWidgetNATNetwork::sltNetworkAvailabilityChanged(bool fChecked)
     153{
     154    m_newData.m_fEnabled = fChecked;
     155    loadDataForOptions();
     156    revalidate();
     157    updateButtonStates();
     158}
     159
     160void UIDetailsWidgetNATNetwork::sltNetworkNameChanged(const QString &strText)
     161{
     162    m_newData.m_strName = strText;
     163    revalidate();
     164    updateButtonStates();
     165}
     166
     167void UIDetailsWidgetNATNetwork::sltNetworkCIDRChanged(const QString &strText)
     168{
     169    m_newData.m_strCIDR = strText;
     170    revalidate();
     171    updateButtonStates();
     172}
     173
     174void UIDetailsWidgetNATNetwork::sltSupportsDHCPChanged(bool fChecked)
     175{
     176    m_newData.m_fSupportsDHCP = fChecked;
     177    revalidate();
     178    updateButtonStates();
     179}
     180
     181void UIDetailsWidgetNATNetwork::sltSupportsIPv6Changed(bool fChecked)
     182{
     183    m_newData.m_fSupportsIPv6 = fChecked;
     184    revalidate();
     185    updateButtonStates();
     186}
     187
     188void UIDetailsWidgetNATNetwork::sltAdvertiseDefaultIPv6RouteChanged(bool fChecked)
     189{
     190    m_newData.m_fAdvertiseDefaultIPv6Route = fChecked;
     191    revalidate();
     192    updateButtonStates();
     193}
     194
     195void UIDetailsWidgetNATNetwork::sltForwardingRulesIPv4Changed()
     196{
     197    m_newData.m_rules4 = m_pForwardingTableIPv4->rules();
     198    revalidate();
     199    updateButtonStates();
     200}
     201
     202void UIDetailsWidgetNATNetwork::sltForwardingRulesIPv6Changed()
     203{
     204    m_newData.m_rules6 = m_pForwardingTableIPv6->rules();
     205    revalidate();
     206    updateButtonStates();
     207}
     208
     209void UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick(QAbstractButton *pButton)
     210{
     211    /* Make sure button-boxes exist: */
     212    if (!m_pButtonBoxOptions || !m_pButtonBoxForwarding)
     213        return;
    219214
    220215    /* Disable buttons first of all: */
    221     m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->setEnabled(false);
    222     m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->setEnabled(false);
    223     m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->setEnabled(false);
    224     m_pButtonBoxServer->button(QDialogButtonBox::Ok)->setEnabled(false);
     216    m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setEnabled(false);
     217    m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setEnabled(false);
     218    m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setEnabled(false);
     219    m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setEnabled(false);
    225220
    226221    /* Compare with known buttons: */
    227     if (   pButton == m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)
    228         || pButton == m_pButtonBoxServer->button(QDialogButtonBox::Cancel))
     222    if (   pButton == m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)
     223        || pButton == m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel))
    229224        emit sigDataChangeRejected();
    230225    else
    231     if (   pButton == m_pButtonBoxInterface->button(QDialogButtonBox::Ok)
    232         || pButton == m_pButtonBoxServer->button(QDialogButtonBox::Ok))
     226    if (   pButton == m_pButtonBoxOptions->button(QDialogButtonBox::Ok)
     227        || pButton == m_pButtonBoxForwarding->button(QDialogButtonBox::Ok))
    233228        emit sigDataChangeAccepted();
    234229}
    235230
    236 void UINetworkDetailsWidget::prepare()
     231void UIDetailsWidgetNATNetwork::prepare()
    237232{
    238233    /* Prepare this: */
     
    246241}
    247242
    248 void UINetworkDetailsWidget::prepareThis()
     243void UIDetailsWidgetNATNetwork::prepareThis()
    249244{
    250245    /* Create layout: */
    251     QVBoxLayout *pLayout = new QVBoxLayout(this);
    252     AssertPtrReturnVoid(pLayout);
     246    new QVBoxLayout(this);
     247    if (layout())
    253248    {
    254249        /* Configure layout: */
    255         pLayout->setContentsMargins(0, 0, 0, 0);
     250        layout()->setContentsMargins(0, 0, 0, 0);
    256251
    257252        /* Prepare tab-widget: */
     
    260255}
    261256
    262 void UINetworkDetailsWidget::prepareTabWidget()
     257void UIDetailsWidgetNATNetwork::prepareTabWidget()
    263258{
    264259    /* Create tab-widget: */
    265     m_pTabWidget = new QITabWidget;
    266     AssertPtrReturnVoid(m_pTabWidget);
    267     {
    268         /* Prepare 'Interface' tab: */
    269         prepareTabInterface();
    270         /* Prepare 'DHCP server' tab: */
    271         prepareTabDHCPServer();
     260    m_pTabWidget = new QITabWidget(this);
     261    if (m_pTabWidget)
     262    {
     263        /* Prepare 'Options' tab: */
     264        prepareTabOptions();
     265        /* Prepare 'Forwarding' tab: */
     266        prepareTabForwarding();
    272267
    273268        /* Add into layout: */
     
    276271}
    277272
    278 void UINetworkDetailsWidget::prepareTabInterface()
    279 {
    280     /* Create 'Interface' tab: */
    281     QWidget *pTabInterface = new QWidget;
    282     AssertPtrReturnVoid(pTabInterface);
    283     {
    284         /* Create 'Interface' layout: */
    285         QGridLayout *pLayoutInterface = new QGridLayout(pTabInterface);
    286         AssertPtrReturnVoid(pLayoutInterface);
     273void UIDetailsWidgetNATNetwork::prepareTabOptions()
     274{
     275    /* Prepare 'Options' tab: */
     276    QWidget *pTabOptions = new QWidget(m_pTabWidget);
     277    if (pTabOptions)
     278    {
     279        /* Prepare 'Options' layout: */
     280        QGridLayout *pLayoutOptions = new QGridLayout(pTabOptions);
     281        if (pLayoutOptions)
     282        {
     283#ifdef VBOX_WS_MAC
     284            pLayoutOptions->setSpacing(10);
     285            pLayoutOptions->setContentsMargins(10, 10, 10, 10);
     286#endif
     287
     288            /* Prepare network availability check-box: */
     289            m_pCheckboxNetworkAvailable = new QCheckBox(pTabOptions);
     290            if (m_pCheckboxNetworkAvailable)
     291            {
     292                connect(m_pCheckboxNetworkAvailable, &QCheckBox::toggled,
     293                        this, &UIDetailsWidgetNATNetwork::sltNetworkAvailabilityChanged);
     294                pLayoutOptions->addWidget(m_pCheckboxNetworkAvailable, 0, 0, 1, 2);
     295            }
     296
     297            /* Prepare 20-px shifting spacer: */
     298            QSpacerItem *pSpacerItem = new QSpacerItem(20, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
     299            if (pSpacerItem)
     300                pLayoutOptions->addItem(pSpacerItem, 1, 0);
     301
     302            /* Prepare settings widget layout: */
     303            QGridLayout *pLayoutSettings = new QGridLayout;
     304            if (pLayoutSettings)
     305            {
     306                pLayoutSettings->setContentsMargins(0, 0, 0, 0);
     307                pLayoutSettings->setColumnStretch(3, 1);
     308
     309                /* Prepare network name label: */
     310                m_pLabelNetworkName = new QLabel(pTabOptions);
     311                if (m_pLabelNetworkName)
     312                {
     313                    m_pLabelNetworkName->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
     314                    pLayoutSettings->addWidget(m_pLabelNetworkName, 0, 0);
     315                }
     316                /* Prepare network name editor: */
     317                m_pEditorNetworkName = new QLineEdit(pTabOptions);
     318                if (m_pEditorNetworkName)
     319                {
     320                    if (m_pLabelNetworkName)
     321                        m_pLabelNetworkName->setBuddy(m_pEditorNetworkName);
     322                    connect(m_pEditorNetworkName, &QLineEdit::textEdited,
     323                            this, &UIDetailsWidgetNATNetwork::sltNetworkNameChanged);
     324
     325                    pLayoutSettings->addWidget(m_pEditorNetworkName, 0, 1, 1, 3);
     326                }
     327
     328                /* Prepare network CIDR label: */
     329                m_pLabelNetworkCIDR = new QLabel(pTabOptions);
     330                if (m_pLabelNetworkCIDR)
     331                {
     332                    m_pLabelNetworkCIDR->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
     333                    pLayoutSettings->addWidget(m_pLabelNetworkCIDR, 1, 0);
     334                }
     335                /* Prepare network CIDR editor: */
     336                m_pEditorNetworkCIDR = new QLineEdit(pTabOptions);
     337                if (m_pEditorNetworkCIDR)
     338                {
     339                    if (m_pLabelNetworkCIDR)
     340                        m_pLabelNetworkCIDR->setBuddy(m_pEditorNetworkCIDR);
     341                    connect(m_pEditorNetworkCIDR, &QLineEdit::textEdited,
     342                            this, &UIDetailsWidgetNATNetwork::sltNetworkCIDRChanged);
     343
     344                    pLayoutSettings->addWidget(m_pEditorNetworkCIDR, 1, 1, 1, 3);
     345                }
     346
     347                /* Prepare extended label: */
     348                m_pLabelExtended = new QLabel(pTabOptions);
     349                if (m_pLabelExtended)
     350                {
     351                    m_pLabelExtended->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
     352                    pLayoutSettings->addWidget(m_pLabelExtended, 2, 0);
     353                }
     354                /* Prepare 'supports DHCP' check-box: */
     355                m_pCheckboxSupportsDHCP = new QCheckBox(pTabOptions);
     356                if (m_pCheckboxSupportsDHCP)
     357                {
     358                    connect(m_pCheckboxSupportsDHCP, &QCheckBox::toggled,
     359                            this, &UIDetailsWidgetNATNetwork::sltSupportsDHCPChanged);
     360                    pLayoutSettings->addWidget(m_pCheckboxSupportsDHCP, 2, 1, 1, 2);
     361                }
     362                /* Prepare 'supports IPv6' check-box: */
     363                m_pCheckboxSupportsIPv6 = new QCheckBox(pTabOptions);
     364                if (m_pCheckboxSupportsIPv6)
     365                {
     366                    connect(m_pCheckboxSupportsIPv6, &QCheckBox::toggled,
     367                            this, &UIDetailsWidgetNATNetwork::sltSupportsIPv6Changed);
     368                    pLayoutSettings->addWidget(m_pCheckboxSupportsIPv6, 3, 1, 1, 2);
     369                }
     370                /* Prepare 'advertise default IPv6 route' check-box: */
     371                m_pCheckboxAdvertiseDefaultIPv6Route = new QCheckBox(pTabOptions);
     372                if (m_pCheckboxAdvertiseDefaultIPv6Route)
     373                {
     374                    connect(m_pCheckboxAdvertiseDefaultIPv6Route, &QCheckBox::toggled,
     375                            this, &UIDetailsWidgetNATNetwork::sltAdvertiseDefaultIPv6RouteChanged);
     376                    pLayoutSettings->addWidget(m_pCheckboxAdvertiseDefaultIPv6Route, 4, 1, 1, 2);
     377                }
     378
     379                pLayoutOptions->addLayout(pLayoutSettings, 1, 1);
     380            }
     381
     382            /* If parent embedded into stack: */
     383            if (m_enmEmbedding == EmbedTo_Stack)
     384            {
     385                /* Prepare button-box: */
     386                m_pButtonBoxOptions = new QIDialogButtonBox(pTabOptions);
     387                if (m_pButtonBoxOptions)
     388                {
     389                    m_pButtonBoxOptions->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
     390                    connect(m_pButtonBoxOptions, &QIDialogButtonBox::clicked, this, &UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick);
     391
     392                    pLayoutOptions->addWidget(m_pButtonBoxOptions, 2, 0, 1, 2);
     393                }
     394            }
     395        }
     396
     397        m_pTabWidget->addTab(pTabOptions, QString());
     398    }
     399}
     400
     401void UIDetailsWidgetNATNetwork::prepareTabForwarding()
     402{
     403    /* Prepare 'Forwarding' tab: */
     404    QWidget *pTabForwarding = new QWidget(m_pTabWidget);
     405    if (pTabForwarding)
     406    {
     407        /* Prepare 'Forwarding' layout: */
     408        QGridLayout *pLayoutForwarding = new QGridLayout(pTabForwarding);
     409        if (pLayoutForwarding)
    287410        {
    288411#ifdef VBOX_WS_MAC
    289412            /* Configure layout: */
    290             pLayoutInterface->setSpacing(10);
    291             pLayoutInterface->setContentsMargins(10, 10, 10, 10);
     413            pLayoutForwarding->setSpacing(10);
     414            pLayoutForwarding->setContentsMargins(10, 10, 10, 10);
    292415#endif
    293416
    294             /* Get the required icon metric: */
    295             const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
    296 
    297             /* Create automatic interface configuration layout: */
    298             QHBoxLayout *pLayoutAutomatic = new QHBoxLayout;
    299             AssertPtrReturnVoid(pLayoutAutomatic);
     417            /* Prepare forwarding tab-widget: */
     418            m_pTabWidgetForwarding = new QITabWidget(pTabForwarding);
     419            if (m_pTabWidgetForwarding)
    300420            {
    301                 /* Configure layout: */
    302                 pLayoutAutomatic->setContentsMargins(0, 0, 0, 0);
    303 
    304                 /* Create automatic interface configuration radio-button: */
    305                 m_pButtonAutomatic = new QRadioButton;
    306                 AssertPtrReturnVoid(m_pButtonAutomatic);
    307                 {
    308                     /* Configure radio-button: */
    309                     connect(m_pButtonAutomatic, &QRadioButton::toggled,
    310                             this, &UINetworkDetailsWidget::sltToggledButtonAutomatic);
    311                     /* Add into layout: */
    312                     pLayoutAutomatic->addWidget(m_pButtonAutomatic);
    313                 }
    314                 /* Create automatic interface configuration error pane: */
    315                 m_pErrorPaneAutomatic = new QLabel;
    316                 AssertPtrReturnVoid(m_pErrorPaneAutomatic);
    317                 {
    318                     /* Configure label: */
    319                     m_pErrorPaneAutomatic->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    320                     m_pErrorPaneAutomatic->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
    321                     m_pErrorPaneAutomatic->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    322                                                      .pixmap(QSize(iIconMetric, iIconMetric)));
    323                     /* Add into layout: */
    324                     pLayoutAutomatic->addWidget(m_pErrorPaneAutomatic);
    325                 }
    326                 /* Add into layout: */
    327                 pLayoutInterface->addLayout(pLayoutAutomatic, 0, 0, 1, 3);
    328 #ifdef VBOX_WS_MAC
    329                 pLayoutInterface->setRowMinimumHeight(0, 22);
    330 #endif
    331             }
    332 
    333             /* Create manual interface configuration layout: */
    334             QHBoxLayout *pLayoutManual = new QHBoxLayout;
    335             AssertPtrReturnVoid(pLayoutManual);
    336             {
    337                 /* Configure layout: */
    338                 pLayoutManual->setContentsMargins(0, 0, 0, 0);
    339                 /* Create manual interface configuration radio-button: */
    340                 m_pButtonManual = new QRadioButton;
    341                 AssertPtrReturnVoid(m_pButtonManual);
    342                 {
    343                     /* Configure radio-button: */
    344                     connect(m_pButtonManual, &QRadioButton::toggled,
    345                             this, &UINetworkDetailsWidget::sltToggledButtonManual);
    346                     /* Add into layout: */
    347                     pLayoutManual->addWidget(m_pButtonManual);
    348                 }
    349                 /* Create manual interface configuration error pane: */
    350                 m_pErrorPaneManual = new QLabel;
    351                 AssertPtrReturnVoid(m_pErrorPaneManual);
    352                 {
    353                     /* Configure label: */
    354                     m_pErrorPaneManual->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    355                     m_pErrorPaneManual->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
    356                     m_pErrorPaneManual->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    357                                                   .pixmap(QSize(iIconMetric, iIconMetric)));
    358                     /* Add into layout: */
    359                     pLayoutManual->addWidget(m_pErrorPaneManual);
    360                 }
    361                 /* Add into layout: */
    362                 pLayoutInterface->addLayout(pLayoutManual, 1, 0, 1, 3);
    363 #ifdef VBOX_WS_MAC
    364                 pLayoutInterface->setRowMinimumHeight(1, 22);
    365 #endif
    366             }
    367 
    368             /* Create IPv4 address label: */
    369             m_pLabelIPv4 = new QLabel;
    370             AssertPtrReturnVoid(m_pLabelIPv4);
    371             {
    372                 /* Configure label: */
    373                 m_pLabelIPv4->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    374                 /* Add into layout: */
    375                 pLayoutInterface->addWidget(m_pLabelIPv4, 2, 1);
    376             }
    377             /* Create IPv4 layout: */
    378             QHBoxLayout *pLayoutIPv4 = new QHBoxLayout;
    379             AssertPtrReturnVoid(pLayoutIPv4);
    380             {
    381                 /* Configure layout: */
    382                 pLayoutIPv4->setContentsMargins(0, 0, 0, 0);
    383                 /* Create IPv4 address editor: */
    384                 m_pEditorIPv4 = new QILineEdit;
    385                 AssertPtrReturnVoid(m_pEditorIPv4);
    386                 {
    387                     /* Configure editor: */
    388                     m_pLabelIPv4->setBuddy(m_pEditorIPv4);
    389                     connect(m_pEditorIPv4, &QLineEdit::textChanged,
    390                             this, &UINetworkDetailsWidget::sltTextChangedIPv4);
    391                     /* Add into layout: */
    392                     pLayoutIPv4->addWidget(m_pEditorIPv4);
    393                 }
    394                 /* Create IPv4 error pane: */
    395                 m_pErrorPaneIPv4 = new QLabel;
    396                 AssertPtrReturnVoid(m_pErrorPaneIPv4);
    397                 {
    398                     /* Configure label: */
    399                     m_pErrorPaneIPv4->setAlignment(Qt::AlignCenter);
    400                     m_pErrorPaneIPv4->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    401                                                 .pixmap(QSize(iIconMetric, iIconMetric)));
    402                     /* Add into layout: */
    403                     pLayoutIPv4->addWidget(m_pErrorPaneIPv4);
    404                 }
    405                 /* Add into layout: */
    406                 pLayoutInterface->addLayout(pLayoutIPv4, 2, 2);
    407             }
    408 
    409             /* Create NMv4 network mask label: */
    410             m_pLabelNMv4 = new QLabel;
    411             AssertPtrReturnVoid(m_pLabelNMv4);
    412             {
    413                 /* Configure label: */
    414                 m_pLabelNMv4->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    415                 /* Add into layout: */
    416                 pLayoutInterface->addWidget(m_pLabelNMv4, 3, 1);
    417             }
    418             /* Create NMv4 layout: */
    419             QHBoxLayout *pLayoutNMv4 = new QHBoxLayout;
    420             AssertPtrReturnVoid(pLayoutNMv4);
    421             {
    422                 /* Configure layout: */
    423                 pLayoutNMv4->setContentsMargins(0, 0, 0, 0);
    424                 /* Create NMv4 network mask editor: */
    425                 m_pEditorNMv4 = new QILineEdit;
    426                 AssertPtrReturnVoid(m_pEditorNMv4);
    427                 {
    428                     /* Configure editor: */
    429                     m_pLabelNMv4->setBuddy(m_pEditorNMv4);
    430                     connect(m_pEditorNMv4, &QLineEdit::textChanged,
    431                             this, &UINetworkDetailsWidget::sltTextChangedNMv4);
    432                     /* Add into layout: */
    433                     pLayoutNMv4->addWidget(m_pEditorNMv4);
    434                 }
    435                 /* Create NMv4 error pane: */
    436                 m_pErrorPaneNMv4 = new QLabel;
    437                 AssertPtrReturnVoid(m_pErrorPaneNMv4);
    438                 {
    439                     /* Configure label: */
    440                     m_pErrorPaneNMv4->setAlignment(Qt::AlignCenter);
    441                     m_pErrorPaneNMv4->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    442                                                 .pixmap(QSize(iIconMetric, iIconMetric)));
    443                     /* Add into layout: */
    444                     pLayoutNMv4->addWidget(m_pErrorPaneNMv4);
    445                 }
    446                 /* Add into layout: */
    447                 pLayoutInterface->addLayout(pLayoutNMv4, 3, 2);
    448             }
    449 
    450             /* Create IPv6 address label: */
    451             m_pLabelIPv6 = new QLabel;
    452             AssertPtrReturnVoid(m_pLabelIPv6);
    453             {
    454                 /* Configure label: */
    455                 m_pLabelIPv6->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    456                 /* Add into layout: */
    457                 pLayoutInterface->addWidget(m_pLabelIPv6, 4, 1);
    458             }
    459             /* Create IPv6 layout: */
    460             QHBoxLayout *pLayoutIPv6 = new QHBoxLayout;
    461             AssertPtrReturnVoid(pLayoutIPv6);
    462             {
    463                 /* Configure layout: */
    464                 pLayoutIPv6->setContentsMargins(0, 0, 0, 0);
    465                 /* Create IPv6 address editor: */
    466                 m_pEditorIPv6 = new QILineEdit;
    467                 AssertPtrReturnVoid(m_pEditorIPv6);
    468                 {
    469                     /* Configure editor: */
    470                     m_pLabelIPv6->setBuddy(m_pEditorIPv6);
    471                     connect(m_pEditorIPv6, &QLineEdit::textChanged,
    472                             this, &UINetworkDetailsWidget::sltTextChangedIPv6);
    473                     /* Add into layout: */
    474                     pLayoutIPv6->addWidget(m_pEditorIPv6);
    475                 }
    476                 /* Create IPv4 error pane: */
    477                 m_pErrorPaneIPv6 = new QLabel;
    478                 AssertPtrReturnVoid(m_pErrorPaneIPv6);
    479                 {
    480                     /* Configure label: */
    481                     m_pErrorPaneIPv6->setAlignment(Qt::AlignCenter);
    482                     m_pErrorPaneIPv6->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    483                                                 .pixmap(QSize(iIconMetric, iIconMetric)));
    484                     /* Add into layout: */
    485                     pLayoutIPv6->addWidget(m_pErrorPaneIPv6);
    486                 }
    487                 /* Add into layout: */
    488                 pLayoutInterface->addLayout(pLayoutIPv6, 4, 2);
    489             }
    490 
    491             /* Create NMv6 network mask label: */
    492             m_pLabelNMv6 = new QLabel;
    493             AssertPtrReturnVoid(m_pLabelNMv6);
    494             {
    495                 /* Configure label: */
    496                 m_pLabelNMv6->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    497                 /* Add into layout: */
    498                 pLayoutInterface->addWidget(m_pLabelNMv6, 5, 1);
    499             }
    500             /* Create NMv6 layout: */
    501             QHBoxLayout *pLayoutNMv6 = new QHBoxLayout;
    502             AssertPtrReturnVoid(pLayoutNMv6);
    503             {
    504                 /* Configure layout: */
    505                 pLayoutNMv6->setContentsMargins(0, 0, 0, 0);
    506                 /* Create NMv6 network mask editor: */
    507                 m_pEditorNMv6 = new QILineEdit;
    508                 AssertPtrReturnVoid(m_pEditorNMv6);
    509                 {
    510                     /* Configure editor: */
    511                     m_pLabelNMv6->setBuddy(m_pEditorNMv6);
    512                     connect(m_pEditorNMv6, &QLineEdit::textChanged,
    513                             this, &UINetworkDetailsWidget::sltTextChangedNMv6);
    514                     /* Add into layout: */
    515                     pLayoutNMv6->addWidget(m_pEditorNMv6);
    516                 }
    517                 /* Create NMv6 error pane: */
    518                 m_pErrorPaneNMv6 = new QLabel;
    519                 AssertPtrReturnVoid(m_pErrorPaneNMv6);
    520                 {
    521                     /* Configure label: */
    522                     m_pErrorPaneNMv6->setAlignment(Qt::AlignCenter);
    523                     m_pErrorPaneNMv6->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    524                                                 .pixmap(QSize(iIconMetric, iIconMetric)));
    525                     /* Add into layout: */
    526                     pLayoutNMv6->addWidget(m_pErrorPaneNMv6);
    527                 }
    528                 /* Add into layout: */
    529                 pLayoutInterface->addLayout(pLayoutNMv6, 5, 2);
    530             }
    531 
    532             /* Create indent: */
    533             QStyleOption options;
    534             options.initFrom(m_pButtonManual);
    535             const int iWidth = m_pButtonManual->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth, &options, m_pButtonManual) +
    536                                m_pButtonManual->style()->pixelMetric(QStyle::PM_RadioButtonLabelSpacing, &options, m_pButtonManual) -
    537                                pLayoutInterface->spacing() - 1;
    538             QSpacerItem *pSpacer1 = new QSpacerItem(iWidth, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
    539             AssertPtrReturnVoid(pSpacer1);
    540             {
    541                 /* Add into layout: */
    542                 pLayoutInterface->addItem(pSpacer1, 2, 0, 4);
    543             }
    544             /* Create stretch: */
    545             QSpacerItem *pSpacer2 = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
    546             AssertPtrReturnVoid(pSpacer2);
    547             {
    548                 /* Add into layout: */
    549                 pLayoutInterface->addItem(pSpacer2, 6, 0, 1, 3);
     421                /* Prepare IPv4 forwarding table: */
     422                m_pForwardingTableIPv4 = new UIPortForwardingTable(UIPortForwardingDataList(), false, true);
     423                if (m_pForwardingTableIPv4)
     424                {
     425                    connect(m_pForwardingTableIPv4, &UIPortForwardingTable::sigDataChanged,
     426                            this, &UIDetailsWidgetNATNetwork::sltForwardingRulesIPv4Changed);
     427                    m_pTabWidgetForwarding->addTab(m_pForwardingTableIPv4, QString());
     428                }
     429                /* Prepare IPv6 forwarding table: */
     430                m_pForwardingTableIPv6 = new UIPortForwardingTable(UIPortForwardingDataList(), true, true);
     431                if (m_pForwardingTableIPv6)
     432                {
     433                    connect(m_pForwardingTableIPv4, &UIPortForwardingTable::sigDataChanged,
     434                            this, &UIDetailsWidgetNATNetwork::sltForwardingRulesIPv6Changed);
     435                    m_pTabWidgetForwarding->addTab(m_pForwardingTableIPv6, QString());
     436                }
     437
     438                pLayoutForwarding->addWidget(m_pTabWidgetForwarding, 0, 0);
    550439            }
    551440
     
    553442            if (m_enmEmbedding == EmbedTo_Stack)
    554443            {
    555                 /* Create button-box: */
    556                 m_pButtonBoxInterface = new QIDialogButtonBox;
    557                 AssertPtrReturnVoid(m_pButtonBoxInterface);
    558                 /* Configure button-box: */
    559                 m_pButtonBoxInterface->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
    560                 connect(m_pButtonBoxInterface, &QIDialogButtonBox::clicked, this, &UINetworkDetailsWidget::sltHandleButtonBoxClick);
    561 
    562                 /* Add into layout: */
    563                 pLayoutInterface->addWidget(m_pButtonBoxInterface, 7, 0, 1, 3);
     444                /* Prepare button-box: */
     445                m_pButtonBoxForwarding = new QIDialogButtonBox(pTabForwarding);
     446                if (m_pButtonBoxForwarding)
     447                {
     448                    m_pButtonBoxForwarding->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
     449                    connect(m_pButtonBoxForwarding, &QIDialogButtonBox::clicked, this, &UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick);
     450
     451                    pLayoutForwarding->addWidget(m_pButtonBoxForwarding, 1, 0);
     452                }
    564453            }
    565454        }
    566         /* Add to tab-widget: */
    567         m_pTabWidget->addTab(pTabInterface, QString());
    568     }
    569 }
    570 
    571 void UINetworkDetailsWidget::prepareTabDHCPServer()
    572 {
    573     /* Create 'DHCP server' tab: */
    574     QWidget *pTabDHCPServer = new QWidget;
    575     AssertPtrReturnVoid(pTabDHCPServer);
    576     {
    577         /* Create 'DHCP server' layout: */
    578         QGridLayout *pLayoutDHCPServer = new QGridLayout(pTabDHCPServer);
    579         AssertPtrReturnVoid(pLayoutDHCPServer);
    580         {
    581 #ifdef VBOX_WS_MAC
    582             /* Configure layout: */
    583             pLayoutDHCPServer->setSpacing(10);
    584             pLayoutDHCPServer->setContentsMargins(10, 10, 10, 10);
    585 #endif
    586 
    587             /* Get the required icon metric: */
    588             const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
    589 
    590             /* Create DHCP server status check-box: */
    591             m_pCheckBoxDHCP = new QCheckBox;
    592             AssertPtrReturnVoid(m_pCheckBoxDHCP);
    593             {
    594                 /* Configure check-box: */
    595                 connect(m_pCheckBoxDHCP, &QCheckBox::stateChanged,
    596                         this, &UINetworkDetailsWidget::sltStatusChangedServer);
    597                 /* Add into layout: */
    598                 pLayoutDHCPServer->addWidget(m_pCheckBoxDHCP, 0, 0, 1, 2);
    599 #ifdef VBOX_WS_MAC
    600                 pLayoutDHCPServer->setRowMinimumHeight(0, 22);
    601 #endif
    602             }
    603 
    604             /* Create DHCP address label: */
    605             m_pLabelDHCPAddress = new QLabel;
    606             AssertPtrReturnVoid(m_pLabelDHCPAddress);
    607             {
    608                 /* Configure label: */
    609                 m_pLabelDHCPAddress->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    610                 /* Add into layout: */
    611                 pLayoutDHCPServer->addWidget(m_pLabelDHCPAddress, 1, 1);
    612             }
    613             /* Create DHCP address layout: */
    614             QHBoxLayout *pLayoutDHCPAddress = new QHBoxLayout;
    615             AssertPtrReturnVoid(pLayoutDHCPAddress);
    616             {
    617                 /* Configure layout: */
    618                 pLayoutDHCPAddress->setContentsMargins(0, 0, 0, 0);
    619                 /* Create DHCP address editor: */
    620                 m_pEditorDHCPAddress = new QILineEdit;
    621                 AssertPtrReturnVoid(m_pEditorDHCPAddress);
    622                 {
    623                     /* Configure editor: */
    624                     m_pLabelDHCPAddress->setBuddy(m_pEditorDHCPAddress);
    625                     connect(m_pEditorDHCPAddress, &QLineEdit::textChanged,
    626                             this, &UINetworkDetailsWidget::sltTextChangedAddress);
    627                     /* Add into layout: */
    628                     pLayoutDHCPAddress->addWidget(m_pEditorDHCPAddress);
    629                 }
    630                 /* Create DHCP address error pane: */
    631                 m_pErrorPaneDHCPAddress = new QLabel;
    632                 AssertPtrReturnVoid(m_pErrorPaneDHCPAddress);
    633                 {
    634                     /* Configure label: */
    635                     m_pErrorPaneDHCPAddress->setAlignment(Qt::AlignCenter);
    636                     m_pErrorPaneDHCPAddress->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    637                                                        .pixmap(QSize(iIconMetric, iIconMetric)));
    638                     /* Add into layout: */
    639                     pLayoutDHCPAddress->addWidget(m_pErrorPaneDHCPAddress);
    640                 }
    641                 /* Add into layout: */
    642                 pLayoutDHCPServer->addLayout(pLayoutDHCPAddress, 1, 2);
    643             }
    644 
    645             /* Create DHCP network mask label: */
    646             m_pLabelDHCPMask = new QLabel;
    647             AssertPtrReturnVoid(m_pLabelDHCPMask);
    648             {
    649                 /* Configure label: */
    650                 m_pLabelDHCPMask->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    651                 /* Add into layout: */
    652                 pLayoutDHCPServer->addWidget(m_pLabelDHCPMask, 2, 1);
    653             }
    654             /* Create DHCP mask layout: */
    655             QHBoxLayout *pLayoutDHCPMask = new QHBoxLayout;
    656             AssertPtrReturnVoid(pLayoutDHCPMask);
    657             {
    658                 /* Configure layout: */
    659                 pLayoutDHCPMask->setContentsMargins(0, 0, 0, 0);
    660                 /* Create DHCP network mask editor: */
    661                 m_pEditorDHCPMask = new QILineEdit;
    662                 AssertPtrReturnVoid(m_pEditorDHCPMask);
    663                 {
    664                     /* Configure editor: */
    665                     m_pLabelDHCPMask->setBuddy(m_pEditorDHCPMask);
    666                     connect(m_pEditorDHCPMask, &QLineEdit::textChanged,
    667                             this, &UINetworkDetailsWidget::sltTextChangedMask);
    668                     /* Add into layout: */
    669                     pLayoutDHCPMask->addWidget(m_pEditorDHCPMask);
    670                 }
    671                 /* Create DHCP mask error pane: */
    672                 m_pErrorPaneDHCPMask = new QLabel;
    673                 AssertPtrReturnVoid(m_pErrorPaneDHCPMask);
    674                 {
    675                     /* Configure label: */
    676                     m_pErrorPaneDHCPMask->setAlignment(Qt::AlignCenter);
    677                     m_pErrorPaneDHCPMask->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    678                                                     .pixmap(QSize(iIconMetric, iIconMetric)));
    679                     /* Add into layout: */
    680                     pLayoutDHCPMask->addWidget(m_pErrorPaneDHCPMask);
    681                 }
    682                 /* Add into layout: */
    683                 pLayoutDHCPServer->addLayout(pLayoutDHCPMask, 2, 2);
    684             }
    685 
    686             /* Create DHCP lower address label: */
    687             m_pLabelDHCPLowerAddress = new QLabel;
    688             AssertPtrReturnVoid(m_pLabelDHCPLowerAddress);
    689             {
    690                 /* Configure label: */
    691                 m_pLabelDHCPLowerAddress->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    692                 /* Add into layout: */
    693                 pLayoutDHCPServer->addWidget(m_pLabelDHCPLowerAddress, 3, 1);
    694             }
    695             /* Create DHCP lower address layout: */
    696             QHBoxLayout *pLayoutDHCPLowerAddress = new QHBoxLayout;
    697             AssertPtrReturnVoid(pLayoutDHCPLowerAddress);
    698             {
    699                 /* Configure layout: */
    700                 pLayoutDHCPLowerAddress->setContentsMargins(0, 0, 0, 0);
    701                 /* Create DHCP lower address editor: */
    702                 m_pEditorDHCPLowerAddress = new QILineEdit;
    703                 AssertPtrReturnVoid(m_pEditorDHCPLowerAddress);
    704                 {
    705                     /* Configure editor: */
    706                     m_pLabelDHCPLowerAddress->setBuddy(m_pEditorDHCPLowerAddress);
    707                     connect(m_pEditorDHCPLowerAddress, &QLineEdit::textChanged,
    708                             this, &UINetworkDetailsWidget::sltTextChangedLowerAddress);
    709                     /* Add into layout: */
    710                     pLayoutDHCPLowerAddress->addWidget(m_pEditorDHCPLowerAddress);
    711                 }
    712                 /* Create DHCP lower address error pane: */
    713                 m_pErrorPaneDHCPLowerAddress = new QLabel;
    714                 AssertPtrReturnVoid(m_pErrorPaneDHCPLowerAddress);
    715                 {
    716                     /* Configure label: */
    717                     m_pErrorPaneDHCPLowerAddress->setAlignment(Qt::AlignCenter);
    718                     m_pErrorPaneDHCPLowerAddress->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    719                                                             .pixmap(QSize(iIconMetric, iIconMetric)));
    720                     /* Add into layout: */
    721                     pLayoutDHCPLowerAddress->addWidget(m_pErrorPaneDHCPLowerAddress);
    722                 }
    723                 /* Add into layout: */
    724                 pLayoutDHCPServer->addLayout(pLayoutDHCPLowerAddress, 3, 2);
    725             }
    726 
    727             /* Create DHCP upper address label: */
    728             m_pLabelDHCPUpperAddress = new QLabel;
    729             AssertPtrReturnVoid(m_pLabelDHCPUpperAddress);
    730             {
    731                 /* Configure label: */
    732                 m_pLabelDHCPUpperAddress->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
    733                 /* Add into layout: */
    734                 pLayoutDHCPServer->addWidget(m_pLabelDHCPUpperAddress, 4, 1);
    735             }
    736             /* Create DHCP upper address layout: */
    737             QHBoxLayout *pLayoutDHCPUpperAddress = new QHBoxLayout;
    738             AssertPtrReturnVoid(pLayoutDHCPUpperAddress);
    739             {
    740                 /* Configure layout: */
    741                 pLayoutDHCPUpperAddress->setContentsMargins(0, 0, 0, 0);
    742                 /* Create DHCP upper address editor: */
    743                 m_pEditorDHCPUpperAddress = new QILineEdit;
    744                 AssertPtrReturnVoid(m_pEditorDHCPUpperAddress);
    745                 {
    746                     /* Configure editor: */
    747                     m_pLabelDHCPUpperAddress->setBuddy(m_pEditorDHCPUpperAddress);
    748                     connect(m_pEditorDHCPUpperAddress, &QLineEdit::textChanged,
    749                             this, &UINetworkDetailsWidget::sltTextChangedUpperAddress);
    750                     /* Add into layout: */
    751                     pLayoutDHCPUpperAddress->addWidget(m_pEditorDHCPUpperAddress);
    752                 }
    753                 /* Create DHCP upper address error pane: */
    754                 m_pErrorPaneDHCPUpperAddress = new QLabel;
    755                 AssertPtrReturnVoid(m_pErrorPaneDHCPUpperAddress);
    756                 {
    757                     /* Configure label: */
    758                     m_pErrorPaneDHCPUpperAddress->setAlignment(Qt::AlignCenter);
    759                     m_pErrorPaneDHCPUpperAddress->setPixmap(UIIconPool::iconSet(":/status_error_16px.png")
    760                                                             .pixmap(QSize(iIconMetric, iIconMetric)));
    761                     /* Add into layout: */
    762                     pLayoutDHCPUpperAddress->addWidget(m_pErrorPaneDHCPUpperAddress);
    763                 }
    764                 /* Add into layout: */
    765                 pLayoutDHCPServer->addLayout(pLayoutDHCPUpperAddress, 4, 2);
    766             }
    767 
    768             /* Create indent: */
    769             QStyleOption options;
    770             options.initFrom(m_pCheckBoxDHCP);
    771             const int iWidth = m_pCheckBoxDHCP->style()->pixelMetric(QStyle::PM_IndicatorWidth, &options, m_pCheckBoxDHCP) +
    772                                m_pCheckBoxDHCP->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &options, m_pCheckBoxDHCP) -
    773                                pLayoutDHCPServer->spacing() - 1;
    774             QSpacerItem *pSpacer1 = new QSpacerItem(iWidth, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
    775             AssertPtrReturnVoid(pSpacer1);
    776             {
    777                 /* Add into layout: */
    778                 pLayoutDHCPServer->addItem(pSpacer1, 1, 0, 4);
    779             }
    780             /* Create stretch: */
    781             QSpacerItem *pSpacer2 = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
    782             AssertPtrReturnVoid(pSpacer2);
    783             {
    784                 /* Add into layout: */
    785                 pLayoutDHCPServer->addItem(pSpacer2, 5, 0, 1, 3);
    786             }
    787 
    788             /* If parent embedded into stack: */
    789             if (m_enmEmbedding == EmbedTo_Stack)
    790             {
    791                 /* Create button-box: */
    792                 m_pButtonBoxServer = new QIDialogButtonBox;
    793                 AssertPtrReturnVoid(m_pButtonBoxServer);
    794                 /* Configure button-box: */
    795                 m_pButtonBoxServer->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
    796                 connect(m_pButtonBoxServer, &QIDialogButtonBox::clicked, this, &UINetworkDetailsWidget::sltHandleButtonBoxClick);
    797 
    798                 /* Add into layout: */
    799                 pLayoutDHCPServer->addWidget(m_pButtonBoxServer, 6, 0, 1, 3);
    800             }
    801         }
    802         /* Add to tab-widget: */
    803         m_pTabWidget->addTab(pTabDHCPServer, QString());
    804     }
    805 }
    806 
    807 void UINetworkDetailsWidget::loadDataForInterface()
    808 {
    809     /* Toggle IPv4 & IPv6 interface fields availability: */
    810     const bool fIsInterfaceConfigurable = !m_newData.m_interface.m_fDHCPEnabled;
    811     m_pLabelIPv4->setEnabled(fIsInterfaceConfigurable);
    812     m_pLabelNMv4->setEnabled(fIsInterfaceConfigurable);
    813     m_pEditorIPv4->setEnabled(fIsInterfaceConfigurable);
    814     m_pEditorNMv4->setEnabled(fIsInterfaceConfigurable);
    815 
    816     /* Load IPv4 interface fields: */
    817     m_pButtonAutomatic->setChecked(!fIsInterfaceConfigurable);
    818     m_pButtonManual->setChecked(fIsInterfaceConfigurable);
    819     m_pEditorIPv4->setText(m_newData.m_interface.m_strAddress);
    820     m_pEditorNMv4->setText(m_newData.m_interface.m_strMask);
    821 
    822     /* Toggle IPv6 interface fields availability: */
    823     const bool fIsIpv6Configurable = fIsInterfaceConfigurable && m_newData.m_interface.m_fSupportedIPv6;
    824     m_pLabelIPv6->setEnabled(fIsIpv6Configurable);
    825     m_pLabelNMv6->setEnabled(fIsIpv6Configurable);
    826     m_pEditorIPv6->setEnabled(fIsIpv6Configurable);
    827     m_pEditorNMv6->setEnabled(fIsIpv6Configurable);
    828 
    829     /* Load IPv6 interface fields: */
    830     m_pEditorIPv6->setText(m_newData.m_interface.m_strAddress6);
    831     m_pEditorNMv6->setText(m_newData.m_interface.m_strPrefixLength6);
    832 }
    833 
    834 void UINetworkDetailsWidget::loadDataForDHCPServer()
    835 {
    836     /* Toggle DHCP server fields availability: */
    837     const bool fIsDHCPServerEnabled = m_newData.m_dhcpserver.m_fEnabled;
    838     m_pLabelDHCPAddress->setEnabled(fIsDHCPServerEnabled);
    839     m_pLabelDHCPMask->setEnabled(fIsDHCPServerEnabled);
    840     m_pLabelDHCPLowerAddress->setEnabled(fIsDHCPServerEnabled);
    841     m_pLabelDHCPUpperAddress->setEnabled(fIsDHCPServerEnabled);
    842     m_pEditorDHCPAddress->setEnabled(fIsDHCPServerEnabled);
    843     m_pEditorDHCPMask->setEnabled(fIsDHCPServerEnabled);
    844     m_pEditorDHCPLowerAddress->setEnabled(fIsDHCPServerEnabled);
    845     m_pEditorDHCPUpperAddress->setEnabled(fIsDHCPServerEnabled);
    846 
    847     /* Load DHCP server fields: */
    848     m_pCheckBoxDHCP->setChecked(fIsDHCPServerEnabled);
    849     m_pEditorDHCPAddress->setText(m_newData.m_dhcpserver.m_strAddress);
    850     m_pEditorDHCPMask->setText(m_newData.m_dhcpserver.m_strMask);
    851     m_pEditorDHCPLowerAddress->setText(m_newData.m_dhcpserver.m_strLowerAddress);
    852     m_pEditorDHCPUpperAddress->setText(m_newData.m_dhcpserver.m_strUpperAddress);
    853 
    854     /* Invent default values if server was enabled
    855      * but at least one current value is invalid: */
    856     if (   fIsDHCPServerEnabled
    857         && (   m_pEditorDHCPAddress->text().isEmpty()
    858             || m_pEditorDHCPAddress->text() == "0.0.0.0"
    859             || m_pEditorDHCPMask->text().isEmpty()
    860             || m_pEditorDHCPMask->text() == "0.0.0.0"
    861             || m_pEditorDHCPLowerAddress->text().isEmpty()
    862             || m_pEditorDHCPLowerAddress->text() == "0.0.0.0"
    863             || m_pEditorDHCPUpperAddress->text().isEmpty()
    864             || m_pEditorDHCPUpperAddress->text() == "0.0.0.0"))
    865     {
    866         const QStringList &proposal = makeDhcpServerProposal(m_oldData.m_interface.m_strAddress,
    867                                                              m_oldData.m_interface.m_strMask);
    868         m_pEditorDHCPAddress->setText(proposal.at(0));
    869         m_pEditorDHCPMask->setText(proposal.at(1));
    870         m_pEditorDHCPLowerAddress->setText(proposal.at(2));
    871         m_pEditorDHCPUpperAddress->setText(proposal.at(3));
    872     }
    873 }
    874 
    875 void UINetworkDetailsWidget::revalidate(QWidget *pWidget /* = 0 */)
    876 {
     455
     456        m_pTabWidget->addTab(pTabForwarding, QString());
     457    }
     458}
     459
     460void UIDetailsWidgetNATNetwork::loadDataForOptions()
     461{
     462    /* Check whether network exists and enabled: */
     463    const bool fIsNetworkExists = m_newData.m_fExists;
     464    const bool fIsNetworkEnabled = m_newData.m_fEnabled;
     465
     466    /* Update 'Options' field availability: */
     467    m_pCheckboxNetworkAvailable->setEnabled(fIsNetworkExists);
     468    m_pLabelNetworkName->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     469    m_pEditorNetworkName->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     470    m_pLabelNetworkCIDR->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     471    m_pEditorNetworkCIDR->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     472    m_pLabelExtended->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     473    m_pCheckboxSupportsDHCP->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     474    m_pCheckboxSupportsIPv6->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     475    m_pCheckboxAdvertiseDefaultIPv6Route->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     476
     477    /* Load 'Options' fields: */
     478    m_pCheckboxNetworkAvailable->setChecked(fIsNetworkEnabled);
     479    m_pEditorNetworkName->setText(m_newData.m_strName);
     480    m_pEditorNetworkCIDR->setText(m_newData.m_strCIDR);
     481    m_pCheckboxSupportsDHCP->setChecked(m_newData.m_fSupportsDHCP);
     482    m_pCheckboxSupportsIPv6->setChecked(m_newData.m_fSupportsIPv6);
     483    m_pCheckboxAdvertiseDefaultIPv6Route->setChecked(m_newData.m_fAdvertiseDefaultIPv6Route);
     484}
     485
     486void UIDetailsWidgetNATNetwork::loadDataForForwarding()
     487{
     488    /* Check whether network exists and enabled: */
     489    const bool fIsNetworkExists = m_newData.m_fExists;
     490    const bool fIsNetworkEnabled = m_newData.m_fEnabled;
     491
     492    /* Update 'Forwarding' field availability: */
     493    m_pForwardingTableIPv4->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     494    m_pForwardingTableIPv6->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
     495
     496    /* Load 'Forwarding' fields: */
     497    m_pForwardingTableIPv4->setRules(m_newData.m_rules4);
     498    m_pForwardingTableIPv6->setRules(m_newData.m_rules6);
     499}
     500
     501void UIDetailsWidgetNATNetwork::revalidate(QWidget * /*pWidget*/ /* = 0 */)
     502{
     503#if 0
    877504    /* Validate 'Interface' tab content: */
    878505    if (!pWidget || pWidget == m_pErrorPaneAutomatic)
     
    956583    /* Retranslate validation: */
    957584    retranslateValidation(pWidget);
    958 }
    959 
    960 void UINetworkDetailsWidget::retranslateValidation(QWidget *pWidget /* = 0 */)
    961 {
     585#endif
     586}
     587
     588void UIDetailsWidgetNATNetwork::retranslateValidation(QWidget * /*pWidget*/ /* = 0 */)
     589{
     590#if 0
    962591    /* Translate 'Interface' tab content: */
    963592    if (!pWidget || pWidget == m_pErrorPaneAutomatic)
     
    990619        m_pErrorPaneDHCPUpperAddress->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
    991620                                                    "DHCP server upper address bound.").arg(m_newData.m_interface.m_strName));
    992 }
    993 
    994 void UINetworkDetailsWidget::updateButtonStates()
     621#endif
     622}
     623
     624void UIDetailsWidgetNATNetwork::updateButtonStates()
    995625{
    996626//    if (m_oldData != m_newData)
    997 //        printf("Interface: %s, %s, %s, %s;  DHCP server: %d, %s, %s, %s, %s\n",
    998 //               m_newData.m_interface.m_strAddress.toUtf8().constData(),
    999 //               m_newData.m_interface.m_strMask.toUtf8().constData(),
    1000 //               m_newData.m_interface.m_strAddress6.toUtf8().constData(),
    1001 //               m_newData.m_interface.m_strPrefixLength6.toUtf8().constData(),
    1002 //               (int)m_newData.m_dhcpserver.m_fEnabled,
    1003 //               m_newData.m_dhcpserver.m_strAddress.toUtf8().constData(),
    1004 //               m_newData.m_dhcpserver.m_strMask.toUtf8().constData(),
    1005 //               m_newData.m_dhcpserver.m_strLowerAddress.toUtf8().constData(),
    1006 //               m_newData.m_dhcpserver.m_strUpperAddress.toUtf8().constData());
     627//        printf("Network: %d, %s, %s, %d, %d, %d\n",
     628//               m_newData.m_fEnabled,
     629//               m_newData.m_strName.toUtf8().constData(),
     630//               m_newData.m_strCIDR.toUtf8().constData(),
     631//               m_newData.m_fSupportsDHCP,
     632//               m_newData.m_fSupportsIPv6,
     633//               m_newData.m_fAdvertiseDefaultIPv6Route);
    1007634
    1008635    /* Update 'Apply' / 'Reset' button states: */
    1009     if (m_pButtonBoxInterface)
    1010     {
    1011         m_pButtonBoxInterface->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
    1012         m_pButtonBoxInterface->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
    1013     }
    1014     if (m_pButtonBoxServer)
    1015     {
    1016         m_pButtonBoxServer->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
    1017         m_pButtonBoxServer->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
     636    if (m_pButtonBoxOptions)
     637    {
     638        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
     639        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
     640    }
     641    if (m_pButtonBoxForwarding)
     642    {
     643        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
     644        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
    1018645    }
    1019646
     
    1021648    emit sigDataChanged(m_oldData != m_newData);
    1022649}
    1023 
  • trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.h

    r87207 r87276  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UINetworkDetailsWidget class declaration.
     3 * VBox Qt GUI - UIDetailsWidgetNATNetwork class declaration.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2020 Oracle Corporation
     7 * Copyright (C) 2009-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 #ifndef FEQT_INCLUDED_SRC_networkmanager_UINetworkDetailsWidget_h
    19 #define FEQT_INCLUDED_SRC_networkmanager_UINetworkDetailsWidget_h
     18#ifndef FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h
     19#define FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h
    2020#ifndef RT_WITHOUT_PRAGMA_ONCE
    2121# pragma once
     
    2828#include "QIManagerDialog.h"
    2929#include "QIWithRetranslateUI.h"
     30#include "UIPortForwardingTable.h"
    3031
    3132/* Forward declarations: */
     
    3940
    4041
    41 /** Host Network Manager: Host Network Interface data structure. */
    42 struct UIDataHostNetworkInterface
     42/** Network Manager: NAT network data structure. */
     43struct UIDataNATNetwork
    4344{
    4445    /** Constructs data. */
    45     UIDataHostNetworkInterface()
    46         : m_strName(QString())
    47         , m_fDHCPEnabled(false)
    48         , m_strAddress(QString())
    49         , m_strMask(QString())
    50         , m_fSupportedIPv6(false)
    51         , m_strAddress6(QString())
    52         , m_strPrefixLength6(QString())
     46    UIDataNATNetwork()
     47        : m_fExists(false)
     48        , m_fEnabled(false)
     49        , m_strName(QString())
     50        , m_strCIDR(QString())
     51        , m_fSupportsDHCP(false)
     52        , m_fSupportsIPv6(false)
     53        , m_fAdvertiseDefaultIPv6Route(false)
    5354    {}
    5455
    5556    /** Returns whether the @a other passed data is equal to this one. */
    56     bool equal(const UIDataHostNetworkInterface &other) const
     57    bool equal(const UIDataNATNetwork &other) const
    5758    {
    5859        return true
     60               && (m_fExists == other.m_fExists)
     61               && (m_fEnabled == other.m_fEnabled)
    5962               && (m_strName == other.m_strName)
    60                && (m_fDHCPEnabled == other.m_fDHCPEnabled)
    61                && (m_strAddress == other.m_strAddress)
    62                && (m_strMask == other.m_strMask)
    63                && (m_fSupportedIPv6 == other.m_fSupportedIPv6)
    64                && (m_strAddress6 == other.m_strAddress6)
    65                && (m_strPrefixLength6 == other.m_strPrefixLength6)
     63               && (m_strCIDR == other.m_strCIDR)
     64               && (m_fSupportsDHCP == other.m_fSupportsDHCP)
     65               && (m_fSupportsIPv6 == other.m_fSupportsIPv6)
     66               && (m_fAdvertiseDefaultIPv6Route == other.m_fAdvertiseDefaultIPv6Route)
     67               && (m_rules4 == other.m_rules4)
     68               && (m_rules6 == other.m_rules6)
    6669               ;
    6770    }
    6871
    6972    /** Returns whether the @a other passed data is equal to this one. */
    70     bool operator==(const UIDataHostNetworkInterface &other) const { return equal(other); }
     73    bool operator==(const UIDataNATNetwork &other) const { return equal(other); }
    7174    /** Returns whether the @a other passed data is different from this one. */
    72     bool operator!=(const UIDataHostNetworkInterface &other) const { return !equal(other); }
    73 
    74     /** Holds interface name. */
    75     QString m_strName;
    76     /** Holds whether DHCP is enabled for that interface. */
    77     bool m_fDHCPEnabled;
    78     /** Holds IPv4 interface address. */
    79     QString m_strAddress;
    80     /** Holds IPv4 interface mask. */
    81     QString m_strMask;
    82     /** Holds whether IPv6 protocol supported. */
    83     bool m_fSupportedIPv6;
    84     /** Holds IPv6 interface address. */
    85     QString m_strAddress6;
    86     /** Holds IPv6 interface prefix length. */
    87     QString m_strPrefixLength6;
     75    bool operator!=(const UIDataNATNetwork &other) const { return !equal(other); }
     76
     77    /** Holds whether this network is not NULL. */
     78    bool                      m_fExists;
     79    /** Holds whether this network enabled. */
     80    bool                      m_fEnabled;
     81    /** Holds network name. */
     82    QString                   m_strName;
     83    /** Holds network CIDR. */
     84    QString                   m_strCIDR;
     85    /** Holds whether this network supports DHCP. */
     86    bool                      m_fSupportsDHCP;
     87    /** Holds whether this network supports IPv6. */
     88    bool                      m_fSupportsIPv6;
     89    /** Holds whether this network advertised as default IPv6 route. */
     90    bool                      m_fAdvertiseDefaultIPv6Route;
     91    /** Holds IPv4 port forwarding rules. */
     92    UIPortForwardingDataList  m_rules4;
     93    /** Holds IPv6 port forwarding rules. */
     94    UIPortForwardingDataList  m_rules6;
    8895};
    8996
    9097
    91 /** Host Network Manager: DHCP Server data structure. */
    92 struct UIDataDHCPServer
    93 {
    94     /** Constructs data. */
    95     UIDataDHCPServer()
    96         : m_fEnabled(false)
    97         , m_strAddress(QString())
    98         , m_strMask(QString())
    99         , m_strLowerAddress(QString())
    100         , m_strUpperAddress(QString())
    101     {}
    102 
    103     /** Returns whether the @a other passed data is equal to this one. */
    104     bool equal(const UIDataDHCPServer &other) const
    105     {
    106         return true
    107                && (m_fEnabled == other.m_fEnabled)
    108                && (m_strAddress == other.m_strAddress)
    109                && (m_strMask == other.m_strMask)
    110                && (m_strLowerAddress == other.m_strLowerAddress)
    111                && (m_strUpperAddress == other.m_strUpperAddress)
    112                ;
    113     }
    114 
    115     /** Returns whether the @a other passed data is equal to this one. */
    116     bool operator==(const UIDataDHCPServer &other) const { return equal(other); }
    117     /** Returns whether the @a other passed data is different from this one. */
    118     bool operator!=(const UIDataDHCPServer &other) const { return !equal(other); }
    119 
    120     /** Holds whether DHCP server enabled. */
    121     bool m_fEnabled;
    122     /** Holds DHCP server address. */
    123     QString m_strAddress;
    124     /** Holds DHCP server mask. */
    125     QString m_strMask;
    126     /** Holds DHCP server lower address. */
    127     QString m_strLowerAddress;
    128     /** Holds DHCP server upper address. */
    129     QString m_strUpperAddress;
    130 };
    131 
    132 
    133 /** Host Network Manager: Host network data structure. */
    134 struct UIDataHostNetwork
    135 {
    136     /** Constructs data. */
    137     UIDataHostNetwork()
    138         : m_interface(UIDataHostNetworkInterface())
    139         , m_dhcpserver(UIDataDHCPServer())
    140     {}
    141 
    142     /** Returns whether the @a other passed data is equal to this one. */
    143     bool equal(const UIDataHostNetwork &other) const
    144     {
    145         return true
    146                && (m_interface == other.m_interface)
    147                && (m_dhcpserver == other.m_dhcpserver)
    148                ;
    149     }
    150 
    151     /** Returns whether the @a other passed data is equal to this one. */
    152     bool operator==(const UIDataHostNetwork &other) const { return equal(other); }
    153     /** Returns whether the @a other passed data is different from this one. */
    154     bool operator!=(const UIDataHostNetwork &other) const { return !equal(other); }
    155 
    156     /** Holds the interface data. */
    157     UIDataHostNetworkInterface m_interface;
    158     /** Holds the DHCP server data. */
    159     UIDataDHCPServer m_dhcpserver;
    160 };
    161 
    162 
    163 /** Host Network Manager: Host network details-widget. */
    164 class UINetworkDetailsWidget : public QIWithRetranslateUI<QWidget>
     98/** Network Manager: NAT network details-widget. */
     99class UIDetailsWidgetNATNetwork : public QIWithRetranslateUI<QWidget>
    165100{
    166101    Q_OBJECT;
     
    180115    /** Constructs medium details dialog passing @a pParent to the base-class.
    181116      * @param  enmEmbedding  Brings embedding type. */
    182     UINetworkDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent = 0);
     117    UIDetailsWidgetNATNetwork(EmbedTo enmEmbedding, QWidget *pParent = 0);
    183118
    184119    /** Returns the host network data. */
    185     const UIDataHostNetwork &data() const { return m_newData; }
     120    const UIDataNATNetwork &data() const { return m_newData; }
    186121    /** Defines the host network @a data. */
    187     void setData(const UIDataHostNetwork &data);
     122    void setData(const UIDataNATNetwork &data);
    188123
    189124protected:
     
    196131    /** @name Change handling stuff.
    197132      * @{ */
    198         /** Handles interface automatic configuration choice change. */
    199         void sltToggledButtonAutomatic(bool fChecked);
    200         /** Handles interface manual configuration choice change. */
    201         void sltToggledButtonManual(bool fChecked);
    202         /** Handles interface IPv4 text change. */
    203         void sltTextChangedIPv4(const QString &strText);
    204         /** Handles interface NMv4 text change. */
    205         void sltTextChangedNMv4(const QString &strText);
    206         /** Handles interface IPv6 text change. */
    207         void sltTextChangedIPv6(const QString &strText);
    208         /** Handles interface NMv6 text change. */
    209         void sltTextChangedNMv6(const QString &strText);
    210 
    211         /** Handles DHCP server status change. */
    212         void sltStatusChangedServer(int iChecked);
    213         /** Handles DHCP server address text change. */
    214         void sltTextChangedAddress(const QString &strText);
    215         /** Handles DHCP server mask text change. */
    216         void sltTextChangedMask(const QString &strText);
    217         /** Handles DHCP server lower address text change. */
    218         void sltTextChangedLowerAddress(const QString &strText);
    219         /** Handles DHCP server upper address text change. */
    220         void sltTextChangedUpperAddress(const QString &strText);
     133        /** Handles network availability choice change. */
     134        void sltNetworkAvailabilityChanged(bool fChecked);
     135        /** Handles network name text change. */
     136        void sltNetworkNameChanged(const QString &strText);
     137        /** Handles network CIDR text change. */
     138        void sltNetworkCIDRChanged(const QString &strText);
     139        /** Handles network supports DHCP choice change. */
     140        void sltSupportsDHCPChanged(bool fChecked);
     141        /** Handles network supports IPv6 choice change. */
     142        void sltSupportsIPv6Changed(bool fChecked);
     143        /** Handles network advertised as default IPv6 route choice change. */
     144        void sltAdvertiseDefaultIPv6RouteChanged(bool fChecked);
     145
     146        /** */
     147        void sltForwardingRulesIPv4Changed();
     148        /** */
     149        void sltForwardingRulesIPv6Changed();
    221150
    222151        /** Handles button-box button click. */
     
    234163        /** Prepares tab-widget. */
    235164        void prepareTabWidget();
    236         /** Prepares 'Interface' tab. */
    237         void prepareTabInterface();
    238         /** Prepares 'DHCP server' tab. */
    239         void prepareTabDHCPServer();
     165        /** Prepares 'Options' tab. */
     166        void prepareTabOptions();
     167        /** Prepares 'Forwarding' tab. */
     168        void prepareTabForwarding();
    240169    /** @} */
    241170
    242171    /** @name Loading stuff.
    243172      * @{ */
    244         /** Loads interface data. */
    245         void loadDataForInterface();
    246         /** Loads server data. */
    247         void loadDataForDHCPServer();
     173        /** Loads 'Options' data. */
     174        void loadDataForOptions();
     175        /** Loads 'Forwarding' data. */
     176        void loadDataForForwarding();
    248177    /** @} */
    249178
     
    264193
    265194        /** Holds the old data copy. */
    266         UIDataHostNetwork  m_oldData;
     195        UIDataNATNetwork  m_oldData;
    267196        /** Holds the new data copy. */
    268         UIDataHostNetwork  m_newData;
     197        UIDataNATNetwork  m_newData;
    269198
    270199        /** Holds the tab-widget. */
     
    272201    /** @} */
    273202
    274     /** @name Interface variables.
    275       * @{ */
    276         /** Holds the automatic interface configuration button. */
    277         QRadioButton *m_pButtonAutomatic;
    278         /** Holds the automatic interface configuration error pane. */
    279         QLabel       *m_pErrorPaneAutomatic;
    280 
    281         /** Holds the manual interface configuration button. */
    282         QRadioButton *m_pButtonManual;
    283         /** Holds the manual interface configuration error pane. */
    284         QLabel       *m_pErrorPaneManual;
    285 
    286         /** Holds the IPv4 address label. */
    287         QLabel       *m_pLabelIPv4;
    288         /** Holds the IPv4 address editor. */
    289         QILineEdit   *m_pEditorIPv4;
    290         /** Holds the IPv4 address error pane. */
    291         QLabel       *m_pErrorPaneIPv4;
    292 
    293         /** Holds the IPv4 network mask label. */
    294         QLabel       *m_pLabelNMv4;
    295         /** Holds the IPv4 network mask editor. */
    296         QILineEdit   *m_pEditorNMv4;
    297         /** Holds the IPv4 network mask error pane. */
    298         QLabel       *m_pErrorPaneNMv4;
    299 
    300         /** Holds the IPv6 address label. */
    301         QLabel       *m_pLabelIPv6;
    302         /** Holds the IPv6 address editor. */
    303         QILineEdit   *m_pEditorIPv6;
    304         /** Holds the IPv6 address error pane. */
    305         QLabel       *m_pErrorPaneIPv6;
    306 
    307         /** Holds the IPv6 network mask label. */
    308         QLabel       *m_pLabelNMv6;
    309         /** Holds the IPv6 network mask editor. */
    310         QILineEdit   *m_pEditorNMv6;
    311         /** Holds the IPv6 network mask error pane. */
    312         QLabel       *m_pErrorPaneNMv6;
    313 
    314         /** Holds the interface button-box instance. */
    315         QIDialogButtonBox *m_pButtonBoxInterface;
    316     /** @} */
    317 
    318     /** @name DHCP server variables.
    319       * @{ */
    320         /** Holds the DHCP server status chack-box. */
    321         QCheckBox  *m_pCheckBoxDHCP;
    322 
    323         /** Holds the DHCP address label. */
    324         QLabel     *m_pLabelDHCPAddress;
    325         /** Holds the DHCP address editor. */
    326         QILineEdit *m_pEditorDHCPAddress;
    327         /** Holds the DHCP address error pane. */
    328         QLabel     *m_pErrorPaneDHCPAddress;
    329 
    330         /** Holds the DHCP network mask label. */
    331         QLabel     *m_pLabelDHCPMask;
    332         /** Holds the DHCP network mask editor. */
    333         QILineEdit *m_pEditorDHCPMask;
    334         /** Holds the DHCP network mask error pane. */
    335         QLabel     *m_pErrorPaneDHCPMask;
    336 
    337         /** Holds the DHCP lower address label. */
    338         QLabel     *m_pLabelDHCPLowerAddress;
    339         /** Holds the DHCP lower address editor. */
    340         QILineEdit *m_pEditorDHCPLowerAddress;
    341         /** Holds the DHCP lower address error pane. */
    342         QLabel     *m_pErrorPaneDHCPLowerAddress;
    343 
    344         /** Holds the DHCP upper address label. */
    345         QLabel     *m_pLabelDHCPUpperAddress;
    346         /** Holds the DHCP upper address editor. */
    347         QILineEdit *m_pEditorDHCPUpperAddress;
    348         /** Holds the DHCP upper address error pane. */
    349         QLabel     *m_pErrorPaneDHCPUpperAddress;
    350 
    351         /** Holds the server button-box instance. */
    352         QIDialogButtonBox *m_pButtonBoxServer;
     203    /** @name Network variables.
     204      * @{ */
     205        /** Holds the network availability check-box instance. */
     206        QCheckBox         *m_pCheckboxNetworkAvailable;
     207        /** Holds the network name label instance. */
     208        QLabel            *m_pLabelNetworkName;
     209        /** Holds the network name editor instance. */
     210        QLineEdit         *m_pEditorNetworkName;
     211        /** Holds the network CIDR label instance. */
     212        QLabel            *m_pLabelNetworkCIDR;
     213        /** Holds the network CIDR editor instance. */
     214        QLineEdit         *m_pEditorNetworkCIDR;
     215        /** Holds the extended label instance. */
     216        QLabel            *m_pLabelExtended;
     217        /** Holds the 'supports DHCP' check-box instance. */
     218        QCheckBox         *m_pCheckboxSupportsDHCP;
     219        /** Holds the 'supports IPv6' check-box instance. */
     220        QCheckBox         *m_pCheckboxSupportsIPv6;
     221        /** Holds the 'advertise default IPv6 route' check-box instance. */
     222        QCheckBox         *m_pCheckboxAdvertiseDefaultIPv6Route;
     223        /** Holds the 'Options' button-box instance. */
     224        QIDialogButtonBox *m_pButtonBoxOptions;
     225    /** @} */
     226
     227    /** @name Forwarding variables.
     228      * @{ */
     229        /** */
     230        QITabWidget           *m_pTabWidgetForwarding;
     231        /** */
     232        UIPortForwardingTable *m_pForwardingTableIPv4;
     233        /** */
     234        UIPortForwardingTable *m_pForwardingTableIPv6;
     235        /** Holds the 'Forwarding' button-box instance. */
     236        QIDialogButtonBox     *m_pButtonBoxForwarding;
    353237    /** @} */
    354238};
    355239
    356 #endif /* !FEQT_INCLUDED_SRC_networkmanager_UINetworkDetailsWidget_h */
    357 
     240
     241#endif /* !FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h */
     242
  • trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.cpp

    r87271 r87276  
    2727#include "QITreeWidget.h"
    2828#include "UIActionPoolManager.h"
     29#include "UIConverter.h"
    2930#include "UIDetailsWidgetHostNetwork.h"
     31#include "UIDetailsWidgetNATNetwork.h"
    3032#include "UIExtraDataManager.h"
    3133#include "UIIconPool.h"
     
    4345#include "CHost.h"
    4446#include "CHostNetworkInterface.h"
     47#include "CNATNetwork.h"
    4548
    4649/* Other VBox includes: */
     
    5255{
    5356    TabWidgetIndex_HostNetwork,
     57    TabWidgetIndex_NATNetwork,
    5458};
    5559
     
    6670
    6771
     72/** NAT network tree-widget column indexes. */
     73enum NATNetworkColumn
     74{
     75    NATNetworkColumn_Availability,
     76    NATNetworkColumn_Name,
     77    NATNetworkColumn_Max,
     78};
     79
     80
    6881/** Network Manager: Host Network tree-widget item. */
    6982class UIItemHostNetwork : public QITreeWidgetItem, public UIDataHostNetwork
     
    8396    /** Returns CIDR for a passed @a strMask. */
    8497    static int maskToCidr(const QString &strMask);
     98};
     99
     100
     101/** Network Manager: NAT Network tree-widget item. */
     102class UIItemNATNetwork : public QITreeWidgetItem, public UIDataNATNetwork
     103{
     104    Q_OBJECT;
     105
     106public:
     107
     108    /** Updates item fields from data. */
     109    void updateFields();
     110
     111    /** Returns item name. */
     112    QString name() const { return m_strName; }
    85113};
    86114
     
    194222
    195223/*********************************************************************************************************************************
     224*   Class UIItemNATNetwork implementation.                                                                                       *
     225*********************************************************************************************************************************/
     226
     227void UIItemNATNetwork::updateFields()
     228{
     229    /* Compose item fields: */
     230    setCheckState(NATNetworkColumn_Availability, m_fEnabled ? Qt::Checked : Qt::Unchecked);
     231    setText(NATNetworkColumn_Name, m_strName);
     232
     233    /* Compose tool-tip: */
     234    const QString strTable("<table cellspacing=5>%1</table>");
     235    const QString strHeader("<tr><td><nobr>%1:&nbsp;</nobr></td><td><nobr>%2</nobr></td></tr>");
     236    const QString strSubHeader("<tr><td><nobr>&nbsp;&nbsp;%1:&nbsp;</nobr></td><td><nobr>%2</nobr></td></tr>");
     237    QString strToolTip;
     238
     239    /* Network information: */
     240    strToolTip += strHeader.arg(tr("Network Name"), m_strName);
     241    strToolTip += strHeader.arg(tr("Network CIDR"), m_strCIDR);
     242    strToolTip += strHeader.arg(tr("Supports DHCP"), m_fSupportsDHCP ? tr("yes") : tr("no"));
     243    strToolTip += strHeader.arg(tr("Supports IPv6"), m_fSupportsIPv6 ? tr("yes") : tr("no"));
     244    if (m_fSupportsIPv6 && m_fAdvertiseDefaultIPv6Route)
     245        strToolTip += strSubHeader.arg(tr("Default IPv6 route"), tr("yes"));
     246
     247    /* Assign tool-tip finally: */
     248    setToolTip(NATNetworkColumn_Name, strTable.arg(strToolTip));
     249}
     250
     251
     252/*********************************************************************************************************************************
    196253*   Class UINetworkManagerWidget implementation.                                                                                 *
    197254*********************************************************************************************************************************/
     
    209266    , m_pTreeWidgetHostNetwork(0)
    210267    , m_pDetailsWidgetHostNetwork(0)
     268    , m_pTabNATNetwork(0)
     269    , m_pLayoutNATNetwork(0)
     270    , m_pTreeWidgetNATNetwork(0)
     271    , m_pDetailsWidgetNATNetwork(0)
    211272{
    212273    prepare();
     
    234295    /* Translate tab-widget: */
    235296    if (m_pTabWidget)
     297    {
    236298        m_pTabWidget->setTabText(0, UINetworkManager::tr("Host-only Networks"));
     299        m_pTabWidget->setTabText(1, UINetworkManager::tr("NAT Networks"));
     300    }
    237301
    238302    /* Translate host network tree-widget: */
     
    246310        m_pTreeWidgetHostNetwork->setHeaderLabels(fields);
    247311    }
     312
     313    /* Translate NAT network tree-widget: */
     314    if (m_pTreeWidgetNATNetwork)
     315    {
     316        const QStringList fields = QStringList()
     317                                   << UINetworkManager::tr("Active")
     318                                   << UINetworkManager::tr("Name");
     319        m_pTreeWidgetNATNetwork->setHeaderLabels(fields);
     320    }
    248321}
    249322
     
    275348    {
    276349        case TabWidgetIndex_HostNetwork: sltHandleCurrentItemChangeHostNetwork(); break;
     350        case TabWidgetIndex_NATNetwork: sltHandleCurrentItemChangeNATNetwork(); break;
    277351        default: break;
    278352    }
     
    288362    {
    289363        case TabWidgetIndex_HostNetwork: sltApplyDetailsChangesHostNetwork(); break;
     364        case TabWidgetIndex_NATNetwork: sltApplyDetailsChangesNATNetwork(); break;
    290365        default: break;
    291366    }
     
    437512}
    438513
     514void UINetworkManagerWidget::sltCreateNATNetwork()
     515{
     516    /* For NAT networks only: */
     517    if (m_pTabWidget->currentIndex() != TabWidgetIndex_NATNetwork)
     518        return;
     519
     520    /* Compose a set of busy names: */
     521    QSet<QString> names;
     522    for (int i = 0; i < m_pTreeWidgetNATNetwork->topLevelItemCount(); ++i)
     523        names << qobject_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->childItem(i))->name();
     524    /* Compose a map of busy indexes: */
     525    QMap<int, bool> presence;
     526    const QString strNameTemplate("NatNetwork%1");
     527    const QRegExp regExp(strNameTemplate.arg("([\\d]*)"));
     528    foreach (const QString &strName, names)
     529        if (regExp.indexIn(strName) != -1)
     530            presence[regExp.cap(1).toInt()] = true;
     531    /* Search for a minimum index: */
     532    int iMinimumIndex = 0;
     533    for (int i = 0; !presence.isEmpty() && i <= presence.lastKey() + 1; ++i)
     534        if (!presence.contains(i))
     535        {
     536            iMinimumIndex = i;
     537            break;
     538        }
     539    /* Compose resulting index and name: */
     540    const QString strNetworkName = strNameTemplate.arg(iMinimumIndex == 0 ? QString() : QString::number(iMinimumIndex));
     541
     542    /* Compose new item data: */
     543    UIDataNATNetwork oldData;
     544    oldData.m_fExists = true;
     545    oldData.m_fEnabled = true;
     546    oldData.m_strName = strNetworkName;
     547    oldData.m_strCIDR = "10.0.2.0/24";
     548    oldData.m_fSupportsDHCP = true;
     549    oldData.m_fSupportsIPv6 = false;
     550    oldData.m_fAdvertiseDefaultIPv6Route = false;
     551
     552    /* Get VirtualBox for further activities: */
     553    CVirtualBox comVBox = uiCommon().virtualBox();
     554
     555    /* Create network: */
     556    CNATNetwork comNetwork = comVBox.CreateNATNetwork(oldData.m_strName);
     557
     558    /* Show error message if necessary: */
     559    if (!comVBox.isOk())
     560        msgCenter().cannotCreateNATNetwork(comVBox, this);
     561    else
     562    {
     563        /* Save whether NAT network is enabled: */
     564        if (comNetwork.isOk())
     565            comNetwork.SetEnabled(oldData.m_fEnabled);
     566        /* Save NAT network name: */
     567        if (comNetwork.isOk())
     568            comNetwork.SetNetworkName(oldData.m_strName);
     569        /* Save NAT network CIDR: */
     570        if (comNetwork.isOk())
     571            comNetwork.SetNetwork(oldData.m_strCIDR);
     572        /* Save whether NAT network needs DHCP server: */
     573        if (comNetwork.isOk())
     574            comNetwork.SetNeedDhcpServer(oldData.m_fSupportsDHCP);
     575        /* Save whether NAT network supports IPv6: */
     576        if (comNetwork.isOk())
     577            comNetwork.SetIPv6Enabled(oldData.m_fSupportsIPv6);
     578        /* Save whether NAT network should advertise default IPv6 route: */
     579        if (comNetwork.isOk())
     580            comNetwork.SetAdvertiseDefaultIPv6RouteEnabled(oldData.m_fAdvertiseDefaultIPv6Route);
     581
     582        /* Show error message if necessary: */
     583        if (!comNetwork.isOk())
     584            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
     585
     586        /* Add network to the tree: */
     587        UIDataNATNetwork newData;
     588        loadNATNetwork(comNetwork, newData);
     589        createItemForNATNetwork(newData, true);
     590
     591        /* Adjust tree-widgets: */
     592        sltAdjustTreeWidgets();
     593    }
     594}
     595
     596void UINetworkManagerWidget::sltRemoveNATNetwork()
     597{
     598    /* For NAT networks only: */
     599    if (m_pTabWidget->currentIndex() != TabWidgetIndex_NATNetwork)
     600        return;
     601
     602    /* Check NAT network tree-widget: */
     603    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
     604
     605    /* Get network item: */
     606    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
     607    AssertMsgReturnVoid(pItem, ("Current item must not be null!\n"));
     608
     609    /* Get network name: */
     610    const QString strNetworkName(pItem->name());
     611
     612    /* Confirm host network removal: */
     613    if (!msgCenter().confirmNATNetworkRemoval(strNetworkName, this))
     614        return;
     615
     616    /* Get VirtualBox for further activities: */
     617    CVirtualBox comVBox = uiCommon().virtualBox();
     618
     619    /* Find corresponding network: */
     620    const CNATNetwork &comNetwork = comVBox.FindNATNetworkByName(strNetworkName);
     621
     622    /* Show error message if necessary: */
     623    if (!comVBox.isOk() || comNetwork.isNull())
     624        msgCenter().cannotFindNATNetwork(comVBox, strNetworkName, this);
     625    else
     626    {
     627        /* Remove network finally: */
     628        comVBox.RemoveNATNetwork(comNetwork);
     629
     630        /* Show error message if necessary: */
     631        if (!comVBox.isOk())
     632            msgCenter().cannotRemoveNATNetwork(comVBox, strNetworkName, this);
     633        else
     634        {
     635            /* Remove interface from the tree: */
     636            delete pItem;
     637
     638            /* Adjust tree-widgets: */
     639            sltAdjustTreeWidgets();
     640        }
     641    }
     642}
     643
    439644void UINetworkManagerWidget::sltToggleDetailsVisibility(bool fVisible)
    440645{
     
    446651        case TabWidgetIndex_HostNetwork:
    447652        {
     653            if (m_pDetailsWidgetNATNetwork)
     654                m_pDetailsWidgetNATNetwork->setVisible(false);
    448655            if (m_pDetailsWidgetHostNetwork)
    449656                m_pDetailsWidgetHostNetwork->setVisible(fVisible);
    450657            break;
    451658        }
     659        case TabWidgetIndex_NATNetwork:
     660        {
     661            if (m_pDetailsWidgetHostNetwork)
     662                m_pDetailsWidgetHostNetwork->setVisible(false);
     663            if (m_pDetailsWidgetNATNetwork)
     664                m_pDetailsWidgetNATNetwork->setVisible(fVisible);
     665            break;
     666        }
    452667    }
    453668    /* Notify external listeners: */
     
    463678        case TabWidgetIndex_HostNetwork:
    464679        {
     680            if (m_pDetailsWidgetNATNetwork)
     681                m_pDetailsWidgetNATNetwork->setVisible(false);
    465682            if (m_pDetailsWidgetHostNetwork)
    466683                m_pDetailsWidgetHostNetwork->setVisible(fVisible);
     684            break;
     685        }
     686        case TabWidgetIndex_NATNetwork:
     687        {
     688            if (m_pDetailsWidgetHostNetwork)
     689                m_pDetailsWidgetHostNetwork->setVisible(false);
     690            if (m_pDetailsWidgetNATNetwork)
     691                m_pDetailsWidgetNATNetwork->setVisible(fVisible);
    467692            break;
    468693        }
     
    495720        m_pTreeWidgetHostNetwork->setColumnWidth(HostNetworkColumn_DHCP, iWidth3);
    496721        m_pTreeWidgetHostNetwork->setColumnWidth(HostNetworkColumn_Name, iTotal - iWidth1 - iWidth2 - iWidth3);
     722    }
     723
     724    /* Check NAT network tree-widget: */
     725    if (m_pTreeWidgetNATNetwork)
     726    {
     727        /* Get the tree-widget abstract interface: */
     728        QAbstractItemView *pItemView = m_pTreeWidgetNATNetwork;
     729        /* Get the tree-widget header-view: */
     730        QHeaderView *pItemHeader = m_pTreeWidgetNATNetwork->header();
     731
     732        /* Calculate the total tree-widget width: */
     733        const int iTotal = m_pTreeWidgetNATNetwork->viewport()->width();
     734        /* Look for a minimum width hints for non-important columns: */
     735        const int iMinWidth1 = qMax(pItemView->sizeHintForColumn(NATNetworkColumn_Availability), pItemHeader->sectionSizeHint(NATNetworkColumn_Availability));
     736        /* Propose suitable width hints for non-important columns: */
     737        const int iWidth1 = iMinWidth1 < iTotal / NATNetworkColumn_Max ? iMinWidth1 : iTotal / NATNetworkColumn_Max;
     738        /* Apply the proposal: */
     739        m_pTreeWidgetNATNetwork->setColumnWidth(NATNetworkColumn_Availability, iWidth1);
     740        m_pTreeWidgetNATNetwork->setColumnWidth(NATNetworkColumn_Name, iTotal - iWidth1);
    497741    }
    498742}
     
    752996}
    753997
     998void UINetworkManagerWidget::sltHandleItemChangeNATNetwork(QTreeWidgetItem *pItem)
     999{
     1000    /* Get network item: */
     1001    UIItemNATNetwork *pChangedItem = static_cast<UIItemNATNetwork*>(pItem);
     1002    AssertMsgReturnVoid(pChangedItem, ("Changed item must not be null!\n"));
     1003
     1004    /* Get item data: */
     1005    UIDataNATNetwork oldData = *pChangedItem;
     1006
     1007    /* Make sure network availability status changed: */
     1008    if (   (   oldData.m_fEnabled
     1009            && pChangedItem->checkState(NATNetworkColumn_Availability) == Qt::Checked)
     1010        || (   !oldData.m_fEnabled
     1011            && pChangedItem->checkState(NATNetworkColumn_Availability) == Qt::Unchecked))
     1012        return;
     1013
     1014    /* Get VirtualBox for further activities: */
     1015    CVirtualBox comVBox = uiCommon().virtualBox();
     1016
     1017    /* Find corresponding network: */
     1018    CNATNetwork comNetwork = comVBox.FindNATNetworkByName(oldData.m_strName);
     1019
     1020    /* Show error message if necessary: */
     1021    if (!comVBox.isOk() || comNetwork.isNull())
     1022        msgCenter().cannotFindNATNetwork(comVBox, oldData.m_strName, this);
     1023    else
     1024    {
     1025        /* Save whether NAT network is enabled: */
     1026        if (comNetwork.isOk())
     1027            comNetwork.SetEnabled(!oldData.m_fEnabled);
     1028
     1029        /* Show error message if necessary: */
     1030        if (!comNetwork.isOk())
     1031            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
     1032        else
     1033        {
     1034            /* Update network in the tree: */
     1035            UIDataNATNetwork data;
     1036            loadNATNetwork(comNetwork, data);
     1037            updateItemForNATNetwork(data, true, pChangedItem);
     1038
     1039            /* Make sure current item fetched: */
     1040            sltHandleCurrentItemChangeNATNetwork();
     1041
     1042            /* Adjust tree-widgets: */
     1043            sltAdjustTreeWidgets();
     1044        }
     1045    }
     1046}
     1047
     1048void UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork()
     1049{
     1050    /* Check NAT network tree-widget: */
     1051    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
     1052
     1053    /* Get network item: */
     1054    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
     1055
     1056    /* Update actions availability: */
     1057    m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove)->setEnabled(pItem);
     1058    m_pActionPool->action(UIActionIndexMN_M_Network_T_Details)->setEnabled(pItem);
     1059
     1060    /* Check NAT network details-widget: */
     1061    AssertMsgReturnVoid(m_pDetailsWidgetNATNetwork, ("NAT network details-widget isn't created!\n"));
     1062
     1063    /* If there is an item => update details data: */
     1064    if (pItem)
     1065        m_pDetailsWidgetNATNetwork->setData(*pItem);
     1066    /* Otherwise => clear details: */
     1067    else
     1068        m_pDetailsWidgetNATNetwork->setData(UIDataNATNetwork());
     1069}
     1070
     1071void UINetworkManagerWidget::sltHandleContextMenuRequestNATNetwork(const QPoint &position)
     1072{
     1073    /* Check NAT network tree-widget: */
     1074    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
     1075
     1076    /* Compose temporary context-menu: */
     1077    QMenu menu;
     1078    if (m_pTreeWidgetNATNetwork->itemAt(position))
     1079    {
     1080        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove));
     1081        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_T_Details));
     1082    }
     1083    else
     1084    {
     1085        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create));
     1086//        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Refresh));
     1087    }
     1088    /* And show it: */
     1089    menu.exec(m_pTreeWidgetNATNetwork->mapToGlobal(position));
     1090}
     1091
     1092void UINetworkManagerWidget::sltApplyDetailsChangesNATNetwork()
     1093{
     1094    /* Check NAT network tree-widget: */
     1095    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
     1096
     1097    /* Get NAT network item: */
     1098    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
     1099    AssertMsgReturnVoid(pItem, ("Current item must not be null!\n"));
     1100
     1101    /* Check NAT network details-widget: */
     1102    AssertMsgReturnVoid(m_pDetailsWidgetNATNetwork, ("NAT network details-widget isn't created!\n"));
     1103
     1104    /* Get item data: */
     1105    UIDataNATNetwork oldData = *pItem;
     1106    UIDataNATNetwork newData = m_pDetailsWidgetNATNetwork->data();
     1107
     1108    /* Get VirtualBox for further activities: */
     1109    CVirtualBox comVBox = uiCommon().virtualBox();
     1110
     1111    /* Find corresponding network: */
     1112    CNATNetwork comNetwork = comVBox.FindNATNetworkByName(oldData.m_strName);
     1113
     1114    /* Show error message if necessary: */
     1115    if (!comVBox.isOk() || comNetwork.isNull())
     1116        msgCenter().cannotFindNATNetwork(comVBox, oldData.m_strName, this);
     1117    else
     1118    {
     1119        /* Save whether NAT network is enabled: */
     1120        if (comNetwork.isOk() && newData.m_fEnabled != oldData.m_fEnabled)
     1121            comNetwork.SetEnabled(newData.m_fEnabled);
     1122        /* Save NAT network name: */
     1123        if (comNetwork.isOk() && newData.m_strName != oldData.m_strName)
     1124            comNetwork.SetNetworkName(newData.m_strName);
     1125        /* Save NAT network CIDR: */
     1126        if (comNetwork.isOk() && newData.m_strCIDR != oldData.m_strCIDR)
     1127            comNetwork.SetNetwork(newData.m_strCIDR);
     1128        /* Save whether NAT network needs DHCP server: */
     1129        if (comNetwork.isOk() && newData.m_fSupportsDHCP != oldData.m_fSupportsDHCP)
     1130            comNetwork.SetNeedDhcpServer(newData.m_fSupportsDHCP);
     1131        /* Save whether NAT network supports IPv6: */
     1132        if (comNetwork.isOk() && newData.m_fSupportsIPv6 != oldData.m_fSupportsIPv6)
     1133            comNetwork.SetIPv6Enabled(newData.m_fSupportsIPv6);
     1134        /* Save whether NAT network should advertise default IPv6 route: */
     1135        if (comNetwork.isOk() && newData.m_fAdvertiseDefaultIPv6Route != oldData.m_fAdvertiseDefaultIPv6Route)
     1136            comNetwork.SetAdvertiseDefaultIPv6RouteEnabled(newData.m_fAdvertiseDefaultIPv6Route);
     1137
     1138        /* Save IPv4 forwarding rules: */
     1139        if (comNetwork.isOk() && newData.m_rules4 != oldData.m_rules4)
     1140        {
     1141            UIPortForwardingDataList oldRules = oldData.m_rules4;
     1142
     1143            /* Remove rules to be removed: */
     1144            foreach (const UIDataPortForwardingRule &oldRule, oldData.m_rules4)
     1145                if (comNetwork.isOk() && !newData.m_rules4.contains(oldRule))
     1146                {
     1147                    comNetwork.RemovePortForwardRule(false /* IPv6? */, oldRule.name);
     1148                    oldRules.removeAll(oldRule);
     1149                }
     1150            /* Add rules to be added: */
     1151            foreach (const UIDataPortForwardingRule &newRule, newData.m_rules4)
     1152                if (comNetwork.isOk() && !oldRules.contains(newRule))
     1153                {
     1154                    comNetwork.AddPortForwardRule(false /* IPv6? */, newRule.name, newRule.protocol,
     1155                                                  newRule.hostIp, newRule.hostPort.value(),
     1156                                                  newRule.guestIp, newRule.guestPort.value());
     1157                    oldRules.append(newRule);
     1158                }
     1159        }
     1160        /* Save IPv6 forwarding rules: */
     1161        if (comNetwork.isOk() && newData.m_rules6 != oldData.m_rules6)
     1162        {
     1163            UIPortForwardingDataList oldRules = oldData.m_rules6;
     1164
     1165            /* Remove rules to be removed: */
     1166            foreach (const UIDataPortForwardingRule &oldRule, oldData.m_rules6)
     1167                if (comNetwork.isOk() && !newData.m_rules6.contains(oldRule))
     1168                {
     1169                    comNetwork.RemovePortForwardRule(true /* IPv6? */, oldRule.name);
     1170                    oldRules.removeAll(oldRule);
     1171                }
     1172            /* Add rules to be added: */
     1173            foreach (const UIDataPortForwardingRule &newRule, newData.m_rules6)
     1174                if (comNetwork.isOk() && !oldRules.contains(newRule))
     1175                {
     1176                    comNetwork.AddPortForwardRule(true /* IPv6? */, newRule.name, newRule.protocol,
     1177                                                  newRule.hostIp, newRule.hostPort.value(),
     1178                                                  newRule.guestIp, newRule.guestPort.value());
     1179                    oldRules.append(newRule);
     1180                }
     1181        }
     1182
     1183        /* Show error message if necessary: */
     1184        if (!comNetwork.isOk())
     1185            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
     1186        else
     1187        {
     1188            /* Update network in the tree: */
     1189            UIDataNATNetwork data;
     1190            loadNATNetwork(comNetwork, data);
     1191            updateItemForNATNetwork(data, true, pItem);
     1192
     1193            /* Make sure current item fetched: */
     1194            sltHandleCurrentItemChangeNATNetwork();
     1195
     1196            /* Adjust tree-widgets: */
     1197            sltAdjustTreeWidgets();
     1198        }
     1199    }
     1200}
     1201
    7541202void UINetworkManagerWidget::prepare()
    7551203{
     
    7691217    /* Load networks: */
    7701218    loadHostNetworks();
     1219    loadNATNetworks();
    7711220}
    7721221
     
    7821231    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create), &QAction::triggered,
    7831232            this, &UINetworkManagerWidget::sltCreateHostNetwork);
     1233    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create), &QAction::triggered,
     1234            this, &UINetworkManagerWidget::sltCreateNATNetwork);
    7841235    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove), &QAction::triggered,
    7851236            this, &UINetworkManagerWidget::sltRemoveHostNetwork);
     1237    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove), &QAction::triggered,
     1238            this, &UINetworkManagerWidget::sltRemoveNATNetwork);
    7861239    connect(m_pActionPool->action(UIActionIndexMN_M_Network_T_Details), &QAction::toggled,
    7871240            this, &UINetworkManagerWidget::sltToggleDetailsVisibility);
     
    8111264        /* Prepare details widgets: */
    8121265        prepareDetailsWidgetHostNetwork();
     1266        prepareDetailsWidgetNATNetwork();
    8131267    }
    8141268}
     
    8521306
    8531307        prepareTabHostNetwork();
     1308        prepareTabNATNetwork();
    8541309
    8551310        /* Add into layout: */
     
    9221377}
    9231378
     1379void UINetworkManagerWidget::prepareTabNATNetwork()
     1380{
     1381    /* Prepare NAT network tab: */
     1382    m_pTabNATNetwork = new QWidget(m_pTabWidget);
     1383    if (m_pTabNATNetwork)
     1384    {
     1385        /* Prepare NAT network layout: */
     1386        m_pLayoutNATNetwork = new QVBoxLayout(m_pTabNATNetwork);
     1387        if (m_pLayoutNATNetwork)
     1388            prepareTreeWidgetNATNetwork();
     1389
     1390        /* Add into tab-widget: */
     1391        m_pTabWidget->insertTab(TabWidgetIndex_NATNetwork, m_pTabNATNetwork, QString());
     1392    }
     1393}
     1394
     1395void UINetworkManagerWidget::prepareTreeWidgetNATNetwork()
     1396{
     1397    /* Prepare NAT network tree-widget: */
     1398    m_pTreeWidgetNATNetwork = new QITreeWidget(m_pTabNATNetwork);
     1399    if (m_pTreeWidgetNATNetwork)
     1400    {
     1401        m_pTreeWidgetNATNetwork->setRootIsDecorated(false);
     1402        m_pTreeWidgetNATNetwork->setAlternatingRowColors(true);
     1403        m_pTreeWidgetNATNetwork->setContextMenuPolicy(Qt::CustomContextMenu);
     1404        m_pTreeWidgetNATNetwork->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     1405        m_pTreeWidgetNATNetwork->setColumnCount(NATNetworkColumn_Max);
     1406        m_pTreeWidgetNATNetwork->setSortingEnabled(true);
     1407        m_pTreeWidgetNATNetwork->sortByColumn(NATNetworkColumn_Name, Qt::AscendingOrder);
     1408        m_pTreeWidgetNATNetwork->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
     1409        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::currentItemChanged,
     1410                this, &UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork);
     1411        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::customContextMenuRequested,
     1412                this, &UINetworkManagerWidget::sltHandleContextMenuRequestNATNetwork);
     1413        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::itemChanged,
     1414                this, &UINetworkManagerWidget::sltHandleItemChangeNATNetwork);
     1415        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::itemDoubleClicked,
     1416                m_pActionPool->action(UIActionIndexMN_M_Network_T_Details), &QAction::setChecked);
     1417
     1418        /* Add into layout: */
     1419        m_pLayoutNATNetwork->addWidget(m_pTreeWidgetNATNetwork);
     1420    }
     1421}
     1422
     1423void UINetworkManagerWidget::prepareDetailsWidgetNATNetwork()
     1424{
     1425    /* Prepare NAT network details-widget: */
     1426    m_pDetailsWidgetNATNetwork = new UIDetailsWidgetNATNetwork(m_enmEmbedding, this);
     1427    if (m_pDetailsWidgetNATNetwork)
     1428    {
     1429        m_pDetailsWidgetNATNetwork->setVisible(false);
     1430        m_pDetailsWidgetNATNetwork->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
     1431        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChanged,
     1432                this, &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork);
     1433        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChangeRejected,
     1434                this, &UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork);
     1435        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChangeAccepted,
     1436                this, &UINetworkManagerWidget::sltApplyDetailsChangesNATNetwork);
     1437
     1438        /* Add into layout: */
     1439        layout()->addWidget(m_pDetailsWidgetNATNetwork);
     1440    }
     1441}
     1442
    9241443void UINetworkManagerWidget::loadSettings()
    9251444{
     
    9731492{
    9741493    /* Gather interface settings: */
     1494    if (comInterface.isNotNull())
     1495        data.m_interface.m_fExists = true;
    9751496    if (comInterface.isOk())
    9761497        data.m_interface.m_strName = comInterface.GetName();
     
    10281549}
    10291550
     1551void UINetworkManagerWidget::loadNATNetworks()
     1552{
     1553    /* Check NAT network tree-widget: */
     1554    if (!m_pTreeWidgetNATNetwork)
     1555        return;
     1556
     1557    /* Clear tree first of all: */
     1558    m_pTreeWidgetNATNetwork->clear();
     1559
     1560    /* Get VirtualBox for further activities: */
     1561    const CVirtualBox comVBox = uiCommon().virtualBox();
     1562
     1563    /* Get interfaces for further activities: */
     1564    const QVector<CNATNetwork> networks = comVBox.GetNATNetworks();
     1565
     1566    /* Show error message if necessary: */
     1567    if (!comVBox.isOk())
     1568        msgCenter().cannotAcquireNATNetworks(comVBox, this);
     1569    else
     1570    {
     1571        /* For each NAT network => load it to the tree: */
     1572        foreach (const CNATNetwork &comNetwork, networks)
     1573        {
     1574            UIDataNATNetwork data;
     1575            loadNATNetwork(comNetwork, data);
     1576            createItemForNATNetwork(data, false);
     1577        }
     1578
     1579        /* Choose the 1st item as current initially: */
     1580        m_pTreeWidgetNATNetwork->setCurrentItem(m_pTreeWidgetNATNetwork->topLevelItem(0));
     1581        sltHandleCurrentItemChangeNATNetwork();
     1582
     1583        /* Adjust tree-widgets: */
     1584        sltAdjustTreeWidgets();
     1585    }
     1586}
     1587
     1588void UINetworkManagerWidget::loadNATNetwork(const CNATNetwork &comNetwork, UIDataNATNetwork &data)
     1589{
     1590    /* Gather network settings: */
     1591    if (comNetwork.isNotNull())
     1592        data.m_fExists = true;
     1593    if (comNetwork.isOk())
     1594        data.m_fEnabled = comNetwork.GetEnabled();
     1595    if (comNetwork.isOk())
     1596        data.m_strName = comNetwork.GetNetworkName();
     1597    if (comNetwork.isOk())
     1598        data.m_strCIDR = comNetwork.GetNetwork();
     1599    if (comNetwork.isOk())
     1600        data.m_fSupportsDHCP = comNetwork.GetNeedDhcpServer();
     1601    if (comNetwork.isOk())
     1602        data.m_fSupportsIPv6 = comNetwork.GetIPv6Enabled();
     1603    if (comNetwork.isOk())
     1604        data.m_fAdvertiseDefaultIPv6Route = comNetwork.GetAdvertiseDefaultIPv6RouteEnabled();
     1605
     1606    /* Gather forwarding rules: */
     1607    if (comNetwork.isOk())
     1608    {
     1609        /* Load IPv4 rules: */
     1610        foreach (QString strIPv4Rule, comNetwork.GetPortForwardRules4())
     1611        {
     1612            /* Replace all ':' with ',' first: */
     1613            strIPv4Rule.replace(':', ',');
     1614            /* Parse rules: */
     1615            QStringList rules = strIPv4Rule.split(',');
     1616            Assert(rules.size() == 6);
     1617            if (rules.size() != 6)
     1618                continue;
     1619            data.m_rules4 << UIDataPortForwardingRule(rules.at(0),
     1620                                                      gpConverter->fromInternalString<KNATProtocol>(rules.at(1)),
     1621                                                      QString(rules.at(2)).remove('[').remove(']'),
     1622                                                      rules.at(3).toUInt(),
     1623                                                      QString(rules.at(4)).remove('[').remove(']'),
     1624                                                      rules.at(5).toUInt());
     1625        }
     1626
     1627        /* Load IPv6 rules: */
     1628        foreach (QString strIPv6Rule, comNetwork.GetPortForwardRules6())
     1629        {
     1630            /* Replace all ':' with ',' first: */
     1631            strIPv6Rule.replace(':', ',');
     1632            /* But replace ',' back with ':' for addresses: */
     1633            QRegExp re("\\[[0-9a-fA-F,]*,[0-9a-fA-F,]*\\]");
     1634            re.setMinimal(true);
     1635            while (re.indexIn(strIPv6Rule) != -1)
     1636            {
     1637                QString strCapOld = re.cap(0);
     1638                QString strCapNew = strCapOld;
     1639                strCapNew.replace(',', ':');
     1640                strIPv6Rule.replace(strCapOld, strCapNew);
     1641            }
     1642            /* Parse rules: */
     1643            QStringList rules = strIPv6Rule.split(',');
     1644            Assert(rules.size() == 6);
     1645            if (rules.size() != 6)
     1646                continue;
     1647            data.m_rules6 << UIDataPortForwardingRule(rules.at(0),
     1648                                                      gpConverter->fromInternalString<KNATProtocol>(rules.at(1)),
     1649                                                      QString(rules.at(2)).remove('[').remove(']'),
     1650                                                      rules.at(3).toUInt(),
     1651                                                      QString(rules.at(4)).remove('[').remove(']'),
     1652                                                      rules.at(5).toUInt());
     1653        }
     1654    }
     1655
     1656    /* Show error message if necessary: */
     1657    if (!comNetwork.isOk())
     1658        msgCenter().cannotAcquireNATNetworkParameter(comNetwork, this);
     1659}
     1660
    10301661void UINetworkManagerWidget::createItemForHostNetwork(const UIDataHostNetwork &data, bool fChooseItem)
    10311662{
     
    10561687        if (fChooseItem)
    10571688            m_pTreeWidgetHostNetwork->setCurrentItem(pItem);
     1689    }
     1690}
     1691
     1692void UINetworkManagerWidget::createItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem)
     1693{
     1694    /* Create new item: */
     1695    UIItemNATNetwork *pItem = new UIItemNATNetwork;
     1696    if (pItem)
     1697    {
     1698        /* Configure item: */
     1699        pItem->UIDataNATNetwork::operator=(data);
     1700        pItem->updateFields();
     1701        /* Add item to the tree: */
     1702        m_pTreeWidgetNATNetwork->addTopLevelItem(pItem);
     1703        /* And choose it as current if necessary: */
     1704        if (fChooseItem)
     1705            m_pTreeWidgetNATNetwork->setCurrentItem(pItem);
     1706    }
     1707}
     1708
     1709void UINetworkManagerWidget::updateItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem, UIItemNATNetwork *pItem)
     1710{
     1711    /* Update passed item: */
     1712    if (pItem)
     1713    {
     1714        /* Configure item: */
     1715        pItem->UIDataNATNetwork::operator=(data);
     1716        pItem->updateFields();
     1717        /* And choose it as current if necessary: */
     1718        if (fChooseItem)
     1719            m_pTreeWidgetNATNetwork->setCurrentItem(pItem);
    10581720    }
    10591721}
     
    11611823    connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedHostNetwork,
    11621824            button(ButtonType_Reset), &QPushButton::setEnabled);
     1825    connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork,
     1826            button(ButtonType_Apply), &QPushButton::setEnabled);
     1827    connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork,
     1828            button(ButtonType_Reset), &QPushButton::setEnabled);
    11631829    connect(buttonBox(), &QIDialogButtonBox::clicked,
    11641830            this, &UINetworkManager::sltHandleButtonBoxClick);
  • trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.h

    r87271 r87276  
    3131/* Forward declarations: */
    3232class CHostNetworkInterface;
     33class CNATNetwork;
    3334class QAbstractButton;
    3435class QTreeWidgetItem;
     
    3940class UIActionPool;
    4041class UIDetailsWidgetHostNetwork;
     42class UIDetailsWidgetNATNetwork;
    4143class UIItemHostNetwork;
     44class UIItemNATNetwork;
    4245class QIToolBar;
    4346struct UIDataHostNetwork;
     47struct UIDataNATNetwork;
    4448
    4549
     
    5660    /** Notifies listeners about host network details data @a fDiffers. */
    5761    void sigDetailsDataChangedHostNetwork(bool fDiffers);
     62
     63    /** Notifies listeners about NAT network details data @a fDiffers. */
     64    void sigDetailsDataChangedNATNetwork(bool fDiffers);
    5865
    5966public:
     
    106113        /** Handles command to remove host network. */
    107114        void sltRemoveHostNetwork();
     115
     116        /** Handles command to create NAT network. */
     117        void sltCreateNATNetwork();
     118        /** Handles command to remove NAT network. */
     119        void sltRemoveNATNetwork();
    108120
    109121        /** Handles command to make details @a fVisible. */
     
    127139        /** Handles command to apply host network details changes. */
    128140        void sltApplyDetailsChangesHostNetwork();
     141
     142        /** Handles NAT network tree-widget @a pItem change. */
     143        void sltHandleItemChangeNATNetwork(QTreeWidgetItem *pItem);
     144        /** Handles NAT network tree-widget current item change. */
     145        void sltHandleCurrentItemChangeNATNetwork();
     146        /** Handles NAT network context-menu request for tree-widget @a position. */
     147        void sltHandleContextMenuRequestNATNetwork(const QPoint &position);
     148        /** Handles command to apply NAT network details changes. */
     149        void sltApplyDetailsChangesNATNetwork();
    129150    /** @} */
    130151
     
    149170        /** Prepares host network details-widget. */
    150171        void prepareDetailsWidgetHostNetwork();
     172        /** Prepares NAT network tab. */
     173        void prepareTabNATNetwork();
     174        /** Prepares NAT network tree-widget. */
     175        void prepareTreeWidgetNATNetwork();
     176        /** Prepares NAT network details-widget. */
     177        void prepareDetailsWidgetNATNetwork();
    151178        /** Load settings: */
    152179        void loadSettings();
     
    159186        /** Loads host @a comInterface data to passed @a data container. */
    160187        void loadHostNetwork(const CHostNetworkInterface &comInterface, UIDataHostNetwork &data);
     188
     189        /** Loads NAT networks. */
     190        void loadNATNetworks();
     191        /** Loads NAT @a comNetwork data to passed @a data container. */
     192        void loadNATNetwork(const CNATNetwork &comNetwork, UIDataNATNetwork &data);
    161193    /** @} */
    162194
     
    167199        /** Updates passed host network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
    168200        void updateItemForHostNetwork(const UIDataHostNetwork &data, bool fChooseItem, UIItemHostNetwork *pItem);
     201
     202        /** Creates a new NAT network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
     203        void createItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem);
     204        /** Updates passed NAT network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
     205        void updateItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem, UIItemNATNetwork *pItem);
    169206    /** @} */
    170207
     
    198235        /** Holds the host network details-widget instance. */
    199236        UIDetailsWidgetHostNetwork *m_pDetailsWidgetHostNetwork;
     237
     238        /** Holds the NAT network tab. */
     239        QWidget                   *m_pTabNATNetwork;
     240        /** Holds the NAT network tab layout. */
     241        QVBoxLayout               *m_pLayoutNATNetwork;
     242        /** Holds the NAT network tree-widget instance. */
     243        QITreeWidget              *m_pTreeWidgetNATNetwork;
     244        /** Holds the NAT network details-widget instance. */
     245        UIDetailsWidgetNATNetwork *m_pDetailsWidgetNATNetwork;
    200246    /** @} */
    201247};
Note: See TracChangeset for help on using the changeset viewer.

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