Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Crash when assigning proxy model to ChartView, but not TableView
Forum Updated to NodeBB v4.3 + New Features

Crash when assigning proxy model to ChartView, but not TableView

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 2 Posters 2.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • YosemiteY Offline
    YosemiteY Offline
    Yosemite
    wrote on last edited by Yosemite
    #1

    I have a custom QAbstractTableModel and a proxy model which flips the axes of the first model. With the table this works, I just switch the model. When I switch to my proxy model for the chart it crashes at the point where I assign the rows to the QHXYModelMapper.

    This is the table model:

    #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();
    }
    
    //QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
    //{
    
    //}
    
    

    This is the proxy model implementation:

    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;
    }
    

    This is where I assign the model:

    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();
    }
    
    

    What have I screwed up? : /

    1 Reply Last reply
    0
    • YosemiteY Offline
      YosemiteY Offline
      Yosemite
      wrote on last edited by
      #2

      Some more info...

      Looking at the debugger, it seems that the index being created in the ProxyModel and passed to the original model is -1/-1 (invalid). Does line 9 in this debug output mean that the base class QAbstractProxyModel::data() is being called, instead of the one from my derived proxy model? If so, why?

      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 *)
      
      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        Your data function has the wrong signature. You're missing the role argument.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • YosemiteY Offline
          YosemiteY Offline
          Yosemite
          wrote on last edited by Yosemite
          #4

          So, after fixing that the crash happens at the same place. I confirmed that my proxy data() was returning the correct indexes from the original model as well. The QHXYModelMapper was simply asking for invalid indexes, beyond the number of columns in the model. The only way I was able to fix it, was calling the setColumnCount() method myself, like so:

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

          The docs seem to imply that the default value will use the total number of columns in the model:

          http://doc.qt.io/qt-5/qhxymodelmapper.html#columnCount-prop

          Maybe I misunderstand though?

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            From the doc, that sounds like the right conclusion.

            You should take a look at the bug report system to see if there's something related to this matter.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            1
            • YosemiteY Offline
              YosemiteY Offline
              Yosemite
              wrote on last edited by
              #6

              Okay, so I don't see anything in the Bug Tracker related to QHXYModelMapper. I'll open one (my first!). Before I do though, I'm wondering - would this be considered an issue with the documentation or the implementation?

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Might be both. I'd go with an implementation in this case but you can mention in the bug description that the documentation is not clear on that matter. If it's indeed a documentation issue it will be assigned to the documentation team.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1
                • YosemiteY Offline
                  YosemiteY Offline
                  Yosemite
                  wrote on last edited by
                  #8

                  For completeness, here is the bug:

                  https://bugreports.qt.io/browse/QTBUG-57342

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Thanks for the link !

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved