Index: trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 48531)
+++ trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 48533)
@@ -386,4 +386,5 @@
 	src/widgets/UIPopupStack.h \
 	src/widgets/UIPopupStackViewport.h \
+	src/widgets/UIPortForwardingTable.h \
 	src/widgets/UIProgressDialog.h \
 	src/widgets/UISpacerWidgets.h \
@@ -458,8 +459,8 @@
 	src/selector/UIVMDesktop.cpp \
 	src/settings/UISettingsDialogSpecific.cpp \
-	src/settings/machine/UIMachineSettingsPortForwardingDlg.cpp \
 	src/settings/machine/UIMachineSettingsStorage.cpp \
 	src/settings/machine/UIMachineSettingsUSB.cpp \
 	src/widgets/UIHotKeyEditor.cpp \
+	src/widgets/UIPortForwardingTable.cpp \
 	src/wizards/importappliance/UIWizardImportApp.cpp
 
@@ -640,4 +641,5 @@
 	src/widgets/UIPopupStack.cpp \
 	src/widgets/UIPopupStackViewport.cpp \
+	src/widgets/UIPortForwardingTable.cpp \
 	src/widgets/UIProgressDialog.cpp \
 	src/widgets/UISpecialControls.cpp \
Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.cpp	(revision 48531)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.cpp	(revision 48533)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -19,624 +19,45 @@
 
 /* Qt includes: */
-#include <QHBoxLayout>
-#include <QMenu>
-#include <QAction>
-#include <QHeaderView>
+#include <QVBoxLayout>
 #include <QPushButton>
-#include <QStyledItemDelegate>
-#include <QItemEditorFactory>
-#include <QComboBox>
-#include <QLineEdit>
-#include <QSpinBox>
-#include <QTimer>
 
 /* GUI includes: */
 #include "UIMachineSettingsPortForwardingDlg.h"
-#include "UIMessageCenter.h"
-#include "UIToolBar.h"
-#include "QITableView.h"
+#include "UIIconPool.h"
 #include "QIDialogButtonBox.h"
-#include "UIIconPool.h"
-#include "UIConverter.h"
 
