Показаны сообщения с ярлыком Bug. Показать все сообщения
Показаны сообщения с ярлыком Bug. Показать все сообщения

четверг, 18 мая 2017 г.

Qt Bug QAbstractItemModel beginMoveRows Ru

При попытке создания древовидной иерархической модели на базе QAbstractItemModel для QTreeView, и создания кнопки "переместить элемент вниз", столкнулся с неприятным багом в moveRows (точнее - beginMoveRows).

Я получил ошибку:

 ASSERT: "!this->isEmpty()" in file ..\..\include/QtCore/../../src/corelib/tools/qstack.h

Но ведь никакого QStack явно не используется!

При попытке выяснить причину,  оказалось, что программа падает на вызове endMoveRows, если sourceRow < destinationChild. (Реализация "переместить вверх" была тривиальна, но "вниз"... )
Нашлись следующие чем-то похожие баги:
https://bugreports.qt.io/browse/QTBUG-6940
https://bugreports.qt.io/browse/QTBUG-24337

Решение:
Если sourceRow < destinationChild уже нельзя использовать beginMoveRows, и поэтому решением было использовать сигналы layoutAboutToBeChanged и layoutChanged. (Я генерировал их, передавая индексы, однако без параметров тоже всё работает отлично.)
Так же добавил проверку beginMoveRows на истинность для других ситуаций.

Code fragment: 

bool TreeModel::moveRows (const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) {
        ...
         if(sourceRow > destinationChild) {
        // See https://bugreports.qt.io/browse/QTBUG-6940
        if(!beginMoveRows(sourceParent, sourceRow, sourceRow+count-1, destinationParent, destinationChild))
            return false;
        // Действия с данными здесь
        endMoveRows();
        return true;
        }
        // Because Qt bug :(. with endMoveRows, indexes and qstack.
        if(sourceRow < destinationChild) {
            QList<QPersistentModelIndex> parents;
            parents << QPersistentModelIndex(sourceParent) << QPersistentModelIndex(destinationParent);
            emit layoutAboutToBeChanged(parents);
            // Действия с данными здесь
            emit layoutChanged(parents);
            return true;
       }
...
}

Qt Bug QAbstractItemModel beginMoveRows En

When trying to create a tree-based hierarchical model based on QAbstractItemModel for QTreeView, and creating the "move item down" button (in one level), I encountered an unpleasant bug in moveRows (more precisely - beginMoveRows).

I got the error:

 ASSERT: "!this->isEmpty()" in file ..\..\include/QtCore/../../src/corelib/tools/qstack.h

But I know, that no QStack used by me!

When trying to find out the reason, it turned out that the program crashes on calling endMoveRows, if sourceRow < destinationChild. (The implementation of "move up" was trivial, but "down" ...)

I see next similar (but other models) messages:
https://bugreports.qt.io/browse/QTBUG-6940
https://bugreports.qt.io/browse/QTBUG-24337

My solution:
If sourceRow <destinationChild can no longer use beginMoveRows, and so the solution was to use the layoutAboutToBeChanged and layoutChanged signals. (I emited them by passing indexes, but without parameters, everything also works fine.)

I also added a beginMoveRows check to the truth for other situations.

Code fragment: 

bool TreeModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) {
        ...
         if(sourceRow > destinationChild) {
        // See https://bugreports.qt.io/browse/QTBUG-6940
        if(!beginMoveRows(sourceParent, sourceRow, sourceRow+count-1, destinationParent, destinationChild))
            return false;
        // Do somethig with items here
        endMoveRows();
        return true;
        }
        // Because Qt bug :(. with endMoveRows, indexes and qstack.
        if(sourceRow < destinationChild) {
            QList<QPersistentModelIndex> parents;
            parents << QPersistentModelIndex(sourceParent) << QPersistentModelIndex(destinationParent);
            emit layoutAboutToBeChanged(parents);
            // Do somethig with items here
            emit layoutChanged(parents);
            return true;
       }
...
}

It would be great if someone tried to reproduce and wrote to the official bugtracker Qt Framework
https://bugreports.qt.io/.

P.S.
Please, sorry my English. It's not my native language, and I use translator.