Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-53750

crash while drag-and-drop if Qt::DecorationRole is used

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • P2: Important
    • None
    • 5.5.1
    • Widgets: Itemviews
    • None
    • Kubuntu 16.04 64-bit

    Description

      the following program works fine:

      main.cpp
      #include "listmodel.h"
      #include <QApplication>
      #include <QListView>
      #include <QMainWindow>
      
      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();}
      
      listmodel.h
      #ifndef LISTMODEL_H
      #define LISTMODEL_H
      
      #include <QtCore/QAbstractListModel>
      #include <QtCore/QStringList>
      
      class ListModel : public QAbstractListModel {
      Q_OBJECT
      public:
      	explicit ListModel(QObject *parent = 0);
      	QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
      	Qt::ItemFlags flags(const QModelIndex &index) const;
      	bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
      	bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
      	int rowCount(const QModelIndex &parent = QModelIndex()) const;
      	bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
      	Qt::DropActions supportedDropActions() const;
      private:
      	QStringList items;};
      
      #endif // LISTMODEL_H
      
      listmodel.cpp
      #include "listmodel.h"
      #include <QtWidgets/QApplication>
      #include <QtWidgets/QStyle>
      
      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;}
      

      but as soon as those two lines in ListModel::data() are uncommented, drag-and-dropping of the items starts crashing the app:

      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

      i'm using CMake:

      CMakeLists.txt
      CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
      PROJECT(crashtest)
      set(CMAKE_AUTOMOC ON)
      set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
      FIND_PACKAGE(Qt5Widgets REQUIRED)
      SET(crashtest_SOURCES main.cpp listmodel.cpp)
      ADD_EXECUTABLE(crashtest ${crashtest_SOURCES})
      QT5_USE_MODULES(crashtest Widgets)
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              mmutz Marc Mutz
              combiner combiner
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes