diff --git a/src/kde/kioslave/recoll/00README.txt b/src/kde/kioslave/recoll/00README.txt index 7e7c8c7e..c9064d84 100644 --- a/src/kde/kioslave/recoll/00README.txt +++ b/src/kde/kioslave/recoll/00README.txt @@ -1,6 +1,4 @@ -(this used to work but last time I tried with konqueror (kde3, 11-2007), it failed with "protocol not authorized" or such. Didn't investigate more). - This is a small experiment with a recoll kio_slave A kio_slave was implemented, supporting the "get" operation. Ie, you type @@ -15,25 +13,38 @@ quite useful in this case. Implementation notes: ----------------------- +- There are two main ways to do this: + - a-la kio_beagle, using listDir() to list entries pointing to the + different operations or objects (help, status, search result + entries, bookmarks, whatever...). The nice thing is that the + results really look like file object in a directory (probably, + didn't try it actually), no need for look and feel, it's provided by kde + + - Or a la strigi: all interactions are through html pages and get() + operations. Looks less like a normal konqueror file-system + listing, and needs more html coding but all in all probably + simpler. + + Recoll is currently doing the html thing. As far as I understand, the + way to trigger a listdir is to have a inode/directory default mime + type in the protocol file, and return inode/directory when + appropriate in mimetype() (look at kio_beagle). Some kde daemon needs + to be restarted when doing this (the protocol file is cached + somewhere). + +Also would need a page header, configuration polish etc... Not done for +the same reason, this is a proof of concept. + +KDE3 notes - Not using libtool. Probably should. compilation flags in the Makefile were copy-pasted from a kdebase compilation tree on FreeBSD (kio/man). - - You MUST install a kio_recoll.la in lib/kde3 along with kio_recoll.so, else kdeinit won't be able to load the lib (probably uses the libltdl thingy?). The one in this directory was duplicated/adjusted from kio_man.la. The contents don't seem too critical, just needs to exist. - -- Currently retrieves all results on one page. Need to add state and - previous/next buttons. As I didn't find this thing to be particularly - useful, I didn't bothered to. - -- Also would need a page header, configuration polish etc... Not done for - the same reason, this is a proof of concept. - - If you want to try, compile, then install kio_recoll.la kio_recoll.so wherever kde keeps its plugins (ie: lib/kde3), and recoll.protocol in the services directory (share/services ? look for other .protocol file). - - I saw after doing the build/config mockup that kdevelop can generate a kio_slave project. This might be the next thing to do. otoh would need to separate the kio from the main source to avoid having to distribute 2megs diff --git a/src/kde/kioslave/recoll/CMakeLists.txt b/src/kde/kioslave/recoll/CMakeLists.txt index 07a50677..f67c9c84 100644 --- a/src/kde/kioslave/recoll/CMakeLists.txt +++ b/src/kde/kioslave/recoll/CMakeLists.txt @@ -7,40 +7,44 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules ) include(InstallRequiredSystemLibraries) -#set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Recoll KIO Slave") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Recoll KIO Slave") #set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") #set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") -#set(CPACK_PACKAGE_VERSION "${VERSION}") -#set(CPACK_GENERATOR TGZ) -#set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION}" CACHE INTERNAL " -#tarball basename") -#SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME} ${CPACK_PACKAGE_VERSION}") -#include(CPack) +set(CPACK_PACKAGE_VERSION "${VERSION}") +set(CPACK_GENERATOR TGZ) +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION}" CACHE INTERNAL "tarball basename") +SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME} ${CPACK_PACKAGE_VERSION}") +include(CPack) # search packages used by KDE find_package(KDE4 REQUIRED) -include (UsePkgConfig) -include (KDE4Defaults) -include (MacroLibrary) +include(UsePkgConfig) +include(KDE4Defaults) +include(MacroLibrary) include(MacroOptionalAddSubdirectory) -add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) +add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) +add_definitions(-DKDE_DEFAULT_DEBUG_AREA=7130) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") set(depth ../../../) +set(rcltop ${CMAKE_CURRENT_SOURCE_DIR}/${depth}) include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES} -${depth}/utils ${depth}/rcldb ${depth}/query ${depth}/unac -${depth}/common ${depth}/internfile ${depth}/index ${depth}/bincimapmime + ${rcltop}/utils ${rcltop}/rcldb ${rcltop}/query ${rcltop}/unac + ${rcltop}/common ${rcltop}/internfile ${rcltop}/index ${rcltop}/bincimapmime ) -set(kio_recoll_SRCS - kio_recoll.cpp -) +set(kio_recoll_SRCS kio_recoll.cpp) kde4_add_plugin(kio_recoll ${kio_recoll_SRCS}) -link_directories(/home/dockes/projets/fulltext/recoll/src/lib) -target_link_libraries(kio_recoll rcl xapian ${KDE4_KIO_LIBS}) +target_link_libraries(kio_recoll + ${rcltop}/lib/librcl.a + ${rcltop}/bincimapmime/libmime.a + xapian ${KDE4_KIO_LIBS}) install(TARGETS kio_recoll DESTINATION ${PLUGIN_INSTALL_DIR}) -install(FILES recoll.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) +install(FILES recoll.protocol DESTINATION ${SERVICES_INSTALL_DIR}) +install(FILES data/welcome.html + DESTINATION ${DATA_INSTALL_DIR}/kio_recoll) diff --git a/src/kde/kioslave/recoll/data/welcome.html b/src/kde/kioslave/recoll/data/welcome.html new file mode 100644 index 00000000..b13ff2b7 --- /dev/null +++ b/src/kde/kioslave/recoll/data/welcome.html @@ -0,0 +1,20 @@ + + + + Recoll Search + + + +

Recoll search

+ +

+ Query type:
+ Query language
+ All terms
+ Any term
+ + Enter search string: +

+ + + diff --git a/src/kde/kioslave/recoll/kio_recoll.cpp b/src/kde/kioslave/recoll/kio_recoll.cpp index 989a547d..ba71ebc7 100644 --- a/src/kde/kioslave/recoll/kio_recoll.cpp +++ b/src/kde/kioslave/recoll/kio_recoll.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.14 2008-11-19 12:28:59 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.15 2008-11-20 13:10:23 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #include @@ -26,6 +26,7 @@ using namespace std; //#include #include +#include #include "rclconfig.h" #include "rcldb.h" @@ -36,9 +37,65 @@ using namespace std; #include "wasastringtoquery.h" #include "wasatorcl.h" #include "kio_recoll.h" +#include "docseqdb.h" +#include "readfile.h" +#include "smallut.h" using namespace KIO; +bool RecollKioPager::append(const string& data) +{ + if (!m_parent) return false; + m_parent->data(QByteArray(data.c_str())); + return true; +} + +string RecollKioPager::detailsLink() +{ + string chunk = ""; + chunk += tr("(show query)") + ""; + return chunk; +} + +const static string parformat = + "" + "%R %S " + "Open  %T
" + "%M %D   %U
" + "%A %K"; +const string &RecollKioPager::parFormat() +{ + return parformat; +} + +string RecollKioPager::pageTop() +{ + return "

New Search

"; +} + +string RecollKioPager::nextUrl() +{ + int pagenum = pageNumber(); + if (pagenum < 0) + pagenum = 0; + else + pagenum++; + char buf[100]; + sprintf(buf, "recoll://command/Page%d", pagenum); + return buf; +} +string RecollKioPager::prevUrl() +{ + int pagenum = pageNumber(); + if (pagenum <= 0) + pagenum = 0; + else + pagenum--; + char buf[100]; + sprintf(buf, "recoll://command/Page%d", pagenum); + return buf; +} + static RclConfig *rclconfig; RclConfig *RclConfig::getMainConfig() { @@ -49,6 +106,7 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app) : SlaveBase("recoll", pool, app), m_initok(false), m_rclconfig(0), m_rcldb(0) { + m_pager.setParent(this); string reason; rclconfig = m_rclconfig = recollinit(0, 0, m_reason); if (!m_rclconfig || !m_rclconfig->ok()) { @@ -99,9 +157,86 @@ bool RecollProtocol::maybeOpenDb(string &reason) return true; } +static string welcomedata; + +void RecollProtocol::welcomePage() +{ + kDebug() << endl; + if (welcomedata.empty()) { + QString location = + KStandardDirs::locate("data", "kio_recoll/welcome.html"); + string reason; + if (location.isEmpty() || + !file_to_string((const char *)location.toUtf8(), + welcomedata, &reason)) { + welcomedata = "Recoll Error" + "

