Мой Qt QAbstractProxyModel падает с ChartView, но не с TableView?

У меня есть пользовательский QAbstractTableModel и модель прокси, которая переворачивает оси первой модели. С таблицей это работает, я просто переключаю модель. Когда я переключаюсь на свою модель прокси для диаграммы, она падает в точке, где я назначаю строки в QHXYModelMapper. Что я облажался?

Это модель стола:

#include "tablemodel.h"

TableModel::TableModel(QObject *parent) :
    QAbstractTableModel(parent)
{

}

int TableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_data.count();
}

int TableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    if(m_data.count() < 1)
    {
        return 0;
    }
    return m_data[0].count();
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal) {
        if (section % 2 == 0)
            return "x";
        else
            return "y";
    } else {
        return QString("%1").arg(section + 1);
    }
}

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if (!role == Qt::DisplayRole)
    {
        return QVariant();
    }
    return m_data[index.row()].at(index.column());
}

bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        m_data[index.row()].replace(index.column(), value.toDouble());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

void TableModel::appendRow(QVector<double> row)
{
    emit layoutAboutToBeChanged();
    emit beginInsertRows(QModelIndex(), rowCount(), rowCount());

    m_data.append(row);

    emit endInsertRows();
    emit layoutChanged();
}

void TableModel::clear()
{
    for(int i = 0; i < m_data.count(); ++i)
    {
        m_data[i].clear();
    }
    m_data.clear();
}

Это реализация прокси:

HorizontalProxyModel::HorizontalProxyModel(QObject *parent) : QAbstractProxyModel(parent)
{
}

QModelIndex HorizontalProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (sourceModel()) {
        return sourceModel()->index(proxyIndex.column(), proxyIndex.row());
    } else {
        return QModelIndex();
    }
}

QModelIndex HorizontalProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    return index(sourceIndex.column(), sourceIndex.row());
}

QModelIndex HorizontalProxyModel::index(int row, int column, const QModelIndex &) const
{
    return createIndex(row, column, (void*) 0);
}

QModelIndex HorizontalProxyModel::parent(const QModelIndex &) const
{
    return QModelIndex();
}

int HorizontalProxyModel::rowCount(const QModelIndex &) const
{
    return sourceModel() ? sourceModel()->columnCount() : 0;
}

int HorizontalProxyModel::columnCount(const QModelIndex &) const
{
    return sourceModel() ? sourceModel()->rowCount() : 0;
}

QVariant HorizontalProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (!sourceModel()) { return QVariant(); }
    Qt::Orientation new_orientation = orientation == Qt::Horizontal ?
                Qt::Vertical : Qt::Horizontal;
    return sourceModel() ? sourceModel()->headerData(section, new_orientation, role) : 0;
}

QVariant HorizontalProxyModel::data(const QModelIndex &index) const
{
    qDebug() << "h model data";
    return sourceModel() ? sourceModel()->data(sourceModel()->index(index.column(), index.row())) : 0;
}

И вот где я назначаю модель:

void MainWindow::plot(QAbstractItemModel* m)
{
QChart* chart = new QChart;

qDebug() << m->rowCount() << " " << m->columnCount();

for(int row = 0; row < m->rowCount(); ++row)
{

    QLineSeries *series = new QLineSeries;
    QHXYModelMapper* mapper = new QHXYModelMapper;
    QString name = "Row " + QString::number(row);

    series->setName(name);
    mapper->setModel(m);
    mapper->setSeries(series);
    mapper->setXRow(row);  //crashes here if proxy model
    mapper->setYRow(row);

    chart->addSeries(series);

}
chart->createDefaultAxes();
QChart* oldChart = chartView->chart();
chartView->setChart(chart);
oldChart->deleteLater();
}

РЕДАКТИРОВАТЬ

Еще немного информации...

Глядя на отладчик, кажется, что индекс, создаваемый в ProxyModel и передаваемый исходной модели, равен -1/-1 (недействительно). Означает ли строка 9 в этом отладочном выводе, что вызывается базовый класс QAbstractProxyModel::data() вместо класса из моей производной прокси-модели? Если так, то почему?

1   __pthread_kill                                                                                 

    0x7fff91eaff06 
2   pthread_kill                                                                                       0x7fff907204ec 
3   abort                                                                                              0x7fff876cd6df 
4   qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&)                             0x100ac3e79    
5   QMessageLogger::fatal(const char *, ...) const                                                     0x100ac5847    
6   qt_assert_x(const char *, const char *, const char *, int)                                         0x100ac0682    
7   QList<QVector<double>>::operator[](int) const                               qlist.h            541 0x10000fced    
8   TableModel::data(QModelIndex const&, int) const                             tablemodel.cpp     46  0x10000f8f1    
9   QAbstractProxyModel::data(QModelIndex const&, int) const                                           0x100c4c28b    
10  QtCharts::QXYModelMapperPrivate::valueFromModel(QModelIndex)                                       0x10171dfb3    
11  QtCharts::QXYModelMapperPrivate::initializeXYFromModel()                                           0x10171d92f    
12  QtCharts::QHXYModelMapper::setYRow(int)                                                            0x101720bf4    
13  MainWindow::plot(QAbstractItemModel *)

UDPATE: FIX

Итак, исправление, которое я имею сейчас, это позвонить QHXYModelMapper::setColumnCount() вручную, вот так:

mapper->setModel(m);
mapper->setSeries(series);
mapper->setColumnCount(m->columnCount());
mapper->setXRow(row);
mapper->setYRow(row);

Документы, кажется, подразумевают, что значение по умолчанию будет использовать общее количество столбцов в модели, если я не установлю это явно:

http://doc.qt.io/qt-5/qhxymodelmapper.html

1 ответ

Решение

Обсудили это на форумах Qt немного, это похоже на ошибку, где значение по умолчанию для HXYModelMappercolumnCount свойство на самом деле не получить надлежащее columnCount от модели. Обходной путь должен позвонить setColumnCount себя и установите его на columnCount вашей модели.

mapper->setModel(m);
mapper->setSeries(series);
mapper->setColumnCount(m->columnCount());
mapper->setXRow(row);
mapper->setYRow(row);

Отчет об ошибке: https://bugreports.qt.io/browse/QTBUG-57342

Другие вопросы по тегам