Qt 5.15 - QSortFilterProxyModel与QAbstractTableModel崩溃的数据改变的信



我已经实现了一个自定义的QAbstractTableModel,我已经通过QAbstractItemModelTester运行它,并且在我的模型中没有更多的问题。然而,我现在正试图通过QSortFilterProxyModel实现排序,我似乎无法得到任何工作。

void RDMSensorModels::UpdateDevice(ArtNet::ArtRdmDevice* rdmDev, const RDM::RDMProcessor::RDMDeviceModel& model, int pid) {
if (s_RequiredPIDs.contains(pid)) {
for (int i = 0; i < m_RDMDevices.size(); i++) {
if (m_RDMDevices[i] == rdmDev) {
emit dataChanged(createIndex(i, 0), createIndex(i, columnCount() - 1));
return;
}
}
}
}

这是函数,它发出模型的datachchanged信号,我不认为这里有问题,但在发出这个信号后,程序在QSortFilterProxyModels内部的datachchanged处理程序内崩溃

因为我还不能在我的问题中嵌入图片,这里有一个链接到调试器在QSortFilterProxyModel中中断的地方

最奇怪的是,无论我传递什么给datachchanged信号,QSortFilterProxyModel中的proxy_columns总是空的。

你可以在调试器中看到,容器是空的

如果有任何帮助,这是我的QSortFilterProxyModel实现,它基本上是完全空的。

class RDMSensorSortFilterProxyModel final : public QSortFilterProxyModel {
enum SortValue {
MANUFACTUER_MODEL,
UNIVERSE_DMXADDRESS,
};
public:
RDMSensorSortFilterProxyModel(RDMSensorModels *sourceModel, QObject *parent = nullptr) : QSortFilterProxyModel(parent) {
setSourceModel(sourceModel);
}
int SortIndex();
void SetSortIndex(int value);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
private:
SortValue m_SortValue = MANUFACTUER_MODEL;
};
int RDMSensorSortFilterProxyModel::SortIndex() { return m_SortValue; }
void RDMSensorSortFilterProxyModel::SetSortIndex(int value) {
m_SortValue = static_cast<SortValue>(value);
invalidate();
}
bool RDMSensorSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { return true; }
bool RDMSensorSortFilterProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
auto leftDeviceManufacturer  = sourceModel()->data(left, RDMSensorModels::Roles::DeviceManufacturerRole).toString();
auto rightDeviceManufacturer = sourceModel()->data(right, RDMSensorModels::Roles::DeviceManufacturerRole).toString();
auto same = QString::compare(leftDeviceManufacturer, rightDeviceManufacturer, Qt::CaseInsensitive) == 0;
return same;
}

这里是我的QAbstractTableModel重新实现的函数

QVariant RDMSensorModels::headerData(int section, Qt::Orientation orientation, int role) const {
if (section < 1)
return QString("Device");
else
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 {};
}
}
QHash<int, QByteArray> RDMSensorModels::roleNames() const { return s_RoleNames; }

任何帮助都将非常感激!

事实证明,尝试在较小的规模上复制这个问题使我的大脑神经元足够活跃,我发现了问题所在。我的模型列计数可以改变,它确实改变了,但是,我没有写任何通知关于列计数改变beginRemoveColumns和endRemoveColumns和beginInsertColumns和endInsertColumns。我在代码中实现了这些,像这样

void RDMSensorModels::UpdateColumnCount() {
int sensorCount = 1;
for (auto device : m_RDMDevices) {
int deviceSensorCount = device->Sensors().size();
if (deviceSensorCount + 1 > sensorCount)
sensorCount = deviceSensorCount + 1; // +1 for device column
}
if (m_ColumnCount != sensorCount) {
if (m_ColumnCount < sensorCount) {
beginInsertColumns(QModelIndex(), m_ColumnCount, sensorCount - 1);
m_ColumnCount = sensorCount;
endInsertColumns();
} else {
beginRemoveColumns(QModelIndex(), sensorCount, m_ColumnCount - 1);
m_ColumnCount = sensorCount;
endRemoveColumns();
}
}
}

代理模型现在按预期工作。希望这能帮助任何有QSortFilterProxyModel问题的人。

值得注意的是,QAbstractItemModelTester并没有捕捉到这个问题,因为我的模型会根据当前发现的设备的最大传感器计数来更改列计数。

最新更新