NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxXmlOptionItem.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 
12 
13 /*
14  * sscXmlOptionItem.cpp
15  *
16  * Created on: May 28, 2010
17  * Author: christiana
18  */
19 #include "cxXmlOptionItem.h"
20 
21 #include <map>
22 #include <iostream>
23 #include <QFile>
24 #include <QDir>
25 #include <QFileInfo>
26 #include <QTextStream>
27 #include <QDomElement>
28 #include <QDataStream>
29 #include <QStringList>
30 #include <QMutex>
31 #include <QBuffer>
32 #include "cxLogger.h"
33 #include "cxTypeConversions.h"
34 
35 namespace cx
36 {
37 
42 {
43 public:
45  {
46  if (!mInstance)
47  mInstance = new SharedDocuments();
48  return mInstance;
49  }
50 
54  QDomDocument loadDocument(const QString& filename)
55  {
56  QDomDocument retval;
57  retval = this->getDocument(filename);
58  if (retval.isNull())
59  {
60  retval = this->readFromFile(filename);
61  this->addDocument(filename, retval);
62  }
63  return retval;
64  }
65 
66 private:
67  SharedDocuments() : mDocumentMutex(QMutex::Recursive) {}
68 
69  QDomDocument getDocument(const QString& filename)
70  {
71  QMutexLocker lock(&mDocumentMutex);
72  DocumentMap::iterator iter = mDocuments.find(filename);
73  // if filename found, attempt to retrieve document from node.
74  if (iter != mDocuments.end())
75  {
76  return iter->second.ownerDocument();
77  }
78  return QDomDocument(); // null node
79  }
80 
81  void addDocument(const QString& filename, QDomDocument document)
82  {
83  QMutexLocker lock(&mDocumentMutex);
84  mDocuments[filename] = document.documentElement();
85  }
86 
87  QDomDocument readFromFile(QString filename)
88  {
89  QFile file(filename);
90  if (!file.open(QIODevice::ReadOnly))
91  {
92  QDomDocument doc;
93  doc.appendChild(doc.createElement("root"));
94  return doc;
95  }
96 
97  QDomDocument loadedDoc;
98  QString error;
99  int line, col;
100  if (!loadedDoc.setContent(&file, &error, &line, &col))
101  {
102  QString msg = QString("error setting xml content [%1,%2] %3").arg(line).arg(col).arg(error);
103  reportWarning(msg);
104  }
105  file.close();
106  return loadedDoc;
107  }
108 
109  static SharedDocuments* mInstance;
110  typedef std::map<QString, QDomElement> DocumentMap;
111  QMutex mDocumentMutex;
112  DocumentMap mDocuments;
113 };
115 SharedDocuments* SharedDocuments::mInstance = NULL;
117 
121 
122 QString XmlOptionItem::SerializeDataToB64String(const QVariant& data)
123 {
124  QByteArray byteArray;
125  QBuffer writeBuffer(&byteArray);
126  writeBuffer.open(QIODevice::WriteOnly);
127  QDataStream out(&writeBuffer);
128 
129  out << data;
130 
131  writeBuffer.close();
132 
133  QString s = QString(byteArray.toBase64());
134 
135 // qDebug() << "array size when written:" << byteArray.size();
136 
137  return s;
138 }
139 
140 
141 QVariant XmlOptionItem::DeserializeB64String(const QString& serializedVariant)
142 {
143  QByteArray readArr = QByteArray::fromBase64(serializedVariant.toUtf8());
144  QBuffer readBuffer(&readArr);
145  readBuffer.open(QIODevice::ReadOnly);
146  QDataStream in(&readBuffer);
147 
148  QVariant data;
149 
150  in >> data;
151 
152 // qDebug() << "array size when read:" << readArr.size();
153 
154  return data;
155 }
156 
157 XmlOptionItem::XmlOptionItem(const QString& uid, QDomElement root) :
158  mUid(uid), mRoot(root)
159 {
160 
161 }
162 
163 QVariant XmlOptionItem::readVariant(const QVariant& defval) const
164 {
165  QString text = this->readValue("");
166  if (text.isEmpty())
167  return defval;
168  QVariant val = DeserializeB64String(text);
169  return val;
170 }
171 
172 void XmlOptionItem::writeVariant(const QVariant& val)
173 {
174  QString text = SerializeDataToB64String(val);
175  this->writeValue(text);
176 }
177 
178 QString XmlOptionItem::readValue(const QString& defval) const
179 {
180  // read value is present
181  QDomElement item = this->findElemFromUid(mUid, mRoot);
182  if (!item.isNull() && item.hasAttribute("value"))
183  {
184  return item.attribute("value");
185  }
186  return defval;
187 }
188 
189 void XmlOptionItem::writeValue(const QString& val)
190 {
191  if (mRoot.isNull())
192  return;
193  QDomElement item = findElemFromUid(mUid, mRoot);
194  // create option if not present
195  if (item.isNull())
196  {
197  item = mRoot.ownerDocument().createElement("option");
198  item.setAttribute("id", mUid);
199  mRoot.appendChild(item);
200  }
201  item.setAttribute("value", val);
202 }
203 
204 QDomElement XmlOptionItem::findElemFromUid(const QString& uid, QDomNode root) const
205 {
206  QDomNodeList settings = root.childNodes();
207  for (int i = 0; i < settings.size(); ++i)
208  {
209  QDomElement item = settings.item(i).toElement();
210  if (item.attribute("id") == uid)
211  return item;
212  }
213  return QDomElement();
214 }
215 
219 
221 {
222  XmlOptionFile retval;
223  retval.mDocument = QDomDocument();
224  retval.mCurrentElement = QDomElement();
225  return retval;
226 }
227 
229 {
230  mDocument.appendChild(mDocument.createElement("root"));
231  mCurrentElement = mDocument.documentElement();
232 }
233 
234 XmlOptionFile::XmlOptionFile(QString filename) :
235  mFilename(filename)
236 {
237  mDocument = SharedDocuments::getInstance()->loadDocument(filename);
238 
239  mCurrentElement = mDocument.documentElement();
240 
241  if (mCurrentElement.isNull())
242  {
243  mDocument.appendChild(mDocument.createElement("root"));
244  mCurrentElement = mDocument.documentElement();
245  }
246 }
247 
249 {
250 }
251 
253 {
254  return mFilename;
255 }
256 
258 {
259  if(mCurrentElement.isNull() || mDocument.isNull())
260  return true;
261  return false;
262 }
263 
265 {
266  XmlOptionFile retval = *this;
267  retval.mCurrentElement = mDocument.documentElement();
268  return retval;
269 }
270 
271 XmlOptionFile XmlOptionFile::descend(QString element) const
272 {
273  XmlOptionFile retval = *this;
274  retval.mCurrentElement = retval.getElement(element);
275  return retval;
276 }
277 
278 XmlOptionFile XmlOptionFile::descend(QString element, QString attributeName, QString attributeValue) const
279 {
280  XmlOptionFile retval = this->tryDescend(element, attributeName, attributeValue);
281  if (!retval.getDocument().isNull())
282  return retval;
283 
284  // create a new element if not found
285  retval = *this;
286  QDomElement current = retval.getDocument().createElement(element);
287  current.setAttribute(attributeName, attributeValue);
288  retval.mCurrentElement.appendChild(current);
289  retval.mCurrentElement = current;
290  return retval;
291 }
292 
293 XmlOptionFile XmlOptionFile::tryDescend(QString element, QString attributeName, QString attributeValue) const
294 {
295  XmlOptionFile retval = *this;
296 
297  QDomNodeList presetNodeList = retval.getElement().elementsByTagName(element);
298  for (int i = 0; i < presetNodeList.count(); ++i)
299  {
300  QDomElement current = presetNodeList.item(i).toElement();
301  QString name = current.attribute(attributeName);
302  if (attributeValue == name)
303  {
304  retval.mCurrentElement = current;
305  return retval;
306  }
307  }
308 
309  return XmlOptionFile::createNull();
310 }
311 
313 {
314  XmlOptionFile retval = *this;
315  retval.mCurrentElement = mCurrentElement.parentNode().toElement();
316  if (retval.mCurrentElement.isNull())
317  return *this;
318  return retval;
319 }
320 
323 QDomElement XmlOptionFile::safeGetElement(QDomElement parent, QString childName)
324 {
325  QDomElement child = parent.namedItem(childName).toElement();
326 
327  if (child.isNull())
328  {
329  child = mDocument.createElement(childName);
330  parent.appendChild(child);
331  }
332 
333  return child;
334 }
335 
337 {
338  printDocument(mDocument);
339 }
340 
342 {
343  printElement(mCurrentElement);
344 }
345 
346 void XmlOptionFile::printDocument(QDomDocument document)
347 {
348  QTextStream stream(stdout);
349  stream << "\nTEST" << document.toString(4) << "\n";
350 }
351 
352 void XmlOptionFile::printElement(QDomElement element)
353 {
354  QTextStream stream(stdout);
355  stream << "\n";
356  element.save(stream, 4);
357  stream << "\n";
358 }
359 
361 {
362  return mDocument;
363 }
364 
366 {
367  return mCurrentElement;
368 }
369 
370 QDomElement XmlOptionFile::getElement(QString level1)
371 {
372  QDomElement elem1 = this->safeGetElement(mCurrentElement, level1);
373  return elem1;
374 }
375 
376 QDomElement XmlOptionFile::getElement(QString level1, QString level2)
377 {
378  QDomElement elem1 = this->safeGetElement(mCurrentElement, level1);
379  QDomElement elem2 = this->safeGetElement(elem1, level2);
380  return elem2;
381 }
382 
384 {
385  while (mCurrentElement.hasChildNodes())
386  mCurrentElement.removeChild(mCurrentElement.firstChild());
387 }
388 
390 {
391  QDomNode parentNode = mCurrentElement.parentNode();
392  parentNode.removeChild(mCurrentElement);
393  mCurrentElement = QDomElement();// Create null element
394 }
395 
397 {
398  if (mFilename.isEmpty())
399  {
400  reportWarning("XmlOptionFile::save() No file name");
401  return; //Don't do anything if on filename isn't supplied
402  }
403 
404  QString path = QFileInfo(mFilename).absolutePath();
405  QDir().mkpath(path);
406  QFile file(mFilename);
407  if (file.open(QIODevice::WriteOnly | QIODevice::Truncate))
408  {
409  QTextStream stream(&file);
410  stream << mDocument.toString(4);
411  file.close();
412 // report("Created " + file.fileName());
413  }
414  else
415  {
416  reportError("XmlOptionFile::save() Could not open " + file.fileName() + " Error: "
417  + file.errorString());
418  }
419 }
420 
421 
422 } // namespace cx
cx::XmlOptionFile
Helper class for xml files used to store ssc/cx data.
Definition: cxXmlOptionItem.h:78
cx::XmlOptionFile::printDocument
void printDocument()
print the entire document
Definition: cxXmlOptionItem.cpp:336
cx::XmlOptionItem::writeVariant
void writeVariant(const QVariant &val)
Definition: cxXmlOptionItem.cpp:172
cx::XmlOptionFile::printElement
void printElement()
print just the current element
Definition: cxXmlOptionItem.cpp:341
cxLogger.h
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::XmlOptionFile::XmlOptionFile
XmlOptionFile()
Definition: cxXmlOptionItem.cpp:228
cx::XmlOptionFile::save
void save()
save entire document.
Definition: cxXmlOptionItem.cpp:396
cxXmlOptionItem.h
cx::XmlOptionFile::descend
XmlOptionFile descend(QString element) const
step one level down in the xml tree
Definition: cxXmlOptionItem.cpp:271
cx::XmlOptionFile::deleteNode
void deleteNode()
Delete the current node.
Definition: cxXmlOptionItem.cpp:389
cx::XmlOptionFile::safeGetElement
QDomElement safeGetElement(QDomElement parent, QString childName)
Definition: cxXmlOptionItem.cpp:323
cx::XmlOptionFile::root
XmlOptionFile root() const
set the current element to root
Definition: cxXmlOptionItem.cpp:264
cx::XmlOptionItem::readVariant
QVariant readVariant(const QVariant &defval=QVariant()) const
Definition: cxXmlOptionItem.cpp:163
cx::XmlOptionFile::getElement
QDomElement getElement()
return the current element
Definition: cxXmlOptionItem.cpp:365
cxTypeConversions.h
cx::XmlOptionItem::XmlOptionItem
XmlOptionItem()
Definition: cxXmlOptionItem.h:41
cx::XmlOptionFile::removeChildren
void removeChildren()
remove all child nodes of the current element.
Definition: cxXmlOptionItem.cpp:383
cx::XmlOptionFile::getFileName
QString getFileName()
Definition: cxXmlOptionItem.cpp:252
cx::XmlOptionItem::readValue
QString readValue(const QString &defval) const
Definition: cxXmlOptionItem.cpp:178
cx::XmlOptionFile::tryDescend
XmlOptionFile tryDescend(QString element, QString attributeName, QString attributeValue) const
Definition: cxXmlOptionItem.cpp:293
cx::SharedDocuments::getInstance
static SharedDocuments * getInstance()
Definition: cxXmlOptionItem.cpp:44
cx::XmlOptionItem::writeValue
void writeValue(const QString &val)
Definition: cxXmlOptionItem.cpp:189
cx::XmlOptionFile::createNull
static XmlOptionFile createNull()
create an empty document
Definition: cxXmlOptionItem.cpp:220
cx::reportError
void reportError(QString msg)
Definition: cxLogger.cpp:71
cx::SharedDocuments::loadDocument
QDomDocument loadDocument(const QString &filename)
Definition: cxXmlOptionItem.cpp:54
cx::XmlOptionFile::getDocument
QDomDocument getDocument()
returns the document
Definition: cxXmlOptionItem.cpp:360
cx::XmlOptionFile::ascend
XmlOptionFile ascend() const
step one level up in the xml tree
Definition: cxXmlOptionItem.cpp:312
cx::XmlOptionFile::isNull
bool isNull() const
checks if this is null
Definition: cxXmlOptionItem.cpp:257
cx::XmlOptionFile::~XmlOptionFile
~XmlOptionFile()
Definition: cxXmlOptionItem.cpp:248
cx::reportWarning
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
cx::settings
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
cx::SharedDocuments
Definition: cxXmlOptionItem.cpp:41