|
|
|
/***************************************************************************
|
|
|
|
copyright : (C) 2003-2006 by Robby Stephenson
|
|
|
|
email : robby@periapsis.org
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of version 2 of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "entryview.h"
|
|
|
|
#include "entry.h"
|
|
|
|
#include "field.h"
|
|
|
|
#include "filehandler.h"
|
|
|
|
#include "translators/xslthandler.h"
|
|
|
|
#include "translators/tellicoxmlexporter.h"
|
|
|
|
#include "collection.h"
|
|
|
|
#include "imagefactory.h"
|
|
|
|
#include "tellico_kernel.h"
|
|
|
|
#include "tellico_utils.h"
|
|
|
|
#include "core/tellico_config.h"
|
|
|
|
#include "newstuff/manager.h"
|
|
|
|
#include "document.h"
|
|
|
|
#include "latin1literal.h"
|
|
|
|
#include "../core/drophandler.h"
|
|
|
|
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <krun.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <khtmlview.h>
|
|
|
|
#include <dom/dom_element.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <ktempfile.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
|
|
|
|
using Tellico::EntryView;
|
|
|
|
|
|
|
|
EntryView::EntryView(TQWidget* parent_, const char* name_) : KHTMLPart(parent_, name_),
|
|
|
|
m_entry(0), m_handler(0), m_run(0), m_tempFile(0), m_useGradientImages(true), m_checkCommonFile(true) {
|
|
|
|
setJScriptEnabled(false);
|
|
|
|
setJavaEnabled(false);
|
|
|
|
setMetaRefreshEnabled(false);
|
|
|
|
setPluginsEnabled(false);
|
|
|
|
clear(); // needed for initial layout
|
|
|
|
|
|
|
|
view()->setAcceptDrops(true);
|
|
|
|
DropHandler* drophandler = new DropHandler(this);
|
|
|
|
view()->installEventFilter(drophandler);
|
|
|
|
|
|
|
|
connect(browserExtension(), TQT_SIGNAL(openURLRequest(const KURL&, const KParts::URLArgs&)),
|
|
|
|
TQT_SLOT(slotOpenURL(const KURL&)));
|
|
|
|
connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), TQT_SLOT(slotResetColors()));
|
|
|
|
}
|
|
|
|
|
|
|
|
EntryView::~EntryView() {
|
|
|
|
if(m_run) {
|
|
|
|
m_run->abort();
|
|
|
|
}
|
|
|
|
delete m_handler;
|
|
|
|
m_handler = 0;
|
|
|
|
delete m_tempFile;
|
|
|
|
m_tempFile = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::clear() {
|
|
|
|
m_entry = 0;
|
|
|
|
|
|
|
|
// just clear the view
|
|
|
|
begin();
|
|
|
|
if(!m_textToShow.isEmpty()) {
|
|
|
|
write(m_textToShow);
|
|
|
|
}
|
|
|
|
end();
|
|
|
|
view()->layout(); // I need this because some of the margins and widths may get messed up
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::showEntry(Data::EntryPtr entry_) {
|
|
|
|
if(!entry_) {
|
|
|
|
clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_textToShow = TQString();
|
|
|
|
#if 0
|
|
|
|
kdWarning() << "EntryView::showEntry() - turn me off!" << endl;
|
|
|
|
m_entry = 0;
|
|
|
|
setXSLTFile(m_xsltFile);
|
|
|
|
#endif
|
|
|
|
if(!m_handler || !m_handler->isValid()) {
|
|
|
|
setXSLTFile(m_xsltFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_entry = entry_;
|
|
|
|
|
|
|
|
// by setting the xslt file as the URL, any images referenced in the xslt "theme" can be found
|
|
|
|
// by simply using a relative path in the xslt file
|
|
|
|
KURL u;
|
|
|
|
u.setPath(m_xsltFile);
|
|
|
|
begin(u);
|
|
|
|
|
|
|
|
Export::TellicoXMLExporter exporter(entry_->collection());
|
|
|
|
exporter.setEntries(entry_);
|
|
|
|
long opt = exporter.options();
|
|
|
|
// verify images for the view
|
|
|
|
opt |= Export::ExportVerifyImages;
|
|
|
|
// on second thought, don't auto-format everything, just clean it
|
|
|
|
// if(Data::Field::autoFormat()) {
|
|
|
|
// opt = Export::ExportFormatted;
|
|
|
|
// }
|
|
|
|
if(entry_->collection()->type() == Data::Collection::Bibtex) {
|
|
|
|
opt |= Export::ExportClean;
|
|
|
|
}
|
|
|
|
exporter.setOptions(opt);
|
|
|
|
TQDomDocument dom = exporter.exportXML();
|
|
|
|
|
|
|
|
// myDebug() << dom.toString() << endl;
|
|
|
|
#if 0
|
|
|
|
kdWarning() << "EntryView::showEntry() - turn me off!" << endl;
|
|
|
|
TQFile f1(TQString::fromLatin1("/tmp/test.xml"));
|
|
|
|
if(f1.open(IO_WriteOnly)) {
|
|
|
|
TQTextStream t(&f1);
|
|
|
|
t << dom.toString();
|
|
|
|
}
|
|
|
|
f1.close();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQString html = m_handler->applyStylesheet(dom.toString());
|
|
|
|
// write out image files
|
|
|
|
Data::FieldVec fields = entry_->collection()->imageFields();
|
|
|
|
for(Data::FieldVec::Iterator field = fields.begin(); field != fields.end(); ++field) {
|
|
|
|
TQString id = entry_->field(field);
|
|
|
|
if(id.isEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(Data::Document::self()->allImagesOnDisk()) {
|
|
|
|
ImageFactory::writeCachedImage(id, ImageFactory::DataDir);
|
|
|
|
} else {
|
|
|
|
ImageFactory::writeCachedImage(id, ImageFactory::TempDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
kdWarning() << "EntryView::showEntry() - turn me off!" << endl;
|
|
|
|
TQFile f2(TQString::fromLatin1("/tmp/test.html"));
|
|
|
|
if(f2.open(IO_WriteOnly)) {
|
|
|
|
TQTextStream t(&f2);
|
|
|
|
t << html;
|
|
|
|
}
|
|
|
|
f2.close();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// myDebug() << html << endl;
|
|
|
|
write(html);
|
|
|
|
end();
|
|
|
|
// not need anymore?
|
|
|
|
view()->layout(); // I need this because some of the margins and widths may get messed up
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::showText(const TQString& text_) {
|
|
|
|
m_textToShow = text_;
|
|
|
|
begin();
|
|
|
|
write(text_);
|
|
|
|
end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::setXSLTFile(const TQString& file_) {
|
|
|
|
TQString oldFile = m_xsltFile;
|
|
|
|
// if starts with slash, then absolute path
|
|
|
|
if(file_.at(0) == '/') {
|
|
|
|
m_xsltFile = file_;
|
|
|
|
} else {
|
|
|
|
const TQString templateDir = TQString::fromLatin1("entry-templates/");
|
|
|
|
m_xsltFile = locate("appdata", templateDir + file_);
|
|
|
|
if(m_xsltFile.isEmpty()) {
|
|
|
|
if(!file_.isEmpty()) {
|
|
|
|
kdWarning() << "EntryView::setXSLTFile() - can't locate " << file_ << endl;
|
|
|
|
}
|
|
|
|
m_xsltFile = locate("appdata", templateDir + TQString::fromLatin1("Fancy.xsl"));
|
|
|
|
if(m_xsltFile.isEmpty()) {
|
|
|
|
TQString str = TQString::fromLatin1("<qt>");
|
|
|
|
str += i18n("Tellico is unable to locate the default entry stylesheet.");
|
|
|
|
str += TQChar(' ');
|
|
|
|
str += i18n("Please check your installation.");
|
|
|
|
str += TQString::fromLatin1("</qt>");
|
|
|
|
KMessageBox::error(view(), str);
|
|
|
|
clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const int type = m_entry ? m_entry->collection()->type() : Kernel::self()->collectionType();
|
|
|
|
|
|
|
|
// we need to know if the colors changed from last time, in case
|
|
|
|
// we need to do that ugly hack to reload the cache
|
|
|
|
bool reloadImages = m_useGradientImages;
|
|
|
|
// if m_useGradientImages is false, then we don't even need to check
|
|
|
|
// if there's no handler, there there's _no way_ to check
|
|
|
|
if(m_handler && reloadImages) {
|
|
|
|
// the only two colors that matter for the gradients are the base color
|
|
|
|
// and highlight base color
|
|
|
|
const TQCString& oldBase = m_handler->param("bgcolor");
|
|
|
|
const TQCString& oldHigh = m_handler->param("color2");
|
|
|
|
// remember the string params have apostrophes on either side, so we can start search at pos == 1
|
|
|
|
reloadImages = oldBase.find(TQString(Config::templateBaseColor(type).name()).latin1(), 1) == -1
|
|
|
|
|| oldHigh.find(TQString(Config::templateHighlightedBaseColor(type).name()).latin1(), 1) == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!m_handler || m_xsltFile != oldFile) {
|
|
|
|
delete m_handler;
|
|
|
|
// must read the file name to get proper context
|
|
|
|
m_handler = new XSLTHandler(TQFile::encodeName(m_xsltFile));
|
|
|
|
if(m_checkCommonFile && !m_handler->isValid()) {
|
|
|
|
NewStuff::Manager::checkCommonFile();
|
|
|
|
m_checkCommonFile = false;
|
|
|
|
delete m_handler;
|
|
|
|
m_handler = new XSLTHandler(TQFile::encodeName(m_xsltFile));
|
|
|
|
}
|
|
|
|
if(!m_handler->isValid()) {
|
|
|
|
kdWarning() << "EntryView::setXSLTFile() - invalid xslt handler" << endl;
|
|
|
|
clear();
|
|
|
|
delete m_handler;
|
|
|
|
m_handler = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_handler->addStringParam("font", TQString(Config::templateFont(type).family()).latin1());
|
|
|
|
m_handler->addStringParam("fontsize", TQCString().setNum(Config::templateFont(type).pointSize()));
|
|
|
|
m_handler->addStringParam("bgcolor", TQString(Config::templateBaseColor(type).name()).latin1());
|
|
|
|
m_handler->addStringParam("fgcolor", TQString(Config::templateTextColor(type).name()).latin1());
|
|
|
|
m_handler->addStringParam("color1", TQString(Config::templateHighlightedTextColor(type).name()).latin1());
|
|
|
|
m_handler->addStringParam("color2", TQString(Config::templateHighlightedBaseColor(type).name()).latin1());
|
|
|
|
|
|
|
|
if(Data::Document::self()->allImagesOnDisk()) {
|
|
|
|
m_handler->addStringParam("imgdir", TQFile::encodeName(ImageFactory::dataDir()));
|
|
|
|
} else {
|
|
|
|
m_handler->addStringParam("imgdir", TQFile::encodeName(ImageFactory::tempDir()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// look for a file that gets installed to know the installation directory
|
|
|
|
TQString appdir = TDEGlobal::dirs()->findResourceDir("appdata", TQString::fromLatin1("pics/tellico.png"));
|
|
|
|
m_handler->addStringParam("datadir", TQFile::encodeName(appdir));
|
|
|
|
|
|
|
|
// if we don't have to reload the images, then just show the entry and we're done
|
|
|
|
if(!reloadImages) {
|
|
|
|
showEntry(m_entry);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// now, have to recreate images and refresh khtml cache
|
|
|
|
resetColors();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::slotRefresh() {
|
|
|
|
setXSLTFile(m_xsltFile);
|
|
|
|
showEntry(m_entry);
|
|
|
|
view()->repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
// do some contortions in case the url is relative
|
|
|
|
// need to interpret it relative to document URL instead of xslt file
|
|
|
|
// the current node under the mouse vould be the text node inside
|
|
|
|
// the anchor node, so iterate up the parents
|
|
|
|
void EntryView::slotOpenURL(const KURL& url_) {
|
|
|
|
if(url_.protocol() == Latin1Literal("tc")) {
|
|
|
|
// handle this internally
|
|
|
|
emit signalAction(url_);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KURL u = url_;
|
|
|
|
for(DOM::Node node = nodeUnderMouse(); !node.isNull(); node = node.parentNode()) {
|
|
|
|
if(node.nodeType() == DOM::Node::ELEMENT_NODE && static_cast<DOM::Element>(node).tagName() == "a") {
|
|
|
|
TQString href = static_cast<DOM::Element>(node).getAttribute("href").string();
|
|
|
|
if(!href.isEmpty() && KURL::isRelativeURL(href)) {
|
|
|
|
// interpet url relative to document url
|
|
|
|
u = KURL(Kernel::self()->URL(), href);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// open the url, m_run gets auto-deleted
|
|
|
|
m_run = new KRun(u);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::slotReloadEntry() {
|
|
|
|
// this slot should only be connected in setXSLTFile()
|
|
|
|
// must disconnect the signal first, otherwise, get an infinite loop
|
|
|
|
disconnect(TQT_SIGNAL(completed()));
|
|
|
|
closeURL(); // this is needed to stop everything, for some reason
|
|
|
|
view()->setUpdatesEnabled(true);
|
|
|
|
|
|
|
|
if(m_entry) {
|
|
|
|
showEntry(m_entry);
|
|
|
|
} else {
|
|
|
|
// setXSLTFile() writes some html to clear the image cache
|
|
|
|
// but we don't want to see that, so just clear everything
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
delete m_tempFile;
|
|
|
|
m_tempFile = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::setXSLTOptions(const StyleOptions& opt_) {
|
|
|
|
m_handler->addStringParam("font", opt_.fontFamily.latin1());
|
|
|
|
m_handler->addStringParam("fontsize", TQCString().setNum(opt_.fontSize));
|
|
|
|
m_handler->addStringParam("bgcolor", TQString(opt_.baseColor.name()).latin1());
|
|
|
|
m_handler->addStringParam("fgcolor", TQString(opt_.textColor.name()).latin1());
|
|
|
|
m_handler->addStringParam("color1", TQString(opt_.highlightedTextColor.name()).latin1());
|
|
|
|
m_handler->addStringParam("color2", TQString(opt_.highlightedBaseColor.name()).latin1());
|
|
|
|
m_handler->addStringParam("imgdir", TQFile::encodeName(opt_.imgDir));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EntryView::slotResetColors() {
|
|
|
|
// this will delete and reread the default colors, assuming they changed
|
|
|
|
// better to do this elsewhere, but do it here for now
|
|
|
|
Config::deleteAndReset();
|
|
|
|
delete m_handler; m_handler = 0;
|
|
|
|
setXSLTFile(m_xsltFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EntryView::resetColors() {
|
|
|
|
ImageFactory::createStyleImages(); // recreate gradients
|
|
|
|
|
|
|
|
TQString dir = m_handler ? m_handler->param("imgdir") : TQString();
|
|
|
|
if(dir.isEmpty()) {
|
|
|
|
dir = Data::Document::self()->allImagesOnDisk() ? ImageFactory::dataDir() : ImageFactory::tempDir();
|
|
|
|
} else {
|
|
|
|
// it's a string param, so it has quotes on both sides
|
|
|
|
dir = dir.mid(1);
|
|
|
|
dir.truncate(dir.length()-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// this is a rather bad hack to get around the fact that the image cache is not reloaded when
|
|
|
|
// the gradient files are changed on disk. Setting the URLArgs for write() calls doesn't seem to
|
|
|
|
// work. So force a reload with a temp file, then catch the completed signal and repaint
|
|
|
|
TQString s = TQString::fromLatin1("<html><body><img src=\"%1\"><img src=\"%2\"></body></html>")
|
|
|
|
.arg(dir + TQString::fromLatin1("gradient_bg.png"))
|
|
|
|
.arg(dir + TQString::fromLatin1("gradient_header.png"));
|
|
|
|
|
|
|
|
delete m_tempFile;
|
|
|
|
m_tempFile = new KTempFile;
|
|
|
|
m_tempFile->setAutoDelete(true);
|
|
|
|
*m_tempFile->textStream() << s;
|
|
|
|
m_tempFile->file()->close(); // have to close it
|
|
|
|
|
|
|
|
KParts::URLArgs args = browserExtension()->urlArgs();
|
|
|
|
args.reload = true; // tell the cache to reload images
|
|
|
|
browserExtension()->setURLArgs(args);
|
|
|
|
|
|
|
|
// don't flicker
|
|
|
|
view()->setUpdatesEnabled(false);
|
|
|
|
openURL(m_tempFile->name());
|
|
|
|
connect(this, TQT_SIGNAL(completed()), TQT_SLOT(slotReloadEntry()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "entryview.moc"
|