From 3e311495be951b999e8d5ab46b5e5de6b8b45098 Mon Sep 17 00:00:00 2001 From: dockes Date: Thu, 4 Dec 2008 11:49:59 +0000 Subject: [PATCH] kio_recoll: html/dir switching --- src/kde/kioslave/recoll/data/help.html | 94 ++++++++++++++++--------- src/kde/kioslave/recoll/dirif.cpp | 27 +++++-- src/kde/kioslave/recoll/htmlif.cpp | 20 ++++-- src/kde/kioslave/recoll/kio_recoll.cpp | 15 ++-- src/kde/kioslave/recoll/kio_recoll.h | 4 +- src/kde/kioslave/recoll/notes.txt | Bin 6177 -> 6107 bytes src/query/reslistpager.cpp | 8 ++- src/query/reslistpager.h | 6 +- src/rcldb/rcldb.cpp | 10 +-- src/utils/pathut.h | 4 +- 10 files changed, 120 insertions(+), 68 deletions(-) diff --git a/src/kde/kioslave/recoll/data/help.html b/src/kde/kioslave/recoll/data/help.html index d6619ade..6e86f180 100644 --- a/src/kde/kioslave/recoll/data/help.html +++ b/src/kde/kioslave/recoll/data/help.html @@ -5,60 +5,86 @@ Recoll search -

Recoll kio slave

+

Recoll kio slave

Use this module to perform Recoll searches from any program with - a KIO interface (sort of...). kio_recoll is primarily + a KIO interface. kio_recoll is primarily designed and tested with konqueror, and you will undoubtedly get even more surprising effects with other tools.

-

The module can work in two different modes, depending on the form - of the URLS that it is given:

-
  • Html interface: this is what you get into when you just type - recoll: or recoll:/ in the address bar, and then click the initial - icon.
  • -
  • File/Directory interface: which you enter when you pass - an URL ending with a '/'
  • +

    The module can work in two modes:

    + -

    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.

    +

    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 + report it.

    -

    HTML interface

    +

    The module is particularly unhelpful with search hits inside + email folders, which Konqueror has no way to access.

    -

    This works more or less like the Recoll QT GUI, much - simplified. The + +

    HTML interface

    + +

    This works more or less like the Recoll QT GUI, much simplified. The - Recoll manual describes the queries that can be - performed.

    + Recoll manual describes the queries that can be performed.

    +

    Most pages in the interface should quite self-explanatory.

    -

    File interface

    +

    You normally enter this interface by entering "recoll:" or + "recoll:/" in the Konqueror URL entry, and following the "search" + link.
    In most circumstances, entering a link like + "recoll:/some search terms" will also yield an HTML result + list.

    -

    kio_recoll enters this mode when it receives an URL ending with - a '/', ie:

    -
    recoll:///xapian recoll ext:.html/
    + +

    File manager interface

    + +

    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.

    The path part of the URI is taken as a Recoll query language string and executed. The results are displayed as directory entries.

    -

    This works fine with normal documents, very badly with message - inside folders, which Konqueror has no way to access.

    +

    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 kio_max_direntries parameter in your recoll + configuration file (typically ~/.recoll/recoll.conf)

    -

    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). - - More information about Recoll configuration.

    +

    There are several ways to enter this interface:

    + + +

    Recoll Search

    diff --git a/src/kde/kioslave/recoll/dirif.cpp b/src/kde/kioslave/recoll/dirif.cpp index ed6c8ed7..64259262 100644 --- a/src/kde/kioslave/recoll/dirif.cpp +++ b/src/kde/kioslave/recoll/dirif.cpp @@ -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 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)); diff --git a/src/kde/kioslave/recoll/htmlif.cpp b/src/kde/kioslave/recoll/htmlif.cpp index 2305f65a..0750fd24 100644 --- a/src/kde/kioslave/recoll/htmlif.cpp +++ b/src/kde/kioslave/recoll/htmlif.cpp @@ -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 "

    New Search

    "; + return "

    " + "New Search" +#if KDE_IS_VERSION(4,1,0) + "    m_query.query.toUtf8())) + + "/\">Directory view (you may need to reload the page)" +#endif + "

    "; } 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) { diff --git a/src/kde/kioslave/recoll/kio_recoll.cpp b/src/kde/kioslave/recoll/kio_recoll.cpp index 60228237..8c26cc99 100644 --- a/src/kde/kioslave/recoll/kio_recoll.cpp +++ b/src/kde/kioslave/recoll/kio_recoll.cpp @@ -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(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; } diff --git a/src/kde/kioslave/recoll/kio_recoll.h b/src/kde/kioslave/recoll/kio_recoll.h index 19f300ff..33b42701 100644 --- a/src/kde/kioslave/recoll/kio_recoll.h +++ b/src/kde/kioslave/recoll/kio_recoll.h @@ -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); diff --git a/src/kde/kioslave/recoll/notes.txt b/src/kde/kioslave/recoll/notes.txt index 00e81e8c8b2129630bc8c99c9ede40058852d2dc..f1dd5452268c143704e2a9432efef17883cc770b 100644 GIT binary patch delta 81 zcmZ2za9f{0BtIoTwV2Bm1h}}kHnui$80#wd(;G delta 152 zcmcbuztEsQBtIoTwV2Bm1h}}uGg9*uipw)gk~1>%(iM_YOUhG$B1%Q6$@w`sR{F)M ziABj73dJQwKxrj~#Jm)AIWCBtzLJhYX>qDTNk*zdL1KEULSAWZQfiSxT2X#3STLg` dH%B2;pDj(no{NiNBYz_YGgpZJ=EEEk`~cK2GNk|j diff --git a/src/query/reslistpager.cpp b/src/query/reslistpager.cpp index 99598702..30cd57dd 100644 --- a/src/query/reslistpager.cpp +++ b/src/query/reslistpager.cpp @@ -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 @@ -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 diff --git a/src/query/reslistpager.h b/src/query/reslistpager.h index 4811028b..b9a9e0d4 100644 --- a/src/query/reslistpager.h +++ b/src/query/reslistpager.h @@ -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 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 m_docSource; - int m_pagesize; + const int m_pagesize; bool m_hasNext; vector m_respage; diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index f3ea24e9..cb622f20 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -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; diff --git a/src/utils/pathut.h b/src/utils/pathut.h index 24064aec..ef602ee1 100644 --- a/src/utils/pathut.h +++ b/src/utils/pathut.h @@ -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 #include @@ -51,7 +51,7 @@ extern list 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);