Search code examples
c++qtqtreeviewqstandarditemmodel

Can't get item from QTreeView by QModelIndex


I create a QTreeView in a window, and I want to get the text of selected items when double clicking them. I try to use the signal "doubleClicked(const QModelIndex &)" to get the index of selected item.

But when I received the signal and wanted to do something with the index passed in, I can't get the item properly.

I found the index passed in is something like that:

root

|...item1 (0, 0)

|...|...subItem1 (0, 0)

|...|...subitem2 (1, 0)

|...item2 (1, 0)

There are two (0, 0) and (1, 0) items??? EDIT: I got this result by

qDebug(QString::number(index.row()).toLatin1().data()); // row
qDebug(QString::number(index.column()).toLatin1().data()); // column

Here is my code, create QTreeView and QStandardItemModel:

mTree = new QTreeView(this);  // mTree is a class member
treeModel = new QStandardItemModel(); // also a class member

proxymodel = new MySortFilterProxyModel(); // for sorting
proxymodel->setSourceModel(treeModel);
mTree->setModel(proxymodel);

and a custom slot to receive the signal:

private slots:
    void getSelectedIP(const QModelIndex &);

connect signal and slot:

connect(mTree, SIGNAL(doubleClicked(const QModelIndex &)),
    this, SLOT(getSelectedIP(const QModelIndex &)));

implementation of the slot, and the program crashed in this code:

void HostTreeFrame::getSelectedIP(const QModelIndex &index)
{
    QStandardItem *selectedItem = treeModel->itemFromIndex(index);
    qDebug(QString::number(index.row()).toLatin1().data());
    qDebug(QString::number(index.column()).toLatin1().data());
    qDebug("1");
    QString selectedIPString = selectedItem->text(); // program crashed here, selectedItem == nullptr
    qDebug("2");
}

EDIT: The selectedItem is nullptr, that's why the program crashed, but why it is nullptr?


Solution

  • Consider the code...

    void HostTreeFrame::getSelectedIP(const QModelIndex &index)
    {
        QStandardItem *selectedItem = treeModel->itemFromIndex(index);
    

    The problem is that index is associated with the model being used by the view but that's the proxy model -- not the QStandardItemModel.

    You need to map the model index index to the correct model. So something like...

    void HostTreeFrame::getSelectedIP(const QModelIndex &index)
    {
        auto standard_item_model_index = proxymodel->mapToSource(index);
        QStandardItem *selectedItem = treeModel->itemFromIndex(standard_item_model_index);
    
        /*
         * Check selectedItem before dereferencing.
         */
        if (selectedItem) {
            ...
    

    The code above assumes proxymodel is a member of (or is directly visible to) HostTreeFrame.