revamped history feature to be udi-based while supporting old format
This commit is contained in:
parent
35f32a18a8
commit
b7166eb67e
@ -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
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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_ */
|
||||
|
||||
@ -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
123
src/query/dynconf.h
Normal 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_ */
|
||||
@ -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_ */
|
||||
Loading…
x
Reference in New Issue
Block a user