-/* Other VBox includes: */
-#include <iprt/cidr.h>
-
-/* External includes: */
-#include <math.h>
-
-/* IP validator: */
-class IPValidator : public QValidator
+UIMachineSettingsPortForwardingDlg::UIMachineSettingsPortForwardingDlg(QWidget *pParent,
+                                                                       const UIPortForwardingDataList &rules)
+    : QIWithRetranslateUI<QIDialog>(pParent)
+    , m_pTable(0)
+    , m_pButtonBox(0)
 {
-    Q_OBJECT;
-
-public:
-
-    IPValidator(QObject *pParent) : QValidator(pParent) {}
-    ~IPValidator() {}
-
-    QValidator::State validate(QString &strInput, int & /* iPos */) const
-    {
-        QString strStringToValidate(strInput);
-        strStringToValidate.remove(' ');
-        QString strDot("\\.");
-        QString strDigits("(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)");
-        QRegExp intRegExp(QString("^(%1?(%2(%1?(%2(%1?(%2%1?)?)?)?)?)?)?$").arg(strDigits).arg(strDot));
-        RTNETADDRIPV4 Network, Mask;
-        if (strStringToValidate == "..." || RTCidrStrToIPv4(strStringToValidate.toLatin1().constData(), &Network, &Mask) == VINF_SUCCESS)
-            return QValidator::Acceptable;
-        else if (intRegExp.indexIn(strStringToValidate) != -1)
-            return QValidator::Intermediate;
-        else
-            return QValidator::Invalid;
-    }
-};
-
-/* Name editor: */
-class NameEditor : public QLineEdit
-{
-    Q_OBJECT;
-    Q_PROPERTY(NameData name READ name WRITE setName USER true);
-
-public:
-
-    NameEditor(QWidget *pParent = 0) : QLineEdit(pParent)
-    {
-        setFrame(false);
-        setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
-        setValidator(new QRegExpValidator(QRegExp("[^,]*"), this));
-    }
-
-private:
-
-    void setName(NameData name)
-    {
-        setText(name);
-    }
-
-    NameData name() const
-    {
-        return text();
-    }
-};
-
-/* Protocol editor: */
-class ProtocolEditor : public QComboBox
-{
-    Q_OBJECT;
-    Q_PROPERTY(KNATProtocol protocol READ protocol WRITE setProtocol USER true);
-
-public:
-
-    ProtocolEditor(QWidget *pParent = 0) : QComboBox(pParent)
-    {
-        addItem(gpConverter->toString(KNATProtocol_UDP), QVariant::fromValue(KNATProtocol_UDP));
-        addItem(gpConverter->toString(KNATProtocol_TCP), QVariant::fromValue(KNATProtocol_TCP));
-    }
-
-private:
-
-    void setProtocol(KNATProtocol p)
-    {
-        for (int i = 0; i < count(); ++i)
-        {
-            if (itemData(i).value<KNATProtocol>() == p)
-            {
-                setCurrentIndex(i);
-                break;
-            }
-        }
-    }
-
-    KNATProtocol protocol() const
-    {
-        return itemData(currentIndex()).value<KNATProtocol>();
-    }
-};
-
-/* IP editor: */
-class IPEditor : public QLineEdit
-{
-    Q_OBJECT;
-    Q_PROPERTY(IpData ip READ ip WRITE setIp USER true);
-
-public:
-
-    IPEditor(QWidget *pParent = 0) : QLineEdit(pParent)
-    {
-        setFrame(false);
-        setAlignment(Qt::AlignCenter);
-        setValidator(new IPValidator(this));
-        setInputMask("000.000.000.000");
-    }
-
-private:
-
-    void setIp(IpData ip)
-    {
-        setText(ip);
-    }
-
-    IpData ip() const
-    {
-        return text() == "..." ? QString() : text();
-    }
-};
-
-/* Port editor: */
-class PortEditor : public QSpinBox
-{
-    Q_OBJECT;
-    Q_PROPERTY(PortData port READ port WRITE setPort USER true);
-
-public:
-
-    PortEditor(QWidget *pParent = 0) : QSpinBox(pParent)
-    {
-        setFrame(false);
-        setRange(0, (1 << (8 * sizeof(ushort))) - 1);
-    }
-
-private:
-
-    void setPort(PortData port)
-    {
-        setValue(port.value());
-    }
-
-    PortData port() const
-    {
-        return value();
-    }
-};
-
-/* Port forwarding data model: */
-class UIPortForwardingModel : public QAbstractTableModel
-{
-    Q_OBJECT;
-
-public:
-
-    /* Column names: */
-    enum UIPortForwardingDataType
-    {
-        UIPortForwardingDataType_Name,
-        UIPortForwardingDataType_Protocol,
-        UIPortForwardingDataType_HostIp,
-        UIPortForwardingDataType_HostPort,
-        UIPortForwardingDataType_GuestIp,
-        UIPortForwardingDataType_GuestPort,
-        UIPortForwardingDataType_Max
-    };
-
-    /* Port forwarding model constructor: */
-    UIPortForwardingModel(QObject *pParent = 0, const UIPortForwardingDataList &rules = UIPortForwardingDataList())
-        : QAbstractTableModel(pParent), m_dataList(rules) {}
-    /* Port forwarding model destructor: */
-    ~UIPortForwardingModel() {}
-
-    /* The list of chosen rules: */
-    const UIPortForwardingDataList& rules() const
-    {
-        return m_dataList;
-    }
-
-    /* Flags for model indexes: */
-    Qt::ItemFlags flags(const QModelIndex &index) const
-    {
-        /* Check index validness: */
-        if (!index.isValid())
-            return Qt::NoItemFlags;
-        /* All columns have similar flags: */
-        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
-    }
-
-    /* Row count getter: */
-    int rowCount(const QModelIndex & parent = QModelIndex()) const
-    {
-        Q_UNUSED(parent);
-        return m_dataList.size();
-    }
-
-    /* Column count getter: */
-    int columnCount(const QModelIndex & parent = QModelIndex()) const
-    {
-        Q_UNUSED(parent);
-        return UIPortForwardingDataType_Max;
-    }
-
-    /* Get header data: */
-    QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const
-    {
-        /* Display role for horizontal header: */
-        if (iRole == Qt::DisplayRole && orientation == Qt::Horizontal)
-        {
-            /* Switch for different columns: */
-            switch (iSection)
-            {
-                case UIPortForwardingDataType_Name: return tr("Name");
-                case UIPortForwardingDataType_Protocol: return tr("Protocol");
-                case UIPortForwardingDataType_HostIp: return tr("Host IP");
-                case UIPortForwardingDataType_HostPort: return tr("Host Port");
-                case UIPortForwardingDataType_GuestIp: return tr("Guest IP");
-                case UIPortForwardingDataType_GuestPort: return tr("Guest Port");
-                default: break;
-            }
-        }
-        /* Return wrong value: */
-        return QVariant();
-    }
-
-    /* Get index data: */
-    QVariant data(const QModelIndex &index, int iRole) const
-    {
-        /* Check index validness: */
-        if (!index.isValid())
-            return QVariant();
-        /* Switch for different roles: */
-        switch (iRole)
-        {
-            /* Display role: */
-            case Qt::DisplayRole:
-            {
-                /* Switch for different columns: */
-                switch (index.column())
-                {
-                    case UIPortForwardingDataType_Name: return m_dataList[index.row()].name;
-                    case UIPortForwardingDataType_Protocol: return gpConverter->toString(m_dataList[index.row()].protocol);
-                    case UIPortForwardingDataType_HostIp: return m_dataList[index.row()].hostIp;
-                    case UIPortForwardingDataType_HostPort: return m_dataList[index.row()].hostPort.value();
-                    case UIPortForwardingDataType_GuestIp: return m_dataList[index.row()].guestIp;
-                    case UIPortForwardingDataType_GuestPort: return m_dataList[index.row()].guestPort.value();
-                    default: return QVariant();
-                }
-            }
-            /* Edit role: */
-            case Qt::EditRole:
-            {
-                /* Switch for different columns: */
-                switch (index.column())
-                {
-                    case UIPortForwardingDataType_Name: return QVariant::fromValue(m_dataList[index.row()].name);
-                    case UIPortForwardingDataType_Protocol: return QVariant::fromValue(m_dataList[index.row()].protocol);
-                    case UIPortForwardingDataType_HostIp: return QVariant::fromValue(m_dataList[index.row()].hostIp);
-                    case UIPortForwardingDataType_HostPort: return QVariant::fromValue(m_dataList[index.row()].hostPort);
-                    case UIPortForwardingDataType_GuestIp: return QVariant::fromValue(m_dataList[index.row()].guestIp);
-                    case UIPortForwardingDataType_GuestPort: return QVariant::fromValue(m_dataList[index.row()].guestPort);
-                    default: return QVariant();
-                }
-            }
-            /* Alignment role: */
-            case Qt::TextAlignmentRole:
-            {
-                /* Switch for different columns: */
-                switch (index.column())
-                {
-                    case UIPortForwardingDataType_Name:
-                    case UIPortForwardingDataType_Protocol:
-                    case UIPortForwardingDataType_HostPort:
-                    case UIPortForwardingDataType_GuestPort:
-                        return (int)(Qt::AlignLeft | Qt::AlignVCenter);
-                    case UIPortForwardingDataType_HostIp:
-                    case UIPortForwardingDataType_GuestIp:
-                        return Qt::AlignCenter;
-                    default: return QVariant();
-                }
-            }
-            case Qt::SizeHintRole:
-            {
-                /* Switch for different columns: */
-                switch (index.column())
-                {
-                    case UIPortForwardingDataType_HostIp:
-                    case UIPortForwardingDataType_GuestIp:
-                        return QSize(QApplication::fontMetrics().width(" 888.888.888.888 "), QApplication::fontMetrics().height());
-                    default: return QVariant();
-                }
-            }
-            default: break;
-        }
-        /* Return wrong value: */
-        return QVariant();
-    }
-
-    /* Set index data: */
-    bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole)
-    {
-        /* Check index validness: */
-        if (!index.isValid() || iRole != Qt::EditRole)
-            return false;
-        /* Switch for different columns: */
-        switch (index.column())
-        {
-            case UIPortForwardingDataType_Name:
-                m_dataList[index.row()].name = value.value<NameData>();
-                emit dataChanged(index, index);
-                return true;
-            case UIPortForwardingDataType_Protocol:
-                m_dataList[index.row()].protocol = value.value<KNATProtocol>();
-                emit dataChanged(index, index);
-                return true;
-            case UIPortForwardingDataType_HostIp:
-                m_dataList[index.row()].hostIp = value.value<IpData>();
-                emit dataChanged(index, index);
-                return true;
-            case UIPortForwardingDataType_HostPort:
-                m_dataList[index.row()].hostPort = value.value<PortData>();
-                emit dataChanged(index, index);
-                return true;
-            case UIPortForwardingDataType_GuestIp:
-                m_dataList[index.row()].guestIp = value.value<IpData>();
-                emit dataChanged(index, index);
-                return true;
-            case UIPortForwardingDataType_GuestPort:
-                m_dataList[index.row()].guestPort = value.value<PortData>();
-                emit dataChanged(index, index);
-                return true;
-            default: return false;
-        }
-        /* Return false value: */
-        return false;
-    }
-
-    /* Add/Copy rule: */
-    void addRule(const QModelIndex &index)
-    {
-        beginInsertRows(QModelIndex(), m_dataList.size(), m_dataList.size());
-        /* Search for existing "Rule [NUMBER]" record: */
-        uint uMaxIndex = 0;
-        QString strTemplate("Rule %1");
-        QRegExp regExp(strTemplate.arg("(\\d+)"));
-        for (int i = 0; i < m_dataList.size(); ++i)
-            if (regExp.indexIn(m_dataList[i].name) > -1)
-                uMaxIndex = regExp.cap(1).toUInt() > uMaxIndex ? regExp.cap(1).toUInt() : uMaxIndex;
-        /* If index is valid => copy data: */
-        if (index.isValid())
-            m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), m_dataList[index.row()].protocol,
-                                               m_dataList[index.row()].hostIp, m_dataList[index.row()].hostPort,
-                                               m_dataList[index.row()].guestIp, m_dataList[index.row()].guestPort);
-        /* If index is NOT valid => use default values: */
-        else
-            m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), KNATProtocol_TCP,
-                                               QString(""), 0, QString(""), 0);
-        endInsertRows();
-    }
-
-    /* Delete rule: */
-    void delRule(const QModelIndex &index)
-    {
-        if (!index.isValid())
-            return;
-        beginRemoveRows(QModelIndex(), index.row(), index.row());
-        m_dataList.removeAt(index.row());
-        endRemoveRows();
-    }
-
-private:
-
-    /* Data container: */
-    UIPortForwardingDataList m_dataList;
-};
-
-/* Port forwarding dialog constructor: */
-UIMachineSettingsPortForwardingDlg::UIMachineSettingsPortForwardingDlg(QWidget *pParent,
-                                                                 const UIPortForwardingDataList &rules)
-    : QIWithRetranslateUI<QIDialog>(pParent)
-    , fIsTableDataChanged(false)
-    , m_pTableView(0)
-    , m_pToolBar(0)
-    , m_pButtonBox(0)
-    , m_pModel(0)
-    , m_pAddAction(0)
-    , m_pCopyAction(0)
-    , m_pDelAction(0)
-{
-#ifdef Q_WS_MAC
-    setWindowFlags(Qt::Sheet);
-#endif /* Q_WS_MAC */
-
     /* Set dialog icon: */
     setWindowIcon(UIIconPool::iconSetFull(QSize(32, 32), QSize(16, 16), ":/nw_32px.png", ":/nw_16px.png"));
 
-    /* Create table: */
-    m_pTableView = new QITableView(this);
-    m_pTableView->setTabKeyNavigation(false);
-    m_pTableView->verticalHeader()->hide();
-    m_pTableView->verticalHeader()->setDefaultSectionSize((int)(m_pTableView->verticalHeader()->minimumSectionSize() * 1.33));
-    m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
-    m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
-    m_pTableView->installEventFilter(this);
-    connect(m_pTableView, SIGNAL(sigCurrentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(sltCurrentChanged()));
-    connect(m_pTableView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(sltShowTableContexMenu(const QPoint &)));
-
-    /* Create actions: */
-    m_pAddAction = new QAction(this);
-    m_pCopyAction = new QAction(this);
-    m_pDelAction = new QAction(this);
-    m_pAddAction->setShortcut(QKeySequence("Ins"));
-    m_pDelAction->setShortcut(QKeySequence("Del"));
-    m_pAddAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
-    m_pCopyAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
-    m_pDelAction->setIcon(UIIconPool::iconSet(":/controller_remove_16px.png", ":/controller_remove_disabled_16px.png"));
-    connect(m_pAddAction, SIGNAL(triggered(bool)), this, SLOT(sltAddRule()));
-    connect(m_pCopyAction, SIGNAL(triggered(bool)), this, SLOT(sltCopyRule()));
-    connect(m_pDelAction, SIGNAL(triggered(bool)), this, SLOT(sltDelRule()));
-
-    /* Create toolbar: */
-    m_pToolBar = new UIToolBar(this);
-    m_pToolBar->setIconSize(QSize(16, 16));
-    m_pToolBar->setOrientation(Qt::Vertical);
-    m_pToolBar->addAction(m_pAddAction);
-    m_pToolBar->addAction(m_pDelAction);
-
-    /* Create table & toolbar layout: */
-    QHBoxLayout *pTableAndToolbarLayout = new QHBoxLayout;
-    pTableAndToolbarLayout->setSpacing(1);
-    pTableAndToolbarLayout->addWidget(m_pTableView);
-    pTableAndToolbarLayout->addWidget(m_pToolBar);
-
-    /* Create buttonbox: */
-    m_pButtonBox = new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
-    connect(m_pButtonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
-    connect(m_pButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
-
-    /* Create main layout: */
-    QVBoxLayout *pMainLayout = new QVBoxLayout;
-    this->setLayout(pMainLayout);
-    pMainLayout->addLayout(pTableAndToolbarLayout);
-    pMainLayout->addWidget(m_pButtonBox);
-
-    /* Create model: */
-    m_pModel = new UIPortForwardingModel(this, rules);
-    connect(m_pModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(sltTableDataChanged()));
-    connect(m_pModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(sltTableDataChanged()));
-    connect(m_pModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(sltTableDataChanged()));
-    m_pTableView->setModel(m_pModel);
-
-    /* Register delegates editors: */
-    if (QAbstractItemDelegate *pAbstractItemDelegate = m_pTableView->itemDelegate())
+    /* Create layout: */
+    QVBoxLayout *pMainLayout = new QVBoxLayout(this);
     {
-        if (QStyledItemDelegate *pStyledItemDelegate = qobject_cast<QStyledItemDelegate*>(pAbstractItemDelegate))
+        /* Create table: */
+        m_pTable = new UIPortForwardingTable(rules);
+        /* Create button-box: */
+        m_pButtonBox = new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
         {
-            /* Create new item editor factory: */
-            QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory;
-
-            /* Register name type: */
-            int iNameId = qRegisterMetaType<NameData>();
-            /* Register name editor: */
-            QStandardItemEditorCreator<NameEditor> *pNameEditorItemCreator = new QStandardItemEditorCreator<NameEditor>();
-            /* Link name type & editor: */
-            pNewItemEditorFactory->registerEditor((QVariant::Type)iNameId, pNameEditorItemCreator);
-
-            /* Register protocol type: */
-            int iProtocolId = qRegisterMetaType<KNATProtocol>();
-            /* Register protocol editor: */
-            QStandardItemEditorCreator<ProtocolEditor> *pProtocolEditorItemCreator = new QStandardItemEditorCreator<ProtocolEditor>();
-            /* Link protocol type & editor: */
-            pNewItemEditorFactory->registerEditor((QVariant::Type)iProtocolId, pProtocolEditorItemCreator);
-
-            /* Register ip type: */
-            int iIpId = qRegisterMetaType<IpData>();
-            /* Register ip editor: */
-            QStandardItemEditorCreator<IPEditor> *pIpEditorItemCreator = new QStandardItemEditorCreator<IPEditor>();
-            /* Link ip type & editor: */
-            pNewItemEditorFactory->registerEditor((QVariant::Type)iIpId, pIpEditorItemCreator);
-
-            /* Register port type: */
-            int iPortId = qRegisterMetaType<PortData>();
-            /* Register port editor: */
-            QStandardItemEditorCreator<PortEditor> *pPortEditorItemCreator = new QStandardItemEditorCreator<PortEditor>();
-            /* Link port type & editor: */
-            pNewItemEditorFactory->registerEditor((QVariant::Type)iPortId, pPortEditorItemCreator);
-
-            /* Set newly created item editor factory for table delegate: */
-            pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory);
+            /* Configure button-box: */
+            connect(m_pButtonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
+            connect(m_pButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
         }
+        /* Add widgets into layout: */
+        pMainLayout->addWidget(m_pTable);
+        pMainLayout->addWidget(m_pButtonBox);
     }
 
     /* Retranslate dialog: */
     retranslateUi();
-
-    /* Minimum Size: */
-    setMinimumSize(600, 300);
-}
-
-/* Port forwarding dialog destructor: */
-UIMachineSettingsPortForwardingDlg::~UIMachineSettingsPortForwardingDlg()
-{
 }
 
 const UIPortForwardingDataList& UIMachineSettingsPortForwardingDlg::rules() const
 {
-    return m_pModel->rules();
-}
-
-/* Add rule slot: */
-void UIMachineSettingsPortForwardingDlg::sltAddRule()
-{
-    m_pModel->addRule(QModelIndex());
-    m_pTableView->setFocus();
-    m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
-    sltCurrentChanged();
-    sltAdjustTable();
-}
-
-/* Copy rule slot: */
-void UIMachineSettingsPortForwardingDlg::sltCopyRule()
-{
-    m_pModel->addRule(m_pTableView->currentIndex());
-    m_pTableView->setFocus();
-    m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
-    sltCurrentChanged();
-    sltAdjustTable();
-}
-
-/* Del rule slot: */
-void UIMachineSettingsPortForwardingDlg::sltDelRule()
-{
-    m_pModel->delRule(m_pTableView->currentIndex());
-    m_pTableView->setFocus();
-    sltCurrentChanged();
-    sltAdjustTable();
-}
-
-/* Table data change handler: */
-void UIMachineSettingsPortForwardingDlg::sltTableDataChanged()
-{
-    fIsTableDataChanged = true;
-}
-
-/* Table index-change handler: */
-void UIMachineSettingsPortForwardingDlg::sltCurrentChanged()
-{
-    bool fTableFocused = m_pTableView->hasFocus();
-    bool fTableChildrenFocused = m_pTableView->findChildren<QWidget*>().contains(QApplication::focusWidget());
-    bool fTableOrChildrenFocused = fTableFocused || fTableChildrenFocused;
-    m_pCopyAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildrenFocused);
-    m_pDelAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildrenFocused);
-}
-
-/* Table context-menu handler: */
-void UIMachineSettingsPortForwardingDlg::sltShowTableContexMenu(const QPoint &pos)
-{
-    /* Prepare context menu: */
-    QMenu menu(m_pTableView);
-    /* If some index is currently selected: */
-    if (m_pTableView->indexAt(pos).isValid())
-    {
-        menu.addAction(m_pCopyAction);
-        menu.addAction(m_pDelAction);
-    }
-    /* If no valid index selected: */
-    else
-    {
-        menu.addAction(m_pAddAction);
-    }
-    menu.exec(m_pTableView->viewport()->mapToGlobal(pos));
-}
-
-/* Adjusts table column's sizes: */
-void UIMachineSettingsPortForwardingDlg::sltAdjustTable()
-{
-    m_pTableView->horizontalHeader()->setStretchLastSection(false);
-    /* If table is NOT empty: */
-    if (m_pModel->rowCount())
-    {
-        /* Resize table to contents size-hint and emit a spare place for first column: */
-        m_pTableView->resizeColumnsToContents();
-        uint uFullWidth = m_pTableView->viewport()->width();
-        for (uint u = 1; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
-            uFullWidth -= m_pTableView->horizontalHeader()->sectionSize(u);
-        m_pTableView->horizontalHeader()->resizeSection(UIPortForwardingModel::UIPortForwardingDataType_Name, uFullWidth);
-    }
-    /* If table is empty: */
-    else
-    {
-        /* Resize table columns to be equal in size: */
-        uint uFullWidth = m_pTableView->viewport()->width();
-        for (uint u = 0; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
-            m_pTableView->horizontalHeader()->resizeSection(u, uFullWidth / UIPortForwardingModel::UIPortForwardingDataType_Max);
-    }
-    m_pTableView->horizontalHeader()->setStretchLastSection(true);
+    return m_pTable->rules();
 }
 
@@ -644,14 +65,8 @@
 {
     /* Validate table: */
-    for (int i = 0; i < m_pModel->rowCount(); ++i)
-    {
-        if (m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_HostPort), Qt::EditRole).value<PortData>().value() == 0 ||
-            m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_GuestPort), Qt::EditRole).value<PortData>().value() == 0)
-        {
-            msgCenter().warnAboutIncorrectPort(this);
-            return;
-        }
-    }
-    /* Base class accept() slot: */
+    bool fPassed = m_pTable->validate();
+    if (!fPassed)
+        return;
+    /* Call to base-class: */
     QIWithRetranslateUI<QIDialog>::accept();
 }
