190 lines
6.1 KiB
C++
190 lines
6.1 KiB
C++
#ifndef _RECOLL_H
|
|
#define _RECOLL_H
|
|
/* Copyright (C) 2005 J.F.Dockes
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <string>
|
|
using std::string;
|
|
|
|
#include <qglobal.h>
|
|
#include <qstring.h>
|
|
|
|
#include <kurl.h>
|
|
#include <kio/global.h>
|
|
#include <kio/slavebase.h>
|
|
#include <kdeversion.h>
|
|
|
|
#include "rclconfig.h"
|
|
#include "rcldb.h"
|
|
#include "reslistpager.h"
|
|
#include "docseq.h"
|
|
#include "refcntr.h"
|
|
|
|
class RecollProtocol;
|
|
|
|
/** Specialize the recoll html pager for the kind of links we use etc. */
|
|
class RecollKioPager : public ResListPager {
|
|
public:
|
|
RecollKioPager() : m_parent(0) {}
|
|
void setParent(RecollProtocol *proto) {m_parent = proto;}
|
|
|
|
virtual bool append(const string& data);
|
|
virtual bool append(const string& data, int, const Rcl::Doc&)
|
|
{return append(data);}
|
|
virtual string detailsLink();
|
|
virtual const string &parFormat();
|
|
virtual string nextUrl();
|
|
virtual string prevUrl();
|
|
virtual string pageTop();
|
|
|
|
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 isPreview(QueryDesc *q, int *num) {
|
|
if (m_type != UIMT_PREVIEW) 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,
|
|
UIMT_PREVIEW};
|
|
MyType m_type;
|
|
};
|
|
|
|
|
|
/**
|
|
* A KIO slave to execute and display Recoll searches.
|
|
*
|
|
* Things are made a little complicated because KIO slaves can't hope
|
|
* that their internal state will remain consistent with their user
|
|
* application state: slaves die, are restarted, reused, at random
|
|
* between requests.
|
|
* In our case, this means that any request has to be processed
|
|
* without reference to the last operation performed. Ie, if the
|
|
* search parameters are not those from the last request, the search
|
|
* must be restarted anew. This happens for example with different
|
|
* searches in 2 konqueror screens: typically only one kio_slave will
|
|
* be used.
|
|
* The fact that we check if the search is the same as the last one,
|
|
* to avoid restarting is an optimization, not the base mechanism
|
|
* (contrary to what was initially assumed, and may have left a few
|
|
* crumbs around).
|
|
*
|
|
* We have two modes of operation, one based on html forms and result
|
|
* pages, which can potentially be developped to the full Recoll
|
|
* functionality, and one based on a directory listing model, which
|
|
* will always be more limited, but may be useful in some cases to
|
|
* allow easy copying of files etc. Which one is in use is decided by
|
|
* the form of the URL.
|
|
*/
|
|
class RecollProtocol : public KIO::SlaveBase {
|
|
public:
|
|
RecollProtocol(const QByteArray &pool, const QByteArray &app );
|
|
virtual ~RecollProtocol();
|
|
virtual void mimetype(const KUrl& url);
|
|
virtual void get(const KUrl& url);
|
|
// The directory mode is not available with KDE 4.0, I could find
|
|
// no way to avoid crashing kdirmodel
|
|
#if KDE_IS_VERSION(4,1,0)
|
|
virtual void stat(const KUrl & url);
|
|
virtual void listDir(const KUrl& url);
|
|
#endif
|
|
|
|
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 QueryDesc& qd);
|
|
|
|
void searchPage();
|
|
void queryDetails();
|
|
string makeQueryUrl(int page, bool isdet = false);
|
|
bool syncSearch(const QueryDesc& qd);
|
|
void htmlDoSearch(const QueryDesc& qd);
|
|
void showPreview(const Rcl::Doc& doc);
|
|
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
|
|
// changes. This is very wasteful 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;
|
|
RefCntr<DocSequence> m_source;
|
|
// Note: page here is not used, current page always comes from m_pager.
|
|
QueryDesc m_query;
|
|
};
|
|
|
|
extern "C" {int kdemain(int, char**);}
|
|
|
|
#endif // _RECOLL_H
|