VirtualBox

Changeset 101417 in vbox


Ignore:
Timestamp:
Oct 11, 2023 4:17:18 PM (19 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159466
Message:

FE/Qt: bugref:10513: Large rework for UIAdvancedSettingsDialog; This one directed to replace tree-widget selector with new tree-view selector having own item representation delegate.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r101327 r101417  
    10831083        src/notificationcenter/UINotificationCenter.cpp \
    10841084        src/settings/UIAdvancedSettingsDialog.cpp \
     1085        src/settings/UISettingsSelector.cpp \
    10851086        src/settings/editors/UIBaseMemoryEditor.cpp \
    10861087        src/settings/editors/UIBootOrderEditor.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/UIAdvancedSettingsDialog.cpp

    r101342 r101417  
    940940#else /* !VBOX_GUI_WITH_TOOLBAR_SETTINGS */
    941941
     942    /* Make sure there is a serious spacing between selector and pages: */
     943    m_pLayoutMain->setColumnMinimumWidth(1, 20);
     944
    942945    /* Prepare classical tree-view selector: */
    943     m_pSelector = new UISettingsSelectorTreeWidget(centralWidget());
     946    m_pSelector = new UISettingsSelectorTreeView(centralWidget());
    944947    if (m_pSelector)
    945948    {
    946         m_pLayoutMain->addWidget(m_pSelector->widget(), 0, 0, 2, 1);
     949        m_pLayoutMain->addWidget(m_pSelector->widget(), 1, 0);
    947950        m_pSelector->widget()->setFocus();
    948951    }
     
    954957        connect(m_pEditorFilter, &UIFilterEditor::sigTextChanged,
    955958                this, &UIAdvancedSettingsDialog::sltHandleFilterTextChanged);
    956         m_pLayoutMain->addWidget(m_pEditorFilter, 0, 1);
     959        m_pLayoutMain->addWidget(m_pEditorFilter, 0, 2);
    957960    }
    958961#endif /* !VBOX_GUI_WITH_TOOLBAR_SETTINGS */
     
    994997
    995998        /* Add scroll-area into main layout: */
    996         m_pLayoutMain->addWidget(m_pScrollArea, 1, 1);
     999        m_pLayoutMain->addWidget(m_pScrollArea, 1, 2);
    9971000    }
    9981001}
     
    10551058
    10561059        /* Add button-box into main layout: */
    1057         m_pLayoutMain->addWidget(m_pButtonBox, 2, 0, 1, 2);
     1060        m_pLayoutMain->addWidget(m_pButtonBox, 2, 0, 1, 3);
    10581061    }
    10591062}
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsSelector.cpp

    r101392 r101417  
    2727
    2828/* Qt includes: */
     29#include <QAbstractItemModel>
    2930#include <QAccessibleWidget>
    3031#include <QAction>
    3132#include <QActionGroup>
    3233#include <QHeaderView>
     34#include <QItemDelegate>
    3335#include <QLayout>
     36#include <QPainter>
    3437#include <QTabWidget>
    3538#include <QToolButton>
     
    3740/* GUI includes: */
    3841#include "QITabWidget.h"
     42#include "QITreeView.h"
    3943#include "QITreeWidget.h"
    4044#include "UISettingsSelector.h"
    4145#include "UIIconPool.h"
     46#include "UIImageTools.h"
    4247#include "UISettingsPage.h"
    4348#include "QIToolBar.h"
     
    102107    /** Returns corresponding toolbar button. */
    103108    QToolButton *button() const { return qobject_cast<QToolButton*>(widget()); }
     109};
     110
     111
     112/** QITreeViewItem subclass used as selector tree-view item. */
     113class UISelectorTreeViewItem : public QITreeViewItem
     114{
     115    Q_OBJECT;
     116
     117public:
     118
     119    /** Constructs selector item passing @a pParent to the base-class.
     120      * This is constructor for root-item only. */
     121    UISelectorTreeViewItem(QITreeView *pParent);
     122    /** Constructs selector item passing @a pParentItem to the base-class.
     123      * This is constructor for rest of items we need.
     124      * @param  iID      Brings the item ID.
     125      * @param  icon     Brings the item icon.
     126      * @param  strLink  Brings the item link. */
     127    UISelectorTreeViewItem(UISelectorTreeViewItem *pParentItem,
     128                           int iID,
     129                           const QIcon &icon,
     130                           const QString &strLink);
     131
     132    /** Returns item ID. */
     133    int id() const { return m_iID; }
     134    /** Returns item icon. */
     135    QIcon icon() const { return m_icon; }
     136    /** Returns item link. */
     137    QString link() const { return m_strLink; }
     138
     139    /** Returns item text. */
     140    virtual QString text() const RT_OVERRIDE { return m_strText; }
     141    /** Defines item @a strText. */
     142    virtual void setText(const QString &strText) { m_strText = strText; }
     143
     144    /** Returns the number of children. */
     145    virtual int childCount() const RT_OVERRIDE { return m_children.size(); }
     146    /** Returns the child item with @a iIndex. */
     147    virtual UISelectorTreeViewItem *childItem(int iIndex) const RT_OVERRIDE { return m_children.at(iIndex); }
     148
     149    /** Adds @a pChild to this item. */
     150    void addChild(UISelectorTreeViewItem *pChild) { m_children << pChild; }
     151    /** Assigns @a children for this item. */
     152    void setChildren(const QList<UISelectorTreeViewItem*> &children) { m_children = children; }
     153    /** Returns position for the passed @a pChild. */
     154    int posOfChild(UISelectorTreeViewItem *pChild) const { return m_children.indexOf(pChild); }
     155
     156    /** Searches for the child with @a iID specified. */
     157    UISelectorTreeViewItem *childItemById(int iID) const;
     158    /** Searches for the child with @a strLink specified. */
     159    UISelectorTreeViewItem *childItemByLink(const QString &strLink) const;
     160
     161private:
     162
     163    /** Holds the item ID. */
     164    int      m_iID;
     165    /** Holds the item icon. */
     166    QIcon    m_icon;
     167    /** Holds the item link. */
     168    QString  m_strLink;
     169    /** Holds the item text. */
     170    QString  m_strText;
     171
     172    /** Holds the list of children. */
     173    QList<UISelectorTreeViewItem*>  m_children;
     174};
     175
     176
     177/** QItemDelegate subclass used as selector tree-view item delegate. */
     178class UISelectorDelegate : public QItemDelegate
     179{
     180    Q_OBJECT;
     181
     182public:
     183
     184    /** Constructs selector item delegate passing @a pParent to the base-class. */
     185    UISelectorDelegate(QObject *pParent);
     186
     187private:
     188
     189    /** Paints @a index item with specified @a option using specified @a pPainter. */
     190    void paint(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
     191};
     192
     193
     194/** QAbstractItemModel subclass used as selector model. */
     195class UISelectorModel : public QAbstractItemModel
     196{
     197    Q_OBJECT;
     198
     199public:
     200
     201    /** Data roles. */
     202    enum DataRole
     203    {
     204        R_Margin = Qt::UserRole + 1,
     205        R_Spacing,
     206        R_IconSize,
     207
     208        R_ItemId,
     209        R_ItemPixmap,
     210        R_ItemPixmapRect,
     211        R_ItemName,
     212        R_ItemNamePoint,
     213    };
     214
     215    /** Constructs selector model passing @a pParent to the base-class. */
     216    UISelectorModel(QITreeView *pParent);
     217    /** Destructs selector model. */
     218    virtual ~UISelectorModel() RT_OVERRIDE;
     219
     220    /** Returns row count for the passed @a parentIndex. */
     221    virtual int rowCount(const QModelIndex &parentIndex = QModelIndex()) const RT_OVERRIDE;
     222    /** Returns column count for the passed @a parentIndex. */
     223    virtual int columnCount(const QModelIndex &parentIndex = QModelIndex()) const RT_OVERRIDE;
     224
     225    /** Returns parent item of @a specifiedIndex item. */
     226    virtual QModelIndex parent(const QModelIndex &specifiedIndex) const RT_OVERRIDE;
     227    /** Returns item specified by @a iRow, @a iColum and @a parentIndex. */
     228    virtual QModelIndex index(int iRow, int iColumn, const QModelIndex &parentIndex = QModelIndex()) const RT_OVERRIDE;
     229    /** Returns root item. */
     230    QModelIndex root() const;
     231
     232    /** Returns model data for @a specifiedIndex and @a iRole. */
     233    virtual QVariant data(const QModelIndex &specifiedIndex, int iRole) const RT_OVERRIDE;
     234    /** Defines model data for @a specifiedIndex and @a iRole as @a value. */
     235    virtual bool setData(const QModelIndex &specifiedIndex, const QVariant &value, int iRole) RT_OVERRIDE;
     236
     237    /** Adds item with certain @a strId. */
     238    QModelIndex addItem(int iID, const QIcon &icon, const QString &strLink);
     239    /** Deletes item with certain @a iID. */
     240    void delItem(int iID);
     241
     242    /** Returns item with certain @a iID. */
     243    QModelIndex findItem(int iID);
     244    /** Returns item with certain @a strLink. */
     245    QModelIndex findItem(const QString &strLink);
     246
     247    /** Sorts the contents of model by @a iColumn and @a enmOrder. */
     248    virtual void sort(int iColumn = 0, Qt::SortOrder enmOrder = Qt::AscendingOrder) RT_OVERRIDE;
     249
     250private:
     251
     252    /** Returns model flags for @a specifiedIndex. */
     253    virtual Qt::ItemFlags flags(const QModelIndex &specifiedIndex) const RT_OVERRIDE;
     254
     255    /** Returns a pointer to item containing within @a specifiedIndex. */
     256    static UISelectorTreeViewItem *indexToItem(const QModelIndex &specifiedIndex);
     257
     258    /** Holds the parent tree-view reference. */
     259    QITreeView *m_pParentTree;
     260
     261    /** Holds the root item instance. */
     262    UISelectorTreeViewItem *m_pRootItem;
     263};
     264
     265
     266/** QITreeView extension used as selector tree-view. */
     267class UISelectorTreeView : public QITreeView
     268{
     269    Q_OBJECT;
     270
     271public:
     272
     273    /** Constructs selector tree-view passing @a pParent to the base-class. */
     274    UISelectorTreeView(QWidget *pParent);
     275
     276    /** Calculates widget minimum size-hint. */
     277    virtual QSize minimumSizeHint() const RT_OVERRIDE;
     278    /** Calculates widget size-hint. */
     279    virtual QSize sizeHint() const RT_OVERRIDE;
     280
     281private:
     282
     283    /** Prepares all. */
     284    void prepare();
    104285};
    105286
     
    207388
    208389/*********************************************************************************************************************************
     390*   Class UISelectorTreeViewItem implementation.                                                                                 *
     391*********************************************************************************************************************************/
     392
     393UISelectorTreeViewItem::UISelectorTreeViewItem(QITreeView *pParent)
     394    : QITreeViewItem(pParent)
     395{
     396}
     397
     398UISelectorTreeViewItem::UISelectorTreeViewItem(UISelectorTreeViewItem *pParentItem,
     399                                               int iID,
     400                                               const QIcon &icon,
     401                                               const QString &strLink)
     402    : QITreeViewItem(pParentItem)
     403    , m_iID(iID)
     404    , m_icon(icon)
     405    , m_strLink(strLink)
     406{
     407    if (pParentItem)
     408        pParentItem->addChild(this);
     409}
     410
     411UISelectorTreeViewItem *UISelectorTreeViewItem::childItemById(int iID) const
     412{
     413    for (int i = 0; i < childCount(); ++i)
     414        if (UISelectorTreeViewItem *pItem = childItem(i))
     415            if (pItem->id() == iID)
     416                return pItem;
     417    return 0;
     418}
     419
     420UISelectorTreeViewItem *UISelectorTreeViewItem::childItemByLink(const QString &strLink) const
     421{
     422    for (int i = 0; i < childCount(); ++i)
     423        if (UISelectorTreeViewItem *pItem = childItem(i))
     424            if (pItem->link() == strLink)
     425                return pItem;
     426    return 0;
     427}
     428
     429
     430/*********************************************************************************************************************************
     431*   Class UISelectorDelegate implementation.                                                                                     *
     432*********************************************************************************************************************************/
     433
     434UISelectorDelegate::UISelectorDelegate(QObject *pParent)
     435    : QItemDelegate(pParent)
     436{
     437}
     438
     439void UISelectorDelegate::paint(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const
     440{
     441    /* Sanity checks: */
     442    AssertPtrReturnVoid(pPainter);
     443    AssertReturnVoid(index.isValid());
     444
     445    /* Acquire model: */
     446    const UISelectorModel *pModel = qobject_cast<const UISelectorModel*>(index.model());
     447
     448    /* Acquire item properties: */
     449    const QPalette palette = QGuiApplication::palette();
     450    const QRect itemRectangle = option.rect;
     451    const QStyle::State enmState = option.state;
     452    const bool fChosen = enmState & QStyle::State_Selected;
     453
     454    /* Draw background: */
     455    QColor backColor;
     456    if (fChosen)
     457    {
     458        /* Prepare painter path: */
     459        QPainterPath painterPath;
     460        painterPath.lineTo(itemRectangle.width() - itemRectangle.height(), 0);
     461        painterPath.lineTo(itemRectangle.width(),                          itemRectangle.height());
     462        painterPath.lineTo(0,                                              itemRectangle.height());
     463        painterPath.closeSubpath();
     464        painterPath.translate(itemRectangle.topLeft());
     465
     466        /* Prepare painting gradient: */
     467        backColor = palette.color(QPalette::Active, QPalette::Highlight);
     468        const QColor bcTone1 = backColor.lighter(100);
     469        const QColor bcTone2 = backColor.lighter(120);
     470        QLinearGradient grad(itemRectangle.topLeft(), itemRectangle.bottomRight());
     471        grad.setColorAt(0, bcTone1);
     472        grad.setColorAt(1, bcTone2);
     473
     474        /* Paint fancy shape: */
     475        pPainter->save();
     476        pPainter->setClipPath(painterPath);
     477        pPainter->setPen(backColor);
     478        pPainter->fillRect(itemRectangle, grad);
     479        pPainter->restore();
     480    }
     481    else
     482    {
     483        /* Just init painting color: */
     484        backColor = palette.color(QPalette::Active, QPalette::Window);
     485    }
     486
     487    /* Draw icon: */
     488    const QRect itemPixmapRect = pModel->data(index, UISelectorModel::R_ItemPixmapRect).toRect();
     489    const QPixmap itemPixmap = pModel->data(index, UISelectorModel::R_ItemPixmap).value<QPixmap>();
     490    pPainter->save();
     491    pPainter->translate(itemRectangle.topLeft());
     492    pPainter->drawPixmap(itemPixmapRect, itemPixmap);
     493    pPainter->restore();
     494
     495    /* Draw name: */
     496    const QColor foreground = suitableForegroundColor(palette, backColor);
     497    const QFont font = pModel->data(index, Qt::FontRole).value<QFont>();
     498    const QPoint namePoint = pModel->data(index, UISelectorModel::R_ItemNamePoint).toPoint();
     499    const QString strName = pModel->data(index, UISelectorModel::R_ItemName).toString();
     500    pPainter->save();
     501    pPainter->translate(itemRectangle.topLeft());
     502    pPainter->setPen(foreground);
     503    pPainter->setFont(font);
     504    pPainter->drawText(namePoint, strName);
     505    pPainter->restore();
     506}
     507
     508
     509/*********************************************************************************************************************************
     510*   Class UISelectorModel implementation.                                                                                        *
     511*********************************************************************************************************************************/
     512
     513UISelectorModel::UISelectorModel(QITreeView *pParentTree)
     514    : QAbstractItemModel(pParentTree)
     515    , m_pParentTree(pParentTree)
     516    , m_pRootItem(new UISelectorTreeViewItem(pParentTree))
     517{
     518}
     519
     520UISelectorModel::~UISelectorModel()
     521{
     522    delete m_pRootItem;
     523}
     524
     525int UISelectorModel::rowCount(const QModelIndex &parentIndex) const
     526{
     527    UISelectorTreeViewItem *pParentItem = indexToItem(parentIndex);
     528    return pParentItem ? pParentItem->childCount() : 1 /* root item */;
     529}
     530
     531int UISelectorModel::columnCount(const QModelIndex & /* parentIndex */) const
     532{
     533    return 1;
     534}
     535
     536QModelIndex UISelectorModel::parent(const QModelIndex &specifiedIndex) const
     537{
     538    if (!specifiedIndex.isValid())
     539        return QModelIndex();
     540
     541    UISelectorTreeViewItem *pItem = indexToItem(specifiedIndex);
     542    UISelectorTreeViewItem *pParentOfItem =
     543        pItem ? qobject_cast<UISelectorTreeViewItem*>(pItem->parentItem()) : 0;
     544    UISelectorTreeViewItem *pParentOfParent =
     545        pParentOfItem ? qobject_cast<UISelectorTreeViewItem*>(pParentOfItem->parentItem()) : 0;
     546    const int iParentPosition = pParentOfParent ? pParentOfParent->posOfChild(pParentOfItem) : 0;
     547
     548    return pParentOfItem ? createIndex(iParentPosition, 0, pParentOfItem) : QModelIndex();
     549}
     550
     551QModelIndex UISelectorModel::index(int iRow, int iColumn, const QModelIndex &parentIndex) const
     552{
     553    if (!hasIndex(iRow, iColumn, parentIndex))
     554        return QModelIndex();
     555
     556    UISelectorTreeViewItem *pItem = !parentIndex.isValid()
     557                                  ? m_pRootItem
     558                                  : indexToItem(parentIndex)->childItem(iRow);
     559
     560    return pItem ? createIndex(iRow, iColumn, pItem) : QModelIndex();
     561}
     562
     563QModelIndex UISelectorModel::root() const
     564{
     565    return index(0, 0);
     566}
     567
     568QVariant UISelectorModel::data(const QModelIndex &specifiedIndex, int iRole) const
     569{
     570    if (!specifiedIndex.isValid())
     571        return QVariant();
     572
     573    switch (iRole)
     574    {
     575        /* Basic Attributes: */
     576        case Qt::FontRole:
     577        {
     578            QFont font = m_pParentTree->font();
     579            font.setBold(true);
     580            return font;
     581        }
     582        case Qt::SizeHintRole:
     583        {
     584            const QFontMetrics fm(data(specifiedIndex, Qt::FontRole).value<QFont>());
     585            const int iMargin = data(specifiedIndex, R_Margin).toInt();
     586            const int iSpacing = data(specifiedIndex, R_Spacing).toInt();
     587            const int iIconSize = data(specifiedIndex, R_IconSize).toInt();
     588            const QString strName = data(specifiedIndex, R_ItemName).toString();
     589            const int iMinimumContentWidth = iIconSize /* icon width */
     590                                           + iSpacing
     591                                           + fm.horizontalAdvance(strName) /* name width */;
     592            const int iMinimumContentHeight = qMax(fm.height() /* font height */,
     593                                                   iIconSize /* icon height */);
     594            const int iMinimumWidth = iMinimumContentWidth + iMargin * 2;
     595            const int iMinimumHeight = iMinimumContentHeight + iMargin * 2;
     596            return QSize(iMinimumWidth, iMinimumHeight);
     597        }
     598
     599        /* Advanced Attributes: */
     600        case R_Margin:
     601        {
     602            return QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin) / 1.5;
     603        }
     604        case R_Spacing:
     605        {
     606            return QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing) * 2;
     607        }
     608        case R_IconSize:
     609        {
     610            return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * 1.5;
     611        }
     612        case R_ItemId:
     613        {
     614            if (UISelectorTreeViewItem *pItem = indexToItem(specifiedIndex))
     615                return pItem->id();
     616            return QUuid();
     617        }
     618        case R_ItemPixmap:
     619        {
     620            if (UISelectorTreeViewItem *pItem = indexToItem(specifiedIndex))
     621            {
     622                const QIcon icon = pItem->icon();
     623                const int iIconSize = data(specifiedIndex, R_IconSize).toInt();
     624                return icon.pixmap(m_pParentTree->windowHandle(), QSize(iIconSize, iIconSize));
     625            }
     626            return QPixmap();
     627        }
     628        case R_ItemPixmapRect:
     629        {
     630            const int iMargin = data(specifiedIndex, R_Margin).toInt();
     631            const int iWidth = data(specifiedIndex, R_IconSize).toInt();
     632            return QRect(iMargin, iMargin, iWidth, iWidth);
     633        }
     634        case R_ItemName:
     635        {
     636            if (UISelectorTreeViewItem *pItem = indexToItem(specifiedIndex))
     637                return pItem->text();
     638            return QString();
     639        }
     640        case R_ItemNamePoint:
     641        {
     642            const int iMargin = data(specifiedIndex, R_Margin).toInt();
     643            const int iSpacing = data(specifiedIndex, R_Spacing).toInt();
     644            const int iIconSize = data(specifiedIndex, R_IconSize).toInt();
     645            const QFontMetrics fm(data(specifiedIndex, Qt::FontRole).value<QFont>());
     646            const QSize sizeHint = data(specifiedIndex, Qt::SizeHintRole).toSize();
     647            return QPoint(iMargin + iIconSize + iSpacing,
     648                          sizeHint.height() / 2 + fm.ascent() / 2 - 1 /* base line */);
     649        }
     650
     651        default:
     652            break;
     653    }
     654
     655    return QVariant();
     656}
     657
     658bool UISelectorModel::setData(const QModelIndex &specifiedIndex, const QVariant &aValue, int iRole)
     659{
     660    if (!specifiedIndex.isValid())
     661        return QAbstractItemModel::setData(specifiedIndex, aValue, iRole);
     662
     663    switch (iRole)
     664    {
     665        /* Advanced Attributes: */
     666        case R_ItemName:
     667        {
     668            if (UISelectorTreeViewItem *pItem = indexToItem(specifiedIndex))
     669            {
     670                pItem->setText(aValue.toString());
     671                emit dataChanged(specifiedIndex, specifiedIndex);
     672                return true;
     673            }
     674            return false;
     675        }
     676
     677        default:
     678            break;
     679    }
     680
     681    return false;
     682}
     683
     684QModelIndex UISelectorModel::addItem(int iID, const QIcon &icon, const QString &strLink)
     685{
     686    beginInsertRows(root(), m_pRootItem->childCount(), m_pRootItem->childCount());
     687    new UISelectorTreeViewItem(m_pRootItem, iID, icon, strLink);
     688    endInsertRows();
     689    return index(m_pRootItem->childCount() - 1, 0, root());
     690}
     691
     692void UISelectorModel::delItem(int iID)
     693{
     694    if (UISelectorTreeViewItem *pItem = m_pRootItem->childItemById(iID))
     695    {
     696        const int iItemPosition = m_pRootItem->posOfChild(pItem);
     697        beginRemoveRows(root(), iItemPosition, iItemPosition);
     698        delete pItem;
     699        endRemoveRows();
     700    }
     701}
     702
     703QModelIndex UISelectorModel::findItem(int iID)
     704{
     705    UISelectorTreeViewItem *pItem = m_pRootItem->childItemById(iID);
     706    if (!pItem)
     707        return QModelIndex();
     708
     709    const int iItemPosition = m_pRootItem->posOfChild(pItem);
     710    return pItem ? createIndex(iItemPosition, 0, pItem) : QModelIndex();
     711}
     712
     713QModelIndex UISelectorModel::findItem(const QString &strLink)
     714{
     715    UISelectorTreeViewItem *pItem = m_pRootItem->childItemByLink(strLink);
     716    if (!pItem)
     717        return QModelIndex();
     718
     719    const int iItemPosition = m_pRootItem->posOfChild(pItem);
     720    return pItem ? createIndex(iItemPosition, 0, pItem) : QModelIndex();
     721}
     722
     723void UISelectorModel::sort(int /* iColumn */, Qt::SortOrder enmOrder)
     724{
     725    /* Prepare empty list for sorted items: */
     726    QList<UISelectorTreeViewItem*> sortedItems;
     727
     728    /* For each of items: */
     729    const int iItemCount = m_pRootItem->childCount();
     730    for (int iItemPos = 0; iItemPos < iItemCount; ++iItemPos)
     731    {
     732        /* Get iterated item/id: */
     733        UISelectorTreeViewItem *pItem = m_pRootItem->childItem(iItemPos);
     734        const int iID = pItem->id();
     735
     736        /* Gather suitable position in the list of sorted items: */
     737        int iInsertPosition = 0;
     738        for (; iInsertPosition < sortedItems.size(); ++iInsertPosition)
     739        {
     740            /* Get sorted item/id: */
     741            UISelectorTreeViewItem *pSortedItem = sortedItems.at(iInsertPosition);
     742            const int iSortedID = pSortedItem->id();
     743
     744            /* Apply sorting rule: */
     745            if (   ((enmOrder == Qt::AscendingOrder) && (iID < iSortedID))
     746                || ((enmOrder == Qt::DescendingOrder) && (iID > iSortedID)))
     747                break;
     748        }
     749
     750        /* Insert iterated item into sorted position: */
     751        sortedItems.insert(iInsertPosition, pItem);
     752    }
     753
     754    /* Update corresponding model-indexes: */
     755    m_pRootItem->setChildren(sortedItems);
     756    beginMoveRows(root(), 0, iItemCount - 1, root(), 0);
     757    endMoveRows();
     758}
     759
     760Qt::ItemFlags UISelectorModel::flags(const QModelIndex &specifiedIndex) const
     761{
     762    return !specifiedIndex.isValid() ? QAbstractItemModel::flags(specifiedIndex)
     763                                     : Qt::ItemIsEnabled | Qt::ItemIsSelectable;
     764}
     765
     766/* static */
     767UISelectorTreeViewItem *UISelectorModel::indexToItem(const QModelIndex &specifiedIndex)
     768{
     769    if (!specifiedIndex.isValid())
     770        return 0;
     771    return static_cast<UISelectorTreeViewItem*>(specifiedIndex.internalPointer());
     772}
     773
     774
     775/*********************************************************************************************************************************
     776*   Class UISelectorTreeView implementation.                                                                                     *
     777*********************************************************************************************************************************/
     778
     779UISelectorTreeView::UISelectorTreeView(QWidget *pParent)
     780    : QITreeView(pParent)
     781{
     782    prepare();
     783}
     784
     785QSize UISelectorTreeView::minimumSizeHint() const
     786{
     787    /* Sanity check: */
     788    UISelectorModel *pModel = qobject_cast<UISelectorModel*>(model());
     789    AssertPtrReturn(pModel, QITreeView::minimumSizeHint());
     790
     791    /* Calculate largest column width: */
     792    int iMaximumColumnWidth = 0;
     793    int iCumulativeColumnHeight = 0;
     794    for (int i = 0; i < pModel->rowCount(pModel->root()); ++i)
     795    {
     796        const QModelIndex iteratedIndex = pModel->index(i, 0, pModel->root());
     797        const QSize sizeHint = pModel->data(iteratedIndex, Qt::SizeHintRole).toSize();
     798        const int iHeightHint = sizeHint.height();
     799        iMaximumColumnWidth = qMax(iMaximumColumnWidth, sizeHint.width() + iHeightHint /* to get the fancy shape */);
     800        iCumulativeColumnHeight += iHeightHint;
     801    }
     802
     803    /* Return selector size-hint: */
     804    return QSize(iMaximumColumnWidth, iCumulativeColumnHeight);
     805}
     806
     807QSize UISelectorTreeView::sizeHint() const
     808{
     809    // WORKAROUND:
     810    // By default QTreeView uses own size-hint
     811    // which we don't like and want to ignore:
     812    return minimumSizeHint();
     813}
     814
     815void UISelectorTreeView::prepare()
     816{
     817    /* Configure tree-view: */
     818    setFrameShape(QFrame::NoFrame);
     819    viewport()->setAutoFillBackground(false);
     820    setContextMenuPolicy(Qt::PreventContextMenu);
     821    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     822    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     823    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
     824
     825    /* Prepare selector delegate: */
     826    UISelectorDelegate *pDelegate = new UISelectorDelegate(this);
     827    if (pDelegate)
     828        setItemDelegate(pDelegate);
     829}
     830
     831
     832/*********************************************************************************************************************************
    209833*   Class UISettingsSelector implementation.                                                                                     *
    210834*********************************************************************************************************************************/
     
    286910        }
    287911    return pResult;
     912}
     913
     914
     915/*********************************************************************************************************************************
     916*   Class UISettingsSelectorTreeView implementation.                                                                             *
     917*********************************************************************************************************************************/
     918
     919UISettingsSelectorTreeView::UISettingsSelectorTreeView(QWidget *pParent /* = 0 */)
     920    : UISettingsSelector(pParent)
     921    , m_pTreeView(0)
     922    , m_pModel(0)
     923{
     924    prepare();
     925}
     926
     927UISettingsSelectorTreeView::~UISettingsSelectorTreeView()
     928{
     929    cleanup();
     930}
     931
     932QWidget *UISettingsSelectorTreeView::widget() const
     933{
     934    return m_pTreeView;
     935}
     936
     937QWidget *UISettingsSelectorTreeView::addItem(const QString & /* strBigIcon */,
     938                                             const QString &strMediumIcon ,
     939                                             const QString & /* strSmallIcon */,
     940                                             int iID,
     941                                             const QString &strLink,
     942                                             UISettingsPage *pPage /* = 0 */,
     943                                             int iParentID /* = -1 */)
     944{
     945    QWidget *pResult = 0;
     946    if (pPage)
     947    {
     948        /* Adjust page a bit: */
     949        pPage->setContentsMargins(0, 0, 0, 0);
     950        if (pPage->layout())
     951            pPage->layout()->setContentsMargins(0, 0, 0, 0);
     952        pResult = pPage;
     953
     954        /* Add selector-item object: */
     955        const QIcon icon = UIIconPool::iconSet(strMediumIcon);
     956        UISelectorItem *pItem = new UISelectorItem(icon, iID, strLink, pPage, iParentID);
     957        if (pItem)
     958            m_list.append(pItem);
     959
     960        /* Add model-item: */
     961        m_pModel->addItem(iID, pItem->icon(), strLink);
     962    }
     963    return pResult;
     964}
     965
     966void UISettingsSelectorTreeView::setItemText(int iID, const QString &strText)
     967{
     968    /* Call to base-class: */
     969    UISettingsSelector::setItemText(iID, strText);
     970
     971    /* Look for the tree-view item to assign the text: */
     972    QModelIndex specifiedIndex = m_pModel->findItem(iID);
     973    if (specifiedIndex.isValid())
     974        m_pModel->setData(specifiedIndex, strText, UISelectorModel::R_ItemName);
     975}
     976
     977QString UISettingsSelectorTreeView::itemText(int iID) const
     978{
     979    QString strResult;
     980    if (UISelectorItem *pItem = findItem(iID))
     981        strResult = pItem->text();
     982    return strResult;
     983}
     984
     985int UISettingsSelectorTreeView::currentId() const
     986{
     987    int iID = -1;
     988    const QModelIndex currentIndex = m_pTreeView->currentIndex();
     989    if (currentIndex.isValid())
     990        iID = m_pModel->data(currentIndex, UISelectorModel::R_ItemId).toString().toInt();
     991    return iID;
     992}
     993
     994int UISettingsSelectorTreeView::linkToId(const QString &strLink) const
     995{
     996    int iID = -1;
     997    const QModelIndex specifiedIndex = m_pModel->findItem(strLink);
     998    if (specifiedIndex.isValid())
     999        iID = m_pModel->data(specifiedIndex, UISelectorModel::R_ItemId).toString().toInt();
     1000    return iID;
     1001}
     1002
     1003void UISettingsSelectorTreeView::selectById(int iID)
     1004{
     1005    const QModelIndex specifiedIndex = m_pModel->findItem(iID);
     1006    if (specifiedIndex.isValid())
     1007        m_pTreeView->setCurrentIndex(specifiedIndex);
     1008}
     1009
     1010void UISettingsSelectorTreeView::sltHandleCurrentChanged(const QModelIndex &currentIndex,
     1011                                                         const QModelIndex & /* previousIndex */)
     1012{
     1013    if (currentIndex.isValid())
     1014    {
     1015        const int iID = m_pModel->data(currentIndex, UISelectorModel::R_ItemId).toString().toInt();
     1016        Assert(iID >= 0);
     1017        emit sigCategoryChanged(iID);
     1018    }
     1019}
     1020
     1021void UISettingsSelectorTreeView::prepare()
     1022{
     1023    /* Prepare the tree-widget: */
     1024    m_pTreeView = new UISelectorTreeView(qobject_cast<QWidget*>(parent()));
     1025    if (m_pTreeView)
     1026    {
     1027        /* Prepare the model: */
     1028        m_pModel = new UISelectorModel(m_pTreeView);
     1029        if (m_pModel)
     1030        {
     1031            m_pTreeView->setModel(m_pModel);
     1032            m_pTreeView->setRootIndex(m_pModel->root());
     1033        }
     1034
     1035        /* Setup connections: */
     1036        connect(m_pTreeView, &QITreeView::currentItemChanged,
     1037                this, &UISettingsSelectorTreeView::sltHandleCurrentChanged);
     1038    }
     1039}
     1040
     1041void UISettingsSelectorTreeView::cleanup()
     1042{
     1043    /* Cleanup the model: */
     1044    delete m_pModel;
     1045    m_pModel = 0;
     1046    /* Cleanup the tree-view: */
     1047    delete m_pTreeView;
     1048    m_pTreeView = 0;
    2881049}
    2891050
     
    7311492
    7321493}
     1494
     1495
     1496#include "UISettingsSelector.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/UISettingsSelector.h

    r101389 r101417  
    4747class UISelectorActionItem;
    4848class UISelectorItem;
     49class UISelectorModel;
     50class UISelectorTreeView;
    4951class UISettingsPage;
    5052class QIToolBar;
     
    129131/** UISettingsSelector subclass providing settings dialog
    130132  * with the means to switch between settings pages.
    131   * This one represented as tree-widget. */
    132 class SHARED_LIBRARY_STUFF UISettingsSelectorTreeWidget : public UISettingsSelector
     133  * This one represented as tree-view. */
     134class SHARED_LIBRARY_STUFF UISettingsSelectorTreeView : public UISettingsSelector
    133135{
    134136    Q_OBJECT;
     
    137139
    138140    /** Constructs settings selector passing @a pParent to the base-class. */
    139     UISettingsSelectorTreeWidget(QWidget *pParent = 0);
     141    UISettingsSelectorTreeView(QWidget *pParent);
    140142    /** Destructs settings selector. */
    141     virtual ~UISettingsSelectorTreeWidget() RT_OVERRIDE;
     143    virtual ~UISettingsSelectorTreeView() RT_OVERRIDE;
    142144
    143145    /** Returns the widget selector operates on. */
     
    169171    virtual void selectById(int iID) RT_OVERRIDE;
    170172
    171     /** Performs selector polishing. */
    172     virtual void polish() RT_OVERRIDE;
    173 
    174173private slots:
    175174
    176175    /** Handles selector section change from @a pPrevItem to @a pItem. */
    177     void sltSettingsGroupChanged(QTreeWidgetItem *pItem, QTreeWidgetItem *pPrevItem);
     176    void sltHandleCurrentChanged(const QModelIndex &current, const QModelIndex &previous);
    178177
    179178private:
     
    181180    /** Prepares all. */
    182181    void prepare();
    183 
    184     /** Returns page path for passed @a strMatch. */
    185     QString pagePath(const QString &strMatch) const;
    186     /** Find item within the passed @a pView and @a iColumn matching @a strMatch. */
    187     QTreeWidgetItem *findItem(QTreeWidget *pView, const QString &strMatch, int iColumn) const;
    188     /** Performs @a iID to QString serialization. */
    189     QString idToString(int iID) const;
    190 
    191     /** Forges the full path for passed @a pItem. */
    192     static QString path(const QTreeWidgetItem *pItem);
    193 
    194     /** Holds the tree-widget instance. */
    195     QITreeWidget *m_pTreeWidget;
     182    /** Cleanups all. */
     183    void cleanup();
     184
     185    /** Holds the tree-view instance. */
     186    UISelectorTreeView *m_pTreeView;
     187    /** Holds the tree-view instance. */
     188    UISelectorModel    *m_pModel;
    196189};
    197190
     
    199192/** UISettingsSelector subclass providing settings dialog
    200193  * with the means to switch between settings pages.
    201   * This one represented as tool-bar. */
    202 class SHARED_LIBRARY_STUFF UISettingsSelectorToolBar : public UISettingsSelector
     194  * This one represented as tree-widget. */
     195class SHARED_LIBRARY_STUFF UISettingsSelectorTreeWidget : public UISettingsSelector
    203196{
    204197    Q_OBJECT;
     
    207200
    208201    /** Constructs settings selector passing @a pParent to the base-class. */
    209     UISettingsSelectorToolBar(QWidget *pParent = 0);
     202    UISettingsSelectorTreeWidget(QWidget *pParent = 0);
    210203    /** Destructs settings selector. */
    211     virtual ~UISettingsSelectorToolBar() RT_OVERRIDE;
     204    virtual ~UISettingsSelectorTreeWidget() RT_OVERRIDE;
    212205
    213206    /** Returns the widget selector operates on. */
     
    236229    virtual int linkToId(const QString &strLink) const RT_OVERRIDE;
    237230
     231    /** Make the section with @a iID current. */
     232    virtual void selectById(int iID) RT_OVERRIDE;
     233
     234    /** Performs selector polishing. */
     235    virtual void polish() RT_OVERRIDE;
     236
     237private slots:
     238
     239    /** Handles selector section change from @a pPrevItem to @a pItem. */
     240    void sltSettingsGroupChanged(QTreeWidgetItem *pItem, QTreeWidgetItem *pPrevItem);
     241
     242private:
     243
     244    /** Prepares all. */
     245    void prepare();
     246
     247    /** Returns page path for passed @a strMatch. */
     248    QString pagePath(const QString &strMatch) const;
     249    /** Find item within the passed @a pView and @a iColumn matching @a strMatch. */
     250    QTreeWidgetItem *findItem(QTreeWidget *pView, const QString &strMatch, int iColumn) const;
     251    /** Performs @a iID to QString serialization. */
     252    QString idToString(int iID) const;
     253
     254    /** Forges the full path for passed @a pItem. */
     255    static QString path(const QTreeWidgetItem *pItem);
     256
     257    /** Holds the tree-widget instance. */
     258    QITreeWidget *m_pTreeWidget;
     259};
     260
     261
     262/** UISettingsSelector subclass providing settings dialog
     263  * with the means to switch between settings pages.
     264  * This one represented as tool-bar. */
     265class SHARED_LIBRARY_STUFF UISettingsSelectorToolBar : public UISettingsSelector
     266{
     267    Q_OBJECT;
     268
     269public:
     270
     271    /** Constructs settings selector passing @a pParent to the base-class. */
     272    UISettingsSelectorToolBar(QWidget *pParent = 0);
     273    /** Destructs settings selector. */
     274    virtual ~UISettingsSelectorToolBar() RT_OVERRIDE;
     275
     276    /** Returns the widget selector operates on. */
     277    virtual QWidget *widget() const RT_OVERRIDE;
     278
     279    /** Adds a new selector item.
     280      * @param  strBigIcon     Brings the big icon reference.
     281      * @param  strMediumIcon  Brings the medium icon reference.
     282      * @param  strSmallIcon   Brings the small icon reference.
     283      * @param  iID            Brings the selector section ID.
     284      * @param  strLink        Brings the selector section link.
     285      * @param  pPage          Brings the selector section page reference.
     286      * @param  iParentID      Brings the parent section ID or -1 if there is no parent. */
     287    virtual QWidget *addItem(const QString &strBigIcon, const QString &strMediumIcon, const QString &strSmallIcon,
     288                             int iID, const QString &strLink, UISettingsPage *pPage = 0, int iParentID = -1) RT_OVERRIDE;
     289
     290    /** Defines the @a strText for section with @a iID. */
     291    virtual void setItemText(int iID, const QString &strText) RT_OVERRIDE;
     292    /** Returns the text for section with @a iID. */
     293    virtual QString itemText(int iID) const RT_OVERRIDE;
     294
     295    /** Returns the current selector ID. */
     296    virtual int currentId() const RT_OVERRIDE;
     297
     298    /** Returns the section ID for passed @a strLink. */
     299    virtual int linkToId(const QString &strLink) const RT_OVERRIDE;
     300
    238301    /** Returns the section page for passed @a iID. */
    239302    virtual QWidget *idToPage(int iID) const RT_OVERRIDE;
Note: See TracChangeset for help on using the changeset viewer.

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