Index: /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 87275)
+++ /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 87276)
@@ -620,4 +620,5 @@
 	src/monitor/resource/UIResourceMonitor.h \
 	src/networkmanager/UIDetailsWidgetHostNetwork.h \
+	src/networkmanager/UIDetailsWidgetNATNetwork.h \
 	src/networkmanager/UINetworkManager.h \
 	src/snapshots/UISnapshotDetailsWidget.h \
@@ -1101,4 +1102,5 @@
 	src/monitor/resource/UIResourceMonitor.cpp \
 	src/networkmanager/UIDetailsWidgetHostNetwork.cpp \
+	src/networkmanager/UIDetailsWidgetNATNetwork.cpp \
 	src/networkmanager/UINetworkManager.cpp \
 	src/networkmanager/UINetworkManagerUtils.cpp \
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp	(revision 87275)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp	(revision 87276)
@@ -1866,4 +1866,48 @@
 }
 
+void UIMessageCenter::cannotAcquireNATNetworks(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */) const
+{
+    error(pParent, MessageType_Error,
+          tr("Failed to acquire NAT networks."),
+          UIErrorString::formatErrorInfo(comVBox));
+}
+
+void UIMessageCenter::cannotAcquireNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent /* = 0 */) const
+{
+    error(pParent, MessageType_Error,
+          tr("Failed to acquire NAT network parameter."),
+          UIErrorString::formatErrorInfo(comNetwork));
+}
+
+void UIMessageCenter::cannotCreateNATNetwork(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */)
+{
+    error(pParent, MessageType_Error,
+          tr("Failed to create a NAT network."),
+          UIErrorString::formatErrorInfo(comVBox));
+}
+
+void UIMessageCenter::cannotSaveNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent /* = 0 */) const
+{
+    error(pParent, MessageType_Error,
+          tr("Failed to save NAT network parameter."),
+          UIErrorString::formatErrorInfo(comNetwork));
+}
+
+void UIMessageCenter::cannotFindNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent /* = 0 */) const
+{
+    error(pParent, MessageType_Error,
+          tr("Unable to find the NAT network <b>%1</b>.")
+             .arg(strNetworkName),
+          UIErrorString::formatErrorInfo(comVBox));
+}
+
+void UIMessageCenter::cannotRemoveNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent /* = 0 */) const
+{
+    error(pParent, MessageType_Error,
+          tr("Failed to remove the NAT network <b>%1</b>.")
+             .arg(strNetworkName),
+          UIErrorString::formatErrorInfo(comVBox));
+}
+
 void UIMessageCenter::cannotAcquireCloudProviderManager(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */) const
 {
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h	(revision 87275)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h	(revision 87276)
@@ -380,5 +380,5 @@
     void cannotCloseMedium(const UIMedium &medium, const COMResult &rc, QWidget *pParent = 0) const;
 
-    /* API: Host Network Manager warnings: */
+    /* API: Network Manager warnings: */
     bool confirmHostOnlyInterfaceRemoval(const QString &strName, QWidget *pParent = 0) const;
     void cannotAcquireHostNetworkInterfaces(const CHost &comHost, QWidget *pParent = 0) const;
@@ -394,4 +394,10 @@
     void cannotAcquireDHCPServerParameter(const CDHCPServer &comServer, QWidget *pParent = 0) const;
     void cannotSaveDHCPServerParameter(const CDHCPServer &comServer, QWidget *pParent = 0) const;
+    void cannotAcquireNATNetworks(const CVirtualBox &comVBox, QWidget *pParent = 0) const;
+    void cannotAcquireNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent = 0) const;
+    void cannotCreateNATNetwork(const CVirtualBox &comVBox, QWidget *pParent = 0);
+    void cannotSaveNATNetworkParameter(const CNATNetwork &comNetwork, QWidget *pParent = 0) const;
+    void cannotFindNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent = 0) const;
+    void cannotRemoveNATNetwork(const CVirtualBox &comVBox, const QString &strNetworkName, QWidget *pParent = 0) const;
 
     /* API: Cloud Profile Manager warnings: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.cpp	(revision 87276)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.cpp	(revision 87276)
@@ -0,0 +1,649 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIDetailsWidgetNATNetwork class implementation.
+ */
+
+/*
+ * Copyright (C) 2009-2021 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/* Qt includes: */
+#include <QCheckBox>
+#include <QLabel>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QRegExpValidator>
+#include <QStyleOption>
+#include <QVBoxLayout>
+
+/* GUI includes: */
+#include "QIDialogButtonBox.h"
+#include "QILineEdit.h"
+#include "QITabWidget.h"
+#include "UIIconPool.h"
+#include "UIDetailsWidgetNATNetwork.h"
+#include "UINetworkManagerUtils.h"
+
+/* Other VBox includes: */
+#include "iprt/assert.h"
+#include "iprt/cidr.h"
+
+
+UIDetailsWidgetNATNetwork::UIDetailsWidgetNATNetwork(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */)
+    : QIWithRetranslateUI<QWidget>(pParent)
+    , m_enmEmbedding(enmEmbedding)
+    , m_pTabWidget(0)
+    , m_pCheckboxNetworkAvailable(0)
+    , m_pLabelNetworkName(0)
+    , m_pEditorNetworkName(0)
+    , m_pLabelNetworkCIDR(0)
+    , m_pEditorNetworkCIDR(0)
+    , m_pLabelExtended(0)
+    , m_pCheckboxSupportsDHCP(0)
+    , m_pCheckboxSupportsIPv6(0)
+    , m_pCheckboxAdvertiseDefaultIPv6Route(0)
+    , m_pButtonBoxOptions(0)
+    , m_pTabWidgetForwarding(0)
+    , m_pForwardingTableIPv4(0)
+    , m_pForwardingTableIPv6(0)
+    , m_pButtonBoxForwarding(0)
+{
+    prepare();
+}
+
+void UIDetailsWidgetNATNetwork::setData(const UIDataNATNetwork &data)
+{
+    /* Cache old/new data: */
+    m_oldData = data;
+    m_newData = m_oldData;
+
+    /* Load 'Options' data: */
+    loadDataForOptions();
+    /* Load 'Forwarding' data: */
+    loadDataForForwarding();
+}
+
+void UIDetailsWidgetNATNetwork::retranslateUi()
+{
+    /* Translate tab-widget: */
+    if (m_pTabWidget)
+    {
+        m_pTabWidget->setTabText(0, tr("&General Options"));
+        m_pTabWidget->setTabText(1, tr("&Port Forwarding"));
+    }
+
+    /* Translate 'Options' tab content: */
+    if (m_pCheckboxNetworkAvailable)
+    {
+        m_pCheckboxNetworkAvailable->setText(tr("&Enable Network"));
+        m_pCheckboxNetworkAvailable->setToolTip(tr("When checked, this network will be enabled."));
+    }
+    if (m_pLabelNetworkName)
+        m_pLabelNetworkName->setText(tr("Network &Name:"));
+    if (m_pEditorNetworkName)
+        m_pEditorNetworkName->setToolTip(tr("Holds the name for this network."));
+    if (m_pLabelNetworkCIDR)
+        m_pLabelNetworkCIDR->setText(tr("Network &CIDR:"));
+    if (m_pEditorNetworkCIDR)
+        m_pEditorNetworkCIDR->setToolTip(tr("Holds the CIDR for this network."));
+    if (m_pLabelExtended)
+        m_pLabelExtended->setText(tr("Extended Features:"));
+    if (m_pCheckboxSupportsDHCP)
+    {
+        m_pCheckboxSupportsDHCP->setText(tr("Supports &DHCP"));
+        m_pCheckboxSupportsDHCP->setToolTip(tr("When checked, this network will support DHCP."));
+    }
+    if (m_pCheckboxSupportsIPv6)
+    {
+        m_pCheckboxSupportsIPv6->setText(tr("Supports &IPv6"));
+        m_pCheckboxSupportsIPv6->setToolTip(tr("When checked, this network will support IPv6."));
+    }
+    if (m_pCheckboxAdvertiseDefaultIPv6Route)
+    {
+        m_pCheckboxAdvertiseDefaultIPv6Route->setText(tr("Advertise Default IPv6 &Route"));
+        m_pCheckboxAdvertiseDefaultIPv6Route->setToolTip(tr("When checked, this network will be advertised as the default IPv6 route."));
+    }
+    if (m_pButtonBoxOptions)
+    {
+        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
+        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current interface details"));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current interface details"));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->
+            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->shortcut().toString()));
+        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->
+            setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->shortcut().toString()));
+    }
+
+    /* Translate 'Forwarding' tab content: */
+    if (m_pTabWidgetForwarding)
+    {
+        m_pTabWidgetForwarding->setTabText(0, tr("&IPv4"));
+        m_pTabWidgetForwarding->setTabText(1, tr("&IPv6"));
+    }
+    if (m_pButtonBoxForwarding)
+    {
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current interface details"));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current interface details"));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->
+            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->shortcut().toString()));
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->
+            setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->shortcut().toString()));
+    }
+
+    /* Retranslate validation: */
+    retranslateValidation();
+}
+
+void UIDetailsWidgetNATNetwork::sltNetworkAvailabilityChanged(bool fChecked)
+{
+    m_newData.m_fEnabled = fChecked;
+    loadDataForOptions();
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltNetworkNameChanged(const QString &strText)
+{
+    m_newData.m_strName = strText;
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltNetworkCIDRChanged(const QString &strText)
+{
+    m_newData.m_strCIDR = strText;
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltSupportsDHCPChanged(bool fChecked)
+{
+    m_newData.m_fSupportsDHCP = fChecked;
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltSupportsIPv6Changed(bool fChecked)
+{
+    m_newData.m_fSupportsIPv6 = fChecked;
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltAdvertiseDefaultIPv6RouteChanged(bool fChecked)
+{
+    m_newData.m_fAdvertiseDefaultIPv6Route = fChecked;
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltForwardingRulesIPv4Changed()
+{
+    m_newData.m_rules4 = m_pForwardingTableIPv4->rules();
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltForwardingRulesIPv6Changed()
+{
+    m_newData.m_rules6 = m_pForwardingTableIPv6->rules();
+    revalidate();
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick(QAbstractButton *pButton)
+{
+    /* Make sure button-boxes exist: */
+    if (!m_pButtonBoxOptions || !m_pButtonBoxForwarding)
+        return;
+
+    /* Disable buttons first of all: */
+    m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setEnabled(false);
+    m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setEnabled(false);
+    m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setEnabled(false);
+    m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+    /* Compare with known buttons: */
+    if (   pButton == m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)
+        || pButton == m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel))
+        emit sigDataChangeRejected();
+    else
+    if (   pButton == m_pButtonBoxOptions->button(QDialogButtonBox::Ok)
+        || pButton == m_pButtonBoxForwarding->button(QDialogButtonBox::Ok))
+        emit sigDataChangeAccepted();
+}
+
+void UIDetailsWidgetNATNetwork::prepare()
+{
+    /* Prepare this: */
+    prepareThis();
+
+    /* Apply language settings: */
+    retranslateUi();
+
+    /* Update button states finally: */
+    updateButtonStates();
+}
+
+void UIDetailsWidgetNATNetwork::prepareThis()
+{
+    /* Create layout: */
+    new QVBoxLayout(this);
+    if (layout())
+    {
+        /* Configure layout: */
+        layout()->setContentsMargins(0, 0, 0, 0);
+
+        /* Prepare tab-widget: */
+        prepareTabWidget();
+    }
+}
+
+void UIDetailsWidgetNATNetwork::prepareTabWidget()
+{
+    /* Create tab-widget: */
+    m_pTabWidget = new QITabWidget(this);
+    if (m_pTabWidget)
+    {
+        /* Prepare 'Options' tab: */
+        prepareTabOptions();
+        /* Prepare 'Forwarding' tab: */
+        prepareTabForwarding();
+
+        /* Add into layout: */
+        layout()->addWidget(m_pTabWidget);
+    }
+}
+
+void UIDetailsWidgetNATNetwork::prepareTabOptions()
+{
+    /* Prepare 'Options' tab: */
+    QWidget *pTabOptions = new QWidget(m_pTabWidget);
+    if (pTabOptions)
+    {
+        /* Prepare 'Options' layout: */
+        QGridLayout *pLayoutOptions = new QGridLayout(pTabOptions);
+        if (pLayoutOptions)
+        {
+#ifdef VBOX_WS_MAC
+            pLayoutOptions->setSpacing(10);
+            pLayoutOptions->setContentsMargins(10, 10, 10, 10);
+#endif
+
+            /* Prepare network availability check-box: */
+            m_pCheckboxNetworkAvailable = new QCheckBox(pTabOptions);
+            if (m_pCheckboxNetworkAvailable)
+            {
+                connect(m_pCheckboxNetworkAvailable, &QCheckBox::toggled,
+                        this, &UIDetailsWidgetNATNetwork::sltNetworkAvailabilityChanged);
+                pLayoutOptions->addWidget(m_pCheckboxNetworkAvailable, 0, 0, 1, 2);
+            }
+
+            /* Prepare 20-px shifting spacer: */
+            QSpacerItem *pSpacerItem = new QSpacerItem(20, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
+            if (pSpacerItem)
+                pLayoutOptions->addItem(pSpacerItem, 1, 0);
+
+            /* Prepare settings widget layout: */
+            QGridLayout *pLayoutSettings = new QGridLayout;
+            if (pLayoutSettings)
+            {
+                pLayoutSettings->setContentsMargins(0, 0, 0, 0);
+                pLayoutSettings->setColumnStretch(3, 1);
+
+                /* Prepare network name label: */
+                m_pLabelNetworkName = new QLabel(pTabOptions);
+                if (m_pLabelNetworkName)
+                {
+                    m_pLabelNetworkName->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+                    pLayoutSettings->addWidget(m_pLabelNetworkName, 0, 0);
+                }
+                /* Prepare network name editor: */
+                m_pEditorNetworkName = new QLineEdit(pTabOptions);
+                if (m_pEditorNetworkName)
+                {
+                    if (m_pLabelNetworkName)
+                        m_pLabelNetworkName->setBuddy(m_pEditorNetworkName);
+                    connect(m_pEditorNetworkName, &QLineEdit::textEdited,
+                            this, &UIDetailsWidgetNATNetwork::sltNetworkNameChanged);
+
+                    pLayoutSettings->addWidget(m_pEditorNetworkName, 0, 1, 1, 3);
+                }
+
+                /* Prepare network CIDR label: */
+                m_pLabelNetworkCIDR = new QLabel(pTabOptions);
+                if (m_pLabelNetworkCIDR)
+                {
+                    m_pLabelNetworkCIDR->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+                    pLayoutSettings->addWidget(m_pLabelNetworkCIDR, 1, 0);
+                }
+                /* Prepare network CIDR editor: */
+                m_pEditorNetworkCIDR = new QLineEdit(pTabOptions);
+                if (m_pEditorNetworkCIDR)
+                {
+                    if (m_pLabelNetworkCIDR)
+                        m_pLabelNetworkCIDR->setBuddy(m_pEditorNetworkCIDR);
+                    connect(m_pEditorNetworkCIDR, &QLineEdit::textEdited,
+                            this, &UIDetailsWidgetNATNetwork::sltNetworkCIDRChanged);
+
+                    pLayoutSettings->addWidget(m_pEditorNetworkCIDR, 1, 1, 1, 3);
+                }
+
+                /* Prepare extended label: */
+                m_pLabelExtended = new QLabel(pTabOptions);
+                if (m_pLabelExtended)
+                {
+                    m_pLabelExtended->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+                    pLayoutSettings->addWidget(m_pLabelExtended, 2, 0);
+                }
+                /* Prepare 'supports DHCP' check-box: */
+                m_pCheckboxSupportsDHCP = new QCheckBox(pTabOptions);
+                if (m_pCheckboxSupportsDHCP)
+                {
+                    connect(m_pCheckboxSupportsDHCP, &QCheckBox::toggled,
+                            this, &UIDetailsWidgetNATNetwork::sltSupportsDHCPChanged);
+                    pLayoutSettings->addWidget(m_pCheckboxSupportsDHCP, 2, 1, 1, 2);
+                }
+                /* Prepare 'supports IPv6' check-box: */
+                m_pCheckboxSupportsIPv6 = new QCheckBox(pTabOptions);
+                if (m_pCheckboxSupportsIPv6)
+                {
+                    connect(m_pCheckboxSupportsIPv6, &QCheckBox::toggled,
+                            this, &UIDetailsWidgetNATNetwork::sltSupportsIPv6Changed);
+                    pLayoutSettings->addWidget(m_pCheckboxSupportsIPv6, 3, 1, 1, 2);
+                }
+                /* Prepare 'advertise default IPv6 route' check-box: */
+                m_pCheckboxAdvertiseDefaultIPv6Route = new QCheckBox(pTabOptions);
+                if (m_pCheckboxAdvertiseDefaultIPv6Route)
+                {
+                    connect(m_pCheckboxAdvertiseDefaultIPv6Route, &QCheckBox::toggled,
+                            this, &UIDetailsWidgetNATNetwork::sltAdvertiseDefaultIPv6RouteChanged);
+                    pLayoutSettings->addWidget(m_pCheckboxAdvertiseDefaultIPv6Route, 4, 1, 1, 2);
+                }
+
+                pLayoutOptions->addLayout(pLayoutSettings, 1, 1);
+            }
+
+            /* If parent embedded into stack: */
+            if (m_enmEmbedding == EmbedTo_Stack)
+            {
+                /* Prepare button-box: */
+                m_pButtonBoxOptions = new QIDialogButtonBox(pTabOptions);
+                if (m_pButtonBoxOptions)
+                {
+                    m_pButtonBoxOptions->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
+                    connect(m_pButtonBoxOptions, &QIDialogButtonBox::clicked, this, &UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick);
+
+                    pLayoutOptions->addWidget(m_pButtonBoxOptions, 2, 0, 1, 2);
+                }
+            }
+        }
+
+        m_pTabWidget->addTab(pTabOptions, QString());
+    }
+}
+
+void UIDetailsWidgetNATNetwork::prepareTabForwarding()
+{
+    /* Prepare 'Forwarding' tab: */
+    QWidget *pTabForwarding = new QWidget(m_pTabWidget);
+    if (pTabForwarding)
+    {
+        /* Prepare 'Forwarding' layout: */
+        QGridLayout *pLayoutForwarding = new QGridLayout(pTabForwarding);
+        if (pLayoutForwarding)
+        {
+#ifdef VBOX_WS_MAC
+            /* Configure layout: */
+            pLayoutForwarding->setSpacing(10);
+            pLayoutForwarding->setContentsMargins(10, 10, 10, 10);
+#endif
+
+            /* Prepare forwarding tab-widget: */
+            m_pTabWidgetForwarding = new QITabWidget(pTabForwarding);
+            if (m_pTabWidgetForwarding)
+            {
+                /* Prepare IPv4 forwarding table: */
+                m_pForwardingTableIPv4 = new UIPortForwardingTable(UIPortForwardingDataList(), false, true);
+                if (m_pForwardingTableIPv4)
+                {
+                    connect(m_pForwardingTableIPv4, &UIPortForwardingTable::sigDataChanged,
+                            this, &UIDetailsWidgetNATNetwork::sltForwardingRulesIPv4Changed);
+                    m_pTabWidgetForwarding->addTab(m_pForwardingTableIPv4, QString());
+                }
+                /* Prepare IPv6 forwarding table: */
+                m_pForwardingTableIPv6 = new UIPortForwardingTable(UIPortForwardingDataList(), true, true);
+                if (m_pForwardingTableIPv6)
+                {
+                    connect(m_pForwardingTableIPv4, &UIPortForwardingTable::sigDataChanged,
+                            this, &UIDetailsWidgetNATNetwork::sltForwardingRulesIPv6Changed);
+                    m_pTabWidgetForwarding->addTab(m_pForwardingTableIPv6, QString());
+                }
+
+                pLayoutForwarding->addWidget(m_pTabWidgetForwarding, 0, 0);
+            }
+
+            /* If parent embedded into stack: */
+            if (m_enmEmbedding == EmbedTo_Stack)
+            {
+                /* Prepare button-box: */
+                m_pButtonBoxForwarding = new QIDialogButtonBox(pTabForwarding);
+                if (m_pButtonBoxForwarding)
+                {
+                    m_pButtonBoxForwarding->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
+                    connect(m_pButtonBoxForwarding, &QIDialogButtonBox::clicked, this, &UIDetailsWidgetNATNetwork::sltHandleButtonBoxClick);
+
+                    pLayoutForwarding->addWidget(m_pButtonBoxForwarding, 1, 0);
+                }
+            }
+        }
+
+        m_pTabWidget->addTab(pTabForwarding, QString());
+    }
+}
+
+void UIDetailsWidgetNATNetwork::loadDataForOptions()
+{
+    /* Check whether network exists and enabled: */
+    const bool fIsNetworkExists = m_newData.m_fExists;
+    const bool fIsNetworkEnabled = m_newData.m_fEnabled;
+
+    /* Update 'Options' field availability: */
+    m_pCheckboxNetworkAvailable->setEnabled(fIsNetworkExists);
+    m_pLabelNetworkName->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pEditorNetworkName->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pLabelNetworkCIDR->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pEditorNetworkCIDR->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pLabelExtended->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pCheckboxSupportsDHCP->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pCheckboxSupportsIPv6->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pCheckboxAdvertiseDefaultIPv6Route->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+
+    /* Load 'Options' fields: */
+    m_pCheckboxNetworkAvailable->setChecked(fIsNetworkEnabled);
+    m_pEditorNetworkName->setText(m_newData.m_strName);
+    m_pEditorNetworkCIDR->setText(m_newData.m_strCIDR);
+    m_pCheckboxSupportsDHCP->setChecked(m_newData.m_fSupportsDHCP);
+    m_pCheckboxSupportsIPv6->setChecked(m_newData.m_fSupportsIPv6);
+    m_pCheckboxAdvertiseDefaultIPv6Route->setChecked(m_newData.m_fAdvertiseDefaultIPv6Route);
+}
+
+void UIDetailsWidgetNATNetwork::loadDataForForwarding()
+{
+    /* Check whether network exists and enabled: */
+    const bool fIsNetworkExists = m_newData.m_fExists;
+    const bool fIsNetworkEnabled = m_newData.m_fEnabled;
+
+    /* Update 'Forwarding' field availability: */
+    m_pForwardingTableIPv4->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+    m_pForwardingTableIPv6->setEnabled(fIsNetworkExists && fIsNetworkEnabled);
+
+    /* Load 'Forwarding' fields: */
+    m_pForwardingTableIPv4->setRules(m_newData.m_rules4);
+    m_pForwardingTableIPv6->setRules(m_newData.m_rules6);
+}
+
+void UIDetailsWidgetNATNetwork::revalidate(QWidget * /*pWidget*/ /* = 0 */)
+{
+#if 0
+    /* Validate 'Interface' tab content: */
+    if (!pWidget || pWidget == m_pErrorPaneAutomatic)
+    {
+        const bool fError =    m_newData.m_interface.m_fDHCPEnabled
+                            && !m_newData.m_dhcpserver.m_fEnabled;
+        m_pErrorPaneAutomatic->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneManual)
+    {
+        const bool fError = false;
+        m_pErrorPaneManual->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneIPv4)
+    {
+        const bool fError =    !m_newData.m_interface.m_fDHCPEnabled
+                            && !m_newData.m_interface.m_strAddress.trimmed().isEmpty()
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_interface.m_strAddress.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_interface.m_strAddress.toUtf8().constData()));
+        m_pErrorPaneIPv4->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneNMv4)
+    {
+        const bool fError =    !m_newData.m_interface.m_fDHCPEnabled
+                            && !m_newData.m_interface.m_strMask.trimmed().isEmpty()
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_interface.m_strMask.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_interface.m_strMask.toUtf8().constData()));
+        m_pErrorPaneNMv4->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneIPv6)
+    {
+        const bool fError =    !m_newData.m_interface.m_fDHCPEnabled
+                            && m_newData.m_interface.m_fSupportedIPv6
+                            && !m_newData.m_interface.m_strAddress6.trimmed().isEmpty()
+                            && (   !RTNetIsIPv6AddrStr(m_newData.m_interface.m_strAddress6.toUtf8().constData())
+                                || RTNetStrIsIPv6AddrAny(m_newData.m_interface.m_strAddress6.toUtf8().constData()));
+        m_pErrorPaneIPv6->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneNMv6)
+    {
+        bool fIsMaskPrefixLengthNumber = false;
+        const int iMaskPrefixLength = m_newData.m_interface.m_strPrefixLength6.trimmed().toInt(&fIsMaskPrefixLengthNumber);
+        const bool fError =    !m_newData.m_interface.m_fDHCPEnabled
+                            && m_newData.m_interface.m_fSupportedIPv6
+                            && (   !fIsMaskPrefixLengthNumber
+                                || iMaskPrefixLength < 0
+                                || iMaskPrefixLength > 128);
+        m_pErrorPaneNMv6->setVisible(fError);
+    }
+
+    /* Validate 'DHCP server' tab content: */
+    if (!pWidget || pWidget == m_pErrorPaneDHCPAddress)
+    {
+        const bool fError =    m_newData.m_dhcpserver.m_fEnabled
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_dhcpserver.m_strAddress.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_dhcpserver.m_strAddress.toUtf8().constData()));
+        m_pErrorPaneDHCPAddress->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneDHCPMask)
+    {
+        const bool fError =    m_newData.m_dhcpserver.m_fEnabled
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_dhcpserver.m_strMask.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_dhcpserver.m_strMask.toUtf8().constData()));
+        m_pErrorPaneDHCPMask->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneDHCPLowerAddress)
+    {
+        const bool fError =    m_newData.m_dhcpserver.m_fEnabled
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_dhcpserver.m_strLowerAddress.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_dhcpserver.m_strLowerAddress.toUtf8().constData()));
+        m_pErrorPaneDHCPLowerAddress->setVisible(fError);
+    }
+    if (!pWidget || pWidget == m_pErrorPaneDHCPUpperAddress)
+    {
+        const bool fError =    m_newData.m_dhcpserver.m_fEnabled
+                            && (   !RTNetIsIPv4AddrStr(m_newData.m_dhcpserver.m_strUpperAddress.toUtf8().constData())
+                                || RTNetStrIsIPv4AddrAny(m_newData.m_dhcpserver.m_strUpperAddress.toUtf8().constData()));
+        m_pErrorPaneDHCPUpperAddress->setVisible(fError);
+    }
+
+    /* Retranslate validation: */
+    retranslateValidation(pWidget);
+#endif
+}
+
+void UIDetailsWidgetNATNetwork::retranslateValidation(QWidget * /*pWidget*/ /* = 0 */)
+{
+#if 0
+    /* Translate 'Interface' tab content: */
+    if (!pWidget || pWidget == m_pErrorPaneAutomatic)
+        m_pErrorPaneAutomatic->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> is set to obtain the address automatically "
+                                             "but the corresponding DHCP server is not enabled.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneIPv4)
+        m_pErrorPaneIPv4->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                        "IPv4 address.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneNMv4)
+        m_pErrorPaneNMv4->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                        "IPv4 network mask.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneIPv6)
+        m_pErrorPaneIPv6->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                        "IPv6 address.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneNMv6)
+        m_pErrorPaneNMv6->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                        "IPv6 prefix length.").arg(m_newData.m_interface.m_strName));
+
+    /* Translate 'DHCP server' tab content: */
+    if (!pWidget || pWidget == m_pErrorPaneDHCPAddress)
+        m_pErrorPaneDHCPAddress->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                               "DHCP server address.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneDHCPMask)
+        m_pErrorPaneDHCPMask->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                            "DHCP server mask.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneDHCPLowerAddress)
+        m_pErrorPaneDHCPLowerAddress->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                                    "DHCP server lower address bound.").arg(m_newData.m_interface.m_strName));
+    if (!pWidget || pWidget == m_pErrorPaneDHCPUpperAddress)
+        m_pErrorPaneDHCPUpperAddress->setToolTip(tr("Host interface <nobr><b>%1</b></nobr> does not currently have a valid "
+                                                    "DHCP server upper address bound.").arg(m_newData.m_interface.m_strName));
+#endif
+}
+
+void UIDetailsWidgetNATNetwork::updateButtonStates()
+{
+//    if (m_oldData != m_newData)
+//        printf("Network: %d, %s, %s, %d, %d, %d\n",
+//               m_newData.m_fEnabled,
+//               m_newData.m_strName.toUtf8().constData(),
+//               m_newData.m_strCIDR.toUtf8().constData(),
+//               m_newData.m_fSupportsDHCP,
+//               m_newData.m_fSupportsIPv6,
+//               m_newData.m_fAdvertiseDefaultIPv6Route);
+
+    /* Update 'Apply' / 'Reset' button states: */
+    if (m_pButtonBoxOptions)
+    {
+        m_pButtonBoxOptions->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
+        m_pButtonBoxOptions->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
+    }
+    if (m_pButtonBoxForwarding)
+    {
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
+        m_pButtonBoxForwarding->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
+    }
+
+    /* Notify listeners as well: */
+    emit sigDataChanged(m_oldData != m_newData);
+}
Index: /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.h	(revision 87276)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UIDetailsWidgetNATNetwork.h	(revision 87276)
@@ -0,0 +1,242 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIDetailsWidgetNATNetwork class declaration.
+ */
+
+/*
+ * Copyright (C) 2009-2021 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h
+#define FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Qt includes: */
+#include <QWidget>
+
+/* GUI includes: */
+#include "QIManagerDialog.h"
+#include "QIWithRetranslateUI.h"
+#include "UIPortForwardingTable.h"
+
+/* Forward declarations: */
+class QAbstractButton;
+class QCheckBox;
+class QLabel;
+class QRadioButton;
+class QIDialogButtonBox;
+class QILineEdit;
+class QITabWidget;
+
+
+/** Network Manager: NAT network data structure. */
+struct UIDataNATNetwork
+{
+    /** Constructs data. */
+    UIDataNATNetwork()
+        : m_fExists(false)
+        , m_fEnabled(false)
+        , m_strName(QString())
+        , m_strCIDR(QString())
+        , m_fSupportsDHCP(false)
+        , m_fSupportsIPv6(false)
+        , m_fAdvertiseDefaultIPv6Route(false)
+    {}
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool equal(const UIDataNATNetwork &other) const
+    {
+        return true
+               && (m_fExists == other.m_fExists)
+               && (m_fEnabled == other.m_fEnabled)
+               && (m_strName == other.m_strName)
+               && (m_strCIDR == other.m_strCIDR)
+               && (m_fSupportsDHCP == other.m_fSupportsDHCP)
+               && (m_fSupportsIPv6 == other.m_fSupportsIPv6)
+               && (m_fAdvertiseDefaultIPv6Route == other.m_fAdvertiseDefaultIPv6Route)
+               && (m_rules4 == other.m_rules4)
+               && (m_rules6 == other.m_rules6)
+               ;
+    }
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool operator==(const UIDataNATNetwork &other) const { return equal(other); }
+    /** Returns whether the @a other passed data is different from this one. */
+    bool operator!=(const UIDataNATNetwork &other) const { return !equal(other); }
+
+    /** Holds whether this network is not NULL. */
+    bool                      m_fExists;
+    /** Holds whether this network enabled. */
+    bool                      m_fEnabled;
+    /** Holds network name. */
+    QString                   m_strName;
+    /** Holds network CIDR. */
+    QString                   m_strCIDR;
+    /** Holds whether this network supports DHCP. */
+    bool                      m_fSupportsDHCP;
+    /** Holds whether this network supports IPv6. */
+    bool                      m_fSupportsIPv6;
+    /** Holds whether this network advertised as default IPv6 route. */
+    bool                      m_fAdvertiseDefaultIPv6Route;
+    /** Holds IPv4 port forwarding rules. */
+    UIPortForwardingDataList  m_rules4;
+    /** Holds IPv6 port forwarding rules. */
+    UIPortForwardingDataList  m_rules6;
+};
+
+
+/** Network Manager: NAT network details-widget. */
+class UIDetailsWidgetNATNetwork : public QIWithRetranslateUI<QWidget>
+{
+    Q_OBJECT;
+
+signals:
+
+    /** Notifies listeners about data changed and whether it @a fDiffers. */
+    void sigDataChanged(bool fDiffers);
+
+    /** Notifies listeners about data change rejected and should be reseted. */
+    void sigDataChangeRejected();
+    /** Notifies listeners about data change accepted and should be applied. */
+    void sigDataChangeAccepted();
+
+public:
+
+    /** Constructs medium details dialog passing @a pParent to the base-class.
+      * @param  enmEmbedding  Brings embedding type. */
+    UIDetailsWidgetNATNetwork(EmbedTo enmEmbedding, QWidget *pParent = 0);
+
+    /** Returns the host network data. */
+    const UIDataNATNetwork &data() const { return m_newData; }
+    /** Defines the host network @a data. */
+    void setData(const UIDataNATNetwork &data);
+
+protected:
+
+    /** Handles translation event. */
+    virtual void retranslateUi() /* override */;
+
+private slots:
+
+    /** @name Change handling stuff.
+      * @{ */
+        /** Handles network availability choice change. */
+        void sltNetworkAvailabilityChanged(bool fChecked);
+        /** Handles network name text change. */
+        void sltNetworkNameChanged(const QString &strText);
+        /** Handles network CIDR text change. */
+        void sltNetworkCIDRChanged(const QString &strText);
+        /** Handles network supports DHCP choice change. */
+        void sltSupportsDHCPChanged(bool fChecked);
+        /** Handles network supports IPv6 choice change. */
+        void sltSupportsIPv6Changed(bool fChecked);
+        /** Handles network advertised as default IPv6 route choice change. */
+        void sltAdvertiseDefaultIPv6RouteChanged(bool fChecked);
+
+        /** */
+        void sltForwardingRulesIPv4Changed();
+        /** */
+        void sltForwardingRulesIPv6Changed();
+
+        /** Handles button-box button click. */
+        void sltHandleButtonBoxClick(QAbstractButton *pButton);
+    /** @} */
+
+private:
+
+    /** @name Prepare/cleanup cascade.
+      * @{ */
+        /** Prepares all. */
+        void prepare();
+        /** Prepares this. */
+        void prepareThis();
+        /** Prepares tab-widget. */
+        void prepareTabWidget();
+        /** Prepares 'Options' tab. */
+        void prepareTabOptions();
+        /** Prepares 'Forwarding' tab. */
+        void prepareTabForwarding();
+    /** @} */
+
+    /** @name Loading stuff.
+      * @{ */
+        /** Loads 'Options' data. */
+        void loadDataForOptions();
+        /** Loads 'Forwarding' data. */
+        void loadDataForForwarding();
+    /** @} */
+
+    /** @name Change handling stuff.
+      * @{ */
+        /** Revalidates changes for passed @a pWidget. */
+        void revalidate(QWidget *pWidget = 0);
+        /** Retranslates validation for passed @a pWidget. */
+        void retranslateValidation(QWidget *pWidget = 0);
+        /** Updates button states. */
+        void updateButtonStates();
+    /** @} */
+
+    /** @name General variables.
+      * @{ */
+        /** Holds the parent widget embedding type. */
+        const EmbedTo m_enmEmbedding;
+
+        /** Holds the old data copy. */
+        UIDataNATNetwork  m_oldData;
+        /** Holds the new data copy. */
+        UIDataNATNetwork  m_newData;
+
+        /** Holds the tab-widget. */
+        QITabWidget *m_pTabWidget;
+    /** @} */
+
+    /** @name Network variables.
+      * @{ */
+        /** Holds the network availability check-box instance. */
+        QCheckBox         *m_pCheckboxNetworkAvailable;
+        /** Holds the network name label instance. */
+        QLabel            *m_pLabelNetworkName;
+        /** Holds the network name editor instance. */
+        QLineEdit         *m_pEditorNetworkName;
+        /** Holds the network CIDR label instance. */
+        QLabel            *m_pLabelNetworkCIDR;
+        /** Holds the network CIDR editor instance. */
+        QLineEdit         *m_pEditorNetworkCIDR;
+        /** Holds the extended label instance. */
+        QLabel            *m_pLabelExtended;
+        /** Holds the 'supports DHCP' check-box instance. */
+        QCheckBox         *m_pCheckboxSupportsDHCP;
+        /** Holds the 'supports IPv6' check-box instance. */
+        QCheckBox         *m_pCheckboxSupportsIPv6;
+        /** Holds the 'advertise default IPv6 route' check-box instance. */
+        QCheckBox         *m_pCheckboxAdvertiseDefaultIPv6Route;
+        /** Holds the 'Options' button-box instance. */
+        QIDialogButtonBox *m_pButtonBoxOptions;
+    /** @} */
+
+    /** @name Forwarding variables.
+      * @{ */
+        /** */
+        QITabWidget           *m_pTabWidgetForwarding;
+        /** */
+        UIPortForwardingTable *m_pForwardingTableIPv4;
+        /** */
+        UIPortForwardingTable *m_pForwardingTableIPv6;
+        /** Holds the 'Forwarding' button-box instance. */
+        QIDialogButtonBox     *m_pButtonBoxForwarding;
+    /** @} */
+};
+
+
+#endif /* !FEQT_INCLUDED_SRC_networkmanager_UIDetailsWidgetNATNetwork_h */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.cpp	(revision 87275)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.cpp	(revision 87276)
@@ -27,5 +27,7 @@
 #include "QITreeWidget.h"
 #include "UIActionPoolManager.h"
