ctkCmdLineModuleXmlProgressWatcher.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*===================================================================
  2. BlueBerry Platform
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics.
  5. All rights reserved.
  6. This software is distributed WITHOUT ANY WARRANTY; without
  7. even the implied warranty of MERCHANTABILITY or FITNESS FOR
  8. A PARTICULAR PURPOSE.
  9. See LICENSE.txt or http://www.mitk.org for details.
  10. ===================================================================*/
  11. #include "ctkCmdLineModuleXmlProgressWatcher.h"
  12. #include <QIODevice>
  13. #include <QXmlStreamReader>
  14. #include <QDebug>
  15. namespace {
  16. static QString FILTER_START = "filter-start";
  17. static QString FILTER_NAME = "filter-name";
  18. static QString FILTER_COMMENT = "filter-comment";
  19. static QString FILTER_PROGRESS = "filter-progress";
  20. static QString FILTER_END = "filter-end";
  21. }
  22. class ctkCmdLineModuleXmlProgressWatcherPrivate
  23. {
  24. public:
  25. ctkCmdLineModuleXmlProgressWatcherPrivate(QIODevice* input, ctkCmdLineModuleXmlProgressWatcher* qq)
  26. : input(input), readPos(0), q(qq), error(false), currentProgress(0)
  27. {
  28. // wrap the content in an artifical root element
  29. reader.addData("<module-root>");
  30. }
  31. void _q_readyRead()
  32. {
  33. input->seek(readPos);
  34. reader.addData(input->readAll());
  35. readPos = input->pos();
  36. parseProgressXml();
  37. }
  38. void parseProgressXml()
  39. {
  40. QXmlStreamReader::TokenType type = reader.readNext();
  41. while(type != QXmlStreamReader::Invalid)
  42. {
  43. switch(type)
  44. {
  45. case QXmlStreamReader::NoToken: break;
  46. case QXmlStreamReader::Characters:
  47. {
  48. if (stack.empty()) break;
  49. if (stack.size() == 2 && stack.front() == FILTER_START)
  50. {
  51. if (stack.back() == FILTER_NAME)
  52. {
  53. currentName = reader.text().toString().trimmed();
  54. }
  55. else if (stack.back() == FILTER_COMMENT)
  56. {
  57. currentComment = reader.text().toString().trimmed();
  58. }
  59. }
  60. else if (stack.size() == 1 && stack.back() == FILTER_PROGRESS)
  61. {
  62. currentProgress = reader.text().toString().toFloat();
  63. }
  64. break;
  65. }
  66. case QXmlStreamReader::StartElement:
  67. {
  68. QStringRef name = reader.name();
  69. QString parent;
  70. if (!stack.empty()) parent = stack.back();
  71. if (name.compare("module-root") != 0)
  72. {
  73. stack.push_back(name.toString());
  74. }
  75. if (name.compare(FILTER_START, Qt::CaseInsensitive) == 0 ||
  76. name.compare(FILTER_PROGRESS, Qt::CaseInsensitive) == 0 ||
  77. name.compare(FILTER_END, Qt::CaseInsensitive) == 0)
  78. {
  79. if (!parent.isEmpty())
  80. {
  81. unexpectedNestedElement(name.toString());
  82. break;
  83. }
  84. if (name.compare(FILTER_START, Qt::CaseInsensitive) == 0)
  85. {
  86. currentName.clear();
  87. currentComment.clear();
  88. currentProgress = 0;
  89. }
  90. }
  91. break;
  92. }
  93. case QXmlStreamReader::EndElement:
  94. {
  95. QStringRef name = reader.name();
  96. QString curr;
  97. QString parent;
  98. if (!stack.empty())
  99. {
  100. curr = stack.back();
  101. stack.pop_back();
  102. if (!stack.empty()) parent = stack.back();
  103. }
  104. if (parent.isEmpty())
  105. {
  106. if (name.compare(FILTER_START, Qt::CaseInsensitive) == 0)
  107. {
  108. emit q->filterStarted(currentName, currentComment);
  109. }
  110. else if (name.compare(FILTER_PROGRESS, Qt::CaseInsensitive) == 0)
  111. {
  112. emit q->filterProgress(currentProgress);
  113. }
  114. else if (name.compare(FILTER_END, Qt::CaseInsensitive) == 0)
  115. {
  116. emit q->filterFinished(currentName);
  117. }
  118. }
  119. break;
  120. }
  121. default:
  122. break;
  123. }
  124. type = reader.readNext();
  125. }
  126. if (type == QXmlStreamReader::Invalid && reader.error() != QXmlStreamReader::PrematureEndOfDocumentError)
  127. {
  128. if (!error)
  129. {
  130. error = true;
  131. emit q->filterXmlError(QString("Error parsing XML at line %1, column %2: ")
  132. .arg(reader.lineNumber()).arg(reader.columnNumber()) + reader.errorString());
  133. }
  134. }
  135. }
  136. void unexpectedNestedElement(const QString& element)
  137. {
  138. if (!error)
  139. {
  140. error = true;
  141. emit q->filterXmlError(QString("\"%1\" must be a top-level element, found at line %2.")
  142. .arg(element).arg(reader.lineNumber()));
  143. }
  144. }
  145. QIODevice* input;
  146. qint64 readPos;
  147. ctkCmdLineModuleXmlProgressWatcher* q;
  148. bool error;
  149. QXmlStreamReader reader;
  150. QList<QString> stack;
  151. QString currentName;
  152. QString currentComment;
  153. float currentProgress;
  154. };
  155. ctkCmdLineModuleXmlProgressWatcher::ctkCmdLineModuleXmlProgressWatcher(QIODevice* input)
  156. : d(new ctkCmdLineModuleXmlProgressWatcherPrivate(input, this))
  157. {
  158. if (d->input == NULL) return;
  159. if (!(d->input->openMode() & QIODevice::ReadOnly))
  160. {
  161. input->open(QIODevice::ReadOnly);
  162. }
  163. connect(d->input, SIGNAL(readyRead()), SLOT(_q_readyRead()));
  164. }
  165. ctkCmdLineModuleXmlProgressWatcher::~ctkCmdLineModuleXmlProgressWatcher()
  166. {
  167. }
  168. #include "moc_ctkCmdLineModuleXmlProgressWatcher.cxx"