VirtualBox

Changeset 73948 in vbox


Ignore:
Timestamp:
Aug 29, 2018 12:31:13 PM (6 years ago)
Author:
vboxsync
Message:

FE/Qt: VirtualBox Manager UI: Large cleanup for UIChooserItemGroup, doxygen + style fixes.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItem.h

    r73927 r73948  
    8282signals:
    8383
    84     /** @name Basic stuff.
     84    /** @name Item stuff.
    8585      * @{ */
    8686        /** Notifies listeners about hover enter. */
     
    190190        void updateGeometry();
    191191
    192         /** Updates layout.  */
     192        /** Updates layout. */
    193193        virtual void updateLayout() = 0;
    194194
     
    227227protected:
    228228
    229     /** @name Event-processing stuff.
     229    /** @name Event-handling stuff.
    230230      * @{ */
    231231        /** Handles hover enter @a event. */
    232         void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);
     232        virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */;
    233233        /** Handles hover leave @a event. */
    234         void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);
     234        virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */;
    235235
    236236        /** Handles mouse press @a event. */
    237         void mousePressEvent(QGraphicsSceneMouseEvent *pEvent);
     237        virtual void mousePressEvent(QGraphicsSceneMouseEvent *pEvent) /* override */;
    238238        /** Handles mouse move @a event. */
    239         void mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent);
     239        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *pEvent) /* override */;
    240240
    241241        /** Handles drag move @a event. */
    242         void dragMoveEvent(QGraphicsSceneDragDropEvent *pEvent);
     242        virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */;
    243243        /** Handles drag leave @a event. */
    244         void dragLeaveEvent(QGraphicsSceneDragDropEvent *pEvent);
     244        virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */;
    245245        /** Handles drop @a event. */
    246         void dropEvent(QGraphicsSceneDragDropEvent *pEvent);
     246        virtual void dropEvent(QGraphicsSceneDragDropEvent *pEvent) /* override */;
    247247    /** @} */
    248248
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemGroup.cpp

    r73927 r73948  
    55
    66/*
    7  * Copyright (C) 2012-2017 Oracle Corporation
     7 * Copyright (C) 2012-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121
    2222/* Qt includes: */
     23# include <QGraphicsScene>
     24# include <QGraphicsSceneDragDropEvent>
     25# include <QHBoxLayout>
     26# include <QLineEdit>
     27# include <QMenu>
    2328# include <QPainter>
    2429# include <QStyleOptionGraphicsItem>
    25 # include <QGraphicsSceneDragDropEvent>
    26 # include <QLineEdit>
    27 # include <QGraphicsScene>
    28 # include <QHBoxLayout>
    29 # include <QMenu>
    3030
    3131/* GUI includes: */
     
    4444
    4545
    46 /* static */
    47 QString UIChooserItemGroup::className() { return "UIChooserItemGroup"; }
     46/*********************************************************************************************************************************
     47*   Class UIChooserItemGroup implementation.                                                                                     *
     48*********************************************************************************************************************************/
    4849
    4950UIChooserItemGroup::UIChooserItemGroup(QGraphicsScene *pScene)
    5051    : UIChooserItem(0, false /* temporary? */)
     52    , m_fMainRoot(true)
    5153    , m_fClosed(false)
    52     , m_fMainRoot(true)
     54    , m_iAdditionalHeight(0)
     55    , m_iCornerRadius(0)
     56    , m_iBlackoutDarkness(0)
     57    , m_pToggleButton(0)
     58    , m_pEnterButton(0)
     59    , m_pExitButton(0)
     60    , m_pNameEditorWidget(0)
     61    , m_pNameEditor(0)
    5362{
    5463    /* Prepare: */
     
    6271    retranslateUi();
    6372
    64     /* Prepare main-root-item connections: */
    65     connect(this, SIGNAL(sigMinimumWidthHintChanged(int)),
    66             model(), SIGNAL(sigRootItemMinimumWidthHintChanged(int)));
    67     connect(this, SIGNAL(sigMinimumHeightHintChanged(int)),
    68             model(), SIGNAL(sigRootItemMinimumHeightHintChanged(int)));
     73    /* Prepare connections: */
     74    connect(this, &UIChooserItemGroup::sigMinimumWidthHintChanged,
     75            model(), &UIChooserModel::sigRootItemMinimumWidthHintChanged);
     76    connect(this, &UIChooserItemGroup::sigMinimumHeightHintChanged,
     77            model(), &UIChooserModel::sigRootItemMinimumHeightHintChanged);
    6978}
    7079
    7180UIChooserItemGroup::UIChooserItemGroup(QGraphicsScene *pScene,
    72                                          UIChooserItemGroup *pCopyFrom,
    73                                          bool fMainRoot)
     81                                       UIChooserItemGroup *pCopyFrom,
     82                                       bool fMainRoot)
    7483    : UIChooserItem(0, true /* temporary? */)
     84    , m_fMainRoot(fMainRoot)
    7585    , m_fClosed(pCopyFrom->isClosed())
    76     , m_fMainRoot(fMainRoot)
     86    , m_iAdditionalHeight(0)
     87    , m_iCornerRadius(0)
     88    , m_iBlackoutDarkness(0)
    7789    , m_strName(pCopyFrom->name())
     90    , m_pToggleButton(0)
     91    , m_pEnterButton(0)
     92    , m_pExitButton(0)
     93    , m_pNameEditorWidget(0)
     94    , m_pNameEditor(0)
    7895{
    7996    /* Prepare: */
     
    97114
    98115UIChooserItemGroup::UIChooserItemGroup(UIChooserItem *pParent,
    99                                          const QString &strName,
    100                                          bool fOpened /* = false */,
    101                                          int iPosition /* = -1 */)
     116                                       const QString &strName,
     117                                       bool fOpened /* = false */,
     118                                       int iPosition /* = -1 */)
    102119    : UIChooserItem(pParent, pParent->isTemporary())
     120    , m_fMainRoot(false)
    103121    , m_fClosed(!fOpened)
    104     , m_fMainRoot(false)
     122    , m_iAdditionalHeight(0)
     123    , m_iCornerRadius(0)
     124    , m_iBlackoutDarkness(0)
    105125    , m_strName(strName)
     126    , m_pToggleButton(0)
     127    , m_pEnterButton(0)
     128    , m_pExitButton(0)
     129    , m_pNameEditorWidget(0)
     130    , m_pNameEditor(0)
    106131{
    107132    /* Prepare: */
     
    112137    parentItem()->addItem(this, iPosition);
    113138    setZValue(parentItem()->zValue() + 1);
    114     connect(this, SIGNAL(sigToggleStarted()), model(), SIGNAL(sigToggleStarted()));
    115     connect(this, SIGNAL(sigToggleFinished()), model(), SIGNAL(sigToggleFinished()), Qt::QueuedConnection);
     139    connect(this, &UIChooserItemGroup::sigToggleStarted,
     140            model(), &UIChooserModel::sigToggleStarted);
     141    connect(this, &UIChooserItemGroup::sigToggleFinished,
     142            model(), &UIChooserModel::sigToggleFinished,
     143            Qt::QueuedConnection);
    116144    connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped,
    117145            this, &UIChooserItemGroup::sltHandleWindowRemapped);
     
    126154    updateToolTip();
    127155
    128     /* Prepare root-item connections: */
    129     connect(this, SIGNAL(sigMinimumWidthHintChanged(int)),
    130             model(), SIGNAL(sigRootItemMinimumWidthHintChanged(int)));
    131     connect(this, SIGNAL(sigMinimumHeightHintChanged(int)),
    132             model(), SIGNAL(sigRootItemMinimumHeightHintChanged(int)));
     156    /* Prepare connections: */
     157    connect(this, &UIChooserItemGroup::sigMinimumWidthHintChanged,
     158            model(), &UIChooserModel::sigRootItemMinimumWidthHintChanged);
     159    connect(this, &UIChooserItemGroup::sigMinimumHeightHintChanged,
     160            model(), &UIChooserModel::sigRootItemMinimumHeightHintChanged);
    133161}
    134162
    135163UIChooserItemGroup::UIChooserItemGroup(UIChooserItem *pParent,
    136                                          UIChooserItemGroup *pCopyFrom,
    137                                          int iPosition /* = -1 */)
     164                                       UIChooserItemGroup *pCopyFrom,
     165                                       int iPosition /* = -1 */)
    138166    : UIChooserItem(pParent, pParent->isTemporary())
     167    , m_fMainRoot(false)
    139168    , m_fClosed(pCopyFrom->isClosed())
    140     , m_fMainRoot(false)
     169    , m_iAdditionalHeight(0)
     170    , m_iCornerRadius(0)
     171    , m_iBlackoutDarkness(0)
    141172    , m_strName(pCopyFrom->name())
     173    , m_pToggleButton(0)
     174    , m_pEnterButton(0)
     175    , m_pExitButton(0)
     176    , m_pNameEditorWidget(0)
     177    , m_pNameEditor(0)
    142178{
    143179    /* Prepare: */
     
    148184    parentItem()->addItem(this, iPosition);
    149185    setZValue(parentItem()->zValue() + 1);
    150     connect(this, SIGNAL(sigToggleStarted()), model(), SIGNAL(sigToggleStarted()));
    151     connect(this, SIGNAL(sigToggleFinished()), model(), SIGNAL(sigToggleFinished()));
     186    connect(this, &UIChooserItemGroup::sigToggleStarted,
     187            model(), &UIChooserModel::sigToggleStarted);
     188    connect(this, &UIChooserItemGroup::sigToggleFinished,
     189            model(), &UIChooserModel::sigToggleFinished);
    152190    connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped,
    153191            this, &UIChooserItemGroup::sltHandleWindowRemapped);
     
    193231    if (parentItem())
    194232        parentItem()->removeItem(this);
     233}
     234
     235void UIChooserItemGroup::setName(const QString &strName)
     236{
     237    /* Something changed? */
     238    if (m_strName == strName)
     239        return;
     240
     241    /* Remember new name: */
     242    m_strName = strName;
     243
     244    /* Update linked values: */
     245    updateVisibleName();
     246    updateMinimumHeaderSize();
     247}
     248
     249void UIChooserItemGroup::close(bool fAnimated /* = true */)
     250{
     251    AssertMsg(!isRoot(), ("Can't close root-item!"));
     252    m_pToggleButton->setToggled(false, fAnimated);
     253}
     254
     255bool UIChooserItemGroup::isClosed() const
     256{
     257    return m_fClosed && !isRoot();
     258}
     259
     260void UIChooserItemGroup::open(bool fAnimated /* = true */)
     261{
     262    AssertMsg(!isRoot(), ("Can't open root-item!"));
     263    m_pToggleButton->setToggled(true, fAnimated);
     264}
     265
     266bool UIChooserItemGroup::isOpened() const
     267{
     268    return !m_fClosed || isRoot();
     269}
     270
     271/* static */
     272QString UIChooserItemGroup::className()
     273{
     274    return "UIChooserItemGroup";
     275}
     276
     277void UIChooserItemGroup::retranslateUi()
     278{
     279    /* Update description: */
     280    m_strDescription = tr("Virtual Machine group");
     281
     282    /* Update group tool-tip: */
     283    updateToolTip();
     284
     285    /* Update button tool-tips: */
     286    if (m_pEnterButton)
     287        m_pEnterButton->setToolTip(tr("Enter group"));
     288    if (m_pExitButton)
     289        m_pExitButton->setToolTip(tr("Exit group"));
     290    updateToggleButtonToolTip();
     291}
     292
     293void UIChooserItemGroup::showEvent(QShowEvent *pEvent)
     294{
     295    /* Call to base-class: */
     296    UIChooserItem::showEvent(pEvent);
     297
     298    /* Update pixmaps: */
     299    updatePixmaps();
     300}
     301
     302void UIChooserItemGroup::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
     303{
     304    /* Call to base-class: */
     305    UIChooserItem::resizeEvent(pEvent);
     306
     307    /* What is the new geometry? */
     308    const QRectF newGeometry = geometry();
     309
     310    /* Should we update visible name? */
     311    if (previousGeometry().width() != newGeometry.width())
     312        updateVisibleName();
     313
     314    /* Remember the new geometry: */
     315    setPreviousGeometry(newGeometry);
     316}
     317
     318void UIChooserItemGroup::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)
     319{
     320    /* Skip if hovered: */
     321    if (isHovered())
     322        return;
     323
     324    /* Prepare variables: */
     325    const QPoint pos = pEvent->pos().toPoint();
     326    const int iMargin = data(GroupItemData_VerticalMargin).toInt();
     327    const int iHeaderHeight = m_minimumHeaderSize.height();
     328    const int iFullHeaderHeight = 2 * iMargin + iHeaderHeight;
     329    /* Skip if hovered part out of the header: */
     330    if (pos.y() >= iFullHeaderHeight)
     331        return;
     332
     333    /* Call to base-class: */
     334    UIChooserItem::hoverMoveEvent(pEvent);
     335
     336    /* Update linked values: */
     337    updateVisibleName();
     338}
     339
     340void UIChooserItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)
     341{
     342    /* Skip if not hovered: */
     343    if (!isHovered())
     344        return;
     345
     346    /* Call to base-class: */
     347    UIChooserItem::hoverLeaveEvent(pEvent);
     348
     349    /* Update linked values: */
     350    updateVisibleName();
     351}
     352
     353void UIChooserItemGroup::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget* /* pWidget = 0 */)
     354{
     355    /* Setup: */
     356    pPainter->setRenderHint(QPainter::Antialiasing);
     357
     358    /* Paint background: */
     359    paintBackground(pPainter, pOptions->rect);
     360
     361    /* Paint header: */
     362    paintHeader(pPainter, pOptions->rect);
     363}
     364
     365void UIChooserItemGroup::show()
     366{
     367    /* Call to base-class: */
     368    UIChooserItem::show();
     369    /* Show children: */
     370    if (!isClosed())
     371        foreach (UIChooserItem *pItem, items())
     372            pItem->show();
     373}
     374
     375void UIChooserItemGroup::hide()
     376{
     377    /* Call to base-class: */
     378    UIChooserItem::hide();
     379    /* Hide children: */
     380    foreach (UIChooserItem *pItem, items())
     381        pItem->hide();
     382}
     383
     384void UIChooserItemGroup::startEditing()
     385{
     386    /* Not for root: */
     387    if (isRoot())
     388        return;
     389
     390    /* Not while saving groups: */
     391    if (model()->isGroupSavingInProgress())
     392        return;
     393
     394    /* Unlock name-editor: */
     395    m_pNameEditor->show();
     396    m_pNameEditorWidget->setText(name());
     397    m_pNameEditorWidget->setFocus();
     398}
     399
     400void UIChooserItemGroup::updateToolTip()
     401{
     402    /* Not for main root: */
     403    if (isMainRoot())
     404        return;
     405
     406    /* Prepare variables: */
     407    QStringList toolTipInfo;
     408
     409    /* Should we add name? */
     410    if (!name().isEmpty())
     411    {
     412        /* Template: */
     413        QString strTemplateForName = tr("<b>%1</b>", "Group item tool-tip / Group name");
     414
     415        /* Append value: */
     416        toolTipInfo << strTemplateForName.arg(name());
     417    }
     418
     419    /* Should we add group info? */
     420    if (!items(UIChooserItemType_Group).isEmpty())
     421    {
     422        /* Template: */
     423        QString strGroupCount = tr("%n group(s)", "Group item tool-tip / Group info", items(UIChooserItemType_Group).size());
     424
     425        /* Append value: */
     426        QString strValue = tr("<nobr>%1</nobr>", "Group item tool-tip / Group info wrapper").arg(strGroupCount);
     427        toolTipInfo << strValue;
     428    }
     429
     430    /* Should we add machine info? */
     431    if (!items(UIChooserItemType_Machine).isEmpty())
     432    {
     433        /* Check if 'this' group contains started VMs: */
     434        int iCountOfStartedMachineItems = 0;
     435        foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
     436            if (UIVirtualMachineItem::isItemStarted(pItem->toMachineItem()))
     437                ++iCountOfStartedMachineItems;
     438        /* Template: */
     439        QString strMachineCount = tr("%n machine(s)", "Group item tool-tip / Machine info", items(UIChooserItemType_Machine).size());
     440        QString strStartedMachineCount = tr("(%n running)", "Group item tool-tip / Running machine info", iCountOfStartedMachineItems);
     441
     442        /* Append value: */
     443        QString strValue = !iCountOfStartedMachineItems ?
     444                           tr("<nobr>%1</nobr>", "Group item tool-tip / Machine info wrapper").arg(strMachineCount) :
     445                           tr("<nobr>%1 %2</nobr>", "Group item tool-tip / Machine info wrapper, including running").arg(strMachineCount).arg(strStartedMachineCount);
     446        toolTipInfo << strValue;
     447    }
     448
     449    /* Set tool-tip: */
     450    setToolTip(toolTipInfo.join("<br>"));
    195451}
    196452
     
    224480}
    225481
    226 void UIChooserItemGroup::setName(const QString &strName)
    227 {
    228     /* Something changed? */
    229     if (m_strName == strName)
    230         return;
    231 
    232     /* Remember new name: */
    233     m_strName = strName;
     482void UIChooserItemGroup::handleRootStatusChange()
     483{
     484    /* Call to base-class: */
     485    UIChooserItem::handleRootStatusChange();
    234486
    235487    /* Update linked values: */
     
    238490}
    239491
    240 bool UIChooserItemGroup::isClosed() const
    241 {
    242     return m_fClosed && !isRoot();
    243 }
    244 
    245 bool UIChooserItemGroup::isOpened() const
    246 {
    247     return !m_fClosed || isRoot();
    248 }
    249 
    250 void UIChooserItemGroup::close(bool fAnimated /* = true */)
    251 {
    252     AssertMsg(!isRoot(), ("Can't close root-item!"));
    253     m_pToggleButton->setToggled(false, fAnimated);
    254 }
    255 
    256 void UIChooserItemGroup::open(bool fAnimated /* = true */)
    257 {
    258     AssertMsg(!isRoot(), ("Can't open root-item!"));
    259     m_pToggleButton->setToggled(true, fAnimated);
    260 }
    261 
    262 bool UIChooserItemGroup::isContainsMachine(const QString &strId) const
    263 {
    264     /* Check each machine-item: */
    265     foreach (UIChooserItem *pItem, m_machineItems)
    266         if (pItem->toMachineItem()->id() == strId)
    267             return true;
     492void UIChooserItemGroup::addItem(UIChooserItem *pItem, int iPosition)
     493{
     494    /* Check item type: */
     495    switch (pItem->type())
     496    {
     497        case UIChooserItemType_Group:
     498        {
     499            AssertMsg(!m_groupItems.contains(pItem), ("Group-item already added!"));
     500            if (iPosition < 0 || iPosition >= m_groupItems.size())
     501                m_groupItems.append(pItem);
     502            else
     503                m_groupItems.insert(iPosition, pItem);
     504            scene()->addItem(pItem);
     505            break;
     506        }
     507        case UIChooserItemType_Global:
     508        {
     509            AssertMsg(!m_globalItems.contains(pItem), ("Global-item already added!"));
     510            if (iPosition < 0 || iPosition >= m_globalItems.size())
     511                m_globalItems.append(pItem);
     512            else
     513                m_globalItems.insert(iPosition, pItem);
     514            scene()->addItem(pItem);
     515            break;
     516        }
     517        case UIChooserItemType_Machine:
     518        {
     519            AssertMsg(!m_machineItems.contains(pItem), ("Machine-item already added!"));
     520            if (iPosition < 0 || iPosition >= m_machineItems.size())
     521                m_machineItems.append(pItem);
     522            else
     523                m_machineItems.insert(iPosition, pItem);
     524            scene()->addItem(pItem);
     525            break;
     526        }
     527        default:
     528        {
     529            AssertMsgFailed(("Invalid item type!"));
     530            break;
     531        }
     532    }
     533
     534    /* Update linked values: */
     535    updateItemCountInfo();
     536    updateToolTip();
     537    updateGeometry();
     538}
     539
     540void UIChooserItemGroup::removeItem(UIChooserItem *pItem)
     541{
     542    /* Check item type: */
     543    switch (pItem->type())
     544    {
     545        case UIChooserItemType_Group:
     546        {
     547            AssertMsg(m_groupItems.contains(pItem), ("Group-item was not found!"));
     548            scene()->removeItem(pItem);
     549            m_groupItems.removeAt(m_groupItems.indexOf(pItem));
     550            break;
     551        }
     552        case UIChooserItemType_Global:
     553        {
     554            AssertMsg(m_globalItems.contains(pItem), ("Global-item was not found!"));
     555            scene()->removeItem(pItem);
     556            m_globalItems.removeAt(m_globalItems.indexOf(pItem));
     557            break;
     558        }
     559        case UIChooserItemType_Machine:
     560        {
     561            AssertMsg(m_machineItems.contains(pItem), ("Machine-item was not found!"));
     562            scene()->removeItem(pItem);
     563            m_machineItems.removeAt(m_machineItems.indexOf(pItem));
     564            break;
     565        }
     566        default:
     567        {
     568            AssertMsgFailed(("Invalid item type!"));
     569            break;
     570        }
     571    }
     572
     573    /* Update linked values: */
     574    updateItemCountInfo();
     575    updateToolTip();
     576    updateGeometry();
     577}
     578
     579void UIChooserItemGroup::setItems(const QList<UIChooserItem*> &items, UIChooserItemType type)
     580{
     581    /* Check item type: */
     582    switch (type)
     583    {
     584        case UIChooserItemType_Group: m_groupItems = items; break;
     585        case UIChooserItemType_Global: m_globalItems = items; break;
     586        case UIChooserItemType_Machine: m_machineItems = items; break;
     587        default: AssertMsgFailed(("Invalid item type!")); break;
     588    }
     589
     590    /* Update linked values: */
     591    updateItemCountInfo();
     592    updateToolTip();
     593    updateGeometry();
     594}
     595
     596QList<UIChooserItem*> UIChooserItemGroup::items(UIChooserItemType type /* = UIChooserItemType_Any */) const
     597{
     598    switch (type)
     599    {
     600        case UIChooserItemType_Any: return items(UIChooserItemType_Global) + items(UIChooserItemType_Group) + items(UIChooserItemType_Machine);
     601        case UIChooserItemType_Group: return m_groupItems;
     602        case UIChooserItemType_Global: return m_globalItems;
     603        case UIChooserItemType_Machine: return m_machineItems;
     604        default: break;
     605    }
     606    return QList<UIChooserItem*>();
     607}
     608
     609bool UIChooserItemGroup::hasItems(UIChooserItemType type /* = UIChooserItemType_Any */) const
     610{
     611    switch (type)
     612    {
     613        case UIChooserItemType_Any:
     614            return hasItems(UIChooserItemType_Global) || hasItems(UIChooserItemType_Group) || hasItems(UIChooserItemType_Machine);
     615        case UIChooserItemType_Group:
     616            return !m_groupItems.isEmpty();
     617        case UIChooserItemType_Global:
     618            return !m_globalItems.isEmpty();
     619        case UIChooserItemType_Machine:
     620            return !m_machineItems.isEmpty();
     621    }
     622    return false;
     623}
     624
     625void UIChooserItemGroup::clearItems(UIChooserItemType type /* = UIChooserItemType_Any */)
     626{
     627    switch (type)
     628    {
     629        case UIChooserItemType_Any:
     630        {
     631            clearItems(UIChooserItemType_Group);
     632            clearItems(UIChooserItemType_Global);
     633            clearItems(UIChooserItemType_Machine);
     634            break;
     635        }
     636        case UIChooserItemType_Group:
     637        {
     638            while (!m_groupItems.isEmpty()) { delete m_groupItems.last(); }
     639            AssertMsg(m_groupItems.isEmpty(), ("Group items cleanup failed!"));
     640            break;
     641        }
     642        case UIChooserItemType_Global:
     643        {
     644            while (!m_globalItems.isEmpty()) { delete m_globalItems.last(); }
     645            AssertMsg(m_globalItems.isEmpty(), ("Global items cleanup failed!"));
     646            break;
     647        }
     648        case UIChooserItemType_Machine:
     649        {
     650            while (!m_machineItems.isEmpty()) { delete m_machineItems.last(); }
     651            AssertMsg(m_machineItems.isEmpty(), ("Machine items cleanup failed!"));
     652            break;
     653        }
     654    }
     655
     656    /* Update linked values: */
     657    updateItemCountInfo();
     658    updateToolTip();
     659    updateGeometry();
     660}
     661
     662void UIChooserItemGroup::updateAllItems(const QString &strId)
     663{
     664    /* Update all the required items recursively: */
     665    foreach (UIChooserItem *pItem, items())
     666        pItem->updateAllItems(strId);
     667}
     668
     669void UIChooserItemGroup::removeAllItems(const QString &strId)
     670{
     671    /* Remove all the required items recursively: */
     672    foreach (UIChooserItem *pItem, items())
     673        pItem->removeAllItems(strId);
     674}
     675
     676UIChooserItem* UIChooserItemGroup::searchForItem(const QString &strSearchTag, int iItemSearchFlags)
     677{
     678    /* Are we searching among group-items? */
     679    if (iItemSearchFlags & UIChooserItemSearchFlag_Group)
     680    {
     681        /* Are we searching by the exact name? */
     682        if (iItemSearchFlags & UIChooserItemSearchFlag_ExactName)
     683        {
     684            /* Exact name matches? */
     685            if (name() == strSearchTag)
     686                return this;
     687        }
     688        /* Are we searching by the few first symbols? */
     689        else
     690        {
     691            /* Name starts with passed symbols? */
     692            if (name().startsWith(strSearchTag, Qt::CaseInsensitive))
     693                return this;
     694        }
     695    }
     696
     697    /* Search among all the children, but machines first: */
     698    foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
     699        if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
     700            return pFoundItem;
     701    foreach (UIChooserItem *pItem, items(UIChooserItemType_Global))
     702        if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
     703            return pFoundItem;
     704    foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
     705        if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
     706            return pFoundItem;
     707
    268708    /* Found nothing? */
     709    return 0;
     710}
     711
     712UIChooserItem *UIChooserItemGroup::firstMachineItem()
     713{
     714    /* If this group-item have at least one machine-item: */
     715    if (hasItems(UIChooserItemType_Machine))
     716        /* Return the first machine-item: */
     717        return items(UIChooserItemType_Machine).first()->firstMachineItem();
     718    /* If this group-item have at least one group-item: */
     719    else if (hasItems(UIChooserItemType_Group))
     720        /* Return the first machine-item of the first group-item: */
     721        return items(UIChooserItemType_Group).first()->firstMachineItem();
     722    /* Found nothing? */
     723    return 0;
     724}
     725
     726void UIChooserItemGroup::sortItems()
     727{
     728    /* Sort group-items: */
     729    QMap<QString, UIChooserItem*> sorter;
     730    foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
     731        sorter.insert(pItem->name().toLower(), pItem);
     732    setItems(sorter.values(), UIChooserItemType_Group);
     733
     734    /* Sort machine-items: */
     735    sorter.clear();
     736    foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
     737        sorter.insert(pItem->name().toLower(), pItem);
     738    setItems(sorter.values(), UIChooserItemType_Machine);
     739
     740    /* Update model: */
     741    model()->updateNavigation();
     742    model()->updateLayout();
     743}
     744
     745void UIChooserItemGroup::updateLayout()
     746{
     747    /* Prepare variables: */
     748    int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
     749    int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();
     750    int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();
     751    int iFullHeaderHeight = m_minimumHeaderSize.height();
     752    int iRootIndent = data(GroupItemData_RootIndent).toInt();
     753    int iPreviousVerticalIndent = 0;
     754
     755    /* Header (root-item): */
     756    if (isRoot())
     757    {
     758        /* Header (main root-item): */
     759        if (isMainRoot())
     760        {
     761            /* Prepare body indent: */
     762            iPreviousVerticalIndent = iRootIndent;
     763        }
     764        /* Header (non-main root-item): */
     765        else
     766        {
     767            /* Hide unnecessary buttons: */
     768            if (m_pToggleButton)
     769                m_pToggleButton->hide();
     770            if (m_pEnterButton)
     771                m_pEnterButton->hide();
     772
     773            /* Exit-button: */
     774            if (m_pExitButton)
     775            {
     776                /* Prepare variables: */
     777                int iExitButtonHeight = m_exitButtonSize.height();
     778                /* Layout exit-button: */
     779                int iExitButtonX = iHorizontalMargin + iRootIndent;
     780                int iExitButtonY = iExitButtonHeight == iFullHeaderHeight ? iVerticalMargin :
     781                                   iVerticalMargin + (iFullHeaderHeight - iExitButtonHeight) / 2;
     782                m_pExitButton->setPos(iExitButtonX, iExitButtonY);
     783                /* Show exit-button: */
     784                m_pExitButton->show();
     785            }
     786
     787            /* Prepare body indent: */
     788            iPreviousVerticalIndent = iVerticalMargin + iFullHeaderHeight + iVerticalMargin + iMinorSpacing;
     789        }
     790    }
     791    /* Header (non-root-item): */
     792    else
     793    {
     794        /* Hide unnecessary button: */
     795        if (m_pExitButton)
     796            m_pExitButton->hide();
     797
     798        /* Toggle-button: */
     799        if (m_pToggleButton)
     800        {
     801            /* Prepare variables: */
     802            int iToggleButtonHeight = m_toggleButtonSize.height();
     803            /* Layout toggle-button: */
     804            int iToggleButtonX = iHorizontalMargin;
     805            int iToggleButtonY = iToggleButtonHeight == iFullHeaderHeight ? iVerticalMargin :
     806                                 iVerticalMargin + (iFullHeaderHeight - iToggleButtonHeight) / 2;
     807            m_pToggleButton->setPos(iToggleButtonX, iToggleButtonY);
     808            /* Show toggle-button: */
     809            m_pToggleButton->show();
     810        }
     811
     812        /* Enter-button: */
     813        if (m_pEnterButton)
     814        {
     815            /* Prepare variables: */
     816            int iFullWidth = (int)geometry().width();
     817            int iEnterButtonWidth = m_enterButtonSize.width();
     818            int iEnterButtonHeight = m_enterButtonSize.height();
     819            /* Layout enter-button: */
     820            int iEnterButtonX = iFullWidth - iHorizontalMargin - iEnterButtonWidth;
     821            int iEnterButtonY = iEnterButtonHeight == iFullHeaderHeight ? iVerticalMargin :
     822                                iVerticalMargin + (iFullHeaderHeight - iEnterButtonHeight) / 2;
     823            m_pEnterButton->setPos(iEnterButtonX, iEnterButtonY);
     824        }
     825
     826        /* Name-editor: */
     827        if (m_pNameEditor && m_pNameEditorWidget)
     828        {
     829            /* Prepare variables: */
     830            int iMajorSpacing = data(GroupItemData_MajorSpacing).toInt();
     831            int iToggleButtonWidth = m_toggleButtonSize.width();
     832            /* Layout name-editor: */
     833            int iNameEditorX = iHorizontalMargin + iToggleButtonWidth + iMajorSpacing;
     834            int iNameEditorY = 1;
     835            m_pNameEditor->setPos(iNameEditorX, iNameEditorY);
     836            m_pNameEditorWidget->resize((int)(geometry().width() - iNameEditorX - iHorizontalMargin), m_pNameEditorWidget->height());
     837        }
     838
     839        /* Prepare body indent: */
     840        iPreviousVerticalIndent = 3 * iVerticalMargin + iFullHeaderHeight;
     841    }
     842
     843    /* No body for closed group: */
     844    if (isClosed())
     845    {
     846        /* Hide all the items: */
     847        foreach (UIChooserItem *pItem, items())
     848            pItem->hide();
     849    }
     850    /* Body for opened group: */
     851    else
     852    {
     853        /* Prepare variables: */
     854        int iHorizontalIndent = isRoot() ? iRootIndent : iHorizontalMargin;
     855        QRect geo = geometry().toRect();
     856        int iX = geo.x();
     857        int iY = geo.y();
     858        int iWidth = geo.width();
     859
     860        /* Layout all the items: */
     861        foreach (UIChooserItem *pItem, items())
     862        {
     863            /* Show if hidden: */
     864            pItem->show();
     865            /* Get item height-hint: */
     866            int iMinimumHeight = pItem->minimumHeightHint();
     867            /* Set item position: */
     868            pItem->setPos(iX + iHorizontalIndent, iY + iPreviousVerticalIndent);
     869            /* Set item size: */
     870            pItem->resize(iWidth - 2 * iHorizontalIndent, iMinimumHeight);
     871            /* Relayout group: */
     872            pItem->updateLayout();
     873            /* Update indent for next items: */
     874            iPreviousVerticalIndent += (iMinimumHeight + iMinorSpacing);
     875        }
     876    }
     877}
     878
     879int UIChooserItemGroup::minimumWidthHint() const
     880{
     881    return minimumWidthHintForGroup(isOpened());
     882}
     883
     884int UIChooserItemGroup::minimumHeightHint() const
     885{
     886    return minimumHeightHintForGroup(isOpened());
     887}
     888
     889QSizeF UIChooserItemGroup::sizeHint(Qt::SizeHint enmWhich, const QSizeF &constraint /* = QSizeF() */) const
     890{
     891    /* If Qt::MinimumSize requested: */
     892    if (enmWhich == Qt::MinimumSize)
     893        return minimumSizeHintForProup(isOpened());
     894    /* Else call to base-class: */
     895    return UIChooserItem::sizeHint(enmWhich, constraint);
     896}
     897
     898QPixmap UIChooserItemGroup::toPixmap()
     899{
     900    /* Ask item to paint itself into pixmap: */
     901    QSize minimumSize = minimumSizeHintForProup(false).toSize();
     902    QPixmap pixmap(minimumSize);
     903    pixmap.fill(Qt::transparent);
     904    QPainter painter(&pixmap);
     905    painter.setRenderHint(QPainter::Antialiasing);
     906    QStyleOptionGraphicsItem options;
     907    options.rect = QRect(QPoint(0, 0), minimumSize);
     908    paint(&painter, &options);
     909    return pixmap;
     910}
     911
     912bool UIChooserItemGroup::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const
     913{
     914    /* No drops while saving groups: */
     915    if (model()->isGroupSavingInProgress())
     916        return false;
     917    /* Get mime: */
     918    const QMimeData *pMimeData = pEvent->mimeData();
     919    /* If drag token is shown, its up to parent to decide: */
     920    if (where != DragToken_Off)
     921        return parentItem()->isDropAllowed(pEvent);
     922    /* Else we should check mime format: */
     923    if (pMimeData->hasFormat(UIChooserItemGroup::className()))
     924    {
     925        /* Get passed group-item: */
     926        const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);
     927        AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
     928        UIChooserItem *pItem = pCastedMimeData->item();
     929        /* Make sure passed group is mutable within this group: */
     930        if (pItem->toGroupItem()->isContainsLockedMachine() &&
     931            !items(UIChooserItemType_Group).contains(pItem))
     932            return false;
     933        /* Make sure passed group is not 'this': */
     934        if (pItem == this)
     935            return false;
     936        /* Make sure passed group is not among our parents: */
     937        const UIChooserItem *pTestedWidget = this;
     938        while (UIChooserItem *pParentOfTestedWidget = pTestedWidget->parentItem())
     939        {
     940            if (pItem == pParentOfTestedWidget)
     941                return false;
     942            pTestedWidget = pParentOfTestedWidget;
     943        }
     944        return true;
     945    }
     946    else if (pMimeData->hasFormat(UIChooserItemMachine::className()))
     947    {
     948        /* Get passed machine-item: */
     949        const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);
     950        AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
     951        UIChooserItem *pItem = pCastedMimeData->item();
     952        /* Make sure passed machine is mutable within this group: */
     953        if (pItem->toMachineItem()->isLockedMachine() &&
     954            !items(UIChooserItemType_Machine).contains(pItem))
     955            return false;
     956        switch (pEvent->proposedAction())
     957        {
     958            case Qt::MoveAction:
     959            {
     960                /* Make sure passed item is ours or there is no other item with such id: */
     961                return m_machineItems.contains(pItem) || !isContainsMachine(pItem->toMachineItem()->id());
     962            }
     963            case Qt::CopyAction:
     964            {
     965                /* Make sure there is no other item with such id: */
     966                return !isContainsMachine(pItem->toMachineItem()->id());
     967            }
     968            default: break; /* Shut up, MSC! */
     969        }
     970    }
     971    /* That was invalid mime: */
    269972    return false;
    270973}
    271974
    272 bool UIChooserItemGroup::isContainsLockedMachine()
    273 {
    274     /* Check each machine-item: */
    275     foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
    276         if (pItem->toMachineItem()->isLockedMachine())
    277             return true;
    278     /* Check each group-item: */
    279     foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
    280         if (pItem->toGroupItem()->isContainsLockedMachine())
    281             return true;
    282     /* Found nothing? */
    283     return false;
     975void UIChooserItemGroup::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where)
     976{
     977    /* Get mime: */
     978    const QMimeData *pMime = pEvent->mimeData();
     979    /* Check mime format: */
     980    if (pMime->hasFormat(UIChooserItemGroup::className()))
     981    {
     982        switch (pEvent->proposedAction())
     983        {
     984            case Qt::MoveAction:
     985            case Qt::CopyAction:
     986            {
     987                /* Remember scene: */
     988                UIChooserModel *pModel = model();
     989
     990                /* Get passed group-item: */
     991                const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);
     992                AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
     993                UIChooserItem *pItem = pCastedMime->item();
     994
     995                /* Check if we have position information: */
     996                int iPosition = m_groupItems.size();
     997                if (pFromWho && where != DragToken_Off)
     998                {
     999                    /* Make sure sender item if our child: */
     1000                    AssertMsg(m_groupItems.contains(pFromWho), ("Sender item is NOT our child!"));
     1001                    if (m_groupItems.contains(pFromWho))
     1002                    {
     1003                        iPosition = m_groupItems.indexOf(pFromWho);
     1004                        if (where == DragToken_Down)
     1005                            ++iPosition;
     1006                    }
     1007                }
     1008
     1009                /* Copy passed item into this group: */
     1010                UIChooserItem *pNewGroupItem = new UIChooserItemGroup(this, pItem->toGroupItem(), iPosition);
     1011                if (isClosed())
     1012                    open(false);
     1013
     1014                /* If proposed action is 'move': */
     1015                if (pEvent->proposedAction() == Qt::MoveAction)
     1016                {
     1017                    /* Delete passed item: */
     1018                    delete pItem;
     1019                }
     1020
     1021                /* Update model: */
     1022                pModel->cleanupGroupTree();
     1023                pModel->updateNavigation();
     1024                pModel->updateLayout();
     1025                pModel->setCurrentItem(pNewGroupItem);
     1026                pModel->saveGroupSettings();
     1027                break;
     1028            }
     1029            default:
     1030                break;
     1031        }
     1032    }
     1033    else if (pMime->hasFormat(UIChooserItemMachine::className()))
     1034    {
     1035        switch (pEvent->proposedAction())
     1036        {
     1037            case Qt::MoveAction:
     1038            case Qt::CopyAction:
     1039            {
     1040                /* Remember scene: */
     1041                UIChooserModel *pModel = model();
     1042
     1043                /* Get passed item: */
     1044                const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);
     1045                AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
     1046                UIChooserItem *pItem = pCastedMime->item();
     1047
     1048                /* Check if we have position information: */
     1049                int iPosition = m_machineItems.size();
     1050                if (pFromWho && where != DragToken_Off)
     1051                {
     1052                    /* Make sure sender item if our child: */
     1053                    AssertMsg(m_machineItems.contains(pFromWho), ("Sender item is NOT our child!"));
     1054                    if (m_machineItems.contains(pFromWho))
     1055                    {
     1056                        iPosition = m_machineItems.indexOf(pFromWho);
     1057                        if (where == DragToken_Down)
     1058                            ++iPosition;
     1059                    }
     1060                }
     1061
     1062                /* Copy passed machine-item into this group: */
     1063                UIChooserItem *pNewMachineItem = new UIChooserItemMachine(this, pItem->toMachineItem(), iPosition);
     1064                if (isClosed())
     1065                    open(false);
     1066
     1067                /* If proposed action is 'move': */
     1068                if (pEvent->proposedAction() == Qt::MoveAction)
     1069                {
     1070                    /* Delete passed item: */
     1071                    delete pItem;
     1072                }
     1073
     1074                /* Update model: */
     1075                pModel->cleanupGroupTree();
     1076                pModel->updateNavigation();
     1077                pModel->updateLayout();
     1078                pModel->setCurrentItem(pNewMachineItem);
     1079                pModel->saveGroupSettings();
     1080                break;
     1081            }
     1082            default:
     1083                break;
     1084        }
     1085    }
     1086}
     1087
     1088void UIChooserItemGroup::resetDragToken()
     1089{
     1090    /* Reset drag token for this item: */
     1091    if (dragTokenPlace() != DragToken_Off)
     1092    {
     1093        setDragTokenPlace(DragToken_Off);
     1094        update();
     1095    }
     1096    /* Reset drag tokens for all the items: */
     1097    foreach (UIChooserItem *pItem, items())
     1098        pItem->resetDragToken();
     1099}
     1100
     1101QMimeData* UIChooserItemGroup::createMimeData()
     1102{
     1103    return new UIChooserItemMimeData(this);
    2841104}
    2851105
     
    3881208    /* Unindent to previous root: */
    3891209    model()->unindentRoot();
    390 }
    391 
    392 QVariant UIChooserItemGroup::data(int iKey) const
    393 {
    394     /* Provide other members with required data: */
    395     switch (iKey)
    396     {
    397         /* Layout hints: */
    398         case GroupItemData_HorizonalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
    399         case GroupItemData_VerticalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
    400         case GroupItemData_MajorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
    401         case GroupItemData_MinorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 5;
    402         case GroupItemData_RootIndent: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 6;
    403 
    404         /* Default: */
    405         default: break;
    406     }
    407     return QVariant();
    4081210}
    4091211
     
    4311233        /* Setup toggle-button: */
    4321234        m_pToggleButton = new UIGraphicsRotatorButton(this, "additionalHeight", isOpened());
    433         connect(m_pToggleButton, SIGNAL(sigRotationStart()), this, SLOT(sltGroupToggleStart()));
    434         connect(m_pToggleButton, SIGNAL(sigRotationFinish(bool)), this, SLOT(sltGroupToggleFinish(bool)));
     1235        connect(m_pToggleButton, &UIGraphicsRotatorButton::sigRotationStart,
     1236                this, &UIChooserItemGroup::sltGroupToggleStart);
     1237        connect(m_pToggleButton, &UIGraphicsRotatorButton::sigRotationFinish,
     1238                this, &UIChooserItemGroup::sltGroupToggleFinish);
    4351239        m_pToggleButton->hide();
    4361240
    4371241        /* Setup enter-button: */
    4381242        m_pEnterButton = new UIGraphicsButton(this, UIIconPool::iconSet(":/next_16px.png"));
    439         connect(m_pEnterButton, SIGNAL(sigButtonClicked()), this, SLOT(sltIndentRoot()));
     1243        connect(m_pEnterButton, &UIGraphicsButton::sigButtonClicked,
     1244                this, &UIChooserItemGroup::sltIndentRoot);
    4401245        m_pEnterButton->hide();
    4411246
     
    4431248        m_pNameEditorWidget = new UIEditorGroupRename(name(), this);
    4441249        m_pNameEditorWidget->setFont(m_nameFont);
    445         connect(m_pNameEditorWidget, SIGNAL(sigEditingFinished()), this, SLOT(sltNameEditingFinished()));
     1250        connect(m_pNameEditorWidget, &UIEditorGroupRename::sigEditingFinished,
     1251                this, &UIChooserItemGroup::sltNameEditingFinished);
    4461252        m_pNameEditor = new QGraphicsProxyWidget(this);
    4471253        m_pNameEditor->setWidget(m_pNameEditorWidget);
     
    4531259        /* Setup exit-button: */
    4541260        m_pExitButton = new UIGraphicsButton(this, UIIconPool::iconSet(":/previous_16px.png"));
    455         connect(m_pExitButton, SIGNAL(sigButtonClicked()), this, SLOT(sltUnindentRoot()));
     1261        connect(m_pExitButton, &UIGraphicsButton::sigButtonClicked,
     1262                this, &UIChooserItemGroup::sltUnindentRoot);
    4561263        QSizeF sh = m_pExitButton->minimumSizeHint();
    4571264        m_pExitButton->setTransformOriginPoint(sh.width() / 2, sh.height() / 2);
     
    4791286}
    4801287
    481 void UIChooserItemGroup::handleRootStatusChange()
    482 {
    483     /* Call to base-class: */
    484     UIChooserItem::handleRootStatusChange();
     1288QVariant UIChooserItemGroup::data(int iKey) const
     1289{
     1290    /* Provide other members with required data: */
     1291    switch (iKey)
     1292    {
     1293        /* Layout hints: */
     1294        case GroupItemData_HorizonalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
     1295        case GroupItemData_VerticalMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
     1296        case GroupItemData_MajorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
     1297        case GroupItemData_MinorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 5;
     1298        case GroupItemData_RootIndent: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 6;
     1299
     1300        /* Default: */
     1301        default: break;
     1302    }
     1303    return QVariant();
     1304}
     1305
     1306void UIChooserItemGroup::setAdditionalHeight(int iAdditionalHeight)
     1307{
     1308    m_iAdditionalHeight = iAdditionalHeight;
     1309    updateGeometry();
     1310    model()->updateLayout();
     1311}
     1312
     1313int UIChooserItemGroup::additionalHeight() const
     1314{
     1315    return m_iAdditionalHeight;
     1316}
     1317
     1318void UIChooserItemGroup::updateAnimationParameters()
     1319{
     1320    /* Only for item with button: */
     1321    if (!m_pToggleButton)
     1322        return;
     1323
     1324    /* Recalculate animation parameters: */
     1325    QSizeF openedSize = minimumSizeHintForProup(true);
     1326    QSizeF closedSize = minimumSizeHintForProup(false);
     1327    int iAdditionalHeight = (int)(openedSize.height() - closedSize.height());
     1328    m_pToggleButton->setAnimationRange(0, iAdditionalHeight);
     1329}
     1330
     1331void UIChooserItemGroup::updateToggleButtonToolTip()
     1332{
     1333    /* Only for item with button: */
     1334    if (!m_pToggleButton)
     1335        return;
     1336
     1337    /* Update toggle-button tool-tip: */
     1338    m_pToggleButton->setToolTip(isOpened() ? tr("Collapse group") : tr("Expand group"));
     1339}
     1340
     1341bool UIChooserItemGroup::isContainsMachine(const QString &strId) const
     1342{
     1343    /* Check each machine-item: */
     1344    foreach (UIChooserItem *pItem, m_machineItems)
     1345        if (pItem->toMachineItem()->id() == strId)
     1346            return true;
     1347    /* Found nothing? */
     1348    return false;
     1349}
     1350
     1351bool UIChooserItemGroup::isContainsLockedMachine()
     1352{
     1353    /* Check each machine-item: */
     1354    foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
     1355        if (pItem->toMachineItem()->isLockedMachine())
     1356            return true;
     1357    /* Check each group-item: */
     1358    foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
     1359        if (pItem->toGroupItem()->isContainsLockedMachine())
     1360            return true;
     1361    /* Found nothing? */
     1362    return false;
     1363}
     1364
     1365void UIChooserItemGroup::updateItemCountInfo()
     1366{
     1367    /* Not for main root: */
     1368    if (isMainRoot())
     1369        return;
     1370
     1371    /* Update item info attributes: */
     1372    QPaintDevice *pPaintDevice = model()->paintDevice();
     1373    QString strInfoGroups = m_groupItems.isEmpty() ? QString() : QString::number(m_groupItems.size());
     1374    QString strInfoMachines = m_machineItems.isEmpty() ? QString() : QString::number(m_machineItems.size());
     1375    QSize infoSizeGroups = textSize(m_infoFont, pPaintDevice, strInfoGroups);
     1376    QSize infoSizeMachines = textSize(m_infoFont, pPaintDevice, strInfoMachines);
    4851377
    4861378    /* Update linked values: */
    487     updateVisibleName();
    488     updateMinimumHeaderSize();
     1379    bool fSomethingChanged = false;
     1380    if (m_strInfoGroups != strInfoGroups)
     1381    {
     1382        m_strInfoGroups = strInfoGroups;
     1383        fSomethingChanged = true;
     1384    }
     1385    if (m_strInfoMachines != strInfoMachines)
     1386    {
     1387        m_strInfoMachines = strInfoMachines;
     1388        fSomethingChanged = true;
     1389    }
     1390    if (m_infoSizeGroups != infoSizeGroups)
     1391    {
     1392        m_infoSizeGroups = infoSizeGroups;
     1393        fSomethingChanged = true;
     1394    }
     1395    if (m_infoSizeMachines != infoSizeMachines)
     1396    {
     1397        m_infoSizeMachines = infoSizeMachines;
     1398        fSomethingChanged = true;
     1399    }
     1400    if (fSomethingChanged)
     1401    {
     1402        updateVisibleName();
     1403        updateMinimumHeaderSize();
     1404    }
     1405}
     1406
     1407int UIChooserItemGroup::minimumWidthHintForGroup(bool fGroupOpened) const
     1408{
     1409    /* Calculating proposed width: */
     1410    int iProposedWidth = 0;
     1411
     1412    /* Main root-item: */
     1413    if (isMainRoot())
     1414    {
     1415        /* Main root-item always takes body into account: */
     1416        if (hasItems())
     1417        {
     1418            /* Prepare variables: */
     1419            int iRootIndent = data(GroupItemData_RootIndent).toInt();
     1420
     1421            /* We have to take every child width into account: */
     1422            int iMaximumChildWidth = 0;
     1423            foreach (UIChooserItem *pItem, items())
     1424                iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());
     1425            iProposedWidth += iMaximumChildWidth;
     1426
     1427            /* And 2 indents at last - left and right: */
     1428            iProposedWidth += 2 * iRootIndent;
     1429        }
     1430    }
     1431    /* Other items, including temporary roots: */
     1432    else
     1433    {
     1434        /* Prepare variables: */
     1435        int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
     1436
     1437        /* Basically we have to take header width into account: */
     1438        iProposedWidth += m_minimumHeaderSize.width();
     1439
     1440        /* But if group-item is opened: */
     1441        if (fGroupOpened)
     1442        {
     1443            /* We have to take every child width into account: */
     1444            int iMaximumChildWidth = 0;
     1445            foreach (UIChooserItem *pItem, items())
     1446                iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());
     1447            iProposedWidth = qMax(iProposedWidth, iMaximumChildWidth);
     1448        }
     1449
     1450        /* And 2 margins at last - left and right: */
     1451        iProposedWidth += 2 * iHorizontalMargin;
     1452    }
     1453
     1454    /* Return result: */
     1455    return iProposedWidth;
     1456}
     1457
     1458int UIChooserItemGroup::minimumHeightHintForGroup(bool fGroupOpened) const
     1459{
     1460    /* Prepare variables: */
     1461    int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();
     1462
     1463    /* Calculating proposed height: */
     1464    int iProposedHeight = 0;
     1465
     1466    /* Main root-item: */
     1467    if (isMainRoot())
     1468    {
     1469        /* Main root-item always takes body into account: */
     1470        if (hasItems())
     1471        {
     1472            /* Prepare variables: */
     1473            int iRootIndent = data(GroupItemData_RootIndent).toInt();
     1474
     1475            /* Main root-item have 2 indents - top and bottom: */
     1476            iProposedHeight += 2 * iRootIndent;
     1477            /* And every existing: */
     1478            foreach (UIChooserItem *pItem, items())
     1479            {
     1480                /* Child height: */
     1481                iProposedHeight += pItem->minimumHeightHint();
     1482                /* And interline spacing: */
     1483                iProposedHeight += iMinorSpacing;
     1484            }
     1485            /* Excpect the last one spacing: */
     1486            iProposedHeight -= iMinorSpacing;
     1487        }
     1488    }
     1489    /* Other items, including temporary roots: */
     1490    else
     1491    {
     1492        /* Prepare variables: */
     1493        int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();
     1494
     1495        /* Group-item header have 2 margins - top and bottom: */
     1496        iProposedHeight += 2 * iVerticalMargin;
     1497        /* And header content height to take into account: */
     1498        iProposedHeight += m_minimumHeaderSize.height();
     1499
     1500        /* But if group-item is opened: */
     1501        if (fGroupOpened)
     1502        {
     1503            /* Prepare variables: */
     1504            int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
     1505
     1506            /* We should take into spacing between header and body: */
     1507            iProposedHeight += iVerticalMargin;
     1508            /* Every existing: */
     1509            foreach (UIChooserItem *pItem, items())
     1510            {
     1511                /* Child height: */
     1512                iProposedHeight += pItem->minimumHeightHint();
     1513                /* And interline spacing: */
     1514                iProposedHeight += iMinorSpacing;
     1515            }
     1516            /* Excpect the last one spacing: */
     1517            iProposedHeight -= iMinorSpacing;
     1518            /* And bottom margin at last: */
     1519            iProposedHeight += iHorizontalMargin;
     1520        }
     1521
     1522        /* Finally, additional height during animation: */
     1523        if (!fGroupOpened && m_pToggleButton && m_pToggleButton->isAnimationRunning())
     1524            iProposedHeight += m_iAdditionalHeight;
     1525    }
     1526
     1527    /* Return result: */
     1528    return iProposedHeight;
     1529}
     1530
     1531QSizeF UIChooserItemGroup::minimumSizeHintForProup(bool fGroupOpened) const
     1532{
     1533    return QSizeF(minimumWidthHintForGroup(fGroupOpened), minimumHeightHintForGroup(fGroupOpened));
    4891534}
    4901535
     
    5651610    m_pixmapSizeGroups = m_groupsPixmap.size() / m_groupsPixmap.devicePixelRatio();
    5661611    m_pixmapSizeMachines = m_machinesPixmap.size() / m_machinesPixmap.devicePixelRatio();
    567 }
    568 
    569 void UIChooserItemGroup::updateItemCountInfo()
    570 {
    571     /* Not for main root: */
    572     if (isMainRoot())
    573         return;
    574 
    575     /* Update item info attributes: */
    576     QPaintDevice *pPaintDevice = model()->paintDevice();
    577     QString strInfoGroups = m_groupItems.isEmpty() ? QString() : QString::number(m_groupItems.size());
    578     QString strInfoMachines = m_machineItems.isEmpty() ? QString() : QString::number(m_machineItems.size());
    579     QSize infoSizeGroups = textSize(m_infoFont, pPaintDevice, strInfoGroups);
    580     QSize infoSizeMachines = textSize(m_infoFont, pPaintDevice, strInfoMachines);
    581 
    582     /* Update linked values: */
    583     bool fSomethingChanged = false;
    584     if (m_strInfoGroups != strInfoGroups)
    585     {
    586         m_strInfoGroups = strInfoGroups;
    587         fSomethingChanged = true;
    588     }
    589     if (m_strInfoMachines != strInfoMachines)
    590     {
    591         m_strInfoMachines = strInfoMachines;
    592         fSomethingChanged = true;
    593     }
    594     if (m_infoSizeGroups != infoSizeGroups)
    595     {
    596         m_infoSizeGroups = infoSizeGroups;
    597         fSomethingChanged = true;
    598     }
    599     if (m_infoSizeMachines != infoSizeMachines)
    600     {
    601         m_infoSizeMachines = infoSizeMachines;
    602         fSomethingChanged = true;
    603     }
    604     if (fSomethingChanged)
    605     {
    606         updateVisibleName();
    607         updateMinimumHeaderSize();
    608     }
    6091612}
    6101613
     
    6821685}
    6831686
    684 void UIChooserItemGroup::updateToolTip()
    685 {
    686     /* Not for main root: */
    687     if (isMainRoot())
    688         return;
    689 
    690     /* Prepare variables: */
    691     QStringList toolTipInfo;
    692 
    693     /* Should we add name? */
    694     if (!name().isEmpty())
    695     {
    696         /* Template: */
    697         QString strTemplateForName = tr("<b>%1</b>", "Group item tool-tip / Group name");
    698 
    699         /* Append value: */
    700         toolTipInfo << strTemplateForName.arg(name());
    701     }
    702 
    703     /* Should we add group info? */
    704     if (!items(UIChooserItemType_Group).isEmpty())
    705     {
    706         /* Template: */
    707         QString strGroupCount = tr("%n group(s)", "Group item tool-tip / Group info", items(UIChooserItemType_Group).size());
    708 
    709         /* Append value: */
    710         QString strValue = tr("<nobr>%1</nobr>", "Group item tool-tip / Group info wrapper").arg(strGroupCount);
    711         toolTipInfo << strValue;
    712     }
    713 
    714     /* Should we add machine info? */
    715     if (!items(UIChooserItemType_Machine).isEmpty())
    716     {
    717         /* Check if 'this' group contains started VMs: */
    718         int iCountOfStartedMachineItems = 0;
    719         foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
    720             if (UIVirtualMachineItem::isItemStarted(pItem->toMachineItem()))
    721                 ++iCountOfStartedMachineItems;
    722         /* Template: */
    723         QString strMachineCount = tr("%n machine(s)", "Group item tool-tip / Machine info", items(UIChooserItemType_Machine).size());
    724         QString strStartedMachineCount = tr("(%n running)", "Group item tool-tip / Running machine info", iCountOfStartedMachineItems);
    725 
    726         /* Append value: */
    727         QString strValue = !iCountOfStartedMachineItems ?
    728                            tr("<nobr>%1</nobr>", "Group item tool-tip / Machine info wrapper").arg(strMachineCount) :
    729                            tr("<nobr>%1 %2</nobr>", "Group item tool-tip / Machine info wrapper, including running").arg(strMachineCount).arg(strStartedMachineCount);
    730         toolTipInfo << strValue;
    731     }
    732 
    733     /* Set tool-tip: */
    734     setToolTip(toolTipInfo.join("<br>"));
    735 }
    736 
    737 void UIChooserItemGroup::updateToggleButtonToolTip()
    738 {
    739     /* Is toggle-button created? */
    740     if (!m_pToggleButton)
    741         return;
    742 
    743     /* Update toggle-button tool-tip: */
    744     m_pToggleButton->setToolTip(isOpened() ? tr("Collapse group") : tr("Expand group"));
    745 }
    746 
    747 void UIChooserItemGroup::retranslateUi()
    748 {
    749     /* Update description: */
    750     m_strDescription = tr("Virtual Machine group");
    751 
    752     /* Update group tool-tip: */
    753     updateToolTip();
    754 
    755     /* Update button tool-tips: */
    756     if (m_pEnterButton)
    757         m_pEnterButton->setToolTip(tr("Enter group"));
    758     if (m_pExitButton)
    759         m_pExitButton->setToolTip(tr("Exit group"));
    760     updateToggleButtonToolTip();
    761 }
    762 
    763 void UIChooserItemGroup::show()
    764 {
    765     /* Call to base-class: */
    766     UIChooserItem::show();
    767     /* Show children: */
    768     if (!isClosed())
    769         foreach (UIChooserItem *pItem, items())
    770             pItem->show();
    771 }
    772 
    773 void UIChooserItemGroup::hide()
    774 {
    775     /* Call to base-class: */
    776     UIChooserItem::hide();
    777     /* Hide children: */
    778     foreach (UIChooserItem *pItem, items())
    779         pItem->hide();
    780 }
    781 
    782 void UIChooserItemGroup::startEditing()
    783 {
    784     /* Not for root: */
    785     if (isRoot())
    786         return;
    787 
    788     /* Not while saving groups: */
    789     if (model()->isGroupSavingInProgress())
    790         return;
    791 
    792     /* Unlock name-editor: */
    793     m_pNameEditor->show();
    794     m_pNameEditorWidget->setText(name());
    795     m_pNameEditorWidget->setFocus();
    796 }
    797 
    798 void UIChooserItemGroup::addItem(UIChooserItem *pItem, int iPosition)
    799 {
    800     /* Check item type: */
    801     switch (pItem->type())
    802     {
    803         case UIChooserItemType_Group:
    804         {
    805             AssertMsg(!m_groupItems.contains(pItem), ("Group-item already added!"));
    806             if (iPosition < 0 || iPosition >= m_groupItems.size())
    807                 m_groupItems.append(pItem);
    808             else
    809                 m_groupItems.insert(iPosition, pItem);
    810             scene()->addItem(pItem);
    811             break;
    812         }
    813         case UIChooserItemType_Global:
    814         {
    815             AssertMsg(!m_globalItems.contains(pItem), ("Global-item already added!"));
    816             if (iPosition < 0 || iPosition >= m_globalItems.size())
    817                 m_globalItems.append(pItem);
    818             else
    819                 m_globalItems.insert(iPosition, pItem);
    820             scene()->addItem(pItem);
    821             break;
    822         }
    823         case UIChooserItemType_Machine:
    824         {
    825             AssertMsg(!m_machineItems.contains(pItem), ("Machine-item already added!"));
    826             if (iPosition < 0 || iPosition >= m_machineItems.size())
    827                 m_machineItems.append(pItem);
    828             else
    829                 m_machineItems.insert(iPosition, pItem);
    830             scene()->addItem(pItem);
    831             break;
    832         }
    833         default:
    834         {
    835             AssertMsgFailed(("Invalid item type!"));
    836             break;
    837         }
    838     }
    839 
    840     /* Update linked values: */
    841     updateItemCountInfo();
    842     updateToolTip();
    843     updateGeometry();
    844 }
    845 
    846 void UIChooserItemGroup::removeItem(UIChooserItem *pItem)
    847 {
    848     /* Check item type: */
    849     switch (pItem->type())
    850     {
    851         case UIChooserItemType_Group:
    852         {
    853             AssertMsg(m_groupItems.contains(pItem), ("Group-item was not found!"));
    854             scene()->removeItem(pItem);
    855             m_groupItems.removeAt(m_groupItems.indexOf(pItem));
    856             break;
    857         }
    858         case UIChooserItemType_Global:
    859         {
    860             AssertMsg(m_globalItems.contains(pItem), ("Global-item was not found!"));
    861             scene()->removeItem(pItem);
    862             m_globalItems.removeAt(m_globalItems.indexOf(pItem));
    863             break;
    864         }
    865         case UIChooserItemType_Machine:
    866         {
    867             AssertMsg(m_machineItems.contains(pItem), ("Machine-item was not found!"));
    868             scene()->removeItem(pItem);
    869             m_machineItems.removeAt(m_machineItems.indexOf(pItem));
    870             break;
    871         }
    872         default:
    873         {
    874             AssertMsgFailed(("Invalid item type!"));
    875             break;
    876         }
    877     }
    878 
    879     /* Update linked values: */
    880     updateItemCountInfo();
    881     updateToolTip();
    882     updateGeometry();
    883 }
    884 
    885 void UIChooserItemGroup::setItems(const QList<UIChooserItem*> &items, UIChooserItemType type)
    886 {
    887     /* Check item type: */
    888     switch (type)
    889     {
    890         case UIChooserItemType_Group: m_groupItems = items; break;
    891         case UIChooserItemType_Global: m_globalItems = items; break;
    892         case UIChooserItemType_Machine: m_machineItems = items; break;
    893         default: AssertMsgFailed(("Invalid item type!")); break;
    894     }
    895 
    896     /* Update linked values: */
    897     updateItemCountInfo();
    898     updateToolTip();
    899     updateGeometry();
    900 }
    901 
    902 QList<UIChooserItem*> UIChooserItemGroup::items(UIChooserItemType type /* = UIChooserItemType_Any */) const
    903 {
    904     switch (type)
    905     {
    906         case UIChooserItemType_Any: return items(UIChooserItemType_Global) + items(UIChooserItemType_Group) + items(UIChooserItemType_Machine);
    907         case UIChooserItemType_Group: return m_groupItems;
    908         case UIChooserItemType_Global: return m_globalItems;
    909         case UIChooserItemType_Machine: return m_machineItems;
    910         default: break;
    911     }
    912     return QList<UIChooserItem*>();
    913 }
    914 
    915 bool UIChooserItemGroup::hasItems(UIChooserItemType type /* = UIChooserItemType_Any */) const
    916 {
    917     switch (type)
    918     {
    919         case UIChooserItemType_Any:
    920             return hasItems(UIChooserItemType_Global) || hasItems(UIChooserItemType_Group) || hasItems(UIChooserItemType_Machine);
    921         case UIChooserItemType_Group:
    922             return !m_groupItems.isEmpty();
    923         case UIChooserItemType_Global:
    924             return !m_globalItems.isEmpty();
    925         case UIChooserItemType_Machine:
    926             return !m_machineItems.isEmpty();
    927     }
    928     return false;
    929 }
    930 
    931 void UIChooserItemGroup::clearItems(UIChooserItemType type /* = UIChooserItemType_Any */)
    932 {
    933     switch (type)
    934     {
    935         case UIChooserItemType_Any:
    936         {
    937             clearItems(UIChooserItemType_Group);
    938             clearItems(UIChooserItemType_Global);
    939             clearItems(UIChooserItemType_Machine);
    940             break;
    941         }
    942         case UIChooserItemType_Group:
    943         {
    944             while (!m_groupItems.isEmpty()) { delete m_groupItems.last(); }
    945             AssertMsg(m_groupItems.isEmpty(), ("Group items cleanup failed!"));
    946             break;
    947         }
    948         case UIChooserItemType_Global:
    949         {
    950             while (!m_globalItems.isEmpty()) { delete m_globalItems.last(); }
    951             AssertMsg(m_globalItems.isEmpty(), ("Global items cleanup failed!"));
    952             break;
    953         }
    954         case UIChooserItemType_Machine:
    955         {
    956             while (!m_machineItems.isEmpty()) { delete m_machineItems.last(); }
    957             AssertMsg(m_machineItems.isEmpty(), ("Machine items cleanup failed!"));
    958             break;
    959         }
    960     }
    961 
    962     /* Update linked values: */
    963     updateItemCountInfo();
    964     updateToolTip();
    965     updateGeometry();
    966 }
    967 
    968 void UIChooserItemGroup::updateAllItems(const QString &strId)
    969 {
    970     /* Update all the required items recursively: */
    971     foreach (UIChooserItem *pItem, items())
    972         pItem->updateAllItems(strId);
    973 }
    974 
    975 void UIChooserItemGroup::removeAllItems(const QString &strId)
    976 {
    977     /* Remove all the required items recursively: */
    978     foreach (UIChooserItem *pItem, items())
    979         pItem->removeAllItems(strId);
    980 }
    981 
    982 UIChooserItem* UIChooserItemGroup::searchForItem(const QString &strSearchTag, int iItemSearchFlags)
    983 {
    984     /* Are we searching among group-items? */
    985     if (iItemSearchFlags & UIChooserItemSearchFlag_Group)
    986     {
    987         /* Are we searching by the exact name? */
    988         if (iItemSearchFlags & UIChooserItemSearchFlag_ExactName)
    989         {
    990             /* Exact name matches? */
    991             if (name() == strSearchTag)
    992                 return this;
    993         }
    994         /* Are we searching by the few first symbols? */
    995         else
    996         {
    997             /* Name starts with passed symbols? */
    998             if (name().startsWith(strSearchTag, Qt::CaseInsensitive))
    999                 return this;
    1000         }
    1001     }
    1002 
    1003     /* Search among all the children, but machines first: */
    1004     foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
    1005         if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
    1006             return pFoundItem;
    1007     foreach (UIChooserItem *pItem, items(UIChooserItemType_Global))
    1008         if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
    1009             return pFoundItem;
    1010     foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
    1011         if (UIChooserItem *pFoundItem = pItem->searchForItem(strSearchTag, iItemSearchFlags))
    1012             return pFoundItem;
    1013 
    1014     /* Found nothing? */
    1015     return 0;
    1016 }
    1017 
    1018 UIChooserItem *UIChooserItemGroup::firstMachineItem()
    1019 {
    1020     /* If this group-item have at least one machine-item: */
    1021     if (hasItems(UIChooserItemType_Machine))
    1022         /* Return the first machine-item: */
    1023         return items(UIChooserItemType_Machine).first()->firstMachineItem();
    1024     /* If this group-item have at least one group-item: */
    1025     else if (hasItems(UIChooserItemType_Group))
    1026         /* Return the first machine-item of the first group-item: */
    1027         return items(UIChooserItemType_Group).first()->firstMachineItem();
    1028     /* Found nothing? */
    1029     return 0;
    1030 }
    1031 
    1032 void UIChooserItemGroup::sortItems()
    1033 {
    1034     /* Sort group-items: */
    1035     QMap<QString, UIChooserItem*> sorter;
    1036     foreach (UIChooserItem *pItem, items(UIChooserItemType_Group))
    1037         sorter.insert(pItem->name().toLower(), pItem);
    1038     setItems(sorter.values(), UIChooserItemType_Group);
    1039 
    1040     /* Sort machine-items: */
    1041     sorter.clear();
    1042     foreach (UIChooserItem *pItem, items(UIChooserItemType_Machine))
    1043         sorter.insert(pItem->name().toLower(), pItem);
    1044     setItems(sorter.values(), UIChooserItemType_Machine);
    1045 
    1046     /* Update model: */
    1047     model()->updateNavigation();
    1048     model()->updateLayout();
    1049 }
    1050 
    1051 void UIChooserItemGroup::updateLayout()
    1052 {
    1053     /* Prepare variables: */
    1054     int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
    1055     int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();
    1056     int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();
    1057     int iFullHeaderHeight = m_minimumHeaderSize.height();
    1058     int iRootIndent = data(GroupItemData_RootIndent).toInt();
    1059     int iPreviousVerticalIndent = 0;
    1060 
    1061     /* Header (root-item): */
    1062     if (isRoot())
    1063     {
    1064         /* Header (main root-item): */
    1065         if (isMainRoot())
    1066         {
    1067             /* Prepare body indent: */
    1068             iPreviousVerticalIndent = iRootIndent;
    1069         }
    1070         /* Header (non-main root-item): */
    1071         else
    1072         {
    1073             /* Hide unnecessary buttons: */
    1074             if (m_pToggleButton)
    1075                 m_pToggleButton->hide();
    1076             if (m_pEnterButton)
    1077                 m_pEnterButton->hide();
    1078 
    1079             /* Exit-button: */
    1080             if (m_pExitButton)
    1081             {
    1082                 /* Prepare variables: */
    1083                 int iExitButtonHeight = m_exitButtonSize.height();
    1084                 /* Layout exit-button: */
    1085                 int iExitButtonX = iHorizontalMargin + iRootIndent;
    1086                 int iExitButtonY = iExitButtonHeight == iFullHeaderHeight ? iVerticalMargin :
    1087                                    iVerticalMargin + (iFullHeaderHeight - iExitButtonHeight) / 2;
    1088                 m_pExitButton->setPos(iExitButtonX, iExitButtonY);
    1089                 /* Show exit-button: */
    1090                 m_pExitButton->show();
    1091             }
    1092 
    1093             /* Prepare body indent: */
    1094             iPreviousVerticalIndent = iVerticalMargin + iFullHeaderHeight + iVerticalMargin + iMinorSpacing;
    1095         }
    1096     }
    1097     /* Header (non-root-item): */
    1098     else
    1099     {
    1100         /* Hide unnecessary button: */
    1101         if (m_pExitButton)
    1102             m_pExitButton->hide();
    1103 
    1104         /* Toggle-button: */
    1105         if (m_pToggleButton)
    1106         {
    1107             /* Prepare variables: */
    1108             int iToggleButtonHeight = m_toggleButtonSize.height();
    1109             /* Layout toggle-button: */
    1110             int iToggleButtonX = iHorizontalMargin;
    1111             int iToggleButtonY = iToggleButtonHeight == iFullHeaderHeight ? iVerticalMargin :
    1112                                  iVerticalMargin + (iFullHeaderHeight - iToggleButtonHeight) / 2;
    1113             m_pToggleButton->setPos(iToggleButtonX, iToggleButtonY);
    1114             /* Show toggle-button: */
    1115             m_pToggleButton->show();
    1116         }
    1117 
    1118         /* Enter-button: */
    1119         if (m_pEnterButton)
    1120         {
    1121             /* Prepare variables: */
    1122             int iFullWidth = (int)geometry().width();
    1123             int iEnterButtonWidth = m_enterButtonSize.width();
    1124             int iEnterButtonHeight = m_enterButtonSize.height();
    1125             /* Layout enter-button: */
    1126             int iEnterButtonX = iFullWidth - iHorizontalMargin - iEnterButtonWidth;
    1127             int iEnterButtonY = iEnterButtonHeight == iFullHeaderHeight ? iVerticalMargin :
    1128                                 iVerticalMargin + (iFullHeaderHeight - iEnterButtonHeight) / 2;
    1129             m_pEnterButton->setPos(iEnterButtonX, iEnterButtonY);
    1130         }
    1131 
    1132         /* Name-editor: */
    1133         if (m_pNameEditor && m_pNameEditorWidget)
    1134         {
    1135             /* Prepare variables: */
    1136             int iMajorSpacing = data(GroupItemData_MajorSpacing).toInt();
    1137             int iToggleButtonWidth = m_toggleButtonSize.width();
    1138             /* Layout name-editor: */
    1139             int iNameEditorX = iHorizontalMargin + iToggleButtonWidth + iMajorSpacing;
    1140             int iNameEditorY = 1;
    1141             m_pNameEditor->setPos(iNameEditorX, iNameEditorY);
    1142             m_pNameEditorWidget->resize((int)(geometry().width() - iNameEditorX - iHorizontalMargin), m_pNameEditorWidget->height());
    1143         }
    1144 
    1145         /* Prepare body indent: */
    1146         iPreviousVerticalIndent = 3 * iVerticalMargin + iFullHeaderHeight;
    1147     }
    1148 
    1149     /* No body for closed group: */
    1150     if (isClosed())
    1151     {
    1152         /* Hide all the items: */
    1153         foreach (UIChooserItem *pItem, items())
    1154             pItem->hide();
    1155     }
    1156     /* Body for opened group: */
    1157     else
    1158     {
    1159         /* Prepare variables: */
    1160         int iHorizontalIndent = isRoot() ? iRootIndent : iHorizontalMargin;
    1161         QRect geo = geometry().toRect();
    1162         int iX = geo.x();
    1163         int iY = geo.y();
    1164         int iWidth = geo.width();
    1165 
    1166         /* Layout all the items: */
    1167         foreach (UIChooserItem *pItem, items())
    1168         {
    1169             /* Show if hidden: */
    1170             pItem->show();
    1171             /* Get item height-hint: */
    1172             int iMinimumHeight = pItem->minimumHeightHint();
    1173             /* Set item position: */
    1174             pItem->setPos(iX + iHorizontalIndent, iY + iPreviousVerticalIndent);
    1175             /* Set item size: */
    1176             pItem->resize(iWidth - 2 * iHorizontalIndent, iMinimumHeight);
    1177             /* Relayout group: */
    1178             pItem->updateLayout();
    1179             /* Update indent for next items: */
    1180             iPreviousVerticalIndent += (iMinimumHeight + iMinorSpacing);
    1181         }
    1182     }
    1183 }
    1184 
    1185 int UIChooserItemGroup::minimumWidthHint(bool fOpenedGroup) const
    1186 {
    1187     /* Calculating proposed width: */
    1188     int iProposedWidth = 0;
    1189 
    1190     /* Main root-item: */
    1191     if (isMainRoot())
    1192     {
    1193         /* Main root-item always takes body into account: */
    1194         if (hasItems())
    1195         {
    1196             /* Prepare variables: */
    1197             int iRootIndent = data(GroupItemData_RootIndent).toInt();
    1198 
    1199             /* We have to take every child width into account: */
    1200             int iMaximumChildWidth = 0;
    1201             foreach (UIChooserItem *pItem, items())
    1202                 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());
    1203             iProposedWidth += iMaximumChildWidth;
    1204 
    1205             /* And 2 indents at last - left and right: */
    1206             iProposedWidth += 2 * iRootIndent;
    1207         }
    1208     }
    1209     /* Other items, including temporary roots: */
    1210     else
    1211     {
    1212         /* Prepare variables: */
    1213         int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
    1214 
    1215         /* Basically we have to take header width into account: */
    1216         iProposedWidth += m_minimumHeaderSize.width();
    1217 
    1218         /* But if group-item is opened: */
    1219         if (fOpenedGroup)
    1220         {
    1221             /* We have to take every child width into account: */
    1222             int iMaximumChildWidth = 0;
    1223             foreach (UIChooserItem *pItem, items())
    1224                 iMaximumChildWidth = qMax(iMaximumChildWidth, pItem->minimumWidthHint());
    1225             iProposedWidth = qMax(iProposedWidth, iMaximumChildWidth);
    1226         }
    1227 
    1228         /* And 2 margins at last - left and right: */
    1229         iProposedWidth += 2 * iHorizontalMargin;
    1230     }
    1231 
    1232     /* Return result: */
    1233     return iProposedWidth;
    1234 }
    1235 
    1236 int UIChooserItemGroup::minimumHeightHint(bool fOpenedGroup) const
    1237 {
    1238     /* Prepare variables: */
    1239     int iMinorSpacing = data(GroupItemData_MinorSpacing).toInt();
    1240 
    1241     /* Calculating proposed height: */
    1242     int iProposedHeight = 0;
    1243 
    1244     /* Main root-item: */
    1245     if (isMainRoot())
    1246     {
    1247         /* Main root-item always takes body into account: */
    1248         if (hasItems())
    1249         {
    1250             /* Prepare variables: */
    1251             int iRootIndent = data(GroupItemData_RootIndent).toInt();
    1252 
    1253             /* Main root-item have 2 indents - top and bottom: */
    1254             iProposedHeight += 2 * iRootIndent;
    1255             /* And every existing: */
    1256             foreach (UIChooserItem *pItem, items())
    1257             {
    1258                 /* Child height: */
    1259                 iProposedHeight += pItem->minimumHeightHint();
    1260                 /* And interline spacing: */
    1261                 iProposedHeight += iMinorSpacing;
    1262             }
    1263             /* Excpect the last one spacing: */
    1264             iProposedHeight -= iMinorSpacing;
    1265         }
    1266     }
    1267     /* Other items, including temporary roots: */
    1268     else
    1269     {
    1270         /* Prepare variables: */
    1271         int iVerticalMargin = data(GroupItemData_VerticalMargin).toInt();
    1272 
    1273         /* Group-item header have 2 margins - top and bottom: */
    1274         iProposedHeight += 2 * iVerticalMargin;
    1275         /* And header content height to take into account: */
    1276         iProposedHeight += m_minimumHeaderSize.height();
    1277 
    1278         /* But if group-item is opened: */
    1279         if (fOpenedGroup)
    1280         {
    1281             /* Prepare variables: */
    1282             int iHorizontalMargin = data(GroupItemData_HorizonalMargin).toInt();
    1283 
    1284             /* We should take into spacing between header and body: */
    1285             iProposedHeight += iVerticalMargin;
    1286             /* Every existing: */
    1287             foreach (UIChooserItem *pItem, items())
    1288             {
    1289                 /* Child height: */
    1290                 iProposedHeight += pItem->minimumHeightHint();
    1291                 /* And interline spacing: */
    1292                 iProposedHeight += iMinorSpacing;
    1293             }
    1294             /* Excpect the last one spacing: */
    1295             iProposedHeight -= iMinorSpacing;
    1296             /* And bottom margin at last: */
    1297             iProposedHeight += iHorizontalMargin;
    1298         }
    1299 
    1300         /* Finally, additional height during animation: */
    1301         if (!fOpenedGroup && m_pToggleButton && m_pToggleButton->isAnimationRunning())
    1302             iProposedHeight += m_iAdditionalHeight;
    1303     }
    1304 
    1305     /* Return result: */
    1306     return iProposedHeight;
    1307 }
    1308 
    1309 int UIChooserItemGroup::minimumWidthHint() const
    1310 {
    1311     return minimumWidthHint(isOpened());
    1312 }
    1313 
    1314 int UIChooserItemGroup::minimumHeightHint() const
    1315 {
    1316     return minimumHeightHint(isOpened());
    1317 }
    1318 
    1319 QSizeF UIChooserItemGroup::minimumSizeHint(bool fOpenedGroup) const
    1320 {
    1321     return QSizeF(minimumWidthHint(fOpenedGroup), minimumHeightHint(fOpenedGroup));
    1322 }
    1323 
    1324 QSizeF UIChooserItemGroup::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
    1325 {
    1326     /* If Qt::MinimumSize requested: */
    1327     if (which == Qt::MinimumSize)
    1328         return minimumSizeHint(isOpened());
    1329     /* Else call to base-class: */
    1330     return UIChooserItem::sizeHint(which, constraint);
    1331 }
    1332 
    1333 QPixmap UIChooserItemGroup::toPixmap()
    1334 {
    1335     /* Ask item to paint itself into pixmap: */
    1336     QSize minimumSize = minimumSizeHint(false).toSize();
    1337     QPixmap pixmap(minimumSize);
    1338     pixmap.fill(Qt::transparent);
    1339     QPainter painter(&pixmap);
    1340     painter.setRenderHint(QPainter::Antialiasing);
    1341     QStyleOptionGraphicsItem options;
    1342     options.rect = QRect(QPoint(0, 0), minimumSize);
    1343     paint(&painter, &options);
    1344     return pixmap;
    1345 }
    1346 
    1347 bool UIChooserItemGroup::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const
    1348 {
    1349     /* No drops while saving groups: */
    1350     if (model()->isGroupSavingInProgress())
    1351         return false;
    1352     /* Get mime: */
    1353     const QMimeData *pMimeData = pEvent->mimeData();
    1354     /* If drag token is shown, its up to parent to decide: */
    1355     if (where != DragToken_Off)
    1356         return parentItem()->isDropAllowed(pEvent);
    1357     /* Else we should check mime format: */
    1358     if (pMimeData->hasFormat(UIChooserItemGroup::className()))
    1359     {
    1360         /* Get passed group-item: */
    1361         const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);
    1362         AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
    1363         UIChooserItem *pItem = pCastedMimeData->item();
    1364         /* Make sure passed group is mutable within this group: */
    1365         if (pItem->toGroupItem()->isContainsLockedMachine() &&
    1366             !items(UIChooserItemType_Group).contains(pItem))
    1367             return false;
    1368         /* Make sure passed group is not 'this': */
    1369         if (pItem == this)
    1370             return false;
    1371         /* Make sure passed group is not among our parents: */
    1372         const UIChooserItem *pTestedWidget = this;
    1373         while (UIChooserItem *pParentOfTestedWidget = pTestedWidget->parentItem())
    1374         {
    1375             if (pItem == pParentOfTestedWidget)
    1376                 return false;
    1377             pTestedWidget = pParentOfTestedWidget;
    1378         }
    1379         return true;
    1380     }
    1381     else if (pMimeData->hasFormat(UIChooserItemMachine::className()))
    1382     {
    1383         /* Get passed machine-item: */
    1384         const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);
    1385         AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
    1386         UIChooserItem *pItem = pCastedMimeData->item();
    1387         /* Make sure passed machine is mutable within this group: */
    1388         if (pItem->toMachineItem()->isLockedMachine() &&
    1389             !items(UIChooserItemType_Machine).contains(pItem))
    1390             return false;
    1391         switch (pEvent->proposedAction())
    1392         {
    1393             case Qt::MoveAction:
    1394             {
    1395                 /* Make sure passed item is ours or there is no other item with such id: */
    1396                 return m_machineItems.contains(pItem) || !isContainsMachine(pItem->toMachineItem()->id());
    1397             }
    1398             case Qt::CopyAction:
    1399             {
    1400                 /* Make sure there is no other item with such id: */
    1401                 return !isContainsMachine(pItem->toMachineItem()->id());
    1402             }
    1403             default: break; /* Shut up, MSC! */
    1404         }
    1405     }
    1406     /* That was invalid mime: */
    1407     return false;
    1408 }
    1409 
    1410 void UIChooserItemGroup::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where)
    1411 {
    1412     /* Get mime: */
    1413     const QMimeData *pMime = pEvent->mimeData();
    1414     /* Check mime format: */
    1415     if (pMime->hasFormat(UIChooserItemGroup::className()))
    1416     {
    1417         switch (pEvent->proposedAction())
    1418         {
    1419             case Qt::MoveAction:
    1420             case Qt::CopyAction:
    1421             {
    1422                 /* Remember scene: */
    1423                 UIChooserModel *pModel = model();
    1424 
    1425                 /* Get passed group-item: */
    1426                 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);
    1427                 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
    1428                 UIChooserItem *pItem = pCastedMime->item();
    1429 
    1430                 /* Check if we have position information: */
    1431                 int iPosition = m_groupItems.size();
    1432                 if (pFromWho && where != DragToken_Off)
    1433                 {
    1434                     /* Make sure sender item if our child: */
    1435                     AssertMsg(m_groupItems.contains(pFromWho), ("Sender item is NOT our child!"));
    1436                     if (m_groupItems.contains(pFromWho))
    1437                     {
    1438                         iPosition = m_groupItems.indexOf(pFromWho);
    1439                         if (where == DragToken_Down)
    1440                             ++iPosition;
    1441                     }
    1442                 }
    1443 
    1444                 /* Copy passed item into this group: */
    1445                 UIChooserItem *pNewGroupItem = new UIChooserItemGroup(this, pItem->toGroupItem(), iPosition);
    1446                 if (isClosed())
    1447                     open(false);
    1448 
    1449                 /* If proposed action is 'move': */
    1450                 if (pEvent->proposedAction() == Qt::MoveAction)
    1451                 {
    1452                     /* Delete passed item: */
    1453                     delete pItem;
    1454                 }
    1455 
    1456                 /* Update model: */
    1457                 pModel->cleanupGroupTree();
    1458                 pModel->updateNavigation();
    1459                 pModel->updateLayout();
    1460                 pModel->setCurrentItem(pNewGroupItem);
    1461                 pModel->saveGroupSettings();
    1462                 break;
    1463             }
    1464             default:
    1465                 break;
    1466         }
    1467     }
    1468     else if (pMime->hasFormat(UIChooserItemMachine::className()))
    1469     {
    1470         switch (pEvent->proposedAction())
    1471         {
    1472             case Qt::MoveAction:
    1473             case Qt::CopyAction:
    1474             {
    1475                 /* Remember scene: */
    1476                 UIChooserModel *pModel = model();
    1477 
    1478                 /* Get passed item: */
    1479                 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);
    1480                 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
    1481                 UIChooserItem *pItem = pCastedMime->item();
    1482 
    1483                 /* Check if we have position information: */
    1484                 int iPosition = m_machineItems.size();
    1485                 if (pFromWho && where != DragToken_Off)
    1486                 {
    1487                     /* Make sure sender item if our child: */
    1488                     AssertMsg(m_machineItems.contains(pFromWho), ("Sender item is NOT our child!"));
    1489                     if (m_machineItems.contains(pFromWho))
    1490                     {
    1491                         iPosition = m_machineItems.indexOf(pFromWho);
    1492                         if (where == DragToken_Down)
    1493                             ++iPosition;
    1494                     }
    1495                 }
    1496 
    1497                 /* Copy passed machine-item into this group: */
    1498                 UIChooserItem *pNewMachineItem = new UIChooserItemMachine(this, pItem->toMachineItem(), iPosition);
    1499                 if (isClosed())
    1500                     open(false);
    1501 
    1502                 /* If proposed action is 'move': */
    1503                 if (pEvent->proposedAction() == Qt::MoveAction)
    1504                 {
    1505                     /* Delete passed item: */
    1506                     delete pItem;
    1507                 }
    1508 
    1509                 /* Update model: */
    1510                 pModel->cleanupGroupTree();
    1511                 pModel->updateNavigation();
    1512                 pModel->updateLayout();
    1513                 pModel->setCurrentItem(pNewMachineItem);
    1514                 pModel->saveGroupSettings();
    1515                 break;
    1516             }
    1517             default:
    1518                 break;
    1519         }
    1520     }
    1521 }
    1522 
    1523 void UIChooserItemGroup::resetDragToken()
    1524 {
    1525     /* Reset drag token for this item: */
    1526     if (dragTokenPlace() != DragToken_Off)
    1527     {
    1528         setDragTokenPlace(DragToken_Off);
    1529         update();
    1530     }
    1531     /* Reset drag tokens for all the items: */
    1532     foreach (UIChooserItem *pItem, items())
    1533         pItem->resetDragToken();
    1534 }
    1535 
    1536 QMimeData* UIChooserItemGroup::createMimeData()
    1537 {
    1538     return new UIChooserItemMimeData(this);
    1539 }
    1540 
    1541 void UIChooserItemGroup::showEvent(QShowEvent *pEvent)
    1542 {
    1543     /* Call to base-class: */
    1544     UIChooserItem::showEvent(pEvent);
    1545 
    1546     /* Update pixmaps: */
    1547     updatePixmaps();
    1548 }
    1549 
    1550 void UIChooserItemGroup::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
    1551 {
    1552     /* Call to base-class: */
    1553     UIChooserItem::resizeEvent(pEvent);
    1554 
    1555     /* What is the new geometry? */
    1556     QRectF newGeometry = geometry();
    1557 
    1558     /* Should we update visible name? */
    1559     if (previousGeometry().width() != newGeometry.width())
    1560         updateVisibleName();
    1561 
    1562     /* Remember the new geometry: */
    1563     setPreviousGeometry(newGeometry);
    1564 }
    1565 
    1566 void UIChooserItemGroup::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)
    1567 {
    1568     /* Skip if hovered: */
    1569     if (isHovered())
    1570         return;
    1571 
    1572     /* Prepare variables: */
    1573     QPoint pos = pEvent->pos().toPoint();
    1574     int iMargin = data(GroupItemData_VerticalMargin).toInt();
    1575     int iHeaderHeight = m_minimumHeaderSize.height();
    1576     int iFullHeaderHeight = 2 * iMargin + iHeaderHeight;
    1577     /* Skip if hovered part out of the header: */
    1578     if (pos.y() >= iFullHeaderHeight)
    1579         return;
    1580 
    1581     /* Call to base-class: */
    1582     UIChooserItem::hoverMoveEvent(pEvent);
    1583 
    1584     /* Update linked values: */
    1585     updateVisibleName();
    1586 }
    1587 
    1588 void UIChooserItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)
    1589 {
    1590     /* Skip if not hovered: */
    1591     if (!isHovered())
    1592         return;
    1593 
    1594     /* Call to base-class: */
    1595     UIChooserItem::hoverLeaveEvent(pEvent);
    1596 
    1597     /* Update linked values: */
    1598     updateVisibleName();
    1599 }
    1600 
    1601 void UIChooserItemGroup::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget* /* pWidget = 0 */)
    1602 {
    1603     /* Setup: */
    1604     pPainter->setRenderHint(QPainter::Antialiasing);
    1605 
    1606     /* Paint background: */
    1607     paintBackground(pPainter, pOption->rect);
    1608 
    1609     /* Paint header: */
    1610     paintHeader(pPainter, pOption->rect);
    1611 }
    1612 
    16131687void UIChooserItemGroup::paintBackground(QPainter *pPainter, const QRect &rect)
    16141688{
     
    18731947}
    18741948
    1875 void UIChooserItemGroup::updateAnimationParameters()
    1876 {
    1877     /* Only for item with button: */
    1878     if (!m_pToggleButton)
    1879         return;
    1880 
    1881     /* Recalculate animation parameters: */
    1882     QSizeF openedSize = minimumSizeHint(true);
    1883     QSizeF closedSize = minimumSizeHint(false);
    1884     int iAdditionalHeight = (int)(openedSize.height() - closedSize.height());
    1885     m_pToggleButton->setAnimationRange(0, iAdditionalHeight);
    1886 }
    1887 
    1888 void UIChooserItemGroup::setAdditionalHeight(int iAdditionalHeight)
    1889 {
    1890     m_iAdditionalHeight = iAdditionalHeight;
    1891     updateGeometry();
    1892     model()->updateLayout();
    1893 }
    1894 
    1895 int UIChooserItemGroup::additionalHeight() const
    1896 {
    1897     return m_iAdditionalHeight;
    1898 }
     1949
     1950/*********************************************************************************************************************************
     1951*   Class UIEditorGroupRename implementation.                                                                                    *
     1952*********************************************************************************************************************************/
    18991953
    19001954UIEditorGroupRename::UIEditorGroupRename(const QString &strName, UIChooserItem *pParent)
     
    19031957    , m_pTemporaryMenu(0)
    19041958{
    1905     /* Create line-edit: */
    1906     m_pLineEdit = new QLineEdit(strName, this);
    1907     m_pLineEdit->setTextMargins(0, 0, 0, 0);
    1908     connect(m_pLineEdit, SIGNAL(returnPressed()), this, SIGNAL(sigEditingFinished()));
    1909     /* Create main-layout: */
     1959    /* Create layout: */
    19101960    QHBoxLayout *pLayout = new QHBoxLayout(this);
    1911     pLayout->setContentsMargins(0, 0, 0, 0);
    1912     /* Add line-edit into main-layout: */
    1913     pLayout->addWidget(m_pLineEdit);
     1961    if (pLayout)
     1962    {
     1963        /* Configure layout: */
     1964        pLayout->setContentsMargins(0, 0, 0, 0);
     1965
     1966        /* Create line-edit: */
     1967        m_pLineEdit = new QLineEdit(strName);
     1968        if (m_pLineEdit)
     1969        {
     1970            m_pLineEdit->setTextMargins(0, 0, 0, 0);
     1971            connect(m_pLineEdit, &QLineEdit::returnPressed,
     1972                    this, &UIEditorGroupRename::sigEditingFinished);
     1973        }
     1974
     1975        /* Add into layout: */
     1976        pLayout->addWidget(m_pLineEdit);
     1977    }
     1978
    19141979    /* Install event-filter: */
    19151980    m_pLineEdit->installEventFilter(this);
    19161981}
    19171982
     1983void UIEditorGroupRename::setText(const QString &strText)
     1984{
     1985    m_pLineEdit->setText(strText);
     1986}
     1987
    19181988QString UIEditorGroupRename::text() const
    19191989{
    19201990    return m_pLineEdit->text();
    1921 }
    1922 
    1923 void UIEditorGroupRename::setText(const QString &strText)
    1924 {
    1925     m_pLineEdit->setText(strText);
    19261991}
    19271992
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemGroup.h

    r73927 r73948  
    55
    66/*
    7  * Copyright (C) 2012-2017 Oracle Corporation
     7 * Copyright (C) 2012-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 #ifndef __UIChooserItemGroup_h__
    19 #define __UIChooserItemGroup_h__
     18#ifndef ___UIChooserItemGroup_h___
     19#define ___UIChooserItemGroup_h___
    2020
    2121/* Qt includes: */
     22#include <QPixmap>
     23#include <QString>
    2224#include <QWidget>
    23 #include <QPixmap>
    2425
    2526/* GUI includes: */
     
    2728
    2829/* Forward declarations: */
     30class QGraphicsProxyWidget;
    2931class QGraphicsScene;
    30 class QGraphicsProxyWidget;
    3132class QLineEdit;
     33class QMenu;
     34class QMimeData;
     35class QPainter;
     36class QStyleOptionGraphicsItem;
     37class UIEditorGroupRename;
    3238class UIGraphicsButton;
    3339class UIGraphicsRotatorButton;
    34 class UIEditorGroupRename;
    35 
    36 /* Graphics group-item
    37  * for graphics selector model/view architecture: */
     40
     41
     42/** UIChooserItem extension implementing group item. */
    3843class UIChooserItemGroup : public UIChooserItem
    3944{
     
    4348signals:
    4449
    45     /* Notifiers: Toggle stuff: */
    46     void sigToggleStarted();
    47     void sigToggleFinished();
     50    /** @name Item stuff.
     51      * @{ */
     52        /** Notifies listeners about toggle start. */
     53        void sigToggleStarted();
     54        /** Notifies listeners about toggle finish. */
     55        void sigToggleFinished();
     56    /** @} */
    4857
    4958public:
    5059
    51     /* Class-name used for drag&drop mime-data format: */
    52     static QString className();
    53 
    54     /* Graphics-item type: */
     60    /** RTTI item type. */
    5561    enum { Type = UIChooserItemType_Group };
    56     int type() const { return Type; }
    57 
    58     /* Constructor (main-root-item): */
     62
     63    /** Constructs main-root item passing pScene to the base-class. */
    5964    UIChooserItemGroup(QGraphicsScene *pScene);
    60     /* Constructor (temporary main-root-item/root-item copy): */
     65    /** Constructs temporary @a fMainRoot item as a @a pCopyFrom passing pScene to the base-class. */
    6166    UIChooserItemGroup(QGraphicsScene *pScene, UIChooserItemGroup *pCopyFrom, bool fMainRoot);
    62     /* Constructor (new non-root-item): */
     67    /** Constructs non-root item with specified @a strName and @a iPosition, @a fOpened if requested. */
    6368    UIChooserItemGroup(UIChooserItem *pParent, const QString &strName, bool fOpened = false, int iPosition  = -1);
    64     /* Constructor (new non-root-item copy): */
     69    /** Constructs temporary non-root item with specified @a iPosition as a @a pCopyFrom. */
    6570    UIChooserItemGroup(UIChooserItem *pParent, UIChooserItemGroup *pCopyFrom, int iPosition = -1);
    66     /* Destructor: */
     71    /** Destructs group item. */
    6772    ~UIChooserItemGroup();
    6873
    69     /* API: Basic stuff: */
    70     QString name() const;
    71     QString description() const;
    72     QString fullName() const;
    73     QString definition() const;
    74     void setName(const QString &strName);
    75     bool isClosed() const;
    76     bool isOpened() const;
    77     void close(bool fAnimated = true);
    78     void open(bool fAnimated = true);
    79 
    80     /* API: Children stuff: */
    81     bool isContainsMachine(const QString &strId) const;
    82     bool isContainsLockedMachine();
     74    /** @name Item stuff.
     75      * @{ */
     76        /** Defines group @a strName. */
     77        void setName(const QString &strName);
     78
     79        /** Closes group in @a fAnimated way if requested. */
     80        void close(bool fAnimated = true);
     81        /** Returns whether group is closed. */
     82        bool isClosed() const;
     83
     84        /** Opens group in @a fAnimated way if requested. */
     85        void open(bool fAnimated = true);
     86        /** Returns whether group is opened. */
     87        bool isOpened() const;
     88    /** @} */
     89
     90    /** @name Navigation stuff.
     91      * @{ */
     92        /** Class-name used for drag&drop mime-data format. */
     93        static QString className();
     94    /** @} */
     95
     96protected:
     97
     98    /** @name Event-handling stuff.
     99      * @{ */
     100        /** Handles translation event. */
     101        virtual void retranslateUi() /* override */;
     102
     103        /** Handles show @a pEvent. */
     104        virtual void showEvent(QShowEvent *pEvent) /* override */;
     105
     106        /** Handles resize @a pEvent. */
     107        virtual void resizeEvent(QGraphicsSceneResizeEvent *pEvent) /* override */;
     108
     109        /** Handles hover enter @a event. */
     110        virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */;
     111        /** Handles hover leave @a event. */
     112        virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) /* override */;
     113
     114        /** Performs painting using passed @a pPainter, @a pOptions and optionally specified @a pWidget. */
     115        virtual void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget *pWidget = 0) /* override */;
     116    /** @} */
     117
     118    /** @name Item stuff.
     119      * @{ */
     120        /** Returns RTTI item type. */
     121        virtual int type() const /* override */ { return Type; }
     122
     123        /** Shows item. */
     124        virtual void show() /* override */;
     125        /** Hides item. */
     126        virtual void hide() /* override */;
     127
     128        /** Starts item editing. */
     129        virtual void startEditing() /* override */;
     130
     131        /** Updates item tool-tip. */
     132        virtual void updateToolTip() /* override */;
     133
     134        /** Returns item name. */
     135        virtual QString name() const /* override */;
     136        /** Returns item description. */
     137        virtual QString description() const /* override */;
     138        /** Returns item full-name. */
     139        virtual QString fullName() const /* override */;
     140        /** Returns item definition. */
     141        virtual QString definition() const /* override */;
     142
     143        /** Handles root status change. */
     144        virtual void handleRootStatusChange() /* override */;
     145    /** @} */
     146
     147    /** @name Children stuff.
     148      * @{ */
     149        /** Adds child @a pItem to certain @a iPosition. */
     150        virtual void addItem(UIChooserItem *pItem, int iPosition) /* override */;
     151        /** Removes child @a pItem. */
     152        virtual void removeItem(UIChooserItem *pItem) /* override */;
     153
     154        /** Replaces children @a items of certain @a enmType. */
     155        virtual void setItems(const QList<UIChooserItem*> &items, UIChooserItemType enmType) /* override */;
     156        /** Returns children items of certain @a enmType. */
     157        virtual QList<UIChooserItem*> items(UIChooserItemType enmType = UIChooserItemType_Any) const /* override */;
     158        /** Returns whether there are children items of certain @a enmType. */
     159        virtual bool hasItems(UIChooserItemType enmType = UIChooserItemType_Any) const /* override */;
     160        /** Clears children items of certain @a enmType. */
     161        virtual void clearItems(UIChooserItemType enmType = UIChooserItemType_Any) /* override */;
     162
     163        /** Updates all children items with specified @a strId. */
     164        virtual void updateAllItems(const QString &strId) /* override */;
     165        /** Removes all children items with specified @a strId. */
     166        virtual void removeAllItems(const QString &strId) /* override */;
     167
     168        /** Searches for a first child item answering to specified @a strSearchTag and @a iItemSearchFlags. */
     169        virtual UIChooserItem *searchForItem(const QString &strSearchTag, int iItemSearchFlags) /* override */;
     170
     171        /** Searches for a first machine child item. */
     172        virtual UIChooserItem *firstMachineItem() /* override */;
     173
     174        /** Sorts children items. */
     175        virtual void sortItems() /* override */;
     176    /** @} */
     177
     178    /** @name Layout stuff.
     179      * @{ */
     180        /** Updates layout. */
     181        virtual void updateLayout() /* override */;
     182
     183        /** Returns minimum width-hint. */
     184        virtual int minimumWidthHint() const /* override */;
     185        /** Returns minimum height-hint. */
     186        virtual int minimumHeightHint() const /* override */;
     187
     188        /** Returns size-hint.
     189          * @param  enmWhich    Brings size-hint type.
     190          * @param  constraint  Brings size constraint. */
     191        virtual QSizeF sizeHint(Qt::SizeHint enmWhich, const QSizeF &constraint = QSizeF()) const /* override */;
     192    /** @} */
     193
     194    /** @name Navigation stuff.
     195      * @{ */
     196        /** Returns pixmap item representation. */
     197        virtual QPixmap toPixmap() /* override */;
     198
     199        /** Returns whether item drop is allowed.
     200          * @param  pEvent    Brings information about drop event.
     201          * @param  enmPlace  Brings the place of drag token to the drop moment. */
     202        virtual bool isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const /* override */;
     203        /** Processes item drop.
     204          * @param  pEvent    Brings information about drop event.
     205          * @param  pFromWho  Brings the item according to which we choose drop position.
     206          * @param  enmPlace  Brings the place of drag token to the drop moment (according to item mentioned above). */
     207        virtual void processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where) /* override */;
     208        /** Reset drag token. */
     209        virtual void resetDragToken() /* override */;
     210
     211        /** Returns D&D mime data. */
     212        virtual QMimeData *createMimeData() /* override */;
     213    /** @} */
    83214
    84215private slots:
    85216
    86     /** Handles top-level window remaps. */
    87     void sltHandleWindowRemapped();
    88 
    89     /* Handler: Name editing stuff: */
    90     void sltNameEditingFinished();
    91 
    92     /* Handler: Toggle stuff: */
    93     void sltGroupToggleStart();
    94     void sltGroupToggleFinish(bool fToggled);
    95 
    96     /* Handlers: Indent root stuff: */
    97     void sltIndentRoot();
    98     void sltUnindentRoot();
     217    /** @name Item stuff.
     218      * @{ */
     219        /** Handles top-level window remaps. */
     220        void sltHandleWindowRemapped();
     221
     222        /** Handles name editing trigger. */
     223        void sltNameEditingFinished();
     224
     225        /** Handles group toggle start. */
     226        void sltGroupToggleStart();
     227        /** Handles group toggle finish for group finally @a fToggled. */
     228        void sltGroupToggleFinish(bool fToggled);
     229
     230        /** Handles root indentation. */
     231        void sltIndentRoot();
     232        /** Handles root unindentation. */
     233        void sltUnindentRoot();
     234    /** @} */
    99235
    100236private:
    101237
    102     /* Data enumerator: */
     238    /** Data field types. */
    103239    enum GroupItemData
    104240    {
     
    111247    };
    112248
    113     /* Data provider: */
    114     QVariant data(int iKey) const;
    115 
    116     /* Helpers: Prepare stuff: */
    117     void prepare();
    118     static void copyContent(UIChooserItemGroup *pFrom, UIChooserItemGroup *pTo);
    119 
    120     /* Helpers: Update stuff: */
    121     void handleRootStatusChange();
    122     void updateVisibleName();
    123     void updatePixmaps();
    124     void updateItemCountInfo();
    125     void updateMinimumHeaderSize();
    126     void updateToolTip();
    127     void updateToggleButtonToolTip();
    128 
    129     /* Helper: Translate stuff: */
    130     void retranslateUi();
    131 
    132     /* Helpers: Basic stuff: */
    133     void show();
    134     void hide();
    135     void startEditing();
    136     bool isMainRoot() const { return m_fMainRoot; }
    137 
    138     /* Helpers: Children stuff: */
    139     void addItem(UIChooserItem *pItem, int iPosition);
    140     void removeItem(UIChooserItem *pItem);
    141     void setItems(const QList<UIChooserItem*> &items, UIChooserItemType type);
    142     QList<UIChooserItem*> items(UIChooserItemType type = UIChooserItemType_Any) const;
    143     bool hasItems(UIChooserItemType type = UIChooserItemType_Any) const;
    144     void clearItems(UIChooserItemType type = UIChooserItemType_Any);
    145     void updateAllItems(const QString &strId);
    146     void removeAllItems(const QString &strId);
    147     UIChooserItem *searchForItem(const QString &strSearchTag, int iItemSearchFlags);
    148     UIChooserItem *firstMachineItem();
    149     void sortItems();
    150 
    151     /* Helpers: Layout stuff: */
    152     void updateLayout();
    153     int minimumWidthHint(bool fOpenedGroup) const;
    154     int minimumHeightHint(bool fOpenedGroup) const;
    155     int minimumWidthHint() const;
    156     int minimumHeightHint() const;
    157 #ifdef VBOX_WS_MAC
    158 # pragma clang diagnostic push
    159 # pragma clang diagnostic ignored "-Woverloaded-virtual"
    160 #endif
    161     QSizeF minimumSizeHint(bool fOpenedGroup) const;
    162 #ifdef VBOX_WS_MAC
    163 # pragma clang diagnostic pop
    164 #endif
    165     QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
    166 
    167     /* Helpers: Drag&drop stuff: */
    168     QPixmap toPixmap();
    169     bool isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const;
    170     void processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, DragToken where);
    171     void resetDragToken();
    172     QMimeData* createMimeData();
    173 
    174     /** Handles show @a pEvent. */
    175     virtual void showEvent(QShowEvent *pEvent) /* override */;
    176 
    177     /* Handler: Resize handling stuff: */
    178     void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
    179 
    180     /* Handlers: Hover handling stuff: */
    181     void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);
    182     void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);
    183 
    184     /* Helpers: Paint stuff: */
    185     void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
    186     void paintBackground(QPainter *pPainter, const QRect &rect);
    187     void paintHeader(QPainter *pPainter, const QRect &rect);
    188 
    189     /* Helpers: Animation stuff: */
    190     void updateAnimationParameters();
    191     void setAdditionalHeight(int iAdditionalHeight);
    192     int additionalHeight() const;
    193 
    194     /* Helper: Color stuff: */
    195     int blackoutDarkness() const { return m_iBlackoutDarkness; }
    196 
    197     /* Variables: */
    198     bool m_fClosed;
    199     UIGraphicsRotatorButton *m_pToggleButton;
    200     UIGraphicsButton *m_pEnterButton;
    201     UIGraphicsButton *m_pExitButton;
    202     UIEditorGroupRename *m_pNameEditorWidget;
    203     QGraphicsProxyWidget *m_pNameEditor;
    204     QList<UIChooserItem*> m_groupItems;
    205     QList<UIChooserItem*> m_globalItems;
    206     QList<UIChooserItem*> m_machineItems;
    207     int m_iAdditionalHeight;
    208     int m_iCornerRadius;
    209     bool m_fMainRoot;
    210     int m_iBlackoutDarkness;
    211     /* Cached values: */
    212     QString m_strName;
    213     QString m_strDescription;
    214     QString m_strVisibleName;
    215     QString m_strInfoGroups;
    216     QString m_strInfoMachines;
    217     QSize m_visibleNameSize;
    218     QSize m_infoSizeGroups;
    219     QSize m_infoSizeMachines;
    220     QSize m_pixmapSizeGroups;
    221     QSize m_pixmapSizeMachines;
    222     QSize m_minimumHeaderSize;
    223     QSize m_toggleButtonSize;
    224     QSize m_enterButtonSize;
    225     QSize m_exitButtonSize;
    226     QFont m_nameFont;
    227     QFont m_infoFont;
    228     QPixmap m_groupsPixmap;
    229     QPixmap m_machinesPixmap;
     249    /** @name Prepare/cleanup cascade.
     250      * @{ */
     251        /** Prepares all. */
     252        void prepare();
     253
     254        /** Copies group contents @a pFrom one item @a pTo another. */
     255        static void copyContent(UIChooserItemGroup *pFrom, UIChooserItemGroup *pTo);
     256    /** @} */
     257
     258    /** @name Item stuff.
     259      * @{ */
     260        /** Returns abstractly stored data value for certain @a iKey. */
     261        QVariant data(int iKey) const;
     262
     263        /** Returns whether group is main-root. */
     264        bool isMainRoot() const { return m_fMainRoot; }
     265
     266        /** Returns blackout item darkness. */
     267        int blackoutDarkness() const { return m_iBlackoutDarkness; }
     268
     269        /** Defines @a iAdditionalHeight. */
     270        void setAdditionalHeight(int iAdditionalHeight);
     271        /** Returns additional height. */
     272        int additionalHeight() const;
     273
     274        /** Updates animation parameters. */
     275        void updateAnimationParameters();
     276        /** Updates toggle-button tool-tip. */
     277        void updateToggleButtonToolTip();
     278    /** @} */
     279
     280    /** @name Children stuff.
     281      * @{ */
     282        /** Returns whether group contains machine with @a strId. */
     283        bool isContainsMachine(const QString &strId) const;
     284        /** Returns whether group contains locked machine. */
     285        bool isContainsLockedMachine();
     286
     287        /** Updates user count info. */
     288        void updateItemCountInfo();
     289    /** @} */
     290
     291    /** @name Layout stuff.
     292      * @{ */
     293        /** Returns minimum width-hint depending on whether @a fGroupOpened. */
     294        int minimumWidthHintForGroup(bool fGroupOpened) const;
     295        /** Returns minimum height-hint depending on whether @a fGroupOpened. */
     296        int minimumHeightHintForGroup(bool fGroupOpened) const;
     297        /** Returns minimum size-hint depending on whether @a fGroupOpened. */
     298        QSizeF minimumSizeHintForProup(bool fGroupOpened) const;
     299
     300        /** Updates visible name. */
     301        void updateVisibleName();
     302        /** Updates pixmaps. */
     303        void updatePixmaps();
     304        /** Updates minimum header size. */
     305        void updateMinimumHeaderSize();
     306    /** @} */
     307
     308    /** @name Painting stuff.
     309      * @{ */
     310        /** Paints background using specified @a pPainter and certain @a rect. */
     311        void paintBackground(QPainter *pPainter, const QRect &rect);
     312        /** Paints header using specified @a pPainter and certain @a rect. */
     313        void paintHeader(QPainter *pPainter, const QRect &rect);
     314    /** @} */
     315
     316    /** @name Item stuff.
     317      * @{ */
     318        /** Holds whether group is main-root. */
     319        bool  m_fMainRoot;
     320        /** Holds whether group is closed. */
     321        bool  m_fClosed;
     322
     323        /** Holds aditional height. */
     324        int  m_iAdditionalHeight;
     325        /** Holds corner radious. */
     326        int  m_iCornerRadius;
     327        /** Holds blackout item darkness. */
     328        int  m_iBlackoutDarkness;
     329
     330        /** Holds the cached name. */
     331        QString m_strName;
     332        /** Holds the cached description. */
     333        QString m_strDescription;
     334        /** Holds the cached visible name. */
     335        QString m_strVisibleName;
     336
     337        /** Holds the name font. */
     338        QFont  m_nameFont;
     339
     340        /** Holds the group toggle button instance. */
     341        UIGraphicsRotatorButton *m_pToggleButton;
     342        /** Holds the group enter button instance. */
     343        UIGraphicsButton        *m_pEnterButton;
     344        /** Holds the group exit button instance. */
     345        UIGraphicsButton        *m_pExitButton;
     346
     347        /** Holds the group name editor instance. */
     348        UIEditorGroupRename  *m_pNameEditorWidget;
     349        /** Holds the group name editor proxy instance. */
     350        QGraphicsProxyWidget *m_pNameEditor;
     351    /** @} */
     352
     353    /** @name Children stuff.
     354      * @{ */
     355        /** Holds the group children list. */
     356        QList<UIChooserItem*>  m_groupItems;
     357        /** Holds the global children list. */
     358        QList<UIChooserItem*>  m_globalItems;
     359        /** Holds the machine children list. */
     360        QList<UIChooserItem*>  m_machineItems;
     361
     362        /** Holds group children pixmap. */
     363        QPixmap  m_groupsPixmap;
     364        /** Holds machine children pixmap. */
     365        QPixmap  m_machinesPixmap;
     366
     367        /** Holds the cached group children info. */
     368        QString  m_strInfoGroups;
     369        /** Holds the cached machine children info. */
     370        QString  m_strInfoMachines;
     371
     372        /** Holds the children info font. */
     373        QFont  m_infoFont;
     374    /** @} */
     375
     376    /** @name Layout stuff.
     377      * @{ */
     378        /** Holds cached visible name size. */
     379        QSize  m_visibleNameSize;
     380        /** Holds cached group children pixmap size. */
     381        QSize  m_pixmapSizeGroups;
     382        /** Holds cached machine children pixmap size. */
     383        QSize  m_pixmapSizeMachines;
     384        /** Holds cached group children info size. */
     385        QSize  m_infoSizeGroups;
     386        /** Holds cached machine children info size. */
     387        QSize  m_infoSizeMachines;
     388        /** Holds cached minimum header size. */
     389        QSize  m_minimumHeaderSize;
     390        /** Holds cached toggle button size. */
     391        QSize  m_toggleButtonSize;
     392        /** Holds cached enter button size. */
     393        QSize  m_enterButtonSize;
     394        /** Holds cached exit button size. */
     395        QSize  m_exitButtonSize;
     396    /** @} */
    230397};
    231398
     399
     400/** QWidget extension to use as group name editor. */
    232401class UIEditorGroupRename : public QWidget
    233402{
     
    236405signals:
    237406
    238     /* Notifier: Editing stuff: */
     407    /** Notifies about group editing finished. */
    239408    void sigEditingFinished();
    240409
    241410public:
    242411
    243     /* Constructor: */
     412    /** Constructs group editor with initial @a strName passing @a pParent to the base-class. */
    244413    UIEditorGroupRename(const QString &strName, UIChooserItem *pParent);
    245414
    246     /* API: Text stuff: */
     415    /** Defines editor @a strText. */
     416    void setText(const QString &strText);
     417    /** Returns editor text. */
    247418    QString text() const;
    248     void setText(const QString &strText);
    249 
    250     /* API: Font stuff: */
     419
     420    /** Defines editor @a font. */
    251421    void setFont(const QFont &font);
    252422
    253423public slots:
    254424
    255     /* API/Handler: Focus stuff: */
     425    /** ACquires keyboard focus. */
    256426    void setFocus();
    257427
     428protected:
     429
     430    /** Preprocesses any Qt @a pEvent for passed @a pObject. */
     431    virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */;
     432
    258433private:
    259434
    260     /* Handler: Event-filter: */
    261     bool eventFilter(QObject *pWatched, QEvent *pEvent);
    262 
    263     /* Helper: Context-menu stuff: */
    264     void handleContextMenuEvent(QContextMenuEvent *pContextMenuEvent);
    265 
    266     /* Variables: */
     435    /** Handles context-menu @a pEvent. */
     436    void handleContextMenuEvent(QContextMenuEvent *pEvent);
     437
     438    /** Holds the parent reference. */
    267439    UIChooserItem *m_pParent;
     440
     441    /** Holds the line-edit instance. */
    268442    QLineEdit *m_pLineEdit;
    269     QMenu *m_pTemporaryMenu;
     443    /** Holds the conect-menu instance. */
     444    QMenu     *m_pTemporaryMenu;
    270445};
    271446
    272 #endif /* __UIChooserItemGroup_h__ */
    273 
     447
     448#endif /* !___UIChooserItemGroup_h___ */
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