cleaned up virtual tree and url handling. Drag to desktop now works with appropriate name. recollf protocol
This commit is contained in:
parent
8b164381d2
commit
0b649ae8d6
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 *)
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
Loading…
x
Reference in New Issue
Block a user