Index: /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.cpp	(revision 68297)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.cpp	(revision 68298)
@@ -22,8 +22,14 @@
 /* Qt includes: */
 # include <QApplication>
+# include <QDrag>
+# include <QDragEnterEvent>
+# include <QDragMoveEvent>
+# include <QDropEvent>
 # include <QEvent>
 # include <QHBoxLayout>
 # include <QLabel>
+# include <QMimeData>
 # include <QMouseEvent>
+# include <QStyleOption>
 # include <QPainter>
 # ifdef VBOX_WS_MAC
@@ -43,7 +49,9 @@
 /* Forward declarations: */
 class QApplication;
+class QDrag;
 class QEvent;
 class QHBoxLayout;
 class QLabel;
+class QMimeData;
 class QMouseEvent;
 #ifdef VBOX_WS_MAC
@@ -51,4 +59,5 @@
 #endif
 class QStyle;
+class QStyleOption;
 class QToolButton;
 
@@ -67,5 +76,11 @@
     void sigCloseClicked(UITabBarItem *pItem);
 
+    /** Notifies about drag-object destruction. */
+    void sigDragObjectDestroy();
+
 public:
+
+    /** Holds the mime-type for the D&D system. */
+    static const QString MimeType;
 
     /** Creates tab-bar item on the basis of passed @a uuid, @a icon and @a strName. */
@@ -87,6 +102,10 @@
     virtual void paintEvent(QPaintEvent *pEvent) /* override */;
 
+    /** Handles mouse-press @a pEvent. */
+    virtual void mousePressEvent(QMouseEvent *pEvent) /* override */;
     /** Handles mouse-release @a pEvent. */
     virtual void mouseReleaseEvent(QMouseEvent *pEvent) /* override */;
+    /** Handles mouse-move @a pEvent. */
+    virtual void mouseMoveEvent(QMouseEvent *pEvent) /* override */;
     /** Handles mouse-enter @a pEvent. */
     virtual void enterEvent(QEvent *pEvent) /* override */;
@@ -129,4 +148,7 @@
     /** Holds the close button instance. */
     QToolButton *m_pButtonClose;
+
+    /** Holds the last mouse-press position. */
+    QPoint m_mousePressPosition;
 };
 
@@ -135,4 +157,7 @@
 *   Class UITabBarItem implementation.                                                                                           *
 *********************************************************************************************************************************/
+
+/* static */
+const QString UITabBarItem::MimeType = QString("application/virtualbox;value=TabID");
 
 UITabBarItem::UITabBarItem(const QUuid &uuid, const QIcon &icon /* = QIcon() */, const QString &strName /* = QString() */)
@@ -247,4 +272,14 @@
 }
 
+void UITabBarItem::mousePressEvent(QMouseEvent *pEvent)
+{
+    /* We are interested in left button only: */
+    if (pEvent->button() != Qt::LeftButton)
+        return QWidget::mousePressEvent(pEvent);
+
+    /* Remember mouse-press position: */
+    m_mousePressPosition = pEvent->globalPos();
+}
+
 void UITabBarItem::mouseReleaseEvent(QMouseEvent *pEvent)
 {
@@ -253,6 +288,36 @@
         return QWidget::mouseReleaseEvent(pEvent);
 
+    /* Forget mouse-press position: */
+    m_mousePressPosition = QPoint();
+
     /* Notify listeners about the item was clicked: */
     emit sigClicked(this);
+}
+
+void UITabBarItem::mouseMoveEvent(QMouseEvent *pEvent)
+{
+    /* Make sure item isn't already dragged: */
+    if (m_mousePressPosition.isNull())
+        return QWidget::mouseMoveEvent(pEvent);
+
+    /* Make sure item is now being dragged: */
+    if (QLineF(pEvent->globalPos(), m_mousePressPosition).length() < QApplication::startDragDistance())
+        return QWidget::mouseMoveEvent(pEvent);
+
+    /* Revoke hovered state: */
+    m_fHovered = false;
+    /* And call for repaint: */
+    update();
+
+    /* Initialize dragging: */
+    m_mousePressPosition = QPoint();
+    QDrag *pDrag = new QDrag(this);
+    connect(pDrag, &QObject::destroyed, this, &UITabBarItem::sigDragObjectDestroy);
+    QMimeData *pMimeData = new QMimeData;
+    pMimeData->setData(MimeType, uuid().toByteArray());
+    pDrag->setMimeData(pMimeData);
+    const int iMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
+    pDrag->setPixmap(icon().pixmap(iMetric, iMetric));
+    pDrag->exec();
 }
 
