3

In one of my projects on Qt, I have this requirement of selecting multiple items from a folder like view (tree-view), and populate the selected items in another widget. To display available items for multi-selection, I'm using a QTreeView, and populating element hierarchy like the following

m_StandardModel = new QStandardItemModel ;
QStandardItem *rootNode = m_StandardModel->invisibleRootItem();

//defining a couple of items
QStandardItem *item1 =  new QStandardItem(tr("ITEM1"));
QStandardItem *item2 =  new QStandardItem(tr("ITEM2"));
QStandardItem *item3 =  new QStandardItem(tr("ITEM3"));
QStandardItem *item4 =  new QStandardItem(tr("ITEM4"));

rootNode->appendRow(item1 );
rootNode->appendRow(item2 );
rootNode->appendRow(item3 );
rootNode->appendRow(item4 );

 //register the model
ui->treeView->setModel(m_StandardModel);
ui->treeView->expandAll();

//enabling multiselection behaviour
QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);

Everything's fine till here. I'm able to display my items in tree-view and also able to multiselect items. The problem occurs when I'm trying to use these multiple selected items from tree view.

In my UI, I have connected a button's clicked() signal to my slot, which handles the iteration and manipulation of selected items. Here's the function that's being called:

//User selects a number of features listed on the left pane and clicks this button to  disable them
void MainWindow::on_pushButton_2_clicked()
{        
    QModelIndexList selectedItems =  ui->treeView->selectionModel()->selectedIndexes();

    QStringList items;

    foreach(QModelIndex index, selectedItems)
    {
        QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
        if(itemModel)
        {
            QStandardItem* item = itemModel->itemFromIndex(index);
            items<< item->data().toString();
        }
    }
}

Debugging till the function end is perfect. But as soon as I exit this function (shown above), I get a DEBUG ASSERTION !! like the following

HEAP[myprog.exe]: Invalid address specified to RtlValidateHeap( 00390000, 01946798 )

The call stack is showing that this assertion is reached because of destruction of local QModelIndexList that I've created in the function.

Following is the call stack at the time of debug assertion: enter image description here

Any idea, what I might be missing? I have tried a number of times, but yet unable to figure out the real problem. Is there a better way of doing what is being done here? I'm using QT 4.8.4, and am building/debugging my application in DEBUG configuration on Windows 7.

Manmohan Singh
  • 439
  • 1
  • 3
  • 15
  • 1
    Do you show complete `void MainWindow::on_pushButton_2_clicked()` function? How do you use items (QStringList)? Please show the complete code. – vahancho May 07 '14 at 09:35
  • @vahancho : The function void MainWindow::on_pushButton_2_clicked() is complete here. items is a QStringList, which i was using to see if i am getting correct values selected. I have simplified the actual logic here. Actually there is no assertion if i don't use QModelIndexList! It's only after I use it, the problem ocurs. – Manmohan Singh May 07 '14 at 10:19

1 Answers1

0

I tried your code in a Windows application and I don't see your behaviour, maybe you have extra code in other part of the program that generates that behaviour. The code I tested is the following (I only modified the way to get the data, ot get the display role item->data(Qt::DisplayRole).toString()):

The cpp file:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_StandardModel = new QStandardItemModel ;
    QStandardItem *rootNode = m_StandardModel->invisibleRootItem();

    //defining a couple of items
    QStandardItem *item1 =  new QStandardItem(tr("ITEM1"));
    QStandardItem *item2 =  new QStandardItem(tr("ITEM2"));
    QStandardItem *item3 =  new QStandardItem(tr("ITEM3"));
    QStandardItem *item4 =  new QStandardItem(tr("ITEM4"));

    rootNode->appendRow(item1 );
    rootNode->appendRow(item2 );
    rootNode->appendRow(item3 );
    rootNode->appendRow(item4 );

     //register the model
    ui->treeView->setModel(m_StandardModel);
    ui->treeView->expandAll();

    //enabling multiselection behaviour
    QItemSelectionModel *selectionModel= ui->treeView->selectionModel();
    ui->treeView->setSelectionMode(QAbstractItemView::MultiSelection);

    connect(ui->pushButton,     SIGNAL(clicked()),
            this,               SLOT(on_pushButton_clicked()) );
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked(){
    QModelIndexList selectedItems =  ui->treeView->selectionModel()->selectedIndexes();

       QStringList items;

       foreach(QModelIndex index, selectedItems)
       {
           QStandardItemModel* itemModel = dynamic_cast<QStandardItemModel*>(ui->treeView->model());
           if(itemModel)
           {
               QStandardItem* item = itemModel->itemFromIndex(index);
               items << item->data(Qt::DisplayRole).toString();
           }
       }
}


The header file:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QStandardItemModel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QStandardItemModel * m_StandardModel ;
};

#endif // MAINWINDOW_H

Maybe you can publish the hole source code to see the behaviour you are having.

Gasteizko
  • 208
  • 1
  • 9