QTableView drag and drop crashing program
-
I've created a minimal QTableView example using QAbstractTableModel with drag and drop.
It works fine except that dragging a selection to the area surrounding the table crashes the program:

Any idea of why this is happening?
I list my implementation of
QAbstractTableModelbelow. The full project is at GitHub.#include "mainwindow.h" #include <QAbstractTableModel> #include <qabstractitemmodel.h> #include "tablemodel.h" using std::vector; QModelIndex TableModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED(parent); return createIndex(row, column); } QModelIndex TableModel::parent(const QModelIndex &child) const { Q_UNUSED(child); return QModelIndex(); } QVariant TableModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return dataList[index.row()][index.column()]; return QVariant(); } bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_UNUSED(role); dataList[index.row()][index.column()] = value; emit dataChanged(index, index); return true; } int TableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return dataList.size(); } int TableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 3; } Qt::ItemFlags TableModel::flags(const QModelIndex &index) const { Q_UNUSED(index); return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } Qt::DropActions TableModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } bool TableModel::insertRows(int row, int count, const QModelIndex &parent) { if (count > 0) { beginInsertRows(parent, row, row + count + 1); for (int i = 0; i != count; i++) dataList.emplace(dataList.begin() + row, columnCount()); endInsertRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } } bool TableModel::removeRows(int row, int count, const QModelIndex &parent) { if (count > 0) { beginRemoveRows(parent, row, row + count + 1); dataList.erase(dataList.begin() + row, dataList.begin() + row + count); endRemoveRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } } -
Hi
Good call with a runnable project. makes it more appealing to look into.It seems to crash in emplace as row is -1 when you drop outside the rows and
datalist.begin() -1 will then point to something invalid.
Also in the base class
void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
{
Q_ASSERT(first >= 0);which is also shown when run. ( as row is -1 so first is not > 0)
So it seems thats the issue. as
bool TableModel::insertRows(int row, int count, const QModelIndex &parent) { if (row < 0) return false; ////<<<<< skip if minus if (count > 0) { beginInsertRows(parent, row, row + count + 1); for (int i = 0; i != count; i++) dataList.emplace(dataList.begin() + row, columnCount()); endInsertRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } }makes it not crash when dragging there so i think you just need to handle that case and append it to your data list.
-
I've created a minimal QTableView example using QAbstractTableModel with drag and drop.
It works fine except that dragging a selection to the area surrounding the table crashes the program:

Any idea of why this is happening?
I list my implementation of
QAbstractTableModelbelow. The full project is at GitHub.#include "mainwindow.h" #include <QAbstractTableModel> #include <qabstractitemmodel.h> #include "tablemodel.h" using std::vector; QModelIndex TableModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED(parent); return createIndex(row, column); } QModelIndex TableModel::parent(const QModelIndex &child) const { Q_UNUSED(child); return QModelIndex(); } QVariant TableModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return dataList[index.row()][index.column()]; return QVariant(); } bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_UNUSED(role); dataList[index.row()][index.column()] = value; emit dataChanged(index, index); return true; } int TableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return dataList.size(); } int TableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 3; } Qt::ItemFlags TableModel::flags(const QModelIndex &index) const { Q_UNUSED(index); return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } Qt::DropActions TableModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } bool TableModel::insertRows(int row, int count, const QModelIndex &parent) { if (count > 0) { beginInsertRows(parent, row, row + count + 1); for (int i = 0; i != count; i++) dataList.emplace(dataList.begin() + row, columnCount()); endInsertRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } } bool TableModel::removeRows(int row, int count, const QModelIndex &parent) { if (count > 0) { beginRemoveRows(parent, row, row + count + 1); dataList.erase(dataList.begin() + row, dataList.begin() + row + count); endRemoveRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } } -
Hi
Good call with a runnable project. makes it more appealing to look into.It seems to crash in emplace as row is -1 when you drop outside the rows and
datalist.begin() -1 will then point to something invalid.
Also in the base class
void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
{
Q_ASSERT(first >= 0);which is also shown when run. ( as row is -1 so first is not > 0)
So it seems thats the issue. as
bool TableModel::insertRows(int row, int count, const QModelIndex &parent) { if (row < 0) return false; ////<<<<< skip if minus if (count > 0) { beginInsertRows(parent, row, row + count + 1); for (int i = 0; i != count; i++) dataList.emplace(dataList.begin() + row, columnCount()); endInsertRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } }makes it not crash when dragging there so i think you just need to handle that case and append it to your data list.
-
@mrjj said in QTableView drag and drop crashing program:
beginInsertRows(parent, row, row + count + 1);
This is wrong: https://doc.qt.io/qt-5/qabstractitemmodel.html#beginInsertRows
-
@JonB ,
It seems @mrjj figured it out, but to answer your question, I only see the information below. Perhaps there is a way to configure Qt Creator to show more but I haven't seen it (I am a newbie with it):12:34:28: Starting /Users/rodrigobraz/Documents/Qt Projects/build-tabledraganddrop-Desktop_Qt_5_15_2_clang_64bit-Debug/qtableviewdraganddrop.app/Contents/MacOS/qtableviewdraganddrop ... 12:34:32: The program has unexpectedly finished. 12:34:32: The process was ended forcefully. 12:34:32: /Users/rodrigobraz/Documents/Qt Projects/build-tabledraganddrop-Desktop_Qt_5_15_2_clang_64bit-Debug/qtableviewdraganddrop.app/Contents/MacOS/qtableviewdraganddrop crashed. -
@JonB ,
It seems @mrjj figured it out, but to answer your question, I only see the information below. Perhaps there is a way to configure Qt Creator to show more but I haven't seen it (I am a newbie with it):12:34:28: Starting /Users/rodrigobraz/Documents/Qt Projects/build-tabledraganddrop-Desktop_Qt_5_15_2_clang_64bit-Debug/qtableviewdraganddrop.app/Contents/MacOS/qtableviewdraganddrop ... 12:34:32: The program has unexpectedly finished. 12:34:32: The process was ended forcefully. 12:34:32: /Users/rodrigobraz/Documents/Qt Projects/build-tabledraganddrop-Desktop_Qt_5_15_2_clang_64bit-Debug/qtableviewdraganddrop.app/Contents/MacOS/qtableviewdraganddrop crashed. -
Hi
Good call with a runnable project. makes it more appealing to look into.It seems to crash in emplace as row is -1 when you drop outside the rows and
datalist.begin() -1 will then point to something invalid.
Also in the base class
void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
{
Q_ASSERT(first >= 0);which is also shown when run. ( as row is -1 so first is not > 0)
So it seems thats the issue. as
bool TableModel::insertRows(int row, int count, const QModelIndex &parent) { if (row < 0) return false; ////<<<<< skip if minus if (count > 0) { beginInsertRows(parent, row, row + count + 1); for (int i = 0; i != count; i++) dataList.emplace(dataList.begin() + row, columnCount()); endInsertRows(); emit dataChanged(index(row, 0), index(row + count - 1, columnCount())); emit layoutChanged(); return true; } else { return false; } }makes it not crash when dragging there so i think you just need to handle that case and append it to your data list.
@mrjj That's a great answer, thank you very much!
And of course I now see I could have debugged just like you did... lesson learned! :-)
-
@mrjj said in QTableView drag and drop crashing program:
beginInsertRows(parent, row, row + count + 1);
This is wrong: https://doc.qt.io/qt-5/qabstractitemmodel.html#beginInsertRows
@Christian-Ehrlicher Thank you, you're right! I had meant to type "-1".
-
@Rodrigo-B
For next time: you are supposed to run your code via Debug in Creator. Running under a debugger, it should stop when it crashed, and allow you to view where in your code the problem emanated.Great tip, thank you, @JonB!