17 */ |
17 */ |
18 |
18 |
19 #pragma once |
19 #pragma once |
20 #include "main.h" |
20 #include "main.h" |
21 #include "linetypes/modelobject.h" |
21 #include "linetypes/modelobject.h" |
|
22 #include "types/resourcevector.h" |
22 |
23 |
23 /* |
24 /* |
24 * This class represents a LDraw model, consisting of a vector of objects. It manages LDObject ownership. |
25 * This class represents a LDraw model, consisting of a vector of objects. It manages LDObject ownership. |
25 */ |
26 */ |
26 class Model : public QObject |
27 class Model : public QObject |
27 { |
28 { |
28 Q_OBJECT |
29 Q_OBJECT |
29 |
30 |
30 public: |
31 public: |
|
32 using Filter = std::function<bool(LDObject*)>; |
|
33 using Callback = std::function<void(LDObject*, int)>; |
|
34 |
31 Model(class DocumentManager* manager); |
35 Model(class DocumentManager* manager); |
32 Model(const Model& other) = delete; |
36 Model(const Model& other) = delete; |
33 ~Model(); |
|
34 |
37 |
35 void addObject(LDObject* object); |
38 bool swapObjects(LDObject* one, LDObject* other); |
36 virtual void insertObject(int position, LDObject* object); |
|
37 virtual bool swapObjects(LDObject* one, LDObject* other); |
|
38 virtual bool setObjectAt(int idx, LDObject* obj); |
|
39 template<typename T, typename... Args> T* emplace(Args&& ...args); |
39 template<typename T, typename... Args> T* emplace(Args&& ...args); |
40 template<typename T, typename... Args> T* emplaceAt(int position, Args&& ...args); |
40 template<typename T, typename... Args> T* emplaceAt(int position, Args&& ...args); |
41 template<typename T, typename... Args> T* emplaceReplacement(LDObject* object, Args&& ...args); |
41 template<typename T, typename... Args> T* emplaceReplacement(LDObject* object, Args&& ...args); |
42 template<typename T, typename... Args> T* emplaceReplacementAt(int position, Args&& ...args); |
|
43 void removeAt(int position); |
42 void removeAt(int position); |
44 void remove(LDObject* object); |
43 void remove(LDObject* object); |
45 void replace(LDObject *object, Model& model); |
44 void replace(LDObject *object, Model& model); |
46 void clear(); |
45 void clear(); |
47 void merge(Model& other, int position = -1); |
46 void merge(Model& other, int position = -1, Filter filter = nullptr, Callback callback = nullptr); |
48 int size() const; |
47 int size() const; |
49 const QVector<LDObject*>& objects() const; |
48 const ResourceVector<LDObject>& objects() const; |
50 LDObject* getObject(int position) const; |
49 LDObject* getObject(int position) const; |
51 void recountTriangles(); |
50 void recountTriangles(); |
52 int triangleCount() const; |
51 int triangleCount() const; |
53 QVector<LDObject*>::iterator begin(); |
52 LDObject* const* begin(); |
54 QVector<LDObject*>::iterator end(); |
53 LDObject* const* end(); |
55 bool isEmpty() const; |
54 bool isEmpty() const; |
56 class DocumentManager* documentManager() const; |
55 class DocumentManager* documentManager() const; |
57 LDObject* insertFromString(int position, QString line); |
56 LDObject* insertFromString(int position, QString line); |
58 LDObject* addFromString(QString line); |
57 LDObject* addFromString(QString line); |
59 LDObject* replaceWithFromString(LDObject* object, QString line); |
58 LDObject* replaceWithFromString(LDObject* object, QString line); |
60 |
59 |
61 signals: |
60 signals: |
62 void objectAdded(LDObject* object); |
61 void objectAdded(LDObject* object, int position); |
63 void aboutToRemoveObject(LDObject* object); |
62 void aboutToRemoveObject(LDObject* object, int position); |
64 void objectModified(LDObject* object); |
63 void objectModified(LDObject* object); |
|
64 void objectsSwapped(LDObject* one, LDObject* other); |
65 |
65 |
66 protected: |
66 protected: |
67 template<typename T, typename... Args> T* constructObject(Args&& ...args); |
67 template<typename T, typename... Args> T* constructObject(Args&& ...args); |
68 void withdraw(LDObject* object); |
|
69 virtual LDObject* withdrawAt(int position); |
|
70 |
68 |
71 QVector<LDObject*> _objects; |
69 ResourceVector<LDObject> _objects; |
72 class DocumentManager* _manager; |
70 class DocumentManager* _manager; |
73 mutable int _triangleCount = 0; |
71 mutable int _triangleCount = 0; |
74 mutable bool _needsTriangleRecount; |
72 mutable bool _needsTriangleRecount; |
|
73 |
|
74 private: |
|
75 void finalizeNewObject(int position, LDObject* object); |
|
76 ResourceVector<LDObject>& mutableObjects(); |
75 }; |
77 }; |
76 |
78 |
77 int countof(Model& model); |
79 int countof(Model& model); |
78 |
80 |
79 /* |
81 /* |
90 * model->emplace<LDLine>(v1, v2); |
92 * model->emplace<LDLine>(v1, v2); |
91 */ |
93 */ |
92 template<typename T, typename... Args> |
94 template<typename T, typename... Args> |
93 T* Model::emplace(Args&& ...args) |
95 T* Model::emplace(Args&& ...args) |
94 { |
96 { |
95 T* object = constructObject<T>(args...); |
97 T* object = _objects.append<T>(args..., this); |
96 addObject(object); |
98 finalizeNewObject(size() - 1, object); |
97 return object; |
99 return object; |
98 } |
100 } |
99 |
101 |
100 /* |
102 /* |
101 * Like emplace<>() but also takes a position as the first argument and emplaces the object at the given position instead of the |
103 * Like emplace<>() but also takes a position as the first argument and emplaces the object at the given position instead of the |
102 * end of the model. |
104 * end of the model. |
103 */ |
105 */ |
104 template<typename T, typename... Args> |
106 template<typename T, typename... Args> |
105 T* Model::emplaceAt(int position, Args&& ...args) |
107 T* Model::emplaceAt(int position, Args&& ...args) |
106 { |
108 { |
107 T* object = constructObject<T>(args...); |
109 T* object = _objects.insert<T>(position, args..., this); |
108 insertObject(position, object); |
110 finalizeNewObject(position, object); |
109 return object; |
111 return object; |
110 } |
112 } |
111 |
113 |
112 /* |
114 /* |
113 * Like emplace<>() but instead of inserting the constructed object, the new object replaces the object given in the first parameter. |
115 * Like emplace<>() but instead of inserting the constructed object, the new object replaces the object given in the first parameter. |
117 T* Model::emplaceReplacement(LDObject* object, Args&& ...args) |
119 T* Model::emplaceReplacement(LDObject* object, Args&& ...args) |
118 { |
120 { |
119 if (object->model() == this) |
121 if (object->model() == this) |
120 { |
122 { |
121 int position = object->lineNumber(); |
123 int position = object->lineNumber(); |
122 T* replacement = constructObject<T>(args...); |
124 removeAt(position); |
123 setObjectAt(position, replacement); |
125 T* replacement = _objects.insert<T>(position, args..., this); |
|
126 finalizeNewObject(position, replacement); |
124 return replacement; |
127 return replacement; |
125 } |
128 } |
126 else |
129 else |
|
130 { |
127 return nullptr; |
131 return nullptr; |
|
132 } |
128 } |
133 } |
129 |
|
130 /* |
|
131 * Like emplaceAt<>() but instead of inserting the constructed object, it replaces the document at the given spot instead. |
|
132 * The replaced object is deleted in the process. |
|
133 */ |
|
134 template<typename T, typename... Args> |
|
135 T* Model::emplaceReplacementAt(int position, Args&& ...args) |
|
136 { |
|
137 T* replacement = constructObject<T>(args...); |
|
138 setObjectAt(position, replacement); |
|
139 return replacement; |
|
140 } |
|
141 |
|
142 /* |
|
143 * Constructs an LDObject such that it gets this model as its model pointer. |
|
144 */ |
|
145 template<typename T, typename... Args> |
|
146 T* Model::constructObject(Args&& ...args) |
|
147 { |
|
148 static_assert (std::is_base_of<LDObject, T>::value, "Can only use this function with LDObject-derivatives"); |
|
149 T* object = new T {args..., this}; |
|
150 |
|
151 // Set default color. Relying on virtual functions, this cannot be done in the c-tor. |
|
152 // TODO: store -1 as the default color |
|
153 if (object->isColored()) |
|
154 object->setColor(object->defaultColor()); |
|
155 |
|
156 return object; |
|
157 } |
|