diff --git a/src/qtgui/preview_w.h b/src/qtgui/preview_w.h index c6c0fcf6..49da7158 100644 --- a/src/qtgui/preview_w.h +++ b/src/qtgui/preview_w.h @@ -1,6 +1,6 @@ #ifndef _PREVIEW_W_H_INCLUDED_ #define _PREVIEW_W_H_INCLUDED_ -/* @(#$Id: preview_w.h,v 1.19 2008-10-03 08:09:35 dockes Exp $ (C) 2006 J.F.Dockes */ +/* @(#$Id: preview_w.h,v 1.20 2008-12-16 14:20:10 dockes Exp $ (C) 2006 J.F.Dockes */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,7 +69,8 @@ class TabData { class PlainToRichQtPreview : public PlainToRich { public: int lastanchor; - PlainToRichQtPreview(bool inputhtml = false) : PlainToRich(inputhtml) { + PlainToRichQtPreview() + { lastanchor = 0; } virtual ~PlainToRichQtPreview() {} diff --git a/src/qtgui/reslist.cpp b/src/qtgui/reslist.cpp index 70c928d4..5dfde16b 100644 --- a/src/qtgui/reslist.cpp +++ b/src/qtgui/reslist.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: reslist.cpp,v 1.50 2008-12-12 11:01:01 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: reslist.cpp,v 1.51 2008-12-16 14:20:10 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #include @@ -50,7 +50,6 @@ static char rcsid[] = "@(#$Id: reslist.cpp,v 1.50 2008-12-12 11:01:01 dockes Exp #define MIN(A,B) ((A) < (B) ? (A) : (B)) #endif - class PlainToRichQtReslist : public PlainToRich { public: virtual ~PlainToRichQtReslist() {} @@ -78,10 +77,10 @@ ResList::ResList(QWidget* parent, const char* name) #if (QT_VERSION >= 0x040000) connect(this, SIGNAL(selectionChanged()), this, SLOT(selecChanged())); #endif - m_winfirst = -1; m_curPvDoc = -1; m_lstClckMod = 0; m_listId = 0; + m_pager = new QtGuiResListPager(this, prefs.respagesize); } ResList::~ResList() @@ -132,6 +131,7 @@ void ResList::setDocSource() m_sortspecs, title)); } + m_pager->setDocSource(m_docSource); resultPageNext(); } @@ -149,7 +149,6 @@ void ResList::setFilterParams(const DocSeqFiltSpec& spec) void ResList::resetList() { - m_winfirst = -1; m_curPvDoc = -1; // There should be a progress bar for long searches but there isn't // We really want the old result list to go away, otherwise, for a @@ -184,7 +183,6 @@ void ResList::languageChange() bool ResList::getTerms(vector& terms, vector >& groups, vector& gslks) { - // We could just return m_baseDocSource->getTerms(terms, groups, gslks); } @@ -198,12 +196,12 @@ list ResList::expand(Rcl::Doc& doc) // Get document number from paragraph number int ResList::docnumfromparnum(int par) { - if (m_winfirst == -1) + if (m_pager->pageNumber() < 0) return -1; std::map::iterator it = m_pageParaToReldocnums.find(par); int dn; if (it != m_pageParaToReldocnums.end()) { - dn = m_winfirst + it->second; + dn = m_pager->pageNumber() * prefs.respagesize + it->second; } else { dn = -1; } @@ -213,9 +211,12 @@ int ResList::docnumfromparnum(int par) // Get paragraph number from document number int ResList::parnumfromdocnum(int docnum) { - if (m_winfirst == -1 || docnum - m_winfirst < 0) + if (m_pager->pageNumber() < 0) return -1; - docnum -= m_winfirst; + int winfirst = m_pager->pageNumber() * prefs.respagesize; + if (docnum - winfirst < 0) + return -1; + docnum -= winfirst; for (std::map::iterator it = m_pageParaToReldocnums.begin(); it != m_pageParaToReldocnums.end(); it++) { if (docnum == it->second) @@ -230,27 +231,28 @@ int ResList::parnumfromdocnum(int docnum) // result in a one-page change. bool ResList::getDoc(int docnum, Rcl::Doc &doc) { - LOGDEB(("ResList::getDoc: docnum %d m_winfirst %d\n", docnum, m_winfirst)); + LOGDEB(("ResList::getDoc: docnum %d winfirst %d\n", docnum, + m_pager->pageNumber() * prefs.respagesize)); if (docnum < 0) return false; + if (m_pager->pageNumber() < 0) + return false; + int winfirst = m_pager->pageNumber() * prefs.respagesize; // Is docnum in current page ? Then all Ok - if (docnum >= int(m_winfirst) && - docnum < int(m_winfirst + m_curDocs.size())) { - doc = m_curDocs[docnum - m_winfirst]; + if (docnum >= winfirst && docnum < winfirst + int(m_curDocs.size())) { + doc = m_curDocs[docnum - winfirst]; return true; } // Else we accept to page down or up but not further - if (docnum < int(m_winfirst) && - docnum >= int(m_winfirst) - prefs.respagesize) { + if (docnum < winfirst && docnum >= winfirst - prefs.respagesize) { resultPageBack(); - } else if (docnum < - int(m_winfirst + m_curDocs.size()) + prefs.respagesize) { + } else if (docnum < winfirst + int(m_curDocs.size()) + prefs.respagesize) { resultPageNext(); } - if (docnum >= int(m_winfirst) && - docnum < int(m_winfirst + m_curDocs.size())) { - doc = m_curDocs[docnum - m_winfirst]; + winfirst = m_pager->pageNumber() * prefs.respagesize; + if (docnum >= winfirst && docnum < winfirst + int(m_curDocs.size())) { + doc = m_curDocs[docnum - winfirst]; return true; } return false; @@ -323,23 +325,21 @@ void ResList::resPageDownOrNext() // 2 pages and show next page. void ResList::resultPageBack() { - if (m_winfirst <= 0) - return; - m_winfirst -= 2 * prefs.respagesize; - resultPageNext(); + m_pager->resultPageBack(); + displayPage(); } // Go to the first page void ResList::resultPageFirst() { - m_winfirst = -1; - resultPageNext(); + m_pager->resultPageFirst(); + displayPage(); } void ResList::append(const QString &text) { QTEXTBROWSER::append(text); -#if 0 +#if 1 { FILE *fp = fopen("/tmp/debugreslist", "a"); fprintf(fp, "%s\n", (const char *)text.utf8()); @@ -348,268 +348,88 @@ void ResList::append(const QString &text) #endif } +bool QtGuiResListPager::append(const string& data) +{ + LOGDEB1(("QtGuiReslistPager::append: %s\n", data.c_str())); + m_parent->append(QString::fromUtf8(data.c_str())); + return true; +} +bool QtGuiResListPager::append(const string& data, int i, const Rcl::Doc& doc) +{ + LOGDEB1(("QtGuiReslistPager::append: %d %s %s\n", + i, doc.url.c_str(), doc.ipath.c_str())); + m_parent->setCursorPosition(0,0); + m_parent->ensureCursorVisible(); + m_parent->m_pageParaToReldocnums[m_parent->paragraphs()] = i; + m_parent->m_curDocs.push_back(doc); + return append(data); +} + +string QtGuiResListPager::trans(const string& in) +{ + return string((const char*)ResList::tr(in.c_str()).utf8()); +} +string QtGuiResListPager::detailsLink() +{ + string chunk = ""; + chunk += (const char*)ResList::tr("(show query)"); + chunk += ""; + return chunk; +} +const string& QtGuiResListPager::parFormat() +{ + static string parformat; + if (parformat.empty()) + parformat = (const char*)prefs.reslistformat.utf8(); + return parformat; +} +string QtGuiResListPager::nextUrl() +{ + return "n-1"; +} +string QtGuiResListPager::prevUrl() +{ + return "p-1"; +} +string QtGuiResListPager::pageTop() +{ + m_parent->clear(); + return string(); +} + +string QtGuiResListPager::iconPath(const string& mtype) +{ + string iconpath; + RclConfig::getMainConfig()->getMimeIconName(mtype, &iconpath); + return iconpath; +} + // Fill up result list window with next screen of hits void ResList::resultPageNext() { - if (m_docSource.isNull()) - return; + m_pager->resultPageNext(); + displayPage(); +} - int resCnt = m_docSource->getResCnt(); +void ResList::displayPage() +{ + // Query term colorization + static QStyleSheetItem *item; + if (!item) { + item = new QStyleSheetItem(styleSheet(), "termtag" ); + if (item) + item->setColor(prefs.qtermcolor); + } + + m_curDocs.clear(); m_pageParaToReldocnums.clear(); - LOGDEB(("resultPageNext: rescnt %d, winfirst %d\n", resCnt, - m_winfirst)); - - bool hasPrev = false; - if (m_winfirst < 0) { - m_winfirst = 0; - } else { - m_winfirst += prefs.respagesize; - } - if (m_winfirst) - hasPrev = true; - emit prevPageAvailable(hasPrev); - - // Get the next page of results. - vector respage; - int pagelen = m_docSource->getSeqSlice(m_winfirst, - prefs.respagesize, respage); - - // If page was truncated, there is no next - bool hasNext = pagelen == prefs.respagesize; - emit nextPageAvailable(hasNext); - - if (pagelen <= 0) { - // No results ? This can only happen on the first page or if the - // actual result list size is a multiple of the page pref (else - // there would have been no Next on the last page) - if (m_winfirst) { - // Have already results. Let them show, just disable the - // Next button. We'd need to remove the Next link from the page - // too. - // Restore the m_winfirst value - m_winfirst -= prefs.respagesize; - return; - } - clear(); - QString chunk = "

