small cleanups and comments. Still some weirdness

This commit is contained in:
dockes 2008-12-01 18:42:52 +00:00
parent 7471971c46
commit dbe29d4a7b
5 changed files with 91 additions and 82 deletions

View File

@ -4,7 +4,7 @@
<title>Recoll Kio Slave</title>
</head>
<body>
<a href="recoll:///welcome">Recoll search</a>
<h3>Recoll kio slave</h3>
<p>Use this module to perform Recoll searches from any program with
@ -58,5 +58,7 @@
selection, copies, and other file operations on the results, which
may be useful in some cases (or not :))</p>
<p><a href="recoll:///welcome">Recoll Search</a></p>
</body>
</html>

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.4 2008-12-01 15:36:52 dockes Exp $ (C) 2008 J.F.Dockes";
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.5 2008-12-01 18:42:52 dockes Exp $ (C) 2008 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -39,7 +39,6 @@ static char rcsid[] = "@(#$Id: dirif.cpp,v 1.4 2008-12-01 15:36:52 dockes Exp $
#include <kurl.h>
#include <kio/global.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include "kio_recoll.h"
@ -49,18 +48,24 @@ using namespace KIO;
static const QString resultBaseName("recollResult");
//
// Check if the input URL is of the form that konqueror builds by
// appending one of our result file names to the directory name (which
// is the search string). If it is, extract return the result document
// number. Possibly restart the search if the search string does not
// match the current one
bool RecollProtocol::isRecollResult(const KUrl &url, int *num)
{
*num = -1;
kDebug() << "url" << url << "m_srchStr" << m_srchStr;
// Does the url look like a recoll search result ??
// Basic checks
if (!url.host().isEmpty() || url.path().isEmpty() ||
url.protocol().compare("recoll"))
return false;
QString path = url.path();
if (!path.startsWith("/"))
return false;
// Look for the last '/' and check if it is followed by
// resultBaseName (riiiight...)
int slashpos = path.lastIndexOf("/");
@ -72,6 +77,7 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num)
if (path.mid(slashpos, resultBaseName.length()).compare(resultBaseName))
return false;
// Extract the result number
QString snum = path.mid(slashpos + resultBaseName.length());
sscanf(snum.toAscii(), "%d", num);
if (*num == -1)
@ -84,7 +90,6 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num)
QString searchstring = path.mid(1, slashpos-2);
kDebug() << "Comparing search strings" << m_srchStr << "and" << searchstring;
if (searchstring.compare(m_srchStr)) {
kDebug() << "Starting new search";
if (!doSearch(searchstring))
return false;
}
@ -92,6 +97,7 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num)
return true;
}
// Translate rcldoc result into directory entry
static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
{
UDSEntry entry;
@ -186,7 +192,9 @@ void RecollProtocol::stat(const KUrl & url)
entry = resultToUDSEntry(doc, num);
}
} else {
// ??
// Don't return an error here, we get stat() on yet unperformed searches
// ie stat("recoll:/some search string")
// Would have to perform the search, better to return bogus ok
}
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
@ -202,8 +210,8 @@ void RecollProtocol::listDir(const KUrl& url)
// autocompletion it comes with a / at the end, which offers
// an opportunity to not perform it.
if (url.path() != "/" && url.path().endsWith("/")) {
kDebug() << "Endswith/" << endl;
error(-1, "");
kDebug() << "EndsWith /" << endl;
error(ERR_SLAVE_DEFINED, "Autocompletion search aborted");
return;
}
@ -255,7 +263,6 @@ void RecollProtocol::listDir(const KUrl& url)
vector<ResListEntry> page;
int pagelen = m_source->getSeqSlice(0, numentries, page);
kDebug() << "Got " << pagelen << " results.";
UDSEntryList entries;
for (int i = 0; i < pagelen; i++) {
entries.append(resultToUDSEntry(page[i].doc, i));

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.3 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.4 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -47,7 +47,8 @@ using namespace KIO;
bool RecollKioPager::append(const string& data)
{
if (!m_parent) return false;
if (!m_parent)
return false;
m_parent->data(QByteArray(data.c_str()));
return true;
}
@ -65,7 +66,7 @@ const static string parformat =
"<a href=\"%U\">Open</a>&nbsp;&nbsp;<b>%T</b><br>"
"%M&nbsp;%D&nbsp;&nbsp; <i>%U</i><br>"
"%A %K";
const string &RecollKioPager::parFormat()
const string& RecollKioPager::parFormat()
{
return parformat;
}
@ -108,7 +109,7 @@ static string welcomedata;
void RecollProtocol::welcomePage()
{
kDebug() << endl;
kDebug();
mimeType("text/html");
if (welcomedata.empty()) {
QString location =
@ -128,12 +129,11 @@ void RecollProtocol::welcomePage()
subs['Q'] = "";
pcSubst(welcomedata, tmp, subs);
data(tmp.c_str());
kDebug() << "done" << endl;
}
void RecollProtocol::queryDetails()
{
kDebug() << endl;
kDebug();
mimeType("text/html");
QByteArray array;
QTextStream os(&array, QIODevice::WriteOnly);
@ -149,12 +149,13 @@ void RecollProtocol::queryDetails()
"\">Return to results</a>" << endl;
os << "</body></html>" << endl;
data(array);
kDebug() << "done" << endl;
}
void RecollProtocol::htmlDoSearch(const QString& q, const QString &opt, int page)
{
kDebug();
kDebug() << "q" << q << "opt" << opt << "page" << page;
if (m_source.isNull())
kDebug() << "Null source";
// Check if same search or need to start new
if (q.compare(m_srchStr) || opt.compare(m_opt)) {
if (!doSearch(q, opt))
@ -177,23 +178,5 @@ void RecollProtocol::htmlDoSearch(const QString& q, const QString &opt, int page
// Display
mimeType("text/html");
m_pager.displayPage();
kDebug() << "done" << endl;
}
void RecollProtocol::outputError(const QString& errmsg)
{
mimeType("text/html");
QByteArray array;
QTextStream os(&array, QIODevice::WriteOnly);
os << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\">" << endl;
os << "<html><head>" << endl;
os << "<meta http-equiv=\"Content-Type\" content=\"text/html;"
"charset=utf-8\">" << endl;
os << "<title>" << "Recoll error" << "</title>\n" << endl;
os << "</head>" << endl;
os << "<body><p><b>Recoll error: </b>" << errmsg << "</p>" << endl;
os << "<p><a href=\"recoll:///\">New query</a></p>"<< endl;
os << "</body></html>" << endl;
data(array);
kDebug() << "done";
}

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.19 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.20 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -24,23 +24,14 @@ static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.19 2008-12-01 15:36:52 dockes
#include <errno.h>
#include <string>
using namespace std;
#include <qglobal.h>
#if (QT_VERSION < 0x040000)
#include <qglobal.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qstring.h>
#else
#include <QFile>
#include <QTextStream>
#include <QByteArray>
#endif
#include <kdebug.h>
//#include <kinstance.h>
#include <kcomponentdata.h>
#include <kstandarddirs.h>
@ -60,6 +51,7 @@ using namespace std;
using namespace KIO;
RclConfig *RecollProtocol::o_rclconfig;
RclConfig *RclConfig::getMainConfig()
{
return RecollProtocol::o_rclconfig;
@ -78,7 +70,8 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
}
if (o_rclconfig->getDbDir().empty()) {
// Note: this will have to be replaced by a call to a
// configuration buildin dialog for initial configuration
// configuration building dialog for initial configuration? Or
// do we assume that the QT GUO is always used for this ?
m_reason = "No db directory in configuration ??";
return;
}
@ -97,7 +90,7 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
// Doesn't seem needed in the kio context.
RecollProtocol::~RecollProtocol()
{
kDebug() << endl;
kDebug();
delete m_rcldb;
}
@ -116,6 +109,7 @@ bool RecollProtocol::maybeOpenDb(string &reason)
return true;
}
// Not sure this is ever used
void RecollProtocol::mimetype(const KUrl &url)
{
kDebug() << url << endl;
@ -126,6 +120,7 @@ void RecollProtocol::mimetype(const KUrl &url)
bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt,
int *page)
{
// "recoll:/some query/" or "recoll:/some query"
if (url.host().isEmpty()) {
q = url.path();
opt = "l";
@ -141,7 +136,7 @@ bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt,
if (page) {
QString p = url.queryItem("p");
if (p.isEmpty()) {
page = 0;
*page = 0;
} else {
sscanf(p.toAscii(), "%d", page);
}
@ -149,9 +144,14 @@ bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt,
}
if (q.startsWith("/"))
q.remove(0,1);
if (q.endsWith("/"))
q.chop(1);
return true;
}
// This is used by the html interface, but also by the directory one
// when doing file copies for exemple. This is the central dispatcher
// for requests, it has to know a little about both models.
void RecollProtocol::get(const KUrl & url)
{
kDebug() << url << endl;
@ -199,13 +199,12 @@ void RecollProtocol::get(const KUrl & url)
goto out;
}
}
kDebug() << "Unrecognized URL: " << url << endl;
error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL");
out:
finished();
kDebug() << "done" << endl;
}
// Execute Recoll search, and set the docsource etc.
bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
{
kDebug() << "query" << q << "opt" << qopt;
@ -234,11 +233,9 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
if (sd && clp)
sd->addClause(clp);
} else {
kDebug() << "Parsing query: " << qs.c_str();
sd = wasaStringToRcl(qs, m_reason);
}
if (!sd) {
kDebug() << "Could not build search data from user string";
m_reason = "Internal Error: cant build search";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
finished();
@ -247,26 +244,21 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
RefCntr<Rcl::SearchData> sdata(sd);
sdata->setStemlang("english");
kDebug() << "Executing query";
RefCntr<Rcl::Query>query(new Rcl::Query(m_rcldb));
if (!query->setQuery(sdata)) {
m_reason = "Query execute failed. Invalid query or syntax error?";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
finished();
kDebug() << "setQuery failed, returning";
return false;
}
kDebug() << "Building docsequence";
DocSequenceDb *src =
new DocSequenceDb(RefCntr<Rcl::Query>(query), "Query results", sdata);
if (src == 0) {
kDebug() << "Cant' build result sequence";
error(KIO::ERR_SLAVE_DEFINED, "Can't build result sequence");
finished();
return false;
}
kDebug() << "Setting source";
m_source = RefCntr<DocSequence>(src);
return true;
}

View File

@ -1,5 +1,5 @@
#ifndef _RECOLL_H
/* @(#$Id: kio_recoll.h,v 1.10 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes */
/* @(#$Id: kio_recoll.h,v 1.11 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes */
#define _RECOLL_H
/*
* This program is free software; you can redistribute it and/or modify
@ -22,12 +22,7 @@
using std::string;
#include <qglobal.h>
#if (QT_VERSION < 0x040000)
#include <qstring.h>
#else
#include <QString>
#endif
#include <kurl.h>
#include <kio/global.h>
@ -42,6 +37,7 @@ using std::string;
class RecollProtocol;
/** Specialize the recoll html pager for the kind of links we use etc. */
class RecollKioPager : public ResListPager {
public:
RecollKioPager() : m_parent(0) {}
@ -53,16 +49,44 @@ public:
virtual string nextUrl();
virtual string prevUrl();
virtual string pageTop();
private:
RecollProtocol *m_parent;
};
/**
* A KIO slave to execute and display Recoll searches.
*
* Things are made a little complicated because KIO slaves can't hope
* that their internal state will remain consistent with their user
* application state: slaves die, are restarted, reused, at random
* between requests.
* In our case, this means that any request has to be processed
* without reference to the last operation performed. Ie, if the
* search parameters are not those from the last request, the search
* must be restarted anew. This happens for example with different
* searches in 2 konqueror screens: typically only one kio_slave will
* be used.
* The fact that we check if the search is the same as the last one,
* to avoid restarting is an optimization, not the base mechanism
* (contrary to what was initially assumed, and may have left a few
* crumbs around).
*
* We have two modes of operation, one based on html forms and result
* pages, which can potentially be developped to the full Recoll
* functionality, and one based on a directory listing model, which
* will always be more limited, but may be useful in some cases to
* allow easy copying of files etc. Which one is in use is decided by
* the form of the URL.
*/
class RecollProtocol : public KIO::SlaveBase {
public:
RecollProtocol(const QByteArray &pool, const QByteArray &app );
virtual ~RecollProtocol();
virtual void mimetype(const KUrl & url );
virtual void get(const KUrl & url );
virtual void mimetype(const KUrl& url);
virtual void get(const KUrl& url);
// The directory mode is not available with KDE 4.0, I could find
// no way to avoid crashing kdirmodel
#if KDE_IS_VERSION(4,1,0)
virtual void stat(const KUrl & url);
virtual void listDir(const KUrl& url);
@ -71,29 +95,30 @@ class RecollProtocol : public KIO::SlaveBase {
static RclConfig *o_rclconfig;
friend class RecollKioPager;
private:
bool maybeOpenDb(string &reason);
void outputError(const QString& errmsg);
bool maybeOpenDb(string& reason);
bool URLToQuery(const KUrl &url, QString& q, QString& opt, int *page=0);
bool doSearch(const QString& q, const QString& opt = "l");
void welcomePage();
void queryDetails();
void htmlDoSearch(const QString& q, const QString& opt, int page);
bool URLToQuery(const KUrl &url, QString& q, QString& opt, int *page=0);
bool isRecollResult(const KUrl &url, int *num);
string makeQueryUrl(int page);
void htmlDoSearch(const QString& q, const QString& opt, int page);
bool isRecollResult(const KUrl &url, int *num);
bool m_initok;
Rcl::Db *m_rcldb;
std::string m_reason;
string m_reason;
// All details about the current search state: because of how the
// KIO slaves are used / reused, we can't be sure that the next
// request will be for the same search, and we need to check and
// restart one if the data changes. This is very wasteful of
// course but hopefully won't happen too much in actual use. One
// possible workaround for some scenarios (one slave several
// konqueror windows) would be to have a small cache of recent
// searches kept open.
// Search state: because of how the KIO slaves are used / reused,
// we can't be sure that the next request will be for the same
// search, and we need to check and restart one if the data
// changes. This is very wasteful but hopefully won't happen too
// much in actual use. One possible workaround for some scenarios
// (one slave several konqueror windows) would be to have a small
// cache of recent searches kept open.
RecollKioPager m_pager;
RefCntr<DocSequence> m_source;
QString m_srchStr;