diff --git a/src/kde/kioslave/recoll/CMakeLists.txt b/src/kde/kioslave/recoll/CMakeLists.txt index cdba9852..c1e063ea 100644 --- a/src/kde/kioslave/recoll/CMakeLists.txt +++ b/src/kde/kioslave/recoll/CMakeLists.txt @@ -42,6 +42,7 @@ ${rcltop}/common/textsplit.cpp ${rcltop}/common/unacpp.cpp ${rcltop}/index/mimetype.cpp ${rcltop}/internfile/htmlparse.cpp +${rcltop}/internfile/internfile.cpp ${rcltop}/internfile/myhtmlparse.cpp ${rcltop}/internfile/mimehandler.cpp ${rcltop}/internfile/mh_exec.cpp diff --git a/src/kde/kioslave/recoll/data/help.html b/src/kde/kioslave/recoll/data/help.html index 6e86f180..ae2e9b3f 100644 --- a/src/kde/kioslave/recoll/data/help.html +++ b/src/kde/kioslave/recoll/data/help.html @@ -16,8 +16,8 @@

The module is still in its infancy. You will undoubtedly obtain @@ -41,8 +41,8 @@

You normally enter this interface by entering "recoll:" or "recoll:/" in the Konqueror URL entry, and following the "search" link.
In most circumstances, entering a link like - "recoll:/some search terms" will also yield an HTML result - list.

+ recoll:/john smith will also + yield an HTML result list.

File manager interface

