revamped history feature to be udi-based while supporting old format

This commit is contained in:
dockes 2009-11-23 16:12:20 +00:00
parent 35f32a18a8
commit b7166eb67e
12 changed files with 291 additions and 266 deletions

View File

@ -6,8 +6,8 @@ LIBS = librcl.a
all: $(LIBS)
OBJS = rclaspell.o rclconfig.o rclinit.o textsplit.o unacpp.o beaglequeue.o csguess.o fsindexer.o indexer.o mimetype.o htmlparse.o myhtmlparse.o mimehandler.o internfile.o mh_exec.o mh_execm.o mh_html.o mh_mail.o mh_mbox.o mh_text.o docseq.o docseqdb.o docseqhist.o filtseq.o history.o plaintorich.o recollq.o reslistpager.o sortseq.o wasastringtoquery.o wasatorcl.o rcldb.o rcldoc.o rclquery.o searchdata.o stemdb.o stoplist.o base64.o circache.o closefrom.o conftree.o copyfile.o debuglog.o execmd.o fstreewalk.o idfile.o fileudi.o md5.o mimeparse.o netcon.o pathut.o pxattr.o readfile.o smallut.o transcode.o wipedir.o x11mon.o mime-getpart.o mime-parsefull.o mime-parseonlyheader.o mime-printbody.o mime-printdoc.o mime-printheader.o mime.o convert.o iodevice.o iofactory.o
DEPS = rclaspell.dep.stamp rclconfig.dep.stamp rclinit.dep.stamp textsplit.dep.stamp unacpp.dep.stamp beaglequeue.dep.stamp csguess.dep.stamp fsindexer.dep.stamp indexer.dep.stamp mimetype.dep.stamp htmlparse.dep.stamp myhtmlparse.dep.stamp mimehandler.dep.stamp internfile.dep.stamp mh_exec.dep.stamp mh_execm.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_mbox.dep.stamp mh_text.dep.stamp docseq.dep.stamp docseqdb.dep.stamp docseqhist.dep.stamp filtseq.dep.stamp history.dep.stamp plaintorich.dep.stamp recollq.dep.stamp reslistpager.dep.stamp sortseq.dep.stamp wasastringtoquery.dep.stamp wasatorcl.dep.stamp rcldb.dep.stamp rcldoc.dep.stamp rclquery.dep.stamp searchdata.dep.stamp stemdb.dep.stamp stoplist.dep.stamp base64.dep.stamp circache.dep.stamp closefrom.dep.stamp conftree.dep.stamp copyfile.dep.stamp debuglog.dep.stamp execmd.dep.stamp fstreewalk.dep.stamp idfile.dep.stamp fileudi.dep.stamp md5.dep.stamp mimeparse.dep.stamp netcon.dep.stamp pathut.dep.stamp pxattr.dep.stamp readfile.dep.stamp smallut.dep.stamp transcode.dep.stamp wipedir.dep.stamp x11mon.dep.stamp mime-getpart.dep.stamp mime-parsefull.dep.stamp mime-parseonlyheader.dep.stamp mime-printbody.dep.stamp mime-printdoc.dep.stamp mime-printheader.dep.stamp mime.dep.stamp convert.dep.stamp iodevice.dep.stamp iofactory.dep.stamp
OBJS = rclaspell.o rclconfig.o rclinit.o textsplit.o unacpp.o beaglequeue.o csguess.o fsindexer.o indexer.o mimetype.o htmlparse.o myhtmlparse.o mimehandler.o internfile.o mh_exec.o mh_execm.o mh_html.o mh_mail.o mh_mbox.o mh_text.o docseq.o docseqdb.o docseqhist.o filtseq.o dynconf.o plaintorich.o recollq.o reslistpager.o sortseq.o wasastringtoquery.o wasatorcl.o rcldb.o rcldoc.o rclquery.o searchdata.o stemdb.o stoplist.o base64.o circache.o closefrom.o conftree.o copyfile.o debuglog.o execmd.o fstreewalk.o idfile.o fileudi.o md5.o mimeparse.o netcon.o pathut.o pxattr.o readfile.o smallut.o transcode.o wipedir.o x11mon.o mime-getpart.o mime-parsefull.o mime-parseonlyheader.o mime-printbody.o mime-printdoc.o mime-printheader.o mime.o convert.o iodevice.o iofactory.o
DEPS = rclaspell.dep.stamp rclconfig.dep.stamp rclinit.dep.stamp textsplit.dep.stamp unacpp.dep.stamp beaglequeue.dep.stamp csguess.dep.stamp fsindexer.dep.stamp indexer.dep.stamp mimetype.dep.stamp htmlparse.dep.stamp myhtmlparse.dep.stamp mimehandler.dep.stamp internfile.dep.stamp mh_exec.dep.stamp mh_execm.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_mbox.dep.stamp mh_text.dep.stamp docseq.dep.stamp docseqdb.dep.stamp docseqhist.dep.stamp filtseq.dep.stamp dynconf.dep.stamp plaintorich.dep.stamp recollq.dep.stamp reslistpager.dep.stamp sortseq.dep.stamp wasastringtoquery.dep.stamp wasatorcl.dep.stamp rcldb.dep.stamp rcldoc.dep.stamp rclquery.dep.stamp searchdata.dep.stamp stemdb.dep.stamp stoplist.dep.stamp base64.dep.stamp circache.dep.stamp closefrom.dep.stamp conftree.dep.stamp copyfile.dep.stamp debuglog.dep.stamp execmd.dep.stamp fstreewalk.dep.stamp idfile.dep.stamp fileudi.dep.stamp md5.dep.stamp mimeparse.dep.stamp netcon.dep.stamp pathut.dep.stamp pxattr.dep.stamp readfile.dep.stamp smallut.dep.stamp transcode.dep.stamp wipedir.dep.stamp x11mon.dep.stamp mime-getpart.dep.stamp mime-parsefull.dep.stamp mime-parseonlyheader.dep.stamp mime-printbody.dep.stamp mime-printdoc.dep.stamp mime-printheader.dep.stamp mime.dep.stamp convert.dep.stamp iodevice.dep.stamp iofactory.dep.stamp
librcl.a : $(DEPS) $(OBJS) unac.o
ar ru librcl.a $(OBJS) unac.o
@ -63,8 +63,8 @@ docseqhist.o : ../query/docseqhist.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/docseqhist.cpp
filtseq.o : ../query/filtseq.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/filtseq.cpp
history.o : ../query/history.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/history.cpp
dynconf.o : ../query/dynconf.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/dynconf.cpp
plaintorich.o : ../query/plaintorich.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/plaintorich.cpp
recollq.o : ../query/recollq.cpp
@ -227,9 +227,9 @@ docseqhist.dep.stamp : ../query/docseqhist.cpp
filtseq.dep.stamp : ../query/filtseq.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../query/filtseq.cpp > filtseq.dep
touch filtseq.dep.stamp
history.dep.stamp : ../query/history.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../query/history.cpp > history.dep
touch history.dep.stamp
dynconf.dep.stamp : ../query/dynconf.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../query/dynconf.cpp > dynconf.dep
touch dynconf.dep.stamp
plaintorich.dep.stamp : ../query/plaintorich.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../query/plaintorich.cpp > plaintorich.dep
touch plaintorich.dep.stamp
@ -350,7 +350,7 @@ include docseq.dep
include docseqdb.dep
include docseqhist.dep
include filtseq.dep
include history.dep
include dynconf.dep
include plaintorich.dep
include recollq.dep
include reslistpager.dep

