diff --git a/src/qtgui/main.cpp b/src/qtgui/main.cpp index c47d024e..1b99268e 100644 --- a/src/qtgui/main.cpp +++ b/src/qtgui/main.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: main.cpp,v 1.19 2005-11-25 10:26:35 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: main.cpp,v 1.20 2005-11-28 15:31:01 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #include @@ -36,7 +36,7 @@ int recollNeedsExit; string tmpdir; bool showicons; string iconsdir; -RclQHistory *history; +RclDHistory *history; void getQueryStemming(bool &dostem, std::string &stemlang) { @@ -172,7 +172,7 @@ int main( int argc, char ** argv ) string historyfile = rclconfig->getConfDir(); path_cat(historyfile, "history"); - history = new RclQHistory(historyfile); + history = new RclDHistory(historyfile); dbdir = path_tildexpand(dbdir); diff --git a/src/qtgui/recoll.h b/src/qtgui/recoll.h index fc17d869..e196ee6f 100644 --- a/src/qtgui/recoll.h +++ b/src/qtgui/recoll.h @@ -1,6 +1,6 @@ #ifndef _RECOLL_H_INCLUDED_ #define _RECOLL_H_INCLUDED_ -/* @(#$Id: recoll.h,v 1.6 2005-11-25 10:02:36 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: recoll.h,v 1.7 2005-11-28 15:31:01 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -20,7 +20,7 @@ extern Rcl::Db *rcldb; extern std::string tmpdir; extern bool showicons; extern string iconsdir; -extern RclQHistory *history; +extern RclDHistory *history; extern int recollNeedsExit; diff --git a/src/qtgui/recollmain.ui.h b/src/qtgui/recollmain.ui.h index 6ddda70a..a69a64b7 100644 --- a/src/qtgui/recollmain.ui.h +++ b/src/qtgui/recollmain.ui.h @@ -260,7 +260,7 @@ void RecollMain::reslistTE_doubleClicked(int par, int) Rcl::Doc doc; int reldocnum = reldocnumfromparnum(par); - if (!docsource->getDoc(reslist_winfirst + reldocnum, doc, 0)) + if (!docsource->getDoc(reslist_winfirst + reldocnum, doc, 0, 0)) return; // Look for appropriate viewer @@ -439,9 +439,10 @@ void RecollMain::listNextPB_clicked() // Insert results if any in result list window for (int i = 0; i < last; i++) { + string sh; doc.erase(); - if (!docsource->getDoc(reslist_winfirst + i, doc, &percent)) { + if (!docsource->getDoc(reslist_winfirst + i, doc, &percent, &sh)) { if (i == 0) reslist_winfirst = -1; break; @@ -498,7 +499,10 @@ void RecollMain::listNextPB_clicked() } string abst = stripMarkup(doc.abstract); LOGDEB1(("Abstract: {%s}\n", abst.c_str())); - string result = string("

"); + string result; + if (!sh.empty()) + result += string("
") + sh + "

\n"; + result += string("

