kio_recoll: html/dir switching
This commit is contained in:
parent
0b649ae8d6
commit
3e311495be
@ -5,60 +5,86 @@
|
||||
</head>
|
||||
<body>
|
||||
<a href="recoll:///search.html">Recoll search</a>
|
||||
<h3>Recoll kio slave</h3>
|
||||
<h2>Recoll kio slave</h2>
|
||||
|
||||
<p>Use this module to perform Recoll searches from any program with
|
||||
a KIO interface (sort of...). <b>kio_recoll</b> is primarily
|
||||
a KIO interface. <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>The module can work in two modes:</p>
|
||||
<ul>
|
||||
<li><b>Html interface</b>, close to a simplified QT Recoll
|
||||
interface.</li>
|
||||
<li><b>File manager interface</b>, which presents results as
|
||||
directory entries</li>
|
||||
</ul>
|
||||
|
||||
<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>
|
||||
<p>The module is still in its infancy. You will undoubtedly obtain
|
||||
strange effects from time to time. If you have any remarks or
|
||||
ideas about improving kio_recoll, or observe an interesting and
|
||||
reproducible sequence, please <a href="mailto:jfd@recoll.org">
|
||||
report it</a>.</p>
|
||||
|
||||
<h4>HTML interface</h4>
|
||||
<p>The module is particularly unhelpful with search hits inside
|
||||
email folders, which Konqueror has no way to access.</p>
|
||||
|
||||
<p>This works more or less like the Recoll QT GUI, much
|
||||
simplified. The
|
||||
|
||||
<h3>HTML interface</h3>
|
||||
|
||||
<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>
|
||||
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>You normally enter this interface by entering "recoll:" or
|
||||
"recoll:/" in the Konqueror URL entry, and following the "search"
|
||||
link.<br> In most circumstances, entering a link like
|
||||
"recoll:/some search terms" will also yield an HTML result
|
||||
list.</p>
|
||||
|
||||
<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>
|
||||
|
||||
<h3>File manager interface</h3>
|
||||
|
||||
<p>Search results are returned as directory entries. No search
|
||||
result details (samples, relevance etc.) are available, but this
|
||||
interface allows multiple selections and copies, usage inside any
|
||||
KDE open dialog, etc.</p>
|
||||
|
||||
<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>To avoid swamping the interface with thousands of results, the
|
||||
result count is limited to 100 by default. You can change this value
|
||||
by setting the <code>kio_max_direntries</code> parameter in your recoll
|
||||
configuration file (typically ~/.recoll/recoll.conf)</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>There are several ways to enter this interface:</p>
|
||||
<ul>
|
||||
<li>Using "recollf" as protocol name instead of "recoll". This is
|
||||
probably the easiest option inside open dialogs.</li>
|
||||
|
||||
<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>
|
||||
<li>Using an URL ending with a '/', ie:
|
||||
<blockquote><i>recoll:/red apples ext:.html/</i></blockquote></li>
|
||||
|
||||
<p><a href="recoll:///welcome">Recoll Search</a></p>
|
||||
<li>Switching from the HTML interface in konqueror by clicking the
|
||||
"Directory view" link at the top of the page. When doing
|
||||
this, the directory content will be synchronized with the
|
||||
current HTML result page. This offers a way to display results
|
||||
in the file manager beyond the <code>kio_max_direntries</code>
|
||||
limit. <em>In most cases, you will have to reload the file
|
||||
manager page to obtain this synchronization</em>.</li>
|
||||
|
||||
<li>Users who will want to use the file manager view most of the
|
||||
time can set the <code>RECOLL_KIO_ALWAYS_DIR</code> environment
|
||||
variable or the <code>kio_always_dir</code> recoll.conf variable
|
||||
to 1. The HTML interface will then only be accessible
|
||||
through the search link in the top "recoll:" view.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="recoll:///search.html">Recoll Search</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.9 2008-12-03 17:04:20 dockes Exp $ (C) 2008 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: dirif.cpp,v 1.10 2008-12-04 11:49:58 dockes Exp $ (C) 2008 J.F.Dockes";
|
||||
#endif
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -141,7 +141,7 @@ static void createRootEntry(KIO::UDSEntry& entry)
|
||||
static void createGoHomeEntry(KIO::UDSEntry& entry)
|
||||
{
|
||||
entry.clear();
|
||||
entry.insert(KIO::UDSEntry::UDS_NAME, "search");
|
||||
entry.insert(KIO::UDSEntry::UDS_NAME, "search.html");
|
||||
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:///search.html");
|
||||
@ -173,6 +173,7 @@ void RecollProtocol::stat(const KUrl & url)
|
||||
UrlIngester ingest(this, url);
|
||||
|
||||
KIO::UDSEntry entry;
|
||||
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
|
||||
UrlIngester::RootEntryType rettp;
|
||||
QueryDesc qd;
|
||||
int num;
|
||||
@ -194,7 +195,8 @@ void RecollProtocol::stat(const KUrl & url)
|
||||
} else if (ingest.isResult(&qd, &num)) {
|
||||
if (syncSearch(qd)) {
|
||||
Rcl::Doc doc;
|
||||
if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) {
|
||||
if (num >= 0 && !m_source.isNull() &&
|
||||
m_source->getDoc(num, doc)) {
|
||||
entry = resultToUDSEntry(doc, num);
|
||||
} else {
|
||||
error(ERR_DOES_NOT_EXIST, "");
|
||||
@ -214,14 +216,15 @@ void RecollProtocol::stat(const KUrl & url)
|
||||
// Another approach would be to use different protocol names
|
||||
// to avoid any possibility of mixups
|
||||
if (m_alwaysdir || ingest.alwaysDir() || ingest.endSlashQuery()) {
|
||||
kDebug() << "Directory type";
|
||||
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);
|
||||
entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, time(0));
|
||||
entry.insert( KIO::UDSEntry::UDS_CREATION_TIME, time(0));
|
||||
}
|
||||
}
|
||||
|
||||
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
|
||||
statEntry(entry);
|
||||
finished();
|
||||
}
|
||||
@ -253,7 +256,6 @@ void RecollProtocol::listDir(const KUrl& url)
|
||||
return;
|
||||
default:
|
||||
error(ERR_CANNOT_ENTER_DIRECTORY, "");
|
||||
finished();
|
||||
return;
|
||||
}
|
||||
} else if (ingest.isQuery(&qd)) {
|
||||
@ -266,6 +268,7 @@ void RecollProtocol::listDir(const KUrl& url)
|
||||
return;
|
||||
}
|
||||
if (!syncSearch(qd)) {
|
||||
// syncSearch did the error thing
|
||||
return;
|
||||
}
|
||||
// Fallthrough to actually listing the directory
|
||||
@ -283,8 +286,18 @@ void RecollProtocol::listDir(const KUrl& url)
|
||||
numentries = 100;
|
||||
}
|
||||
|
||||
// If the html pager is set, begin display at the current page. This
|
||||
// allows paging the dir display by switching between both modes
|
||||
int first = 0;
|
||||
if (m_pager.pageNumber() > 0) {
|
||||
first = m_pager.pageNumber() * m_pager.pageSize();
|
||||
}
|
||||
vector<ResListEntry> page;
|
||||
int pagelen = m_source->getSeqSlice(0, numentries, page);
|
||||
int pagelen = m_source->getSeqSlice(first, numentries, page);
|
||||
if (pagelen < 0) {
|
||||
error(ERR_SLAVE_DEFINED, "Internal error");
|
||||
return;
|
||||
}
|
||||
UDSEntryList entries;
|
||||
for (int i = 0; i < pagelen; i++) {
|
||||
entries.append(resultToUDSEntry(page[i].doc, i));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.6 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.7 2008-12-04 11:49:59 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
#endif
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -57,7 +57,7 @@ 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(),
|
||||
url_encode((const char*)m_query.query.toUtf8()).c_str(),
|
||||
(const char*)m_query.opt.toUtf8(),
|
||||
page);
|
||||
string ret(buf);
|
||||
@ -87,7 +87,14 @@ const string& RecollKioPager::parFormat()
|
||||
|
||||
string RecollKioPager::pageTop()
|
||||
{
|
||||
return "<p align=\"center\"><a href=\"recoll:///search.html\">New Search</a></p>";
|
||||
return "<p align=\"center\">"
|
||||
"<a href=\"recoll:///search.html\">New Search</a>"
|
||||
#if KDE_IS_VERSION(4,1,0)
|
||||
" <a href=\"recoll:///" +
|
||||
url_encode(string(m_parent->m_query.query.toUtf8())) +
|
||||
"/\">Directory view</a> (you may need to reload the page)"
|
||||
#endif
|
||||
"</p>";
|
||||
}
|
||||
|
||||
string RecollKioPager::nextUrl()
|
||||
@ -183,11 +190,10 @@ void RecollProtocol::htmlDoSearch(const QueryDesc& qd)
|
||||
|
||||
mimeType("text/html");
|
||||
|
||||
bool samesearch;
|
||||
if (!syncSearch(qd, &samesearch))
|
||||
if (!syncSearch(qd))
|
||||
return;
|
||||
if (!samesearch) {
|
||||
m_pager.setDocSource(m_source);
|
||||
// syncSearch/doSearch do the setDocSource when needed
|
||||
if (m_pager.pageNumber() < 0) {
|
||||
m_pager.resultPageNext();
|
||||
}
|
||||
if (qd.isDetReq) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.21 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.22 2008-12-04 11:49:59 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
#endif
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -164,7 +164,8 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
|
||||
m_query.page = 0;
|
||||
}
|
||||
} else {
|
||||
if (url.host().compare("search")) {
|
||||
kDebug() << "host" << url.host() << "path" << url.path();
|
||||
if (url.host().compare("search") || url.path().compare("/query")) {
|
||||
return;
|
||||
}
|
||||
m_type = UIMT_QUERY;
|
||||
@ -187,6 +188,7 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
|
||||
if (m_query.query.startsWith("/"))
|
||||
m_query.query.remove(0,1);
|
||||
if (m_query.query.endsWith("/")) {
|
||||
kDebug() << "Ends with /";
|
||||
m_slashend = true;
|
||||
m_query.query.chop(1);
|
||||
} else {
|
||||
@ -195,7 +197,7 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
|
||||
return;
|
||||
}
|
||||
|
||||
bool RecollProtocol::syncSearch(const QueryDesc &qd, bool *same)
|
||||
bool RecollProtocol::syncSearch(const QueryDesc &qd)
|
||||
{
|
||||
kDebug();
|
||||
if (!m_initok || !maybeOpenDb(m_reason)) {
|
||||
@ -204,12 +206,8 @@ bool RecollProtocol::syncSearch(const QueryDesc &qd, bool *same)
|
||||
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);
|
||||
}
|
||||
@ -331,6 +329,9 @@ bool RecollProtocol::doSearch(const QueryDesc& qd)
|
||||
return false;
|
||||
}
|
||||
m_source = RefCntr<DocSequence>(src);
|
||||
// Reset pager in all cases. Costs nothing, stays at page -1 initially
|
||||
// htmldosearch will fetch the first page if needed.
|
||||
m_pager.setDocSource(m_source);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef _RECOLL_H
|
||||
/* @(#$Id: kio_recoll.h,v 1.12 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes */
|
||||
/* @(#$Id: kio_recoll.h,v 1.13 2008-12-04 11:49:59 dockes Exp $ (C) 2005 J.F.Dockes */
|
||||
#define _RECOLL_H
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -153,7 +153,7 @@ class RecollProtocol : public KIO::SlaveBase {
|
||||
void searchPage();
|
||||
void queryDetails();
|
||||
string makeQueryUrl(int page, bool isdet = false);
|
||||
bool syncSearch(const QueryDesc& qd, bool *same = 0);
|
||||
bool syncSearch(const QueryDesc& qd);
|
||||
void htmlDoSearch(const QueryDesc& qd);
|
||||
|
||||
bool isRecollResult(const KUrl &url, int *num, QString* q);
|
||||
|
||||
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.4 2008-12-02 13:14:01 dockes Exp $ (C) 2007 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: reslistpager.cpp,v 1.5 2008-12-04 11:49:59 dockes Exp $ (C) 2007 J.F.Dockes";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@ -30,7 +30,7 @@ Prefs prefs = {true, true};
|
||||
void ResListPager::resultPageNext()
|
||||
{
|
||||
if (m_docSource.isNull()) {
|
||||
LOGDEB(("ResListPager::displayPage: null source\n"));
|
||||
LOGDEB(("ResListPager::resultPageNext: null source\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -75,6 +75,10 @@ void ResListPager::displayPage()
|
||||
LOGDEB(("ResListPager::displayPage: null source\n"));
|
||||
return;
|
||||
}
|
||||
if (m_winfirst < 0) {
|
||||
LOGDEB(("ResListPager::displayPage: sequence error: winfirst < 0\n"));
|
||||
return;
|
||||
}
|
||||
string chunk;
|
||||
|
||||
// Display list header
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#ifndef _reslistpager_h_included_
|
||||
#define _reslistpager_h_included_
|
||||
/* @(#$Id: reslistpager.h,v 1.2 2008-11-20 13:10:23 dockes Exp $ (C) 2007 J.F.Dockes */
|
||||
/* @(#$Id: reslistpager.h,v 1.3 2008-12-04 11:49:59 dockes Exp $ (C) 2007 J.F.Dockes */
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
@ -32,6 +32,7 @@ public:
|
||||
return -1;
|
||||
return m_winfirst / m_pagesize;
|
||||
}
|
||||
virtual int pageSize() const {return m_pagesize;}
|
||||
void pageNext();
|
||||
bool hasNext() {return m_hasNext;}
|
||||
bool hasPrev() {return m_winfirst > 0;}
|
||||
@ -60,12 +61,11 @@ public:
|
||||
virtual string nextUrl();
|
||||
virtual string prevUrl();
|
||||
virtual string pageTop() {return string();}
|
||||
|
||||
private:
|
||||
// First docnum (from docseq) in current page
|
||||
int m_winfirst;
|
||||
RefCntr<DocSequence> m_docSource;
|
||||
int m_pagesize;
|
||||
const int m_pagesize;
|
||||
|
||||
bool m_hasNext;
|
||||
vector<ResListEntry> m_respage;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.148 2008-10-07 06:44:23 dockes Exp $ (C) 2004 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.149 2008-12-04 11:49:59 dockes Exp $ (C) 2004 J.F.Dockes";
|
||||
#endif
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -333,8 +333,8 @@ string Db::Native::makeAbstract(Xapian::docid docid, Query *query)
|
||||
unsigned int occurrences = 0;
|
||||
for (pos = db.positionlist_begin(docid, qterm);
|
||||
pos != db.positionlist_end(docid, qterm); pos++) {
|
||||
unsigned int ipos = *pos;
|
||||
if (ipos < baseTextPosition) // Not in text body
|
||||
int ipos = *pos;
|
||||
if (ipos < int(baseTextPosition)) // Not in text body
|
||||
continue;
|
||||
LOGABS(("makeAbstract: [%s] at %d occurrences %d maxoccs %d\n",
|
||||
qterm.c_str(), ipos, occurrences, maxoccs));
|
||||
@ -344,7 +344,7 @@ string Db::Native::makeAbstract(Xapian::docid docid, Query *query)
|
||||
unsigned int sta = MAX(0, ipos-m_db->m_synthAbsWordCtxLen);
|
||||
unsigned int sto = ipos+m_db->m_synthAbsWordCtxLen;
|
||||
for (unsigned int ii = sta; ii <= sto; ii++) {
|
||||
if (ii == ipos)
|
||||
if (ii == (unsigned int)ipos)
|
||||
sparseDoc[ii] = qterm;
|
||||
else
|
||||
sparseDoc[ii] = emptys;
|
||||
@ -1366,6 +1366,8 @@ bool Db::stemExpand(const string &lang, const string &term,
|
||||
LOGDEB1(("Db::stemExpand: Got %d from %s\n",
|
||||
more.size(), it->c_str()));
|
||||
result.insert(result.end(), more.begin(), more.end());
|
||||
if (result.size() >= (unsigned int)max)
|
||||
break;
|
||||
}
|
||||
LOGDEB1(("Db:::stemExpand: final count %d \n", result.size()));
|
||||
return true;
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
*/
|
||||
#ifndef _PATHUT_H_INCLUDED_
|
||||
#define _PATHUT_H_INCLUDED_
|
||||
/* @(#$Id: pathut.h,v 1.15 2008-07-01 11:51:51 dockes Exp $ (C) 2004 J.F.Dockes */
|
||||
/* @(#$Id: pathut.h,v 1.16 2008-12-04 11:49:59 dockes Exp $ (C) 2004 J.F.Dockes */
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
@ -51,7 +51,7 @@ extern list<string> path_dirglob(const string &dir,
|
||||
const string pattern);
|
||||
/// Encode according to rfc 1738
|
||||
extern string url_encode(const string url,
|
||||
string::size_type offs);
|
||||
string::size_type offs = 0);
|
||||
extern bool printableUrl(const string &fcharset,
|
||||
const string &in, string &out);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user