src/documentmanager.cpp

changeset 213
ee5758ddb6d2
parent 212
27259810da6d
child 214
8e1fe64ce4e3
equal deleted inserted replaced
212:27259810da6d 213:ee5758ddb6d2
18 18
19 #include <QFile> 19 #include <QFile>
20 #include <QDir> 20 #include <QDir>
21 #include <QFileInfo> 21 #include <QFileInfo>
22 #include <QSaveFile> 22 #include <QSaveFile>
23 #include <deque>
23 #include "documentmanager.h" 24 #include "documentmanager.h"
24 #include "parser.h" 25 #include "parser.h"
25 26
26 DocumentManager::DocumentManager() 27 DocumentManager::DocumentManager()
27 { 28 {
253 }); 254 });
254 return QObject::tr("The following files could not be opened: %1") 255 return QObject::tr("The following files could not be opened: %1")
255 .arg(missingString); 256 .arg(missingString);
256 } 257 }
257 258
258 /** 259 template<typename T, typename K>
259 * @brief Cleans up and erases models that are no longer required. 260 void removeFromSet(std::set<T>& set, K&& valueToRemove)
260 */ 261 {
262 const auto it = std::lower_bound(set.begin(), set.end(), valueToRemove);
263 if (it != set.end() and *it == valueToRemove) {
264 set.erase(it);
265 }
266 }
267
268 //! @brief Cleans up and erases models that are no longer required.
261 void DocumentManager::prune() 269 void DocumentManager::prune()
262 { 270 {
263 for (auto it = this->openModels.begin(); it != this->openModels.end(); ++it) 271 Graph<ModelId> dependencyGraph;
264 { 272 forValueInMap(this->openModels, [&dependencyGraph](const ModelInfo& info) {
265 // Find models that are not edited by the user and are not needed by any other model 273 forValueInMap(info.dependencies, [&dependencyGraph, &info](ModelId dep){
266 if (true 274 dependencyGraph.push_back({.from = info.id, .to = dep});
267 and it->second.opentype == OpenType::AutomaticallyOpened 275 });
268 and not this->isReferencedByAnything(it->first) 276 });
269 ) { 277 std::set<ModelId> autoOpened;
270 // Remove the model 278 forValueInMap(this->openModels, [&autoOpened](const ModelInfo& info) {
271 this->openModels.erase(it); 279 if (info.opentype == OpenType::AutomaticallyOpened) {
272 // We need to start over now. It is possible that other models that 280 autoOpened.insert(info.id);
273 // previously were referenced by the model we just erased have 281 }
274 // become prunable. Moreover, our iterator is invalid now and we 282 });
275 // cannot continue in this loop. 283 bool repeat = true;
276 this->prune(); 284 while (repeat) {
277 break; 285 repeat = false;
278 } 286 std::set<ModelId> prunable = autoOpened;
279 } 287 for (const auto& pair : dependencyGraph) {
280 } 288 removeFromSet(prunable, pair.to);
281 289 }
282 /** 290 for (ModelId idToPrune : prunable) {
283 * @brief Finds out whether the specified model id is referenced by any other model 291 auto it = this->openModels.find(idToPrune);
284 * @param modelId 292 if (it != this->openModels.end()) {
285 * @returns bool 293 this->openModels.erase(it);
286 */ 294 }
287 bool DocumentManager::isReferencedByAnything(const ModelId modelId) const 295 removeFromSet(autoOpened, idToPrune);
288 { 296 std::erase_if(dependencyGraph, [&idToPrune](const GraphEdge<ModelId>& edge) {
289 for (auto& haystackModelPair : this->openModels) 297 return edge.from == idToPrune;
290 { 298 });
291 if (haystackModelPair.first != modelId) 299 repeat = true;
292 { 300 }
293 for (auto& dependencyPair : haystackModelPair.second.dependencies) 301 }
294 {
295 if (dependencyPair.second == modelId)
296 {
297 return true;
298 }
299 }
300 }
301 }
302 return false;
303 } 302 }
304 303
305 void DocumentManager::makePolygonCacheForModel(const ModelId modelId) 304 void DocumentManager::makePolygonCacheForModel(const ModelId modelId)
306 { 305 {
307 Model* model = this->getModelById(modelId); 306 Model* model = this->getModelById(modelId);

mercurial