Could not locate Recoll welcome.html file: "; + welcomedata += reason; + welcomedata += "

"; + } + } + string tmp; + map subs; + subs['Q'] = ""; + pcSubst(welcomedata, tmp, subs); + data(tmp.c_str()); + kDebug() << "WelcomePage done" << endl; +} + +void RecollProtocol::doSearch(const QString& q, char opt) +{ + string qs = (const char *)q.toUtf8(); + Rcl::SearchData *sd = 0; + if (opt != 'l') { + Rcl::SearchDataClause *clp = 0; + if (opt == 'f') { + clp = new Rcl::SearchDataClauseFilename(qs); + } else { + // If there is no white space inside the query, then the user + // certainly means it as a phrase. + bool isreallyaphrase = false; + if (qs.find_first_of(" \t") == string::npos) + isreallyaphrase = true; + clp = isreallyaphrase ? + new Rcl::SearchDataClauseDist(Rcl::SCLT_PHRASE, qs, 0) : + new Rcl::SearchDataClauseSimple(opt == 'o' ? + Rcl::SCLT_OR : Rcl::SCLT_AND, + qs); + } + sd = new Rcl::SearchData(Rcl::SCLT_OR); + if (sd && clp) + sd->addClause(clp); + } else { + kDebug() << "Parsing query"; + sd = wasaStringToRcl(qs, m_reason); + } + if (!sd) { + m_reason = "Internal Error: cant allocate new query"; + outputError(m_reason.c_str()); + finished(); + return; + } + + RefCntr sdata(sd); + sdata->setStemlang("english"); + RefCntrquery(new Rcl::Query(m_rcldb)); + if (!query->setQuery(sdata)) { + m_reason = "Internal Error: setQuery failed"; + outputError(m_reason.c_str()); + finished(); + return; + } + DocSequenceDb *src = + new DocSequenceDb(RefCntr(query), "Query results", + sdata); + + m_pager.setDocSource(RefCntr(src)); + m_pager.resultPageNext(); +} + void RecollProtocol::get(const KUrl & url) { - kDebug() << "RecollProtocol::get:" << url << endl; + kDebug() << url << endl; mimeType("text/html"); @@ -111,98 +246,75 @@ void RecollProtocol::get(const KUrl & url) return; } - string iconsdir; - m_rclconfig->getConfParam("iconsdir", iconsdir); - if (iconsdir.empty()) { - iconsdir = path_cat("/usr/local/share/recoll", "images"); - } else { - iconsdir = path_tildexpand(iconsdir); - } - + QString host = url.host(); QString path = url.path(); - kDebug() << "RecollProtocol::get:path:" << path << endl; - QByteArray u8 = path.toUtf8(); + kDebug() << "host:" << host << " path:" << path; + if (host.isEmpty() || !host.compare("welcome")) { + kDebug() << "Host is empty"; + if (path.isEmpty() || !path.compare("/")) { + kDebug() << "Path is empty or strange"; + // Display welcome page + welcomePage(); + finished(); + return; + } + // Ie: "recoll: some search string" + doSearch(path); + } else if (!host.compare("search")) { + if (path.compare("/query")) { + finished(); return; + } + // Decode the forms' arguments + QString query = url.queryItem("q"); + if (query.isEmpty()) { + finished(); return; + } + QString opt = url.queryItem("qtp"); + if (opt.isEmpty()) { + opt = "l"; + } + doSearch(query, opt.toUtf8().at(0)); + } else if (!host.compare("command")) { + if (path.isEmpty()) { + finished();return; + } else if (path.indexOf("/Page") == 0) { + int newpage = 0; + sscanf(path.toUtf8(), "/Page%d", &newpage); + if (newpage > m_pager.pageNumber()) { + int npages = newpage - m_pager.pageNumber(); + for (int i = 0; i < npages; i++) + m_pager.resultPageNext(); + } else if (newpage < m_pager.pageNumber()) { + int npages = m_pager.pageNumber() - newpage; + for (int i = 0; i < npages; i++) + m_pager.resultPageBack(); + } + } else if (path.indexOf("/QueryDetails") == 0) { + QByteArray array; + QTextStream os(&array, QIODevice::WriteOnly); - RefCntr sdata = wasaStringToRcl((const char*)u8, m_reason); - sdata->setStemlang("english"); - - RefCntrquery(new Rcl::Query(m_rcldb)); - if (!query->setQuery(sdata)) { - m_reason = "Internal Error: setQuery failed"; - outputError(m_reason.c_str()); - finished(); - return; + os << "" << endl; + os << "" << "Recoll query details" << "\n" << endl; + os << "" << endl; + os << "

