PDA

View Full Version : Application crashed when QSortFilterProxyModel is used for QTableview sorting



polluxus
14th October 2015, 15:02
I am using QTableview + QAbastractTableModel subclass to display order trading data. It works great. But when I use QSortFilterProxyModel for table sorting/filtering, the application crashes if I sort the rows and then add new data row. Sometimes, even a click in the table would result in a crash. I have not changed any codes in the Model . The following are the codes related. Please kindly help.

VIEW:

pTableView = new QTableView();
pModel = new TradeManagerModel(0);
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(pModel);
proxyModel->setDynamicSortFilter(true);
pTableView->setModel(proxyModel);
pTableView->setSortingEnabled(true);

MODEL: The data is stored in QMap<QString, QStringList> mGridData.

int TradeManagerModel::rowCount(const QModelIndex & /*parent*/) const
{
return mGridData.size();
}

int TradeManagerModel::columnCount(const QModelIndex & /*parent*/) const
{
return 10;
}

QVariant TradeManagerModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
return mGridData[mGridData.keys().at(index.row())].at(index.column());
}
return QVariant();
}

QVariant TradeManagerModel::headerData(int section, Qt::Orientation orientation, int role) const
{

if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal) {
switch (section)
{
case 0:
return QString("TIME");
case 1:
return QString("SYMBOL");
case 2:
return QString("B/S");
case 3:
return QString("QTY");
case 4:
return QString("PRICE");
case 5:
return QString("COMM");
case 6:
return QString("STRATEGYID");
case 7:
return QString("EXECID");
case 8:
return QString("ORDERID");
case 9:
return QString("");
}
}
}
return QVariant();
}

void TradeManagerModel::onTradeItemUpdated(const TradeItem &tradeItem)
{
QString execId = tradeItem.execId;

QStringList tmpStrList;
tmpStrList << tradeItem.tradeTimeStamp
<< tradeItem.symbol
<< tradeItem.action
<< QString::number(tradeItem.fillQty)
<< QString::number(tradeItem.fillPrice)
<< QString::number(tradeItem.commission)
<< tradeItem.orderRef
<< execId
<< tradeItem.orderId
<<"";

if(!mGridData.contains(execId))
{
mGridData[execId] = tmpStrList;
emit layoutChanged();
}

}

d_stranz
14th October 2015, 15:11
Where do you check that the QModelIndex that is passed into any of your methods is valid? In particular, an invalid QModelIndex will have row = -1, col = -1, and I doubt if mGridData.keys().at( -1 ) will make the QMap very happy.

polluxus
15th October 2015, 01:29
Where do you check that the QModelIndex that is passed into any of your methods is valid? In particular, an invalid QModelIndex will have row = -1, col = -1, and I doubt if mGridData.keys().at( -1 ) will make the QMap very happy.

d_stranz, thanks for help.
I add debug as follow. But it turns out the app crashes without print the debug info. So it should be some other reason.



QVariant TradeManagerModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
if(index.row() < 0 || index.column() < 0) qDebug() << "QModelIndex index invalid";
return mGridData[mGridData.keys().at(index.row())].at(index.column());
}
return QVariant();
}

jefftee
15th October 2015, 04:55
Run using the debugger, look at stack trace after crash.

d_stranz
15th October 2015, 16:39
But it turns out the app crashes

Of course it crashes. You are still executing the code that probably causes the crash. Writing out a qDebug() message doesn't change the fact that you are probably using an invalid QModelIndex to access something from a map.

I do not know why the qDebug() message doesn't print - are you actually compiling and running the program in debug mode using the debugger? qDebug() does nothing in release mode. If you are running a debug program under the debugger, then possibly the crash is somewhere else.

As jefftee says, the only way to really know what causes the crash is to run your program in the debugger and either set a breakpoint in the data() method and examine the index manually to see what it contains, or let the program crash and examine the stack to see where the crash occurs.

polluxus
19th October 2015, 05:32
Thanks all for the help. This is the stack after crash:

0 ?? 0x7ffff661eae8
1 QSortFilterProxyModel::flags(QModelIndex const&) const 0x7ffff661ee26
2 QAbstractItemView::focusInEvent(QFocusEvent *) 0x7ffff790a601
3 QWidget::event(QEvent *) 0x7ffff76f2809
4 QFrame::event(QEvent *) 0x7ffff77ed39e
5 QAbstractScrollArea::event(QEvent *) 0x7ffff786fb03
6 QAbstractItemView::event(QEvent *) 0x7ffff7909c8b
7 QApplicationPrivate::notify_helper(QObject *, QEvent *) 0x7ffff76b14dc
8 QApplication::notify(QObject *, QEvent *) 0x7ffff76b6640
9 QCoreApplication::notifyInternal(QObject *, QEvent *) 0x7ffff66556a3
10 QApplicationPrivate::setFocusWidget(QWidget *, Qt::FocusReason) 0x7ffff76b3e7a
11 QWidget::setFocus(Qt::FocusReason) 0x7ffff76eca50
12 QApplication::setActiveWindow(QWidget *) 0x7ffff76b4392
13 QApplicationPrivate::notifyActiveWindowChange(QWin dow *) 0x7ffff76b44a3
14 QGuiApplicationPrivate::processActivatedEvent(QWin dowSystemInterfacePrivate::ActivatedWindowEvent *) 0x7ffff6e398e5
15 QGuiApplicationPrivate::processWindowSystemEvent(Q WindowSystemInterfacePrivate::WindowSystemEvent *) 0x7ffff6e39b6d
16 QWindowSystemInterface::sendWindowSystemEvents(QFl ags<QEventLoop::ProcessEventsFlag>) 0x7ffff6e1ec4f
17 ?? 0x7fffef470170
18 g_main_context_dispatch 0x7ffff4face04
19 ?? 0x7ffff4fad048
... <More>