BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
projectdocument.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/mainwindow/projectdocument.cpp
6 //! @brief Implements class ProjectDocument
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
22 #include <QDir>
23 #include <QElapsedTimer>
24 #include <QXmlStreamReader>
25 
26 namespace {
27 const QString minimal_supported_version = "1.6.0";
28 }
29 
30 ProjectDocument::ProjectDocument(const QString& projectFileName)
31  : m_applicationModels(nullptr)
32  , m_modified(false)
33  , m_documentStatus(ProjectFlags::STATUS_OK)
34  , m_messageService(nullptr)
35  , m_dataService(new OutputDataIOService(this))
36 {
37  setObjectName("ProjectDocument");
38  if (!projectFileName.isEmpty())
40 }
41 
43 {
44  return m_project_name;
45 }
46 
47 void ProjectDocument::setProjectName(const QString& text)
48 {
49  if (m_project_name != text) {
50  m_project_name = text;
51  emit modified();
52  }
53 }
54 
56 {
57  return m_project_dir;
58 }
59 
60 void ProjectDocument::setProjectDir(const QString& text)
61 {
62  m_project_dir = text;
63 }
64 
66 {
67  if (!projectName().isEmpty())
68  return projectDir() + "/" + projectName() + projectFileExtension();
69  else
70  return "";
71 }
72 
73 void ProjectDocument::setProjectFileName(const QString& projectFileName)
74 {
77 }
78 
80 {
81  return ".pro";
82 }
83 
85 {
86  if (applicationModels != m_applicationModels) {
88  m_applicationModels = applicationModels;
90  connectModels();
91  }
92 }
93 
94 void ProjectDocument::save(const QString& project_file_name, bool autoSave)
95 {
96  save_project_data(project_file_name);
97  save_project_file(project_file_name, autoSave);
98 }
99 
100 void ProjectDocument::save_project_file(const QString& project_file_name, bool autoSave)
101 {
102  QElapsedTimer timer;
103  timer.start();
104 
105  QFile file(project_file_name);
106  if (!file.open(QFile::ReadWrite | QIODevice::Truncate | QFile::Text))
107  throw GUIHelpers::Error("ProjectDocument::save_project_file() -> Error. Can't open "
108  "file '"
109  + project_file_name + "' for writing.");
110 
111  writeTo(&file);
112  file.close();
113 
114  if (!autoSave) {
115  setProjectFileName(project_file_name);
116  m_modified = false;
117  emit modified();
118  }
119 }
120 
121 void ProjectDocument::save_project_data(const QString& project_file_name)
122 {
123  QElapsedTimer timer;
124  timer.start();
125 
126  m_dataService->save(ProjectUtils::projectDir(project_file_name));
127 }
128 
129 void ProjectDocument::load(const QString& project_file_name)
130 {
131  QElapsedTimer timer1, timer2;
132  timer1.start();
133 
135  setProjectFileName(project_file_name);
136 
137  QFile file(projectFileName());
138  if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
139  QString message = QString("Open file error '%1'").arg(file.errorString());
140  m_messageService->send_error(this, message);
142  return;
143  }
144 
145  try {
147  readFrom(&file);
148  file.close();
149 
150  timer2.start();
152  connectModels();
153 
156 
157  } catch (const std::exception& ex) {
158  QString message = QString("Exception thrown '%1'").arg(QString(ex.what()));
159  m_messageService->send_error(this, message);
161  }
162 }
163 
165 {
166  return (!m_project_name.isEmpty() && !m_project_dir.isEmpty());
167 }
168 
170 {
171  return m_modified;
172 }
173 
175 {
176  m_modified = flag;
177  if (m_modified)
178  emit modified();
179 }
180 
182 {
183  m_messageService = messageService;
184 }
185 
186 ProjectFlags::DocumentStatus ProjectDocument::documentStatus() const
187 {
188  return m_documentStatus;
189 }
190 
192 {
194 }
195 
197 {
199 }
200 
202 {
204 }
205 
207 {
208  return !m_dataService->nonXMLItems().isEmpty();
209 }
210 
212 {
213  QString result(m_currentVersion);
214  if (result.isEmpty())
216  return result;
217 }
218 
220 {
221  m_modified = true;
222  emit modified();
223 }
224 
225 void ProjectDocument::readFrom(QIODevice* device)
226 {
228  QXmlStreamReader reader(device);
229 
230  while (!reader.atEnd()) {
231  reader.readNext();
232  if (reader.isStartElement()) {
233  if (reader.name() == ProjectDocumentXML::BornAgainTag) {
234  m_currentVersion = reader.attributes()
236  .toString();
237 
239  minimal_supported_version)) {
241  QString message = QString("Can't open document version '%1', "
242  "minimal supported version '%2'")
243  .arg(m_currentVersion)
244  .arg(minimal_supported_version);
245  m_messageService->send_error(this, message);
246  return;
247  }
248 
249  while (reader.readNextStartElement())
250  if (reader.name() == ProjectDocumentXML::InfoTag)
251  reader.skipCurrentElement();
252  else
254 
257  }
258  }
259  }
260 
261  if (reader.hasError()) {
263  QString message = QString("Format error '%1'").arg(reader.errorString());
264  m_messageService->send_error(this, message);
265  return;
266  }
267 }
268 
269 void ProjectDocument::writeTo(QIODevice* device)
270 {
271  QXmlStreamWriter writer(device);
272  writer.setAutoFormatting(true);
273  writer.writeStartDocument();
274  writer.writeStartElement(ProjectDocumentXML::BornAgainTag);
275  QString version_string = GUIHelpers::getBornAgainVersionString();
276  writer.writeAttribute(ProjectDocumentXML::BornAgainVersionAttribute, version_string);
277 
278  writer.writeStartElement(ProjectDocumentXML::InfoTag);
279  writer.writeAttribute(ProjectDocumentXML::InfoNameAttribute, projectName());
280  writer.writeEndElement(); // InfoTag
281 
282  m_applicationModels->writeTo(&writer);
283 
284  writer.writeEndElement(); // BornAgain tag
285  writer.writeEndDocument();
286 }
287 
289 {
293 }
294 
296 {
299  &ProjectDocument::onModelChanged, Qt::UniqueConnection);
300 }
Defines class holding all application models.
#define ASSERT(condition)
Definition: Assert.h:31
Defines class GUIHelpers functions.
Defines class JobModel.
Defines MessageService class.
Defines class OutputDataIOService.
Defines ProjectUtils namespace.
void readFrom(class QXmlStreamReader *reader, MessageService *messageService)
void writeTo(class QXmlStreamWriter *writer)
Writes all model in file one by one.
The service to collect messages from different senders.
void send_error(QObject *sender, const QString &description)
int messageCount(const QObject *sender, const QString &message_type="") const
Reports number of messages of given type reported by the sender.
int warningCount(const QObject *sender=0) const
Returns number of warnings for given sender.
Provide read/write of heavy data files in a separate thread.
void load(const QString &projectDir, MessageService *messageService=nullptr)
void setApplicationModels(ApplicationModels *models)
QVector< SaveLoadInterface * > nonXMLItems() const
Returns all non-XML items available for save/load.
void save(const QString &projectDir)
OutputDataIOService * m_dataService
QString m_project_name
void setApplicationModels(ApplicationModels *applicationModels)
static QString projectFileExtension()
QString projectFileName() const
MessageService * m_messageService
void setProjectDir(const QString &text)
QString documentVersion() const
bool isReady() const
QString projectName() const
void load(const QString &project_file_name)
void readFrom(QIODevice *device)
void setProjectName(const QString &text)
void writeTo(QIODevice *device)
void setLogger(MessageService *messageService)
ApplicationModels * m_applicationModels
bool hasData() const
ProjectFlags::DocumentStatus m_documentStatus
void save_project_data(const QString &project_file_name)
QString projectDir() const
void setProjectFileName(const QString &text)
bool hasWarnings() const
ProjectDocument(const QString &projectFileName="")
bool hasErrors() const
void save(const QString &project_file_name, bool autoSave=false)
void save_project_file(const QString &project_file_name, bool autoSave=false)
QString m_currentVersion
ProjectFlags::DocumentStatus documentStatus() const
void setModified(bool flag)
static void setFlag(ProjectFlags::DocumentStatus &flags, EDocumentStatus status)
Definition: ProjectFlags.h:30
QString getBornAgainVersionString()
Definition: GUIHelpers.cpp:130
bool isVersionMatchMinimal(const QString &version, const QString &minimal_version)
returns true if current BornAgain version match minimal required version
Definition: GUIHelpers.cpp:187
const QString InfoTag("DocumentInfo")
const QString InfoNameAttribute("ProjectName")
const QString BornAgainVersionAttribute("Version")
const QString BornAgainTag("BornAgain")
QString projectName(const QString &projectFileName)
Returns project name deduced from project file name.
QString projectDir(const QString &projectFileName)
Returns project directory deduced from project file name.
Defines class ProjectDocument.