diff --git a/src/maps.h b/src/maps.h --- a/src/maps.h +++ b/src/maps.h @@ -56,6 +56,7 @@ virtual int indexOfObject(QObject *object) const = 0; signals: + void aboutToBeAdded(int index); void added(int index); void aboutToBeRemoved(int index); void removed(int index); @@ -111,10 +112,17 @@ { Q_ASSERT(!m_data.contains(object->index())); - m_data.insert(object->index(), object); + int modelIndex = 0; + for (auto it = m_data.constBegin(); it != m_data.constEnd(); ++it) { + if (object->index() < it.key()) { + break; + } + modelIndex++; + } - const int modelIndex = m_data.keys().indexOf(object->index()); - Q_ASSERT(modelIndex >= 0); + emit aboutToBeAdded(modelIndex); + m_data.insert(object->index(), object); + Q_ASSERT(modelIndex == m_data.keys().indexOf(object->index())); emit added(modelIndex); } @@ -130,19 +138,14 @@ return; } - const bool isNew = !m_data.contains(info->index); - auto *obj = m_data.value(info->index, nullptr); if (!obj) { obj = new Type(parent); } obj->update(info); - m_data.insert(info->index, obj); - if (isNew) { - const int modelIndex = m_data.keys().indexOf(info->index); - Q_ASSERT(modelIndex >= 0); - emit added(modelIndex); + if (!m_data.contains(info->index)) { + insert(obj); } } diff --git a/src/pulseaudio.h b/src/pulseaudio.h --- a/src/pulseaudio.h +++ b/src/pulseaudio.h @@ -38,6 +38,7 @@ PulseObjectRole = Qt::UserRole + 1 }; + ~AbstractModel() override; QHash roleNames() const Q_DECL_FINAL; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_FINAL; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; diff --git a/src/pulseaudio.cpp b/src/pulseaudio.cpp --- a/src/pulseaudio.cpp +++ b/src/pulseaudio.cpp @@ -41,21 +41,28 @@ , m_map(map) { Context::instance()->ref(); - //deref context after we've deleted this object - //see https://bugs.kde.org/show_bug.cgi?id=371215 - connect(this, &QObject::destroyed, []() { - Context::instance()->unref(); - }); - connect(m_map, &MapBaseQObject::added, this, &AbstractModel::onDataAdded); + connect(m_map, &MapBaseQObject::aboutToBeAdded, this, [this](int index) { + beginInsertRows(QModelIndex(), index, index); + }); + connect(m_map, &MapBaseQObject::added, this, [this](int index) { + onDataAdded(index); + endInsertRows(); + }); connect(m_map, &MapBaseQObject::aboutToBeRemoved, this, [this](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(m_map, &MapBaseQObject::removed, this, [this](int index) { Q_UNUSED(index); endRemoveRows(); }); +} +AbstractModel::~AbstractModel() +{ + //deref context after we've deleted this object + //see https://bugs.kde.org/show_bug.cgi?id=371215 + Context::instance()->unref(); } QHash AbstractModel::roleNames() const @@ -70,16 +77,23 @@ int AbstractModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); + if (parent.isValid()) { + return 0; + } return m_map->count(); } QVariant AbstractModel::data(const QModelIndex &index, int role) const { + if (!hasIndex(index.row(), index.column())) { + return QVariant(); + } QObject *data = m_map->objectAt(index.row()); Q_ASSERT(data); if (role == PulseObjectRole) { return QVariant::fromValue(data); + } else if (role == Qt::DisplayRole) { + return static_cast(data)->properties().value(QStringLiteral("name")).toString(); } int property = m_objectProperties.value(role, -1); if (property == -1) { @@ -179,16 +193,14 @@ void AbstractModel::onDataAdded(int index) { - beginInsertRows(QModelIndex(), index, index); QObject *data = m_map->objectAt(index); const QMetaObject *mo = data->metaObject(); // We have all the data changed notify signals already stored auto keys = m_signalIndexToProperties.keys(); foreach (int index, keys) { QMetaMethod meth = mo->method(index); connect(data, meth, this, propertyChangedMetaMethod()); } - endInsertRows(); } QMetaMethod AbstractModel::propertyChangedMetaMethod() const