+#include "UIConverter.h"
 #include "UIDetailsWidgetHostNetwork.h"
+#include "UIDetailsWidgetNATNetwork.h"
 #include "UIExtraDataManager.h"
 #include "UIIconPool.h"
@@ -43,4 +45,5 @@
 #include "CHost.h"
 #include "CHostNetworkInterface.h"
+#include "CNATNetwork.h"
 
 /* Other VBox includes: */
@@ -52,4 +55,5 @@
 {
     TabWidgetIndex_HostNetwork,
+    TabWidgetIndex_NATNetwork,
 };
 
@@ -66,4 +70,13 @@
 
 
+/** NAT network tree-widget column indexes. */
+enum NATNetworkColumn
+{
+    NATNetworkColumn_Availability,
+    NATNetworkColumn_Name,
+    NATNetworkColumn_Max,
+};
+
+
 /** Network Manager: Host Network tree-widget item. */
 class UIItemHostNetwork : public QITreeWidgetItem, public UIDataHostNetwork
@@ -83,4 +96,19 @@
     /** Returns CIDR for a passed @a strMask. */
     static int maskToCidr(const QString &strMask);
+};
+
+
+/** Network Manager: NAT Network tree-widget item. */
+class UIItemNATNetwork : public QITreeWidgetItem, public UIDataNATNetwork
+{
+    Q_OBJECT;
+
+public:
+
+    /** Updates item fields from data. */
+    void updateFields();
+
+    /** Returns item name. */
+    QString name() const { return m_strName; }
 };
 