View File

@ -28,7 +28,7 @@ ${depth}/query/docseq.cpp \
${depth}/query/docseqdb.cpp \
${depth}/query/docseqhist.cpp \
${depth}/query/filtseq.cpp \
${depth}/query/history.cpp \
${depth}/query/dynconf.cpp \
${depth}/query/plaintorich.cpp \
${depth}/query/recollq.cpp \
${depth}/query/reslistpager.cpp \

View File

@ -184,8 +184,6 @@ void rwSettings(bool writing)
// variable.
// This are stored inside the dynamic configuration file (aka: history),
// as they are likely to depend on RECOLL_CONFDIR.
const string allEdbsSk = "allExtDbs";
const string actEdbsSk = "actExtDbs";
if (writing) {
g_dynconf->eraseAll(allEdbsSk);
for (list<string>::const_iterator it = prefs.allExtraDbs.begin();

View File

@ -83,7 +83,7 @@ RclConfig* RclConfig::getMainConfig()
return rclconfig;
}
RclHistory *g_dynconf;
RclDynConf *g_dynconf;
int recollNeedsExit;
int startIndexingAfterConfig;
RclMain *mainWindow;
@ -276,7 +276,7 @@ int main(int argc, char **argv)
#endif
string historyfile = path_cat(rclconfig->getConfDir(), "history");
g_dynconf = new RclHistory(historyfile);
g_dynconf = new RclDynConf(historyfile);
if (!g_dynconf || !g_dynconf->ok()) {
QString msg = app.translate("Main", "Configuration problem (dynconf");
QMessageBox::critical(0, "Recoll", msg);

View File

@ -75,6 +75,7 @@ using std::pair;
#include "cancelcheck.h"
#include "preview_w.h"
#include "guiutils.h"
#include "docseqhist.h"
#if (QT_VERSION < 0x030300)
#define wasCanceled wasCancelled
@ -950,7 +951,9 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
}
// Enter document in document history
g_dynconf->enterDoc(idoc.url, idoc.ipath);
map<string,string>::const_iterator udit = idoc.meta.find(Rcl::Doc::keyudi);
if (udit != idoc.meta.end())
historyEnterDoc(g_dynconf, udit->second);
editor->setFocus();
emit(previewExposed(this, m_searchId, docnum));

View File

@ -779,7 +779,6 @@ void RclMain::previewPrevOrNextInTab(Preview * w, int sid, int docnum, bool nxt)
return;
}
// Check that file exists in file system
w->makeDocCurrent(doc, docnum, true);
}
@ -910,7 +909,7 @@ void RclMain::startNativeViewer(Rcl::Doc doc)
return;
}
// Extract possible attributes
// Extract possible viewer attributes
ConfSimple attrs;
string cmd;
rclconfig->valueSplitAttributes(cmdplusattr, cmd, attrs);
@ -1037,8 +1036,9 @@ void RclMain::startNativeViewer(Rcl::Doc doc)
QString::fromUtf8(prcmd.c_str()) + "]";
stb->message(msg, 5000);
}
if (!istempfile)
g_dynconf->enterDoc(fn, doc.ipath);
historyEnterDoc(g_dynconf, doc.meta[Rcl::Doc::keyudi]);
// We should actually monitor these processes so that we can
// delete the temp files when they exit
LOGDEB(("Executing: [%s]\n", ncmd.c_str()));
@ -1124,7 +1124,7 @@ void RclMain::eraseDocHistory()
{
// Clear file storage
if (g_dynconf)
g_dynconf->eraseAll(RclHistory::docSubkey);
g_dynconf->eraseAll(docHistSubKey);
// Clear possibly displayed history
if (resList->displayingHistory()) {
showDocHistory();

View File

@ -22,7 +22,7 @@
#include "rclconfig.h"
#include "rcldb.h"
#include "idxthread.h"
#include "history.h"
#include "dynconf.h"
// Misc declarations in need of sharing between the UI files
@ -33,7 +33,7 @@ extern RclConfig *rclconfig;
extern Rcl::Db *rcldb;
extern int recollNeedsExit;
extern int startIndexingAfterConfig; // 1st startup
extern RclHistory *g_dynconf;
extern RclDynConf *g_dynconf;
extern void startManual(const string& helpindex);
#ifdef RCL_USE_ASPELL

View File

@ -25,6 +25,84 @@ static char rcsid[] = "@(#$Id: docseqhist.cpp,v 1.4 2008-09-29 08:59:20 dockes E
#include "rcldb.h"
#include "fileudi.h"
#include "internfile.h"
#include "base64.h"
#include "debuglog.h"
#include "smallut.h"
// Encode document history entry:
// U + Unix time + base64 of udi
// The U distinguishes udi-based entries from older fn+ipath ones
bool RclDHistoryEntry::encode(string& value)
{
char chartime[20];
sprintf(chartime, "%ld", unixtime);
string budi;
base64_encode(udi, budi);
value = string("U ") + string(chartime) + " " + budi;
return true;
}
// Decode. We support historical entries which were like "time b64fn [b64ipath]"
// Current entry format is "U time b64udi"
bool RclDHistoryEntry::decode(const string &value)
{
list<string> vall;
stringToStrings(value, vall);
list<string>::const_iterator it = vall.begin();
udi.erase();
string fn, ipath;
switch (vall.size()) {
case 2:
// Old fn+ipath, null ipath case
unixtime = atol((*it++).c_str());
base64_decode(*it++, fn);
break;
case 3:
if (!it->compare("U")) {
// New udi-based entry
it++;
unixtime = atol((*it++).c_str());
base64_decode(*it++, udi);
} else {
// Old fn + ipath. We happen to know how to build an udi
unixtime = atol((*it++).c_str());
base64_decode(*it++, fn);
base64_decode(*it, ipath);
}
break;
default:
return false;
}
if (!fn.empty()) {
// Old style entry found, make an udi, using the fs udi maker
make_udi(fn, ipath, udi);
}
LOGDEB(("RclDHistoryEntry::decode: udi [%s]\n", udi.c_str()));
return true;
}
bool RclDHistoryEntry::equal(const DynConfEntry& other)
{
const RclDHistoryEntry& e = dynamic_cast<const RclDHistoryEntry&>(other);
return e.udi == udi;
}
bool historyEnterDoc(RclDynConf *dncf, const string& udi)
{
LOGDEB(("historyEnterDoc: [%s] into %s\n",
udi.c_str(), dncf->getFilename().c_str()));
RclDHistoryEntry ne(time(0), udi);
RclDHistoryEntry scratch;
return dncf->insertNew(docHistSubKey, ne, scratch, 200);
}
list<RclDHistoryEntry> getDocHistory(RclDynConf* dncf)
{
return dncf->getList<RclDHistoryEntry>(docHistSubKey);
}
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
{
@ -32,7 +110,7 @@ bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
if (!m_hist)
return false;
if (m_hlist.empty())
m_hlist = m_hist->getDocHistory();
m_hlist = getDocHistory(m_hist);
if (num < 0 || num >= (int)m_hlist.size())
return false;
@ -48,7 +126,8 @@ bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
while (skip--)
m_it++;
if (sh) {
if (m_prevtime < 0 || abs (float(m_prevtime) - float(m_it->unixtime)) > 86400) {
if (m_prevtime < 0 ||
abs (float(m_prevtime) - float(m_it->unixtime)) > 86400) {
m_prevtime = m_it->unixtime;
time_t t = (time_t)(m_it->unixtime);
*sh = string(ctime(&t));
@ -57,12 +136,10 @@ bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
} else
sh->erase();
}
string udi;
make_udi(m_it->fn, m_it->ipath, udi);
bool ret = m_db->getDoc(udi, doc);
bool ret = m_db->getDoc(m_it->udi, doc);
if (!ret) {
doc.url = string("file://") + m_it->fn;
doc.ipath = m_it->ipath;
doc.url = "UNKNOWN";
doc.ipath = "";
}
return ret;
}
@ -79,6 +156,6 @@ bool DocSequenceHistory::getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc)
int DocSequenceHistory::getResCnt()
{
if (m_hlist.empty())
m_hlist = m_hist->getDocHistory();
m_hlist = getDocHistory(m_hist);
return m_hlist.size();
}

View File

@ -19,18 +19,32 @@
/* @(#$Id: docseqhist.h,v 1.3 2008-09-29 08:59:20 dockes Exp $ (C) 2004 J.F.Dockes */
#include "docseq.h"
#include "history.h"
#include "dynconf.h"
namespace Rcl {
class Db;
}
/** DynConf Document history entry */
class RclDHistoryEntry : public DynConfEntry {
public:
RclDHistoryEntry() : unixtime(0) {}
RclDHistoryEntry(long t, const string& u)
: unixtime(t), udi(u) {}
virtual ~RclDHistoryEntry() {}
virtual bool decode(const string &value);
virtual bool encode(string& value);
virtual bool equal(const DynConfEntry& other);
long unixtime;
string udi;
};
/** A DocSequence coming from the history file.
* History is kept as a list of urls. This queries the db to fetch
* metadata for an url key */
class DocSequenceHistory : public DocSequence {
public:
DocSequenceHistory(Rcl::Db *d, RclHistory *h, const string &t)
DocSequenceHistory(Rcl::Db *d, RclDynConf *h, const string &t)
: DocSequence(t), m_db(d), m_hist(h), m_prevnum(-1), m_prevtime(-1) {}
virtual ~DocSequenceHistory() {}
@ -41,7 +55,7 @@ class DocSequenceHistory : public DocSequence {
void setDescription(const string& desc) {m_description = desc;}
private:
Rcl::Db *m_db;
RclHistory *m_hist;
RclDynConf *m_hist;
int m_prevnum;
long m_prevtime;
string m_description; // This is just an nls translated 'doc history'
@ -49,4 +63,6 @@ class DocSequenceHistory : public DocSequence {
list<RclDHistoryEntry>::const_iterator m_it;
};
extern bool historyEnterDoc(RclDynConf *dncf, const string& udi);
#endif /* _DOCSEQ_H_INCLUDED_ */

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: history.cpp,v 1.9 2007-12-13 06:58:21 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: dynconf.cpp,v 1.9 2007-12-13 06:58:21 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -23,7 +23,7 @@ static char rcsid[] = "@(#$Id: history.cpp,v 1.9 2007-12-13 06:58:21 dockes Exp
#include <time.h>
#include <cstdlib>
#include "history.h"
#include "dynconf.h"
#include "base64.h"
#include "smallut.h"
#include "debuglog.h"
@ -32,63 +32,20 @@ static char rcsid[] = "@(#$Id: history.cpp,v 1.9 2007-12-13 06:58:21 dockes Exp
using namespace std;
#endif
// Encode/decode document history entry: Unix time + base64 of fn +
// base64 of ipath separated by a space. If ipath is not set, there
// are only 2 parts
bool RclDHistoryEntry::encode(string& value)
{
char chartime[20];
sprintf(chartime, "%ld", unixtime);
string bfn, bipath;
base64_encode(fn, bfn);
base64_encode(ipath, bipath);
value = string(chartime) + " " + bfn + " " + bipath;
return true;
}
bool RclDHistoryEntry::decode(const string &value)
{
list<string> vall;
stringToStrings(value, vall);
list<string>::const_iterator it1 = vall.begin();
if (vall.size() < 2)
return false;
unixtime = atol((*it1++).c_str());
base64_decode(*it1++, fn);
if (vall.size() == 3)
base64_decode(*it1, ipath);
else
ipath.erase();
return true;
}
bool RclDHistoryEntry::equal(const HistoryEntry& other)
{
const RclDHistoryEntry& e = dynamic_cast<const RclDHistoryEntry&>(other);
return e.fn == fn && e.ipath == ipath;
}
// Well known keys for history and external indexes.
const string docHistSubKey = "docs";
const string allEdbsSk = "allExtDbs";
const string actEdbsSk = "actExtDbs";
// Encode/decode simple string. base64 used to avoid problems with
// strange chars
bool RclSListEntry::encode(string& enc)
// @param sk section this is for
// @param n new entry
// @param s a scratch entry used for decoding and comparisons.
// This avoids templating this routine for the actual entry type.
bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
int maxlen)
{
base64_encode(value, enc);
return true;
}
bool RclSListEntry::decode(const string &enc)
{
base64_decode(enc, value);
return true;
}
bool RclSListEntry::equal(const HistoryEntry& other)
{
const RclSListEntry& e = dynamic_cast<const RclSListEntry&>(other);
return e.value == value;
}
bool RclHistory::insertNew(const string &sk, HistoryEntry &n, HistoryEntry &s)
{
// Is this doc already in history ? If it is we remove the old entry
// Is this doc already in list ? If it is we remove the old entry
list<string> names = m_data.getNames(sk);
list<string>::const_iterator it;
bool changed = false;
@ -111,13 +68,13 @@ bool RclHistory::insertNew(const string &sk, HistoryEntry &n, HistoryEntry &s)
if (changed)
names = m_data.getNames(sk);
// How many do we have
if (names.size() >= m_mlen) {
// Need to prune ?
if (maxlen > 0 && names.size() >= (unsigned int)maxlen) {
// Need to erase entries until we're back to size. Note that
// we don't ever reset numbers. Problems will arise when
// history is 4 billion entries old
it = names.begin();
for (unsigned int i = 0; i < names.size() - m_mlen + 1; i++, it++) {
for (unsigned int i = 0; i < names.size() - maxlen + 1; i++, it++) {
m_data.erase(*it, sk);
}
}
@ -137,12 +94,10 @@ bool RclHistory::insertNew(const string &sk, HistoryEntry &n, HistoryEntry &s)
return false;
}
return true;
}
bool RclHistory::eraseAll(const string &sk)
bool RclDynConf::eraseAll(const string &sk)
{
// Is this doc already in history ? If it is we remove the old entry
list<string> names = m_data.getNames(sk);
list<string>::const_iterator it;
for (it = names.begin(); it != names.end(); it++) {
@ -150,31 +105,36 @@ bool RclHistory::eraseAll(const string &sk)
}
return true;
}
bool RclHistory::truncate(const string &sk, unsigned int n)
// Generic string list specialization ///////////////////////////////////
// Encode/decode simple string. base64 used to avoid problems with
// strange chars
bool RclSListEntry::encode(string& enc)
{
// Is this doc already in history ? If it is we remove the old entry
list<string> names = m_data.getNames(sk);
if (names.size() <= n)
return true;
unsigned int i = 0;
for (list<string>::const_iterator it = names.begin();
it != names.end(); it++, i++) {
if (i >= n)
m_data.erase(*it, sk);
}
base64_encode(value, enc);
return true;
}
bool RclHistory::enterString(const string sk, const string value)
bool RclSListEntry::decode(const string &enc)
{
base64_decode(enc, value);
return true;
}
bool RclSListEntry::equal(const DynConfEntry& other)
{
const RclSListEntry& e = dynamic_cast<const RclSListEntry&>(other);
return e.value == value;
}
bool RclDynConf::enterString(const string sk, const string value, int maxlen)
{
RclSListEntry ne(value);
RclSListEntry scratch;
return insertNew(sk, ne, scratch);
return insertNew(sk, ne, scratch, maxlen);
}
list<string> RclHistory::getStringList(const string sk)
list<string> RclDynConf::getStringList(const string sk)
{
list<RclSListEntry> el = getHistory<RclSListEntry>(sk);
list<RclSListEntry> el = getList<RclSListEntry>(sk);
list<string> sl;
for (list<RclSListEntry>::const_iterator it = el.begin();
it != el.end(); it++)
@ -182,26 +142,8 @@ list<string> RclHistory::getStringList(const string sk)
return sl;
}
string RclHistory::docSubkey = "docs";
/// *************** History entries specific methods
bool RclHistory::enterDoc(const string fn, const string ipath)
{
LOGDEB(("RclDHistory::enterDoc: [%s] [%s] into %s\n",
fn.c_str(), ipath.c_str(), m_data.getFilename().c_str()));
RclDHistoryEntry ne(time(0), fn, ipath);
RclDHistoryEntry scratch;
return insertNew(docSubkey, ne, scratch);
}
list<RclDHistoryEntry> RclHistory::getDocHistory()
{
return getHistory<RclDHistoryEntry>(docSubkey);
}
#else
#include <string>
#include <iostream>
@ -216,7 +158,7 @@ static string thisprog;
static string usage =
"trhist [opts] <filename>\n"
" [-s <subkey>]: specify subkey (default: RclHistory::docSubkey)\n"
" [-s <subkey>]: specify subkey (default: RclDynConf::docHistSubKey)\n"
" [-e] : erase all\n"
" [-a <string>] enter string (needs -s, no good for history entries\n"
"\n"
@ -236,7 +178,7 @@ static int op_flags;
int main(int argc, char **argv)
{
string sk = RclHistory::docSubkey;
string sk = "docs";
string value;
thisprog = argv[0];
@ -264,7 +206,7 @@ int main(int argc, char **argv)
Usage();
string filename = *argv++;argc--;
RclHistory hist(filename, 5);
RclDynConf hist(filename, 5);
DebugLog::getdbl()->setloglevel(DEBDEB1);
DebugLog::setfilename("stderr");

123
src/query/dynconf.h Normal file
View File

@ -0,0 +1,123 @@
/*
* 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.
*/
#ifndef _DYNCONF_H_INCLUDED_
#define _DYNCONF_H_INCLUDED_
/* @(#$Id: dynconf.h,v 1.7 2007-06-20 13:16:11 dockes Exp $ (C) 2004 J.F.Dockes */
/**
* Dynamic configuration storage
*
* This used to be called "history" because of the initial usage.
* Used to store some parameters which would fit neither in recoll.conf,
* basically because they change a lot, nor in the QT preferences file, mostly
* because they are specific to a configuration directory.
* Examples:
* - History of documents selected for preview
* - Active and inactive external databases (depend on the
* configuration directory)
* - ...
*
* The storage is performed in a ConfSimple file, with subkeys and
* encodings which depend on the data stored. Under each section, the keys
* are sequential numeric, so this basically manages a set of lists.
*
*/
#include <string>
#include <list>
#include <utility>
#include "conftree.h"
#ifndef NO_NAMESPACES
using namespace std;
#endif
// Entry interface.
class DynConfEntry {
public:
virtual ~DynConfEntry() {}
virtual bool decode(const string &value) = 0;
virtual bool encode(string& value) = 0;
virtual bool equal(const DynConfEntry &other) = 0;
};
/** String storage generic object */
class RclSListEntry : public DynConfEntry {
public:
RclSListEntry() {}
RclSListEntry(const string& v) : value(v) {}
virtual ~RclSListEntry() {}
virtual bool decode(const string &enc);
virtual bool encode(string& enc);
virtual bool equal(const DynConfEntry& other);
string value;
};
/** The dynamic configuration class */
class RclDynConf {
public:
RclDynConf(const string &fn)
: m_data(fn.c_str()) {}
bool ok() {return m_data.getStatus() == ConfSimple::STATUS_RW;}
string getFilename() {return m_data.getFilename();}
// Generic methods
bool eraseAll(const string& sk);
bool insertNew(const string& sk, DynConfEntry &n, DynConfEntry &s,
int maxlen = -1);
template<typename Tp> list<Tp> getList(const string& sk);
// Specialized methods for simple string lists, designated by the
// subkey value
bool enterString(const string sk, const string value, int maxlen = -1);
list<string> getStringList(const string sk);
private:
unsigned int m_mlen;
ConfSimple m_data;
};
template<typename Tp> list<Tp> RclDynConf::getList(const string &sk)
{
list<Tp> mlist;
Tp entry;
list<string> names = m_data.getNames(sk);
for (list<string>::const_iterator it = names.begin();
it != names.end(); it++) {
string value;
if (m_data.get(*it, value, sk)) {
if (!entry.decode(value))
continue;
mlist.push_front(entry);
}
}
return mlist;
}
// Defined subkeys. Values in dynconf.cpp
// History
extern const string docHistSubKey;
// All external indexes
extern const string allEdbsSk;
// Active external indexes
extern const string actEdbsSk;
#endif /* _DYNCONF_H_INCLUDED_ */

View File

@ -1,134 +0,0 @@
/*
* 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.
*/
#ifndef _HISTORY_H_INCLUDED_
#define _HISTORY_H_INCLUDED_
/* @(#$Id: history.h,v 1.7 2007-06-20 13:16:11 dockes Exp $ (C) 2004 J.F.Dockes */
/**
* Dynamic configuration storage
*
* The term "history" is a misnomer as this code is now used to save
* all dynamic parameters except those that are stored in the global
* recollrc QT preferences file. Examples:
* - History of documents selected for preview
* - Active and inactive external databases (these should depend on the
* configuration directory and cant be stored in recollrc).
* - ...
*
* The storage is performed in a ConSimple file, with subkeys and
* encodings which depend on the data stored.
*
*/
#include <string>
#include <list>
#include <utility>
#include "conftree.h"
#ifndef NO_NAMESPACES
using namespace std;
#endif
class HistoryEntry {
public:
virtual ~HistoryEntry() {}
virtual bool decode(const string &value) = 0;
virtual bool encode(string& value) = 0;
virtual bool equal(const HistoryEntry &other) = 0;
};
/** Document history entry */
class RclDHistoryEntry : public HistoryEntry {
public:
RclDHistoryEntry() : unixtime(0) {}
RclDHistoryEntry(long t, const string& f, const string& i)
: unixtime(t), fn(f), ipath(i) {}
virtual ~RclDHistoryEntry() {}
virtual bool decode(const string &value);
virtual bool encode(string& value);
virtual bool equal(const HistoryEntry& other);
long unixtime;
string fn;
string ipath;
};
/** String storage generic object */
class RclSListEntry : public HistoryEntry {
public:
RclSListEntry() {}
RclSListEntry(const string& v) : value(v) {}
virtual ~RclSListEntry() {}
virtual bool decode(const string &enc);
virtual bool encode(string& enc);
virtual bool equal(const HistoryEntry& other);
string value;
};
/**
* The history class. This uses a ConfSimple for storage, and should be
* renamed something like dynconf, as it is used to stored quite a few
* things beyond doc history: all dynamic configuration parameters that are
* not suitable for QT settings because they are specific to a RECOLL_CONFDIR
*/
class RclHistory {
public:
RclHistory(const string &fn, unsigned int maxsize=100)
: m_mlen(maxsize), m_data(fn.c_str()) {}
bool ok() {return m_data.getStatus() == ConfSimple::STATUS_RW;}
// Specific methods for history entries. These are for convenience, they
// just call regular methods with key RclHistory::docSubkey;
bool enterDoc(const string fn, const string ipath);
list<RclDHistoryEntry> getDocHistory();
// Generic methods used for string lists, designated by the subkey value
bool enterString(const string sk, const string value);
list<string> getStringList(const string sk);
bool eraseAll(const string& sk);
bool truncate(const string& sk, unsigned int n);
static string docSubkey;
private:
unsigned int m_mlen;
ConfSimple m_data;
bool insertNew(const string& sk, HistoryEntry &n, HistoryEntry &s);
template<typename Tp> list<Tp> getHistory(const string& sk);
};
template<typename Tp> list<Tp> RclHistory::getHistory(const string &sk)
{
list<Tp> mlist;
Tp entry;
list<string> names = m_data.getNames(sk);
for (list<string>::const_iterator it = names.begin();
it != names.end(); it++) {
string value;
if (m_data.get(*it, value, sk)) {
if (!entry.decode(value))
continue;
mlist.push_front(entry);
}
}
return mlist;
}
#endif /* _HISTORY_H_INCLUDED_ */