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 ?