fb2read.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #include <QtGui>
  2. #include <QTextEdit>
  3. #include "fb2read.h"
  4. static QString Value(const QXmlAttributes &attributes, const QString &name)
  5. {
  6. int count = attributes.count();
  7. for (int i = 0; i < count; i++ ) {
  8. if (attributes.localName(i).compare(name, Qt::CaseInsensitive) == 0) {
  9. return attributes.value(i);
  10. }
  11. }
  12. return QString();
  13. }
  14. //---------------------------------------------------------------------------
  15. // Fb2Handler::RootHandler
  16. //---------------------------------------------------------------------------
  17. Fb2Handler::RootHandler::KeywordHash::KeywordHash()
  18. {
  19. insert("body", Body);
  20. insert("descriptin", Descr);
  21. insert("binary", Binary);
  22. }
  23. Fb2Handler::RootHandler::Keyword Fb2Handler::RootHandler::GetKeyword(const QString &name)
  24. {
  25. static KeywordHash map;
  26. KeywordHash::const_iterator i = map.find(name);
  27. return i == map.end() ? None : i.value();
  28. }
  29. bool Fb2Handler::RootHandler::DoStart(const QString &name, const QXmlAttributes &attributes)
  30. {
  31. switch (GetKeyword(name)) {
  32. case Descr : return m_owner.SetHandler(new DescrHandler(this));
  33. case Body : return m_owner.SetHandler(new BodyHandler(this));
  34. case Binary : return m_owner.SetHandler(new ImageHandler(this, attributes));
  35. }
  36. return false;
  37. }
  38. //---------------------------------------------------------------------------
  39. // Fb2Handler::DescrHandler
  40. //---------------------------------------------------------------------------
  41. bool Fb2Handler::DescrHandler::DoStart(const QString &name, const QXmlAttributes &attributes)
  42. {
  43. return true;
  44. }
  45. bool Fb2Handler::DescrHandler::DoText(const QString &text)
  46. {
  47. return true;
  48. }
  49. bool Fb2Handler::DescrHandler::DoEnd(const QString &name, bool & exit)
  50. {
  51. exit = name == "description";
  52. return true;
  53. }
  54. //---------------------------------------------------------------------------
  55. // Fb2Handler::BodyHandler
  56. //---------------------------------------------------------------------------
  57. Fb2Handler::BodyHandler::KeywordHash::KeywordHash()
  58. {
  59. insert("body", Body);
  60. insert("image", Image);
  61. insert("p", Paragraph);
  62. insert("section", Section);
  63. insert("title", Title);
  64. }
  65. Fb2Handler::BodyHandler::Keyword Fb2Handler::BodyHandler::GetKeyword(const QString &name)
  66. {
  67. static KeywordHash map;
  68. KeywordHash::const_iterator i = map.find(name);
  69. return i == map.end() ? None : i.value();
  70. }
  71. bool Fb2Handler::BodyHandler::DoStart(const QString &name, const QXmlAttributes &attributes)
  72. {
  73. switch (GetKeyword(name)) {
  74. case Image: {
  75. QString image = Value(attributes, "href");
  76. while (image.left(1) == "#") image.remove(0, 1);
  77. if (!image.isEmpty()) m_cursor.insertImage(image);
  78. } break;
  79. case Paragraph: {
  80. m_cursor.insertBlock();
  81. } break;
  82. case Section: {
  83. m_frames << m_cursor.currentFrame();
  84. QTextFrameFormat format;
  85. format.setBorder(1);
  86. format.setPadding(8);
  87. m_cursor.insertFrame(format);
  88. } break;
  89. }
  90. }
  91. bool Fb2Handler::BodyHandler::DoText(const QString &text)
  92. {
  93. m_cursor.insertText(text);
  94. return true;
  95. }
  96. bool Fb2Handler::BodyHandler::DoEnd(const QString &name, bool & exit)
  97. {
  98. switch (GetKeyword(name)) {
  99. case Body: {
  100. exit = true;
  101. }; break;
  102. case Section: {
  103. if (!m_frames.isEmpty()) {
  104. m_cursor.setPosition(m_frames.last()->lastPosition());
  105. m_frames.removeLast();
  106. }
  107. }; break;
  108. }
  109. return true;
  110. }
  111. //---------------------------------------------------------------------------
  112. // Fb2Handler::ImageHandler
  113. //---------------------------------------------------------------------------
  114. Fb2Handler::ImageHandler::ImageHandler(ContentHandler * parent, const QXmlAttributes &attributes)
  115. : ContentHandler(parent), m_name(Value(attributes, "id"))
  116. {
  117. }
  118. //---------------------------------------------------------------------------
  119. // Fb2Handler
  120. //---------------------------------------------------------------------------
  121. Fb2Handler::Fb2Handler(QTextEdit * editor)
  122. : m_editor(editor)
  123. , m_cursor(editor->textCursor())
  124. , m_section(None)
  125. , m_handler(NULL)
  126. {
  127. m_cursor.beginEditBlock();
  128. editor->clear();
  129. m_cursor.movePosition(QTextCursor::Start);
  130. }
  131. Fb2Handler::~Fb2Handler()
  132. {
  133. if (m_handler) delete m_handler;
  134. m_cursor.endEditBlock();
  135. }
  136. bool Fb2Handler::startElement(const QString & /* namespaceURI */,
  137. const QString & /* localName */,
  138. const QString &qName,
  139. const QXmlAttributes &attributes)
  140. {
  141. const QString name = qName.toLower();
  142. if (m_handler) return m_handler->DoStart(name, attributes);
  143. if (name == "fictionbook") {
  144. m_handler = new RootHandler(*this);
  145. return true;
  146. } else {
  147. m_error = QObject::tr("The file is not an FB2 file.");
  148. return false;
  149. }
  150. }
  151. bool Fb2Handler::characters(const QString &str)
  152. {
  153. return m_handler && m_handler->DoText(str);
  154. }
  155. Fb2Handler::ContentHandler * Fb2Handler::Up(Fb2Handler::ContentHandler * handler)
  156. {
  157. if (!handler) return NULL;
  158. ContentHandler * parent = handler->GetParent();
  159. delete handler;
  160. return parent;
  161. }
  162. bool Fb2Handler::endElement(const QString & /* namespaceURI */,
  163. const QString & /* localName */,
  164. const QString &qName)
  165. {
  166. bool exit = false;
  167. bool ok = m_handler && m_handler->DoEnd(qName.toLower(), exit);
  168. if (exit) m_handler = Up(m_handler);
  169. return ok;
  170. }
  171. bool Fb2Handler::fatalError(const QXmlParseException &exception)
  172. {
  173. QMessageBox::information(
  174. m_editor->window(),
  175. QObject::tr("fb2edit"),
  176. QObject::tr("Parse error at line %1, column %2:\n%3")
  177. .arg(exception.lineNumber())
  178. .arg(exception.columnNumber())
  179. .arg(exception.message())
  180. );
  181. return false;
  182. }
  183. QString Fb2Handler::errorString() const
  184. {
  185. return m_error;
  186. }
  187. /*
  188. QMessageBox::information(
  189. m_editor->window(),
  190. QObject::tr("fb2edit"),
  191. QObject::tr("%1=%2\n%1=%3")
  192. .arg(attributes.localName(i))
  193. .arg(attributes.value(i))
  194. .arg(image)
  195. );
  196. //! [2]
  197. QTextCursor cursor(editor->textCursor());
  198. cursor.movePosition(QTextCursor::Start);
  199. //! [2] //! [3]
  200. QTextFrame *topFrame = cursor.currentFrame();
  201. QTextFrameFormat topFrameFormat = topFrame->frameFormat();
  202. topFrameFormat.setPadding(16);
  203. topFrame->setFrameFormat(topFrameFormat);
  204. QTextCharFormat textFormat;
  205. QTextCharFormat boldFormat;
  206. boldFormat.setFontWeight(QFont::Bold);
  207. QTextFrameFormat referenceFrameFormat;
  208. referenceFrameFormat.setBorder(1);
  209. referenceFrameFormat.setPadding(8);
  210. referenceFrameFormat.setPosition(QTextFrameFormat::FloatRight);
  211. referenceFrameFormat.setWidth(QTextLength(QTextLength::PercentageLength, 40));
  212. cursor.insertFrame(referenceFrameFormat);
  213. cursor.insertText("A company", boldFormat);
  214. cursor.insertBlock();
  215. cursor.insertText("321 City Street");
  216. cursor.insertBlock();
  217. cursor.insertText("Industry Park");
  218. cursor.insertBlock();
  219. cursor.insertText("Another country");
  220. //! [3]
  221. //! [4]
  222. cursor.setPosition(topFrame->lastPosition());
  223. cursor.insertText(name, textFormat);
  224. QString line;
  225. foreach (line, address.split("\n")) {
  226. cursor.insertBlock();
  227. cursor.insertText(line);
  228. }
  229. //! [4] //! [5]
  230. cursor.insertBlock();
  231. cursor.insertBlock();
  232. QDate date = QDate::currentDate();
  233. cursor.insertText(tr("Date: %1").arg(date.toString("d MMMM yyyy")),
  234. textFormat);
  235. cursor.insertBlock();
  236. QTextFrameFormat bodyFrameFormat;
  237. bodyFrameFormat.setWidth(QTextLength(QTextLength::PercentageLength, 100));
  238. cursor.insertFrame(bodyFrameFormat);
  239. //! [5]
  240. //! [6]
  241. cursor.insertText(tr("I would like to place an order for the following "
  242. "items:"), textFormat);
  243. cursor.insertBlock();
  244. //! [6] //! [7]
  245. cursor.insertBlock();
  246. //! [7]
  247. //! [8]
  248. QTextTableFormat orderTableFormat;
  249. orderTableFormat.setAlignment(Qt::AlignHCenter);
  250. QTextTable *orderTable = cursor.insertTable(1, 2, orderTableFormat);
  251. QTextFrameFormat orderFrameFormat = cursor.currentFrame()->frameFormat();
  252. orderFrameFormat.setBorder(1);
  253. cursor.currentFrame()->setFrameFormat(orderFrameFormat);
  254. //! [8]
  255. //! [9]
  256. cursor = orderTable->cellAt(0, 0).firstCursorPosition();
  257. cursor.insertText(tr("Product"), boldFormat);
  258. cursor = orderTable->cellAt(0, 1).firstCursorPosition();
  259. cursor.insertText(tr("Quantity"), boldFormat);
  260. //! [9]
  261. //! [10]
  262. for (int i = 0; i < orderItems.count(); ++i) {
  263. QPair<QString,int> item = orderItems[i];
  264. int row = orderTable->rows();
  265. orderTable->insertRows(row, 1);
  266. cursor = orderTable->cellAt(row, 0).firstCursorPosition();
  267. cursor.insertText(item.first, textFormat);
  268. cursor = orderTable->cellAt(row, 1).firstCursorPosition();
  269. cursor.insertText(QString("%1").arg(item.second), textFormat);
  270. }
  271. //! [10]
  272. //! [11]
  273. cursor.setPosition(topFrame->lastPosition());
  274. cursor.insertBlock();
  275. //! [11] //! [12]
  276. cursor.insertText(tr("Please update my records to take account of the "
  277. "following privacy information:"));
  278. cursor.insertBlock();
  279. //! [12]
  280. //! [13]
  281. QTextTable *offersTable = cursor.insertTable(2, 2);
  282. cursor = offersTable->cellAt(0, 1).firstCursorPosition();
  283. cursor.insertText(tr("I want to receive more information about your "
  284. "company's products and special offers."), textFormat);
  285. cursor = offersTable->cellAt(1, 1).firstCursorPosition();
  286. cursor.insertText(tr("I do not want to receive any promotional information "
  287. "from your company."), textFormat);
  288. if (sendOffers)
  289. cursor = offersTable->cellAt(0, 0).firstCursorPosition();
  290. else
  291. cursor = offersTable->cellAt(1, 0).firstCursorPosition();
  292. cursor.insertText("X", boldFormat);
  293. //! [13]
  294. //! [14]
  295. cursor.setPosition(topFrame->lastPosition());
  296. cursor.insertBlock();
  297. cursor.insertText(tr("Sincerely,"), textFormat);
  298. cursor.insertBlock();
  299. cursor.insertBlock();
  300. cursor.insertBlock();
  301. cursor.insertText(name);
  302. printAction->setEnabled(true);
  303. }
  304. //! [14]
  305. */