1 /*
2  * templatemanager.cpp
3  * Copyright 2017, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4  * Copyright 2017, Mohamed Thabet <thabetx@gmail.com>
5  *
6  * This file is part of Tiled.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "templatemanager.h"
23 
24 #include <memory>
25 
26 #include "objecttemplate.h"
27 #include "objecttemplateformat.h"
28 #include "logginginterface.h"
29 
30 #include <QFile>
31 #include <QFileInfo>
32 
33 using namespace Tiled;
34 
35 TemplateManager *TemplateManager::mInstance;
36 
instance()37 TemplateManager *TemplateManager::instance()
38 {
39     if (!mInstance)
40         mInstance = new TemplateManager;
41 
42     return mInstance;
43 }
44 
deleteInstance()45 void TemplateManager::deleteInstance()
46 {
47     delete mInstance;
48     mInstance = nullptr;
49 }
50 
TemplateManager(QObject * parent)51 TemplateManager::TemplateManager(QObject *parent)
52     : QObject(parent),
53       mWatcher(new FileSystemWatcher(this))
54 {
55     connect(mWatcher, &FileSystemWatcher::pathsChanged,
56             this, &TemplateManager::pathsChanged);
57 }
58 
~TemplateManager()59 TemplateManager::~TemplateManager()
60 {
61     qDeleteAll(mObjectTemplates);
62 }
63 
loadObjectTemplate(const QString & fileName,QString * error)64 ObjectTemplate *TemplateManager::loadObjectTemplate(const QString &fileName, QString *error)
65 {
66     ObjectTemplate *objectTemplate = findObjectTemplate(fileName);
67 
68     if (!objectTemplate) {
69         auto newTemplate = readObjectTemplate(fileName, error);
70 
71         // This instance will not have an object. It is used to detect broken
72         // template references.
73         if (!newTemplate)
74             newTemplate = std::make_unique<ObjectTemplate>(fileName);
75 
76         // If the file exists, watch it, regardless of whether the parse was successful.
77         if (QFile::exists(fileName))
78             mWatcher->addPath(fileName);
79 
80         objectTemplate = newTemplate.get();
81         mObjectTemplates.insert(fileName, newTemplate.release());
82     }
83 
84     return objectTemplate;
85 }
86 
pathsChanged(const QStringList & paths)87 void TemplateManager::pathsChanged(const QStringList &paths)
88 {
89     for (const QString &fileName : paths) {
90         ObjectTemplate *objectTemplate = findObjectTemplate(fileName);
91 
92         // Most likely the file was removed.
93         if (!objectTemplate)
94             continue;
95 
96         // Check whether we were the ones saving this file.
97         if (objectTemplate->lastSaved() == QFileInfo(fileName).lastModified())
98             continue;
99 
100         auto newTemplate = readObjectTemplate(fileName);
101         if (newTemplate) {
102             objectTemplate->setObject(newTemplate->object());
103             objectTemplate->setFormat(newTemplate->format());
104             emit objectTemplateChanged(objectTemplate);
105         } else if (objectTemplate->object()) {  // only report error if it had loaded fine before
106             ERROR(tr("Unable to reload template file: %1").arg(fileName));
107         }
108     }
109 }
110 
111 #include "moc_templatemanager.cpp"
112