00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025
00026 #include <QFile>
00027 #include <QDir>
00028 #include <QTextStream>
00029 #include <QScrollArea>
00030 #include <QList>
00031 #include <QStringList>
00032 #include <QProgressDialog>
00033 #include <QGridLayout>
00034 #include <QPushButton>
00035 #include <QMap>
00036 #include <QStackedWidget>
00037 #include <QLineEdit>
00038 #include <QMessageBox>
00039 #include <QScrollBar>
00040 #include <QApplication>
00041 #include <QCloseEvent>
00042 #include <QDebug>
00043 #include <QPainter>
00044 #include <QPlastiqueStyle>
00045
00046 #include <QDomDocument>
00047 #include <QDomElement>
00048
00049 #include <klfbackend.h>
00050
00051 #include <ui_klflatexsymbols.h>
00052
00053 #include <klfpixmapbutton.h>
00054 #include "klfmain.h"
00055 #include "klfconfig.h"
00056 #include "klflatexsymbols.h"
00057
00058
00059
00060
00061
00062
00063 KLFLatexSymbol::KLFLatexSymbol(const QDomElement& e)
00064 : symbol(), preamble(), textmode(false), bbexpand(), hidden(false)
00065 {
00066
00067 QDomNodeList usepackagelist = e.elementsByTagName("usepackage");
00068 int k;
00069 for (k = 0; k < usepackagelist.size(); ++k) {
00070 QString package = usepackagelist.at(k).toElement().attribute("name");
00071 if (package[0] == '[' || package[0] == '{')
00072 preamble.append(QString::fromAscii("\\usepackage%1").arg(package));
00073 else
00074 preamble.append(QString::fromAscii("\\usepackage{%1}").arg(package));
00075 }
00076 QDomNodeList preamblelinelist = e.elementsByTagName("preambleline");
00077 for (k = 0; k < preamblelinelist.size(); ++k) {
00078 preamble.append(preamblelinelist.at(k).toElement().text());
00079 }
00080
00081 if (e.attribute("textmode") == "true")
00082 textmode = true;
00083 else
00084 textmode = false;
00085
00086 if (e.elementsByTagName("hidden").size() > 0)
00087 hidden = true;
00088
00089
00090 QDomNodeList bblist = e.elementsByTagName("bb");
00091 if (bblist.size() > 1) {
00092 fprintf(stderr, "WARNING: Expected at most single <bb expand=\"..\"/> item!\n");
00093 }
00094 if (bblist.size()) {
00095 sscanf(bblist.at(0).toElement().attribute("expand").toLatin1().constData(), "%d,%d,%d,%d",
00096 &bbexpand.t, &bbexpand.r, &bbexpand.b, &bbexpand.l);
00097 }
00098
00099
00100 QDomNodeList latexlist = e.elementsByTagName("latex");
00101 if (latexlist.size() != 1) {
00102 fprintf(stderr, "WARNING: Expected single <latex>...</latex> in symbol entry!\n");
00103 }
00104 if (latexlist.size() == 0)
00105 return;
00106 symbol = latexlist.at(0).toElement().text();
00107
00108 klfDbg("read symbol "<<symbol<<" hidden="<<hidden);
00109 }
00110
00111 KLF_EXPORT bool operator==(const KLFLatexSymbol& a, const KLFLatexSymbol& b)
00112 {
00113 return a.symbol == b.symbol &&
00114 a.textmode == b.textmode &&
00115 a.preamble == b.preamble &&
00116 a.bbexpand.t == b.bbexpand.t &&
00117 a.bbexpand.r == b.bbexpand.r &&
00118 a.bbexpand.b == b.bbexpand.b &&
00119 a.bbexpand.l == b.bbexpand.l &&
00120 a.hidden == b.hidden;
00121 }
00122
00123 KLF_EXPORT bool operator<(const KLFLatexSymbol& a, const KLFLatexSymbol& b)
00124 {
00125 if (a.symbol != b.symbol)
00126 return a.symbol < b.symbol;
00127 if (a.textmode != b.textmode)
00128 return a.textmode < b.textmode;
00129 if (a.preamble.size() != b.preamble.size())
00130 return a.preamble.size() < b.preamble.size();
00131 int k;
00132 for (k = 0; k < a.preamble.size(); ++k)
00133 if (a.preamble[k] != b.preamble[k])
00134 return a.preamble[k] < b.preamble[k];
00135
00136 return false;
00137 }
00138
00139 QDataStream& operator<<(QDataStream& stream, const KLFLatexSymbol& s)
00140 {
00141 return stream << s.symbol << s.preamble << (quint8)s.textmode
00142 << (qint16)s.bbexpand.t << (qint16)s.bbexpand.r
00143 << (qint16)s.bbexpand.b << (qint16)s.bbexpand.l << (quint8)s.hidden;
00144 }
00145
00146 QDataStream& operator>>(QDataStream& stream, KLFLatexSymbol& s)
00147 {
00148 quint8 textmode, hidden;
00149 struct { qint16 t, r, b, l; } readbbexpand;
00150 stream >> s.symbol >> s.preamble >> textmode >> readbbexpand.t >> readbbexpand.r
00151 >> readbbexpand.b >> readbbexpand.l >> hidden;
00152 s.bbexpand.t = readbbexpand.t;
00153 s.bbexpand.r = readbbexpand.r;
00154 s.bbexpand.b = readbbexpand.b;
00155 s.bbexpand.l = readbbexpand.l;
00156 s.textmode = textmode;
00157 s.hidden = hidden;
00158 return stream;
00159 }
00160
00161
00162
00163
00164
00165
00166 KLFLatexSymbolsCache * KLFLatexSymbolsCache::staticCache = NULL;
00167
00168 static QString __rel_cache_file = QString();
00169 static QString relcachefile()
00170 {
00171 if (__rel_cache_file.isEmpty())
00172 __rel_cache_file =
00173 QString("/symbolspixmapcache-klf%1").arg(KLF_DATA_STREAM_APP_VERSION);
00174 return __rel_cache_file;
00175 }
00176
00177 KLFLatexSymbolsCache::KLFLatexSymbolsCache()
00178 {
00179 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00180
00181
00182 QStringList cachefiles;
00183 cachefiles
00184 << klfconfig.homeConfigDir+relcachefile()
00185 << ":/data/symbolspixmapcache_base" ;
00186 int k;
00187 bool ok = false;
00188 for (k = 0; !ok && k < cachefiles.size(); ++k) {
00189
00190
00191 klfDbg("trying to load from "<<cachefiles[k]) ;
00192 ok = ( loadCacheFrom(cachefiles[k], QDataStream::Qt_4_4)
00193 == KLFLatexSymbolsCache::Ok ) ;
00194 if (!ok) {
00195 klfDbg("trying to load from "<<cachefiles[k]<<" with default header datastream version") ;
00196 ok = ( loadCacheFrom(cachefiles[k], -1)
00197 == KLFLatexSymbolsCache::Ok ) ;
00198 }
00199 }
00200 if ( ! ok ) {
00201 qWarning() << KLF_FUNC_NAME << ": error finding and reading cache file!";
00202 }
00203
00204 flag_modified = false;
00205 }
00206
00207 int KLFLatexSymbolsCache::loadCacheStream(QDataStream& stream)
00208 {
00209 QString readHeader;
00210 QString readCompatKLFVersion;
00211 bool r = klfDataStreamReadHeader(stream, QStringList()<<"KLATEXFORMULA_SYMBOLS_PIXMAP_CACHE",
00212 &readHeader, &readCompatKLFVersion);
00213 if (!r) {
00214 klfDbg("failed to read symbolscache data header. readHeader="<<readHeader
00215 <<", readcompatklfver="<<readCompatKLFVersion) ;
00216 if (readHeader.isEmpty() || readCompatKLFVersion.isEmpty())
00217 return BadHeader;
00218
00219 return BadVersion;
00220 }
00221
00222
00223
00224 stream >> cache;
00225
00226 flag_modified = false;
00227 return 0;
00228 }
00229
00230 int KLFLatexSymbolsCache::saveCacheStream(QDataStream& stream)
00231 {
00232 klfDataStreamWriteHeader(stream, "KLATEXFORMULA_SYMBOLS_PIXMAP_CACHE");
00233
00234 stream << cache;
00235 flag_modified = false;
00236 return 0;
00237 }
00238
00239 QPixmap KLFLatexSymbolsCache::getPixmap(const KLFLatexSymbol& sym, bool fromcacheonly)
00240 {
00241 klfDbg("sym.symbol="<<sym.symbol<<" fromCacheOnly="<<fromcacheonly) ;
00242
00243 if (cache.contains(sym)) {
00244 klfDbg("Found symbol in cache! pixmap is null="<<cache[sym].isNull()<<"; sym.preamble="<<sym.preamble.join(";"));
00245 return cache[sym];
00246 }
00247
00248 if (fromcacheonly) {
00249
00250 return QPixmap(":/pics/badsym.png");
00251 }
00252
00253 {
00254 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"/clean cache duplicate test") ;
00255
00256
00257
00258
00259 QMap<KLFLatexSymbol,QPixmap>::iterator it = cache.begin();
00260 while (it != cache.end()) {
00261 klfDbg("Testing symbol "<<it.key().symbol<<",preamble="<<it.key().preamble.join(",")
00262 << "for being a duplicate of "<<sym.symbol);
00263 if (it.key().symbol == sym.symbol) {
00264 klfDbg("erasing duplicate.");
00265 it = cache.erase(it);
00266 } else {
00267 ++it;
00268 }
00269 }
00270 }
00271
00272 if (sym.hidden) {
00273
00274
00275 klfDbg("symbol is hidden. Assigning NULL pixmap.") ;
00276 cache[sym] = QPixmap();
00277 return QPixmap();
00278 }
00279
00280 const float mag = 4.0;
00281
00282 KLFBackend::klfInput in;
00283 in.latex = sym.symbol;
00284 in.mathmode = sym.textmode ? "..." : "\\[ ... \\]";
00285 in.preamble = sym.preamble.join("\n")+"\n";
00286 in.fg_color = qRgb(0,0,0);
00287 in.bg_color = qRgba(255,255,255,0);
00288 in.dpi = (int)(mag * 150);
00289
00290 backendsettings.epstopdfexec = "";
00291 backendsettings.tborderoffset = sym.bbexpand.t;
00292 backendsettings.rborderoffset = sym.bbexpand.r;
00293 backendsettings.bborderoffset = sym.bbexpand.b;
00294 backendsettings.lborderoffset = sym.bbexpand.l;
00295
00296 KLFBackend::klfOutput out = KLFBackend::getLatexFormula(in, backendsettings);
00297
00298 if (out.status != 0) {
00299 qWarning()
00300 <<KLF_FUNC_NAME
00301 <<QString(":ERROR: Can't generate preview for symbol %1 : status %2 !\n\tError: %3\n")
00302 .arg(sym.symbol).arg(out.status).arg(out.errorstr);
00303 return QPixmap(":/pics/badsym.png");
00304 }
00305
00306 flag_modified = true;
00307
00308 QImage scaled = out.result.scaled((int)(out.result.width() / mag),
00309 (int)(out.result.height() / mag),
00310 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00311 QPixmap pix = QPixmap::fromImage(scaled);
00312 cache[sym] = pix;
00313
00314 klfDbg("Ran getLatexFormula(), got the pixmap. Returning.") ;
00315
00316 return pix;
00317 }
00318
00319 int KLFLatexSymbolsCache::precacheList(const QList<KLFLatexSymbol>& list, bool userfeedback,
00320 QWidget *parent)
00321 {
00322 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00323
00324 QProgressDialog *pdlg = NULL;
00325
00326 if (userfeedback) {
00327 pdlg = new QProgressDialog(QObject::tr("Please wait while generating symbol previews ... "),
00328 QObject::tr("Skip"), 0, list.size()-1, parent);
00331
00332 pdlg->setWindowModality(Qt::WindowModal);
00333 pdlg->setModal(true);
00334 pdlg->setValue(0);
00335 }
00336
00337 for (int i = 0; i < list.size(); ++i) {
00338 if (userfeedback) {
00339
00340 qApp->processEvents();
00341 if (pdlg->wasCanceled()) {
00342 delete pdlg;
00343 return 1;
00344 }
00345 pdlg->setValue(i);
00346 }
00347 getPixmap(list[i], false);
00348 }
00349
00350 if (userfeedback) {
00351 delete pdlg;
00352 }
00353
00354 return 0;
00355 };
00356
00357
00358
00359 void KLFLatexSymbolsCache::setBackendSettings(const KLFBackend::klfSettings& settings)
00360 {
00361 backendsettings = settings;
00362 }
00363
00364 KLFLatexSymbol KLFLatexSymbolsCache::findSymbol(const QString& symbolCode)
00365 {
00366 for (QMap<KLFLatexSymbol,QPixmap>::const_iterator it = cache.begin();
00367 it != cache.end(); ++it) {
00368 if (it.key().symbol == symbolCode)
00369 return it.key();
00370 }
00371 return KLFLatexSymbol();
00372 }
00373
00374 QStringList KLFLatexSymbolsCache::symbolCodeList()
00375 {
00376 QStringList l;
00377 for (QMap<KLFLatexSymbol,QPixmap>::const_iterator it = cache.begin();
00378 it != cache.end(); ++it)
00379 l << it.key().symbol;
00380 return l;
00381 }
00382
00383 QPixmap KLFLatexSymbolsCache::findSymbolPixmap(const QString& symbolCode)
00384 {
00385 KLFLatexSymbol sym = findSymbol(symbolCode);
00386 if (sym.symbol.isEmpty()) {
00387
00388 qWarning()<<KLF_FUNC_NAME<<": Can't find symbol "<<symbolCode<<".";
00389 return QPixmap();
00390 }
00391
00392 return cache[sym];
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 int KLFLatexSymbolsCache::loadCacheFrom(const QString& fname, int version)
00403 {
00404 QFile f(fname);
00405 if ( ! f.open(QIODevice::ReadOnly) ) {
00406 klfDbg("Failed to open "<<fname) ;
00407 return -1;
00408 }
00409 QDataStream ds(&f);
00410 if (version >= 0)
00411 ds.setVersion(version);
00412 int r = loadCacheStream(ds);
00413 return r;
00414 }
00415
00416
00417
00418 KLFLatexSymbolsCache * KLFLatexSymbolsCache::theCache()
00419 {
00420 if (staticCache == NULL) {
00421 staticCache = new KLFLatexSymbolsCache;
00422 }
00423 return staticCache;
00424 }
00425
00426 void KLFLatexSymbolsCache::saveTheCache()
00427 {
00428 if (staticCache->cacheNeedsSave()) {
00429 QString s = klfconfig.homeConfigDir + relcachefile();
00430 QFile f(s);
00431 if ( ! f.open(QIODevice::WriteOnly) ) {
00432 qWarning() << KLF_FUNC_NAME<< "Can't save cache to file "<< s << "!";
00433 return;
00434 }
00435 QDataStream ds(&f);
00436 ds.setVersion(QDataStream::Qt_4_4);
00437 staticCache->saveCacheStream(ds);
00438 klfDbg("Saved cache to file "<<s);
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 KLFLatexSymbolsView::KLFLatexSymbolsView(const QString& category, QWidget *parent)
00452 : QScrollArea(parent), _category(category)
00453 {
00454 mFrame = new QWidget(this);
00455
00456 setWidgetResizable(true);
00457
00458
00459
00460
00461 mFrame->setObjectName("frmSymbolList");
00462
00463
00464
00465
00466
00467 mLayout = 0;
00468 mSpacerItem = 0;
00469
00470 setWidget(mFrame);
00471 }
00472
00473 void KLFLatexSymbolsView::setSymbolList(const QList<KLFLatexSymbol>& symbols)
00474 {
00475 _symbols.clear();
00476 appendSymbolList(symbols);
00477 }
00478 void KLFLatexSymbolsView::appendSymbolList(const QList<KLFLatexSymbol>& symbols)
00479 {
00480
00481 int k;
00482 for (k = 0; k < symbols.size(); ++k)
00483 if ( ! symbols[k].hidden )
00484 _symbols.append(symbols[k]);
00485 }
00486
00487 void KLFLatexSymbolsView::buildDisplay()
00488 {
00489 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00490 #ifdef Q_WS_MAC
00491 QStyle *myStyle = new QPlastiqueStyle;
00492 QPalette pal = palette();
00493 pal.setColor(QPalette::Window, QColor(206,207,233));
00494 pal.setColor(QPalette::Base, QColor(206,207,233));
00495 pal.setColor(QPalette::Button, QColor(206,207,233));
00496 #endif
00497 mLayout = new QGridLayout(mFrame);
00498 int i;
00499 for (i = 0; i < _symbols.size(); ++i) {
00500 QPixmap p = KLFLatexSymbolsCache::theCache()->getPixmap(_symbols[i]);
00501 KLFPixmapButton *btn = new KLFPixmapButton(p, mFrame);
00502 #ifdef Q_WS_MAC
00503 btn->setStyle(myStyle);
00504 btn->setPalette(pal);
00505 #endif
00506 btn->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
00507 btn->setProperty("symbol", QVariant::fromValue<int>(i));
00508 btn->setProperty("gridpos", QPoint(-1,-1));
00509 btn->setProperty("gridcolspan", -1);
00510 btn->setProperty("myWidth", p.width() + 4);
00511 QString tooltiptext =
00512 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\""
00513 " \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
00514 "<html><head><meta name=\"qrichtext\" content=\"1\" />"
00515 "<style type=\"text/css\">\n"
00516 "p { white-space: pre-wrap; padding: 0px; margin: 0px 0px 2px 0px; }\n"
00517 "pre { padding: 0px; margin: 0px 0px 2px 0px; }\n"
00518 "</style>"
00519 "</head>"
00520 "<body>\n"
00521 "<p style=\"white-space: pre\">"+tr("LaTeX code:")+" <b><tt>"+_symbols[i].symbol+"</tt></b>"+
00522 (_symbols[i].textmode?tr(" [in text mode]"):QString(""))+
00523 +"</p>";
00524 if (_symbols[i].preamble.size())
00525 tooltiptext += "<p>"+tr("Requires:")+"<b><pre>" +
00526 _symbols[i].preamble.join("\n")+"</pre></b></p>";
00527 tooltiptext += "</body></html>";
00528 btn->setToolTip(tooltiptext);
00529
00530 connect(btn, SIGNAL(clicked()), this, SLOT(slotSymbolActivated()));
00531 mSymbols.append(btn);
00532 }
00533 mSpacerItem = new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
00534 recalcLayout();
00535 }
00536
00537 void KLFLatexSymbolsView::recalcLayout()
00538 {
00539 int row = 0, col = 0, colspan;
00540 int n = klfconfig.UI.symbolsPerLine;
00541 int quantawidth = 55;
00542
00543 int i;
00544
00545 for (i = 0; i < mSymbols.size(); ++i) {
00546 colspan = 1 + mSymbols[i]->property("myWidth").toInt() / quantawidth;
00547 if (colspan < 1)
00548 colspan = 1;
00549
00550 if (colspan > n)
00551 colspan = n;
00552 if (col + colspan > n) {
00553 row++;
00554 col = 0;
00555 }
00556 if (mSymbols[i]->property("gridpos") != QPoint(row, col) ||
00557 mSymbols[i]->property("gridcolspan") != colspan) {
00558
00559 mSymbols[i]->setProperty("gridpos", QPoint(row, col));
00560 mSymbols[i]->setProperty("gridcolspan", colspan);
00561 mLayout->removeWidget(mSymbols[i]);
00562 mLayout->addWidget(mSymbols[i], row, col, 1, colspan);
00563 }
00564 col += colspan;
00565 if (col >= n) {
00566 row++;
00567 col = 0;
00568 }
00569 }
00570
00571 mLayout->removeItem(mSpacerItem);
00572 mLayout->addItem(mSpacerItem, row+1, 0);
00573
00574 setMinimumWidth(mFrame->sizeHint().width() + verticalScrollBar()->width() + 2);
00575 }
00576
00577
00578 void KLFLatexSymbolsView::slotSymbolActivated()
00579 {
00580 QObject *s = sender();
00581 int i = s->property("symbol").toInt();
00582 if (i < 0 || i >= _symbols.size())
00583 qWarning()<<KLF_FUNC_NAME<<": Inavlid symbol index "<<i;
00584 else
00585 emit symbolActivated(_symbols[i]);
00586 }
00587
00588
00589 bool KLFLatexSymbolsView::searchIterMatches(const SearchIterator& pos, const QString& queryString)
00590 {
00591
00592 if (pos < 0 || pos >= mSymbols.size())
00593 return false;
00594
00595 int symIndex = mSymbols[pos]->property("symbol").toInt();
00596 if (symIndex < 0 || symIndex >= _symbols.size()) {
00597 qWarning()<<KLF_FUNC_NAME<<": Inavlid symbol index "<<symIndex;
00598 return false;
00599 }
00600
00601
00602 Qt::CaseSensitivity cs = (queryString.contains(QRegExp("[A-Z]")) ? Qt::CaseSensitive : Qt::CaseInsensitive) ;
00603
00604 if ( _symbols[symIndex].symbol.contains(queryString, cs) ||
00605 _symbols[symIndex].preamble.contains(queryString, cs) ) {
00606 klfDbg("found match at "<<symIndex<<": "<<_symbols[symIndex].symbol) ;
00607 return true;
00608 }
00609 return false;
00610 }
00611
00612 void KLFLatexSymbolsView::searchPerformed(const SearchIterator& result)
00613 {
00614 klfDbg("result is "<<result<<" valid="<<(result<mSymbols.size())) ;
00615
00616 highlightSearchMatches(result);
00617 }
00618 void KLFLatexSymbolsView::searchAbort()
00619 {
00620 KLFIteratorSearchable<int>::searchAbort();
00621 highlightSearchMatches(-1);
00622
00623 }
00624
00625 void KLFLatexSymbolsView::highlightSearchMatches(int currentMatch)
00626 {
00627 QString stylesheets[] = {
00628
00629 "",
00630 "KLFPixmapButton { background-color: rgb(180,180,255); }",
00631 "KLFPixmapButton { background-color: rgb(0,0,255); }"
00632 };
00633
00634 if (currentMatch == -1) {
00635
00636 stylesheets[0] = stylesheets[1] = stylesheets[2] = QString();
00637 }
00638 int k;
00639 for (k = 0; k < mSymbols.size(); ++k) {
00640 int which = 0;
00641 if (k == currentMatch)
00642 which = 2;
00643 else if (searchIterMatches(k, searchQueryString()))
00644 which = 1;
00645 mSymbols[k]->setStyleSheet(stylesheets[which]);
00646 }
00647 if (currentMatch >= 0 && currentMatch < mSymbols.size())
00648 ensureWidgetVisible(mSymbols[currentMatch]);
00649 }
00650
00651
00652
00653
00654
00655 KLFLatexSymbols::KLFLatexSymbols(QWidget *parent, const KLFBackend::klfSettings& baseSettings)
00656 : QWidget(
00657 #if defined(Q_OS_WIN32)
00658 0
00659 #else
00660 parent
00661 #endif
00662 , Qt::Window )
00663 {
00664 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00665
00666 u = new Ui::KLFLatexSymbols;
00667 u->setupUi(this);
00668 setAttribute(Qt::WA_StyledBackground);
00669
00670
00671 pSearchBar = new KLFSearchBar(this);
00672 KLF_DEBUG_ASSIGN_REF_INSTANCE(pSearchBar, "latexsymbols-searchbar") ;
00673 pSearchBar->setShowOverlayMode(true);
00674 pSearchBar->registerShortcuts(this);
00675 pSearchBar->setSearchText("");
00676 pSearchBar->setShowHideButton(true);
00677 connect(pSearchBar, SIGNAL(escapePressed()), pSearchBar, SLOT(hide()));
00678
00679 klfDbg("prepared search bar.") ;
00680
00681 KLFLatexSymbolsCache::theCache()->setBackendSettings(baseSettings);
00682
00683
00684 read_symbols_create_ui();
00685
00686 slotShowCategory(0);
00687
00688 QFont f = u->cbxCategory->font();
00689 int ps = f.pointSize();
00690 if (ps < 8)
00691 ps = QFontInfo(f).pointSize();
00692 f.setPointSize(ps+1);
00693 u->cbxCategory->setFont(f);
00694
00695 connect(u->cbxCategory, SIGNAL(highlighted(int)), this, SLOT(slotShowCategory(int)));
00696 connect(u->cbxCategory, SIGNAL(activated(int)), this, SLOT(slotShowCategory(int)));
00697 connect(u->btnClose, SIGNAL(clicked()), this, SLOT(close()));
00698 }
00699
00700 void KLFLatexSymbols::retranslateUi(bool alsoBaseUi)
00701 {
00702 if (alsoBaseUi)
00703 u->retranslateUi(this);
00704 }
00705
00706 KLFLatexSymbols::~KLFLatexSymbols()
00707 {
00708 KLFLatexSymbolsCache::saveTheCache();
00709 }
00710
00711 void KLFLatexSymbols::read_symbols_create_ui()
00712 {
00713 klfDbgT("called.") ;
00714
00715
00716 u->cbxCategory->clear();
00717 QGridLayout *lytstk = new QGridLayout(u->frmStackContainer);
00718 stkViews = new QStackedWidget(u->frmStackContainer);
00719 lytstk->addWidget(stkViews, 0, 0);
00720
00721 mViews.clear();
00722
00723
00724 QStringList fxmllist;
00725
00726 QStringList fxmldirs;
00727 fxmldirs << klfconfig.homeConfigDir + "/conf/latexsymbols.d/"
00728 << klfconfig.globalShareDir + "/conf/latexsymbols.d/"
00729 << ":/conf/latexsymbols.d/";
00730
00731 klfDbgT("starting to collect XML files from dirs "<<fxmldirs) ;
00732
00733
00734 int k, j;
00735 for (k = 0; k < fxmldirs.size(); ++k) {
00736 QDir fxmldir(fxmldirs[k]);
00737 QStringList xmllist = fxmldir.entryList(QStringList()<<"*.xml", QDir::Files);
00738 for (j = 0; j < xmllist.size(); ++j)
00739 fxmllist << fxmldir.absoluteFilePath(xmllist[j]);
00740 }
00741 klfDbgT("files collected: "<<fxmllist) ;
00742 if (fxmllist.isEmpty()) {
00743
00744 QDir("/").mkpath(klfconfig.homeConfigDir+"/conf/latexsymbols.d");
00745 if (QFile::exists(klfconfig.homeConfigDir+"/latexsymbols.xml")) {
00746 QFile::copy(klfconfig.homeConfigDir+"/latexsymbols.xml",
00747 klfconfig.homeConfigDir+"/conf/latexsymbols.d/mylatexsymbols.xml");
00748 fxmllist << klfconfig.homeConfigDir+"/conf/latexsymbols.d/mylatexsymbols.xml";
00749 } else {
00750 QFile::copy(":/data/latexsymbols.xml",
00751 klfconfig.homeConfigDir+"/conf/latexsymbols.d/defaultlatexsymbols.xml");
00752 fxmllist << klfconfig.homeConfigDir+"/conf/latexsymbols.d/defaultlatexsymbols.xml";
00753 }
00754 }
00755
00756 klfDbgT("got xml files, ensured not empty; fxmllist="<<fxmllist) ;
00757
00758
00759 QList<KLFLatexSymbol> allsymbols;
00760
00761
00762 QStringList categoryTitleLangs;
00763
00764
00765 for (k = 0; k < fxmllist.size(); ++k) {
00766 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"/fxmllist["+('0'+k)+"]");
00767 klfDbg("reading XML file="<<fxmllist[k]);
00768
00769 QString fn = fxmllist[k];
00770 QFile file(fn);
00771 if ( ! file.open(QIODevice::ReadOnly) ) {
00772 qWarning()<<KLF_FUNC_NAME<<": Error: Can't open latex symbols XML file "<<fn<<": "<<file.errorString()<<"!";
00773 continue;
00774 }
00775
00776 QDomDocument doc("latexsymbols");
00777 QString errMsg; int errLine, errCol;
00778 bool r = doc.setContent(&file, false, &errMsg, &errLine, &errCol);
00779 if (!r) {
00780 qWarning()<<KLF_FUNC_NAME<<": Error parsing file "<<fn<<": "<<errMsg<<" at line "<<errLine<<", col "<<errCol;
00781 continue;
00782 }
00783 file.close();
00784
00785 QDomElement root = doc.documentElement();
00786 if (root.nodeName() != "latexsymbollist") {
00787 qWarning("%s: Error parsing XML for latex symbols from file `%s': unexpected root tag `%s'.\n", KLF_FUNC_NAME,
00788 qPrintable(fn), qPrintable(root.nodeName()));
00789 continue;
00790 }
00791
00792 QDomNode n;
00793 for (n = root.firstChild(); ! n.isNull(); n = n.nextSibling()) {
00794 QDomElement e = n.toElement();
00795 if ( e.isNull() || n.nodeType() != QDomNode::ElementNode )
00796 continue;
00797 if ( e.nodeName() != "category" ) {
00798 qWarning("WARNING in parsing XML : ignoring unexpected tag `%s'!\n",
00799 qPrintable(e.nodeName()));
00800 continue;
00801 }
00802
00803 QString heading = e.attribute("name");
00804 QString categoryTitle;
00805
00806 QString curCategoryTitleLang;
00807 QList<KLFLatexSymbol> l;
00808 QDomNode esym;
00809 for (esym = e.firstChild(); ! esym.isNull(); esym = esym.nextSibling() ) {
00810 if ( esym.isNull() || esym.nodeType() != QDomNode::ElementNode )
00811 continue;
00812 QDomElement eesym = esym.toElement();
00813 klfDbg("read element "<<esym.nodeName());
00814 if ( eesym.nodeName() == "category-title" ) {
00815
00816 QString lang = eesym.hasAttribute("xml:lang") ? eesym.attribute("xml:lang") : QString() ;
00817 klfDbg("<category-title>: lang="<<lang<<"; hasAttribute(xml:lang)="<<eesym.hasAttribute("xml:lang")
00818 <<"; current category-title="<<categoryTitle<<",lang="<<curCategoryTitleLang) ;
00819 if (categoryTitle.isEmpty()) {
00820
00821 if (lang.isEmpty() || lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) {
00822
00823 categoryTitle = qApp->translate("xmltr_latexsymbols", eesym.text().toUtf8().constData(),
00824 "[[tag: <category-title>]]", QCoreApplication::UnicodeUTF8);
00825 curCategoryTitleLang = lang;
00826 }
00827
00828 } else {
00829
00830 if ( (lang.startsWith(klfconfig.UI.locale) || klfconfig.UI.locale.startsWith(lang)) &&
00831 (curCategoryTitleLang.isEmpty() || lang.startsWith(curCategoryTitleLang) ) ) {
00832
00833 categoryTitle = eesym.text();
00834 curCategoryTitleLang = lang;
00835 }
00836
00837 }
00838 continue;
00839 }
00840 if ( esym.nodeName() != "sym" ) {
00841 qWarning("%s: WARNING in parsing XML : ignoring unexpected tag `%s' in category `%s'!\n",
00842 KLF_FUNC_NAME, qPrintable(esym.nodeName()), qPrintable(heading));
00843 continue;
00844 }
00845
00846 KLFLatexSymbol sym(eesym);
00847 l.append(sym);
00848 allsymbols.append(sym);
00849 }
00850
00851 KLFLatexSymbolsView * view = NULL;
00852 for (j = 0; j < mViews.size(); ++j) {
00853 if (mViews[j]->category() == heading) {
00854 view = mViews[j];
00855 break;
00856 }
00857 }
00858 if (view == NULL) {
00859
00860 view = new KLFLatexSymbolsView(heading, stkViews);
00861 connect(view, SIGNAL(symbolActivated(const KLFLatexSymbol&)),
00862 this, SIGNAL(insertSymbol(const KLFLatexSymbol&)));
00863 mViews.append(view);
00864 stkViews->addWidget(view);
00865 if (categoryTitle.isEmpty())
00866 categoryTitle = heading;
00867 u->cbxCategory->addItem(categoryTitle, heading);
00868 categoryTitleLangs << curCategoryTitleLang;
00869 } else {
00870
00871 if (!categoryTitle.isEmpty() &&
00872 (categoryTitleLangs[j].isEmpty() || curCategoryTitleLang.startsWith(categoryTitleLangs[j]))) {
00873
00874 u->cbxCategory->setItemText(j, categoryTitle);
00875 } else {
00876
00877 }
00878 }
00879
00880 view->appendSymbolList(l);
00881 }
00882 }
00883
00884
00885 KLFLatexSymbolsCache::theCache()->precacheList(allsymbols, true, this);
00886
00887 int i;
00888 for (i = 0; i < mViews.size(); ++i) {
00889 mViews[i]->buildDisplay();
00890 }
00891
00892 }
00893
00894 void KLFLatexSymbols::slotShowCategory(int c)
00895 {
00896 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00897
00898
00899 stkViews->setCurrentIndex(c);
00900
00901 klfDbg("current index="<<c) ;
00902
00903 QWidget * w = stkViews->currentWidget();
00904 KLFSearchable * target = NULL;
00905 if (w != NULL) {
00906 KLFLatexSymbolsView *view = qobject_cast<KLFLatexSymbolsView*>(w);
00907 if (view != NULL)
00908 target = view;
00909 }
00910 pSearchBar->setSearchTarget(target);
00911 }
00912
00913 void KLFLatexSymbols::closeEvent(QCloseEvent *e)
00914 {
00915 e->accept();
00916 }
00917
00918 void KLFLatexSymbols::showEvent(QShowEvent *e)
00919 {
00920 QWidget::showEvent(e);
00921 }
00922
00923
00924 bool KLFLatexSymbols::event(QEvent *e)
00925 {
00926 if (e->type() == QEvent::Polish) {
00927 u->cbxCategory->setMinimumHeight(u->cbxCategory->sizeHint().height()+5);
00928 }
00929 if (e->type() == QEvent::KeyPress) {
00930 QKeyEvent *ke = (QKeyEvent*)e;
00931 if (ke->key() == Qt::Key_F7 && ke->modifiers() == 0) {
00932 hide();
00933 e->accept();
00934 return true;
00935 }
00936 }
00937 return QWidget::event(e);
00938 }
00939