VirtualBox

Changeset 68298 in vbox for trunk


Ignore:
Timestamp:
Aug 4, 2017 10:30:55 AM (7 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:8900: UITabBar: Allow to reorder items.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/widgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.cpp

    r68296 r68298  
    2222/* Qt includes: */
    2323# include <QApplication>
     24# include <QDrag>
     25# include <QDragEnterEvent>
     26# include <QDragMoveEvent>
     27# include <QDropEvent>
    2428# include <QEvent>
    2529# include <QHBoxLayout>
    2630# include <QLabel>
     31# include <QMimeData>
    2732# include <QMouseEvent>
     33# include <QStyleOption>
    2834# include <QPainter>
    2935# ifdef VBOX_WS_MAC
     
    4349/* Forward declarations: */
    4450class QApplication;
     51class QDrag;
    4552class QEvent;
    4653class QHBoxLayout;
    4754class QLabel;
     55class QMimeData;
    4856class QMouseEvent;
    4957#ifdef VBOX_WS_MAC
     
    5159#endif
    5260class QStyle;
     61class QStyleOption;
    5362class QToolButton;
    5463
     
    6776    void sigCloseClicked(UITabBarItem *pItem);
    6877
     78    /** Notifies about drag-object destruction. */
     79    void sigDragObjectDestroy();
     80
    6981public:
     82
     83    /** Holds the mime-type for the D&D system. */
     84    static const QString MimeType;
    7085
    7186    /** Creates tab-bar item on the basis of passed @a uuid, @a icon and @a strName. */
     
    87102    virtual void paintEvent(QPaintEvent *pEvent) /* override */;
    88103
     104    /** Handles mouse-press @a pEvent. */
     105    virtual void mousePressEvent(QMouseEvent *pEvent) /* override */;
    89106    /** Handles mouse-release @a pEvent. */
    90107    virtual void mouseReleaseEvent(QMouseEvent *pEvent) /* override */;
     108    /** Handles mouse-move @a pEvent. */
     109    virtual void mouseMoveEvent(QMouseEvent *pEvent) /* override */;
    91110    /** Handles mouse-enter @a pEvent. */
    92111    virtual void enterEvent(QEvent *pEvent) /* override */;
     
    129148    /** Holds the close button instance. */
    130149    QToolButton *m_pButtonClose;
     150
     151    /** Holds the last mouse-press position. */
     152    QPoint m_mousePressPosition;
    131153};
    132154
     
    135157*   Class UITabBarItem implementation.                                                                                           *
    136158*********************************************************************************************************************************/
     159
     160/* static */
     161const QString UITabBarItem::MimeType = QString("application/virtualbox;value=TabID");
    137162
    138163UITabBarItem::UITabBarItem(const QUuid &uuid, const QIcon &icon /* = QIcon() */, const QString &strName /* = QString() */)
     
    247272}
    248273
     274void UITabBarItem::mousePressEvent(QMouseEvent *pEvent)
     275{
     276    /* We are interested in left button only: */
     277    if (pEvent->button() != Qt::LeftButton)
     278        return QWidget::mousePressEvent(pEvent);
     279
     280    /* Remember mouse-press position: */
     281    m_mousePressPosition = pEvent->globalPos();
     282}
     283
    249284void UITabBarItem::mouseReleaseEvent(QMouseEvent *pEvent)
    250285{
     
    253288        return QWidget::mouseReleaseEvent(pEvent);
    254289
     290    /* Forget mouse-press position: */
     291    m_mousePressPosition = QPoint();
     292
    255293    /* Notify listeners about the item was clicked: */
    256294    emit sigClicked(this);
     295}
     296
     297void UITabBarItem::mouseMoveEvent(QMouseEvent *pEvent)
     298{
     299    /* Make sure item isn't already dragged: */
     300    if (m_mousePressPosition.isNull())
     301        return QWidget::mouseMoveEvent(pEvent);
     302
     303    /* Make sure item is now being dragged: */
     304    if (QLineF(pEvent->globalPos(), m_mousePressPosition).length() < QApplication::startDragDistance())
     305        return QWidget::mouseMoveEvent(pEvent);
     306
     307    /* Revoke hovered state: */
     308    m_fHovered = false;
     309    /* And call for repaint: */
     310    update();
     311
     312    /* Initialize dragging: */
     313    m_mousePressPosition = QPoint();
     314    QDrag *pDrag = new QDrag(this);
     315    connect(pDrag, &QObject::destroyed, this, &UITabBarItem::sigDragObjectDestroy);
     316    QMimeData *pMimeData = new QMimeData;
     317    pMimeData->setData(MimeType, uuid().toByteArray());
     318    pDrag->setMimeData(pMimeData);
     319    const int iMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
     320    pDrag->setPixmap(icon().pixmap(iMetric, iMetric));
     321    pDrag->exec();
    257322}
    258323
     
    385450    , m_pLayoutTab(0)
    386451    , m_pCurrentItem(0)
     452    , m_pItemToken(0)
     453    , m_fDropAfterTokenItem(0)
    387454{
    388455    /* Prepare: */
     
    399466    {
    400467        /* Configure item: */
    401         connect(pItem, &UITabBarItem::sigClicked,      this, &UITabBar::sltHandleMakeChildCurrent);
    402         connect(pItem, &UITabBarItem::sigCloseClicked, this, &UITabBar::sltHandleChildClose);
     468        connect(pItem, &UITabBarItem::sigClicked,           this, &UITabBar::sltHandleMakeChildCurrent);
     469        connect(pItem, &UITabBarItem::sigCloseClicked,      this, &UITabBar::sltHandleChildClose);
     470        connect(pItem, &UITabBarItem::sigDragObjectDestroy, this, &UITabBar::sltHandleDragObjectDestroy);
    403471        /* Add item into layout and list: */
    404472        m_pLayoutTab->insertWidget(0, pItem);
     
    472540}
    473541
     542void UITabBar::paintEvent(QPaintEvent *pEvent)
     543{
     544    /* Call to base-class: */
     545    QWidget::paintEvent(pEvent);
     546
     547    /* If we have a token item: */
     548    if (m_pItemToken)
     549    {
     550        /* Prepare painter: */
     551        QPainter painter(this);
     552
     553        /* Paint drop token: */
     554        QStyleOption option;
     555        option.state |= QStyle::State_Horizontal;
     556        const QRect geo = m_pItemToken->geometry();
     557        option.rect = !m_fDropAfterTokenItem
     558                    ? QRect(geo.topLeft() - QPoint(5, 5),
     559                            geo.bottomLeft() + QPoint(0, 5))
     560                    : QRect(geo.topRight() - QPoint(0, 5),
     561                            geo.bottomRight() + QPoint(5, 5));
     562        QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator,
     563                                             &option, &painter);
     564    }
     565}
     566
     567void UITabBar::dragEnterEvent(QDragEnterEvent *pEvent)
     568{
     569    /* Make sure event is valid: */
     570    AssertPtrReturnVoid(pEvent);
     571    /* And mime-data is set: */
     572    const QMimeData *pMimeData = pEvent->mimeData();
     573    AssertPtrReturnVoid(pMimeData);
     574
     575    /* Make sure mime-data format is valid: */
     576    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
     577        return;
     578
     579    /* Accept drag-enter event: */
     580    pEvent->acceptProposedAction();
     581}
     582
     583void UITabBar::dragMoveEvent(QDragMoveEvent *pEvent)
     584{
     585    /* Make sure event is valid: */
     586    AssertPtrReturnVoid(pEvent);
     587    /* And mime-data is set: */
     588    const QMimeData *pMimeData = pEvent->mimeData();
     589    AssertPtrReturnVoid(pMimeData);
     590
     591    /* Make sure mime-data format is valid: */
     592    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
     593        return;
     594
     595    /* Reset token: */
     596    m_pItemToken = 0;
     597    m_fDropAfterTokenItem = true;
     598
     599    /* Get event position: */
     600    const QPoint pos = pEvent->pos();
     601    /* Search for most suitable item: */
     602    foreach (UITabBarItem *pItem, m_aItems)
     603    {
     604        /* Advance token: */
     605        m_pItemToken = pItem;
     606        const QRect geo = m_pItemToken->geometry();
     607        if (pos.x() < geo.center().x())
     608        {
     609            m_fDropAfterTokenItem = false;
     610            break;
     611        }
     612    }
     613
     614    /* Update: */
     615    update();
     616}
     617
     618void UITabBar::dragLeaveEvent(QDragLeaveEvent * /* pEvent */)
     619{
     620    /* Reset token: */
     621    m_pItemToken = 0;
     622    m_fDropAfterTokenItem = true;
     623
     624    /* Update: */
     625    update();
     626}
     627
     628void UITabBar::dropEvent(QDropEvent *pEvent)
     629{
     630    /* Make sure event is valid: */
     631    AssertPtrReturnVoid(pEvent);
     632    /* And mime-data is set: */
     633    const QMimeData *pMimeData = pEvent->mimeData();
     634    AssertPtrReturnVoid(pMimeData);
     635
     636    /* Make sure mime-data format is valid: */
     637    if (!pMimeData->hasFormat(UITabBarItem::MimeType))
     638        return;
     639
     640    /* Make sure token-item set: */
     641    if (!m_pItemToken)
     642        return;
     643
     644    /* Determine ID of token-item: */
     645    const QUuid tokenUuid = m_pItemToken->uuid();
     646    /* Determine ID of dropped-item: */
     647    const QUuid droppedUuid = pMimeData->data(UITabBarItem::MimeType);
     648
     649    /* Make sure these uuids are different: */
     650    if (droppedUuid == tokenUuid)
     651        return;
     652
     653    /* Search for an item with dropped ID: */
     654    UITabBarItem *pItemDropped = 0;
     655    foreach (UITabBarItem *pItem, m_aItems)
     656    {
     657        if (pItem->uuid() == droppedUuid)
     658        {
     659            pItemDropped = pItem;
     660            break;
     661        }
     662    }
     663
     664    /* Make sure dropped-item found: */
     665    if (!pItemDropped)
     666        return;
     667
     668    /* Remove dropped-item: */
     669    m_aItems.removeAll(pItemDropped);
     670    m_pLayoutTab->removeWidget(pItemDropped);
     671    /* Insert dropped-item into position of token-item: */
     672    int iPosition = m_aItems.indexOf(m_pItemToken);
     673    AssertReturnVoid(iPosition != -1);
     674    if (m_fDropAfterTokenItem)
     675        ++iPosition;
     676    m_aItems.insert(iPosition, pItemDropped);
     677    m_pLayoutTab->insertWidget(iPosition, pItemDropped);
     678}
     679
    474680void UITabBar::sltHandleMakeChildCurrent(UITabBarItem *pItem)
    475681{
     
    501707}
    502708
     709void UITabBar::sltHandleDragObjectDestroy()
     710{
     711    /* Reset token: */
     712    m_pItemToken = 0;
     713    m_fDropAfterTokenItem = true;
     714
     715    /* Update: */
     716    update();
     717}
     718
    503719void UITabBar::prepare()
    504720{
     721    /* Track D&D events: */
     722    setAcceptDrops(true);
     723
    505724    /* Create main layout: */
    506725    m_pLayoutMain = new QHBoxLayout(this);
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UITabBar.h

    r68295 r68298  
    2626
    2727/* Forward declarations: */
     28class QDragEnterEvent;
     29class QDragLeaveEvent;
     30class QDragMoveEvent;
     31class QDropEvent;
    2832class QHBoxLayout;
    2933class QIcon;
     34class QPaintEvent;
    3035class QString;
    3136class QUuid;
     
    6267    bool setCurrent(const QUuid &uuid);
    6368
     69protected:
     70
     71    /** Handles paint @a pEvent. */
     72    virtual void paintEvent(QPaintEvent *pEvent) /* override */;
     73
     74    /** Handles drag-enter @a pEvent. */
     75    virtual void dragEnterEvent(QDragEnterEvent *pEvent) /* override */;
     76    /** Handles drag-move @a pEvent. */
     77    virtual void dragMoveEvent(QDragMoveEvent *pEvent) /* override */;
     78    /** Handles drag-leave @a pEvent. */
     79    virtual void dragLeaveEvent(QDragLeaveEvent *pEvent) /* override */;
     80    /** Handles drop @a pEvent. */
     81    virtual void dropEvent(QDropEvent *pEvent) /* override */;
     82
    6483private slots:
    6584
     
    6988    /** Handles request to close @a pItem. */
    7089    void sltHandleChildClose(UITabBarItem *pItem);
     90
     91    /** Handles drag object destruction. */
     92    void sltHandleDragObjectDestroy();
    7193
    7294private:
     
    88110        QList<UITabBarItem*> m_aItems;
    89111    /** @} */
     112
     113    /** @name Contents: Order
     114      * @{ */
     115        /** Holds the token-item to drop dragged-item nearby. */
     116        UITabBarItem *m_pItemToken;
     117
     118        /** Holds whether the dragged-item should be dropped <b>after</b> the token-item. */
     119        bool  m_fDropAfterTokenItem;
     120    /** @} */
    90121};
    91122
Note: See TracChangeset for help on using the changeset viewer.

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