@@ -385,4 +450,6 @@
     , m_pLayoutTab(0)
     , m_pCurrentItem(0)
+    , m_pItemToken(0)
+    , m_fDropAfterTokenItem(0)
 {
     /* Prepare: */
@@ -399,6 +466,7 @@
     {
         /* Configure item: */
-        connect(pItem, &UITabBarItem::sigClicked,      this, &UITabBar::sltHandleMakeChildCurrent);
-        connect(pItem, &UITabBarItem::sigCloseClicked, this, &UITabBar::sltHandleChildClose);
+        connect(pItem, &UITabBarItem::sigClicked,           this, &UITabBar::sltHandleMakeChildCurrent);
+        connect(pItem, &UITabBarItem::sigCloseClicked,      this, &UITabBar::sltHandleChildClose);
+        connect(pItem, &UITabBarItem::sigDragObjectDestroy, this, &UITabBar::sltHandleDragObjectDestroy);
         /* Add item into layout and list: */
         m_pLayoutTab->insertWidget(0, pItem);
@@ -472,4 +540,142 @@
 }
 
+void UITabBar::paintEvent(QPaintEvent *pEvent)
+{
+    /* Call to base-class: */
+    QWidget::paintEvent(pEvent);
+
+    /* If we have a token item: */
+    if (m_pItemToken)
+    {
+        /* Prepare painter: */
+        QPainter painter(this);
+
+        /* Paint drop token: */
+        QStyleOption option;
+        option.state |= QStyle::State_Horizontal;
+        const QRect geo = m_pItemToken->geometry();
+        option.rect = !m_fDropAfterTokenItem
+                    ? QRect(geo.topLeft() - QPoint(5, 5),
+                            geo.bottomLeft() + QPoint(0, 5))
+                    : QRect(geo.topRight() - QPoint(0, 5),
+                            geo.bottomRight() + QPoint(5, 5));
+        QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator,
+                                             &option, &painter);
+    }
+}
+
+void UITabBar::dragEnterEvent(QDragEnterEvent *pEvent)
+{
+    /* Make sure event is valid: */
+    AssertPtrReturnVoid(pEvent);
+    /* And mime-data is set: */
+    const QMimeData *pMimeData = pEvent->mimeData();
+    AssertPtrReturnVoid(pMimeData);
+
+    /* Make sure mime-data format is valid: */
+    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
+        return;
+
+    /* Accept drag-enter event: */
+    pEvent->acceptProposedAction();
+}
+
+void UITabBar::dragMoveEvent(QDragMoveEvent *pEvent)
+{
+    /* Make sure event is valid: */
+    AssertPtrReturnVoid(pEvent);
+    /* And mime-data is set: */
+    const QMimeData *pMimeData = pEvent->mimeData();
+    AssertPtrReturnVoid(pMimeData);
+
+    /* Make sure mime-data format is valid: */
+    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
+        return;
+
+    /* Reset token: */
+    m_pItemToken = 0;
+    m_fDropAfterTokenItem = true;
+
+    /* Get event position: */
+    const QPoint pos = pEvent->pos();
+    /* Search for most suitable item: */
+    foreach (UITabBarItem *pItem, m_aItems)
+    {
+        /* Advance token: */
+        m_pItemToken = pItem;
+        const QRect geo = m_pItemToken->geometry();
+        if (pos.x() < geo.center().x())
+        {
+            m_fDropAfterTokenItem = false;
+            break;
+        }
+    }
+
+    /* Update: */
+    update();
+}
+
+void UITabBar::dragLeaveEvent(QDragLeaveEvent * /* pEvent */)
+{
+    /* Reset token: */
+    m_pItemToken = 0;
+    m_fDropAfterTokenItem = true;
+
+    /* Update: */
+    update();
+}
+
+void UITabBar::dropEvent(QDropEvent *pEvent)
+{
+    /* Make sure event is valid: */
+    AssertPtrReturnVoid(pEvent);
+    /* And mime-data is set: */
+    const QMimeData *pMimeData = pEvent->mimeData();
+    AssertPtrReturnVoid(pMimeData);
+
+    /* Make sure mime-data format is valid: */
+    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
+        return;
+
+    /* Make sure token-item set: */
+    if (!m_pItemToken)
+        return;
+
+    /* Determine ID of token-item: */
+    const QUuid tokenUuid = m_pItemToken->uuid();
+    /* Determine ID of dropped-item: */
+    const QUuid droppedUuid = pMimeData->data(UITabBarItem::MimeType);
+
+    /* Make sure these uuids are different: */
+    if (droppedUuid == tokenUuid)
+        return;
+
+    /* Search for an item with dropped ID: */
+    UITabBarItem *pItemDropped = 0;
+    foreach (UITabBarItem *pItem, m_aItems)
+    {
+        if (pItem->uuid() == droppedUuid)
+        {
+            pItemDropped = pItem;
+            break;
+        }
+    }
+
+    /* Make sure dropped-item found: */
+    if (!pItemDropped)
+        return;
+
+    /* Remove dropped-item: */
+    m_aItems.removeAll(pItemDropped);
+    m_pLayoutTab->removeWidget(pItemDropped);
+    /* Insert dropped-item into position of token-item: */
+    int iPosition = m_aItems.indexOf(m_pItemToken);
+    AssertReturnVoid(iPosition != -1);
+    if (m_fDropAfterTokenItem)
+        ++iPosition;
+    m_aItems.insert(iPosition, pItemDropped);
+    m_pLayoutTab->insertWidget(iPosition, pItemDropped);
+}
+
 void UITabBar::sltHandleMakeChildCurrent(UITabBarItem *pItem)
 {
@@ -501,6 +707,19 @@
 }
 
