seems to work by re-rerunning search whenever it changes. Still had one crash, needs cleanup
This commit is contained in:
parent
ae77b9fb99
commit
e106918cfc
@ -123,5 +123,5 @@ ELSE ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
|
|||||||
RENAME recoll.protocol)
|
RENAME recoll.protocol)
|
||||||
ENDIF ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
|
ENDIF ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
|
||||||
|
|
||||||
install(FILES data/welcome.html
|
install(FILES data/welcome.html data/help.html
|
||||||
DESTINATION ${DATA_INSTALL_DIR}/kio_recoll)
|
DESTINATION ${DATA_INSTALL_DIR}/kio_recoll)
|
||||||
|
|||||||
@ -1,2 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake CMakeTmp cmake_uninstall.cmake CPackConfig.cmake CPackSourceConfig.cmake DartTestfile.txt install_manifest.txt kio_recoll_automoc.cpp kio_recoll_automoc.cpp.files kio_recoll.la kio_recoll.so lib Makefile
|
rm -rf CMakeCache.txt CMakeFiles CTestTestfile.cmake \
|
||||||
|
cmake_install.cmake CMakeTmp cmake_uninstall.cmake \
|
||||||
|
CPackConfig.cmake CPackSourceConfig.cmake DartTestfile.txt \
|
||||||
|
install_manifest.txt kio_recoll_automoc.cpp \
|
||||||
|
kio_recoll_automoc.cpp.files kio_recoll.la kio_recoll.so lib Makefile
|
||||||
|
|||||||
62
src/kde/kioslave/recoll/data/help.html
Normal file
62
src/kde/kioslave/recoll/data/help.html
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<title>Recoll Kio Slave</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h3>Recoll kio slave</h3>
|
||||||
|
|
||||||
|
<p>Use this module to perform Recoll searches from any program with
|
||||||
|
a KIO interface (sort of...). <b>kio_recoll</b> is primarily
|
||||||
|
designed and tested with <b>konqueror</b>, and you will
|
||||||
|
undoubtedly get even more surprising effects with other tools.</p>
|
||||||
|
|
||||||
|
<p>The module can work in two different modes, depending on the form
|
||||||
|
of the URLS that it is given:</p>
|
||||||
|
<li><b>Html interface</b>: this is what you get into when you just type
|
||||||
|
recoll: or recoll:/ in the address bar, and then click the initial
|
||||||
|
icon.</li>
|
||||||
|
<li><b>File/Directory interface</b>: which you enter when you pass
|
||||||
|
an URL ending with a '/'</li>
|
||||||
|
|
||||||
|
<p>Please note that this module is still in its infancy and that it
|
||||||
|
is still more a toy than anything else. The semantics of the
|
||||||
|
KIO slaves interface is still a bit unstable between KDE releases,
|
||||||
|
you will certainly get surprising effects from time to time.</p>
|
||||||
|
|
||||||
|
<h4>HTML interface</h4>
|
||||||
|
|
||||||
|
<p>This works more or less like the Recoll QT GUI, much
|
||||||
|
simplified. The
|
||||||
|
<a href="http://www.recoll.org/usermanual/rcl.search.lang.html">
|
||||||
|
Recoll manual</a> describes the queries that can be
|
||||||
|
performed.</p>
|
||||||
|
<p>Most pages in the interface should quite self-explanatory.</p>
|
||||||
|
|
||||||
|
<h4>File interface</h4>
|
||||||
|
|
||||||
|
<p>kio_recoll enters this mode when it receives an URL ending with
|
||||||
|
a '/', ie:</p>
|
||||||
|
<blockquote><i>recoll:///xapian recoll ext:.html/</i></blockquote>
|
||||||
|
|
||||||
|
<p>The <i>path</i> part of the URI is taken as a Recoll query
|
||||||
|
language string and executed. The results are displayed as
|
||||||
|
directory entries.</p>
|
||||||
|
|
||||||
|
<p>This works fine with normal documents, very badly with message
|
||||||
|
inside folders, which Konqueror has no way to access.</p>
|
||||||
|
|
||||||
|
<p>As there is no provision to page directory listings, the number
|
||||||
|
of results returned is limited to a fixed value, 100 by default,
|
||||||
|
which you can change by setting the kio_max_direntries in your
|
||||||
|
Recoll configuration file (usually ~/.recoll).
|
||||||
|
<a href="http://www.recoll.org/usermanual/rcl.install.config.html">
|
||||||
|
More information about Recoll configuration.</a></p>
|
||||||
|
|
||||||
|
<p>This interface is very limited, but allows performing multiple
|
||||||
|
selection, copies, and other file operations on the results, which
|
||||||
|
may be useful in some cases (or not :))</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -7,14 +7,19 @@
|
|||||||
|
|
||||||
<h3>Recoll search</h3>
|
<h3>Recoll search</h3>
|
||||||
|
|
||||||
<p><form method="get" action="recoll://search/query">
|
<p>
|
||||||
|
<form method="get" action="recoll://search/query">
|
||||||
Query type:<br>
|
Query type:<br>
|
||||||
<input type="radio" name="qtp" value="l" checked>Query language<br>
|
<input type="radio" name="qtp" value="l" checked>Query language<br>
|
||||||
<input type="radio" name="qtp" value="a">All terms<br>
|
<input type="radio" name="qtp" value="a">All terms<br>
|
||||||
<input type="radio" name="qtp" value="o">Any term<br>
|
<input type="radio" name="qtp" value="o">Any term<br>
|
||||||
|
<input type="radio" name="qtp" value="f">File name<br>
|
||||||
|
|
||||||
Enter search string: <input type="text" name="q" size="40" value="%Q">
|
<input type="hidden" name="p" value="0">
|
||||||
<input type="submit" value="Search"></p>
|
Enter search string: <input type="text" name="q" size="40" value="%Q">
|
||||||
|
<input type="submit" value="Search">
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.3 2008-11-28 09:14:42 dockes Exp $ (C) 2008 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.4 2008-12-01 15:36:52 dockes Exp $ (C) 2008 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -28,6 +28,7 @@ static char rcsid[] = "@(#$Id: dirif.cpp,v 1.3 2008-11-28 09:14:42 dockes Exp $
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kdeversion.h>
|
#include <kdeversion.h>
|
||||||
|
|
||||||
#if KDE_IS_VERSION(4,1,0)
|
#if KDE_IS_VERSION(4,1,0)
|
||||||
// Couldn't get listDir() to work with kde 4.0, konqueror keeps
|
// Couldn't get listDir() to work with kde 4.0, konqueror keeps
|
||||||
// crashing because of kdirmodel, couldn't find a workaround (not
|
// crashing because of kdirmodel, couldn't find a workaround (not
|
||||||
@ -37,39 +38,71 @@ static char rcsid[] = "@(#$Id: dirif.cpp,v 1.3 2008-11-28 09:14:42 dockes Exp $
|
|||||||
|
|
||||||
#include <kurl.h>
|
#include <kurl.h>
|
||||||
#include <kio/global.h>
|
#include <kio/global.h>
|
||||||
|
#include <kstandarddirs.h>
|
||||||
|
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
|
|
||||||
#include "kio_recoll.h"
|
#include "kio_recoll.h"
|
||||||
|
#include "pathut.h"
|
||||||
|
|
||||||
using namespace KIO;
|
using namespace KIO;
|
||||||
|
|
||||||
void RecollProtocol::stat(const KUrl & url)
|
static const QString resultBaseName("recollResult");
|
||||||
{
|
|
||||||
kDebug() << url << endl ;
|
|
||||||
|
|
||||||
|
//
|
||||||
|
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 ??
|
||||||
|
if (!url.host().isEmpty() || url.path().isEmpty() ||
|
||||||
|
url.protocol().compare("recoll"))
|
||||||
|
return false;
|
||||||
QString path = url.path();
|
QString path = url.path();
|
||||||
KIO::UDSEntry entry;
|
if (!path.startsWith("/"))
|
||||||
if (!path.compare("/"))
|
return false;
|
||||||
entry.insert(KIO::UDSEntry::UDS_NAME, "/welcome");
|
// Look for the last '/' and check if it is followed by
|
||||||
else
|
// resultBaseName (riiiight...)
|
||||||
entry.insert(KIO::UDSEntry::UDS_NAME, url.path());
|
int slashpos = path.lastIndexOf("/");
|
||||||
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
|
if (slashpos == -1 || slashpos == 0 || slashpos == path.length() -1)
|
||||||
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
|
return false;
|
||||||
statEntry(entry);
|
slashpos++;
|
||||||
finished();
|
kDebug() << "Comparing " << path.mid(slashpos, resultBaseName.length()) <<
|
||||||
|
"and " << resultBaseName;
|
||||||
|
if (path.mid(slashpos, resultBaseName.length()).compare(resultBaseName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QString snum = path.mid(slashpos + resultBaseName.length());
|
||||||
|
sscanf(snum.toAscii(), "%d", num);
|
||||||
|
if (*num == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
kDebug() << "URL analysis ok, num:" << *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)) {
|
||||||
|
kDebug() << "Starting new search";
|
||||||
|
if (!doSearch(searchstring))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
|
||||||
|
|
||||||
const UDSEntry resultToUDSEntry(Rcl::Doc doc)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
UDSEntry entry;
|
UDSEntry entry;
|
||||||
|
|
||||||
KUrl url(doc.url.c_str());
|
KUrl url(doc.url.c_str());
|
||||||
kDebug() << doc.url.c_str();
|
kDebug() << doc.url.c_str();
|
||||||
|
|
||||||
entry.insert(KIO::UDSEntry::UDS_NAME, url.fileName());
|
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, url.fileName());
|
||||||
|
char cnum[30];sprintf(cnum, "%d", num);
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_NAME, resultBaseName + cnum);
|
||||||
|
|
||||||
if (!doc.mimetype.compare("application/x-fsdirectory")) {
|
if (!doc.mimetype.compare("application/x-fsdirectory")) {
|
||||||
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
|
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
|
||||||
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
||||||
@ -87,17 +120,16 @@ const UDSEntry resultToUDSEntry(Rcl::Doc doc)
|
|||||||
entry.insert( KIO::UDSEntry::UDS_ACCESS_TIME, info.st_atime);
|
entry.insert( KIO::UDSEntry::UDS_ACCESS_TIME, info.st_atime);
|
||||||
entry.insert( KIO::UDSEntry::UDS_CREATION_TIME, info.st_ctime);
|
entry.insert( KIO::UDSEntry::UDS_CREATION_TIME, info.st_ctime);
|
||||||
}
|
}
|
||||||
|
kDebug() << "entry URL: " << doc.url.c_str();
|
||||||
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, doc.url.c_str());
|
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, doc.url.c_str());
|
||||||
// entry.insert(KIO::UDSEntry::UDS_URL, "recoll://search/query/1");
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// From kio_beagle
|
// From kio_beagle
|
||||||
void RecollProtocol::createRootEntry(KIO::UDSEntry& entry)
|
static void createRootEntry(KIO::UDSEntry& entry)
|
||||||
{
|
{
|
||||||
// home directory
|
|
||||||
entry.clear();
|
entry.clear();
|
||||||
entry.insert( KIO::UDSEntry::UDS_NAME, ".");
|
entry.insert( KIO::UDSEntry::UDS_NAME, ".");
|
||||||
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
|
||||||
@ -105,11 +137,12 @@ void RecollProtocol::createRootEntry(KIO::UDSEntry& entry)
|
|||||||
entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
|
entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecollProtocol::createGoHomeEntry(KIO::UDSEntry& entry)
|
// Points to html query screen
|
||||||
|
static void createGoHomeEntry(KIO::UDSEntry& entry)
|
||||||
{
|
{
|
||||||
// status file
|
|
||||||
entry.clear();
|
entry.clear();
|
||||||
entry.insert(KIO::UDSEntry::UDS_NAME, "Recoll home (click me)");
|
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_FILE_TYPE, S_IFREG);
|
||||||
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///welcome");
|
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///welcome");
|
||||||
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500);
|
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500);
|
||||||
@ -117,6 +150,49 @@ void RecollProtocol::createGoHomeEntry(KIO::UDSEntry& entry)
|
|||||||
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "recoll");
|
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "recoll");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Points to help file
|
||||||
|
static void createGoHelpEntry(KIO::UDSEntry& entry)
|
||||||
|
{
|
||||||
|
QString location =
|
||||||
|
KStandardDirs::locate("data", "kio_recoll/help.html");
|
||||||
|
entry.clear();
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_NAME, "help");
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Recoll help (click me first)");
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, QString("file://") +
|
||||||
|
location);
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500);
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "text/html");
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "help");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecollProtocol::stat(const KUrl & url)
|
||||||
|
{
|
||||||
|
kDebug() << url << endl ;
|
||||||
|
int num = -1;
|
||||||
|
QString path = url.path();
|
||||||
|
KIO::UDSEntry entry;
|
||||||
|
if (!path.compare("/")) {
|
||||||
|
createRootEntry(entry);
|
||||||
|
} else if (!path.compare("/help")) {
|
||||||
|
createGoHelpEntry(entry);
|
||||||
|
} else if (!path.compare("/search")) {
|
||||||
|
createGoHomeEntry(entry);
|
||||||
|
} else if (isRecollResult(url, &num)) {
|
||||||
|
// If this url starts with the current search url appended with a
|
||||||
|
// result name appended, let's stat said result.
|
||||||
|
Rcl::Doc doc;
|
||||||
|
if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) {
|
||||||
|
entry = resultToUDSEntry(doc, num);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ??
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
|
||||||
|
statEntry(entry);
|
||||||
|
finished();
|
||||||
|
}
|
||||||
|
|
||||||
void RecollProtocol::listDir(const KUrl& url)
|
void RecollProtocol::listDir(const KUrl& url)
|
||||||
{
|
{
|
||||||
@ -136,6 +212,7 @@ void RecollProtocol::listDir(const KUrl& url)
|
|||||||
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
|
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.path().isEmpty() || url.path() == "/") {
|
if (url.path().isEmpty() || url.path() == "/") {
|
||||||
kDebug() << "list /" << endl;
|
kDebug() << "list /" << endl;
|
||||||
|
|
||||||
@ -144,12 +221,11 @@ void RecollProtocol::listDir(const KUrl& url)
|
|||||||
|
|
||||||
// entry for '/'
|
// entry for '/'
|
||||||
createRootEntry(entry);
|
createRootEntry(entry);
|
||||||
// listEntry(entry, false);
|
|
||||||
entries.append(entry);
|
entries.append(entry);
|
||||||
|
|
||||||
// entry for 'Information'
|
|
||||||
createGoHomeEntry(entry);
|
createGoHomeEntry(entry);
|
||||||
// listEntry(entry, false);
|
entries.append(entry);
|
||||||
|
createGoHelpEntry(entry);
|
||||||
entries.append(entry);
|
entries.append(entry);
|
||||||
|
|
||||||
listEntries(entries);
|
listEntries(entries);
|
||||||
@ -157,23 +233,32 @@ void RecollProtocol::listDir(const KUrl& url)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString query, opt;
|
QString query, opt;
|
||||||
URLToQuery(url, query, opt);
|
URLToQuery(url, query, opt);
|
||||||
kDebug() << "Query: " << query;
|
kDebug() << "Query: " << query;
|
||||||
if (!query.isEmpty()) {
|
if (!query.isEmpty()) {
|
||||||
if (!doSearch(query, opt.toUtf8().at(0)))
|
if (!doSearch(query, opt))
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
finished();
|
finished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int numentries = -1;
|
||||||
|
if (numentries == -1) {
|
||||||
|
if (o_rclconfig)
|
||||||
|
o_rclconfig->getConfParam("kio_max_direntries", &numentries);
|
||||||
|
if (numentries == -1)
|
||||||
|
numentries = 100;
|
||||||
|
}
|
||||||
|
|
||||||
vector<ResListEntry> page;
|
vector<ResListEntry> page;
|
||||||
int pagelen = m_source->getSeqSlice(0, 100, page);
|
int pagelen = m_source->getSeqSlice(0, numentries, page);
|
||||||
kDebug() << "Got " << pagelen << " results.";
|
kDebug() << "Got " << pagelen << " results.";
|
||||||
UDSEntryList entries;
|
UDSEntryList entries;
|
||||||
for (int i = 0; i < pagelen; i++) {
|
for (int i = 0; i < pagelen; i++) {
|
||||||
entries.append(resultToUDSEntry(page[i].doc));
|
entries.append(resultToUDSEntry(page[i].doc, i));
|
||||||
}
|
}
|
||||||
listEntries(entries);
|
listEntries(entries);
|
||||||
finished();
|
finished();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.2 2008-11-27 17:48:43 dockes Exp $ (C) 2005 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.3 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -75,6 +75,15 @@ string RecollKioPager::pageTop()
|
|||||||
return "<p align=\"center\"><a href=\"recoll:///welcome\">New Search</a></p>";
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
string RecollKioPager::nextUrl()
|
string RecollKioPager::nextUrl()
|
||||||
{
|
{
|
||||||
int pagenum = pageNumber();
|
int pagenum = pageNumber();
|
||||||
@ -82,10 +91,9 @@ string RecollKioPager::nextUrl()
|
|||||||
pagenum = 0;
|
pagenum = 0;
|
||||||
else
|
else
|
||||||
pagenum++;
|
pagenum++;
|
||||||
char buf[100];
|
return m_parent->makeQueryUrl(pagenum);
|
||||||
sprintf(buf, "recoll://command/Page%d", pagenum);
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string RecollKioPager::prevUrl()
|
string RecollKioPager::prevUrl()
|
||||||
{
|
{
|
||||||
int pagenum = pageNumber();
|
int pagenum = pageNumber();
|
||||||
@ -93,9 +101,7 @@ string RecollKioPager::prevUrl()
|
|||||||
pagenum = 0;
|
pagenum = 0;
|
||||||
else
|
else
|
||||||
pagenum--;
|
pagenum--;
|
||||||
char buf[100];
|
return m_parent->makeQueryUrl(pagenum);
|
||||||
sprintf(buf, "recoll://command/Page%d", pagenum);
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static string welcomedata;
|
static string welcomedata;
|
||||||
@ -139,21 +145,37 @@ void RecollProtocol::queryDetails()
|
|||||||
os << "</head>" << endl;
|
os << "</head>" << endl;
|
||||||
os << "<body><h3>Query details:</h3>" << endl;
|
os << "<body><h3>Query details:</h3>" << endl;
|
||||||
os << "<p>" << m_pager.queryDescription().c_str() <<"</p>"<< endl;
|
os << "<p>" << m_pager.queryDescription().c_str() <<"</p>"<< endl;
|
||||||
os << "<p><a href=\"recoll://command/Page" <<
|
os << "<p><a href=\"" << makeQueryUrl(m_pager.pageNumber()).c_str() <<
|
||||||
m_pager.pageNumber() << "\">Return to results</a>" << endl;
|
"\">Return to results</a>" << endl;
|
||||||
os << "</body></html>" << endl;
|
os << "</body></html>" << endl;
|
||||||
data(array);
|
data(array);
|
||||||
kDebug() << "done" << endl;
|
kDebug() << "done" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecollProtocol::htmlDoSearch(const QString& q, char opt)
|
void RecollProtocol::htmlDoSearch(const QString& q, const QString &opt, int page)
|
||||||
{
|
{
|
||||||
kDebug() << "htmlDoSearch" << endl;
|
kDebug();
|
||||||
if (!doSearch(q, opt))
|
// Check if same search or need to start new
|
||||||
return;
|
if (q.compare(m_srchStr) || opt.compare(m_opt)) {
|
||||||
|
if (!doSearch(q, opt))
|
||||||
|
return;
|
||||||
|
m_pager.setDocSource(m_source);
|
||||||
|
// goto page 0
|
||||||
|
m_pager.resultPageNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check / adjust page number
|
||||||
|
if (page > m_pager.pageNumber()) {
|
||||||
|
int npages = 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;
|
||||||
|
for (int i = 0; i < npages; i++)
|
||||||
|
m_pager.resultPageBack();
|
||||||
|
}
|
||||||
|
// Display
|
||||||
mimeType("text/html");
|
mimeType("text/html");
|
||||||
m_pager.setDocSource(m_source);
|
|
||||||
m_pager.resultPageNext();
|
|
||||||
m_pager.displayPage();
|
m_pager.displayPage();
|
||||||
kDebug() << "done" << endl;
|
kDebug() << "done" << endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.18 2008-11-28 09:14:42 dockes Exp $ (C) 2005 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.19 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -66,7 +66,7 @@ RclConfig *RclConfig::getMainConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
|
RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
|
||||||
: SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0)
|
: SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0), m_opt("l")
|
||||||
{
|
{
|
||||||
kDebug() << endl;
|
kDebug() << endl;
|
||||||
if (o_rclconfig == 0) {
|
if (o_rclconfig == 0) {
|
||||||
@ -123,11 +123,14 @@ void RecollProtocol::mimetype(const KUrl &url)
|
|||||||
finished();
|
finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt)
|
bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt,
|
||||||
|
int *page)
|
||||||
{
|
{
|
||||||
if (url.host().isEmpty()) {
|
if (url.host().isEmpty()) {
|
||||||
q = url.path();
|
q = url.path();
|
||||||
opt = "l";
|
opt = "l";
|
||||||
|
if (page)
|
||||||
|
*page = 0;
|
||||||
} else {
|
} else {
|
||||||
// Decode the forms' arguments
|
// Decode the forms' arguments
|
||||||
q = url.queryItem("q");
|
q = url.queryItem("q");
|
||||||
@ -135,6 +138,14 @@ bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt)
|
|||||||
if (opt.isEmpty()) {
|
if (opt.isEmpty()) {
|
||||||
opt = "l";
|
opt = "l";
|
||||||
}
|
}
|
||||||
|
if (page) {
|
||||||
|
QString p = url.queryItem("p");
|
||||||
|
if (p.isEmpty()) {
|
||||||
|
page = 0;
|
||||||
|
} else {
|
||||||
|
sscanf(p.toAscii(), "%d", page);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (q.startsWith("/"))
|
if (q.startsWith("/"))
|
||||||
q.remove(0,1);
|
q.remove(0,1);
|
||||||
@ -146,7 +157,7 @@ void RecollProtocol::get(const KUrl & url)
|
|||||||
kDebug() << url << endl;
|
kDebug() << url << endl;
|
||||||
|
|
||||||
if (!m_initok || !maybeOpenDb(m_reason)) {
|
if (!m_initok || !maybeOpenDb(m_reason)) {
|
||||||
string reason = "RecollProtocol::get:Init error: " + m_reason;
|
string reason = "Recoll: init error: " + m_reason;
|
||||||
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
|
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,56 +165,53 @@ void RecollProtocol::get(const KUrl & url)
|
|||||||
QString host = url.host();
|
QString host = url.host();
|
||||||
QString path = url.path();
|
QString path = url.path();
|
||||||
|
|
||||||
kDebug() << "host:" << host << " path:" << path;
|
int docnum = -1;
|
||||||
|
|
||||||
if (host.isEmpty() &&
|
if (host.isEmpty() &&
|
||||||
(path.isEmpty() || !path.compare("/")||!path.compare("/welcome"))) {
|
(path.isEmpty() || !path.compare("/")||!path.compare("/welcome"))) {
|
||||||
// recoll:/
|
// recoll:/ : print the html form page
|
||||||
welcomePage();
|
welcomePage();
|
||||||
goto out;
|
goto out;
|
||||||
} else if ((!host.compare("search") && !path.compare("/query"))
|
} else if (host.isEmpty() && isRecollResult(url, &docnum)) {
|
||||||
|| host.isEmpty()) {
|
// Matched an url generated by konqueror out of a directory listing:
|
||||||
|
// ie: recoll:/some search string/recollResultxx
|
||||||
|
// Redirect to the result document URL
|
||||||
|
Rcl::Doc doc;
|
||||||
|
if (docnum >= 0 && !m_source.isNull() && m_source->getDoc(docnum, 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"
|
// Either "recoll://search/query?query args"
|
||||||
// Or "recoll: some search string"
|
// Or "recoll:[/]some search string"
|
||||||
|
// HTML style query, maybe initial or request for other page
|
||||||
QString query, opt;
|
QString query, opt;
|
||||||
URLToQuery(url, query, opt);
|
int page;
|
||||||
|
URLToQuery(url, query, opt, &page);
|
||||||
if (!query.isEmpty()) {
|
if (!query.isEmpty()) {
|
||||||
htmlDoSearch(query, opt.toUtf8().at(0));
|
htmlDoSearch(query, opt, page);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (!host.compare("command")) {
|
} else if (!host.compare("command")) {
|
||||||
if (!path.isEmpty()) {
|
if (path.indexOf("/QueryDetails") == 0) {
|
||||||
if (path.indexOf("/Page") == 0) {
|
queryDetails();
|
||||||
int newpage = 0;
|
goto out;
|
||||||
sscanf(path.toUtf8(), "/Page%d", &newpage);
|
}
|
||||||
if (newpage > m_pager.pageNumber()) {
|
|
||||||
int npages = newpage - m_pager.pageNumber();
|
|
||||||
for (int i = 0; i < npages; i++)
|
|
||||||
m_pager.resultPageNext();
|
|
||||||
} else if (newpage < m_pager.pageNumber()) {
|
|
||||||
int npages = m_pager.pageNumber() - newpage;
|
|
||||||
for (int i = 0; i < npages; i++)
|
|
||||||
m_pager.resultPageBack();
|
|
||||||
}
|
|
||||||
mimeType("text/html");
|
|
||||||
m_pager.displayPage();
|
|
||||||
goto out;
|
|
||||||
} else if (path.indexOf("/QueryDetails") == 0) {
|
|
||||||
queryDetails();
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
kDebug() << "Unrecognized URL" << endl;
|
kDebug() << "Unrecognized URL: " << url << endl;
|
||||||
outputError("unrecognized URL");
|
error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL");
|
||||||
out:
|
out:
|
||||||
finished();
|
finished();
|
||||||
kDebug() << "done" << endl;
|
kDebug() << "done" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecollProtocol::doSearch(const QString& q, char opt)
|
bool RecollProtocol::doSearch(const QString& q, const QString &qopt)
|
||||||
{
|
{
|
||||||
kDebug() << q << endl;
|
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();
|
string qs = (const char *)q.toUtf8();
|
||||||
Rcl::SearchData *sd = 0;
|
Rcl::SearchData *sd = 0;
|
||||||
if (opt != 'l') {
|
if (opt != 'l') {
|
||||||
@ -232,7 +240,7 @@ bool RecollProtocol::doSearch(const QString& q, char opt)
|
|||||||
if (!sd) {
|
if (!sd) {
|
||||||
kDebug() << "Could not build search data from user string";
|
kDebug() << "Could not build search data from user string";
|
||||||
m_reason = "Internal Error: cant build search";
|
m_reason = "Internal Error: cant build search";
|
||||||
error(-1, m_reason.c_str());
|
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
|
||||||
finished();
|
finished();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -242,8 +250,8 @@ bool RecollProtocol::doSearch(const QString& q, char opt)
|
|||||||
kDebug() << "Executing query";
|
kDebug() << "Executing query";
|
||||||
RefCntr<Rcl::Query>query(new Rcl::Query(m_rcldb));
|
RefCntr<Rcl::Query>query(new Rcl::Query(m_rcldb));
|
||||||
if (!query->setQuery(sdata)) {
|
if (!query->setQuery(sdata)) {
|
||||||
m_reason = "Internal Error: query execute failed";
|
m_reason = "Query execute failed. Invalid query or syntax error?";
|
||||||
error(-1, m_reason.c_str());
|
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
|
||||||
finished();
|
finished();
|
||||||
kDebug() << "setQuery failed, returning";
|
kDebug() << "setQuery failed, returning";
|
||||||
return false;
|
return false;
|
||||||
@ -254,7 +262,7 @@ bool RecollProtocol::doSearch(const QString& q, char opt)
|
|||||||
new DocSequenceDb(RefCntr<Rcl::Query>(query), "Query results", sdata);
|
new DocSequenceDb(RefCntr<Rcl::Query>(query), "Query results", sdata);
|
||||||
if (src == 0) {
|
if (src == 0) {
|
||||||
kDebug() << "Cant' build result sequence";
|
kDebug() << "Cant' build result sequence";
|
||||||
error(-1, "Can't build result sequence");
|
error(KIO::ERR_SLAVE_DEFINED, "Can't build result sequence");
|
||||||
finished();
|
finished();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef _RECOLL_H
|
#ifndef _RECOLL_H
|
||||||
/* @(#$Id: kio_recoll.h,v 1.9 2008-11-28 09:14:42 dockes Exp $ (C) 2005 J.F.Dockes */
|
/* @(#$Id: kio_recoll.h,v 1.10 2008-12-01 15:36:52 dockes Exp $ (C) 2005 J.F.Dockes */
|
||||||
#define _RECOLL_H
|
#define _RECOLL_H
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -70,23 +70,36 @@ class RecollProtocol : public KIO::SlaveBase {
|
|||||||
|
|
||||||
static RclConfig *o_rclconfig;
|
static RclConfig *o_rclconfig;
|
||||||
|
|
||||||
|
friend class RecollKioPager;
|
||||||
private:
|
private:
|
||||||
bool maybeOpenDb(string &reason);
|
bool maybeOpenDb(string &reason);
|
||||||
void outputError(const QString& errmsg);
|
void outputError(const QString& errmsg);
|
||||||
bool doSearch(const QString& q, char opt = 'l');
|
bool doSearch(const QString& q, const QString& opt = "l");
|
||||||
void welcomePage();
|
void welcomePage();
|
||||||
void queryDetails();
|
void queryDetails();
|
||||||
void htmlDoSearch(const QString& q, char opt);
|
void htmlDoSearch(const QString& q, const QString& opt, int page);
|
||||||
bool URLToQuery(const KUrl &url, QString& q, QString& opt);
|
bool URLToQuery(const KUrl &url, QString& q, QString& opt, int *page=0);
|
||||||
void createRootEntry(KIO::UDSEntry& entry);
|
bool isRecollResult(const KUrl &url, int *num);
|
||||||
void createGoHomeEntry(KIO::UDSEntry& entry);
|
string makeQueryUrl(int page);
|
||||||
|
|
||||||
bool m_initok;
|
bool m_initok;
|
||||||
Rcl::Db *m_rcldb;
|
Rcl::Db *m_rcldb;
|
||||||
std::string m_reason;
|
std::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.
|
||||||
RecollKioPager m_pager;
|
RecollKioPager m_pager;
|
||||||
RefCntr<DocSequence> m_source;
|
RefCntr<DocSequence> m_source;
|
||||||
|
QString m_srchStr;
|
||||||
|
QString m_opt;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {int kdemain(int, char**);}
|
extern "C" {int kdemain(int, char**);}
|
||||||
|
|
||||||
#endif // _RECOLL_H
|
#endif // _RECOLL_H
|
||||||
|
|||||||
@ -34,3 +34,23 @@ le changement ne s'opere pas toujours immediatement quand on change le
|
|||||||
fichier .proto, y compris apres avoir tue tous les process kde (changement
|
fichier .proto, y compris apres avoir tue tous les process kde (changement
|
||||||
à la deuxieme execution de konqueror sur kde4.0). Sur kde4.0 il faut que le
|
à la deuxieme execution de konqueror sur kde4.0). Sur kde4.0 il faut que le
|
||||||
.proto soit sans entree "listing"
|
.proto soit sans entree "listing"
|
||||||
|
|
||||||
|
|
||||||
|
Les KIO slaves ne sont pas associes a une fenetre ! ils sont
|
||||||
|
reutilises au hasard, et leur etat n'a aucune raison de correspondre a
|
||||||
|
celui de l'affichage. On peut tres bien avoir 1 fenetre 2 kio ou 1 kio
|
||||||
|
deux fenetres, et le next d'un search peut arriver au kio qui a
|
||||||
|
l'autre search, donc n'importenaouak. Il faudrait que l'etat soit
|
||||||
|
partage et accede par un identifiant uniquement determine par l'url de
|
||||||
|
la fenetre.
|
||||||
|
|
||||||
|
Meme pour une fenetre unique, au bout d'un moment le kio timeout et exite.
|
||||||
|
|
||||||
|
En fait les slaves ne peuvent pas stocker d'etat du tout. Donc:
|
||||||
|
- soit un serveur central auquel ils parlent
|
||||||
|
- soit ils relancent dynamiquement les recherches si pas de match
|
||||||
|
C'est vrai aussi bien pour les dirlists que pour la version html.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user