@@ -194,4 +222,33 @@
 
 /*********************************************************************************************************************************
+*   Class UIItemNATNetwork implementation.                                                                                       *
+*********************************************************************************************************************************/
+
+void UIItemNATNetwork::updateFields()
+{
+    /* Compose item fields: */
+    setCheckState(NATNetworkColumn_Availability, m_fEnabled ? Qt::Checked : Qt::Unchecked);
+    setText(NATNetworkColumn_Name, m_strName);
+
+    /* Compose tool-tip: */
+    const QString strTable("<table cellspacing=5>%1</table>");
+    const QString strHeader("<tr><td><nobr>%1:&nbsp;</nobr></td><td><nobr>%2</nobr></td></tr>");
+    const QString strSubHeader("<tr><td><nobr>&nbsp;&nbsp;%1:&nbsp;</nobr></td><td><nobr>%2</nobr></td></tr>");
+    QString strToolTip;
+
+    /* Network information: */
+    strToolTip += strHeader.arg(tr("Network Name"), m_strName);
+    strToolTip += strHeader.arg(tr("Network CIDR"), m_strCIDR);
+    strToolTip += strHeader.arg(tr("Supports DHCP"), m_fSupportsDHCP ? tr("yes") : tr("no"));
+    strToolTip += strHeader.arg(tr("Supports IPv6"), m_fSupportsIPv6 ? tr("yes") : tr("no"));
+    if (m_fSupportsIPv6 && m_fAdvertiseDefaultIPv6Route)
+        strToolTip += strSubHeader.arg(tr("Default IPv6 route"), tr("yes"));
+
+    /* Assign tool-tip finally: */
+    setToolTip(NATNetworkColumn_Name, strTable.arg(strToolTip));
+}
+
+
+/*********************************************************************************************************************************
 *   Class UINetworkManagerWidget implementation.                                                                                 *
 *********************************************************************************************************************************/