"; - chunk += "

"; - chunk += QString::fromUtf8(m_docSource->title().c_str()); - chunk += "
"; - chunk += ""; - chunk += tr("Show query details"); - chunk += "
"; - append(chunk); - append(tr("

No results found
")); - if (m_winfirst < 0) - m_winfirst = -1; - return; - } - - clear(); - m_curDocs.clear(); - - // Query term colorization - QStyleSheetItem *item = new QStyleSheetItem(styleSheet(), "termtag" ); - item->setColor(prefs.qtermcolor); - - // Result paragraph format - string sformat = string(prefs.reslistformat.utf8()); - LOGDEB(("resultPageNext: format: [%s]\n", sformat.c_str())); - - // Display list header - // We could use a but the textedit doesnt display - // it prominently - // Note: have to append text in chunks that make sense - // html-wise. If we break things up too much, the editor - // gets confused. Hence the use of the 'chunk' text - // accumulator - // Also note that there can be results beyond the estimated resCnt. - QString chunk = "<qt><head></head><body><p>"; - - chunk += "<font size=+1><b>"; - chunk += QString::fromUtf8(m_docSource->title().c_str()); - chunk += ".</b></font>"; - - chunk += "   "; - - if (m_winfirst + pagelen < resCnt) { - chunk += - tr("Documents <b>%1-%2</b> out of at least <b>%3</b> for ") - .arg(m_winfirst+1) - .arg(m_winfirst+pagelen) - .arg(resCnt); - } else { - chunk += tr("Documents <b>%1-%2</b> for ") - .arg(m_winfirst+1) - .arg(m_winfirst+pagelen); - } - - chunk += "<a href=\"H-1\">"; - chunk += tr("(show query)"); - chunk += "</a>"; - - append(chunk); - - HiliteData hdata; - m_docSource->getTerms(hdata.terms, hdata.groups, hdata.gslks); - - // Insert results in result list window. We have to actually send - // the text to the widget (instead of setting the whole at the - // end), because we need the paragraph number each time we add a - // result paragraph (its diffult and error-prone to compute the - // paragraph numbers in parallel). We would like to disable - // updates while we're doing this, but couldn't find a way to make - // it work, the widget seems to become confused if appended while - // updates are disabled - // setUpdatesEnabled(false); - for (int i = 0; i < pagelen; i++) { - - Rcl::Doc &doc(respage[i].doc); - string& sh(respage[i].subHeader); - int percent; - if (doc.pc == -1) { - percent = 0; - // Document not available, maybe other further, will go on. - doc.meta[Rcl::Doc::keyabs] = string(tr("Unavailable document").utf8()); - } else { - percent = doc.pc; - } - // Percentage of 'relevance' - char perbuf[10]; - sprintf(perbuf, "%3d%% ", percent); - - // Determine icon to display if any - string iconpath; - (void)rclconfig->getMimeIconName(doc.mimetype, &iconpath); - - // Printable url: either utf-8 if transcoding succeeds, or url-encoded - string url; - printableUrl(rclconfig->getDefCharset(), doc.url, url); - - // Make title out of file name if none yet - if (doc.meta[Rcl::Doc::keytt].empty()) { - doc.meta[Rcl::Doc::keytt] = path_getsimple(url); - } - - // Result number - char numbuf[20]; - int docnumforlinks = m_winfirst + 1 + i; - sprintf(numbuf, "%d", docnumforlinks); - - // Document date: either doc or file modification time - char datebuf[100]; - datebuf[0] = 0; - if (!doc.dmtime.empty() || !doc.fmtime.empty()) { - time_t mtime = doc.dmtime.empty() ? - atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str()); - struct tm *tm = localtime(&mtime); -#ifndef sun - strftime(datebuf, 99, " %Y-%m-%d %H:%M:%S %z", tm); -#else - strftime(datebuf, 99, " %Y-%m-%d %H:%M:%S %Z", tm); -#endif - } - - // Size information. We print both doc and file if they differ a lot - long fsize = -1, dsize = -1; - if (!doc.dbytes.empty()) - dsize = atol(doc.dbytes.c_str()); - if (!doc.fbytes.empty()) - fsize = atol(doc.fbytes.c_str()); - string sizebuf; - if (dsize > 0) { - sizebuf = displayableBytes(dsize); - if (fsize > 10 * dsize && fsize - dsize > 1000) - sizebuf += string(" / ") + displayableBytes(fsize); - } else if (fsize >= 0) { - sizebuf = displayableBytes(fsize); - } - - string abstract; - if (prefs.queryBuildAbstract && - (doc.syntabs || prefs.queryReplaceAbstract)) { - abstract = m_docSource->getAbstract(doc); - } else { - abstract = doc.meta[Rcl::Doc::keyabs]; - } - // No need to call escapeHtml(), plaintorich handles it - list<string> lr; - PlainToRichQtReslist ptr; - ptr.plaintorich(abstract, lr, hdata); - string richabst = lr.front(); - - // Links; - string linksbuf; - char vlbuf[100]; - if (canIntern(doc.mimetype, rclconfig)) { - sprintf(vlbuf, "\"P%d\"", docnumforlinks); - linksbuf += string("<a href=") + vlbuf + ">" + "Preview" + "</a>" - + "  "; - } - if (!rclconfig->getMimeViewerDef(doc.mimetype).empty()) { - sprintf(vlbuf, "E%d", docnumforlinks); - linksbuf += string("<a href=") + vlbuf + ">" + "Open" + "</a>"; - } - - // Build the result list paragraph: - chunk = ""; - - // Subheader: this is used by history - if (!sh.empty()) - chunk += "<p><b>" + QString::fromUtf8(sh.c_str()) + "</p>\n<p>"; - else - chunk += "<p>"; - - // Configurable stuff - map<char,string> subs; - subs['A'] = !richabst.empty() ? richabst + "<br>" : ""; - subs['D'] = datebuf; - subs['I'] = iconpath; - subs['i'] = doc.ipath; - subs['K'] = !doc.meta[Rcl::Doc::keykw].empty() ? - escapeHtml(doc.meta[Rcl::Doc::keykw]) + "<br>" : ""; - subs['L'] = linksbuf; - subs['N'] = numbuf; - subs['M'] = doc.mimetype; - subs['R'] = perbuf; - subs['S'] = sizebuf; - subs['T'] = escapeHtml(doc.meta[Rcl::Doc::keytt]); - subs['U'] = url; - - string formatted; - pcSubst(sformat, formatted, subs); - chunk += QString::fromUtf8(formatted.c_str()); - - chunk += "</p>\n"; - - LOGDEB2(("Chunk: [%s]\n", (const char *)chunk.utf8())); - append(chunk); - setCursorPosition(0,0); - ensureCursorVisible(); - - m_pageParaToReldocnums[paragraphs()-1] = i; - m_curDocs.push_back(doc); - } - - // Footer - chunk = "<p align=\"center\">"; - if (hasPrev || hasNext) { - if (hasPrev) { - chunk += "<a href=\"p-1\"><b>"; - chunk += tr("Previous"); - chunk += "</b></a>   "; - } - if (hasNext) { - chunk += "<a href=\"n-1\"><b>"; - chunk += tr("Next"); - chunk += "</b></a>"; - } - } - chunk += "</p>\n"; - chunk += "</body></qt>\n"; - append(chunk); + m_pager->displayPage(); + LOGDEB0(("ResList::resultPageNext: hasNext %d hasPrev %d\n", + m_pager->hasPrev(), m_pager->hasNext())); + emit prevPageAvailable(m_pager->hasPrev()); + emit nextPageAvailable(m_pager->hasNext()); // Possibly color paragraph of current preview if any previewExposed(m_curPvDoc); ensureCursorVisible(); @@ -725,18 +545,17 @@ void ResList::menuPreview() void ResList::menuSeeParent() { Rcl::Doc doc; - if (getDoc(m_popDoc, doc)) { - Rcl::Doc doc1; - if (FileInterner::getEnclosing(doc.url, doc.ipath, - doc1.url, doc1.ipath)) { - emit previewRequested(doc1); - } else { - // No parent doc: show enclosing folder with app configured for - // directories - doc1.url = path_getfather(doc.url); - doc1.mimetype = "application/x-fsdirectory"; - emit editRequested(doc1); - } + if (!getDoc(m_popDoc, doc)) + return; + Rcl::Doc doc1; + if (FileInterner::getEnclosing(doc.url, doc.ipath, doc1.url, doc1.ipath)) { + emit previewRequested(doc1); + } else { + // No parent doc: show enclosing folder with app configured for + // directories + doc1.url = path_getfather(doc.url); + doc1.mimetype = "application/x-fsdirectory"; + emit editRequested(doc1); } } diff --git a/src/qtgui/reslist.h b/src/qtgui/reslist.h index 3380e0d6..6cf8bf1f 100644 --- a/src/qtgui/reslist.h +++ b/src/qtgui/reslist.h @@ -1,6 +1,6 @@ #ifndef _RESLIST_H_INCLUDED_ #define _RESLIST_H_INCLUDED_ -/* @(#$Id: reslist.h,v 1.16 2008-09-29 07:13:47 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: reslist.h,v 1.17 2008-12-16 14:20:10 dockes Exp $ (C) 2005 J.F.Dockes */ #include <list> @@ -25,6 +25,27 @@ class Q3PopupMenu; #include "filtseq.h" #include "refcntr.h" #include "rcldoc.h" +#include "reslistpager.h" + +class ResList; + +class QtGuiResListPager : public ResListPager { +public: + QtGuiResListPager(ResList *p, int ps) + : ResListPager(ps), m_parent(p) + {} + virtual bool append(const string& data); + virtual bool append(const string& data, int idx, const Rcl::Doc& doc); + virtual string trans(const string& in); + virtual string detailsLink(); + virtual const string &parFormat(); + virtual string nextUrl(); + virtual string prevUrl(); + virtual string pageTop(); + virtual string iconPath(const string& mt); +private: + ResList *m_parent; +}; /** * Display a list of document records. The data can be out of the history @@ -39,6 +60,7 @@ class ResList : public QTEXTBROWSER { Q_OBJECT; + friend class QtGuiResListPager; public: ResList(QWidget* parent = 0, const char* name = 0); virtual ~ResList(); @@ -63,9 +85,10 @@ class ResList : public QTEXTBROWSER virtual void doubleClicked(int, int); virtual void resPageUpOrBack(); // Page up pressed virtual void resPageDownOrNext(); // Page down pressed - virtual void resultPageBack(); // Display previous page of results - virtual void resultPageFirst(); // Display first page of results - virtual void resultPageNext(); // Display next (or first) page of results + virtual void resultPageBack(); // Previous page of results + virtual void resultPageFirst(); // First page of results + virtual void resultPageNext(); // Next (or first) page of results + virtual void displayPage(); // Display current page virtual void menuPreview(); virtual void menuEdit(); virtual void menuCopyFN(); @@ -102,6 +125,7 @@ class ResList : public QTEXTBROWSER virtual void showQueryDetails(); private: + QtGuiResListPager *m_pager; // Raw doc source RefCntr<DocSequence> m_baseDocSource; // Possibly filtered/sorted docsource (the one displayed) @@ -111,8 +135,7 @@ class ResList : public QTEXTBROWSER DocSeqFiltSpec m_filtspecs; // Docs for current page std::vector<Rcl::Doc> m_curDocs; - // First docnum (in m_docSource sequence) for current page - int m_winfirst; + // Translate from textedit paragraph number to relative // docnum. Built while we insert text into the qtextedit std::map<int,int> m_pageParaToReldocnums; @@ -122,6 +145,7 @@ class ResList : public QTEXTBROWSER list<int> m_selDocs; int m_listId; + virtual int docnumfromparnum(int); virtual int parnumfromdocnum(int); diff --git a/src/query/plaintorich.h b/src/query/plaintorich.h index 2686b05f..63e9b361 100644 --- a/src/query/plaintorich.h +++ b/src/query/plaintorich.h @@ -16,7 +16,7 @@ */ #ifndef _PLAINTORICH_H_INCLUDED_ #define _PLAINTORICH_H_INCLUDED_ -/* @(#$Id: plaintorich.h,v 1.1 2008-11-19 12:19:40 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: plaintorich.h,v 1.2 2008-12-16 14:20:10 dockes Exp $ (C) 2004 J.F.Dockes */ #include <string> #include <list> @@ -42,7 +42,7 @@ struct HiliteData { */ class PlainToRich { public: - PlainToRich(bool inputhtml = false) : m_inputhtml(inputhtml) {} + PlainToRich() : m_inputhtml(false) {} virtual ~PlainToRich() {} void set_inputhtml(bool v) {m_inputhtml = v;} diff --git a/src/query/reslistpager.cpp b/src/query/reslistpager.cpp index 8d110142..13a90a60 100644 --- a/src/query/reslistpager.cpp +++ b/src/query/reslistpager.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.6 2008-12-15 15:04:53 dockes Exp $ (C) 2007 J.F.Dockes"; +static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.7 2008-12-16 14:20:10 dockes Exp $ (C) 2007 J.F.Dockes"; #endif #include <stdio.h> @@ -13,19 +13,14 @@ static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.6 2008-12-15 15:04:53 dockes #include "plaintorich.h" #include "mimehandler.h" -// This should be passed as an input object to the pager instead +// Default highlighter class PlainToRichHtReslist : public PlainToRich { public: virtual ~PlainToRichHtReslist() {} virtual string startMatch() {return string("<font color=\"blue\">");} virtual string endMatch() {return string("</font>");} }; -// IDEM -struct Prefs { - bool queryBuildAbstract; - bool queryReplaceAbstract; -}; -Prefs prefs = {true, true}; +static PlainToRichHtReslist g_hiliter; void ResListPager::resultPageNext() { @@ -41,7 +36,7 @@ void ResListPager::resultPageNext() if (m_winfirst < 0) { m_winfirst = 0; } else { - m_winfirst += m_pagesize; + m_winfirst += m_respage.size(); } // Get the next page of results. vector<ResListEntry> npage; @@ -59,7 +54,7 @@ void ResListPager::resultPageNext() // Next button. We'd need to remove the Next link from the page // too. // Restore the m_winfirst value, let the current result vector alone - m_winfirst -= m_pagesize; + m_winfirst -= m_respage.size(); } else { // No results at all (on first page) m_winfirst = -1; @@ -71,14 +66,18 @@ void ResListPager::resultPageNext() void ResListPager::displayPage() { + LOGDEB(("ResListPager::displayPage\n")); if (m_docSource.isNull()) { LOGDEB(("ResListPager::displayPage: null source\n")); return; } - if (m_winfirst < 0) { + if (m_winfirst < 0 && !pageEmpty()) { LOGDEB(("ResListPager::displayPage: sequence error: winfirst < 0\n")); return; } + if (m_hiliter == 0) + m_hiliter = &g_hiliter; + string chunk; // Display list header @@ -89,10 +88,8 @@ void ResListPager::displayPage() // gets confused. Hence the use of the 'chunk' text // accumulator // Also note that there can be results beyond the estimated resCnt. - chunk = "<html><head>" - "<meta http-equiv=\"content-type\"" - "content=\"text/html; charset=utf-8\">" - "</head><body>"; + chunk = "<html><head><meta http-equiv=\"content-type\"" + "content=\"text/html; charset=utf-8\"></head><body>"; chunk += pageTop(); chunk += "<p><font size=+1><b>"; chunk += m_docSource->title(); @@ -100,17 +97,17 @@ void ResListPager::displayPage() "   "; if (pageEmpty()) { - chunk += tr("<p><b>No results found</b> for "); + chunk += trans("<p><b>No results found</b><br>"); } else { unsigned int resCnt = m_docSource->getResCnt(); if (m_winfirst + m_respage.size() < resCnt) { - string f1 = tr("Documents <b>%d-%d</b> out of at least <b>%d</b> for "); + string f1 = trans("Documents <b>%d-%d</b> out of at least <b>%d</b> for "); char buf[1024]; snprintf(buf, 1023, f1.c_str(), m_winfirst+1, m_winfirst + m_respage.size(), resCnt); chunk += buf; } else { - string f1 = tr("Documents <b>%d-%d</b> for "); + string f1 = trans("Documents <b>%d-%d</b> for "); char buf[1024]; snprintf(buf, 1023, f1.c_str(), m_winfirst + 1, m_winfirst + m_respage.size()); @@ -122,12 +119,12 @@ void ResListPager::displayPage() chunk += "  "; if (hasPrev()) { chunk += "<a href=\"" + prevUrl() + "\"><b>"; - chunk += tr("Previous"); + chunk += trans("Previous"); chunk += "</b></a>   "; } if (hasNext()) { chunk += "<a href=\""+ nextUrl() + "\"><b>"; - chunk += tr("Next"); + chunk += trans("Next"); chunk += "</b></a>"; } } @@ -137,7 +134,6 @@ void ResListPager::displayPage() if (pageEmpty()) return; - HiliteData hdata; m_docSource->getTerms(hdata.terms, hdata.groups, hdata.gslks); @@ -151,7 +147,7 @@ void ResListPager::displayPage() if (doc.pc == -1) { percent = 0; // Document not available, maybe other further, will go on. - doc.meta[Rcl::Doc::keyabs] = string(tr("Unavailable document")); + doc.meta[Rcl::Doc::keyabs] = string(trans("Unavailable document")); } else { percent = doc.pc; } @@ -160,9 +156,7 @@ void ResListPager::displayPage() sprintf(perbuf, "%3d%% ", percent); // Determine icon to display if any - string iconpath; - RclConfig::getMainConfig()->getMimeIconName(doc.mimetype, &iconpath); - iconpath = string("file://") + iconpath; + string iconpath = iconPath(doc.mimetype); // Printable url: either utf-8 if transcoding succeeds, or url-encoded string url; @@ -208,16 +202,15 @@ void ResListPager::displayPage() } string abstract; - if (prefs.queryBuildAbstract && - (doc.syntabs || prefs.queryReplaceAbstract)) { + if (m_queryBuildAbstract && (doc.syntabs || m_queryReplaceAbstract)) { abstract = m_docSource->getAbstract(doc); } else { abstract = doc.meta[Rcl::Doc::keyabs]; } // No need to call escapeHtml(), plaintorich handles it list<string> lr; - PlainToRichHtReslist ptr; - ptr.plaintorich(abstract, lr, hdata); + m_hiliter->set_inputhtml(false); + m_hiliter->plaintorich(abstract, lr, hdata); string richabst = lr.front(); // Links; @@ -225,12 +218,13 @@ void ResListPager::displayPage() char vlbuf[100]; if (canIntern(doc.mimetype, RclConfig::getMainConfig())) { sprintf(vlbuf, "\"P%d\"", docnumforlinks); - linksbuf += string("<a href=") + vlbuf + ">" + "Preview" + "</a>" - + "  "; + linksbuf += string("<a href=") + vlbuf + ">" + trans("Preview") + + "</a>  "; } if (!RclConfig::getMainConfig()->getMimeViewerDef(doc.mimetype).empty()) { sprintf(vlbuf, "E%d", docnumforlinks); - linksbuf += string("<a href=") + vlbuf + ">" + "Open" + "</a>"; + linksbuf += string("<a href=") + vlbuf + ">" + trans("Open") + + "</a>"; } // Build the result list paragraph: @@ -265,7 +259,7 @@ void ResListPager::displayPage() chunk += "</p>\n"; LOGDEB2(("Chunk: [%s]\n", (const char *)chunk.c_str())); - append(chunk); + append(chunk, i, doc); } // Footer @@ -273,12 +267,12 @@ void ResListPager::displayPage() if (hasPrev() || hasNext()) { if (hasPrev()) { chunk += "<a href=\"" + prevUrl() + "\"><b>"; - chunk += tr("Previous"); + chunk += trans("Previous"); chunk += "</b></a>   "; } if (hasNext()) { chunk += "<a href=\""+ nextUrl() + "\"><b>"; - chunk += tr("Next"); + chunk += trans("Next"); chunk += "</b></a>"; } } @@ -296,6 +290,14 @@ string ResListPager::prevUrl() return "p-1"; } +string ResListPager::iconPath(const string& mtype) +{ + string iconpath; + RclConfig::getMainConfig()->getMimeIconName(mtype, &iconpath); + iconpath = string("file://") + iconpath; + return iconpath; +} + // Default implementations for things that should be re-implemented by our user. bool ResListPager::append(const string& data) { @@ -303,7 +305,7 @@ bool ResListPager::append(const string& data) return true; } -string ResListPager::tr(const string& in) +string ResListPager::trans(const string& in) { return in; } @@ -311,7 +313,7 @@ string ResListPager::tr(const string& in) string ResListPager::detailsLink() { string chunk = "<a href=\"H-1\">"; - chunk += tr("(show query)") + "</a>"; + chunk += trans("(show query)") + "</a>"; return chunk; } diff --git a/src/query/reslistpager.h b/src/query/reslistpager.h index b9a9e0d4..648f2572 100644 --- a/src/query/reslistpager.h +++ b/src/query/reslistpager.h @@ -1,6 +1,6 @@ #ifndef _reslistpager_h_included_ #define _reslistpager_h_included_ -/* @(#$Id: reslistpager.h,v 1.3 2008-12-04 11:49:59 dockes Exp $ (C) 2007 J.F.Dockes */ +/* @(#$Id: reslistpager.h,v 1.4 2008-12-16 14:20:10 dockes Exp $ (C) 2007 J.F.Dockes */ #include <vector> using std::vector; @@ -8,24 +8,31 @@ using std::vector; #include "refcntr.h" #include "docseq.h" +class PlainToRich; + /** - * Produces html text for a paged result list. + * Manage a paged HTML result list. */ class ResListPager { public: - ResListPager() : m_pagesize(10), m_hasNext(false) {} + ResListPager(int pagesize=10) : m_pagesize(pagesize) {initall();} + ResListPager(RefCntr<DocSequence> src, int pagesize) + : m_pagesize(pagesize) + { + initall(); + m_docSource = src; + } + virtual ~ResListPager() {} + + void setHighLighter(PlainToRich *ptr) {m_hiliter = ptr;} void setDocSource(RefCntr<DocSequence> src) { m_winfirst = -1; - m_docSource = src; m_hasNext = false; m_respage.clear(); + m_docSource = src; } - ResListPager(RefCntr<DocSequence> src, int pagesize) - : m_winfirst(-1), m_docSource(src), m_pagesize(pagesize), - m_hasNext(false) - {} - virtual ~ResListPager() {} + int pageNumber() { if (m_winfirst < 0 || m_pagesize <= 0) @@ -55,13 +62,28 @@ public: // Things that need to be reimplemented in the subclass: virtual bool append(const string& data); - virtual string tr(const string& in); + virtual bool append(const string& data, int, const Rcl::Doc&) + { + return append(data); + } + virtual string trans(const string& in); virtual string detailsLink(); virtual const string &parFormat(); virtual string nextUrl(); virtual string prevUrl(); virtual string pageTop() {return string();} + virtual string iconPath(const string& mtype); private: + void initall() + { + m_winfirst = -1; + m_hasNext = false; + m_respage.clear(); + m_queryBuildAbstract = true; + m_queryReplaceAbstract = false; + m_hiliter = 0; + } + // First docnum (from docseq) in current page int m_winfirst; RefCntr<DocSequence> m_docSource; @@ -69,6 +91,9 @@ private: bool m_hasNext; vector<ResListEntry> m_respage; + bool m_queryBuildAbstract; + bool m_queryReplaceAbstract; + PlainToRich *m_hiliter; }; #endif /* _reslistpager_h_included_ */ diff --git a/src/utils/debuglog.cpp b/src/utils/debuglog.cpp index a03b513b..31609a75 100755 --- a/src/utils/debuglog.cpp +++ b/src/utils/debuglog.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: debuglog.cpp,v 1.5 2007-01-16 10:58:09 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: debuglog.cpp,v 1.6 2008-12-16 14:20:10 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -29,9 +29,16 @@ static char rcsid[] = "@(#$Id: debuglog.cpp,v 1.5 2007-01-16 10:58:09 dockes Exp #include <new.h> #endif -#include <stack> +#include <string> +#include <set> +#include <list> +using std::set; +using std::string; +using std::list; #include "debuglog.h" +#include "pathut.h" +#include "smallut.h" #ifndef freeZ #define freeZ(X) {if (X) {free(X);X=0;}} @@ -152,7 +159,26 @@ int DebugLogFileWriter::put(const char *s) return impl ? impl->put(s) : -1; }; - +static set<string> yesfiles; +static void initfiles() +{ + const char *cp = getenv("DEBUGLOG_FILES"); + if (!cp) + return; + list<string> files; + stringToTokens(cp, files, ","); + yesfiles.insert(files.begin(), files.end()); +} +static bool fileInFiles(const string& file) +{ + string sf = path_getsimple(file); + if (yesfiles.find(sf) != yesfiles.end()) { + //fprintf(stderr, "Debug ON: %s \n", file.c_str()); + return true; + } + //fprintf(stderr, "Debug OFF: %s \n", file.c_str()); + return false; +} #ifdef _WINDOWS #include <windows.h> @@ -186,6 +212,12 @@ DebugLog::prolog(int lev, const char *f, int line) { if (!writer) return; + if (!yesfiles.empty() && !fileInFiles(f)) { + fileyes = false; + return; + } else { + fileyes = true; + } if (dodate) { char dts[100]; datestring(dts); @@ -210,7 +242,7 @@ DebugLog::prolog(int lev, const char *f, int line) void DebugLog::log(const char *s ...) { - if (!writer) + if (!writer || !fileyes) return; va_list ap; va_start(ap,s); @@ -308,6 +340,7 @@ DebugLog *getdbl() if (!(dbl = (DebugLog *)pthread_getspecific(dbl_key))) { dbl = new DebugLog; dbl->setwriter(theWriter); + initfiles(); status = pthread_setspecific(dbl_key, dbl); if (status) { fprintf(stderr, "debuglog: cant initialize pthread " @@ -326,6 +359,7 @@ DebugLog *getdbl() if (!dbl) { dbl = new DebugLog; dbl->setwriter(theWriter); + initfiles(); } return dbl; } diff --git a/src/utils/debuglog.h b/src/utils/debuglog.h index 211f0c69..61963a3c 100755 --- a/src/utils/debuglog.h +++ b/src/utils/debuglog.h @@ -44,13 +44,15 @@ namespace DebugLog { class DebugLogWriter; class DebugLog { - std::stack<int> levels; + stack<int> levels; int debuglevel; int dodate; DebugLogWriter *writer; + bool fileyes; public: - DebugLog() : debuglevel(10), dodate(0), writer(0) {} - DebugLog(DebugLogWriter *w) : debuglevel(-1), dodate(0), writer(w) {} + DebugLog() : debuglevel(10), dodate(0), writer(0), fileyes(true) {} + DebugLog(DebugLogWriter *w) : debuglevel(-1), dodate(0), writer(w), + fileyes(true) {} virtual ~DebugLog() {} virtual void setwriter(DebugLogWriter *w) {writer = w;} virtual DebugLogWriter *getwriter() {return writer;}