NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxSessionStorageServiceImpl.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
13 #include "cxSettings.h"
14 #include "cxReporter.h"
15 #include <QTextStream>
16 #include "cxTime.h"
17 #include <QDir>
18 #include "cxConfig.h"
19 #include "cxFileHelpers.h"
20 #include "cxDataLocations.h"
21 #include <QApplication>
22 #include <QTimer>
23 #include "cxLogger.h"
24 #include "cxProfile.h"
25 #include "cxOrderedQDomDocument.h"
26 #include "cxXmlFileHandler.h"
27 
28 
29 namespace cx
30 {
31 
33 {
34  this->clearCache();
35  mActivePatientFolder = this->getNoPatientFolder();
36  connect(this, &SessionStorageServiceImpl::sessionChanged, this, &SessionStorageServiceImpl::onSessionChanged);
37 
38  QTimer::singleShot(100, this, SLOT(startupLoadPatient())); // make sure this is called after application state change
39 }
40 
42 {
43  this->clearCache();
44 }
45 
47 {
48  return false;
49 }
50 
52 {
53  bool valid = this->isValidSessionFolder(dir);
54  bool exists = this->folderExists(dir);
55 
56  if (valid)
57  {
58  this->loadSession(dir);
59  }
60  else if (!exists)
61  {
62  this->initializeNewSession(dir);
63  }
64  else
65  {
66  reportError(QString("Failed to initialize session in existing folder with no valid session: %1").arg(dir));
67  }
68 }
69 
70 QString SessionStorageServiceImpl::getNoPatientFolder() const
71 {
72  return DataLocations::getCachePath() + "/NoPatient";
73 }
74 
75 
76 bool SessionStorageServiceImpl::isValidSessionFolder(QString dir) const
77 {
78  QString filename = QDir(dir).absoluteFilePath(this->getXmlFileName());
79  return QFileInfo::exists(filename);
80 }
81 
82 bool SessionStorageServiceImpl::folderExists(QString dir) const
83 {
84  return QFileInfo(dir).exists() && QFileInfo(dir).isDir();
85 }
86 
87 void SessionStorageServiceImpl::loadSession(QString dir)
88 {
89  if (this->isActivePatient(dir))
90  return;
91  this->loadPatientSilent(dir);
92  this->reportActivePatient();
93  this->writeRecentPatientData();
94 }
95 
96 void SessionStorageServiceImpl::initializeNewSession(QString dir)
97 {
98  this->clearPatientSilent();
99  dir = this->convertToValidFolderName(dir);
100  this->createPatientFolders(dir);
101  this->setActivePatient(dir);
102  this->save();
103  this->reportActivePatient();
104  this->writeRecentPatientData();
105 }
106 
107 QString SessionStorageServiceImpl::getXmlFileName() const
108 {
109  return "custusdoc.xml";
110 }
111 
113 {
114  if (!this->isValid())
115  return;
116 
117  //Gather all the information that needs to be saved
119  this->generateSaveDoc(doc.doc());
120 
121  QDomElement element = doc.doc().documentElement();
122  emit isSaving(element); // give all listeners a chance to add to the document
123 
124  QString filename = QDir(mActivePatientFolder).absoluteFilePath(this->getXmlFileName());
125  XmlFileHandler::writeXmlFile(doc.doc(), filename);
126  report("Saved patient " + mActivePatientFolder);
127 }
128 
130 {
131  this->clearPatientSilent();
132  this->reportActivePatient();
133  this->writeRecentPatientData();
134 }
135 
137 {
138  return !mActivePatientFolder.isEmpty() &&
139  (mActivePatientFolder != this->getNoPatientFolder());
140 }
141 
143 {
144  return mActivePatientFolder;
145 }
146 
147 void SessionStorageServiceImpl::reportActivePatient()
148 {
149  report("Set Active Patient: " + mActivePatientFolder);
150 }
151 
152 void SessionStorageServiceImpl::setActivePatient(const QString& activePatientFolder)
153 {
154  if (activePatientFolder == mActivePatientFolder)
155  return;
156 
157  mActivePatientFolder = activePatientFolder;
158 
159  emit sessionChanged();
160 }
161 
162 void SessionStorageServiceImpl::onSessionChanged()
163 {
164  reporter()->setLoggingFolder(this->getSubFolder("Logs/"));
165 }
166 
167 void SessionStorageServiceImpl::clearPatientSilent()
168 {
169  this->setActivePatient(this->getNoPatientFolder());
170  emit cleared();
171 }
172 
173 bool SessionStorageServiceImpl::isActivePatient(QString patient) const
174 {
175  return (patient == mActivePatientFolder);
176 }
177 
178 void SessionStorageServiceImpl::loadPatientSilent(QString choosenDir)
179 {
180  if (this->isActivePatient(choosenDir))
181  return;
182  this->clearPatientSilent();
183  if (choosenDir == QString::null)
184  return; // On cancel
185 
186  QString filename = QDir(choosenDir).absoluteFilePath(this->getXmlFileName());
187  QDomDocument doc = XmlFileHandler::readXmlFile(filename);
188  mActivePatientFolder = choosenDir; // must set path before emitting isLoading()
189 
190  if (!doc.isNull())
191  {
192  //Read the xml
193  QDomElement element = doc.documentElement();
194  emit isLoading(element);
195  emit isLoadingSecond(element);
196  }
197 
198  emit sessionChanged();
199 }
200 
204 void SessionStorageServiceImpl::writeRecentPatientData()
205 {
206  settings()->setValue("startup/lastPatient", mActivePatientFolder);
207  settings()->setValue("startup/lastPatientSaveTime", QDateTime::currentDateTime().toString(timestampSecondsFormat()));
208 }
209 
210 void SessionStorageServiceImpl::generateSaveDoc(QDomDocument& doc)
211 {
212  doc.appendChild(doc.createProcessingInstruction("xml version =", "'1.0'"));
213 
214  QDomElement patientNode = doc.createElement("patient");
215 
216  // note: all nodes must be below <patient>. XML requires only one root node per file.
217  QDomElement versionName = doc.createElement("version_name");
218  versionName.appendChild(doc.createTextNode(this->getVersionName()));
219  patientNode.appendChild(versionName);
220 
221  QDomElement activePatientNode = doc.createElement("active_patient");
222  activePatientNode.appendChild(doc.createTextNode(mActivePatientFolder.toStdString().c_str()));
223  patientNode.appendChild(activePatientNode);
224  doc.appendChild(patientNode);
225 }
226 
227 QString SessionStorageServiceImpl::convertToValidFolderName(QString dir) const
228 {
229  if (!dir.endsWith(".cx3"))
230  dir.append(".cx3");
231  return dir;
232 }
233 
234 void SessionStorageServiceImpl::createPatientFolders(QString dir)
235 {
236  QDir().mkpath(dir);
237  QDir().mkpath(dir+"/Images");
238  QDir().mkpath(dir+"/Logs");
239  QDir().mkpath(dir+"/US_Acq");
240 }
241 
242 QString SessionStorageServiceImpl::getVersionName()
243 {
244  return QString("%1").arg(CustusX_VERSION_STRING);
245 }
246 
247 void SessionStorageServiceImpl::clearCache()
248 {
249 // std::cout << "DataLocations::getCachePath() " << DataLocations::getCachePath() << std::endl;
250  // clear the global cache used by app
252 }
253 
257 QString SessionStorageServiceImpl::getCommandLineStartupPatient()
258 {
259  int doLoad = QApplication::arguments().indexOf("--load");
260  if (doLoad < 0)
261  return "";
262  if (doLoad + 1 >= QApplication::arguments().size())
263  return "";
264 
265  QString folder = QApplication::arguments()[doLoad + 1];
266 
267  return folder;
268 }
269 
272 void SessionStorageServiceImpl::startupLoadPatient()
273 {
274  QString folder = this->getCommandLineStartupPatient();
275 
276  if (!folder.isEmpty())
277  {
278  report(QString("Startup Load [%1] from command line").arg(folder));
279  }
280 
281  if (folder.isEmpty() && settings()->value("Automation/autoLoadRecentPatient").toBool())
282  {
283  folder = settings()->value("startup/lastPatient").toString();
284  if(this->isValidSessionFolder(folder))
285  {
286  QDateTime lastSaveTime = QDateTime::fromString(settings()->value("startup/lastPatientSaveTime").toString(), timestampSecondsFormat());
287  double minsSinceLastSave = lastSaveTime.secsTo(QDateTime::currentDateTime())/60;
288  double autoLoadRecentPatientWithinHours = settings()->value("Automation/autoLoadRecentPatientWithinHours").toDouble();
289  int allowedMinsSinceLastSave = autoLoadRecentPatientWithinHours*60;
290  if (minsSinceLastSave > allowedMinsSinceLastSave) // if less than 8 hours, accept
291  {
292  report(
293  QString("Startup Load: Ignored recent patient because %1 hours since last save, limit is %2")
294  .arg(int(minsSinceLastSave/60))
295  .arg(int(allowedMinsSinceLastSave/60)));
296  folder = "";
297  }
298  if (!folder.isEmpty())
299  report(QString("Startup Load [%1] as recent patient").arg(folder));
300  }
301  else
302  {
303  report("Startup Load: Ignored recent patient because it is not valid anymore");
304  folder = "";
305  }
306 
307  }
308 
309  if (folder.isEmpty())
310  return;
311 
312  this->load(folder);
313 }
314 
315 } // namespace cx
cxLogger.h
cx::removeNonemptyDirRecursively
bool removeNonemptyDirRecursively(const QString &dirName)
Definition: cxFileHelpers.cpp:70
cx::Settings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:66
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::SessionStorageServiceImpl::load
virtual void load(QString dir)
load session from dir, or create new session in this location if none exist
Definition: cxSessionStorageServiceImpl.cpp:51
cx::report
void report(QString msg)
Definition: cxLogger.cpp:69
cx::SessionStorageServiceImpl::~SessionStorageServiceImpl
virtual ~SessionStorageServiceImpl()
Definition: cxSessionStorageServiceImpl.cpp:41
cx::SessionStorageServiceImpl::save
virtual void save()
Save all application data to XML file.
Definition: cxSessionStorageServiceImpl.cpp:112
cx::XmlFileHandler::writeXmlFile
static void writeXmlFile(QDomDocument &doc, QString &filename)
Definition: cxXmlFileHandler.cpp:44
cxReporter.h
cx::reporter
ReporterPtr reporter()
Definition: cxReporter.cpp:36
cx::SessionStorageServiceImpl::isValid
virtual bool isValid() const
Definition: cxSessionStorageServiceImpl.cpp:136
cx::SessionStorageServiceImpl::getRootFolder
virtual QString getRootFolder() const
Definition: cxSessionStorageServiceImpl.cpp:142
OrderedQDomDocument::doc
QDomDocument & doc()
Definition: cxOrderedQDomDocument.h:43
cxSessionStorageServiceImpl.h
cxProfile.h
cx::DataLocations::getCachePath
static QString getCachePath()
return path to a folder that is used during execution, will be cleared at start and stop.
Definition: cxDataLocations.cpp:247
cxOrderedQDomDocument.h
cx::timestampSecondsFormat
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
cx::SessionStorageServiceImpl::clear
virtual void clear()
Definition: cxSessionStorageServiceImpl.cpp:129
cx::SessionStorageService::isSaving
void isSaving(QDomElement &root)
xml storage is available
cxSettings.h
cxFileHelpers.h
cxTime.h
cxDataLocations.h
cx::Settings::setValue
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:58
cx::SessionStorageService::getSubFolder
QString getSubFolder(QString relative)
return and create a folder/path relative to root. Created if necessary.
Definition: cxSessionStorageService.cpp:50
cx::SessionStorageService::isLoadingSecond
void isLoadingSecond(QDomElement &root)
Emitted after the isLoading signal, to allow for structures that must be loaded after core structures...
OrderedQDomDocument
Definition: cxOrderedQDomDocument.h:24
cx::SessionStorageService::isLoading
void isLoading(QDomElement &root)
emitted while loading a session. Xml storage is available, getRootFolder() is set to loaded value.
cx::reportError
void reportError(QString msg)
Definition: cxLogger.cpp:71
cx::XmlFileHandler::readXmlFile
static QDomDocument readXmlFile(QString &filename)
Definition: cxXmlFileHandler.cpp:22
cx::SessionStorageServiceImpl::isNull
virtual bool isNull() const
Definition: cxSessionStorageServiceImpl.cpp:46
cx::SessionStorageService::sessionChanged
void sessionChanged()
emitted after change to a new session (new or loaded or cleared)
cx::SessionStorageService::cleared
void cleared()
emitted when session is cleared, before isLoading is called
cx::SessionStorageServiceImpl::SessionStorageServiceImpl
SessionStorageServiceImpl(ctkPluginContext *context)
Definition: cxSessionStorageServiceImpl.cpp:32
cx::settings
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
cxXmlFileHandler.h