@@ -659,61 +74,16 @@
 void UIMachineSettingsPortForwardingDlg::reject()
 {
-    /* Check if table data was changed: */
-    if (fIsTableDataChanged && !msgCenter().confirmCancelingPortForwardingDialog(this))
+    /* Discard table: */
+    bool fPassed = m_pTable->discard();
+    if (!fPassed)
         return;
-    /* Base class reject() slot: */
+    /* Call to base-class: */
     QIWithRetranslateUI<QIDialog>::reject();
 }
 
-/* UI Retranslation slot: */
 void UIMachineSettingsPortForwardingDlg::retranslateUi()
 {
     /* Set window title: */
     setWindowTitle(tr("Port Forwarding Rules"));
-
-    /* Table translations: */
-    m_pTableView->setWhatsThis(tr("This table contains a list of port forwarding rules."));
-
-    /* Set action's text: */
-    m_pAddAction->setText(tr("Insert new rule"));
-    m_pCopyAction->setText(tr("Copy selected rule"));
-    m_pDelAction->setText(tr("Delete selected rule"));
-    m_pAddAction->setWhatsThis(tr("This button adds new port forwarding rule."));
-    m_pDelAction->setWhatsThis(tr("This button deletes selected port forwarding rule."));
-    m_pAddAction->setToolTip(QString("%1 (%2)").arg(m_pAddAction->text()).arg(m_pAddAction->shortcut().toString()));
-    m_pDelAction->setToolTip(QString("%1 (%2)").arg(m_pDelAction->text()).arg(m_pDelAction->shortcut().toString()));
 }
 
