src/model.h

changeset 200
ca23936b455b
parent 173
8a3047468994
child 206
654661eab7f3
equal deleted inserted replaced
199:6988973515d2 200:ca23936b455b
18 18
19 #pragma once 19 #pragma once
20 #include <QAbstractListModel> 20 #include <QAbstractListModel>
21 #include <memory> 21 #include <memory>
22 #include "main.h" 22 #include "main.h"
23 #include "header.h" 23 #include "colors.h"
24 #include "linetypes/object.h"
25 #include "linetypes/metacommand.h"
26 #include "gl/common.h"
27 24
28 enum class HeaderProperty 25 struct SubfileReference
29 { 26 {
30 Name 27 QString name;
28 glm::mat4 transformation;
29 bool inverted = false;
31 }; 30 };
31
32 template<typename T>
33 struct Colored : T
34 {
35 ldraw::Color color;
36 };
37
38 struct Comment
39 {
40 QString text;
41 };
42
43 struct ParseError
44 {
45 QString code;
46 };
47
48 struct Empty {};
49
50 using ModelElement = std::variant<
51 Colored<SubfileReference>,
52 Colored<LineSegment>,
53 Colored<Triangle>,
54 Colored<Quadrilateral>,
55 Colored<ConditionalEdge>,
56 Comment,
57 Empty,
58 ParseError>;
59
60 QString modelElementToString(const ModelElement& element);
61 struct ModelId
62 {
63 std::int32_t value;
64 constexpr auto operator<=>(const ModelId& other) const = default;
65 };
66
67 constexpr int qHash(ModelId id)
68 {
69 return qHash(id.value);
70 }
32 71
33 class Model : public QAbstractListModel 72 class Model : public QAbstractListModel
34 { 73 {
35 Q_OBJECT 74 Q_OBJECT
75 struct Entry {
76 ModelElement data;
77 ModelId id;
78 };
79 std::vector<Entry> body;
80 std::map<ModelId, int> positions;
81 ModelId runningId = {1};
36 public: 82 public:
37 Model(QObject* parent = nullptr); 83 Model(QObject* parent);
38 Model(const Model&) = delete; 84 virtual ~Model();
39 85 ModelId append(const ModelElement& value);
40 int size() const; 86 const ModelElement& at(int position) const;
41 ldraw::id_t at(int index) const; 87 ModelId idAt(int position) const;
88 void assignAt(int position, const ModelElement& element);
89 std::optional<int> find(ModelId id) const;
90 void remove(int index);
42 int rowCount(const QModelIndex&) const override; 91 int rowCount(const QModelIndex&) const override;
43 QVariant data(const QModelIndex& index, int role) const override; 92 QVariant data(const QModelIndex& index, int role) const override;
44 ldraw::Object* findObjectById(const ldraw::id_t id); 93 const ModelElement& operator[](int index) const;
45 const ldraw::Object* findObjectById(const ldraw::id_t id) const; 94 int size() const;
46 QModelIndex find(ldraw::id_t id) const; 95 auto operator[](int index) {
47 ldraw::id_t idAt(const QModelIndex& index) const; 96 struct {
48 template<typename R> 97 Model& model;
49 const R* get(ldraw::Id<R> id) const; 98 int index;
50 template<typename R> 99 operator const ModelElement&() {
51 struct Get2Result 100 return model.at(index);
52 { 101 }
53 QModelIndex index; 102 auto& operator=(const ModelElement& newData) {
54 const R* object; 103 model.assignAt(index, newData);
55 }; 104 return *this;
56 template<typename R> 105 }
57 Get2Result<R> get2(ldraw::Id<R> id) const; 106 const auto* operator&() {
58 ldraw::Object* operator[](int index); 107 return &(this->operator const ModelElement&());
59 const ldraw::Object* operator[](int index) const; 108 }
60 using ModelObjectPointer = std::unique_ptr<ldraw::Object>; 109 } result{*this, index};
61 template<typename T, typename... Args> 110 return result;
62 ldraw::Id<T> append(Args&&... args); 111 }
63 ldraw::id_t append(ModelObjectPointer&& object);
64 template<typename T, typename... Args>
65 ldraw::Id<T> insert(std::size_t position, Args&&... args);
66 void remove(int position);
67 void emitDataChangedSignal(int position);
68 private:
69 bool modified = false;
70 std::vector<ModelObjectPointer> body;
71 mutable std::map<ldraw::id_t, std::size_t> objectsById;
72 mutable bool needObjectsByIdRebuild = false;
73 }; 112 };
74 113
75 void save(const Model& model, QIODevice *device); 114 void save(const Model& model, QIODevice *device);
76 115 void updateHeaderNameField(Model& model, const QString &name);
77 /**
78 * @brief Calls the specified function to all matching objects in the model
79 * @tparam R Type of LDraw line type object to filter by
80 * @param fn Function to call.
81 */
82 template<typename R, typename Fn>
83 void applyToModel(const Model& model, Fn&& f)
84 {
85 for (int i = 0; i < model.size(); i += 1)
86 {
87 const ldraw::Object* object = model[i];
88 const R* subobject = dynamic_cast<const R*>(object);
89 if (subobject != nullptr)
90 {
91 f(subobject);
92 }
93 }
94 }
95
96 template<typename T, typename... Args>
97 ldraw::Id<T> Model::append(Args&&... args)
98 {
99 const int position = static_cast<int>(this->body.size());
100 Q_EMIT beginInsertRows({}, position, position);
101 this->body.push_back(std::make_unique<T>(args...));
102 ldraw::Object* pointer = this->body.back().get();
103 this->objectsById[pointer->id] = this->body.size() - 1;
104 Q_EMIT endInsertRows();
105 return ldraw::Id<T>{pointer->id.value};
106 }
107
108 template<typename T, typename... Args>
109 ldraw::Id<T> Model::insert(const std::size_t position, Args&&... args)
110 {
111 Q_EMIT beginInsertRows({}, position, position);
112 this->body.insert(std::begin(this->body) + position, std::make_unique<T>(args...));
113 ldraw::Object* pointer = this->body[position].get();
114 this->objectsById[pointer->id] = position;
115 Q_EMIT endInsertRows();
116 return ldraw::Id<T>{pointer->id.value};
117 }
118
119 template<typename R>
120 const R* Model::get(ldraw::Id<R> id) const
121 {
122 return this->get2(id).object;
123 }
124
125 template<typename R>
126 Model::Get2Result<R> Model::get2(const ldraw::Id<R> id) const
127 {
128 Get2Result<R> result;
129 result.index = this->find(id);
130 if (result.index.isValid())
131 {
132 result.object = static_cast<const R*>((*this)[result.index.row()]);
133 }
134 else
135 {
136 result.object = nullptr;
137 }
138 return result;
139 }

mercurial