@@ -209,4 +266,8 @@
     , m_pTreeWidgetHostNetwork(0)
     , m_pDetailsWidgetHostNetwork(0)
+    , m_pTabNATNetwork(0)
+    , m_pLayoutNATNetwork(0)
+    , m_pTreeWidgetNATNetwork(0)
+    , m_pDetailsWidgetNATNetwork(0)
 {
     prepare();
@@ -234,5 +295,8 @@
     /* Translate tab-widget: */
     if (m_pTabWidget)
+    {
         m_pTabWidget->setTabText(0, UINetworkManager::tr("Host-only Networks"));
+        m_pTabWidget->setTabText(1, UINetworkManager::tr("NAT Networks"));
+    }
 
     /* Translate host network tree-widget: */
@@ -246,4 +310,13 @@
         m_pTreeWidgetHostNetwork->setHeaderLabels(fields);
     }
+
+    /* Translate NAT network tree-widget: */
+    if (m_pTreeWidgetNATNetwork)
+    {
+        const QStringList fields = QStringList()
+                                   << UINetworkManager::tr("Active")
+                                   << UINetworkManager::tr("Name");
+        m_pTreeWidgetNATNetwork->setHeaderLabels(fields);
+    }
 }
 
@@ -275,4 +348,5 @@
     {
         case TabWidgetIndex_HostNetwork: sltHandleCurrentItemChangeHostNetwork(); break;
+        case TabWidgetIndex_NATNetwork: sltHandleCurrentItemChangeNATNetwork(); break;
         default: break;
     }