-/* Extended event-handler: */
-bool UIMachineSettingsPortForwardingDlg::eventFilter(QObject *pObj, QEvent *pEvent)
-{
-    /* Process table: */
-    if (pObj == m_pTableView)
-    {
-        /* Switch for different event-types: */
-        switch (pEvent->type())
-        {
-            case QEvent::FocusIn:
-            case QEvent::FocusOut:
-                /* Update actions: */
-                sltCurrentChanged();
-                break;
-            case QEvent::Show:
-            case QEvent::Resize:
-            {
-                /* Instant table adjusting: */
-                sltAdjustTable();
-                /* Delayed table adjusting: */
-                QTimer::singleShot(0, this, SLOT(sltAdjustTable()));
-                break;
-            }
-            default:
-                break;
-        }
-    }
-    /* Continue with base-class processing: */
-    return QIWithRetranslateUI<QIDialog>::eventFilter(pObj, pEvent);
-}
-
-#include "UIMachineSettingsPortForwardingDlg.moc"
-
Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.h	(revision 48531)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.h	(revision 48533)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -20,84 +20,13 @@
 #define __UIMachineSettingsPortForwardingDlg_h__
 
-/* GUI includes */
+/* GUI includes: */
 #include "QIWithRetranslateUI.h"
 #include "QIDialog.h"
-
-/* COM includes: */
-#include "COMEnums.h"
+#include "UIPortForwardingTable.h"
 
 /* Forward declarations: */
-class QITableView;
-class UIToolBar;
 class QIDialogButtonBox;
-class UIPortForwardingModel;
 
-/* Name data: */
-class NameData : public QString
-{
-public:
-
-    NameData() : QString() {}
-    NameData(const QString &ruleName) : QString(ruleName) {}
-};
-Q_DECLARE_METATYPE(NameData);
-
-/* Ip data: */
-class IpData : public QString
-{
-public:
-
-    IpData() : QString() {}
-    IpData(const QString &ipAddress) : QString(ipAddress) {}
-};
-Q_DECLARE_METATYPE(IpData);
-
-/* Port data: */
-class PortData
-{
-public:
-
-    PortData() : m_uValue(0) {}
-    PortData(ushort uValue) : m_uValue(uValue) {}
-    PortData(const PortData &other) : m_uValue(other.value()) {}
-    bool operator==(const PortData &other) { return m_uValue == other.m_uValue; }
-    ushort value() const { return m_uValue; }
-
-private:
-
-    ushort m_uValue;
-};
-Q_DECLARE_METATYPE(PortData);
-
-/* Port forwarding data: */
-struct UIPortForwardingData
-{
-    UIPortForwardingData(const NameData &strName, KNATProtocol eProtocol,
-                         const IpData &strHostIp, PortData uHostPort,
-                         const IpData &strGuestIp, PortData uGuestPort)
-        : name(strName), protocol(eProtocol)
-        , hostIp(strHostIp), hostPort(uHostPort)
-        , guestIp(strGuestIp), guestPort(uGuestPort) {}
-    bool operator==(const UIPortForwardingData &other)
-    {
-        return name == other.name &&
-               protocol == other.protocol &&
-               hostIp == other.hostIp &&
-               hostPort == other.hostPort &&
-               guestIp == other.guestIp &&
-               guestPort == other.guestPort;
-    }
-    NameData name;
-    KNATProtocol protocol;
-    IpData hostIp;
-    PortData hostPort;
-    IpData guestIp;
-    PortData guestPort;
-};
-
-/* Port forwarding data list: */
-typedef QList<UIPortForwardingData> UIPortForwardingDataList;
-
-/* Port forwarding dialog: */
+/* Machine settings / Network page / NAT attachment / Port forwarding dialog: */
 class UIMachineSettingsPortForwardingDlg : public QIWithRetranslateUI<QIDialog>
 {
@@ -106,27 +35,14 @@
 public:
 
-    /* Port forwarding dialog constructor: */
-    UIMachineSettingsPortForwardingDlg(QWidget *pParent = 0,
-                                    const UIPortForwardingDataList &rules = UIPortForwardingDataList());
-    /* Port forwarding dialog destructor: */
-    ~UIMachineSettingsPortForwardingDlg();
+    /* Constructor/destructor: */
+    UIMachineSettingsPortForwardingDlg(QWidget *pParent,
+                                       const UIPortForwardingDataList &rules = UIPortForwardingDataList());
 
-    /* The list of chosen rules: */
+    /* API: Rules stuff: */
     const UIPortForwardingDataList& rules() const;
 
 private slots:
 
-    /* Action's slots: */
-    void sltAddRule();
-    void sltCopyRule();
-    void sltDelRule();
-
-    /* Table slots: */
-    void sltTableDataChanged();
-    void sltCurrentChanged();
-    void sltShowTableContexMenu(const QPoint &position);
-    void sltAdjustTable();
-
-    /* Dialog slots: */
+    /* Handlers: Dialog stuff: */
     void accept();
     void reject();
@@ -134,27 +50,11 @@
 private:
 
-    /* UI Translator: */
+    /* Handler: Translation stuff: */
     void retranslateUi();
 
-    /* Event filter: */
-    bool eventFilter(QObject *pObj, QEvent *pEvent);
-
-    /* Flags: */
-    bool fIsTableDataChanged;
-
     /* Widgets: */
-    QITableView *m_pTableView;
-    UIToolBar *m_pToolBar;
+    UIPortForwardingTable *m_pTable;
     QIDialogButtonBox *m_pButtonBox;
-
-    /* Model: */
-    UIPortForwardingModel *m_pModel;
-
-    /* Actions: */
-    QAction *m_pAddAction;
-    QAction *m_pCopyAction;
-    QAction *m_pDelAction;
 };
 
 #endif // __UIMachineSettingsPortForwardingDlg_h__
