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

Qt 5.15 - QSortFilterProxyModel with QAbstractTableModel crashing on dataChanged signal



    • Type: Bug
    • Status: Closed
    • Priority: Not Evaluated
    • Resolution: Invalid
    • Affects Version/s: 5.15.0
    • Fix Version/s: None
    • Labels:
    • Environment:
      Windows 10
    • Platform/s:


      I have implemented a custom QAbstractTableModel and I have run it through the QAbstractItemModelTester and there are no more issues in my model. However, I am now trying to implement sorting through a QSortFilterProxyModel and It seems that emiting dataChanged crashes QSortFilterProxyModel.


      These are my implemented functions for QAbstractTableModel

      QVariant RDMSensorModels::headerData(int section, Qt::Orientation orientation, int role) const {
              if (section < 1)
                  return QString("Device");
                  return QString("Sensor %1").arg(section);
          int RDMSensorModels::rowCount(const QModelIndex& parent) const {
              if (parent.isValid())
                  return 0;
              return m_RDMDevices.count();
          int RDMSensorModels::columnCount(const QModelIndex& parent) const {
              if (parent.isValid())
                  return 0;
              return m_ColumnCount;
          QVariant RDMSensorModels::data(const QModelIndex& index, int role) const {
              if (!index.isValid())
                  return {};
              int deviceIndex = index.row();
              switch (role) {
                  case SensorGraphReadingsRole: {
                      auto& readings  = m_RDMDevices[deviceIndex]->Sensors()[index.column() - 1]->LastReadings();
                      auto maxElement = f_SensorMaxReading(index.row(), index.column() - 1);
                      auto minElement = f_SensorMinReading(index.row(), index.column() - 1);
                      QVariantList values;
                      for (int i = 0; i < readings.size(); i++) {
                          values.push_back(Utils::Math::map(readings[i], maxElement, minElement, 0, 1));
                      return values;
                  case SensorMinReadingRole: return f_SensorMinReading(deviceIndex, index.column() - 1);
                  case SensorMaxReadingRole: return f_SensorMaxReading(deviceIndex, index.column() - 1);
                  case DeviceUIDRole: return f_DeviceUIDString(deviceIndex);
                  case DeviceUniverseRole: return f_DeviceUniverseString(deviceIndex);
                  case DeviceLabelRole: return f_DeviceLabelString(deviceIndex);
                  case DeviceManufacturerRole: return f_DeviceManufacturerString(deviceIndex);
                  case DeviceModelRole: return f_DeviceModelString(deviceIndex);
                  case SensorRangeMaxValueRole: return f_SensorRangeMaxValueString(deviceIndex, index.column() - 1);
                  case SensorRangeMinValueRole: return f_SensorRangeMinValueString(deviceIndex, index.column() - 1);
                  case SensorCurrentValueRole: return f_SensorCurrentValueString(deviceIndex, index.column() - 1);
                  case SensorNameRole: return f_SensorNameString(deviceIndex, index.column() - 1);
                  case SensorCurrentValueNormalizedRole: return f_SensorCurrentValueNormalized(deviceIndex, index.column() - 1);
                  case SensorMinNormalValueNormalizedRole: return f_SensorMinNormalValueNormalized(deviceIndex, index.column() - 1);
                  case SensorMaxNormalValueNormalizedRole: return f_SensorMaxNormalValueNormalized(deviceIndex, index.column() - 1);
                  case SensorValidRole: {
                      auto sensorCount = f_DeviceSensorCount(deviceIndex);
                      return sensorCount && (index.column() <= sensorCount);
                  default: return {};


      Thise function adds items to the model

      void RDMSensorModels::Add(const ArtNet::ArtRdmDevice* rdmDevice) {
          if (!m_RDMDevices.contains(rdmDevice)) {
              beginInsertRows(QModelIndex(), rowCount(), rowCount());
              emit dataChanged(createIndex(0, 0), createIndex(0, columnCount() - 1));

      This was the way i tested this. The first row is added fine. The second time this function executes, It adds another row, emits dataChanged and crashes inside QSortFilterProxyModel. No data parsing is done, only the dataChanged signal is emited.


      This is the way im setting up the QSortFilterProxyModel, nothing else is done after this, only items added to the model

      s_RDMSensorProxyModel = new QSortFilterProxyModel();

      The crash happens at 

      The proxy_columns container is empty and is trying to be accessed at index 0.



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



            dfaure_kdab David Faure
            jesuskrists Krists Niedritis
            0 Vote for this issue
            0 Start watching this issue



                Gerrit Reviews

                There are no open Gerrit changes