@@ -288,4 +362,5 @@
     {
         case TabWidgetIndex_HostNetwork: sltApplyDetailsChangesHostNetwork(); break;
+        case TabWidgetIndex_NATNetwork: sltApplyDetailsChangesNATNetwork(); break;
         default: break;
     }
@@ -437,4 +512,134 @@
 }
 
+void UINetworkManagerWidget::sltCreateNATNetwork()
+{
+    /* For NAT networks only: */
+    if (m_pTabWidget->currentIndex() != TabWidgetIndex_NATNetwork)
+        return;
+
+    /* Compose a set of busy names: */
+    QSet<QString> names;
+    for (int i = 0; i < m_pTreeWidgetNATNetwork->topLevelItemCount(); ++i)
+        names << qobject_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->childItem(i))->name();
+    /* Compose a map of busy indexes: */
+    QMap<int, bool> presence;
+    const QString strNameTemplate("NatNetwork%1");
+    const QRegExp regExp(strNameTemplate.arg("([\\d]*)"));
+    foreach (const QString &strName, names)
+        if (regExp.indexIn(strName) != -1)
+            presence[regExp.cap(1).toInt()] = true;
+    /* Search for a minimum index: */
+    int iMinimumIndex = 0;
+    for (int i = 0; !presence.isEmpty() && i <= presence.lastKey() + 1; ++i)
+        if (!presence.contains(i))
+        {
+            iMinimumIndex = i;
+            break;
+        }
+    /* Compose resulting index and name: */
+    const QString strNetworkName = strNameTemplate.arg(iMinimumIndex == 0 ? QString() : QString::number(iMinimumIndex));
+
+    /* Compose new item data: */
+    UIDataNATNetwork oldData;
+    oldData.m_fExists = true;
+    oldData.m_fEnabled = true;
+    oldData.m_strName = strNetworkName;
+    oldData.m_strCIDR = "10.0.2.0/24";
+    oldData.m_fSupportsDHCP = true;
+    oldData.m_fSupportsIPv6 = false;
+    oldData.m_fAdvertiseDefaultIPv6Route = false;
+
+    /* Get VirtualBox for further activities: */
+    CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Create network: */
+    CNATNetwork comNetwork = comVBox.CreateNATNetwork(oldData.m_strName);
+
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotCreateNATNetwork(comVBox, this);
+    else
+    {
+        /* Save whether NAT network is enabled: */
+        if (comNetwork.isOk())
+            comNetwork.SetEnabled(oldData.m_fEnabled);
+        /* Save NAT network name: */
+        if (comNetwork.isOk())
+            comNetwork.SetNetworkName(oldData.m_strName);
+        /* Save NAT network CIDR: */
+        if (comNetwork.isOk())
+            comNetwork.SetNetwork(oldData.m_strCIDR);
+        /* Save whether NAT network needs DHCP server: */
+        if (comNetwork.isOk())
+            comNetwork.SetNeedDhcpServer(oldData.m_fSupportsDHCP);
+        /* Save whether NAT network supports IPv6: */
+        if (comNetwork.isOk())
+            comNetwork.SetIPv6Enabled(oldData.m_fSupportsIPv6);
+        /* Save whether NAT network should advertise default IPv6 route: */
+        if (comNetwork.isOk())
+            comNetwork.SetAdvertiseDefaultIPv6RouteEnabled(oldData.m_fAdvertiseDefaultIPv6Route);
+
+        /* Show error message if necessary: */
+        if (!comNetwork.isOk())
+            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
+
+        /* Add network to the tree: */
+        UIDataNATNetwork newData;
+        loadNATNetwork(comNetwork, newData);
+        createItemForNATNetwork(newData, true);
+
+        /* Adjust tree-widgets: */
+        sltAdjustTreeWidgets();
+    }
+}
+
+void UINetworkManagerWidget::sltRemoveNATNetwork()
+{
+    /* For NAT networks only: */
+    if (m_pTabWidget->currentIndex() != TabWidgetIndex_NATNetwork)
+        return;
+
+    /* Check NAT network tree-widget: */
+    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
+
+    /* Get network item: */
+    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
+    AssertMsgReturnVoid(pItem, ("Current item must not be null!\n"));
+
+    /* Get network name: */
+    const QString strNetworkName(pItem->name());
+
+    /* Confirm host network removal: */
+    if (!msgCenter().confirmNATNetworkRemoval(strNetworkName, this))
+        return;
+
+    /* Get VirtualBox for further activities: */
+    CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Find corresponding network: */
+    const CNATNetwork &comNetwork = comVBox.FindNATNetworkByName(strNetworkName);
+
+    /* Show error message if necessary: */
+    if (!comVBox.isOk() || comNetwork.isNull())
+        msgCenter().cannotFindNATNetwork(comVBox, strNetworkName, this);
+    else
+    {
+        /* Remove network finally: */
+        comVBox.RemoveNATNetwork(comNetwork);
+
+        /* Show error message if necessary: */
+        if (!comVBox.isOk())
+            msgCenter().cannotRemoveNATNetwork(comVBox, strNetworkName, this);
+        else
+        {
+            /* Remove interface from the tree: */
+            delete pItem;
+
+            /* Adjust tree-widgets: */
+            sltAdjustTreeWidgets();
+        }
+    }
+}
+
 void UINetworkManagerWidget::sltToggleDetailsVisibility(bool fVisible)
 {
@@ -446,8 +651,18 @@
         case TabWidgetIndex_HostNetwork:
         {
+            if (m_pDetailsWidgetNATNetwork)
+                m_pDetailsWidgetNATNetwork->setVisible(false);
             if (m_pDetailsWidgetHostNetwork)
                 m_pDetailsWidgetHostNetwork->setVisible(fVisible);
             break;
         }
+        case TabWidgetIndex_NATNetwork:
+        {
+            if (m_pDetailsWidgetHostNetwork)
+                m_pDetailsWidgetHostNetwork->setVisible(false);
+            if (m_pDetailsWidgetNATNetwork)
+                m_pDetailsWidgetNATNetwork->setVisible(fVisible);
+            break;
+        }
     }
     /* Notify external listeners: */
