src/documentmanager.cpp

changeset 340
e17e07661f4c
parent 338
719b909a7d2b
child 374
75efc3ba5a56
equal deleted inserted replaced
339:4787d05e9c89 340:e17e07661f4c
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 <QPlainTextDocumentLayout>
23 #include <deque> 24 #include <deque>
24 #include "src/documentmanager.h" 25 #include "src/documentmanager.h"
25 #include "src/parser.h" 26 #include "src/parser.h"
26 27
27 DocumentManager::DocumentManager(QObject *parent) : 28 DocumentManager::DocumentManager(QObject *parent) :
28 QObject{parent} 29 QObject{parent}
29 { 30 {
31 }
32
33 static std::unique_ptr<QTextDocument> newTextDocument()
34 {
35 std::unique_ptr<QTextDocument> newModel = std::make_unique<QTextDocument>(nullptr);
36 newModel->setDocumentLayout(new QPlainTextDocumentLayout{newModel.get()});
37 return newModel;
30 } 38 }
31 39
32 /** 40 /**
33 * @brief Creates a new model. 41 * @brief Creates a new model.
34 * @returns the ID of the new model 42 * @returns the ID of the new model
35 */ 43 */
36 ModelId DocumentManager::newModel() 44 ModelId DocumentManager::newModel()
37 { 45 {
38 const ModelId modelId{++this->modelIdCounter}; 46 const ModelId modelId{++this->modelIdCounter};
39 this->openModels.emplace(std::make_pair(modelId, ModelInfo{ 47 this->openModels.emplace(std::make_pair(modelId, ModelInfo{
40 .model = std::make_unique<Model>(this), 48 .model = newTextDocument(),
41 .id = modelId, 49 .id = modelId,
42 .opentype = OpenType::ManuallyOpened, 50 .opentype = OpenType::ManuallyOpened,
43 })); 51 }));
44 this->makePolygonCacheForModel(modelId); 52 this->makePolygonCacheForModel(modelId);
45 Q_EMIT this->message(logInfo(tr("New model %1 created").arg(modelId.value))); 53 Q_EMIT this->message(logInfo(tr("New model %1 created").arg(modelId.value)));
46 return modelId; 54 return modelId;
47 } 55 }
48 56
49 Model* DocumentManager::findDependencyByName(const ModelId modelId, const QString& name) 57 QTextDocument* DocumentManager::findDependencyByName(const ModelId modelId, const QString& name)
50 { 58 {
51 const auto modelsIterator = this->openModels.find(modelId); 59 const auto modelsIterator = this->openModels.find(modelId);
52 if (modelsIterator != std::end(this->openModels)) { 60 if (modelsIterator != std::end(this->openModels)) {
53 const auto& dependencies = modelsIterator->second.dependencies; 61 const auto& dependencies = modelsIterator->second.dependencies;
54 const auto dependenciesIterator = dependencies.find(name); 62 const auto dependenciesIterator = dependencies.find(name);
68 /** 76 /**
69 * @brief Gets a model pointer by id or nullptr if not found 77 * @brief Gets a model pointer by id or nullptr if not found
70 * @param modelId id of model to find 78 * @param modelId id of model to find
71 * @returns model pointer or null 79 * @returns model pointer or null
72 */ 80 */
73 Model *DocumentManager::getModelById(ModelId modelId) 81 QTextDocument *DocumentManager::getModelById(ModelId modelId)
74 { 82 {
75 const auto iterator = this->openModels.find(modelId); 83 const auto iterator = this->openModels.find(modelId);
76 if (iterator != this->openModels.end()) 84 if (iterator != this->openModels.end())
77 { 85 {
78 return iterator->second.model.get(); 86 return iterator->second.model.get();
109 * @param path Path to the model to open 117 * @param path Path to the model to open
110 * @param errorStream Where to write any errors 118 * @param errorStream Where to write any errors
111 * @param openType rationale behind opening this file 119 * @param openType rationale behind opening this file
112 * @returns model id, or no value on error 120 * @returns model id, or no value on error
113 */ 121 */
114 #include <QPlainTextDocumentLayout>
115 std::optional<ModelId> DocumentManager::openModel( 122 std::optional<ModelId> DocumentManager::openModel(
116 const QString& path, 123 const QString& path,
117 QTextStream& errorStream, 124 QTextStream& errorStream,
118 const OpenType openType 125 const OpenType openType
119 ) { 126 ) {
120 QFile file{path}; 127 QFile file{path};
121 const QString name = pathToName(QFileInfo{path}); 128 const QString name = pathToName(QFileInfo{path});
122 file.open(QFile::ReadOnly | QFile::Text); 129 file.open(QFile::ReadOnly | QFile::Text);
123 std::unique_ptr<QTextDocument> newModel = std::make_unique<QTextDocument>(nullptr); 130 std::unique_ptr<QTextDocument> newModel = newTextDocument();
124 newModel->setDocumentLayout(new QPlainTextDocumentLayout{newModel.get()});
125 newModel->setPlainText(file.readAll()); 131 newModel->setPlainText(file.readAll());
126 std::optional<ModelId> result; 132 std::optional<ModelId> result;
127 if (file.error() == QFile::NoError) 133 if (file.error() == QFile::NoError)
128 { 134 {
129 const ModelId modelId{++this->modelIdCounter}; 135 const ModelId modelId{++this->modelIdCounter};
193 if (info != nullptr) 199 if (info != nullptr)
194 { 200 {
195 QSaveFile file{info->path}; 201 QSaveFile file{info->path};
196 file.setDirectWriteFallback(true); 202 file.setDirectWriteFallback(true);
197 if (file.open(QSaveFile::WriteOnly)) { 203 if (file.open(QSaveFile::WriteOnly)) {
198 file.write(info->model->toPlainText().toUtf8()); 204 file.write(info->model->toPlainText().replace("\n", "\r\n").toUtf8());
199 const bool commitSucceeded = file.commit(); 205 const bool commitSucceeded = file.commit();
200 if (not commitSucceeded) { 206 if (not commitSucceeded) {
201 errors << QObject::tr("Could not save: %1").arg(file.errorString()); 207 errors << QObject::tr("Could not save: %1").arg(file.errorString());
202 return false; 208 return false;
203 } 209 }
220 /** 226 /**
221 * @brief Searches the open models for the specified model and returns its id if found 227 * @brief Searches the open models for the specified model and returns its id if found
222 * @param model model to look for 228 * @param model model to look for
223 * @return id or no value if not found 229 * @return id or no value if not found
224 */ 230 */
225 std::optional<ModelId> DocumentManager::findIdForModel(const Model *model) const 231 std::optional<ModelId> DocumentManager::findIdForModel(const QTextDocument *model) const
226 { 232 {
227 std::optional<ModelId> result; 233 std::optional<ModelId> result;
228 for (auto it = this->openModels.begin(); it != this->openModels.end(); ++it) 234 for (auto it = this->openModels.begin(); it != this->openModels.end(); ++it)
229 { 235 {
230 if (it->second.model.get() == model) 236 if (it->second.model.get() == model)
317 } 323 }
318 } 324 }
319 325
320 void DocumentManager::makePolygonCacheForModel(const ModelId modelId) 326 void DocumentManager::makePolygonCacheForModel(const ModelId modelId)
321 { 327 {
322 Model* model = this->getModelById(modelId); 328 QTextDocument* model = this->getModelById(modelId);
323 if (model != nullptr) 329 if (model != nullptr)
324 { 330 {
325 const auto modelModified = [this, model]{ 331 const auto modelModified = [this, model]{
326 const std::optional<ModelId> modelId = this->findIdForModel(model); 332 const std::optional<ModelId> modelId = this->findIdForModel(model);
327 if (modelId.has_value()) { 333 if (modelId.has_value()) {
350 referencedFilePath = libraries.findFile(referenceName); 356 referencedFilePath = libraries.findFile(referenceName);
351 } 357 }
352 return referencedFilePath; 358 return referencedFilePath;
353 } 359 }
354 360
355 static std::set<QString> referenceNames(const Model* model) 361 static std::set<QString> referenceNames(const QTextDocument* model)
356 { 362 {
357 std::set<QString> result; 363 std::set<QString> result;
358 for (const QString& line : model->toPlainText().split("\n")) { 364 for (const QString& line : model->toPlainText().split("\n")) {
359 const opt<ParsedLine> parsed = parse(line); 365 const opt<ParsedLine> parsed = parse(line);
360 if (parsed.has_value() and std::holds_alternative<LineType1>(*parsed)) { 366 if (parsed.has_value() and std::holds_alternative<LineType1>(*parsed)) {

mercurial