如果使用 Qt::DecorationRole,拖放时崩溃
crash while drag-and-drop if Qt::DecorationRole is used
以下实现工作正常:
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) {}
QVariant ListModel::data(const QModelIndex &index, int role) const {
QVariant result;
if (index.row() > -1 && index.row() < items.size()) {
if (role == Qt::DisplayRole || role == Qt::EditRole)
result = items.at(index.row());
// else if (role == Qt::DecorationRole)
// result = qApp->style()->standardIcon(QStyle::SP_DirIcon);
}
return result;}
Qt::ItemFlags ListModel::flags(const QModelIndex &index) const {
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
if (!index.isValid()) flags = flags | Qt::ItemIsDropEnabled;
return flags;}
bool ListModel::insertRows(int row, int count, const QModelIndex &parent) {
if (count < 1 || row < 0 || row > rowCount(parent))
return false;
beginInsertRows(QModelIndex(), row, row + count - 1);
for (int i = 0; i < count; ++i)
items.insert(row, QString());
endInsertRows();
return true;}
bool ListModel::removeRows(int row, int count, const QModelIndex &parent) {
if (count < 1 || row < 0 || (row + count) > rowCount(parent))
return false;
beginRemoveRows(QModelIndex(), row, row + count - 1);
for (int i = 0; i < count; ++i)
items.removeAt(row);
endRemoveRows();
return true;}
int ListModel::rowCount(const QModelIndex &parent) const {
if (parent.isValid()) return 0;
return items.count();}
bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role) {
const int indexRow = index.row();
if (indexRow > -1 && indexRow < items.count()) {
if (role == Qt::DisplayRole || role == Qt::EditRole) {
items.replace(indexRow, value.toString());
emit dataChanged(index, index, QVector<int>() << role);
return true;}}
return false;}
Qt::DropActions ListModel::supportedDropActions() const {
return Qt::MoveAction;}
但是一旦 data() 中的这两行取消注释,项目的拖放操作就会开始使应用程序崩溃:
0 __GI_raise /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.23.so 54 0x7ffff6400418
1 __GI_abort /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.23.so 89 0x7ffff640201a
2 __gnu_cxx::__verbose_terminate_handler() 0x7ffff6a3984d
3 ?? 0x7ffff6a376b6 4 std::terminate() 0x7ffff6a37701
5 __cxa_throw 0x7ffff6a37919 6 qBadAlloc() 0x7ffff6dba0e2
7 QAbstractItemModel::decodeData(int, int, QModelIndex const&,
QDataStream&) 0x7ffff6f5bb28
8 QAbstractListModel::dropMimeData(QMimeData const *, Qt::DropAction,
int, int, QModelIndex const&) 0x7ffff6f5c8af
9 QAbstractItemView::dropEvent(QDropEvent *) 0x7ffff7affc6c
这里有一个可以玩的小程序:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow *mainWindow = new QMainWindow;
QListView *listView = new QListView;
ListModel *listModel = new ListModel;
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
listView->setDragDropMode(QAbstractItemView::InternalMove);
listModel->insertRows(0, 3);
listModel->setData(listModel->index(0), "alpha", Qt::DisplayRole);
listModel->setData(listModel->index(1), "beta", Qt::DisplayRole);
listModel->setData(listModel->index(2), "gamma", Qt::DisplayRole);
listView->setModel(listModel);
mainWindow->setCentralWidget(listView);
mainWindow->show();
return app.exec();}
Kubuntu 16.04 64 位,Qt 5.5.1
在我从 Qt 安装程序安装 Qt 5.6.1 后,拖放停止导致程序崩溃。也许,来自 Ubuntu 个存储库的 Qt 包中存在错误。
以下实现工作正常:
ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) {}
QVariant ListModel::data(const QModelIndex &index, int role) const {
QVariant result;
if (index.row() > -1 && index.row() < items.size()) {
if (role == Qt::DisplayRole || role == Qt::EditRole)
result = items.at(index.row());
// else if (role == Qt::DecorationRole)
// result = qApp->style()->standardIcon(QStyle::SP_DirIcon);
}
return result;}
Qt::ItemFlags ListModel::flags(const QModelIndex &index) const {
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
if (!index.isValid()) flags = flags | Qt::ItemIsDropEnabled;
return flags;}
bool ListModel::insertRows(int row, int count, const QModelIndex &parent) {
if (count < 1 || row < 0 || row > rowCount(parent))
return false;
beginInsertRows(QModelIndex(), row, row + count - 1);
for (int i = 0; i < count; ++i)
items.insert(row, QString());
endInsertRows();
return true;}
bool ListModel::removeRows(int row, int count, const QModelIndex &parent) {
if (count < 1 || row < 0 || (row + count) > rowCount(parent))
return false;
beginRemoveRows(QModelIndex(), row, row + count - 1);
for (int i = 0; i < count; ++i)
items.removeAt(row);
endRemoveRows();
return true;}
int ListModel::rowCount(const QModelIndex &parent) const {
if (parent.isValid()) return 0;
return items.count();}
bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role) {
const int indexRow = index.row();
if (indexRow > -1 && indexRow < items.count()) {
if (role == Qt::DisplayRole || role == Qt::EditRole) {
items.replace(indexRow, value.toString());
emit dataChanged(index, index, QVector<int>() << role);
return true;}}
return false;}
Qt::DropActions ListModel::supportedDropActions() const {
return Qt::MoveAction;}
但是一旦 data() 中的这两行取消注释,项目的拖放操作就会开始使应用程序崩溃:
0 __GI_raise /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.23.so 54 0x7ffff6400418
1 __GI_abort /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.23.so 89 0x7ffff640201a
2 __gnu_cxx::__verbose_terminate_handler() 0x7ffff6a3984d
3 ?? 0x7ffff6a376b6 4 std::terminate() 0x7ffff6a37701
5 __cxa_throw 0x7ffff6a37919 6 qBadAlloc() 0x7ffff6dba0e2
7 QAbstractItemModel::decodeData(int, int, QModelIndex const&, QDataStream&) 0x7ffff6f5bb28
8 QAbstractListModel::dropMimeData(QMimeData const *, Qt::DropAction, int, int, QModelIndex const&) 0x7ffff6f5c8af
9 QAbstractItemView::dropEvent(QDropEvent *) 0x7ffff7affc6c
这里有一个可以玩的小程序:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow *mainWindow = new QMainWindow;
QListView *listView = new QListView;
ListModel *listModel = new ListModel;
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
listView->setDragDropMode(QAbstractItemView::InternalMove);
listModel->insertRows(0, 3);
listModel->setData(listModel->index(0), "alpha", Qt::DisplayRole);
listModel->setData(listModel->index(1), "beta", Qt::DisplayRole);
listModel->setData(listModel->index(2), "gamma", Qt::DisplayRole);
listView->setModel(listModel);
mainWindow->setCentralWidget(listView);
mainWindow->show();
return app.exec();}
Kubuntu 16.04 64 位,Qt 5.5.1
在我从 Qt 安装程序安装 Qt 5.6.1 后,拖放停止导致程序崩溃。也许,来自 Ubuntu 个存储库的 Qt 包中存在错误。