@@ -463,6 +678,16 @@
         case TabWidgetIndex_HostNetwork:
         {
+            if (m_pDetailsWidgetNATNetwork)
+                m_pDetailsWidgetNATNetwork->setVisible(false);
             if (m_pDetailsWidgetHostNetwork)
                 m_pDetailsWidgetHostNetwork->setVisible(fVisible);
+            break;
+        }
+        case TabWidgetIndex_NATNetwork:
+        {
+            if (m_pDetailsWidgetHostNetwork)
+                m_pDetailsWidgetHostNetwork->setVisible(false);
+            if (m_pDetailsWidgetNATNetwork)
+                m_pDetailsWidgetNATNetwork->setVisible(fVisible);
             break;
         }
@@ -495,4 +720,23 @@
         m_pTreeWidgetHostNetwork->setColumnWidth(HostNetworkColumn_DHCP, iWidth3);
         m_pTreeWidgetHostNetwork->setColumnWidth(HostNetworkColumn_Name, iTotal - iWidth1 - iWidth2 - iWidth3);
+    }
+
+    /* Check NAT network tree-widget: */
+    if (m_pTreeWidgetNATNetwork)
+    {
+        /* Get the tree-widget abstract interface: */
+        QAbstractItemView *pItemView = m_pTreeWidgetNATNetwork;
+        /* Get the tree-widget header-view: */
+        QHeaderView *pItemHeader = m_pTreeWidgetNATNetwork->header();
+
+        /* Calculate the total tree-widget width: */
+        const int iTotal = m_pTreeWidgetNATNetwork->viewport()->width();
+        /* Look for a minimum width hints for non-important columns: */
+        const int iMinWidth1 = qMax(pItemView->sizeHintForColumn(NATNetworkColumn_Availability), pItemHeader->sectionSizeHint(NATNetworkColumn_Availability));
+        /* Propose suitable width hints for non-important columns: */
+        const int iWidth1 = iMinWidth1 < iTotal / NATNetworkColumn_Max ? iMinWidth1 : iTotal / NATNetworkColumn_Max;
+        /* Apply the proposal: */
+        m_pTreeWidgetNATNetwork->setColumnWidth(NATNetworkColumn_Availability, iWidth1);
+        m_pTreeWidgetNATNetwork->setColumnWidth(NATNetworkColumn_Name, iTotal - iWidth1);
     }
 }
@@ -752,4 +996,208 @@
 }
 
+void UINetworkManagerWidget::sltHandleItemChangeNATNetwork(QTreeWidgetItem *pItem)
+{
+    /* Get network item: */
+    UIItemNATNetwork *pChangedItem = static_cast<UIItemNATNetwork*>(pItem);
+    AssertMsgReturnVoid(pChangedItem, ("Changed item must not be null!\n"));
+
+    /* Get item data: */
+    UIDataNATNetwork oldData = *pChangedItem;
+
+    /* Make sure network availability status changed: */
+    if (   (   oldData.m_fEnabled
+            && pChangedItem->checkState(NATNetworkColumn_Availability) == Qt::Checked)
+        || (   !oldData.m_fEnabled
+            && pChangedItem->checkState(NATNetworkColumn_Availability) == Qt::Unchecked))
+        return;
+
+    /* Get VirtualBox for further activities: */
+    CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Find corresponding network: */
+    CNATNetwork comNetwork = comVBox.FindNATNetworkByName(oldData.m_strName);
+
+    /* Show error message if necessary: */
+    if (!comVBox.isOk() || comNetwork.isNull())
+        msgCenter().cannotFindNATNetwork(comVBox, oldData.m_strName, this);
+    else
+    {
+        /* Save whether NAT network is enabled: */
+        if (comNetwork.isOk())
+            comNetwork.SetEnabled(!oldData.m_fEnabled);
+
+        /* Show error message if necessary: */
+        if (!comNetwork.isOk())
+            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
+        else
+        {
+            /* Update network in the tree: */
+            UIDataNATNetwork data;
+            loadNATNetwork(comNetwork, data);
+            updateItemForNATNetwork(data, true, pChangedItem);
+
+            /* Make sure current item fetched: */
+            sltHandleCurrentItemChangeNATNetwork();
+
+            /* Adjust tree-widgets: */
+            sltAdjustTreeWidgets();
+        }
+    }
+}
+
+void UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork()
+{
+    /* Check NAT network tree-widget: */
+    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
+
+    /* Get network item: */
+    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
+
+    /* Update actions availability: */
+    m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove)->setEnabled(pItem);
+    m_pActionPool->action(UIActionIndexMN_M_Network_T_Details)->setEnabled(pItem);
+
+    /* Check NAT network details-widget: */
+    AssertMsgReturnVoid(m_pDetailsWidgetNATNetwork, ("NAT network details-widget isn't created!\n"));
+
+    /* If there is an item => update details data: */
+    if (pItem)
+        m_pDetailsWidgetNATNetwork->setData(*pItem);
+    /* Otherwise => clear details: */
+    else
+        m_pDetailsWidgetNATNetwork->setData(UIDataNATNetwork());
+}
+
+void UINetworkManagerWidget::sltHandleContextMenuRequestNATNetwork(const QPoint &position)
+{
+    /* Check NAT network tree-widget: */
+    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
+
+    /* Compose temporary context-menu: */
+    QMenu menu;
+    if (m_pTreeWidgetNATNetwork->itemAt(position))
+    {
+        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove));
+        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_T_Details));
+    }
+    else
+    {
+        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create));
+//        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Network_S_Refresh));
+    }
+    /* And show it: */
+    menu.exec(m_pTreeWidgetNATNetwork->mapToGlobal(position));
+}
+
+void UINetworkManagerWidget::sltApplyDetailsChangesNATNetwork()
+{
+    /* Check NAT network tree-widget: */
+    AssertMsgReturnVoid(m_pTreeWidgetNATNetwork, ("NAT network tree-widget isn't created!\n"));
+
+    /* Get NAT network item: */
+    UIItemNATNetwork *pItem = static_cast<UIItemNATNetwork*>(m_pTreeWidgetNATNetwork->currentItem());
+    AssertMsgReturnVoid(pItem, ("Current item must not be null!\n"));
+
+    /* Check NAT network details-widget: */
+    AssertMsgReturnVoid(m_pDetailsWidgetNATNetwork, ("NAT network details-widget isn't created!\n"));
+
+    /* Get item data: */
+    UIDataNATNetwork oldData = *pItem;
+    UIDataNATNetwork newData = m_pDetailsWidgetNATNetwork->data();
+
+    /* Get VirtualBox for further activities: */
+    CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Find corresponding network: */
+    CNATNetwork comNetwork = comVBox.FindNATNetworkByName(oldData.m_strName);
+
+    /* Show error message if necessary: */
+    if (!comVBox.isOk() || comNetwork.isNull())
+        msgCenter().cannotFindNATNetwork(comVBox, oldData.m_strName, this);
+    else
+    {
+        /* Save whether NAT network is enabled: */
+        if (comNetwork.isOk() && newData.m_fEnabled != oldData.m_fEnabled)
+            comNetwork.SetEnabled(newData.m_fEnabled);
+        /* Save NAT network name: */
+        if (comNetwork.isOk() && newData.m_strName != oldData.m_strName)
+            comNetwork.SetNetworkName(newData.m_strName);
+        /* Save NAT network CIDR: */
+        if (comNetwork.isOk() && newData.m_strCIDR != oldData.m_strCIDR)
+            comNetwork.SetNetwork(newData.m_strCIDR);
+        /* Save whether NAT network needs DHCP server: */
+        if (comNetwork.isOk() && newData.m_fSupportsDHCP != oldData.m_fSupportsDHCP)
+            comNetwork.SetNeedDhcpServer(newData.m_fSupportsDHCP);
+        /* Save whether NAT network supports IPv6: */
+        if (comNetwork.isOk() && newData.m_fSupportsIPv6 != oldData.m_fSupportsIPv6)
+            comNetwork.SetIPv6Enabled(newData.m_fSupportsIPv6);
+        /* Save whether NAT network should advertise default IPv6 route: */
+        if (comNetwork.isOk() && newData.m_fAdvertiseDefaultIPv6Route != oldData.m_fAdvertiseDefaultIPv6Route)
+            comNetwork.SetAdvertiseDefaultIPv6RouteEnabled(newData.m_fAdvertiseDefaultIPv6Route);
+
+        /* Save IPv4 forwarding rules: */
+        if (comNetwork.isOk() && newData.m_rules4 != oldData.m_rules4)
+        {
+            UIPortForwardingDataList oldRules = oldData.m_rules4;
+
+            /* Remove rules to be removed: */
+            foreach (const UIDataPortForwardingRule &oldRule, oldData.m_rules4)
+                if (comNetwork.isOk() && !newData.m_rules4.contains(oldRule))
+                {
+                    comNetwork.RemovePortForwardRule(false /* IPv6? */, oldRule.name);
+                    oldRules.removeAll(oldRule);
+                }
+            /* Add rules to be added: */
+            foreach (const UIDataPortForwardingRule &newRule, newData.m_rules4)
+                if (comNetwork.isOk() && !oldRules.contains(newRule))
+                {
+                    comNetwork.AddPortForwardRule(false /* IPv6? */, newRule.name, newRule.protocol,
+                                                  newRule.hostIp, newRule.hostPort.value(),
+                                                  newRule.guestIp, newRule.guestPort.value());
+                    oldRules.append(newRule);
+                }
+        }
+        /* Save IPv6 forwarding rules: */
+        if (comNetwork.isOk() && newData.m_rules6 != oldData.m_rules6)
+        {
+            UIPortForwardingDataList oldRules = oldData.m_rules6;
+
+            /* Remove rules to be removed: */
+            foreach (const UIDataPortForwardingRule &oldRule, oldData.m_rules6)
+                if (comNetwork.isOk() && !newData.m_rules6.contains(oldRule))
+                {
+                    comNetwork.RemovePortForwardRule(true /* IPv6? */, oldRule.name);
+                    oldRules.removeAll(oldRule);
+                }
+            /* Add rules to be added: */
+            foreach (const UIDataPortForwardingRule &newRule, newData.m_rules6)
+                if (comNetwork.isOk() && !oldRules.contains(newRule))
+                {
+                    comNetwork.AddPortForwardRule(true /* IPv6? */, newRule.name, newRule.protocol,
+                                                  newRule.hostIp, newRule.hostPort.value(),
+                                                  newRule.guestIp, newRule.guestPort.value());
+                    oldRules.append(newRule);
+                }
+        }
+
+        /* Show error message if necessary: */
+        if (!comNetwork.isOk())
+            msgCenter().cannotSaveNATNetworkParameter(comNetwork, this);
+        else
+        {
+            /* Update network in the tree: */
+            UIDataNATNetwork data;
+            loadNATNetwork(comNetwork, data);
+            updateItemForNATNetwork(data, true, pItem);
+
+            /* Make sure current item fetched: */
+            sltHandleCurrentItemChangeNATNetwork();
+
+            /* Adjust tree-widgets: */
+            sltAdjustTreeWidgets();
+        }
+    }
+}
+
 void UINetworkManagerWidget::prepare()
 {
@@ -769,4 +1217,5 @@
     /* Load networks: */
     loadHostNetworks();
+    loadNATNetworks();
 }
 
