Connect model to different views with different display roles



  • Hello,

    I created my own class derived from QAbstractItemModel for displaying data in a tree view. Additionally I used a qsortfilterproxymodel for sorting and filtering. Now I want to display parts of the data in a comboBox as well, but the display role must be different, as I want to show something else there. The source model should be the same for both widgets but of course I can create a new proxy model just for the comboBox. Can I somehow tell the comboBox or the proxymodel, that it should take another user defined role for displaying the data? I have already overwritten the roleNames method of my proxymodel, but without success. I even do not know if this would be the right approach. Furthermore, I want to show in the comboBox all the data of the top level nodes, but also of the children of the top level nodes (not the children of the children...). How to achieve that? The question is more general and therefore I do not think that it is necessary to post my code here. I would be very happy to get some hints.

    Thanks a lot.
    Daniel


  • Moderators

    @Dagginio said in Connect model to different views with different display roles:

    Can I somehow tell the comboBox or the proxymodel, that it should take another user defined role for displaying the data?

    subclass QIdentityProxyModel
    Then you can add a property to your custom proxymodel subclass to tell which Role to use instead of the source model's Qt::DisplayRole



  • @raven-worx
    Thanks for the fast reply. I think that helps already. Will try and let you know.

    Daniel



  • 
    class ComboProxy : public QIdentityProxyModel
    {
        Q_OBJECT
        Q_PROPERTY(int displayRole READ displayRole WRITE setDisplayRole NOTIFY displayRoleChanged)
        Q_DISABLE_COPY(ComboProxy)
    public:
        ComboProxy(QObject* parent = Q_NULLPTR)
            :QIdentityProxyModel(parent)
            , m_displayRole(Qt::DisplayRole)
        {}
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE{
            if (role == Qt::DisplayRole) role = m_displayRole;
            return QIdentityProxyModel::data(index, role);
        }
            // The next two are to only display top level and 1st generation children
        bool hasChildren(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE{
            if (parent.parent().parent().isValid()) return false;
            return QIdentityProxyModel::hasChildren(parent);
        }
        int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE{
            if (parent.parent().parent().isValid()) return 0;
            return QIdentityProxyModel::hasChildren(parent);
        }
        int displayRole() const { return m_displayRole; }
        Q_SIGNAL void displayRoleChanged(int role);
        void setDisplayRole(int role)
        {
            if (role == m_displayRole) return;
            m_displayRole = role;
            displayRoleChanged(role);
            emitAllDataChanged();
        }
    private:
        void emitAllDataChanged(const QModelIndex& parent = QModelIndex())
        {
            const int rows = rowCount(parent);
            const int columns = columnCount(parent);
            dataChanged(index(0, 0, parent), index(rows - 1, columns - 1, parent), QVector<int>() << Qt::DisplayRole);
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < columns; ++j) {
                    const QModelIndex currIdx = index(i, j, parent);
                    if (hasChildren(currIdx))
                        emitAllDataChanged(currIdx);
                }
            }
        }
        int m_displayRole;
    };
    

    You'll then have to call QCombobox::setView to set a treeview.
    If, instead, you want the 1st generation child to be displayed in a list at the same level as top level items just put a KDescendantsProxyModel inbetween



  • @VRonin said in Connect model to different views with different display roles:

    KDescendantsProxyModel

    Hey,

    thanks a lot. Using another displayRole in the combo is working fine. However I am still stucking with the data of the top level's children. Since I am using PyQt, I think I cannot use KDE. The last update of PyKDE was in 2013 and I do not find an appropriate wheel for installation. Is there another way with pure Qt (PyQt) components?

    Thanks
    Daniel


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.