QComboBox with custom Model



  • Hi,

    I want to store several information in a 2D Array like this:

    projects[
       [
          name: "Project Name1",
          path: "url to folder",
          ...
       ],
       [
          name: "Project Name2",
          path: "url to folder",
          ...
       ],
       [...]
    ]
    

    The information in the array is user input and will grow over time. I plan to store the array via QSettings and load them during the program start. On the first start of the program the array will be empty.
    To select an entire data set I plan display a QComboBox. I hoped that I can pass the project 2D array as model to a QComboBox and have the name values displayed. Is this feasible?

    I have been reading through the QAbstractModel documentation since I should be able to set a model to a QComboBox but I do not really understand how I should design the Model. Or is this a stupid approach?


  • Lifetime Qt Champion

    Hi,

    So basically you have a JSON structure from which you would only show e.g. the name fields in the QComboBox ?

    What will you do with the rest of the data ?



  • Hi,

    I choose the JSON style, I could be any other. I need the URL to set the root path in a treeView and some other standard folders. In the future I want to have the ability to add to that array in case I need more project specific settings.


  • Qt Champions 2016

    @Sikarjan
    Hi
    Model and views are almost always a better approach
    than something home grown. :)

    You could cheat a bit and use a predefined model class
    https://github.com/dridk/QJsonModel
    Give it a spin and see if it fits :)

    Json is a nice format as its so simple to handle.



  • @mrjj that looks like a very promising link. I will check that out.



  • Okay. I tried to use the QJsonModel as an example and to build my own model. The code is compiling but it crashes as soon as I try to append an item to the model. I guess I made several errors in implementing the class. Especially I did not understand the parent/child stuff.

    #ifndef PROJECTMODEL_H
    #define PROJECTMODEL_H
    
    #include <QAbstractTableModel>
    #include <QVector>
    
    class ProjectModel : public QAbstractTableModel {
        Q_OBJECT
    public:
        ProjectModel(QObject *parent = 0);
    
        bool add(QString name, QString url);
        QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
        QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
        int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
        int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    
    private:
        QVector<QStringList> *projects; // List: 0 => Project name, 1 => Root URL
        QStringList mHeaders;
    };
    
    #endif // PROJECTMODEL_H
    
    #include "projectmodel.h"
    
    ProjectModel::ProjectModel(QObject *parent) :
        QAbstractTableModel(parent) {
        projects = new QVector<QStringList>;
        mHeaders.append("Projects");
    }
    
    bool ProjectModel::add(QString name, QString url){
        QStringList newProject;
        newProject << name << url;
        projects->append(newProject);
        return true;
    }
    
    QVariant ProjectModel::data(const QModelIndex &index, int role) const{
        if (!index.isValid())
            return QVariant();
    
        if (role == Qt::DisplayRole) {
            return projects[index.row()][index.column()];
        }
    
        return QVariant();
    }
    
    QVariant ProjectModel::headerData(int section, Qt::Orientation orientation, int role) const {
        if (role != Qt::DisplayRole)
            return QVariant();
    
        if (orientation == Qt::Horizontal) {
            return mHeaders.value(section);
        }else{
            return QVariant();
        }
    }
    
    int ProjectModel::rowCount(const QModelIndex &parent) const {
        Q_UNUSED(parent);
        return projects->count();
    }
    
    int ProjectModel::columnCount(const QModelIndex &parent) const {
        return projects[parent.row()].count();
    }
    

    [Edit] Switched to QAbstractTableModel and removed index and parent function since I do not need them.


  • Qt Champions 2016

    Hi
    Did you read the docs?
    http://doc.qt.io/qt-5/qabstractitemmodel.html#details
    It explains how it fits together.

    I found models & views slightly confusing even after reading the docs but
    then i tried follow this example and it helped on the overview.
    http://www.informit.com/articles/article.aspx?p=1405547&seqNum=3



  • I have been reading the documentation a lot but this is to vague for me. I have also been looking through other examples and some videos but I still do not understand how this should work. From what I read I guess I need a QAbstractTableModel which only requires data header row and columnCount functions. I adjusted the code above but this still dies not work.

    I am not really sure if it can work at all. How does the QComboBox know that it should use only the first column?


  • Lifetime Qt Champion

    Because it's how it works. You can change the column used with the modelColumn property.


Log in to reply
 

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