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.
465 lines
13 KiB
465 lines
13 KiB
//
|
|
// C++ Implementation: cinfodisplay
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Author: The BibleTime team <info@bibletime.info>, (C) 2004
|
|
//
|
|
// Copyright: See COPYING file that comes with this distribution
|
|
//
|
|
//
|
|
|
|
//BibleTime includes
|
|
#include "cinfodisplay.h"
|
|
|
|
#include "backend/cswordmoduleinfo.h"
|
|
#include "backend/cswordkey.h"
|
|
#include "backend/cswordversekey.h"
|
|
#include "backend/creferencemanager.h"
|
|
#include "backend/cdisplaytemplatemgr.h"
|
|
|
|
#include "frontend/cbtconfig.h"
|
|
#include "frontend/crossrefrendering.h"
|
|
|
|
#include "frontend/display/cdisplay.h"
|
|
#include "frontend/display/creaddisplay.h"
|
|
#include "frontend/display/chtmlreaddisplay.h"
|
|
|
|
#include "util/scoped_resource.h"
|
|
|
|
//Sword includes
|
|
#include <listkey.h>
|
|
|
|
//TQt includes
|
|
#include <tqlayout.h>
|
|
#include <tqlabel.h>
|
|
#include <tqscrollview.h>
|
|
#include <tqregexp.h>
|
|
|
|
//KDE includes
|
|
#include <tdelocale.h>
|
|
#include <kstdaction.h>
|
|
|
|
|
|
using namespace Rendering;
|
|
using namespace sword;
|
|
|
|
namespace InfoDisplay {
|
|
|
|
CInfoDisplay::CInfoDisplay(TQWidget *parent, const char *name)
|
|
: TQWidget(parent, name) {
|
|
TQVBoxLayout* layout = new TQVBoxLayout(this);
|
|
TQLabel* headingLabel = new TQLabel(i18n("Mag (\"shift\" to lock)"),this);
|
|
headingLabel->setMargin(5);
|
|
|
|
m_htmlPart = CDisplay::createReadInstance(0, this);
|
|
m_htmlPart->setMouseTracking(false); //we don't want strong/lemma/note mouse infos
|
|
KStdAction::copy(m_htmlPart->connectionsProxy(), TQ_SLOT(copySelection()), 0, "copyMagSelection");
|
|
|
|
connect(
|
|
m_htmlPart->connectionsProxy(),
|
|
TQ_SIGNAL(referenceClicked(const TQString&, const TQString&)),
|
|
TQ_SLOT(lookup(const TQString&, const TQString&))
|
|
);
|
|
|
|
layout->addWidget(headingLabel);
|
|
layout->addWidget(m_htmlPart->view());
|
|
}
|
|
|
|
|
|
CInfoDisplay::~CInfoDisplay() {}
|
|
|
|
void CInfoDisplay::lookup(const TQString &mod_name, const TQString &key_text) {
|
|
tqWarning("%s %s", mod_name.ascii(), key_text.ascii());
|
|
CSwordModuleInfo* m = CPointers::backend()->findModuleByName(mod_name);
|
|
Q_ASSERT(m);
|
|
if (!m)
|
|
return;
|
|
|
|
util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(m) );
|
|
key->key( key_text );
|
|
|
|
CDisplayTemplateMgr* mgr = CPointers::displayTemplateManager();
|
|
CDisplayTemplateMgr::Settings settings;
|
|
settings.pageCSS_ID = "infodisplay";
|
|
// settings.langAbbrev = "";
|
|
TQString content = mgr->fillTemplate(CBTConfig::get
|
|
(CBTConfig::displayStyle), key->renderedText(), settings);
|
|
|
|
// tqWarning("setting text:\n%s", content.latin1());
|
|
|
|
m_htmlPart->setText(content); // scroll to top
|
|
CHTMLReadDisplay *d = dynamic_cast<CHTMLReadDisplay *>(m_htmlPart);
|
|
d->view()->ensureVisible(0, 0);
|
|
|
|
}
|
|
|
|
void CInfoDisplay::setInfo(const InfoType type, const TQString& data) {
|
|
ListInfoData list;
|
|
list.append( qMakePair(type, data) );
|
|
|
|
setInfo(list);
|
|
}
|
|
|
|
|
|
void CInfoDisplay::setInfo(const ListInfoData& list) {
|
|
//if the widget is hidden it would be inefficient to render and display the data
|
|
if (!isVisible()) {
|
|
return;
|
|
}
|
|
|
|
if (list.count() == 0) {
|
|
m_htmlPart->setText("<html></html>");
|
|
return;
|
|
}
|
|
|
|
TQString text;
|
|
|
|
ListInfoData::const_iterator end = list.end();
|
|
for (ListInfoData::const_iterator it = list.begin(); it != end; ++it) {
|
|
switch ( (*it).first ) {
|
|
case Lemma:
|
|
text.append( decodeStrongs( (*it).second ) );
|
|
continue;
|
|
case Morph:
|
|
text.append( decodeMorph( (*it).second ) );
|
|
continue;
|
|
case CrossReference:
|
|
text.append( decodeCrossReference( (*it).second ) );
|
|
continue;
|
|
case Footnote:
|
|
text.append( decodeFootnote( (*it).second ) );
|
|
continue;
|
|
case WordTranslation:
|
|
text.append( getWordTranslation( (*it).second ) );
|
|
continue;
|
|
case WordGloss:
|
|
//text.append( getWordTranslation( (*it).second ) );
|
|
continue;
|
|
case Abbreviation:
|
|
text.append( decodeAbbreviation( (*it).second ) );
|
|
continue;
|
|
default:
|
|
continue;
|
|
};
|
|
}
|
|
|
|
CDisplayTemplateMgr* mgr = CPointers::displayTemplateManager();
|
|
CDisplayTemplateMgr::Settings settings;
|
|
settings.pageCSS_ID = "infodisplay";
|
|
// settings.langAbbrev = "";
|
|
TQString content = mgr->fillTemplate(CBTConfig::get
|
|
(CBTConfig::displayStyle), text, settings);
|
|
|
|
// tqWarning("setting text:\n%s", content.latin1());
|
|
|
|
m_htmlPart->setText(content);
|
|
}
|
|
|
|
|
|
const TQString CInfoDisplay::decodeAbbreviation( const TQString& data ) {
|
|
// TQStringList strongs = TQStringList::split("|", data);
|
|
TQString ret;
|
|
TQString text = data;
|
|
|
|
ret.append(
|
|
TQString("<div class=\"abbreviation\"><h3>%1: %2</h3><p>%3</p></div>")
|
|
.arg(i18n("Abbreviation"))
|
|
.arg("text")
|
|
.arg(text));
|
|
|
|
return ret;
|
|
}
|
|
|
|
const TQString CInfoDisplay::decodeCrossReference( const TQString& data ) {
|
|
Q_ASSERT(!data.isEmpty());
|
|
if (data.isEmpty()) {
|
|
return TQString("<div class=\"crossrefinfo\"><h3>%1</h3></div>")
|
|
.arg(i18n("Cross references"));
|
|
}
|
|
|
|
// tqWarning("setting crossref %s", data.latin1());
|
|
|
|
CSwordBackend::DisplayOptions dispOpts;
|
|
dispOpts.lineBreaks = false;
|
|
dispOpts.verseNumbers = true;
|
|
|
|
CSwordBackend::FilterOptions filterOpts;
|
|
filterOpts.headings = false;
|
|
filterOpts.strongNumbers = false;
|
|
filterOpts.morphTags = false;
|
|
filterOpts.lemmas = false;
|
|
filterOpts.footnotes = false;
|
|
filterOpts.scriptureReferences = false;
|
|
|
|
CrossRefRendering renderer(dispOpts, filterOpts);
|
|
CTextRendering::KeyTree tree;
|
|
|
|
// const bool isBible = true;
|
|
CSwordModuleInfo* module = CBTConfig::get
|
|
(CBTConfig::standardBible);
|
|
|
|
//a prefixed module gives the module to look into
|
|
TQRegExp re("^[^ ]+:");
|
|
// re.setMinimal(true);
|
|
int pos = re.search(data,0);
|
|
if (pos != -1) {
|
|
pos += re.matchedLength()-1;
|
|
}
|
|
|
|
if (pos > 0) {
|
|
const TQString moduleName = data.left(pos);
|
|
// tqWarning("found module %s", moduleName.latin1());
|
|
module = CPointers::backend()->findModuleByName(moduleName);
|
|
if (!module) {
|
|
module = CBTConfig::get
|
|
(CBTConfig::standardBible);
|
|
}
|
|
// Q_ASSERT(module);
|
|
}
|
|
|
|
Q_ASSERT(module);
|
|
CTextRendering::KeyTreeItem::Settings settings (
|
|
false,
|
|
CTextRendering::KeyTreeItem::Settings::CompleteShort
|
|
);
|
|
|
|
if (module && (module->type() == CSwordModuleInfo::Bible)) {
|
|
VerseKey vk;
|
|
sword::ListKey refs = vk.ParseVerseList((const char*)data.mid((pos == -1) ? 0 : pos+1).utf8(), "Gen 1:1", true);
|
|
|
|
for (int j = 0; j < refs.Count(); ++j) {
|
|
SWKey* key = refs.getElement(j);
|
|
Q_ASSERT(key);
|
|
VerseKey* vk = dynamic_cast<VerseKey*>(key);
|
|
|
|
CTextRendering::KeyTreeItem* i = 0;
|
|
if (vk && vk->isBoundSet()) { //render a range of keys
|
|
i = new CTextRendering::KeyTreeItem(
|
|
TQString::fromUtf8(vk->LowerBound().getText()),
|
|
TQString::fromUtf8(vk->UpperBound().getText()),
|
|
module,
|
|
settings
|
|
);
|
|
}
|
|
else {
|
|
i = new CTextRendering::KeyTreeItem(
|
|
TQString::fromUtf8(key->getText()),
|
|
TQString::fromUtf8(key->getText()),
|
|
module,
|
|
settings
|
|
);
|
|
}
|
|
|
|
Q_ASSERT(i);
|
|
|
|
tree.append( i );
|
|
}
|
|
}
|
|
else if (module) {
|
|
CTextRendering::KeyTreeItem* i = new CTextRendering::KeyTreeItem(
|
|
data.mid((pos == -1) ? 0 : pos+1),
|
|
module,
|
|
settings
|
|
);
|
|
tree.append( i );
|
|
}
|
|
|
|
// tqWarning("rendered the tree: %s", renderer.renderKeyTree(tree).latin1());
|
|
//spanns containing rtl text need dir=rtl on their parent tag to be aligned properly
|
|
return TQString("<div class=\"crossrefinfo\"><h3>%1</h3><div class=\"para\" dir=\"%2\">%3</div></div>")
|
|
.arg(i18n("Cross references"))
|
|
.arg(module ? ((module->textDirection() == CSwordModuleInfo::LeftToRight) ? "ltr" : "rtl") : "")
|
|
.arg(renderer.renderKeyTree(tree));
|
|
}
|
|
|
|
/*!
|
|
\fn CInfoDisplay::decodeFootnote( const TQString& data )
|
|
*/
|
|
const TQString CInfoDisplay::decodeFootnote( const TQString& data ) {
|
|
TQStringList list = TQStringList::split("/", data);
|
|
Q_ASSERT(list.count() >= 3);
|
|
if (!list.count()) {
|
|
return TQString();
|
|
}
|
|
|
|
const TQString modulename = list.first();
|
|
const TQString swordFootnote = list.last();
|
|
|
|
// remove the first and the last and then rejoin it to get a key
|
|
list.pop_back(); list.pop_front();
|
|
const TQString keyname = list.join("/");
|
|
|
|
CSwordModuleInfo* module = CPointers::backend()->findModuleByName(modulename);
|
|
if (!module) {
|
|
return TQString();
|
|
}
|
|
|
|
util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
|
|
key->key(keyname);
|
|
key->renderedText(); //force entryAttributes
|
|
|
|
const char* note = module->module()->getEntryAttributes()["Footnote"][swordFootnote.latin1()]["body"].c_str();
|
|
|
|
TQString text = module->isUnicode() ? TQString::fromUtf8(note) : TQString(note);
|
|
text = TQString::fromUtf8(module->module()->RenderText(
|
|
module->isUnicode()
|
|
? (const char*)text.utf8()
|
|
: (const char*)text.latin1()
|
|
));
|
|
|
|
return TQString("<div class=\"footnoteinfo\"><h3>%1</h3><p>%2</p></div>")
|
|
.arg(i18n("Footnote"))
|
|
.arg(text);
|
|
}
|
|
|
|
const TQString CInfoDisplay::decodeStrongs( const TQString& data ) {
|
|
TQStringList strongs = TQStringList::split("|", data);
|
|
TQString ret;
|
|
|
|
TQStringList::const_iterator end = strongs.end();
|
|
for (TQStringList::const_iterator it = strongs.begin(); it != end; ++it) {
|
|
CSwordModuleInfo* const module = CBTConfig::get
|
|
(
|
|
((*it).left(1) == TQString("H")) ?
|
|
CBTConfig::standardHebrewStrongsLexicon :
|
|
CBTConfig::standardGreekStrongsLexicon
|
|
);
|
|
|
|
TQString text;
|
|
if (module) {
|
|
util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
|
|
key->key( (*it).mid(1) ); //skip H or G (language sign), will have to change later if we have better modules
|
|
text = key->renderedText();
|
|
}
|
|
//if the module could not be found just display an empty lemma info
|
|
|
|
ret.append(
|
|
TQString("<div class=\"strongsinfo\"><h3>%1: %2</h3><p>%3</p></div>")
|
|
.arg(i18n("Strongs"))
|
|
.arg(*it)
|
|
.arg(text)
|
|
);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
const TQString CInfoDisplay::decodeMorph( const TQString& data ) {
|
|
TQStringList morphs = TQStringList::split("|", data);
|
|
TQString ret;
|
|
|
|
for (TQStringList::iterator it = morphs.begin(); it != morphs.end(); ++it) {
|
|
CSwordModuleInfo* module = 0;
|
|
bool skipFirstChar = false;
|
|
TQString value = "";
|
|
TQString valueClass = "";
|
|
|
|
int valStart = (*it).find(':');
|
|
if (valStart > -1) {
|
|
valueClass = (*it).mid(0, valStart);
|
|
module = CPointers::backend()->findModuleByName( valueClass );
|
|
Q_ASSERT(module);
|
|
}
|
|
value = (*it).mid(valStart+1); //works for prepended module and without (-1 +1 == 0).
|
|
|
|
// if we don't have a class assigned or desired one isn't installed...
|
|
if (!module) {
|
|
// Morphs usually don't have [GH] prepended, but some old OLB
|
|
// codes do. We should check if we're digit after first char
|
|
// to better guess this.
|
|
// No need to check len, if at(1) is > len TQChar::null is
|
|
// returned which is ok to .isDigit()
|
|
if (value.at(1).isDigit()) {
|
|
switch (value.at(0).latin1()) {
|
|
case 'G':
|
|
module = CBTConfig::get
|
|
(CBTConfig::standardGreekMorphLexicon);
|
|
skipFirstChar = true;
|
|
break;
|
|
case 'H':
|
|
module = CBTConfig::get
|
|
(CBTConfig::standardHebrewMorphLexicon);
|
|
skipFirstChar = true;
|
|
break;
|
|
default:
|
|
skipFirstChar = false;
|
|
//TODO: we can't tell here if it's a greek or hebrew moprh code, that's a problem we have to solve
|
|
// module = CBTConfig::get(CBTConfig::standardGreekMorphLexicon);
|
|
break;
|
|
}
|
|
}
|
|
//if it is still not set use the default
|
|
if (!module) {
|
|
module = CBTConfig::get
|
|
(CBTConfig::standardGreekMorphLexicon);
|
|
}
|
|
}
|
|
|
|
TQString text;
|
|
Q_ASSERT(module);
|
|
if (module) {
|
|
util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
|
|
|
|
//skip H or G (language sign) if we have to skip it
|
|
const bool isOk = key->key( skipFirstChar ? value.mid(1) : value );
|
|
Q_ASSERT(isOk);
|
|
if (!isOk) { //try to use the other morph lexicon, because this one failed with the current morph code
|
|
key->module(CBTConfig::get
|
|
(CBTConfig::standardHebrewMorphLexicon));
|
|
key->key( skipFirstChar ? value.mid(1) : value );
|
|
}
|
|
|
|
text = key->renderedText();
|
|
}
|
|
|
|
//if the module wasn't found just display an empty morph info
|
|
ret.append( TQString("<div class=\"morphinfo\"><h3>%1: %2</h3><p>%3</p></div>")
|
|
.arg(i18n("Morphology"))
|
|
.arg(value)
|
|
.arg(text)
|
|
);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
const TQString CInfoDisplay::getWordTranslation( const TQString& data ) {
|
|
CSwordModuleInfo* const module = CBTConfig::get
|
|
(CBTConfig::standardLexicon);
|
|
if (!module) {
|
|
return TQString();
|
|
}
|
|
|
|
util::scoped_ptr<CSwordKey> key( CSwordKey::createInstance(module) );
|
|
key->key( data );
|
|
if (key->key().upper() != data.upper()) { //key not present in the lexicon
|
|
return TQString();
|
|
}
|
|
|
|
TQString ret = TQString("<div class=\"translationinfo\"><h3>%1: %2</h3><p>%3</p></div>")
|
|
.arg(i18n("Word lookup"))
|
|
.arg(data)
|
|
.arg(key->renderedText());
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*!
|
|
\fn CInfoDisplay::clearInfo()
|
|
*/
|
|
void CInfoDisplay::clearInfo() {
|
|
CDisplayTemplateMgr* tmgr = CPointers::displayTemplateManager();
|
|
CDisplayTemplateMgr::Settings settings;
|
|
settings.pageCSS_ID = "infodisplay";
|
|
|
|
m_htmlPart->setText( tmgr->fillTemplate(CBTConfig::get
|
|
(CBTConfig::displayStyle), TQString(), settings) );
|
|
}
|
|
|
|
} //end of namespace InfoDisplay
|
|
|
|
#include "cinfodisplay.moc"
|