[Solved] Invidual itemDelegate for each column of table\listview



  • Hi everybody
    I wonder if we can have a invidual itemDelegate for each column in table\listview?
    For example, text for ColumnA and comboBox for ColumnB
    Thanks :)


  • Moderators

    @illunara You can do it in TableViewColumn itself using delegate.



  • @p3c0 omg. Never think of that. Thank you very much ^_^



  • @p3c0 Sorry for dig this up again, but how can i get the modelIndex of item in column in treeview?

    With listview or tableview, i can get data from model with styleData.row, treeview has depth, which mean i will need a QModelIndex of parent to access data


  • Moderators

    @illunara styleData.value should get you the value from model. For Eg:

    TableViewColumn {
        title: "Title"
        role: "title"
        width: 320
        delegate: Rectangle {
            color: "#E5E4E2"
            Text {
                text: styleData.value
            }
        }
    }
    


  • Yeah, but sometime i want to get extra data from model, not just one data from column's role, since i create my own delegate for each column.

    Return a QList or QMap instead of one solid value in get() from model is a work-around, get a QModelIndex() is more straight ahead, i think


  • Moderators

    @illunara Try something similar to this. You already have the rows and columns.



  • You missing this const QModelIndex & parent = QModelIndex()

    index(int row, int column, const QModelIndex & parent = QModelIndex()) const

    The styleData.row in tableViewColumn return the row index of row RELATE to it parent.
    However i don't know which row is it parent.

    Because of that, if you don't set QModelIndex in treeview.index(), it might lead to an app crash ( And i did try it before)


  • Moderators

    @illunara Well ofcourse it is not the exact solution and hence I used the word "Similar". That solution was for TableView which doesn't require parent and it doesn't have parent-child like relationship.
    In case of TreeView you have to include the third parameter parent in index method which will then give you the exact child. But then finding the parent is again difficult IMO externally i.e from outside of TreeView. But you find it inside the TreeView. For eg.

    TreeView {
        anchors.fill: parent
        model: dataModel
        TableViewColumn {
            title: "Title"
            role: "title"
            width: 320
            delegate: Rectangle {
                color: "#E5E4E2"
                Text {
                    text: styleData.value
                }
    
                MouseArea {
                    anchors.fill: parent
                    onClicked: console.log(styleData.index, dataModel.parent(styleData.index))
                    //gives the index of child and parent of that child
                }
            }
        }
    }
    

    If you require it outside of TreeView may be you can try iterating thru parents and finding their children.



  • @p3c0 There is no property styleData.index of TableViewColumn ( In the document, and i run a test as well).


  • Moderators

    @illunara Yes there is inside delegate. Try the example that I posted before this post.



  • @p3c0 So you mean that qt docs is missing information about TableViewColumn?
    [http://doc.qt.io/qt-5/qml-qtquick-controls-tableviewcolumn.html#delegate-prop](link url)

    styleData.index only available in tableview, treeview, not TableViewColumn
    And i did try,

    QVariantMap TreeViewDataModel::get(QModelIndex index) {
        qDebug() << (static_cast<ModelAbstract*>(index.internalPointer()) == nullptr);
        return QVariantMap();
    }
    

    The output is true, which mean QModelIndex is not valid, i guess.


  • Moderators

    @illunara Here it is.

    styleData.index only available in tableview, treeview, not TableViewColumn

    Since it is available in tableview and treeview it is also available in TableViewColumn. Aren't you using TableViewColumn in TreeView ?
    What about this code ?

    MouseArea {
                    anchors.fill: parent
                    onClicked: console.log(styleData.index, dataModel.parent(styleData.index))
                    //gives the index of child and parent of that child
                }
    

    Didn't this work for you ?



  • @p3c0 I'm sorry about the late reply, thing is getting crazy here.
    Anyway about the code you posted. Yes, i tried, but its not working. The styleData in tableviewColumn is difference one from Treeview styleData. That's why, you can't use styleData of tableview to access data in Treeview.

    The internalPointer of QModelIndex() using styleData.index in tableviewColumn is nullpointer


  • Moderators

    @illunara Its time to post your code now :) I think something is missing. The code that I posted earlier for TableViewColumn in TreeView works perfectly for me with QAbstractItemModel.



  • @p3c0 I put the qml code in a gist since it quite long
    https://gist.github.com/illunara/2957ae5d7e41befc77fb

    Here is the Constructor for TreeviewModel, i put an item inside it

    TreeViewDataModel::TreeViewDataModel(QObject* parent ) : QAbstractItemModel(parent) {
    m_root = new Project();
    
    Project* project = new Project();
    project->m_name = "Hello World";
    project->setParent(m_root);
    m_root->appendChild(project);
    

    }

    And this is the function i call from QML

    QVariantMap TreeViewDataModel::get(QModelIndex index) {
    ModelAbstract* model = static_cast<ModelAbstract*>(index.internalPointer());
    qDebug() << model->getData("ItemType");
    return QVariantMap();
    

    }

    The result is

    QVariant(QString, "Project")
    QVariant(QString, "Project")
    

    This function got call twice, that's true ( because i have 2 items in treeview, one is the root, and other is the item i added) but result i wrong.
    And if i add one more item under root, this will crash.


  • Moderators

    @illunara Sorry but I'm unable to figure out what you are trying to do from the code.
    What do you expect it to print ? "Hello World" ?
    Why are you casting index it to model ? index.model() should be a better way to do.
    If you meant to cast it to an Projectobject and get its data it should be something like

    Project *item = static_cast<Project*>(index.internalPointer());
    return item->data(0).toString();
    

    Perhaps you should elaborate it more precisely.



  • @p3c0 Yup i think the output should be

    QVariant(QString, "Project")
    QVariant(QString, "Hello World")
    

    Oh and, Project is delivered class of ModelAbstract. Sorry, my fault

    class ModelAbstract {
    public:
         ModelAbstract();
    
         virtual QVariant    getData(QString dataname) const = 0;
    }
    
    class Project  : public ModelAbstract {
    public:
        virtual Variant    getData(QString dataname) const;
    }

  • Moderators

    @illunara So you mean getData should return a QVariantMap ? Is that the problem ? Can you post the definition of getData method ?



  • @p3c0 Sorry for confuse you, but just focus on this

     ModelAbstract* model = static_cast<ModelAbstract*>(index.internalPointer());
     qDebug() << model->getData("ItemType");
    

    What i meant here is, the index of styleData.value given in tableviewColumn is wrong. Since the output value is same one item.
    And here is the definition of getData(QString dataname)

    virtual QVariant    getData(QString dataname) const;
    QVariant    Project::getData(QString dataname) const {
    if(dataname == "ItemDisplayName") {
        QVariantMap returnData;
        returnData["ItemDisplayName"] = m_name;
        returnData["ItemType"] = m_type;
        return returnData;
    } else if(dataname == "ItemType")
        return "Project";
    else return QVariant();
    }
    

    I also have a Q_INVOKABLE getData(QString dataname) inside QAbstractItemModel class,


  • Moderators

    @illunara According to your earlier code:

    QVariantMap TreeViewDataModel::get(QModelIndex index) {
    ModelAbstract* model = static_cast<ModelAbstract*>(index.internalPointer());
    qDebug() << model->getData("ItemType");
    return QVariantMap();
    

    You are fetching data for "ItemType". And now the definition of getData:

    virtual QVariant    getData(QString dataname) const;
    QVariant    Project::getData(QString dataname) const {
    if(dataname == "ItemDisplayName") {
        QVariantMap returnData;
        returnData["ItemDisplayName"] = m_name;
        returnData["ItemType"] = m_type;
        return returnData;
    } else if(dataname == "ItemType")
        return "Project";
    else return QVariant();
    }
    

    Isn't it obvious that you will get "Project" always for "ItemType" ?



  • @p3c0 You are right, my horrible mistake. I think i drunk, should get home now :(
    I marked this topic as solved, should i some delete needless post too?


  • Moderators

    @illunara That's fine. No need to delete. It might confuse.


Log in to reply
 

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