35 Q_OBJECT |
35 Q_OBJECT |
36 public: |
36 public: |
37 class EditContext; |
37 class EditContext; |
38 Model(QObject* parent = nullptr); |
38 Model(QObject* parent = nullptr); |
39 Model(const Model&) = delete; |
39 Model(const Model&) = delete; |
|
40 |
40 int size() const; |
41 int size() const; |
41 ldraw::id_t at(int index) const; |
42 ldraw::id_t at(int index) const; |
42 EditContext edit(); |
43 EditContext edit(); |
43 int rowCount(const QModelIndex&) const override; |
44 int rowCount(const QModelIndex&) const override; |
44 QVariant data(const QModelIndex& index, int role) const override; |
45 QVariant data(const QModelIndex& index, int role) const override; |
45 QVariant getHeaderProperty(const HeaderProperty property); |
46 QVariant getHeaderProperty(const HeaderProperty property); |
46 const QString& getName() const; |
|
47 QVariant getObjectProperty(const int index, const ldraw::Property property) const; |
47 QVariant getObjectProperty(const int index, const ldraw::Property property) const; |
48 template<ldraw::Property Property> |
48 template<ldraw::Property Property> |
49 ldraw::PropertyType<Property> getObjectProperty(const ldraw::id_t id) const; |
49 ldraw::PropertyType<Property> getObjectProperty(const ldraw::id_t id) const; |
50 std::vector<gl::Polygon> getPolygons(class DocumentManager* documents) const; |
50 QModelIndex find(ldraw::id_t id) const; |
51 QModelIndex lookup(ldraw::id_t id) const; |
51 ldraw::id_t idAt(const QModelIndex& index) const; |
52 ldraw::id_t resolve(const QModelIndex& index) const; |
|
53 template<typename R> |
|
54 ldraw::Id<R> checkType(ldraw::id_t id) const; |
|
55 template<typename R> |
|
56 bool isA(ldraw::id_t id) const; |
|
57 template<typename R> |
52 template<typename R> |
58 const R* get(ldraw::Id<R> id) const; |
53 const R* get(ldraw::Id<R> id) const; |
59 template<typename R> |
54 template<typename R> |
60 struct Get2Result |
55 struct Get2Result |
61 { |
56 { |
65 template<typename R> |
60 template<typename R> |
66 Get2Result<R> get2(ldraw::Id<R> id) const; |
61 Get2Result<R> get2(ldraw::Id<R> id) const; |
67 template<typename R, typename Fn> |
62 template<typename R, typename Fn> |
68 void apply(Fn f) const; |
63 void apply(Fn f) const; |
69 void save(QIODevice *device) const; |
64 void save(QIODevice *device) const; |
70 void makeUnofficial(); |
65 ldraw::Object* operator[](int index); |
71 Q_SIGNALS: |
66 Q_SIGNALS: |
72 void objectAdded(ldraw::id_t id, int position); |
67 void objectAdded(int position); |
73 void objectModified(ldraw::id_t id, int position); |
68 void objectModified(int position); |
|
69 void objectRemoved(ldraw::id_t id); |
74 private: |
70 private: |
75 using ModelObjectPointer = std::unique_ptr<ldraw::Object>; |
71 using ModelObjectPointer = std::unique_ptr<ldraw::Object>; |
76 template<typename T, typename... Args> |
72 template<typename T, typename... Args> |
77 ldraw::Id<T> append(Args&&... args); |
73 ldraw::Id<T> append(Args&&... args); |
78 void append(ModelObjectPointer&& object); |
74 void append(ModelObjectPointer&& object); |
83 const ldraw::Object* objectAt(const QModelIndex& index) const; |
79 const ldraw::Object* objectAt(const QModelIndex& index) const; |
84 template<typename T> |
80 template<typename T> |
85 T* objectAt(ldraw::Id<T> id); |
81 T* objectAt(ldraw::Id<T> id); |
86 template<typename T> |
82 template<typename T> |
87 const T* objectAt(ldraw::Id<T> id) const; |
83 const T* objectAt(ldraw::Id<T> id) const; |
88 void getObjectPolygons( |
|
89 const int index, |
|
90 std::vector<gl::Polygon>& polygons_out, |
|
91 ldraw::GetPolygonsContext* context) const; |
|
92 void editFinished(); |
84 void editFinished(); |
93 void objectModified(ldraw::id_t id); |
85 void objectModified(ldraw::id_t id); |
94 bool modified = false; |
86 bool modified = false; |
95 LDHeader header; |
87 LDHeader header; |
96 std::vector<ModelObjectPointer> body; |
88 std::vector<ModelObjectPointer> body; |
97 std::map<ldraw::id_t, ldraw::Object*> objectsById; |
89 std::map<ldraw::id_t, ldraw::Object*> objectsById; |
98 mutable std::vector<gl::Polygon> cachedPolygons; |
|
99 mutable bool needRecache = true; |
|
100 /** |
90 /** |
101 * @brief Amount of model edit contexts active |
91 * @brief Amount of model edit contexts active |
102 */ |
92 */ |
103 int editCounter = 0; |
93 int editCounter = 0; |
104 }; |
94 }; |
105 |
95 |
106 /** |
96 void makeUnofficial(Model& model); |
107 * @brief Checks whether the id is exactly of the specified type |
|
108 * @tparam R Type of LDraw line type object to test for |
|
109 * @param id Id of object to test |
|
110 * @returns whether the type of the object specified by @c id is the same type as R. Returns false if it is a subclass. |
|
111 */ |
|
112 template<typename R> |
|
113 bool Model::isA(ldraw::id_t id) const |
|
114 { |
|
115 const ldraw::Object* object = this->objectAt(this->lookup(id)); |
|
116 const std::type_info& a = typeid(*object); |
|
117 const std::type_info& b = typeid(R); |
|
118 return a == b; |
|
119 } |
|
120 |
97 |
121 /** |
98 /** |
122 * @brief Calls the specified function to all matching objects in the model |
99 * @brief Calls the specified function to all matching objects in the model |
123 * @tparam R Type of LDraw line type object to filter by |
100 * @tparam R Type of LDraw line type object to filter by |
124 * @param fn Function to call. |
101 * @param fn Function to call. |
134 f(subobject); |
111 f(subobject); |
135 } |
112 } |
136 } |
113 } |
137 } |
114 } |
138 |
115 |
139 /** |
|
140 * \brief Checks type of object behind id |
|
141 * Checks whether the specified id refers to an object of the specified type. |
|
142 * \returns id casted to subclass if appropriate, null id otherwise |
|
143 */ |
|
144 template<typename R> |
|
145 ldraw::Id<R> Model::checkType(ldraw::id_t id) const |
|
146 { |
|
147 if (dynamic_cast<const R*>(this->objectAt(this->lookup(id))) != nullptr) |
|
148 { |
|
149 return ldraw::Id<R>{id.value}; |
|
150 } |
|
151 else |
|
152 { |
|
153 return ldraw::NULL_ID; |
|
154 } |
|
155 } |
|
156 |
|
157 template<typename T, typename... Args> |
116 template<typename T, typename... Args> |
158 ldraw::Id<T> Model::append(Args&&... args) |
117 ldraw::Id<T> Model::append(Args&&... args) |
159 { |
118 { |
160 const int position = static_cast<int>(this->body.size()); |
119 const int position = static_cast<int>(this->body.size()); |
161 Q_EMIT beginInsertRows({}, position, position); |
120 Q_EMIT beginInsertRows({}, position, position); |
162 this->body.push_back(std::make_unique<T>(args...)); |
121 this->body.push_back(std::make_unique<T>(args...)); |
163 ldraw::Object* pointer = this->body.back().get(); |
122 ldraw::Object* pointer = this->body.back().get(); |
164 this->objectsById[pointer->id] = pointer; |
123 this->objectsById[pointer->id] = pointer; |
165 Q_EMIT objectAdded(pointer->id, static_cast<int>(this->body.size() - 1)); |
124 Q_EMIT objectAdded(static_cast<int>(this->body.size() - 1)); |
166 Q_EMIT endInsertRows(); |
125 Q_EMIT endInsertRows(); |
167 this->needRecache = true; |
|
168 return ldraw::Id<T>{pointer->id.value}; |
126 return ldraw::Id<T>{pointer->id.value}; |
169 } |
127 } |
170 |
128 |
171 template<typename T, typename... Args> |
129 template<typename T, typename... Args> |
172 ldraw::Id<T> Model::insert(const std::size_t position, Args&&... args) |
130 ldraw::Id<T> Model::insert(const std::size_t position, Args&&... args) |
173 { |
131 { |
174 Q_EMIT beginInsertRows({}, position, position); |
132 Q_EMIT beginInsertRows({}, position, position); |
175 this->body.insert(std::begin(this->body) + position, std::make_unique<T>(args...)); |
133 this->body.insert(std::begin(this->body) + position, std::make_unique<T>(args...)); |
176 ldraw::Object* pointer = this->body[position].get(); |
134 ldraw::Object* pointer = this->body[position].get(); |
177 this->objectsById[pointer->id] = pointer; |
135 this->objectsById[pointer->id] = pointer; |
178 Q_EMIT objectAdded(pointer->id, static_cast<int>(position)); |
136 Q_EMIT objectAdded(static_cast<int>(position)); |
179 Q_EMIT endInsertRows(); |
137 Q_EMIT endInsertRows(); |
180 this->needRecache = true; |
|
181 return ldraw::Id<T>{pointer->id.value}; |
138 return ldraw::Id<T>{pointer->id.value}; |
182 } |
139 } |
183 |
140 |
184 template<typename R> |
141 template<typename R> |
185 const R* Model::get(ldraw::Id<R> id) const |
142 const R* Model::get(ldraw::Id<R> id) const |
209 * @return object pointer |
166 * @return object pointer |
210 */ |
167 */ |
211 template<typename T> |
168 template<typename T> |
212 T* Model::objectAt(ldraw::Id<T> id) |
169 T* Model::objectAt(ldraw::Id<T> id) |
213 { |
170 { |
214 return static_cast<T*>(this->objectAt(this->lookup(id))); |
171 return static_cast<T*>(this->objectAt(this->find(id))); |
215 } |
172 } |
216 |
173 |
217 template<typename T> |
174 template<typename T> |
218 const T* Model::objectAt(ldraw::Id<T> id) const |
175 const T* Model::objectAt(ldraw::Id<T> id) const |
219 { |
176 { |
220 return static_cast<const T*>(this->objectAt(this->lookup(id))); |
177 return static_cast<const T*>(this->objectAt(this->find(id))); |
221 } |
178 } |
222 |
179 |
223 /** |
180 /** |
224 * @brief Gets an object property by id |
181 * @brief Gets an object property by id |
225 * @tparam Property Property to obtain |
182 * @tparam Property Property to obtain |