LINUX.ORG.RU

При использовании QSortFilterProxyModel и QAbstractItemModel отваливается selectionChanged

 


0

1

Есть наследник QAbstractItemModel и QTreeView для отображения дерева. Все работает.

Добавляю наследника QSortFilterProxyModel с переопределенным методом filterAcceptsRow. Работает, но отваливается

connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::selectionChanged)
, а именно в методе selectionChanged:
    QModelIndex i = selected.indexes().at(0);
    MyCustomItem* a = static_cast<Item*>(i.internalPointer());
    a->value = "new value";
Т.е. в QModelIndex содержится не правильный указатель на мой объект.

Если удаляю из схемы наследника QSortFilterProxyModel, то все работает.

MyCustomItem* a = static_cast<Item*>(i.internalPointer());

Какой-то говнокод. Нельзя просто так взять и кастануть void* во что-то полезное и не замазаться в архитектурное дерьмо.

anonymous ()
Ответ на: комментарий от RazrFalcon

Вот этот вариант работает без проблем:

    ItemModel* m;
    m = new ItemModel(this);
    ui->treeView->setModel(m);

А вот здесь в selectionChanged приходит QModelIndex с непонятным указателем на данные:

    ItemModel* m;
    m = new ItemModel(this);
    ProxyItemModel* pm = new ProxyItemModel(this);
    pm->setSourceModel(m);
    ui->treeView->setModel(pm);

Класс прокси модели почти пустой:

class ProxyItemModel : public QSortFilterProxyModel
{
public:
    enum Filter {
        All,
        Requred,
    };
    explicit ProxyItemModel(QObject* p);

    // QSortFilterProxyModel interface
protected:
    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
};

Я вот думаю, если бы я накосячил в реализации класса ItemModel, то первый вариант тоже бы не работал.

plgrm44 ()
Ответ на: комментарий от anonymous

А я и не знал. Добавил это selected:

    ProxyItemModel* pm = static_cast<ProxyItemModel*>(ui->treeView->model());
    QItemSelection s = pm->mapSelectionToSource(selected);
Теперь в QModelIndex правильный указатель. Странно, а что тогда за адрес ходит в QModelIndex без этого преобразования?

plgrm44 ()
Ответ на: комментарий от plgrm44

а что тогда за адрес ходит в QModelIndex без этого преобразования?

Индекс в «системе координат» прокси модели. А тебе нужен индекс в «системе координат» оригинальной модели.

anonymous ()
Ответ на: комментарий от plgrm44

http://doc.qt.io/qt-5/qabstractitemmodel.html#createIndex
When using a QSortFilterProxyModel, its indexes have their own internal pointer. It is not advisable to access this internal pointer outside of the model. Use the data() function instead.

its indexes have their own internal pointer.

В общем какая-то своя требуха. Так что используй метод data.

ox55ff ★★★★ ()
Ответ на: комментарий от ox55ff

Я так понял, что, если используется QTreeView с QSortFilterProxyModel, то во всех слотах, где используется QModelIndex нужно будет следующее преобразование:

    const ProxyItemModel* proxyModel = static_cast<const ProxyItemModel*>(index.model());
    QModelIndex trueIndex = proxyModel->mapToSource(index);

метод data мне не подходит, потому что он возвращает строку, а не указатель на объект(Item*), хотя, наверно, можно для исходной модели для ItemDataRole::UserRole вовращать указатель на вершину...

plgrm44 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.