#pragma once #include #include #include #include namespace chatterino { namespace util { template class SignalVectorModel : public QAbstractTableModel, pajlada::Signals::SignalHolder { public: SignalVectorModel(util::BaseSignalVector *vec, int columnCount, QObject *parent = nullptr) : QAbstractTableModel(parent) , _columnCount(columnCount) { this->managedConnect(vec->itemInserted, [this](auto args) { std::vector items; for (int i = 0; i < this->_columnCount; i++) { items.push_back(new QStandardItem()); } int row = this->prepareInsert(args.item, args.index, items); assert(row >= 0 && row <= this->rows.size()); // insert row this->beginInsertRows(QModelIndex(), row, row); this->rows.insert(this->rows.begin() + row, Row(items)); this->endInsertRows(); }); this->managedConnect(vec->itemRemoved, [this](auto args) { int row = this->prepareRemove(args.item, args.index); assert(row >= 0 && row <= this->rows.size()); // remove row this->beginRemoveRows(QModelIndex(), row, row); for (QStandardItem *item : this->rows[row].items) { delete item; } this->rows.erase(this->rows.begin() + row); this->endRemoveRows(); }); } virtual ~SignalVectorModel() { for (Row &row : this->rows) { for (QStandardItem *item : row.items) { delete item; } } } int rowCount(const QModelIndex &parent) const { return this->rows.size(); } int columnCount(const QModelIndex &parent) const { return this->_columnCount; } QVariant data(const QModelIndex &index, int role) const { int row = index.row(), column = index.column(); assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount); return rows[row].items[column]->data(role); } bool setData(const QModelIndex &index, const QVariant &value, int role) { this->rows[index.row()].items[index.column()]->setData(value, role); return true; } QStandardItem *getItem(int row, int column) { assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount); return rows[row][column]; } protected: virtual int prepareInsert(const TVectorItem &item, int index, std::vector &rowToAdd) = 0; virtual int prepareRemove(const TVectorItem &item, int index) = 0; private: struct Row { std::vector items; bool isCustomRow; Row(const std::vector _items, bool _isCustomRow = false) : items(_items) , isCustomRow(_isCustomRow) { } }; std::vector rows; int _columnCount; }; } // namespace util } // namespace chatterino