#pragma once #include #include #include namespace qtmt { class MovableModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QAbstractItemModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged) Q_PROPERTY(bool synced READ synced NOTIFY syncedChanged) public: explicit MovableModel(QObject* parent = nullptr); void setSourceModel(QAbstractItemModel *sourceModel); QAbstractItemModel* sourceModel() const; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role) const override; QHash roleNames() const override; Q_INVOKABLE void desyncOrder(); Q_INVOKABLE void syncOrder(); Q_INVOKABLE void move(int from, int to, int count = 1); Q_INVOKABLE QVector order() const; bool synced() const; signals: void sourceModelChanged(); void syncedChanged(); protected slots: #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) void resetInternalData() override; #else void resetInternalData(); #endif private: // source signals handling for synced state void syncedSourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles); void sourceLayoutAboutToBeChanged(const QList& parents, QAbstractItemModel::LayoutChangeHint hint); void sourceLayoutChanged(const QList& parents, QAbstractItemModel::LayoutChangeHint hint); // source signals handling for desynced state void desyncedSourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles); void sourceRowsInserted(const QModelIndex &parent, int first, int last); void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); // other void connectSignalsForSyncedState(); void syncOrderInternal(); QPointer m_sourceModel; bool m_synced = true; std::vector m_indexes; // helpers for handling layoutChanged from source when synced QList m_layoutChangePersistentIndexes; QModelIndexList m_proxyIndexes; }; } // namespace qtmt