Query details:

" << endl; + os << "

" << m_pager.queryDescription().c_str() <<"

"<< endl; + os << "

Return to results" << endl; + os << "" << endl; + data(array); + finished(); + return; + } else { + // Unknown //command/??? + finished(); return; + } + } else { + // Unknown 'host' //??? value + finished(); return; } - string explain = sdata->getDescription(); + m_pager.displayPage(); - QByteArray output; - QTextStream os(&output, QIODevice::ReadWrite); - - os << "" << endl; - os << "" << endl; - os << "" << endl; - os << "" << endl; - os << "Recoll: query results" << endl; - os << "" << endl; - - os << "

Actual query performed: " << endl; - os << explain.c_str() << "

"; - - Rcl::Doc doc; - int cnt = query->getResCnt(); - for (int i = 0; i < cnt; i++) { - string sh; - doc.erase(); - - if (!query->getDoc(i, doc)) { - // This may very well happen for history if the doc has - // been removed since. So don't treat it as fatal. - doc.meta[Rcl::Doc::keykw] = string("Unavailable document"); - } - - string iconname = m_rclconfig->getMimeIconName(doc.mimetype); - if (iconname.empty()) - iconname = "document"; - string imgfile = iconsdir + "/" + iconname + ".png"; - - string result; - if (!sh.empty()) - result += string("

") + sh + "

\n

"; - else - result = "

"; - - char perbuf[10]; - sprintf(perbuf, "%3d%%", doc.pc); - if (doc.meta[Rcl::Doc::keytt].empty()) - doc.meta[Rcl::Doc::keytt] = path_getsimple(doc.url); - 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); - strftime(datebuf, 99, - "Modified: %Y-%m-%d %H:%M:%S", tm); - } - result += "" + - "" + ""; - string abst = escapeHtml(doc.meta[Rcl::Doc::keyabs]); - result += string(perbuf) + " " + doc.meta[Rcl::Doc::keytt] + "
" + - doc.mimetype + " " + - (datebuf[0] ? string(datebuf) + "
" : string("
")) + - (!abst.empty() ? abst + "
" : string("")) + - (!doc.meta[Rcl::Doc::keytt].empty() ? doc.meta[Rcl::Doc::keykw] + - "
" : string("")) + - "" + doc.url + "

