cleaned up virtual tree and url handling. Drag to desktop now works with appropriate name. recollf protocol

This commit is contained in:
dockes 2008-12-03 17:04:20 +00:00
parent 8b164381d2
commit 0b649ae8d6
7 changed files with 320 additions and 187 deletions

View File

@ -95,7 +95,7 @@ target_link_libraries(kio_recoll xapian ${EXTRA_LIBS} ${KDE4_KIO_LIBS})
install(TARGETS kio_recoll DESTINATION ${PLUGIN_INSTALL_DIR})
IF ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
install(FILES recoll.protocol DESTINATION ${SERVICES_INSTALL_DIR})
install(FILES recoll.protocol recollf.protocol DESTINATION ${SERVICES_INSTALL_DIR})
ELSE ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
install(FILES recollnolist.protocol DESTINATION ${SERVICES_INSTALL_DIR}
RENAME recoll.protocol)

View File

@ -4,7 +4,7 @@
<title>Recoll Kio Slave</title>
</head>
<body>
<a href="recoll:///welcome">Recoll search</a>
<a href="recoll:///search.html">Recoll search</a>
<h3>Recoll kio slave</h3>
<p>Use this module to perform Recoll searches from any program with

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.8 2008-12-03 10:02:20 dockes Exp $ (C) 2008 J.F.Dockes";
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.9 2008-12-03 17:04:20 dockes Exp $ (C) 2008 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -53,14 +53,14 @@ static const QString resultBaseName("recollResult");
// 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)
bool RecollProtocol::isRecollResult(const KUrl &url, int *num, QString *q)
{
*num = -1;
kDebug() << "url" << url << "m_srchStr" << m_srchStr;
kDebug() << "url" << url;
// Basic checks
if (!url.host().isEmpty() || url.path().isEmpty() ||
url.protocol().compare("recoll"))
(url.protocol().compare("recoll") && url.protocol().compare("recollf")))
return false;
QString path = url.path();
if (!path.startsWith("/"))
@ -87,13 +87,7 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num)
// We do have something that ressembles a recoll result locator. Check if
// this matches the current search, else have to run the requested one
QString searchstring = path.mid(1, slashpos-2);
kDebug() << "Comparing search strings" << m_srchStr << "and" << searchstring;
if (searchstring.compare(m_srchStr)) {
if (!doSearch(searchstring))
return false;
}
*q = path.mid(1, slashpos-2);
return true;
}
@ -106,7 +100,7 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
kDebug() << doc.url.c_str();
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, url.fileName());
char cnum[30];sprintf(cnum, "%d", num);
char cnum[30];sprintf(cnum, "%04d", num);
entry.insert(KIO::UDSEntry::UDS_NAME, resultBaseName + cnum);
if (!doc.mimetype.compare("application/x-fsdirectory")) {
@ -150,7 +144,7 @@ static void createGoHomeEntry(KIO::UDSEntry& entry)
entry.insert(KIO::UDSEntry::UDS_NAME, "search");
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Recoll search (click me)");
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///welcome");
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///search.html");
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "text/html");
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "recoll");
@ -175,28 +169,40 @@ static void createGoHelpEntry(KIO::UDSEntry& entry)
void RecollProtocol::stat(const KUrl & url)
{
kDebug() << url << endl ;
int num = -1;
QString path = url.path();
QString host = url.host();
UrlIngester ingest(this, url);
KIO::UDSEntry entry;
if (!host.isEmpty()) {
// Do nothing probably coming from the html form, if we return a
// directory here, we crash konqueror
kDebug() << "HOST NOT EMPTY:" << host;
} else if (!path.compare("/")) {
createRootEntry(entry);
} else if (!path.compare("/help")) {
createGoHelpEntry(entry);
} else if (!path.compare("/search")) {
createGoHomeEntry(entry);
// } else if (!path.compare("/welcome")) {
} else if (isRecollResult(url, &num)) {
// Let's stat said result.
Rcl::Doc doc;
if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) {
entry = resultToUDSEntry(doc, num);
UrlIngester::RootEntryType rettp;
QueryDesc qd;
int num;
if (ingest.isRootEntry(&rettp)) {
switch(rettp) {
case UrlIngester::UIRET_ROOT:
createRootEntry(entry);
break;
case UrlIngester::UIRET_HELP:
createGoHelpEntry(entry);
break;
case UrlIngester::UIRET_SEARCH:
createGoHomeEntry(entry);
break;
default:
error(ERR_DOES_NOT_EXIST, "");
break;
}
} else {
} else if (ingest.isResult(&qd, &num)) {
if (syncSearch(qd)) {
Rcl::Doc doc;
if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) {
entry = resultToUDSEntry(doc, num);
} else {
error(ERR_DOES_NOT_EXIST, "");
}
} else {
// hopefully syncSearch() set the error?
}
} else if (ingest.isQuery(&qd)) {
// ie "recoll:/some string" or "recoll:/some string/"
//
// We have a problem here. We'd like to let the user enter
@ -207,13 +213,11 @@ void RecollProtocol::stat(const KUrl & url)
//
// Another approach would be to use different protocol names
// to avoid any possibility of mixups
if (path.endsWith("/")) {
QString q, opt;
URLToQuery(url, q, opt);
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert( KIO::UDSEntry::UDS_ACCESS, 0700);
entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
entry.insert(KIO::UDSEntry::UDS_NAME, q);
if (m_alwaysdir || ingest.alwaysDir() || ingest.endSlashQuery()) {
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0700);
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
entry.insert(KIO::UDSEntry::UDS_NAME, qd.query);
}
}
@ -226,50 +230,48 @@ void RecollProtocol::listDir(const KUrl& url)
{
kDebug() << url << endl;
// It seems that when the request is from konqueror
// 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(ERR_SLAVE_DEFINED, "Autocompletion search aborted");
return;
}
UrlIngester ingest(this, url);
UrlIngester::RootEntryType rettp;
QueryDesc qd;
if (!m_initok || !maybeOpenDb(m_reason)) {
string reason = "RecollProtocol::listDir: Init error:" + m_reason;
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
return;
}
if (url.path().isEmpty() || url.path() == "/") {
kDebug() << "list /" << endl;
UDSEntryList entries;
KIO::UDSEntry entry;
// entry for '/'
createRootEntry(entry);
entries.append(entry);
createGoHomeEntry(entry);
entries.append(entry);
createGoHelpEntry(entry);
entries.append(entry);
listEntries(entries);
finished();
return;
}
QString query, opt;
URLToQuery(url, query, opt);
kDebug() << "Query: " << query;
if (!query.isEmpty()) {
if (!doSearch(query, opt))
if (ingest.isRootEntry(&rettp)) {
switch(rettp) {
case UrlIngester::UIRET_ROOT:
{
kDebug() << "list /" << endl;
UDSEntryList entries;
KIO::UDSEntry entry;
createRootEntry(entry);
entries.append(entry);
createGoHomeEntry(entry);
entries.append(entry);
createGoHelpEntry(entry);
entries.append(entry);
listEntries(entries);
finished();
}
return;
default:
error(ERR_CANNOT_ENTER_DIRECTORY, "");
finished();
return;
}
} else if (ingest.isQuery(&qd)) {
// At this point, it seems that when the request is from
// konqueror autocompletion it comes with a / at the end,
// which offers an opportunity to not perform it.
if (ingest.endSlashQuery()) {
kDebug() << "Ends With /" << endl;
error(ERR_SLAVE_DEFINED, "Autocompletion search aborted");
return;
}
if (!syncSearch(qd)) {
return;
}
// Fallthrough to actually listing the directory
} else {
finished();
kDebug() << "Cant grok input url";
error(ERR_CANNOT_ENTER_DIRECTORY, "");
return;
}
@ -290,7 +292,9 @@ void RecollProtocol::listDir(const KUrl& url)
listEntries(entries);
finished();
}
#else // <--- KDE 4.1+
#include <kurl.h>
#include "kio_recoll.h"
bool RecollProtocol::isRecollResult(const KUrl &, int *)

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.5 2008-12-02 13:14:01 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.6 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -53,10 +53,24 @@ bool RecollKioPager::append(const string& data)
return true;
}
string RecollProtocol::makeQueryUrl(int page, bool isdet)
{
char buf[100];
sprintf(buf, "recoll://search/query?q=%s&qtp=%s&p=%d",
(const char*)m_query.query.toUtf8(),
(const char*)m_query.opt.toUtf8(),
page);
string ret(buf);
if (isdet)
ret += "&det=1";
return ret;
}
string RecollKioPager::detailsLink()
{
string chunk = "<a href=\"recoll://command/QueryDetails\">";
chunk += tr("(show query)") + "</a>";
string chunk = string("<a href=\"") +
m_parent->makeQueryUrl(m_parent->m_pager.pageNumber(), true) + "\">"
+ "(show query)" + "</a>";
return chunk;
}
@ -73,16 +87,7 @@ const string& RecollKioPager::parFormat()
string RecollKioPager::pageTop()
{
return "<p align=\"center\"><a href=\"recoll:///welcome\">New Search</a></p>";
}
string RecollProtocol::makeQueryUrl(int page)
{
char buf[100];
sprintf(buf, "recoll://search/query?q=%s&qtp=%s&p=%d",
(const char*)m_srchStr.toUtf8(), (const char*)m_opt.toUtf8(),
page);
return string(buf);
return "<p align=\"center\"><a href=\"recoll:///search.html\">New Search</a></p>";
}
string RecollKioPager::nextUrl()
@ -107,7 +112,7 @@ string RecollKioPager::prevUrl()
static string welcomedata;
void RecollProtocol::welcomePage()
void RecollProtocol::searchPage()
{
kDebug();
mimeType("text/html");
@ -171,32 +176,35 @@ void RecollProtocol::queryDetails()
data(array);
}
void RecollProtocol::htmlDoSearch(const QString& q, const QString &opt, int page)
void RecollProtocol::htmlDoSearch(const QueryDesc& qd)
{
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))
return;
kDebug() << "q" << qd.query << "opt" << qd.opt << "page" << qd.page <<
"isdet" << qd.isDetReq;
mimeType("text/html");
bool samesearch;
if (!syncSearch(qd, &samesearch))
return;
if (!samesearch) {
m_pager.setDocSource(m_source);
// goto page 0
m_pager.resultPageNext();
}
if (qd.isDetReq) {
queryDetails();
return;
}
// Check / adjust page number
if (page > m_pager.pageNumber()) {
int npages = page - m_pager.pageNumber();
if (qd.page > m_pager.pageNumber()) {
int npages = qd.page - m_pager.pageNumber();
for (int i = 0; i < npages; i++)
m_pager.resultPageNext();
} else if (page < m_pager.pageNumber()) {
int npages = m_pager.pageNumber() - page;
} else if (qd.page < m_pager.pageNumber()) {
int npages = m_pager.pageNumber() - qd.page;
for (int i = 0; i < npages; i++)
m_pager.resultPageBack();
}
// Display
mimeType("text/html");
m_pager.displayPage();
kDebug() << "done";
}

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.20 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.21 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -58,7 +58,8 @@ RclConfig *RclConfig::getMainConfig()
}
RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
: SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0), m_opt("l")
: SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0),
m_alwaysdir(false)
{
kDebug() << endl;
if (o_rclconfig == 0) {
@ -81,6 +82,17 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
m_reason = "Could not build database object. (out of memory ?)";
return;
}
// Decide if we allow switching between html and file manager
// presentation by using an end slash or not. Can also be done dynamically
// by switching proto names.
const char *cp = getenv("RECOLL_KIO_ALWAYS_DIR");
if (cp) {
m_alwaysdir = stringToBool(cp);
} else {
o_rclconfig->getConfParam("kio_always_dir", &m_alwaysdir);
}
m_pager.setParent(this);
m_initok = true;
return;
@ -113,46 +125,99 @@ bool RecollProtocol::maybeOpenDb(string &reason)
void RecollProtocol::mimetype(const KUrl &url)
{
kDebug() << url << endl;
///////////////////////////////REMOVEME REMOVEME REMOVEME when sure !/////
abort();
////////////////////////////////////////////////////////////////////////
mimeType("text/html");
finished();
}
bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt,
int *page)
UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
: m_parent(p), m_slashend(false), m_alwaysdir(false),
m_retType(UIRET_NONE), m_resnum(0), m_type(UIMT_NONE)
{
// "recoll:/some query/" or "recoll:/some query"
kDebug() << "Url" << url;
m_alwaysdir = !url.protocol().compare("recollf");
QString path = url.path();
if (url.host().isEmpty()) {
q = url.path();
opt = "l";
if (page)
*page = 0;
} else {
// Decode the forms' arguments
q = url.queryItem("q");
opt = url.queryItem("qtp");
if (opt.isEmpty()) {
opt = "l";
}
if (page) {
QString p = url.queryItem("p");
if (p.isEmpty()) {
*page = 0;
} else {
sscanf(p.toAscii(), "%d", page);
}
if (path.isEmpty() || !path.compare("/")) {
m_type = UIMT_ROOTENTRY;
m_retType = UIRET_ROOT;
return;
} else if (!path.compare("/help.html")) {
m_type = UIMT_ROOTENTRY;
m_retType = UIRET_HELP;
return;
} else if (!path.compare("/search.html")) {
m_type = UIMT_ROOTENTRY;
m_retType = UIRET_SEARCH;
return;
} else if (m_parent->isRecollResult(url, &m_resnum, &m_query.query)) {
m_type = UIMT_QUERYRESULT;
m_query.opt = "l";
m_query.page = 0;
} else {
// Have to think this is some search string
m_type = UIMT_QUERY;
m_query.query = url.path();
m_query.opt = "l";
m_query.page = 0;
}
} else {
if (url.host().compare("search")) {
return;
}
m_type = UIMT_QUERY;
// Decode the forms' arguments
m_query.query = url.queryItem("q");
m_query.opt = url.queryItem("qtp");
if (m_query.opt.isEmpty()) {
m_query.opt = "l";
}
QString p = url.queryItem("p");
if (p.isEmpty()) {
m_query.page = 0;
} else {
sscanf(p.toAscii(), "%d", &m_query.page);
}
p = url.queryItem("det");
m_query.isDetReq = !p.isEmpty();
}
if (q.startsWith("/"))
q.remove(0,1);
if (q.endsWith("/"))
q.chop(1);
return true;
if (m_query.query.startsWith("/"))
m_query.query.remove(0,1);
if (m_query.query.endsWith("/")) {
m_slashend = true;
m_query.query.chop(1);
} else {
m_slashend = false;
}
return;
}
bool RecollProtocol::syncSearch(const QueryDesc &qd, bool *same)
{
kDebug();
if (!m_initok || !maybeOpenDb(m_reason)) {
string reason = "RecollProtocol::listDir: Init error:" + m_reason;
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
return false;
}
if (qd.sameQuery(m_query)) {
if (same)
*same = true;
return true;
}
if (same)
*same = false;
// doSearch() calls error() if appropriate.
return doSearch(qd);
}
// 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)
void RecollProtocol::get(const KUrl& url)
{
kDebug() << url << endl;
@ -162,56 +227,65 @@ void RecollProtocol::get(const KUrl & url)
return;
}
QString host = url.host();
QString path = url.path();
int docnum = -1;
if (host.isEmpty() &&
(path.isEmpty() || !path.compare("/")||!path.compare("/welcome"))) {
// recoll:/ : print the html form page
welcomePage();
goto out;
} else if (host.isEmpty() && isRecollResult(url, &docnum)) {
UrlIngester ingest(this, url);
UrlIngester::RootEntryType rettp;
QueryDesc qd;
int resnum;
if (ingest.isRootEntry(&rettp)) {
switch(rettp) {
case UrlIngester::UIRET_HELP:
{
QString location =
KStandardDirs::locate("data", "kio_recoll/help.html");
redirection(location);
}
goto out;
default:
searchPage();
goto out;
}
} else if (ingest.isResult(&qd, &resnum)) {
// Matched an url generated by konqueror out of a directory listing:
// ie: recoll:/some search string/recollResultxx
// Redirect to the result document URL
if (!syncSearch(qd)) {
return;
}
Rcl::Doc doc;
if (docnum >= 0 && !m_source.isNull() && m_source->getDoc(docnum, doc)) {
if (resnum >= 0 && !m_source.isNull() && m_source->getDoc(resnum, doc)) {
mimeType(doc.mimetype.c_str());
redirection(KUrl::fromLocalFile((const char *)(doc.url.c_str()+7)));
goto out;
}
} else if (host.isEmpty() ||
(!host.compare("search") && !path.compare("/query"))) {
// Either "recoll://search/query?query args"
// Or "recoll:[/]some search string"
// HTML style query, maybe initial or request for other page
QString query, opt;
int page;
URLToQuery(url, query, opt, &page);
if (!query.isEmpty()) {
htmlDoSearch(query, opt, page);
} else if (ingest.isQuery(&qd)) {
#if 0
// Do we need this ?
if (host.isEmpty()) {
char cpage[20];sprintf(cpage, "%d", page);
QString nurl = QString::fromAscii("recoll://search/query?q=") +
query + "&qtp=" + opt + "&p=" + cpage;
redirection(KUrl(nurl));
goto out;
}
} else if (!host.compare("command")) {
if (path.indexOf("/QueryDetails") == 0) {
queryDetails();
goto out;
}
#endif
// htmlDoSearch does the search syncing (needs to know about changes).
htmlDoSearch(qd);
goto out;
}
error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL");
error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL or internal error");
out:
finished();
}
// Execute Recoll search, and set the docsource etc.
bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
// Execute Recoll search, and set the docsource
bool RecollProtocol::doSearch(const QueryDesc& qd)
{
kDebug() << "query" << q << "opt" << qopt;
m_srchStr = q;
m_opt = qopt;
char opt = qopt.isEmpty() ? 'l' : qopt.toUtf8().at(0);
string qs = (const char *)q.toUtf8();
kDebug() << "query" << qd.query << "opt" << qd.opt;
m_query = qd;
char opt = qd.opt.isEmpty() ? 'l' : qd.opt.toUtf8().at(0);
string qs = (const char *)qd.query.toUtf8();
Rcl::SearchData *sd = 0;
if (opt != 'l') {
Rcl::SearchDataClause *clp = 0;
@ -238,7 +312,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
if (!sd) {
m_reason = "Internal Error: cant build search";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
finished();
return false;
}
@ -248,7 +321,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
if (!query->setQuery(sdata)) {
m_reason = "Query execute failed. Invalid query or syntax error?";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
finished();
return false;
}
@ -256,7 +328,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
new DocSequenceDb(RefCntr<Rcl::Query>(query), "Query results", sdata);
if (src == 0) {
error(KIO::ERR_SLAVE_DEFINED, "Can't build result sequence");
finished();
return false;
}
m_source = RefCntr<DocSequence>(src);

View File

@ -1,5 +1,5 @@
#ifndef _RECOLL_H
/* @(#$Id: kio_recoll.h,v 1.11 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes */
/* @(#$Id: kio_recoll.h,v 1.12 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes */
#define _RECOLL_H
/*
* This program is free software; you can redistribute it and/or modify
@ -54,6 +54,54 @@ private:
RecollProtocol *m_parent;
};
class QueryDesc {
public:
QueryDesc() : opt("l"), page(0), isDetReq(false) {}
QString query;
QString opt;
int page;
bool isDetReq;
bool sameQuery(const QueryDesc& o) const {
return !opt.compare(o.opt) && !query.compare(o.query);
}
};
// Our virtual tree is a bit complicated. We need a class to analyse an URL
// and tell what we should do with it
class UrlIngester {
public:
UrlIngester(RecollProtocol *p, const KUrl& url);
enum RootEntryType {UIRET_NONE, UIRET_ROOT, UIRET_HELP, UIRET_SEARCH};
bool isRootEntry(RootEntryType *tp) {
if (m_type != UIMT_ROOTENTRY) return false;
*tp = m_retType;
return true;
}
bool isQuery(QueryDesc *q) {
if (m_type != UIMT_QUERY) return false;
*q = m_query;
return true;
}
bool isResult(QueryDesc *q, int *num) {
if (m_type != UIMT_QUERYRESULT) 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;
bool m_slashend;
bool m_alwaysdir;
RootEntryType m_retType;
int m_resnum;
enum MyType {UIMT_NONE, UIMT_ROOTENTRY, UIMT_QUERY, UIMT_QUERYRESULT};
MyType m_type;
};
/**
* A KIO slave to execute and display Recoll searches.
*
@ -95,23 +143,25 @@ class RecollProtocol : public KIO::SlaveBase {
static RclConfig *o_rclconfig;
friend class RecollKioPager;
friend class UrlIngester;
private:
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");
bool doSearch(const QueryDesc& qd);
void welcomePage();
void searchPage();
void queryDetails();
string makeQueryUrl(int page);
void htmlDoSearch(const QString& q, const QString& opt, int page);
string makeQueryUrl(int page, bool isdet = false);
bool syncSearch(const QueryDesc& qd, bool *same = 0);
void htmlDoSearch(const QueryDesc& qd);
bool isRecollResult(const KUrl &url, int *num);
bool isRecollResult(const KUrl &url, int *num, QString* q);
bool m_initok;
Rcl::Db *m_rcldb;
string m_reason;
bool m_alwaysdir;
// 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
@ -121,8 +171,8 @@ class RecollProtocol : public KIO::SlaveBase {
// cache of recent searches kept open.
RecollKioPager m_pager;
RefCntr<DocSequence> m_source;
QString m_srchStr;
QString m_opt;
// Note: page here is not used, current page always comes from m_pager.
QueryDesc m_query;
};
extern "C" {int kdemain(int, char**);}

Binary file not shown.