VirtualBox

Changeset 89106 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
May 17, 2021 3:32:35 PM (4 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:10003: Reworking Details pane; Heavy rework for details set layout calculations; Lots of bugs fixed in that area.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/manager/details
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsSet.cpp

    r89103 r89106  
    150150    const int iSpacing = data(SetData_Spacing).toInt();
    151151    const int iMaximumWidth = geometry().width();
    152     const UIDetailsElement *pPreviewElement = element(DetailsElementType_Preview);
    153     const int iPreviewWidth = pPreviewElement ? pPreviewElement->minimumWidthHint() : 0;
    154     const int iPreviewHeight = pPreviewElement ? pPreviewElement->minimumHeightHint() : 0;
     152    UIDetailsElement *pPreviewElement = element(DetailsElementType_Preview);
     153    const bool fPreviewVisible = pPreviewElement && pPreviewElement->isVisible();
     154    const int iPreviewWidth = fPreviewVisible ? pPreviewElement->minimumWidthHint() : 0;
     155    const int iPreviewHeight = fPreviewVisible ? pPreviewElement->minimumHeightHint() : 0;
    155156    int iVerticalIndent = iMargin;
    156 
    157     /* Calculate Preview group elements: */
    158     QList<DetailsElementType> inGroup;
    159     QList<DetailsElementType> outGroup;
    160     int iAdditionalGroupHeight = 0;
    161     int iAdditionalPreviewHeight = 0;
    162     enumerateLayoutItems(inGroup, outGroup, iAdditionalGroupHeight, iAdditionalPreviewHeight);
    163 
    164     /* Layout all the elements: */
     157    int iPreviewGroupHeight = 0;
     158    bool fPreviewGroupUnfinished = fPreviewVisible;
     159    QList<UIDetailsElement*> listPreviewGroup;
     160    m_listPreviewGroup.clear();
     161    m_listOutsideGroup.clear();
     162
     163    /* Layout all the items but Preview: */
    165164    foreach (UIDetailsItem *pItem, items())
    166165    {
    167         /* Skip hidden: */
     166        /* Make sure item exists: */
     167        AssertPtrReturnVoid(pItem);
     168        /* Skip item if hidden: */
    168169        if (!pItem->isVisible())
    169170            continue;
    170171
    171         /* For each particular element: */
     172        /* Acquire element type: */
    172173        UIDetailsElement *pElement = pItem->toElement();
     174        AssertPtrReturnVoid(pElement);
    173175        const DetailsElementType enmElementType = pElement->elementType();
    174         switch (enmElementType)
    175         {
    176             case DetailsElementType_General:
    177             case DetailsElementType_System:
    178             case DetailsElementType_Display:
    179             case DetailsElementType_Storage:
    180             case DetailsElementType_Audio:
    181             case DetailsElementType_Network:
    182             case DetailsElementType_Serial:
    183             case DetailsElementType_USB:
    184             case DetailsElementType_SF:
    185             case DetailsElementType_UI:
    186             case DetailsElementType_Description:
     176        /* Skip Preview element: */
     177        if (enmElementType == DetailsElementType_Preview)
     178            continue;
     179
     180        /* Calculate element size: */
     181        QSizeF elementSize;
     182
     183        /* If we haven't finished filling Preview group: */
     184        if (fPreviewGroupUnfinished)
     185        {
     186            /* For Preview group we have limited element width: */
     187            elementSize.setWidth(iMaximumWidth - (iSpacing + iPreviewWidth));
     188            /* Resize element to width to get corresponding height: */
     189            pElement->resize(elementSize.width(), pElement->geometry().height());
     190            /* Now we can get element height based on width above: */
     191            elementSize.setHeight(pElement->minimumHeightHint());
     192            /* Resize element to height based on width above: */
     193            pElement->resize(pElement->geometry().width(), elementSize.height());
     194
     195            /* Calculate remaining vertical space: */
     196            const int iRemainingSpace = (iPreviewHeight + iSpacing) - iPreviewGroupHeight;
     197
     198            /* If last element height is at least two times taller than the remaining space: */
     199            if (elementSize.height() / 2 > iRemainingSpace)
    187200            {
    188                 /* Move element: */
    189                 pElement->setPos(0, iVerticalIndent);
    190 
    191                 /* Calculate required width: */
    192                 int iWidth = iMaximumWidth;
    193                 if (inGroup.contains(enmElementType))
    194                     iWidth -= (iSpacing + iPreviewWidth);
    195                 /* Resize element to required width (separately from height): */
    196                 if (pElement->geometry().width() != iWidth)
    197                     pElement->resize(iWidth, pElement->geometry().height());
    198 
    199                 /* Calculate required height: */
    200                 int iHeight = pElement->minimumHeightHint();
    201                 if (   !inGroup.isEmpty()
    202                     && inGroup.last() == enmElementType)
     201                /* We should stop filling Preview group now: */
     202                fPreviewGroupUnfinished = false;
     203
     204                /* Advance indent only if there is remaining space at all: */
     205                if (iRemainingSpace > 0)
     206                    iVerticalIndent += iRemainingSpace;
     207            }
     208            /* Otherwise last element can still be inserted to Preview group: */
     209            else
     210            {
     211                /* Advance Preview group height: */
     212                iPreviewGroupHeight += (elementSize.height() + iSpacing);
     213                /* Append last Preview group element: */
     214                listPreviewGroup << pElement;
     215                m_listPreviewGroup << enmElementType;
     216            }
     217        }
     218
     219        /* If we have finished filling Preview group: */
     220        if (!fPreviewGroupUnfinished)
     221        {
     222            /* Calculate element width: */
     223            elementSize.setWidth(iMaximumWidth);
     224            /* Resize element to width to get corresponding height: */
     225            pElement->resize(elementSize.width(), pElement->geometry().height());
     226            /* Now we can get element height based on width above: */
     227            elementSize.setHeight(pElement->minimumHeightHint());
     228            /* Resize element to height based on width above: */
     229            pElement->resize(pElement->geometry().width(), elementSize.height());
     230            /* Append last Outside group element: */
     231            m_listOutsideGroup << enmElementType;
     232        }
     233
     234        /* Move element: */
     235        pElement->setPos(0, iVerticalIndent);
     236        /* Layout element content: */
     237        pElement->updateLayout();
     238
     239        /* Advance indent: */
     240        iVerticalIndent += (elementSize.height() + iSpacing);
     241    }
     242
     243    /* Make sure last opened Preview group item, if exists, consumes rest of vertical space: */
     244    if (!listPreviewGroup.isEmpty())
     245    {
     246        /* Calculate remaining vertical space: */
     247        const int iRemainingSpace = (iPreviewHeight + iSpacing) - iPreviewGroupHeight;
     248        if (iRemainingSpace > 0)
     249        {
     250            /* Look for last opened element: */
     251            int iLastOpenedElement = -1;
     252            foreach (UIDetailsElement *pElement, listPreviewGroup)
     253                if (pElement->isOpened())
     254                    iLastOpenedElement = listPreviewGroup.indexOf(pElement);
     255
     256            /* If at least one is opened: */
     257            if (iLastOpenedElement != -1)
     258            {
     259                /* Resize element to width to get corresponding height: */
     260                UIDetailsElement *pFoundOne = listPreviewGroup.at(iLastOpenedElement);
     261                pFoundOne->resize(pFoundOne->geometry().width(), pFoundOne->geometry().height() + iRemainingSpace);
     262
     263                /* Adjust subsequent element positions: */
     264                for (int i = iLastOpenedElement + 1; i < listPreviewGroup.size(); ++i)
    203265                {
    204                     if (!pElement->isAnimationRunning() && !pElement->isClosed())
    205                         iHeight += iAdditionalGroupHeight;
    206                     else
    207                         iVerticalIndent += iAdditionalGroupHeight;
     266                    UIDetailsElement *pIteratedOne = listPreviewGroup.at(i);
     267                    pIteratedOne->setPos(pIteratedOne->geometry().x(), pIteratedOne->geometry().y() + iRemainingSpace);
    208268                }
    209                 /* Resize element to required height (separately from width): */
    210                 if (pElement->geometry().height() != iHeight)
    211                     pElement->resize(pElement->geometry().width(), iHeight);
    212269
    213270                /* Layout element content: */
    214                 pItem->updateLayout();
    215                 /* Advance indent: */
    216                 iVerticalIndent += (iHeight + iSpacing);
    217 
    218                 break;
     271                pFoundOne->updateLayout();
    219272            }
    220             case DetailsElementType_Preview:
    221             {
    222                 /* Move element: */
    223                 pElement->setPos(iMaximumWidth - iPreviewWidth, iMargin);
    224 
    225                 /* Calculate required size: */
    226                 int iWidth = iPreviewWidth;
    227                 int iHeight = iPreviewHeight;
    228                 if (!pElement->isAnimationRunning() && !pElement->isClosed())
    229                     iHeight += iAdditionalPreviewHeight;
    230                 /* Resize element to required size: */
    231                 pElement->resize(iWidth, iHeight);
    232 
    233                 /* Layout element content: */
    234                 pItem->updateLayout();
    235 
    236                 break;
    237             }
    238             default: AssertFailed(); break; /* Shut up, MSC! */
    239         }
     273        }
     274    }
     275
     276    /* If Preview exists: */
     277    if (fPreviewVisible)
     278    {
     279        /* Align it to the right corner if there is at least one element in the Preview group.
     280         * Otherwise we can put it to the left corner to be able to take whole the space. */
     281        if (!listPreviewGroup.isEmpty())
     282            pPreviewElement->setPos(iMaximumWidth - iPreviewWidth, iMargin);
     283        else
     284            pPreviewElement->setPos(0, iMargin);
     285
     286        /* Resize it to it's size if there is at least one element in the Preview group.
     287         * Otherwise we can take whole the horizontal space we have. */
     288        int iWidth = iPreviewWidth;
     289        int iHeight = iPreviewHeight;
     290        if (listPreviewGroup.isEmpty())
     291            iWidth = iMaximumWidth;
     292        if (!pPreviewElement->isAnimationRunning() && !pPreviewElement->isClosed())
     293            iHeight += iPreviewGroupHeight - (iPreviewHeight + iSpacing);
     294        pPreviewElement->resize(iWidth, iHeight);
     295
     296        /* Layout element content: */
     297        pPreviewElement->updateLayout();
    240298    }
    241299}
     
    495553    const int iSpacing = data(SetData_Spacing).toInt();
    496554
    497     /* Calculate Preview group elements: */
    498     QList<DetailsElementType> inGroup;
    499     QList<DetailsElementType> outGroup;
    500     int iAdditionalGroupHeight = 0;
    501     int iAdditionalPreviewHeight = 0;
    502     enumerateLayoutItems(inGroup, outGroup, iAdditionalGroupHeight, iAdditionalPreviewHeight);
    503 
    504555    /* Take into account all the elements: */
     556    int iMinimumHeightHintPreview = 0;
    505557    int iMinimumHeightHintInGroup = 0;
    506558    int iMinimumHeightHintOutGroup = 0;
    507     int iMinimumHeightHintPreview = 0;
    508559    foreach (UIDetailsItem *pItem, items())
    509560    {
    510         /* Skip hidden: */
     561        /* Make sure item exists: */
     562        AssertPtrReturn(pItem, 0);
     563        /* Skip item if hidden: */
    511564        if (!pItem->isVisible())
    512565            continue;
    513566
    514         /* For each particular element: */
     567        /* Acquire element type: */
    515568        UIDetailsElement *pElement = pItem->toElement();
    516         const DetailsElementType enmElementType = pElement->elementType();
    517         switch (enmElementType)
    518         {
    519             case DetailsElementType_General:
    520             case DetailsElementType_System:
    521             case DetailsElementType_Display:
    522             case DetailsElementType_Storage:
    523             case DetailsElementType_Audio:
    524             case DetailsElementType_Network:
    525             case DetailsElementType_Serial:
    526             case DetailsElementType_USB:
    527             case DetailsElementType_SF:
    528             case DetailsElementType_UI:
    529             case DetailsElementType_Description:
    530             {
    531                 if (inGroup.contains(enmElementType))
    532                 {
    533                     iMinimumHeightHintInGroup += (pItem->minimumHeightHint() + iSpacing);
    534                     if (inGroup.last() == enmElementType)
    535                         iMinimumHeightHintInGroup += iAdditionalGroupHeight;
    536                 }
    537                 else if (outGroup.contains(enmElementType))
    538                     iMinimumHeightHintOutGroup += (pItem->minimumHeightHint() + iSpacing);
    539                 break;
    540             }
    541             case DetailsElementType_Preview:
    542             {
    543                 iMinimumHeightHintPreview = pItem->minimumHeightHint() + iAdditionalPreviewHeight;
    544                 break;
    545             }
    546             default: AssertFailed(); break; /* Shut up, MSC! */
    547         }
    548     }
    549 
     569        AssertPtrReturn(pElement, 0);
     570        DetailsElementType enmElementType = pElement->elementType();
     571
     572        /* Calculate corresponding hints: */
     573        if (enmElementType == DetailsElementType_Preview)
     574            iMinimumHeightHintPreview += pItem->minimumHeightHint();
     575        else
     576        {
     577            if (m_listPreviewGroup.contains(enmElementType))
     578                iMinimumHeightHintInGroup += (pItem->minimumHeightHint() + iSpacing);
     579            else if (m_listOutsideGroup.contains(enmElementType))
     580                iMinimumHeightHintOutGroup += (pItem->minimumHeightHint() + iSpacing);
     581        }
     582    }
    550583    /* Minus last spacing: */
    551584    iMinimumHeightHintInGroup -= iSpacing;
    552585    iMinimumHeightHintOutGroup -= iSpacing;
    553586
    554     /* Calculate minimum height hint: */
    555     int iMinimumHeightHint = qMax(iMinimumHeightHintInGroup, iMinimumHeightHintPreview);
    556 
    557     /* Spacing if necessary: */
    558     if (!inGroup.isEmpty() && !outGroup.isEmpty())
     587    /* Append maximum height of Preview and Preview group: */
     588    int iMinimumHeightHint = qMax(iMinimumHeightHintPreview, iMinimumHeightHintInGroup);
     589    /* Add spacing if necessary: */
     590    if (!m_listPreviewGroup.isEmpty() && !m_listOutsideGroup.isEmpty())
    559591        iMinimumHeightHint += iSpacing;
    560 
    561     /* Spacing if necessary: */
    562     if (!outGroup.isEmpty())
     592    /* Add Outside group height if necessary: */
     593    if (!m_listOutsideGroup.isEmpty())
    563594        iMinimumHeightHint += iMinimumHeightHintOutGroup;
    564 
    565595    /* And two margins finally: */
    566596    iMinimumHeightHint += 2 * iMargin;
    567 
    568597    /* Return result: */
    569598    return iMinimumHeightHint;
     
    703732}
    704733
    705 void UIDetailsSet::enumerateLayoutItems(QList<DetailsElementType> &inGroup,
    706                                         QList<DetailsElementType> &outGroup,
    707                                         int &iAdditionalGroupHeight,
    708                                         int &iAdditionalPreviewHeight) const
    709 {
    710     /* Prepare variables: */
    711     const int iSpacing = data(SetData_Spacing).toInt();
    712     const UIDetailsElement *pPreviewElement = element(DetailsElementType_Preview);
    713     const bool fPreviewVisible = pPreviewElement && pPreviewElement->isVisible();
    714     const int iPreviewHeight = fPreviewVisible ? pPreviewElement->minimumHeightHint() : 0;
    715     int iGroupHeight = 0;
    716 
    717     /* Enumerate all the items: */
    718     foreach (UIDetailsItem *pItem, items())
    719     {
    720         /* Skip hidden: */
    721         if (!pItem->isVisible())
    722             continue;
    723 
    724         /* Acquire element and its type: */
    725         const UIDetailsElement *pElement = pItem->toElement();
    726         const DetailsElementType enmElementType = pElement->elementType();
    727 
    728         /* Skip Preview: */
    729         if (enmElementType == DetailsElementType_Preview)
    730             continue;
    731 
    732         /* Acquire element height: */
    733         const int iElementHeight = pElement->minimumHeightHint();
    734 
    735         /* Advance cumulative height if necessary: */
    736         if (   fPreviewVisible
    737             && outGroup.isEmpty()
    738             && (   iGroupHeight == 0
    739                 || iGroupHeight + iElementHeight / 2 < iPreviewHeight))
    740         {
    741             iGroupHeight += iElementHeight;
    742             iGroupHeight += iSpacing;
    743             inGroup << enmElementType;
    744         }
    745         else
    746             outGroup << enmElementType;
    747     }
    748     /* Minus last spacing: */
    749     iGroupHeight -= iSpacing;
    750 
    751     /* Calculate additional height: */
    752     if (iPreviewHeight > iGroupHeight)
    753         iAdditionalGroupHeight = iPreviewHeight - iGroupHeight;
    754     else
    755         iAdditionalPreviewHeight = iGroupHeight - iPreviewHeight;
    756 }
    757 
    758734void UIDetailsSet::paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions) const
    759735{
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsSet.h

    r89103 r89106  
    180180    /** @} */
    181181
    182     /** @name Layout stuff.
    183       * @{ */
    184         /** Enumerates item being placed into layout.
    185           * @param  inGroup   Will contain a list of items in preview group.
    186           * @param  outGroup  Will contain a list of items ouside of preview group.
    187           * @param  iAdditionalGroupHeight    Will have additional group height.
    188           * @param  iAdditionalPreviewHeight  Will have additional preview height. */
    189         void enumerateLayoutItems(QList<DetailsElementType> &inGroup,
    190                                   QList<DetailsElementType> &outGroup,
    191                                   int &iAdditionalGroupHeight,
    192                                   int &iAdditionalPreviewHeight) const;
    193     /** @} */
    194 
    195182    /** @name Painting stuff.
    196183      * @{ */
     
    233220        QMap<int, UIDetailsItem*>  m_elements;
    234221    /** @} */
     222
     223    /** @name Layout stuff.
     224      * @{ */
     225        /** Holds the list of elements in the Preview group. */
     226        QList<DetailsElementType>  m_listPreviewGroup;
     227        /** Holds the list of elements in the Outside group. */
     228        QList<DetailsElementType>  m_listOutsideGroup;
     229    /** @} */
    235230};
    236231
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