diff -r 6988973515d2 -r ca23936b455b src/model.h --- a/src/model.h Wed May 25 20:36:34 2022 +0300 +++ b/src/model.h Mon Jun 06 22:01:22 2022 +0300 @@ -20,120 +20,96 @@ #include #include #include "main.h" -#include "header.h" -#include "linetypes/object.h" -#include "linetypes/metacommand.h" -#include "gl/common.h" +#include "colors.h" + +struct SubfileReference +{ + QString name; + glm::mat4 transformation; + bool inverted = false; +}; + +template +struct Colored : T +{ + ldraw::Color color; +}; + +struct Comment +{ + QString text; +}; -enum class HeaderProperty +struct ParseError { - Name + QString code; }; +struct Empty {}; + +using ModelElement = std::variant< + Colored, + Colored, + Colored, + Colored, + Colored, + Comment, + Empty, + ParseError>; + +QString modelElementToString(const ModelElement& element); +struct ModelId +{ + std::int32_t value; + constexpr auto operator<=>(const ModelId& other) const = default; +}; + +constexpr int qHash(ModelId id) +{ + return qHash(id.value); +} + class Model : public QAbstractListModel { Q_OBJECT + struct Entry { + ModelElement data; + ModelId id; + }; + std::vector body; + std::map positions; + ModelId runningId = {1}; public: - Model(QObject* parent = nullptr); - Model(const Model&) = delete; - - int size() const; - ldraw::id_t at(int index) const; + Model(QObject* parent); + virtual ~Model(); + ModelId append(const ModelElement& value); + const ModelElement& at(int position) const; + ModelId idAt(int position) const; + void assignAt(int position, const ModelElement& element); + std::optional find(ModelId id) const; + void remove(int index); int rowCount(const QModelIndex&) const override; QVariant data(const QModelIndex& index, int role) const override; - ldraw::Object* findObjectById(const ldraw::id_t id); - const ldraw::Object* findObjectById(const ldraw::id_t id) const; - QModelIndex find(ldraw::id_t id) const; - ldraw::id_t idAt(const QModelIndex& index) const; - template - const R* get(ldraw::Id id) const; - template - struct Get2Result - { - QModelIndex index; - const R* object; - }; - template - Get2Result get2(ldraw::Id id) const; - ldraw::Object* operator[](int index); - const ldraw::Object* operator[](int index) const; - using ModelObjectPointer = std::unique_ptr; - template - ldraw::Id append(Args&&... args); - ldraw::id_t append(ModelObjectPointer&& object); - template - ldraw::Id insert(std::size_t position, Args&&... args); - void remove(int position); - void emitDataChangedSignal(int position); -private: - bool modified = false; - std::vector body; - mutable std::map objectsById; - mutable bool needObjectsByIdRebuild = false; + const ModelElement& operator[](int index) const; + int size() const; + auto operator[](int index) { + struct { + Model& model; + int index; + operator const ModelElement&() { + return model.at(index); + } + auto& operator=(const ModelElement& newData) { + model.assignAt(index, newData); + return *this; + } + const auto* operator&() { + return &(this->operator const ModelElement&()); + } + } result{*this, index}; + return result; + } }; void save(const Model& model, QIODevice *device); - -/** - * @brief Calls the specified function to all matching objects in the model - * @tparam R Type of LDraw line type object to filter by - * @param fn Function to call. - */ -template -void applyToModel(const Model& model, Fn&& f) -{ - for (int i = 0; i < model.size(); i += 1) - { - const ldraw::Object* object = model[i]; - const R* subobject = dynamic_cast(object); - if (subobject != nullptr) - { - f(subobject); - } - } -} - -template -ldraw::Id Model::append(Args&&... args) -{ - const int position = static_cast(this->body.size()); - Q_EMIT beginInsertRows({}, position, position); - this->body.push_back(std::make_unique(args...)); - ldraw::Object* pointer = this->body.back().get(); - this->objectsById[pointer->id] = this->body.size() - 1; - Q_EMIT endInsertRows(); - return ldraw::Id{pointer->id.value}; -} - -template -ldraw::Id Model::insert(const std::size_t position, Args&&... args) -{ - Q_EMIT beginInsertRows({}, position, position); - this->body.insert(std::begin(this->body) + position, std::make_unique(args...)); - ldraw::Object* pointer = this->body[position].get(); - this->objectsById[pointer->id] = position; - Q_EMIT endInsertRows(); - return ldraw::Id{pointer->id.value}; -} - -template -const R* Model::get(ldraw::Id id) const -{ - return this->get2(id).object; -} - -template -Model::Get2Result Model::get2(const ldraw::Id id) const -{ - Get2Result result; - result.index = this->find(id); - if (result.index.isValid()) - { - result.object = static_cast((*this)[result.index.row()]); - } - else - { - result.object = nullptr; - } - return result; -} +void updateHeaderNameField(Model& model, const QString &name);