@@ -67,7 +67,11 @@ probably the easiest option inside open dialogs.
  • Using an URL ending with a '/', ie: -
    recoll:/red apples ext:.html/
  • +
    + + recoll:/red apples ext:html/ +
    +
  • Switching from the HTML interface in konqueror by clicking the "Directory view" link at the top of the page. When doing diff --git a/src/kde/kioslave/recoll/htmlif.cpp b/src/kde/kioslave/recoll/htmlif.cpp index 0750fd24..e65347ea 100644 --- a/src/kde/kioslave/recoll/htmlif.cpp +++ b/src/kde/kioslave/recoll/htmlif.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.7 2008-12-04 11:49:59 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.8 2008-12-08 14:34:50 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@ static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.7 2008-12-04 11:49:59 dockes Exp $ #include #include #include +#include #include @@ -42,6 +43,9 @@ using namespace std; #include "docseqdb.h" #include "readfile.h" #include "smallut.h" +#include "plaintorich.h" +#include "internfile.h" +#include "wipedir.h" using namespace KIO; @@ -52,18 +56,18 @@ bool RecollKioPager::append(const string& data) m_parent->data(QByteArray(data.c_str())); return true; } - +#include string RecollProtocol::makeQueryUrl(int page, bool isdet) { - char buf[100]; - sprintf(buf, "recoll://search/query?q=%s&qtp=%s&p=%d", - url_encode((const char*)m_query.query.toUtf8()).c_str(), - (const char*)m_query.opt.toUtf8(), - page); - string ret(buf); + ostringstream str; + str << "recoll://search/query?q=" << + url_encode((const char*)m_query.query.toUtf8()) << + "&qtp=" << (const char*)m_query.opt.toUtf8(); + if (page >= 0) + str << "&p=" << page; if (isdet) - ret += "&det=1"; - return ret; + str << "&det=1"; + return str.str(); } string RecollKioPager::detailsLink() @@ -74,22 +78,41 @@ string RecollKioPager::detailsLink() return chunk; } -const static string parformat = - "" - "%R %S " - "Open  %T
    " - "%M %D   %U
    " - "%A %K"; +static string parformat; const string& RecollKioPager::parFormat() { - return parformat; + // Need to escape the % inside the query url + string qurl = m_parent->makeQueryUrl(-1, false), escurl; + for (string::size_type pos = 0; pos < qurl.length(); pos++) { + switch(qurl.at(pos)) { + case '%': + escurl += "%%"; + break; + default: + escurl += qurl.at(pos); + } + } + + ostringstream str; + str << + "" + "%R %S " + "Open  "; + str << "Preview
    "; + str << + "%T
    " + "%M %D   %U
    " + "%A %K"; + return parformat = str.str(); } string RecollKioPager::pageTop() { return "

    " "New Search" -#if KDE_IS_VERSION(4,1,0) +// Would be nice to have but doesnt work because the query may be executed +// by another kio instance which has no idea of the current page o +#if 0 && KDE_IS_VERSION(4,1,0) "    m_query.query.toUtf8())) + "/\">Directory view (you may need to reload the page)" @@ -183,6 +206,77 @@ void RecollProtocol::queryDetails() data(array); } +class PlainToRichKio : public PlainToRich { +public: + PlainToRichKio(bool inputhtml = false) : PlainToRich(inputhtml) { + } + virtual ~PlainToRichKio() {} + virtual string header() { + if (m_inputhtml) { + return snull; + } else { + return string("

    "); + } + } + virtual string startMatch() {return string("");} + virtual string endMatch() {return string("");} +}; + +void RecollProtocol::showPreview(const Rcl::Doc& doc) +{ + string fn = doc.url.substr(7); + kDebug() << fn.c_str(); + + struct stat st; + if (::stat(fn.c_str(), &st) != 0) { + string reason = string("File not found: ") + fn.c_str(); + error(KIO::ERR_SLAVE_DEFINED, reason.c_str()); + return; + } + string tmpdir; + string reason; + if (!maketmpdir(tmpdir, reason)) { + error(KIO::ERR_SLAVE_DEFINED, "Cannot create temporary directory"); + return; + } + o_rclconfig->setKeyDir(path_getfather(fn)); + FileInterner interner(fn, &st, o_rclconfig, tmpdir, &doc.mimetype); + Rcl::Doc fdoc; + + if (!interner.internfile(fdoc, fdoc.ipath)) { + wipedir(tmpdir); + rmdir(tmpdir.c_str()); + error(KIO::ERR_SLAVE_DEFINED, "Cannot convert file to internal format"); + return; + } + wipedir(tmpdir); + rmdir(tmpdir.c_str()); + + if (!interner.get_html().empty()) { + fdoc.text = interner.get_html(); + fdoc.mimetype = "text/html"; + } + + mimeType("text/html"); + + PlainToRichKio ptr; + ptr.set_inputhtml(!fdoc.mimetype.compare("text/html")); + list otextlist; + HiliteData hdata; + if (!m_source.isNull()) + m_source->getTerms(hdata.terms, hdata.groups, hdata.gslks); + ptr.plaintorich(fdoc.text, otextlist, hdata); + + QByteArray array; + QTextStream os(&array, QIODevice::WriteOnly); + for (list::iterator it = otextlist.begin(); + it != otextlist.end(); it++) { + os << (*it).c_str(); + } + os << "" << endl; + data(array); +} + void RecollProtocol::htmlDoSearch(const QueryDesc& qd) { kDebug() << "q" << qd.query << "opt" << qd.opt << "page" << qd.page << diff --git a/src/kde/kioslave/recoll/kio_recoll.cpp b/src/kde/kioslave/recoll/kio_recoll.cpp index de5ea7a1..ee735fd2 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.23 2008-12-05 11:09:31 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.24 2008-12-08 14:34:50 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -164,6 +164,8 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url) m_query.page = 0; } } else { + // Non empty host, url must be something like : + // //search/query?q=query¶m=value... kDebug() << "host" << url.host() << "path" << url.path(); if (url.host().compare("search") || url.path().compare("/query")) { return; @@ -184,6 +186,18 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url) } p = url.queryItem("det"); m_query.isDetReq = !p.isEmpty(); + + p = url.queryItem("cmd"); + if (!p.isEmpty() && !p.compare("pv")) { + p = url.queryItem("dn"); + if (!p.isEmpty()) { + // Preview and no docnum ?? + m_resnum = atoi((const char *)p.toUtf8()); + // Result in page is 1+ + m_resnum--; + m_type = UIMT_PREVIEW; + } + } } if (m_query.query.startsWith("/")) m_query.query.remove(0,1); @@ -255,6 +269,15 @@ void RecollProtocol::get(const KUrl& url) redirection(KUrl::fromLocalFile((const char *)(doc.url.c_str()+7))); goto out; } + } else if (ingest.isPreview(&qd, &resnum)) { + if (!syncSearch(qd)) { + return; + } + Rcl::Doc doc; + if (resnum >= 0 && !m_source.isNull() && m_source->getDoc(resnum, doc)) { + showPreview(doc); + goto out; + } } else if (ingest.isQuery(&qd)) { #if 0 // Do we need this ? diff --git a/src/kde/kioslave/recoll/kio_recoll.h b/src/kde/kioslave/recoll/kio_recoll.h index 33b42701..73f1f210 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.13 2008-12-04 11:49:59 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: kio_recoll.h,v 1.14 2008-12-08 14:34:50 dockes Exp $ (C) 2005 J.F.Dockes */ #define _RECOLL_H /* * This program is free software; you can redistribute it and/or modify @@ -88,8 +88,15 @@ public: *num = m_resnum; return true; } + bool isPreview(QueryDesc *q, int *num) { + if (m_type != UIMT_PREVIEW) return false; + *q = m_query; + *num = m_resnum; + return true; + } bool endSlashQuery() {return m_slashend;} bool alwaysDir() {return m_alwaysdir;} + private: RecollProtocol *m_parent; QueryDesc m_query; @@ -97,7 +104,8 @@ private: bool m_alwaysdir; RootEntryType m_retType; int m_resnum; - enum MyType {UIMT_NONE, UIMT_ROOTENTRY, UIMT_QUERY, UIMT_QUERYRESULT}; + enum MyType {UIMT_NONE, UIMT_ROOTENTRY, UIMT_QUERY, UIMT_QUERYRESULT, + UIMT_PREVIEW}; MyType m_type; }; @@ -155,7 +163,7 @@ class RecollProtocol : public KIO::SlaveBase { string makeQueryUrl(int page, bool isdet = false); bool syncSearch(const QueryDesc& qd); void htmlDoSearch(const QueryDesc& qd); - + void showPreview(const Rcl::Doc& doc); bool isRecollResult(const KUrl &url, int *num, QString* q); bool m_initok; diff --git a/src/kde/kioslave/recoll/notes.txt b/src/kde/kioslave/recoll/notes.txt index f1dd5452..cd806cbe 100644 --- a/src/kde/kioslave/recoll/notes.txt +++ b/src/kde/kioslave/recoll/notes.txt @@ -116,18 +116,11 @@ J'ai essaye de mettre une boucle timeout callback callspecial() mais ca ne sert a rien, c'est gere dans le process kio_slave, ca ne maintient pas l'association avec un konqueror. -KDE_FORK_SLAVES resoudrait peut-etre la question ? - - - - - - - - - - - +KDE_FORK_SLAVES sort of solves the problem in a limited way: + - It applies to an application instance, not a KIO slave type, so it + affects other KIO usages. + - If the application has 2 sessions with the same KIO there are no + warranties that 1 kio per session will be used ?