+void UITabBar::sltHandleDragObjectDestroy()
+{
+    /* Reset token: */
+    m_pItemToken = 0;
+    m_fDropAfterTokenItem = true;
+
+    /* Update: */
+    update();
+}
+
 void UITabBar::prepare()
 {
+    /* Track D&D events: */
+    setAcceptDrops(true);
+
     /* Create main layout: */
     m_pLayoutMain = new QHBoxLayout(this);
Index: /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.h	(revision 68297)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.h	(revision 68298)
@@ -26,6 +26,11 @@
 
 /* Forward declarations: */
+class QDragEnterEvent;
+class QDragLeaveEvent;
+class QDragMoveEvent;
+class QDropEvent;
 class QHBoxLayout;
 class QIcon;
+class QPaintEvent;
 class QString;
 class QUuid;
@@ -62,4 +67,18 @@
     bool setCurrent(const QUuid &uuid);
 
+protected:
+
+    /** Handles paint @a pEvent. */
+    virtual void paintEvent(QPaintEvent *pEvent) /* override */;
+
+    /** Handles drag-enter @a pEvent. */
+    virtual void dragEnterEvent(QDragEnterEvent *pEvent) /* override */;
+    /** Handles drag-move @a pEvent. */
+    virtual void dragMoveEvent(QDragMoveEvent *pEvent) /* override */;
+    /** Handles drag-leave @a pEvent. */
+    virtual void dragLeaveEvent(QDragLeaveEvent *pEvent) /* override */;
+    /** Handles drop @a pEvent. */
+    virtual void dropEvent(QDropEvent *pEvent) /* override */;
+
 private slots:
 
@@ -69,4 +88,7 @@
     /** Handles request to close @a pItem. */
     void sltHandleChildClose(UITabBarItem *pItem);
+
+    /** Handles drag object destruction. */
+    void sltHandleDragObjectDestroy();
 
 private:
@@ -88,4 +110,13 @@
         QList<UITabBarItem*> m_aItems;
     /** @} */
+
+    /** @name Contents: Order
+      * @{ */
+        /** Holds the token-item to drop dragged-item nearby. */
+        UITabBarItem *m_pItemToken;
+
+        /** Holds whether the dragged-item should be dropped <b>after</b> the token-item. */
+        bool  m_fDropAfterTokenItem;
+    /** @} */
 };
 