"); if (!img_name.empty()) { result += ""; } diff --git a/src/query/docseq.cpp b/src/query/docseq.cpp index f2415e18..82c04314 100644 --- a/src/query/docseq.cpp +++ b/src/query/docseq.cpp @@ -1,10 +1,13 @@ #ifndef lint -static char rcsid[] = "@(#$Id: docseq.cpp,v 1.1 2005-11-25 10:02:36 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: docseq.cpp,v 1.2 2005-11-28 15:31:01 dockes Exp $ (C) 2005 J.F.Dockes"; #endif +#include + #include "docseq.h" -bool DocSequenceDb::getDoc(int num, Rcl::Doc &doc, int *percent) +bool DocSequenceDb::getDoc(int num, Rcl::Doc &doc, int *percent, string *sh) { + if (sh) sh->erase(); return db ? db->getDoc(num, doc, percent) : false; } @@ -20,7 +23,8 @@ int DocSequenceDb::getResCnt() } -bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, int *percent) { +bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, int *percent, + string *sh) { // Retrieve history list if (!hist) return false; @@ -41,7 +45,15 @@ bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, int *percent) { it++; if (percent) *percent = 100; - return db->getDoc((*it).first, (*it).second, doc); + if (sh) { + if (prevtime < 0 || abs(prevtime - (*it).unixtime) > 86400) { + prevtime = it->unixtime; + time_t t = (time_t)(it->unixtime); + *sh = string(ctime(&t)); + } else + sh->erase(); + } + return db->getDoc((*it).fn, (*it).ipath, doc); } int DocSequenceHistory::getResCnt() diff --git a/src/query/docseq.h b/src/query/docseq.h index 832a528e..dbb997d9 100644 --- a/src/query/docseq.h +++ b/src/query/docseq.h @@ -1,6 +1,6 @@ #ifndef _DOCSEQ_H_INCLUDED_ #define _DOCSEQ_H_INCLUDED_ -/* @(#$Id: docseq.h,v 1.1 2005-11-25 10:02:36 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: docseq.h,v 1.2 2005-11-28 15:31:01 dockes Exp $ (C) 2004 J.F.Dockes */ #include "rcldb.h" #include "history.h" @@ -12,7 +12,8 @@ */ class DocSequence { public: - virtual bool getDoc(int num, Rcl::Doc &doc, int *percent) = 0; + virtual bool getDoc(int num, Rcl::Doc &doc, int *percent, string *sh = 0) + = 0; virtual int getResCnt() = 0; virtual std::string title() = 0; }; @@ -24,7 +25,7 @@ class DocSequenceDb : public DocSequence { public: DocSequenceDb(Rcl::Db *d) : db(d) {} virtual ~DocSequenceDb() {} - virtual bool getDoc(int num, Rcl::Doc &doc, int *percent); + virtual bool getDoc(int num, Rcl::Doc &doc, int *percent, string * = 0); virtual int getResCnt(); virtual std::string title() {return string("Query results");} private: @@ -34,20 +35,21 @@ class DocSequenceDb : public DocSequence { /** A DocSequence coming from the history file */ class DocSequenceHistory : public DocSequence { public: - DocSequenceHistory(Rcl::Db *d, RclQHistory *h) - : db(d), hist(h), prevnum(-1) {} + DocSequenceHistory(Rcl::Db *d, RclDHistory *h) + : db(d), hist(h), prevnum(-1), prevtime(-1) {} virtual ~DocSequenceHistory() {} - virtual bool getDoc(int num, Rcl::Doc &doc, int *percent); + virtual bool getDoc(int num, Rcl::Doc &doc, int *percent, string *sh = 0); virtual int getResCnt(); virtual std::string title() {return string("Document history");} private: Rcl::Db *db; - RclQHistory *hist; + RclDHistory *hist; int prevnum; + long prevtime; - std::list< std::pair > hlist; - std::list< std::pair >::const_iterator it; + std::list hlist; + std::list::const_iterator it; }; #endif /* _DOCSEQ_H_INCLUDED_ */ diff --git a/src/query/history.cpp b/src/query/history.cpp index 3e3bc8e1..657aed94 100644 --- a/src/query/history.cpp +++ b/src/query/history.cpp @@ -1,9 +1,10 @@ #ifndef lint -static char rcsid[] = "@(#$Id: history.cpp,v 1.2 2005-11-25 14:36:45 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: history.cpp,v 1.3 2005-11-28 15:31:01 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #ifndef TEST_HISTORY #include + #include "history.h" #include "base64.h" #include "smallut.h" @@ -13,48 +14,65 @@ static char rcsid[] = "@(#$Id: history.cpp,v 1.2 2005-11-25 14:36:45 dockes Exp using namespace std; #endif -RclQHistory::RclQHistory(const string &fn, unsigned int mxs) +static const char *docSubkey = "docs"; + +RclDHistory::RclDHistory(const string &fn, unsigned int mxs) : m_mlen(mxs), m_data(fn.c_str()) { - } -const char *docSubkey = "docs"; -bool RclQHistory::enterDocument(const string fn, const string ipath) +bool RclDHistory::decodeValue(const string &value, RclDHistoryEntry *e) { - LOGDEB(("RclQHistory::enterDocument: [%s] [%s] into %s\n", + list vall; + stringToStrings(value, vall); + list::const_iterator it1 = vall.begin(); + if (vall.size() < 2) + return false; + e->unixtime = atol((*it1++).c_str()); + base64_decode(*it1++, e->fn); + if (vall.size() == 3) + base64_decode(*it1, e->ipath); + else + e->ipath.erase(); + return true; +} + +bool RclDHistory::enterDocument(const string fn, const string ipath) +{ + LOGDEB(("RclDHistory::enterDocument: [%s] [%s] into %s\n", fn.c_str(), ipath.c_str(), m_data.getFilename().c_str())); - //Encode value part: 2 base64 of fn and ipath separated by a space + // Encode value part: Unix time + base64 of fn + base64 of ipath + // separated by a space. If ipath is not set, there are only 2 parts + char chartime[20]; + time_t now = time(0); + sprintf(chartime, "%ld", (long)now); string bfn, bipath; base64_encode(fn, bfn); base64_encode(ipath, bipath); - string value = bfn + " " + bipath; + string value = string(chartime) + " " + bfn + " " + bipath; - // We trim whitespace from the value (if there is no ipath it now - // ends with a space), else the value later returned by conftree - // will be different because conftree does trim white space, and - // this breaks the comparisons below - trimstring(value); LOGDEB1(("Encoded value [%s] (%d)\n", value.c_str(), value.size())); // Is this doc already in history ? If it is we remove the old entry list names = m_data.getNames(docSubkey); list::const_iterator it; bool changed = false; - for (it = names.begin();it != names.end(); it++) { + for (it = names.begin(); it != names.end(); it++) { string oval; if (!m_data.get(*it, oval, docSubkey)) { LOGDEB(("No data for %s\n", (*it).c_str())); continue; } - LOGDEB1(("Look at %s [%s] (%d)\n", - (*it).c_str(), oval.c_str(), oval.length())); - if (oval == value) { - LOGDEB1(("Erasing old entry\n")); + RclDHistoryEntry entry; + decodeValue(oval, &entry); + + if (entry.fn == fn && entry.ipath == ipath) { + LOGDEB(("Erasing old entry\n")); m_data.erase(*it, docSubkey); changed = true; } } + // Maybe reget list if (changed) names = m_data.getNames(docSubkey); @@ -78,32 +96,24 @@ bool RclQHistory::enterDocument(const string fn, const string ipath) sprintf(nname, "%010u", hi); if (!m_data.set(string(nname), value, docSubkey)) { - LOGERR(("RclQHistory::enterDocument: set failed\n")); + LOGERR(("RclDHistory::enterDocument: set failed\n")); return false; } return true; } -list< pair > RclQHistory::getDocHistory() +list RclDHistory::getDocHistory() { - list< pair > mlist; + list mlist; + RclDHistoryEntry entry; list names = m_data.getNames(docSubkey); - for (list::const_iterator it = names.begin(); it != names.end(); - it++) { + for (list::const_iterator it = names.begin(); + it != names.end(); it++) { string value; if (m_data.get(*it, value, docSubkey)) { - list vall; - stringToStrings(value, vall); - list::const_iterator it1 = vall.begin(); - if (vall.size() < 1) + if (!decodeValue(value, &entry)) continue; - string fn, ipath; - LOGDEB(("RclQHistory::getDocHistory:b64: %s\n", (*it1).c_str())); - base64_decode(*it1++, fn); - LOGDEB(("RclQHistory::getDocHistory:fn: %s\n", fn.c_str())); - if (vall.size() == 2) - base64_decode(*it1, ipath); - mlist.push_front(pair(fn, ipath)); + mlist.push_front(entry); } } return mlist; @@ -122,7 +132,7 @@ using namespace std; int main(int argc, char **argv) { - RclQHistory hist("toto", 5); + RclDHistory hist("toto", 5); DebugLog::getdbl()->setloglevel(DEBDEB1); DebugLog::setfilename("stderr"); diff --git a/src/query/history.h b/src/query/history.h index 4905f66d..01607701 100644 --- a/src/query/history.h +++ b/src/query/history.h @@ -1,6 +1,6 @@ #ifndef _HISTORY_H_INCLUDED_ #define _HISTORY_H_INCLUDED_ -/* @(#$Id: history.h,v 1.1 2005-11-24 18:21:55 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: history.h,v 1.2 2005-11-28 15:31:01 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -8,19 +8,29 @@ #include "conftree.h" +/** Holder for data returned when querying history */ +class RclDHistoryEntry { + public: + RclDHistoryEntry() : unixtime(0) {} + long unixtime; + string fn; + string ipath; +}; + /** - * The query and documents history class. This is based on a ConfTree for no + * The documents history class. This is based on a ConfTree for no * imperative reason */ -class RclQHistory { +class RclDHistory { public: - RclQHistory(const std::string &fn, unsigned int maxsize=1000); + RclDHistory(const std::string &fn, unsigned int maxsize=1000); bool ok() {return m_data.getStatus() == ConfSimple::STATUS_RW;} bool enterDocument(const std::string fn, const std::string ipath); - std::list< std::pair > getDocHistory(); + std::list getDocHistory(); private: + bool decodeValue(const string &value, RclDHistoryEntry *e); unsigned int m_mlen; ConfSimple m_data; };