-
Index: trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.cpp	(revision 48533)
+++ trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.cpp	(revision 48533)
@@ -0,0 +1,718 @@
+/* $Id$ */
+/** @file
+ *
+ * VBox frontends: Qt4 GUI ("VirtualBox"):
+ * UIPortForwardingTable class implementation
+ */
+
+/*
+ * Copyright (C) 2010-2013 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 <QHBoxLayout>
+#include <QMenu>
+#include <QAction>
+#include <QHeaderView>
+#include <QStyledItemDelegate>
+#include <QItemEditorFactory>
+#include <QComboBox>
+#include <QLineEdit>
+#include <QSpinBox>
+
+/* GUI includes: */
+#include "UIPortForwardingTable.h"
+#include "UIMessageCenter.h"
+#include "UIConverter.h"
+#include "UIIconPool.h"
+#include "UIToolBar.h"
+#include "QITableView.h"
+
+/* Other VBox includes: */
+#include <iprt/cidr.h>
+
+/* External includes: */
+#include <math.h>
+
+/* IP validator: */
+class IPValidator : public QValidator
+{
+    Q_OBJECT;
+
+public:
+
+    /* Constructor/destructor: */
+    IPValidator(QObject *pParent) : QValidator(pParent) {}
+    ~IPValidator() {}
+
+    /* Handler: Validation stuff: */
+    QValidator::State validate(QString &strInput, int& /*iPos*/) const
+    {
+        QString strStringToValidate(strInput);
+        strStringToValidate.remove(' ');
+        QString strDot("\\.");
+        QString strDigits("(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)");
+        QRegExp intRegExp(QString("^(%1?(%2(%1?(%2(%1?(%2%1?)?)?)?)?)?)?$").arg(strDigits).arg(strDot));
+        RTNETADDRIPV4 Network, Mask;
+        if (strStringToValidate == "..." || RTCidrStrToIPv4(strStringToValidate.toLatin1().constData(), &Network, &Mask) == VINF_SUCCESS)
+            return QValidator::Acceptable;
+        else if (intRegExp.indexIn(strStringToValidate) != -1)
+            return QValidator::Intermediate;
+        else
+            return QValidator::Invalid;
+    }
+};
+
+/* Name editor: */
+class NameEditor : public QLineEdit
+{
+    Q_OBJECT;
+    Q_PROPERTY(NameData name READ name WRITE setName USER true);
+
+public:
+
+    /* Constructor: */
+    NameEditor(QWidget *pParent = 0) : QLineEdit(pParent)
+    {
+        setFrame(false);
+        setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
+        setValidator(new QRegExpValidator(QRegExp("[^,]*"), this));
+    }
+
+private:
+
+    /* API: Name stuff: */
+    void setName(NameData name)
+    {
+        setText(name);
+    }
+
+    /* API: Name stuff: */
+    NameData name() const
+    {
+        return text();
+    }
+};
+
+/* Protocol editor: */
+class ProtocolEditor : public QComboBox
+{
+    Q_OBJECT;
+    Q_PROPERTY(KNATProtocol protocol READ protocol WRITE setProtocol USER true);
+
+public:
+
+    /* Constructor: */
+    ProtocolEditor(QWidget *pParent = 0) : QComboBox(pParent)
+    {
+        addItem(gpConverter->toString(KNATProtocol_UDP), QVariant::fromValue(KNATProtocol_UDP));
+        addItem(gpConverter->toString(KNATProtocol_TCP), QVariant::fromValue(KNATProtocol_TCP));
+    }
+
+private:
+
+    /* API: Protocol stuff: */
+    void setProtocol(KNATProtocol p)
+    {
+        for (int i = 0; i < count(); ++i)
+        {
+            if (itemData(i).value<KNATProtocol>() == p)
+            {
+                setCurrentIndex(i);
+                break;
+            }
+        }
+    }
+
+    /* API: Protocol stuff: */
+    KNATProtocol protocol() const
+    {
+        return itemData(currentIndex()).value<KNATProtocol>();
+    }
+};
+
+/* IP editor: */
+class IPEditor : public QLineEdit
+{
+    Q_OBJECT;
+    Q_PROPERTY(IpData ip READ ip WRITE setIp USER true);
+
+public:
+
+    /* Constructor: */
+    IPEditor(QWidget *pParent = 0) : QLineEdit(pParent)
+    {
+        setFrame(false);
+        setAlignment(Qt::AlignCenter);
+        setValidator(new IPValidator(this));
+        setInputMask("000.000.000.000");
+    }
+
+private:
+
+    /* API: IP stuff: */
+    void setIp(IpData ip)
+    {
+        setText(ip);
+    }
+
+    /* API: IP stuff: */
+    IpData ip() const
+    {
+        return text() == "..." ? QString() : text();
+    }
+};
+
+/* Port editor: */
+class PortEditor : public QSpinBox
+{
+    Q_OBJECT;
+    Q_PROPERTY(PortData port READ port WRITE setPort USER true);
+
+public:
+
+    /* Constructor: */
+    PortEditor(QWidget *pParent = 0) : QSpinBox(pParent)
+    {
+        setFrame(false);
+        setRange(0, (1 << (8 * sizeof(ushort))) - 1);
+    }
+
+private:
+
+    /* API: Port stuff: */
+    void setPort(PortData port)
+    {
+        setValue(port.value());
+    }
+
+    /* API: Port stuff: */
+    PortData port() const
+    {
+        return value();
+    }
+};
+
+/* Port forwarding data model: */
+class UIPortForwardingModel : public QAbstractTableModel
+{
+    Q_OBJECT;
+
+public:
+
+    /* Enum: Column names: */
+    enum UIPortForwardingDataType
+    {
+        UIPortForwardingDataType_Name,
+        UIPortForwardingDataType_Protocol,
+        UIPortForwardingDataType_HostIp,
+        UIPortForwardingDataType_HostPort,
+        UIPortForwardingDataType_GuestIp,
+        UIPortForwardingDataType_GuestPort,
+        UIPortForwardingDataType_Max
+    };
+
+    /* Constructor: */
+    UIPortForwardingModel(QObject *pParent = 0, const UIPortForwardingDataList &rules = UIPortForwardingDataList())
+        : QAbstractTableModel(pParent)
+        , m_dataList(rules) {}
+
+    /* API: Rule stuff: */
+    const UIPortForwardingDataList& rules() const { return m_dataList; }
+    void addRule(const QModelIndex &index);
+    void delRule(const QModelIndex &index);
+
+    /* API: Index flag stuff: */
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    /* API: Index row-count stuff: */
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+    /* API: Index column-count stuff: */
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+    /* API: Header data stuff: */
+    QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const;
+
+    /* API: Index data stuff: */
+    QVariant data(const QModelIndex &index, int iRole) const;
+    bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole);
+
+private:
+
+    /* Variable: Data stuff: */
+    UIPortForwardingDataList m_dataList;
+};
+
+void UIPortForwardingModel::addRule(const QModelIndex &index)
+{
+    beginInsertRows(QModelIndex(), m_dataList.size(), m_dataList.size());
+    /* Search for existing "Rule [NUMBER]" record: */
+    uint uMaxIndex = 0;
+    QString strTemplate("Rule %1");
+    QRegExp regExp(strTemplate.arg("(\\d+)"));
+    for (int i = 0; i < m_dataList.size(); ++i)
+        if (regExp.indexIn(m_dataList[i].name) > -1)
+            uMaxIndex = regExp.cap(1).toUInt() > uMaxIndex ? regExp.cap(1).toUInt() : uMaxIndex;
+    /* If index is valid => copy data: */
+    if (index.isValid())
+        m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), m_dataList[index.row()].protocol,
+                                           m_dataList[index.row()].hostIp, m_dataList[index.row()].hostPort,
+                                           m_dataList[index.row()].guestIp, m_dataList[index.row()].guestPort);
+    /* If index is NOT valid => use default values: */
+    else
+        m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), KNATProtocol_TCP,
+                                           QString(""), 0, QString(""), 0);
+    endInsertRows();
+}
+
+void UIPortForwardingModel::delRule(const QModelIndex &index)
+{
+    if (!index.isValid())
+        return;
+    beginRemoveRows(QModelIndex(), index.row(), index.row());
+    m_dataList.removeAt(index.row());
+    endRemoveRows();
+}
+
+Qt::ItemFlags UIPortForwardingModel::flags(const QModelIndex &index) const
+{
+    /* Check index validness: */
+    if (!index.isValid())
+        return Qt::NoItemFlags;
+    /* All columns have similar flags: */
+    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
+}
+
+int UIPortForwardingModel::rowCount(const QModelIndex&) const
+{
+    return m_dataList.size();
+}
+
+int UIPortForwardingModel::columnCount(const QModelIndex&) const
+{
+    return UIPortForwardingDataType_Max;
+}
+
+QVariant UIPortForwardingModel::headerData(int iSection, Qt::Orientation orientation, int iRole) const
+{
+    /* Display role for horizontal header: */
+    if (iRole == Qt::DisplayRole && orientation == Qt::Horizontal)
+    {
+        /* Switch for different columns: */
+        switch (iSection)
+        {
+            case UIPortForwardingDataType_Name: return tr("Name");
+            case UIPortForwardingDataType_Protocol: return tr("Protocol");
+            case UIPortForwardingDataType_HostIp: return tr("Host IP");
+            case UIPortForwardingDataType_HostPort: return tr("Host Port");
+            case UIPortForwardingDataType_GuestIp: return tr("Guest IP");
+            case UIPortForwardingDataType_GuestPort: return tr("Guest Port");
+            default: break;
+        }
+    }
+    /* Return wrong value: */
+    return QVariant();
+}
+
+QVariant UIPortForwardingModel::data(const QModelIndex &index, int iRole) const
+{
+    /* Check index validness: */
+    if (!index.isValid())
+        return QVariant();
+    /* Switch for different roles: */
+    switch (iRole)
+    {
+        /* Display role: */
+        case Qt::DisplayRole:
+        {
+            /* Switch for different columns: */
+            switch (index.column())
+            {
+                case UIPortForwardingDataType_Name: return m_dataList[index.row()].name;
+                case UIPortForwardingDataType_Protocol: return gpConverter->toString(m_dataList[index.row()].protocol);
+                case UIPortForwardingDataType_HostIp: return m_dataList[index.row()].hostIp;
+                case UIPortForwardingDataType_HostPort: return m_dataList[index.row()].hostPort.value();
+                case UIPortForwardingDataType_GuestIp: return m_dataList[index.row()].guestIp;
+                case UIPortForwardingDataType_GuestPort: return m_dataList[index.row()].guestPort.value();
+                default: return QVariant();
+            }
+        }
+        /* Edit role: */
+        case Qt::EditRole:
+        {
+            /* Switch for different columns: */
+            switch (index.column())
+            {
+                case UIPortForwardingDataType_Name: return QVariant::fromValue(m_dataList[index.row()].name);
+                case UIPortForwardingDataType_Protocol: return QVariant::fromValue(m_dataList[index.row()].protocol);
+                case UIPortForwardingDataType_HostIp: return QVariant::fromValue(m_dataList[index.row()].hostIp);
+                case UIPortForwardingDataType_HostPort: return QVariant::fromValue(m_dataList[index.row()].hostPort);
+                case UIPortForwardingDataType_GuestIp: return QVariant::fromValue(m_dataList[index.row()].guestIp);
+                case UIPortForwardingDataType_GuestPort: return QVariant::fromValue(m_dataList[index.row()].guestPort);
+                default: return QVariant();
+            }
+        }
+        /* Alignment role: */
+        case Qt::TextAlignmentRole:
+        {
+            /* Switch for different columns: */
+            switch (index.column())
+            {
+                case UIPortForwardingDataType_Name:
+                case UIPortForwardingDataType_Protocol:
+                case UIPortForwardingDataType_HostPort:
+                case UIPortForwardingDataType_GuestPort:
+                    return (int)(Qt::AlignLeft | Qt::AlignVCenter);
+                case UIPortForwardingDataType_HostIp:
+                case UIPortForwardingDataType_GuestIp:
+                    return Qt::AlignCenter;
+                default: return QVariant();
+            }
+        }
+        case Qt::SizeHintRole:
+        {
+            /* Switch for different columns: */
+            switch (index.column())
+            {
+                case UIPortForwardingDataType_HostIp:
+                case UIPortForwardingDataType_GuestIp:
+                    return QSize(QApplication::fontMetrics().width(" 888.888.888.888 "), QApplication::fontMetrics().height());
+                default: return QVariant();
+            }
+        }
+        default: break;
+    }
+    /* Return wrong value: */
+    return QVariant();
+}
+
+bool UIPortForwardingModel::setData(const QModelIndex &index, const QVariant &value, int iRole /*= Qt::EditRole*/)
+{
+    /* Check index validness: */
+    if (!index.isValid() || iRole != Qt::EditRole)
+        return false;
+    /* Switch for different columns: */
+    switch (index.column())
+    {
+        case UIPortForwardingDataType_Name:
+            m_dataList[index.row()].name = value.value<NameData>();
+            emit dataChanged(index, index);
+            return true;
+        case UIPortForwardingDataType_Protocol:
+            m_dataList[index.row()].protocol = value.value<KNATProtocol>();
+            emit dataChanged(index, index);
+            return true;
+        case UIPortForwardingDataType_HostIp:
+            m_dataList[index.row()].hostIp = value.value<IpData>();
+            emit dataChanged(index, index);
+            return true;
+        case UIPortForwardingDataType_HostPort:
+            m_dataList[index.row()].hostPort = value.value<PortData>();
+            emit dataChanged(index, index);
+            return true;
+        case UIPortForwardingDataType_GuestIp:
+            m_dataList[index.row()].guestIp = value.value<IpData>();
+            emit dataChanged(index, index);
+            return true;
+        case UIPortForwardingDataType_GuestPort:
+            m_dataList[index.row()].guestPort = value.value<PortData>();
+            emit dataChanged(index, index);
+            return true;
+        default: return false;
+    }
+    /* Return false value: */
+    return false;
+}
+
+
+UIPortForwardingTable::UIPortForwardingTable(const UIPortForwardingDataList &rules)
+    : m_fIsTableDataChanged(false)
+    , m_pTableView(0)
+    , m_pToolBar(0)
+    , m_pModel(0)
+    , m_pAddAction(0)
+    , m_pCopyAction(0)
+    , m_pDelAction(0)
+{
+    /* Create layout: */
+    QHBoxLayout *pMainLayout = new QHBoxLayout(this);
+    {
+        /* Configure layout: */
+        pMainLayout->setMargin(0);
+        pMainLayout->setSpacing(3);
+        /* Create model: */
+        m_pModel = new UIPortForwardingModel(this, rules);
+        {
+            /* Configure model: */
+            connect(m_pModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(sltTableDataChanged()));
+            connect(m_pModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(sltTableDataChanged()));
+            connect(m_pModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(sltTableDataChanged()));
+        }
+        /* Create table: */
+        m_pTableView = new QITableView;
+        {
+            /* Configure table: */
+            m_pTableView->setModel(m_pModel);
+            m_pTableView->setTabKeyNavigation(false);
+            m_pTableView->verticalHeader()->hide();
+            m_pTableView->verticalHeader()->setDefaultSectionSize((int)(m_pTableView->verticalHeader()->minimumSectionSize() * 1.33));
+            m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
+            m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
+            m_pTableView->installEventFilter(this);
+            connect(m_pTableView, SIGNAL(sigCurrentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(sltCurrentChanged()));
+            connect(m_pTableView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(sltShowTableContexMenu(const QPoint &)));
+        }
+        /* Create toolbar: */
+        m_pToolBar = new UIToolBar;
+        {
+            /* Configure toolbar: */
+            m_pToolBar->setIconSize(QSize(16, 16));
+            m_pToolBar->setOrientation(Qt::Vertical);
+            /* Create 'add' action: */
+            m_pAddAction = new QAction(this);
+            {
+                /* Configure 'add' action: */
+                m_pAddAction->setShortcut(QKeySequence("Ins"));
+                m_pAddAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
+                connect(m_pAddAction, SIGNAL(triggered(bool)), this, SLOT(sltAddRule()));
+                m_pToolBar->addAction(m_pAddAction);
+            }
+            /* Create 'copy' action: */
+            m_pCopyAction = new QAction(this);
+            {
+                /* Configure 'add' action: */
+                m_pCopyAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
+                connect(m_pCopyAction, SIGNAL(triggered(bool)), this, SLOT(sltCopyRule()));
+            }
+            /* Create 'del' action: */
+            m_pDelAction = new QAction(this);
+            {
+                /* Configure 'del' action: */
+                m_pDelAction->setShortcut(QKeySequence("Del"));
+                m_pDelAction->setIcon(UIIconPool::iconSet(":/controller_remove_16px.png", ":/controller_remove_disabled_16px.png"));
+                connect(m_pDelAction, SIGNAL(triggered(bool)), this, SLOT(sltDelRule()));
+                m_pToolBar->addAction(m_pDelAction);
+            }
+        }
+        /* Add widgets into layout: */
+        pMainLayout->addWidget(m_pTableView);
+        pMainLayout->addWidget(m_pToolBar);
+    }
+
+    /* Register delegates editors: */
+    if (QAbstractItemDelegate *pAbstractItemDelegate = m_pTableView->itemDelegate())
+    {
+        if (QStyledItemDelegate *pStyledItemDelegate = qobject_cast<QStyledItemDelegate*>(pAbstractItemDelegate))
+        {
+            /* Create new item editor factory: */
+            QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory;
+
+            /* Register name type: */
+            int iNameId = qRegisterMetaType<NameData>();
+            /* Register name editor: */
+            QStandardItemEditorCreator<NameEditor> *pNameEditorItemCreator = new QStandardItemEditorCreator<NameEditor>();
+            /* Link name type & editor: */
+            pNewItemEditorFactory->registerEditor((QVariant::Type)iNameId, pNameEditorItemCreator);
+
+            /* Register protocol type: */
+            int iProtocolId = qRegisterMetaType<KNATProtocol>();
+            /* Register protocol editor: */
+            QStandardItemEditorCreator<ProtocolEditor> *pProtocolEditorItemCreator = new QStandardItemEditorCreator<ProtocolEditor>();
+            /* Link protocol type & editor: */
+            pNewItemEditorFactory->registerEditor((QVariant::Type)iProtocolId, pProtocolEditorItemCreator);
+
+            /* Register ip type: */
+            int iIpId = qRegisterMetaType<IpData>();
+            /* Register ip editor: */
+            QStandardItemEditorCreator<IPEditor> *pIpEditorItemCreator = new QStandardItemEditorCreator<IPEditor>();
+            /* Link ip type & editor: */
+            pNewItemEditorFactory->registerEditor((QVariant::Type)iIpId, pIpEditorItemCreator);
+
+            /* Register port type: */
+            int iPortId = qRegisterMetaType<PortData>();
+            /* Register port editor: */
+            QStandardItemEditorCreator<PortEditor> *pPortEditorItemCreator = new QStandardItemEditorCreator<PortEditor>();
+            /* Link port type & editor: */
+            pNewItemEditorFactory->registerEditor((QVariant::Type)iPortId, pPortEditorItemCreator);
+
+            /* Set newly created item editor factory for table delegate: */
+            pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory);
+        }
+    }
+
+    /* Retranslate dialog: */
+    retranslateUi();
+
+    /* Minimum Size: */
+    setMinimumSize(600, 250);
+}
+
+const UIPortForwardingDataList& UIPortForwardingTable::rules() const
+{
+    return m_pModel->rules();
+}
+
+bool UIPortForwardingTable::validate() const
+{
+    /* Validate table: */
+    for (int i = 0; i < m_pModel->rowCount(); ++i)
+    {
+        /* If at aleast one port is 'zero': */
+        if (m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_HostPort), Qt::EditRole).value<PortData>().value() == 0 ||
+            m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_GuestPort), Qt::EditRole).value<PortData>().value() == 0)
+        {
+            msgCenter().warnAboutIncorrectPort(window());
+            return false;
+        }
+    }
+    /* True by default: */
+    return true;
+}
+
+bool UIPortForwardingTable::discard() const
+{
+    /* Check if table data was changed and user do not want to loose it: */
+    if (m_fIsTableDataChanged && !msgCenter().confirmCancelingPortForwardingDialog(window()))
+        return false;
+    /* True by default: */
+    return true;
+}
+
+void UIPortForwardingTable::sltAddRule()
+{
+    m_pModel->addRule(QModelIndex());
+    m_pTableView->setFocus();
+    m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
+    sltCurrentChanged();
+    sltAdjustTable();
+}
+
+void UIPortForwardingTable::sltCopyRule()
+{
+    m_pModel->addRule(m_pTableView->currentIndex());
+    m_pTableView->setFocus();
+    m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
+    sltCurrentChanged();
+    sltAdjustTable();
+}
+
+void UIPortForwardingTable::sltDelRule()
+{
+    m_pModel->delRule(m_pTableView->currentIndex());
+    m_pTableView->setFocus();
+    sltCurrentChanged();
+    sltAdjustTable();
+}
+
+void UIPortForwardingTable::sltTableDataChanged()
+{
+    m_fIsTableDataChanged = true;
+}
+
+void UIPortForwardingTable::sltCurrentChanged()
+{
+    bool fTableFocused = m_pTableView->hasFocus();
+    bool fTableChildFocused = m_pTableView->findChildren<QWidget*>().contains(QApplication::focusWidget());
+    bool fTableOrChildFocused = fTableFocused || fTableChildFocused;
+    m_pCopyAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildFocused);
+    m_pDelAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildFocused);
+}
+
+void UIPortForwardingTable::sltShowTableContexMenu(const QPoint &pos)
+{
+    /* Prepare context menu: */
+    QMenu menu(m_pTableView);
+    /* If some index is currently selected: */
+    if (m_pTableView->indexAt(pos).isValid())
+    {
+        menu.addAction(m_pCopyAction);
+        menu.addAction(m_pDelAction);
+    }
+    /* If no valid index selected: */
+    else
+    {
+        menu.addAction(m_pAddAction);
+    }
+    menu.exec(m_pTableView->viewport()->mapToGlobal(pos));
+}
+
+void UIPortForwardingTable::sltAdjustTable()
+{
+    m_pTableView->horizontalHeader()->setStretchLastSection(false);
+    /* If table is NOT empty: */
+    if (m_pModel->rowCount())
+    {
+        /* Resize table to contents size-hint and emit a spare place for first column: */
+        m_pTableView->resizeColumnsToContents();
+        uint uFullWidth = m_pTableView->viewport()->width();
+        for (uint u = 1; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
+            uFullWidth -= m_pTableView->horizontalHeader()->sectionSize(u);
+        m_pTableView->horizontalHeader()->resizeSection(UIPortForwardingModel::UIPortForwardingDataType_Name, uFullWidth);
+    }
+    /* If table is empty: */
+    else
+    {
+        /* Resize table columns to be equal in size: */
+        uint uFullWidth = m_pTableView->viewport()->width();
+        for (uint u = 0; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
+            m_pTableView->horizontalHeader()->resizeSection(u, uFullWidth / UIPortForwardingModel::UIPortForwardingDataType_Max);
+    }
+    m_pTableView->horizontalHeader()->setStretchLastSection(true);
+}
+
+void UIPortForwardingTable::retranslateUi()
+{
+    /* Table translations: */
+    m_pTableView->setToolTip(QApplication::translate("UIMachineSettingsPortForwardingDlg", "This table contains a list of port forwarding rules."));
+
+    /* Set action's text: */
+    m_pAddAction->setText(QApplication::translate("UIMachineSettingsPortForwardingDlg", "Insert new rule"));
+    m_pCopyAction->setText(QApplication::translate("UIMachineSettingsPortForwardingDlg", "Copy selected rule"));
+    m_pDelAction->setText(QApplication::translate("UIMachineSettingsPortForwardingDlg", "Delete selected rule"));
+    m_pAddAction->setWhatsThis(QApplication::translate("UIMachineSettingsPortForwardingDlg", "This button adds new port forwarding rule."));
+    m_pDelAction->setWhatsThis(QApplication::translate("UIMachineSettingsPortForwardingDlg", "This button deletes selected port forwarding rule."));
+    m_pAddAction->setToolTip(QString("%1 (%2)").arg(m_pAddAction->text()).arg(m_pAddAction->shortcut().toString()));
+    m_pDelAction->setToolTip(QString("%1 (%2)").arg(m_pDelAction->text()).arg(m_pDelAction->shortcut().toString()));
+}
+
+bool UIPortForwardingTable::eventFilter(QObject *pObject, QEvent *pEvent)
+{
+    /* Process table: */
+    if (pObject == m_pTableView)
+    {
+        /* Process different event-types: */
+        switch (pEvent->type())
+        {
+            case QEvent::Show:
+            case QEvent::Resize:
+            {
+                /* Adjust table: */
+                sltAdjustTable();
+                break;
+            }
+            case QEvent::FocusIn:
+            case QEvent::FocusOut:
+            {
+                /* Update actions: */
+                sltCurrentChanged();
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    /* Call to base-class: */
+    return QIWithRetranslateUI<QWidget>::eventFilter(pObject, pEvent);
+}
+
+#include "UIPortForwardingTable.moc"
+
Index: trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.h	(revision 48533)
+++ trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPortForwardingTable.h	(revision 48533)
@@ -0,0 +1,155 @@
+/** @file
+ *
+ * VBox frontends: Qt4 GUI ("VirtualBox"):
+ * UIPortForwardingTable class declaration
+ */
+
+/*
+ * Copyright (C) 2010-2013 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 __UIPortForwardingTable_h__
+#define __UIPortForwardingTable_h__
+
+/* Qt includes: */
+#include <QWidget>
+
+/* GUI includes: */
+#include "QIWithRetranslateUI.h"
+
+/* COM includes: */
+#include "COMEnums.h"
+
+/* Forward declarations: */
+class QITableView;
+class UIToolBar;
+class QIDialogButtonBox;
+class UIPortForwardingModel;
+
+/* Name data: */
+class NameData : public QString
+{
+public:
+
+    NameData() : QString() {}
+    NameData(const QString &strName) : QString(strName) {}
+};
+Q_DECLARE_METATYPE(NameData);
+
+/* Ip data: */
+class IpData : public QString
+{
+public:
+
+    IpData() : QString() {}
+    IpData(const QString &strIP) : QString(strIP) {}
+};
+Q_DECLARE_METATYPE(IpData);
+
+/* Port data: */
+class PortData
+{
+public:
+
+    PortData() : m_uValue(0) {}
+    PortData(ushort uValue) : m_uValue(uValue) {}
+    PortData(const PortData &other) : m_uValue(other.value()) {}
+    bool operator==(const PortData &other) { return m_uValue == other.m_uValue; }
+    ushort value() const { return m_uValue; }
+
+private:
+
+    ushort m_uValue;
+};
+Q_DECLARE_METATYPE(PortData);
+
+/* Port forwarding data: */
+struct UIPortForwardingData
+{
+    UIPortForwardingData(const NameData &strName, KNATProtocol protocol,
+                         const IpData &strHostIP, PortData uHostPort,
+                         const IpData &strGuestIP, PortData uGuestPort)
+        : name(strName), protocol(protocol)
+        , hostIp(strHostIP), hostPort(uHostPort)
+        , guestIp(strGuestIP), guestPort(uGuestPort) {}
+    bool operator==(const UIPortForwardingData &other)
+    {
+        return name == other.name &&
+               protocol == other.protocol &&
+               hostIp == other.hostIp &&
+               hostPort == other.hostPort &&
+               guestIp == other.guestIp &&
+               guestPort == other.guestPort;
+    }
+    NameData name;
+    KNATProtocol protocol;
+    IpData hostIp;
+    PortData hostPort;
+    IpData guestIp;
+    PortData guestPort;
+};
+
+/* Port forwarding data list: */
+typedef QList<UIPortForwardingData> UIPortForwardingDataList;
+
+/* Port forwarding dialog: */
+class UIPortForwardingTable : public QIWithRetranslateUI<QWidget>
+{
+    Q_OBJECT;
+
+public:
+
+    /* Constructor: */
+    UIPortForwardingTable(const UIPortForwardingDataList &rules = UIPortForwardingDataList());
+
+    /* API: Rules stuff: */
+    const UIPortForwardingDataList& rules() const;
+    bool validate() const;
+    bool discard() const;
+
+private slots:
+
+    /* Handlers: Table operation stuff: */
+    void sltAddRule();
+    void sltCopyRule();
+    void sltDelRule();
+
+    /* Handlers: Table stuff: */
+    void sltTableDataChanged();
+    void sltCurrentChanged();
+    void sltShowTableContexMenu(const QPoint &position);
+    void sltAdjustTable();
+
+private:
+
+    /* Handler: Translation stuff: */
+    void retranslateUi();
+
+    /* Handlers: Event-processing stuff: */
+    bool eventFilter(QObject *pObject, QEvent *pEvent);
+
+    /* Flags: */
+    bool m_fIsTableDataChanged;
+
+    /* Widgets: */
+    QITableView *m_pTableView;
+    UIToolBar *m_pToolBar;
+
+    /* Model: */
+    UIPortForwardingModel *m_pModel;
+
+    /* Actions: */
+    QAction *m_pAddAction;
+    QAction *m_pCopyAction;
+    QAction *m_pDelAction;
+};
+
+#endif // __UIPortForwardingTable_h__
