VirtualBox

Changeset 105059 in vbox


Ignore:
Timestamp:
Jun 27, 2024 12:50:28 PM (5 months ago)
Author:
vboxsync
Message:

FE/Qt: bugref:10681: UIShortcutConfigurationEditor: Replace old sorting/filtering stuff with sort-filtering model.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/settings/editors
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/editors/UIShortcutConfigurationEditor.cpp

    r105058 r105059  
    3030#include <QHeaderView>
    3131#include <QItemEditorFactory>
     32#include <QSortFilterProxyModel>
    3233#include <QTabWidget>
    3334#include <QVBoxLayout>
     
    184185
    185186
    186 /** Shortcut item sorting functor. */
    187 class UIShortcutItemSortingFunctor
    188 {
    189 public:
    190 
    191     /** Constructs shortcut item sorting functor.
    192       * @param  iColumn     Brings the column sorting should be done according to.
    193       * @param  m_enmOrder  Brings the sorting order to be applied. */
    194     UIShortcutItemSortingFunctor(int iColumn, Qt::SortOrder enmOrder)
    195         : m_iColumn(iColumn)
    196         , m_enmOrder(enmOrder)
    197     {}
    198 
    199     /** Returns whether the @a pItem1 is more/less than the @a pItem2.
    200       * @note  Order depends on the one set through constructor, stored in m_enmOrder. */
    201     bool operator()(UIShortcutTableViewRow *pItem1, UIShortcutTableViewRow *pItem2)
    202     {
    203         switch (m_iColumn)
    204         {
    205             case TableColumnIndex_Description:
    206                 return   m_enmOrder == Qt::AscendingOrder
    207                        ? pItem1->description() < pItem2->description()
    208                        : pItem1->description() > pItem2->description();
    209             case TableColumnIndex_Sequence:
    210                 return   m_enmOrder == Qt::AscendingOrder
    211                        ? pItem1->currentSequence() < pItem2->currentSequence()
    212                        : pItem1->currentSequence() > pItem2->currentSequence();
    213             default:
    214                 break;
    215         }
    216         return   m_enmOrder == Qt::AscendingOrder
    217                ? pItem1->key() < pItem2->key()
    218                : pItem1->key() > pItem2->key();
    219     }
    220 
    221 private:
    222 
    223     /** Holds the column sorting should be done according to. */
    224     int            m_iColumn;
    225     /** Holds the sorting order to be applied. */
    226     Qt::SortOrder  m_enmOrder;
    227 };
    228 
    229 
    230187/** QAbstractTableModel subclass representing shortcut configuration model. */
    231188class UIShortcutConfigurationModel : public QAbstractTableModel
     
    239196
    240197public:
     198
     199    /** Holds the data roles. */
     200    enum DataRoles
     201    {
     202        IsHostCombo = Qt::UserRole + 1,
     203    };
    241204
    242205    /** Constructs model passing @a pParent to the base-class.
     
    253216    /** Returns whether all shortcuts unique. */
    254217    bool isAllShortcutsUnique();
    255 
    256 public slots:
    257 
    258     /** Handle filtering @a strText change. */
    259     void sltHandleFilterTextChange(const QString &strText);
    260218
    261219protected:
     
    275233    virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole) RT_OVERRIDE;
    276234
    277     /** Sorts the model by @a iColumn in the given @a enmOrder. */
    278     virtual void sort(int iColumn, Qt::SortOrder enmOrder = Qt::AscendingOrder) RT_OVERRIDE;
    279 
    280235private:
    281236
     
    283238    QITableView *view() const;
    284239
    285     /** Applies filter. */
    286     void applyFilter();
    287 
    288240    /** Holds the parent shortcut-configuration editor instance. */
    289241    UIShortcutConfigurationEditor *m_pShortcutConfigurationEditor;
     
    292244    UIType  m_enmType;
    293245
    294     /** Holds current filter. */
    295     QString  m_strFilter;
    296 
    297246    /** Holds current shortcut list. */
    298247    UIShortcutTableViewContent  m_shortcuts;
    299     /** Holds current filtered shortcut list. */
    300     UIShortcutTableViewContent  m_filteredShortcuts;
    301248
    302249    /** Holds a set of currently duplicated sequences. */
    303250    QSet<QString>  m_duplicatedSequences;
     251};
     252
     253
     254/** QSortFilterProxyModel subclass representing shortcut configuration proxy-model. */
     255class UIShortcutConfigurationProxyModel : public QSortFilterProxyModel
     256{
     257    Q_OBJECT;
     258
     259public:
     260
     261    /** Constructs the shortcut configuration proxy-model passing @a pParent to the base-class. */
     262    UIShortcutConfigurationProxyModel(QObject *pParent = 0);
     263
     264public slots:
     265
     266    /** Defines model @a strFilter. */
     267    void setFilter(const QString &strFilter);
     268
     269protected:
     270
     271    /** Returns whether item in the row indicated by the given @a iSourceRow and @a srcParentIdx should be included in the model. */
     272    virtual bool filterAcceptsRow(int iSourceRow, const QModelIndex &srcParentIdx) const RT_OVERRIDE;
     273
     274    /** Returns whether value of the item @a srcIdxLeft is less than the value of the item @a srcIdxRight. */
     275    virtual bool lessThan(const QModelIndex &srcIdxLeft, const QModelIndex &srcIdxRight) const RT_OVERRIDE;
     276
     277private:
     278
     279    /** Holds the model filter. */
     280    QString  m_strFilter;
    304281};
    305282
     
    360337    qDeleteAll(m_shortcuts);
    361338    m_shortcuts.clear();
    362     m_filteredShortcuts.clear();
    363339}
    364340
    365341void UIShortcutConfigurationModel::load(const UIShortcutConfigurationList &list)
    366342{
     343    /* Erase rows first if necessary: */
     344    if (!m_shortcuts.isEmpty())
     345    {
     346        beginRemoveRows(QModelIndex(), 0, m_shortcuts.size() - 1);
     347        m_shortcuts.clear();
     348        endRemoveRows();
     349    }
     350
    367351    /* Load a list of passed shortcuts: */
    368352    foreach (const UIShortcutConfigurationItem &item, list)
     
    376360    }
    377361
    378     /* Apply filter: */
    379     applyFilter();
     362    /* Add rows finally if necessary: */
     363    if (!m_shortcuts.isEmpty())
     364    {
     365        beginInsertRows(QModelIndex(), 0, m_shortcuts.size() - 1);
     366        endInsertRows();
     367    }
    380368}
    381369
     
    430418}
    431419
    432 void UIShortcutConfigurationModel::sltHandleFilterTextChange(const QString &strText)
    433 {
    434     m_strFilter = strText;
    435     applyFilter();
    436 }
    437 
    438420int UIShortcutConfigurationModel::rowCount(const QModelIndex& /* parent = QModelIndex() */) const
    439421{
    440     return m_filteredShortcuts.size();
     422    return m_shortcuts.size();
    441423}
    442424
     
    508490                {
    509491                    /* Return shortcut scope and description: */
    510                     const QString strScope = m_filteredShortcuts.at(iIndex)->scope();
    511                     const QString strDescription = m_filteredShortcuts.at(iIndex)->description();
     492                    const QString strScope = m_shortcuts.at(iIndex)->scope();
     493                    const QString strDescription = m_shortcuts.at(iIndex)->description();
    512494                    return strScope.isNull() ? strDescription : QString("%1: %2").arg(strScope, strDescription);
    513495                }
     
    515497                {
    516498                    /* If that is host-combo cell: */
    517                     if (m_filteredShortcuts.at(iIndex)->key() == UIHostCombo::hostComboCacheKey())
     499                    if (m_shortcuts.at(iIndex)->key() == UIHostCombo::hostComboCacheKey())
    518500                        /* We should return host-combo: */
    519                         return UIHostCombo::toReadableString(m_filteredShortcuts.at(iIndex)->currentSequence());
     501                        return UIHostCombo::toReadableString(m_shortcuts.at(iIndex)->currentSequence());
    520502                    /* In other cases we should return hot-combo: */
    521                     QString strHotCombo = m_filteredShortcuts.at(iIndex)->currentSequence();
     503                    QString strHotCombo = m_shortcuts.at(iIndex)->currentSequence();
    522504                    /* But if that is machine table and hot-combo is not empty: */
    523505                    if (m_enmType == UIType_RuntimeUI && !strHotCombo.isEmpty())
     
    538520            {
    539521                case TableColumnIndex_Sequence:
    540                     return   m_filteredShortcuts.at(iIndex)->key() == UIHostCombo::hostComboCacheKey()
    541                            ? QVariant::fromValue(UIHostComboWrapper(m_filteredShortcuts.at(iIndex)->currentSequence()))
     522                    return   m_shortcuts.at(iIndex)->key() == UIHostCombo::hostComboCacheKey()
     523                           ? QVariant::fromValue(UIHostComboWrapper(m_shortcuts.at(iIndex)->currentSequence()))
    542524                           : QVariant::fromValue(UIHotKey(  m_enmType == UIType_RuntimeUI
    543525                                                          ? UIHotKeyType_Simple
    544526                                                          : UIHotKeyType_WithModifiers,
    545                                                           m_filteredShortcuts.at(iIndex)->currentSequence(),
    546                                                           m_filteredShortcuts.at(iIndex)->defaultSequence()));
     527                                                          m_shortcuts.at(iIndex)->currentSequence(),
     528                                                          m_shortcuts.at(iIndex)->defaultSequence()));
    547529                default:
    548530                    break;
     
    560542                case TableColumnIndex_Sequence:
    561543                {
    562                     if (   m_filteredShortcuts.at(iIndex)->key() != UIHostCombo::hostComboCacheKey()
    563                         && m_filteredShortcuts.at(iIndex)->currentSequence() != m_filteredShortcuts.at(iIndex)->defaultSequence())
     544                    if (   m_shortcuts.at(iIndex)->key() != UIHostCombo::hostComboCacheKey()
     545                        && m_shortcuts.at(iIndex)->currentSequence() != m_shortcuts.at(iIndex)->defaultSequence())
    564546                        font.setBold(true);
    565547                    break;
     
    577559                case TableColumnIndex_Sequence:
    578560                {
    579                     if (m_duplicatedSequences.contains(m_filteredShortcuts.at(iIndex)->key()))
     561                    if (m_duplicatedSequences.contains(m_shortcuts.at(iIndex)->key()))
    580562                        return QBrush(Qt::red);
    581563                    break;
     
    585567            /* Default for other cases: */
    586568            return QString();
     569        }
     570        case IsHostCombo:
     571        {
     572            return m_shortcuts.at(iIndex)->key() == UIHostCombo::hostComboCacheKey();
    587573        }
    588574        default: break;
     
    610596                    const int iIndex = index.row();
    611597                    /* Set sequence to shortcut: */
    612                     UIShortcutTableViewRow *pFilteredShortcut = m_filteredShortcuts.at(iIndex);
     598                    UIShortcutTableViewRow *pFilteredShortcut = m_shortcuts.at(iIndex);
    613599                    const int iShortcutIndex = UIShortcutSearchFunctor<UIShortcutTableViewRow>()(m_shortcuts, pFilteredShortcut);
    614600                    if (iShortcutIndex != -1)
     
    634620}
    635621
    636 void UIShortcutConfigurationModel::sort(int iColumn, Qt::SortOrder order /* = Qt::AscendingOrder */)
    637 {
    638     /* Sort whole the list: */
    639     std::stable_sort(m_filteredShortcuts.begin(), m_filteredShortcuts.end(), UIShortcutItemSortingFunctor(iColumn, order));
    640     /* Make sure host-combo item is always the first one: */
    641     UIShortcutConfigurationItem fakeHostComboItem(UIHostCombo::hostComboCacheKey(), QString(), QString(), QString(), QString());
    642     UIShortcutTableViewRow fakeHostComboTableViewRow(0, fakeHostComboItem);
    643     const int iIndexOfHostComboItem = UIShortcutSearchFunctor<UIShortcutTableViewRow>()(m_filteredShortcuts, fakeHostComboTableViewRow);
    644     if (iIndexOfHostComboItem != -1)
    645     {
    646         UIShortcutTableViewRow *pHostComboItem = m_filteredShortcuts.takeAt(iIndexOfHostComboItem);
    647         m_filteredShortcuts.prepend(pHostComboItem);
    648     }
    649     /* Notify the model: */
    650     emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
    651 }
    652 
    653622QITableView *UIShortcutConfigurationModel::view() const
    654623{
     
    661630}
    662631
    663 void UIShortcutConfigurationModel::applyFilter()
    664 {
    665     /* Erase rows first if necessary: */
    666     if (!m_filteredShortcuts.isEmpty())
    667     {
    668         beginRemoveRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1);
    669         m_filteredShortcuts.clear();
    670         endRemoveRows();
    671     }
    672 
    673     /* If filter is empty: */
    674     if (m_strFilter.isEmpty())
    675     {
    676         /* Just add all the rows: */
    677         m_filteredShortcuts = m_shortcuts;
    678     }
    679     else
    680     {
    681         /* Check if the description matches the filter: */
    682         foreach (UIShortcutTableViewRow *pRow, m_shortcuts)
    683         {
    684             /* If neither scope nor description or sequence matches the filter, skip the pRow: */
    685             if (   !pRow->scope().contains(m_strFilter, Qt::CaseInsensitive)
    686                 && !pRow->description().contains(m_strFilter, Qt::CaseInsensitive)
    687                 && !pRow->currentSequence().contains(m_strFilter, Qt::CaseInsensitive))
    688                 continue;
    689             /* Add that pRow: */
    690             m_filteredShortcuts << pRow;
    691         }
    692     }
    693 
    694     /* Add rows finally if necessary: */
    695     if (!m_filteredShortcuts.isEmpty())
    696     {
    697         beginInsertRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1);
    698         endInsertRows();
    699     }
     632
     633/*********************************************************************************************************************************
     634*   Class UIShortcutConfigurationProxyModel implementation.                                                                      *
     635*********************************************************************************************************************************/
     636
     637UIShortcutConfigurationProxyModel::UIShortcutConfigurationProxyModel(QObject *pParent /* = 0 */)
     638    : QSortFilterProxyModel(pParent)
     639{
     640}
     641
     642void UIShortcutConfigurationProxyModel::setFilter(const QString &strFilter)
     643{
     644    m_strFilter = strFilter;
     645    invalidate();
     646}
     647
     648bool UIShortcutConfigurationProxyModel::filterAcceptsRow(int iSourceRow, const QModelIndex &srcIdxParent) const
     649{
     650    /* Acquire child index of source model: */
     651    QModelIndex srcIdxChild = sourceModel()->index(iSourceRow, 0, srcIdxParent);
     652    if (srcIdxChild.isValid())
     653    {
     654        /* Perform QString case-insensitive filtering, default Qt::DisplayRole is Ok: */
     655        if (!sourceModel()->data(srcIdxChild).toString().contains(m_strFilter, Qt::CaseInsensitive))
     656            return false;
     657    }
     658    /* Everything else is allowed: */
     659    return true;
     660}
     661
     662bool UIShortcutConfigurationProxyModel::lessThan(const QModelIndex &srcIdxLeft, const QModelIndex &srcIdxRight) const
     663{
     664    /* Check if left or right index contains the Host-combo shortcut: */
     665    if (sourceModel()->data(srcIdxLeft, UIShortcutConfigurationModel::IsHostCombo).toBool())
     666        return true;
     667    else if (sourceModel()->data(srcIdxRight, UIShortcutConfigurationModel::IsHostCombo).toBool())
     668        return false;
     669
     670    /* Perform QString case-insensitive comparition otherwise: */
     671    return QString::compare(sourceModel()->data(srcIdxLeft).toString(),
     672                            sourceModel()->data(srcIdxRight).toString(),
     673                            Qt::CaseInsensitive) < 0;
    700674}
    701675
     
    814788    , m_pModelManager(0)
    815789    , m_pModelRuntime(0)
     790    , m_pProxyModelManager(0)
     791    , m_pProxyModelRuntime(0)
    816792    , m_pTabWidget(0)
    817793    , m_pEditorFilterManager(0), m_pTableManager(0)
     
    930906            m_pModelManager = new UIShortcutConfigurationModel(this, UIType_ManagerUI);
    931907
     908            /* Prepare Manager UI proxy-model: */
     909            m_pProxyModelManager = new UIShortcutConfigurationProxyModel(this);
     910            if (m_pProxyModelManager)
     911                m_pProxyModelManager->setSourceModel(m_pModelManager);
     912
    932913            /* Prepare Manager UI table: */
    933914            m_pTableManager = new UIShortcutConfigurationView(pTabManager, "m_pTableManager");
    934915            if (m_pTableManager)
    935916            {
    936                 m_pTableManager->setModel(m_pModelManager);
     917                m_pTableManager->setModel(m_pProxyModelManager);
    937918                pLayoutManager->addWidget(m_pTableManager);
    938919            }
     
    967948            m_pModelRuntime = new UIShortcutConfigurationModel(this, UIType_RuntimeUI);
    968949
     950            /* Prepare Runtime UI proxy-model: */
     951            m_pProxyModelRuntime = new UIShortcutConfigurationProxyModel(this);
     952            if (m_pProxyModelRuntime)
     953                m_pProxyModelRuntime->setSourceModel(m_pModelRuntime);
     954
    969955            /* Create Runtime UI table: */
    970956            m_pTableRuntime = new UIShortcutConfigurationView(pTabMachine, "m_pTableRuntime");
    971957            if (m_pTableRuntime)
    972958            {
    973                 m_pTableRuntime->setModel(m_pModelRuntime);
     959                m_pTableRuntime->setModel(m_pProxyModelRuntime);
    974960                pLayoutMachine->addWidget(m_pTableRuntime);
    975961            }
     
    988974    /* Configure 'Manager UI' connections: */
    989975    connect(m_pEditorFilterManager, &QLineEdit::textChanged,
    990             m_pModelManager, &UIShortcutConfigurationModel::sltHandleFilterTextChange);
     976            m_pProxyModelManager, &UIShortcutConfigurationProxyModel::setFilter);
    991977    connect(m_pModelManager, &UIShortcutConfigurationModel::sigDataChanged,
    992978            this, &UIShortcutConfigurationEditor::sigValueChanged);
     
    994980    /* Configure 'Runtime UI' connections: */
    995981    connect(m_pEditorFilterRuntime, &QLineEdit::textChanged,
    996             m_pModelRuntime, &UIShortcutConfigurationModel::sltHandleFilterTextChange);
     982            m_pProxyModelRuntime, &UIShortcutConfigurationProxyModel::setFilter);
    997983    connect(m_pModelRuntime, &UIShortcutConfigurationModel::sigDataChanged,
    998984            this, &UIShortcutConfigurationEditor::sigValueChanged);
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/editors/UIShortcutConfigurationEditor.h

    r105056 r105059  
    4040class QITableView;
    4141class UIShortcutConfigurationModel;
     42class UIShortcutConfigurationProxyModel;
    4243
    4344/** Shortcut search functor template. */
     
    252253    UIShortcutConfigurationModel *m_pModelRuntime;
    253254
     255    /** Holds the proxy Manager UI shortcut configuration model instance. */
     256    UIShortcutConfigurationProxyModel *m_pProxyModelManager;
     257    /** Holds the proxy Runtime UI shortcut configuration model instance. */
     258    UIShortcutConfigurationProxyModel *m_pProxyModelRuntime;
     259
    254260    /** Holds the tab-widget instance. */
    255261    QTabWidget                   *m_pTabWidget;
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