\n"; - - QString str = QString::fromUtf8(result.c_str(), result.length()); - os << str; - } - - os << ""; - - data(output); kDebug() << "call finished" << endl; finished(); } @@ -221,6 +333,8 @@ void RecollProtocol::outputError(const QString& errmsg) data(array); } + + // Note: KDE_EXPORT is actually needed on Unix when building with // cmake. Says something like __attribute__(visibility(defautl)) // (cmake apparently sets all symbols to not exported) @@ -228,9 +342,6 @@ extern "C" {KDE_EXPORT int kdemain(int argc, char **argv);} int kdemain(int argc, char **argv) { - FILE*mf = fopen("/tmp/toto","w"); - fprintf(mf, "KIORECOLL\n"); - fclose(mf); #ifdef KDE_VERSION_3 KInstance instance("kio_recoll"); #else diff --git a/src/kde/kioslave/recoll/kio_recoll.h b/src/kde/kioslave/recoll/kio_recoll.h index 1ec47034..6c1e7a70 100644 --- a/src/kde/kioslave/recoll/kio_recoll.h +++ b/src/kde/kioslave/recoll/kio_recoll.h @@ -1,5 +1,5 @@ #ifndef _RECOLL_H -/* @(#$Id: kio_recoll.h,v 1.5 2008-11-17 14:51:38 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: kio_recoll.h,v 1.6 2008-11-20 13:10:23 dockes Exp $ (C) 2005 J.F.Dockes */ #define _RECOLL_H #include @@ -17,6 +17,25 @@ using std::string; #include #include +#include "reslistpager.h" + +class RecollProtocol; + +class RecollKioPager : public ResListPager { +public: + RecollKioPager() : m_parent(0) {} + void setParent(RecollProtocol *proto) {m_parent = proto;} + + virtual bool append(const string& data); + virtual string detailsLink(); + virtual const string &parFormat(); + virtual string nextUrl(); + virtual string prevUrl(); + virtual string pageTop(); +private: + RecollProtocol *m_parent; +}; + class RecollProtocol : public KIO::SlaveBase { public: RecollProtocol(const QByteArray &pool, const QByteArray &app ); @@ -25,13 +44,18 @@ class RecollProtocol : public KIO::SlaveBase { virtual void get(const KUrl & url ); private: - bool m_initok; - RclConfig *m_rclconfig; - Rcl::Db *m_rcldb; - std::string m_dbdir; - std::string m_reason; bool maybeOpenDb(string &reason); void outputError(const QString& errmsg); + void doSearch(const QString& q, char opt = 'l'); + void welcomePage(); + + bool m_initok; + RclConfig *m_rclconfig; + Rcl::Db *m_rcldb; + std::string m_dbdir; + std::string m_reason; + RecollKioPager m_pager; + }; extern "C" {int kdemain(int, char**);} diff --git a/src/query/reslistpager.cpp b/src/query/reslistpager.cpp index c06bf07f..1b1668df 100644 --- a/src/query/reslistpager.cpp +++ b/src/query/reslistpager.cpp @@ -1,7 +1,11 @@ #ifndef lint -static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.1 2008-11-19 12:19:40 dockes Exp $ (C) 2007 J.F.Dockes"; +static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.2 2008-11-20 13:10:23 dockes Exp $ (C) 2007 J.F.Dockes"; #endif +#include +#include +#include + #include "reslistpager.h" #include "debuglog.h" #include "rclconfig.h" @@ -63,31 +67,9 @@ void ResListPager::resultPageNext() m_respage = npage; } -bool ResListPager::append(const string& data) -{ - fprintf(stderr, "%s", data.c_str()); - return true; -} - -string ResListPager::tr(const string& in) -{ - return in; -} - void ResListPager::displayPage() { string chunk; - if (pageEmpty()) { - chunk = "" - "

