Bibletime – a bible study tool
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cinfodisplay.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. //
  2. // C++ Implementation: cinfodisplay
  3. //
  4. // Description:
  5. //
  6. //
  7. // Author: The BibleTime team <info@bibletime.info>, (C) 2004
  8. //
  9. // Copyright: See COPYING file that comes with this distribution
  10. //
  11. //
  12. //BibleTime includes
  13. #include "cinfodisplay.h"
  14. #include "backend/cswordmoduleinfo.h"
  15. #include "backend/cswordkey.h"
  16. #include "backend/cswordversekey.h"
  17. #include "backend/creferencemanager.h"
  18. #include "backend/cdisplaytemplatemgr.h"
  19. #include "frontend/cbtconfig.h"
  20. #include "frontend/crossrefrendering.h"
  21. #include "frontend/display/cdisplay.h"
  22. #include "frontend/display/creaddisplay.h"
  23. #include "frontend/display/chtmlreaddisplay.h"
  24. #include "util/scoped_resource.h"
  25. //Sword includes
  26. #include <listkey.h>
  27. //TQt includes
  28. #include <tqlayout.h>
  29. #include <tqlabel.h>
  30. #include <tqscrollview.h>
  31. #include <tqregexp.h>
  32. //KDE includes
  33. #include <tdelocale.h>
  34. #include <kstdaction.h>
  35. using namespace Rendering;
  36. using namespace sword;
  37. namespace InfoDisplay {
  38. CInfoDisplay::CInfoDisplay(TQWidget *parent, const char *name)
  39. : TQWidget(parent, name) {
  40. TQVBoxLayout* layout = new TQVBoxLayout(this);
  41. TQLabel* headingLabel = new TQLabel(i18n("Mag (\"shift\" to lock)"),this);
  42. headingLabel->setMargin(5);
  43. m_htmlPart = CDisplay::createReadInstance(0, this);
  44. m_htmlPart->setMouseTracking(false); //we don't want strong/lemma/note mouse infos
  45. KStdAction::copy(m_htmlPart->connectionsProxy(), TQT_SLOT(copySelection()), 0, "copyMagSelection");
  46. connect(
  47. m_htmlPart->connectionsProxy(),
  48. TQT_SIGNAL(referenceClicked(const TQString&, const TQString&)),
  49. TQT_SLOT(lookup(const TQString&, const TQString&))
  50. );
  51. layout->addWidget(headingLabel);
  52. layout->addWidget(m_htmlPart->view());
  53. }
  54. CInfoDisplay::~CInfoDisplay() {}
  55. void CInfoDisplay::lookup(const TQString &mod_name, const TQString &key_text) {
  56. tqWarning("%s %s", mod_name.ascii(), key_text.ascii());
  57. CSwordModuleInfo* m = CPointers::backend()->findModuleByName(mod_name);
  58. Q_ASSERT(m);
  59. if (!m)
  60. return;
  61. util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(m) );
  62. key->key( key_text );
  63. CDisplayTemplateMgr* mgr = CPointers::displayTemplateManager();
  64. CDisplayTemplateMgr::Settings settings;
  65. settings.pageCSS_ID = "infodisplay";
  66. // settings.langAbbrev = "";
  67. TQString content = mgr->fillTemplate(CBTConfig::get
  68. (CBTConfig::displayStyle), key->renderedText(), settings);
  69. // tqWarning("setting text:\n%s", content.latin1());
  70. m_htmlPart->setText(content); // scroll to top
  71. CHTMLReadDisplay *d = dynamic_cast<CHTMLReadDisplay *>(m_htmlPart);
  72. d->view()->ensureVisible(0, 0);
  73. }
  74. void CInfoDisplay::setInfo(const InfoType type, const TQString& data) {
  75. ListInfoData list;
  76. list.append( tqMakePair(type, data) );
  77. setInfo(list);
  78. }
  79. void CInfoDisplay::setInfo(const ListInfoData& list) {
  80. //if the widget is hidden it would be inefficient to render and display the data
  81. if (!isVisible()) {
  82. return;
  83. }
  84. if (list.count() == 0) {
  85. m_htmlPart->setText("<html></html>");
  86. return;
  87. }
  88. TQString text;
  89. ListInfoData::const_iterator end = list.end();
  90. for (ListInfoData::const_iterator it = list.begin(); it != end; ++it) {
  91. switch ( (*it).first ) {
  92. case Lemma:
  93. text.append( decodeStrongs( (*it).second ) );
  94. continue;
  95. case Morph:
  96. text.append( decodeMorph( (*it).second ) );
  97. continue;
  98. case CrossReference:
  99. text.append( decodeCrossReference( (*it).second ) );
  100. continue;
  101. case Footnote:
  102. text.append( decodeFootnote( (*it).second ) );
  103. continue;
  104. case WordTranslation:
  105. text.append( getWordTranslation( (*it).second ) );
  106. continue;
  107. case WordGloss:
  108. //text.append( getWordTranslation( (*it).second ) );
  109. continue;
  110. case Abbreviation:
  111. text.append( decodeAbbreviation( (*it).second ) );
  112. continue;
  113. default:
  114. continue;
  115. };
  116. }
  117. CDisplayTemplateMgr* mgr = CPointers::displayTemplateManager();
  118. CDisplayTemplateMgr::Settings settings;
  119. settings.pageCSS_ID = "infodisplay";
  120. // settings.langAbbrev = "";
  121. TQString content = mgr->fillTemplate(CBTConfig::get
  122. (CBTConfig::displayStyle), text, settings);
  123. // tqWarning("setting text:\n%s", content.latin1());
  124. m_htmlPart->setText(content);
  125. }
  126. const TQString CInfoDisplay::decodeAbbreviation( const TQString& data ) {
  127. // TQStringList strongs = TQStringList::split("|", data);
  128. TQString ret;
  129. TQString text = data;
  130. ret.append(
  131. TQString("<div class=\"abbreviation\"><h3>%1: %2</h3><p>%3</p></div>")
  132. .arg(i18n("Abbreviation"))
  133. .arg("text")
  134. .arg(text));
  135. return ret;
  136. }
  137. const TQString CInfoDisplay::decodeCrossReference( const TQString& data ) {
  138. Q_ASSERT(!data.isEmpty());
  139. if (data.isEmpty()) {
  140. return TQString("<div class=\"crossrefinfo\"><h3>%1</h3></div>")
  141. .arg(i18n("Cross references"));
  142. }
  143. // tqWarning("setting crossref %s", data.latin1());
  144. CSwordBackend::DisplayOptions dispOpts;
  145. dispOpts.lineBreaks = false;
  146. dispOpts.verseNumbers = true;
  147. CSwordBackend::FilterOptions filterOpts;
  148. filterOpts.headings = false;
  149. filterOpts.strongNumbers = false;
  150. filterOpts.morphTags = false;
  151. filterOpts.lemmas = false;
  152. filterOpts.footnotes = false;
  153. filterOpts.scriptureReferences = false;
  154. CrossRefRendering renderer(dispOpts, filterOpts);
  155. CTextRendering::KeyTree tree;
  156. // const bool isBible = true;
  157. CSwordModuleInfo* module = CBTConfig::get
  158. (CBTConfig::standardBible);
  159. //a prefixed module gives the module to look into
  160. TQRegExp re("^[^ ]+:");
  161. // re.setMinimal(true);
  162. int pos = re.search(data,0);
  163. if (pos != -1) {
  164. pos += re.matchedLength()-1;
  165. }
  166. if (pos > 0) {
  167. const TQString moduleName = data.left(pos);
  168. // tqWarning("found module %s", moduleName.latin1());
  169. module = CPointers::backend()->findModuleByName(moduleName);
  170. if (!module) {
  171. module = CBTConfig::get
  172. (CBTConfig::standardBible);
  173. }
  174. // Q_ASSERT(module);
  175. }
  176. Q_ASSERT(module);
  177. CTextRendering::KeyTreeItem::Settings settings (
  178. false,
  179. CTextRendering::KeyTreeItem::Settings::CompleteShort
  180. );
  181. if (module && (module->type() == CSwordModuleInfo::Bible)) {
  182. VerseKey vk;
  183. sword::ListKey refs = vk.ParseVerseList((const char*)data.mid((pos == -1) ? 0 : pos+1).utf8(), "Gen 1:1", true);
  184. for (int j = 0; j < refs.Count(); ++j) {
  185. SWKey* key = refs.getElement(j);
  186. Q_ASSERT(key);
  187. VerseKey* vk = dynamic_cast<VerseKey*>(key);
  188. CTextRendering::KeyTreeItem* i = 0;
  189. if (vk && vk->isBoundSet()) { //render a range of keys
  190. i = new CTextRendering::KeyTreeItem(
  191. TQString::fromUtf8(vk->LowerBound().getText()),
  192. TQString::fromUtf8(vk->UpperBound().getText()),
  193. module,
  194. settings
  195. );
  196. }
  197. else {
  198. i = new CTextRendering::KeyTreeItem(
  199. TQString::fromUtf8(key->getText()),
  200. TQString::fromUtf8(key->getText()),
  201. module,
  202. settings
  203. );
  204. }
  205. Q_ASSERT(i);
  206. tree.append( i );
  207. }
  208. }
  209. else if (module) {
  210. CTextRendering::KeyTreeItem* i = new CTextRendering::KeyTreeItem(
  211. data.mid((pos == -1) ? 0 : pos+1),
  212. module,
  213. settings
  214. );
  215. tree.append( i );
  216. }
  217. // tqWarning("rendered the tree: %s", renderer.renderKeyTree(tree).latin1());
  218. //spanns containing rtl text need dir=rtl on their parent tag to be aligned properly
  219. return TQString("<div class=\"crossrefinfo\"><h3>%1</h3><div class=\"para\" dir=\"%2\">%3</div></div>")
  220. .arg(i18n("Cross references"))
  221. .arg(module ? ((module->textDirection() == CSwordModuleInfo::LeftToRight) ? "ltr" : "rtl") : "")
  222. .arg(renderer.renderKeyTree(tree));
  223. }
  224. /*!
  225. \fn CInfoDisplay::decodeFootnote( const TQString& data )
  226. */
  227. const TQString CInfoDisplay::decodeFootnote( const TQString& data ) {
  228. TQStringList list = TQStringList::split("/", data);
  229. Q_ASSERT(list.count() >= 3);
  230. if (!list.count()) {
  231. return TQString();
  232. }
  233. const TQString modulename = list.first();
  234. const TQString swordFootnote = list.last();
  235. // remove the first and the last and then rejoin it to get a key
  236. list.pop_back(); list.pop_front();
  237. const TQString keyname = list.join("/");
  238. CSwordModuleInfo* module = CPointers::backend()->findModuleByName(modulename);
  239. if (!module) {
  240. return TQString();
  241. }
  242. util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
  243. key->key(keyname);
  244. key->renderedText(); //force entryAttributes
  245. const char* note = module->module()->getEntryAttributes()["Footnote"][swordFootnote.latin1()]["body"].c_str();
  246. TQString text = module->isUnicode() ? TQString::fromUtf8(note) : TQString(note);
  247. text = TQString::fromUtf8(module->module()->RenderText(
  248. module->isUnicode()
  249. ? (const char*)text.utf8()
  250. : (const char*)text.latin1()
  251. ));
  252. return TQString("<div class=\"footnoteinfo\"><h3>%1</h3><p>%2</p></div>")
  253. .arg(i18n("Footnote"))
  254. .arg(text);
  255. }
  256. const TQString CInfoDisplay::decodeStrongs( const TQString& data ) {
  257. TQStringList strongs = TQStringList::split("|", data);
  258. TQString ret;
  259. TQStringList::const_iterator end = strongs.end();
  260. for (TQStringList::const_iterator it = strongs.begin(); it != end; ++it) {
  261. CSwordModuleInfo* const module = CBTConfig::get
  262. (
  263. ((*it).left(1) == TQString("H")) ?
  264. CBTConfig::standardHebrewStrongsLexicon :
  265. CBTConfig::standardGreekStrongsLexicon
  266. );
  267. TQString text;
  268. if (module) {
  269. util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
  270. key->key( (*it).mid(1) ); //skip H or G (language sign), will have to change later if we have better modules
  271. text = key->renderedText();
  272. }
  273. //if the module could not be found just display an empty lemma info
  274. ret.append(
  275. TQString("<div class=\"strongsinfo\"><h3>%1: %2</h3><p>%3</p></div>")
  276. .arg(i18n("Strongs"))
  277. .arg(*it)
  278. .arg(text)
  279. );
  280. }
  281. return ret;
  282. }
  283. const TQString CInfoDisplay::decodeMorph( const TQString& data ) {
  284. TQStringList morphs = TQStringList::split("|", data);
  285. TQString ret;
  286. for (TQStringList::iterator it = morphs.begin(); it != morphs.end(); ++it) {
  287. CSwordModuleInfo* module = 0;
  288. bool skipFirstChar = false;
  289. TQString value = "";
  290. TQString valueClass = "";
  291. int valStart = (*it).find(':');
  292. if (valStart > -1) {
  293. valueClass = (*it).mid(0, valStart);
  294. module = CPointers::backend()->findModuleByName( valueClass );
  295. Q_ASSERT(module);
  296. }
  297. value = (*it).mid(valStart+1); //works for prepended module and without (-1 +1 == 0).
  298. // if we don't have a class assigned or desired one isn't installed...
  299. if (!module) {
  300. // Morphs usually don't have [GH] prepended, but some old OLB
  301. // codes do. We should check if we're digit after first char
  302. // to better guess this.
  303. // No need to check len, if at(1) is > len TQChar::null is
  304. // returned which is ok to .isDigit()
  305. if (value.at(1).isDigit()) {
  306. switch (value.at(0).latin1()) {
  307. case 'G':
  308. module = CBTConfig::get
  309. (CBTConfig::standardGreekMorphLexicon);
  310. skipFirstChar = true;
  311. break;
  312. case 'H':
  313. module = CBTConfig::get
  314. (CBTConfig::standardHebrewMorphLexicon);
  315. skipFirstChar = true;
  316. break;
  317. default:
  318. skipFirstChar = false;
  319. //TODO: we can't tell here if it's a greek or hebrew moprh code, that's a problem we have to solve
  320. // module = CBTConfig::get(CBTConfig::standardGreekMorphLexicon);
  321. break;
  322. }
  323. }
  324. //if it is still not set use the default
  325. if (!module) {
  326. module = CBTConfig::get
  327. (CBTConfig::standardGreekMorphLexicon);
  328. }
  329. }
  330. TQString text;
  331. Q_ASSERT(module);
  332. if (module) {
  333. util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
  334. //skip H or G (language sign) if we have to skip it
  335. const bool isOk = key->key( skipFirstChar ? value.mid(1) : value );
  336. Q_ASSERT(isOk);
  337. if (!isOk) { //try to use the other morph lexicon, because this one failed with the current morph code
  338. key->module(CBTConfig::get
  339. (CBTConfig::standardHebrewMorphLexicon));
  340. key->key( skipFirstChar ? value.mid(1) : value );
  341. }
  342. text = key->renderedText();
  343. }
  344. //if the module wasn't found just display an empty morph info
  345. ret.append( TQString("<div class=\"morphinfo\"><h3>%1: %2</h3><p>%3</p></div>")
  346. .arg(i18n("Morphology"))
  347. .arg(value)
  348. .arg(text)
  349. );
  350. }
  351. return ret;
  352. }
  353. const TQString CInfoDisplay::getWordTranslation( const TQString& data ) {
  354. CSwordModuleInfo* const module = CBTConfig::get
  355. (CBTConfig::standardLexicon);
  356. if (!module) {
  357. return TQString();
  358. }
  359. util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
  360. key->key( data );
  361. if (key->key().upper() != data.upper()) { //key not present in the lexicon
  362. return TQString();
  363. }
  364. TQString ret = TQString("<div class=\"translationinfo\"><h3>%1: %2</h3><p>%3</p></div>")
  365. .arg(i18n("Word lookup"))
  366. .arg(data)
  367. .arg(key->renderedText());
  368. return ret;
  369. }
  370. /*!
  371. \fn CInfoDisplay::clearInfo()
  372. */
  373. void CInfoDisplay::clearInfo() {
  374. CDisplayTemplateMgr* tmgr = CPointers::displayTemplateManager();
  375. CDisplayTemplateMgr::Settings settings;
  376. settings.pageCSS_ID = "infodisplay";
  377. m_htmlPart->setText( tmgr->fillTemplate(CBTConfig::get
  378. (CBTConfig::displayStyle), TQString(), settings) );
  379. }
  380. } //end of namespace InfoDisplay
  381. #include "cinfodisplay.moc"