src/model.h

changeset 150
b6cbba6e29a1
parent 148
e1ced2523cad
child 151
e628fc2e0c72
equal deleted inserted replaced
148:e1ced2523cad 150:b6cbba6e29a1
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
189 146
190 template<typename R> 147 template<typename R>
191 Model::Get2Result<R> Model::get2(const ldraw::Id<R> id) const 148 Model::Get2Result<R> Model::get2(const ldraw::Id<R> id) const
192 { 149 {
193 Get2Result<R> result; 150 Get2Result<R> result;
194 result.index = this->lookup(id); 151 result.index = this->find(id);
195 if (result.index.isValid()) 152 if (result.index.isValid())
196 { 153 {
197 result.object = static_cast<const R*>(this->objectAt(result.index)); 154 result.object = static_cast<const R*>(this->objectAt(result.index));
198 } 155 }
199 else 156 else
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

mercurial