This commit is contained in:
dockes 2008-12-08 14:34:51 +00:00
parent 5997dde6f3
commit 9e74096ad7
6 changed files with 162 additions and 39 deletions

View File

@ -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

View File

@ -16,8 +16,8 @@
<ul>
<li><b>Html interface</b>, close to a simplified QT Recoll
interface.</li>
<li><b>File manager interface</b>, which presents results as
directory entries</li>
<li><b>File manager interface</b>, <em>Only with KDE 4.1 and
newer</em>, which presents results as directory entries</li>
</ul>
<p>The module is still in its infancy. You will undoubtedly obtain
@ -41,8 +41,8 @@
<p>You normally enter this interface by entering "recoll:" or
"recoll:/" in the Konqueror URL entry, and following the "search"
link.<br> In most circumstances, entering a link like
"recoll:/some search terms" will also yield an HTML result
list.</p>
<a href="recoll:/john smith">recoll:/john smith</a> will also
yield an HTML result list.</p>
<h3>File manager interface</h3>
@ -67,7 +67,11 @@
probably the easiest option inside open dialogs.</li>
<li>Using an URL ending with a&nbsp;'/', ie:
<blockquote><i>recoll:/red apples ext:.html/</i></blockquote></li>
<blockquote>
<a href="recoll:/red apples ext:html/">
recoll:/red apples ext:html/</a>
</blockquote>
</li>
<li>Switching from the HTML interface in konqueror by clicking the
"Directory&nbsp;view" link at the top of the page. When doing

View File

@ -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 <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <string>
@ -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 <sstream>
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 =
"<a href=\"%U\"><img src=\"%I\" align=\"left\"></a>"
"%R %S "
"<a href=\"%U\">Open</a>&nbsp;&nbsp;<b>%T</b><br>"
"%M&nbsp;%D&nbsp;&nbsp; <i>%U</i><br>"
"%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 <<
"<a href=\"%U\"><img src=\"%I\" align=\"left\"></a>"
"%R %S "
"<a href=\"%U\">Open</a>&nbsp;&nbsp;";
str << "<a href=\"" << escurl << "&cmd=pv&dn=%N\">Preview</a><br>";
str <<
"<b>%T</b><br>"
"%M&nbsp;%D&nbsp;&nbsp; <i>%U</i><br>"
"%A %K";
return parformat = str.str();
}
string RecollKioPager::pageTop()
{
return "<p align=\"center\">"
"<a href=\"recoll:///search.html\">New Search</a>"
#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)
" &nbsp;&nbsp;&nbsp;<a href=\"recoll:///" +
url_encode(string(m_parent->m_query.query.toUtf8())) +
"/\">Directory view</a> (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("<html><head><title></title></head><body><p>");
}
}
virtual string startMatch() {return string("<font color=\"blue\">");}
virtual string endMatch() {return string("</font>");}
};
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<string> 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<string>::iterator it = otextlist.begin();
it != otextlist.end(); it++) {
os << (*it).c_str();
}
os << "</body></html>" << endl;
data(array);
}
void RecollProtocol::htmlDoSearch(const QueryDesc& qd)
{
kDebug() << "q" << qd.query << "opt" << qd.opt << "page" << qd.page <<

View File

@ -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&param=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 ?

View File

@ -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;

View File

@ -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 ?