@@ -782,6 +1231,10 @@
     connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create), &QAction::triggered,
             this, &UINetworkManagerWidget::sltCreateHostNetwork);
+    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Create), &QAction::triggered,
+            this, &UINetworkManagerWidget::sltCreateNATNetwork);
     connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove), &QAction::triggered,
             this, &UINetworkManagerWidget::sltRemoveHostNetwork);
+    connect(m_pActionPool->action(UIActionIndexMN_M_Network_S_Remove), &QAction::triggered,
+            this, &UINetworkManagerWidget::sltRemoveNATNetwork);
     connect(m_pActionPool->action(UIActionIndexMN_M_Network_T_Details), &QAction::toggled,
             this, &UINetworkManagerWidget::sltToggleDetailsVisibility);
@@ -811,4 +1264,5 @@
         /* Prepare details widgets: */
         prepareDetailsWidgetHostNetwork();
+        prepareDetailsWidgetNATNetwork();
     }
 }
@@ -852,4 +1306,5 @@
 
         prepareTabHostNetwork();
+        prepareTabNATNetwork();
 
         /* Add into layout: */
@@ -922,4 +1377,68 @@
 }
 
+void UINetworkManagerWidget::prepareTabNATNetwork()
+{
+    /* Prepare NAT network tab: */
+    m_pTabNATNetwork = new QWidget(m_pTabWidget);
+    if (m_pTabNATNetwork)
+    {
+        /* Prepare NAT network layout: */
+        m_pLayoutNATNetwork = new QVBoxLayout(m_pTabNATNetwork);
+        if (m_pLayoutNATNetwork)
+            prepareTreeWidgetNATNetwork();
+
+        /* Add into tab-widget: */
+        m_pTabWidget->insertTab(TabWidgetIndex_NATNetwork, m_pTabNATNetwork, QString());
+    }
+}
+
+void UINetworkManagerWidget::prepareTreeWidgetNATNetwork()
+{
+    /* Prepare NAT network tree-widget: */
+    m_pTreeWidgetNATNetwork = new QITreeWidget(m_pTabNATNetwork);
+    if (m_pTreeWidgetNATNetwork)
+    {
+        m_pTreeWidgetNATNetwork->setRootIsDecorated(false);
+        m_pTreeWidgetNATNetwork->setAlternatingRowColors(true);
+        m_pTreeWidgetNATNetwork->setContextMenuPolicy(Qt::CustomContextMenu);
+        m_pTreeWidgetNATNetwork->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+        m_pTreeWidgetNATNetwork->setColumnCount(NATNetworkColumn_Max);
+        m_pTreeWidgetNATNetwork->setSortingEnabled(true);
+        m_pTreeWidgetNATNetwork->sortByColumn(NATNetworkColumn_Name, Qt::AscendingOrder);
+        m_pTreeWidgetNATNetwork->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
+        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::currentItemChanged,
+                this, &UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork);
+        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::customContextMenuRequested,
+                this, &UINetworkManagerWidget::sltHandleContextMenuRequestNATNetwork);
+        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::itemChanged,
+                this, &UINetworkManagerWidget::sltHandleItemChangeNATNetwork);
+        connect(m_pTreeWidgetNATNetwork, &QITreeWidget::itemDoubleClicked,
+                m_pActionPool->action(UIActionIndexMN_M_Network_T_Details), &QAction::setChecked);
+
+        /* Add into layout: */
+        m_pLayoutNATNetwork->addWidget(m_pTreeWidgetNATNetwork);
+    }
+}
+
+void UINetworkManagerWidget::prepareDetailsWidgetNATNetwork()
+{
+    /* Prepare NAT network details-widget: */
+    m_pDetailsWidgetNATNetwork = new UIDetailsWidgetNATNetwork(m_enmEmbedding, this);
+    if (m_pDetailsWidgetNATNetwork)
+    {
+        m_pDetailsWidgetNATNetwork->setVisible(false);
+        m_pDetailsWidgetNATNetwork->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChanged,
+                this, &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork);
+        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChangeRejected,
+                this, &UINetworkManagerWidget::sltHandleCurrentItemChangeNATNetwork);
+        connect(m_pDetailsWidgetNATNetwork, &UIDetailsWidgetNATNetwork::sigDataChangeAccepted,
+                this, &UINetworkManagerWidget::sltApplyDetailsChangesNATNetwork);
+
+        /* Add into layout: */
+        layout()->addWidget(m_pDetailsWidgetNATNetwork);
+    }
+}
+
 void UINetworkManagerWidget::loadSettings()
 {
@@ -973,4 +1492,6 @@
 {
     /* Gather interface settings: */
+    if (comInterface.isNotNull())
+        data.m_interface.m_fExists = true;
     if (comInterface.isOk())
         data.m_interface.m_strName = comInterface.GetName();
@@ -1028,4 +1549,114 @@
 }
 
+void UINetworkManagerWidget::loadNATNetworks()
+{
+    /* Check NAT network tree-widget: */
+    if (!m_pTreeWidgetNATNetwork)
+        return;
+
+    /* Clear tree first of all: */
+    m_pTreeWidgetNATNetwork->clear();
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get interfaces for further activities: */
+    const QVector<CNATNetwork> networks = comVBox.GetNATNetworks();
+
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireNATNetworks(comVBox, this);
+    else
+    {
+        /* For each NAT network => load it to the tree: */
+        foreach (const CNATNetwork &comNetwork, networks)
+        {
+            UIDataNATNetwork data;
+            loadNATNetwork(comNetwork, data);
+            createItemForNATNetwork(data, false);
+        }
+
+        /* Choose the 1st item as current initially: */
+        m_pTreeWidgetNATNetwork->setCurrentItem(m_pTreeWidgetNATNetwork->topLevelItem(0));
+        sltHandleCurrentItemChangeNATNetwork();
+
+        /* Adjust tree-widgets: */
+        sltAdjustTreeWidgets();
+    }
+}
+
+void UINetworkManagerWidget::loadNATNetwork(const CNATNetwork &comNetwork, UIDataNATNetwork &data)
+{
+    /* Gather network settings: */
+    if (comNetwork.isNotNull())
+        data.m_fExists = true;
+    if (comNetwork.isOk())
+        data.m_fEnabled = comNetwork.GetEnabled();
+    if (comNetwork.isOk())
+        data.m_strName = comNetwork.GetNetworkName();
+    if (comNetwork.isOk())
+        data.m_strCIDR = comNetwork.GetNetwork();
+    if (comNetwork.isOk())
+        data.m_fSupportsDHCP = comNetwork.GetNeedDhcpServer();
+    if (comNetwork.isOk())
+        data.m_fSupportsIPv6 = comNetwork.GetIPv6Enabled();
+    if (comNetwork.isOk())
+        data.m_fAdvertiseDefaultIPv6Route = comNetwork.GetAdvertiseDefaultIPv6RouteEnabled();
+
+    /* Gather forwarding rules: */
+    if (comNetwork.isOk())
+    {
+        /* Load IPv4 rules: */
+        foreach (QString strIPv4Rule, comNetwork.GetPortForwardRules4())
+        {
+            /* Replace all ':' with ',' first: */
+            strIPv4Rule.replace(':', ',');
+            /* Parse rules: */
+            QStringList rules = strIPv4Rule.split(',');
+            Assert(rules.size() == 6);
+            if (rules.size() != 6)
+                continue;
+            data.m_rules4 << UIDataPortForwardingRule(rules.at(0),
+                                                      gpConverter->fromInternalString<KNATProtocol>(rules.at(1)),
+                                                      QString(rules.at(2)).remove('[').remove(']'),
+                                                      rules.at(3).toUInt(),
+                                                      QString(rules.at(4)).remove('[').remove(']'),
+                                                      rules.at(5).toUInt());
+        }
+
+        /* Load IPv6 rules: */
+        foreach (QString strIPv6Rule, comNetwork.GetPortForwardRules6())
+        {
+            /* Replace all ':' with ',' first: */
+            strIPv6Rule.replace(':', ',');
+            /* But replace ',' back with ':' for addresses: */
+            QRegExp re("\\[[0-9a-fA-F,]*,[0-9a-fA-F,]*\\]");
+            re.setMinimal(true);
+            while (re.indexIn(strIPv6Rule) != -1)
+            {
+                QString strCapOld = re.cap(0);
+                QString strCapNew = strCapOld;
+                strCapNew.replace(',', ':');
+                strIPv6Rule.replace(strCapOld, strCapNew);
+            }
+            /* Parse rules: */
+            QStringList rules = strIPv6Rule.split(',');
+            Assert(rules.size() == 6);
+            if (rules.size() != 6)
+                continue;
+            data.m_rules6 << UIDataPortForwardingRule(rules.at(0),
+                                                      gpConverter->fromInternalString<KNATProtocol>(rules.at(1)),
+                                                      QString(rules.at(2)).remove('[').remove(']'),
+                                                      rules.at(3).toUInt(),
+                                                      QString(rules.at(4)).remove('[').remove(']'),
+                                                      rules.at(5).toUInt());
+        }
+    }
+
+    /* Show error message if necessary: */
+    if (!comNetwork.isOk())
+        msgCenter().cannotAcquireNATNetworkParameter(comNetwork, this);
+}
+
 void UINetworkManagerWidget::createItemForHostNetwork(const UIDataHostNetwork &data, bool fChooseItem)
 {
@@ -1056,4 +1687,35 @@
         if (fChooseItem)
             m_pTreeWidgetHostNetwork->setCurrentItem(pItem);
+    }
+}
+
+void UINetworkManagerWidget::createItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem)
+{
+    /* Create new item: */
+    UIItemNATNetwork *pItem = new UIItemNATNetwork;
+    if (pItem)
+    {
+        /* Configure item: */
+        pItem->UIDataNATNetwork::operator=(data);
+        pItem->updateFields();
+        /* Add item to the tree: */
+        m_pTreeWidgetNATNetwork->addTopLevelItem(pItem);
+        /* And choose it as current if necessary: */
+        if (fChooseItem)
+            m_pTreeWidgetNATNetwork->setCurrentItem(pItem);
+    }
+}
+
+void UINetworkManagerWidget::updateItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem, UIItemNATNetwork *pItem)
+{
+    /* Update passed item: */
+    if (pItem)
+    {
+        /* Configure item: */
+        pItem->UIDataNATNetwork::operator=(data);
+        pItem->updateFields();
+        /* And choose it as current if necessary: */
+        if (fChooseItem)
+            m_pTreeWidgetNATNetwork->setCurrentItem(pItem);
     }
 }