"; - chunk += m_docSource->title(); - chunk += ""; - chunk += ""; - chunk += tr("Show query details"); - chunk += "
"; - append(chunk); - return; - } // Display list header // We could use a but the textedit doesnt display @@ -97,8 +79,12 @@ 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 = "<qt><head></head><body><p>" - "<font size=+1><b>"; + 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(); chunk += "</b></font>" "   "; @@ -121,9 +107,21 @@ void ResListPager::displayPage() chunk += buf; } } - chunk += "<a href=\"H-1\">"; - chunk += tr("(show query)"); - chunk += "</a></p>"; + chunk += detailsLink(); + if (hasPrev() || hasNext()) { + chunk += "  "; + if (hasPrev()) { + chunk += "<a href=\"" + prevUrl() + "\"><b>"; + chunk += tr("Previous"); + chunk += "</b></a>   "; + } + if (hasNext()) { + chunk += "<a href=\""+ nextUrl() + "\"><b>"; + chunk += tr("Next"); + chunk += "</b></a>"; + } + } + chunk += "</p>"; append(chunk); if (pageEmpty()) @@ -154,6 +152,7 @@ void ResListPager::displayPage() // Determine icon to display if any string iconpath; RclConfig::getMainConfig()->getMimeIconName(doc.mimetype, &iconpath); + iconpath = string("file://") + iconpath; // Printable url: either utf-8 if transcoding succeeds, or url-encoded string url; @@ -249,7 +248,7 @@ void ResListPager::displayPage() subs['U'] = url; string formatted; - pcSubst(m_parformat, formatted, subs); + pcSubst(parFormat(), formatted, subs); chunk += formatted; chunk += "</p>\n"; @@ -262,12 +261,12 @@ void ResListPager::displayPage() chunk = "<p align=\"center\">"; if (hasPrev() || hasNext()) { if (hasPrev()) { - chunk += "<a href=\"p-1\"><b>"; + chunk += "<a href=\"" + prevUrl() + "\"><b>"; chunk += tr("Previous"); chunk += "</b></a>   "; } if (hasNext()) { - chunk += "<a href=\"n-1\"><b>"; + chunk += "<a href=\""+ nextUrl() + "\"><b>"; chunk += tr("Next"); chunk += "</b></a>"; } @@ -276,3 +275,41 @@ void ResListPager::displayPage() chunk += "</body></html>\n"; append(chunk); } + +string ResListPager::nextUrl() +{ + return "n-1"; +} +string ResListPager::prevUrl() +{ + return "p-1"; +} + +// Default implementations for things that should be re-implemented by our user. +bool ResListPager::append(const string& data) +{ + fprintf(stderr, "%s", data.c_str()); + return true; +} + +string ResListPager::tr(const string& in) +{ + return in; +} + +string ResListPager::detailsLink() +{ + string chunk = "<a href=\"H-1\">"; + chunk += tr("(show query)") + "</a>"; + return chunk; +} + +const string &ResListPager::parFormat() +{ + const static string format("<img src=\"%I\" align=\"left\">" + "%R %S %L   <b>%T</b><br>" + "%M %D   <i>%U</i><br>" + "%A %K"); + return format; +} + diff --git a/src/query/reslistpager.h b/src/query/reslistpager.h index 98f479ce..4811028b 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.1 2008-11-19 12:19:40 dockes Exp $ (C) 2007 J.F.Dockes */ +/* @(#$Id: reslistpager.h,v 1.2 2008-11-20 13:10:23 dockes Exp $ (C) 2007 J.F.Dockes */ #include <vector> using std::vector; @@ -13,12 +13,25 @@ using std::vector; */ class ResListPager { public: - ResListPager(RefCntr<DocSequence> src, int pagesize, - const string& parformat) - : m_docSource(src), m_pagesize(pagesize), m_parformat(parformat), - m_hasNext(false) + ResListPager() : m_pagesize(10), m_hasNext(false) {} + void setDocSource(RefCntr<DocSequence> src) + { + m_winfirst = -1; + m_docSource = src; + m_hasNext = false; + m_respage.clear(); + } + 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) + return -1; + return m_winfirst / m_pagesize; + } void pageNext(); bool hasNext() {return m_hasNext;} bool hasPrev() {return m_winfirst > 0;} @@ -35,14 +48,24 @@ public: void resultPageNext(); void displayPage(); bool pageEmpty() {return m_respage.size() == 0;} + + string queryDescription() {return m_docSource.isNull() ? "" : + m_docSource->getDescription();} + + // Things that need to be reimplemented in the subclass: virtual bool append(const string& data); virtual string tr(const string& in); + virtual string detailsLink(); + virtual const string &parFormat(); + virtual string nextUrl(); + virtual string prevUrl(); + virtual string pageTop() {return string();} + private: // First docnum (from docseq) in current page int m_winfirst; RefCntr<DocSequence> m_docSource; int m_pagesize; - string m_parformat; bool m_hasNext; vector<ResListEntry> m_respage;