@@ -1161,4 +1823,8 @@
     connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedHostNetwork,
             button(ButtonType_Reset), &QPushButton::setEnabled);
+    connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork,
+            button(ButtonType_Apply), &QPushButton::setEnabled);
+    connect(widget(), &UINetworkManagerWidget::sigDetailsDataChangedNATNetwork,
+            button(ButtonType_Reset), &QPushButton::setEnabled);
     connect(buttonBox(), &QIDialogButtonBox::clicked,
             this, &UINetworkManager::sltHandleButtonBoxClick);
Index: /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.h	(revision 87275)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/networkmanager/UINetworkManager.h	(revision 87276)
@@ -31,4 +31,5 @@
 /* Forward declarations: */
 class CHostNetworkInterface;
+class CNATNetwork;
 class QAbstractButton;
 class QTreeWidgetItem;
@@ -39,7 +40,10 @@
 class UIActionPool;
 class UIDetailsWidgetHostNetwork;
+class UIDetailsWidgetNATNetwork;
 class UIItemHostNetwork;
+class UIItemNATNetwork;
 class QIToolBar;
 struct UIDataHostNetwork;
+struct UIDataNATNetwork;
 
 
@@ -56,4 +60,7 @@
     /** Notifies listeners about host network details data @a fDiffers. */
     void sigDetailsDataChangedHostNetwork(bool fDiffers);
+
+    /** Notifies listeners about NAT network details data @a fDiffers. */
+    void sigDetailsDataChangedNATNetwork(bool fDiffers);
 
 public:
@@ -106,4 +113,9 @@
         /** Handles command to remove host network. */
         void sltRemoveHostNetwork();
+
+        /** Handles command to create NAT network. */
+        void sltCreateNATNetwork();
+        /** Handles command to remove NAT network. */
+        void sltRemoveNATNetwork();
 
         /** Handles command to make details @a fVisible. */
@@ -127,4 +139,13 @@
         /** Handles command to apply host network details changes. */
         void sltApplyDetailsChangesHostNetwork();
+
+        /** Handles NAT network tree-widget @a pItem change. */
+        void sltHandleItemChangeNATNetwork(QTreeWidgetItem *pItem);
+        /** Handles NAT network tree-widget current item change. */
+        void sltHandleCurrentItemChangeNATNetwork();
+        /** Handles NAT network context-menu request for tree-widget @a position. */
+        void sltHandleContextMenuRequestNATNetwork(const QPoint &position);
+        /** Handles command to apply NAT network details changes. */
+        void sltApplyDetailsChangesNATNetwork();
     /** @} */
 
@@ -149,4 +170,10 @@
         /** Prepares host network details-widget. */
         void prepareDetailsWidgetHostNetwork();
+        /** Prepares NAT network tab. */
+        void prepareTabNATNetwork();
+        /** Prepares NAT network tree-widget. */
+        void prepareTreeWidgetNATNetwork();
+        /** Prepares NAT network details-widget. */
+        void prepareDetailsWidgetNATNetwork();
         /** Load settings: */
         void loadSettings();
@@ -159,4 +186,9 @@
         /** Loads host @a comInterface data to passed @a data container. */
         void loadHostNetwork(const CHostNetworkInterface &comInterface, UIDataHostNetwork &data);
+
+        /** Loads NAT networks. */
+        void loadNATNetworks();
+        /** Loads NAT @a comNetwork data to passed @a data container. */
+        void loadNATNetwork(const CNATNetwork &comNetwork, UIDataNATNetwork &data);
     /** @} */
 
@@ -167,4 +199,9 @@
         /** Updates passed host network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
         void updateItemForHostNetwork(const UIDataHostNetwork &data, bool fChooseItem, UIItemHostNetwork *pItem);
+
+        /** Creates a new NAT network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
+        void createItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem);
+        /** Updates passed NAT network tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
+        void updateItemForNATNetwork(const UIDataNATNetwork &data, bool fChooseItem, UIItemNATNetwork *pItem);
     /** @} */
 
@@ -198,4 +235,13 @@
         /** Holds the host network details-widget instance. */
         UIDetailsWidgetHostNetwork *m_pDetailsWidgetHostNetwork;
+
+        /** Holds the NAT network tab. */
+        QWidget                   *m_pTabNATNetwork;
+        /** Holds the NAT network tab layout. */
+        QVBoxLayout               *m_pLayoutNATNetwork;
+        /** Holds the NAT network tree-widget instance. */
+        QITreeWidget              *m_pTreeWidgetNATNetwork;
+        /** Holds the NAT network details-widget instance. */
+        UIDetailsWidgetNATNetwork *m_pDetailsWidgetNATNetwork;
     /** @} */
 };
