Cleaned up the dynconf/history code by using a container template

This commit is contained in:
Jean-Francois Dockes 2018-05-31 10:37:34 +02:00
parent 7b5f701b1d
commit 3b6dd445e3
10 changed files with 110 additions and 113 deletions

View File

@ -79,10 +79,12 @@ bool AdvSearchHist::read()
{ {
if (!g_dynconf) if (!g_dynconf)
return false; return false;
list<string> lxml = g_dynconf->getStringList(advSearchHistSk);
// getStringEntries() return the entries in order (lower key
for (list<string>::const_iterator it = lxml.begin(); it != lxml.end(); // first), but we want most recent first, so revert
it++) { vector<string> lxml =
g_dynconf->getStringEntries<vector>(advSearchHistSk);
for (auto it = lxml.rbegin(); it != lxml.rend(); it++) {
std::shared_ptr<SearchData> sd = xmlToSearchData(*it); std::shared_ptr<SearchData> sd = xmlToSearchData(*it);
if (sd) if (sd)
m_entries.push_back(sd); m_entries.push_back(sd);

View File

@ -316,19 +316,17 @@ void rwSettings(bool writing)
// as they are likely to depend on RECOLL_CONFDIR. // as they are likely to depend on RECOLL_CONFDIR.
if (writing) { if (writing) {
g_dynconf->eraseAll(allEdbsSk); g_dynconf->eraseAll(allEdbsSk);
for (list<string>::const_iterator it = prefs.allExtraDbs.begin(); for (const auto& dbdir : prefs.allExtraDbs) {
it != prefs.allExtraDbs.end(); it++) { g_dynconf->enterString(allEdbsSk, dbdir);
g_dynconf->enterString(allEdbsSk, *it);
} }
g_dynconf->eraseAll(actEdbsSk); g_dynconf->eraseAll(actEdbsSk);
for (list<string>::const_iterator it = prefs.activeExtraDbs.begin(); for (const auto& dbdir : prefs.activeExtraDbs) {
it != prefs.activeExtraDbs.end(); it++) { g_dynconf->enterString(actEdbsSk, dbdir);
g_dynconf->enterString(actEdbsSk, *it);
} }
} else { } else {
prefs.allExtraDbs = g_dynconf->getStringList(allEdbsSk); prefs.allExtraDbs = g_dynconf->getStringEntries<vector>(allEdbsSk);
const char *cp; const char *cp;
if ((cp = getenv("RECOLL_EXTRA_DBS")) != 0) { if ((cp = getenv("RECOLL_EXTRA_DBS")) != 0) {
vector<string> dbl; vector<string> dbl;
@ -337,17 +335,18 @@ void rwSettings(bool writing)
dit++) { dit++) {
string dbdir = path_canon(*dit); string dbdir = path_canon(*dit);
path_catslash(dbdir); path_catslash(dbdir);
if (std::find(prefs.allExtraDbs.begin(), if (std::find(prefs.allExtraDbs.begin(),
prefs.allExtraDbs.end(), dbdir) != prefs.allExtraDbs.end(), dbdir) !=
prefs.allExtraDbs.end()) prefs.allExtraDbs.end())
continue; continue;
bool stripped; bool stripped;
if (!Rcl::Db::testDbDir(dbdir, &stripped)) { if (!Rcl::Db::testDbDir(dbdir, &stripped)) {
LOGERR("Not a xapian index: [" << (dbdir) << "]\n" ); LOGERR("Not a xapian index: [" << dbdir << "]\n");
continue; continue;
} }
if (stripped != o_index_stripchars) { if (stripped != o_index_stripchars) {
LOGERR("Incompatible character stripping: [" << (dbdir) << "]\n" ); LOGERR("Incompatible character stripping: [" << dbdir <<
"]\n");
continue; continue;
} }
prefs.allExtraDbs.push_back(dbdir); prefs.allExtraDbs.push_back(dbdir);
@ -355,16 +354,17 @@ void rwSettings(bool writing)
} }
// Get the remembered "active external indexes": // Get the remembered "active external indexes":
prefs.activeExtraDbs = g_dynconf->getStringList(actEdbsSk); prefs.activeExtraDbs = g_dynconf->getStringEntries<vector>(actEdbsSk);
// Clean up the list: remove directories which are not // Clean up the list: remove directories which are not
// actually there: useful for removable volumes. // actually there: useful for removable volumes.
for (list<string>::iterator it = prefs.activeExtraDbs.begin(); for (auto it = prefs.activeExtraDbs.begin();
it != prefs.activeExtraDbs.end();) { it != prefs.activeExtraDbs.end();) {
bool stripped; bool stripped;
if (!Rcl::Db::testDbDir(*it, &stripped) || if (!Rcl::Db::testDbDir(*it, &stripped) ||
stripped != o_index_stripchars) { stripped != o_index_stripchars) {
LOGINFO("Not a Xapian index or char stripping differs: [" << *it << "]\n" ); LOGINFO("Not a Xapian index or char stripping differs: [" <<
*it << "]\n");
it = prefs.activeExtraDbs.erase(it); it = prefs.activeExtraDbs.erase(it);
} else { } else {
it++; it++;
@ -418,14 +418,14 @@ void rwSettings(bool writing)
while (prefs.asearchSubdirHist.size() > 20) while (prefs.asearchSubdirHist.size() > 20)
prefs.asearchSubdirHist.pop_back(); prefs.asearchSubdirHist.pop_back();
g_dynconf->eraseAll(asbdSk); g_dynconf->eraseAll(asbdSk);
for (QStringList::iterator it = prefs.asearchSubdirHist.begin(); for (const auto& qdbd : prefs.asearchSubdirHist) {
it != prefs.asearchSubdirHist.end(); it++) { g_dynconf->enterString(asbdSk, qs2utf8s(qdbd));
g_dynconf->enterString(asbdSk, (const char *)((*it).toUtf8()));
} }
} else { } else {
list<string> tl = g_dynconf->getStringList(asbdSk); vector<string> tl = g_dynconf->getStringEntries<vector>(asbdSk);
for (list<string>::iterator it = tl.begin(); it != tl.end(); it++) for (const auto& dbd: tl) {
prefs.asearchSubdirHist.push_front(QString::fromUtf8(it->c_str())); prefs.asearchSubdirHist.push_back(u8s2qs(dbd.c_str()));
}
} }
if (!writing) if (!writing)
havereadsettings = true; havereadsettings = true;

View File

@ -99,8 +99,8 @@ class PrefsPack {
bool showResultsAsTable; bool showResultsAsTable;
// Extra query indexes. This are stored in the history file, not qt prefs // Extra query indexes. This are stored in the history file, not qt prefs
list<string> allExtraDbs; vector<string> allExtraDbs;
list<string> activeExtraDbs; vector<string> activeExtraDbs;
// Advanced search subdir restriction: we don't activate the last value // Advanced search subdir restriction: we don't activate the last value
// but just remember previously entered values // but just remember previously entered values
QStringList asearchSubdirHist; QStringList asearchSubdirHist;

View File

@ -101,10 +101,9 @@ bool maybeOpenDb(string &reason, bool force, bool *maindberror)
if (force) if (force)
rcldb->close(); rcldb->close();
rcldb->rmQueryDb(""); rcldb->rmQueryDb("");
for (list<string>::const_iterator it = prefs.activeExtraDbs.begin(); for (const auto& dbdir : prefs.activeExtraDbs) {
it != prefs.activeExtraDbs.end(); it++) { LOGDEB("main: adding [" << dbdir << "]\n");
LOGDEB("main: adding [" << *it << "]\n" ); rcldb->addQueryDb(dbdir);
rcldb->addQueryDb(*it);
} }
Rcl::Db::OpenError error; Rcl::Db::OpenError error;
if (!rcldb->isopen() && !rcldb->open(Rcl::Db::DbRO, &error)) { if (!rcldb->isopen() && !rcldb->open(Rcl::Db::DbRO, &error)) {

View File

@ -300,9 +300,8 @@ bool SSearch::startSimpleSearch(const string& u8, int maxexp)
sdata->setMaxExpand(maxexp); sdata->setMaxExpand(maxexp);
} }
for (list<string>::const_iterator it = prefs.activeExtraDbs.begin(); for (const auto& dbdir : prefs.activeExtraDbs) {
it != prefs.activeExtraDbs.end(); it++) { xml << " <EX>" << base64_encode(dbdir) << "</EX>";
xml << " <EX>" << base64_encode(*it) << "</EX>";
} }
xml << "</SD>\n"; xml << "</SD>\n";

View File

@ -231,22 +231,18 @@ void UIPrefsDialog::setFromPrefs()
// Initialize the extra indexes listboxes // Initialize the extra indexes listboxes
idxLV->clear(); idxLV->clear();
for (list<string>::iterator it = prefs.allExtraDbs.begin(); for (const auto& dbdir : prefs.allExtraDbs) {
it != prefs.allExtraDbs.end(); it++) {
QListWidgetItem *item = QListWidgetItem *item =
new QListWidgetItem(QString::fromLocal8Bit(it->c_str()), new QListWidgetItem(QString::fromLocal8Bit(dbdir.c_str()), idxLV);
idxLV);
if (item) if (item)
item->setCheckState(Qt::Unchecked); item->setCheckState(Qt::Unchecked);
} }
for (list<string>::iterator it = prefs.activeExtraDbs.begin(); for (const auto& dbdir : prefs.activeExtraDbs) {
it != prefs.activeExtraDbs.end(); it++) { auto items =
QList<QListWidgetItem *>items = idxLV->findItems (QString::fromLocal8Bit(dbdir.c_str()),
idxLV->findItems (QString::fromLocal8Bit(it->c_str()), Qt::MatchFixedString|Qt::MatchCaseSensitive);
Qt::MatchFixedString|Qt::MatchCaseSensitive); for (auto& entry : items) {
for (QList<QListWidgetItem *>::iterator it = items.begin(); entry->setCheckState(Qt::Checked);
it != items.end(); it++) {
(*it)->setCheckState(Qt::Checked);
} }
} }
idxLV->sortItems(); idxLV->sortItems();

View File

@ -14,15 +14,15 @@
* Free Software Foundation, Inc., * Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "docseqhist.h"
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <cmath> #include <cmath>
#include <list> using std::vector;
using std::list;
#include "docseqhist.h"
#include "rcldb.h" #include "rcldb.h"
#include "fileudi.h" #include "fileudi.h"
#include "base64.h" #include "base64.h"
@ -77,7 +77,7 @@ bool RclDHistoryEntry::decode(const string &value)
// Old style entry found, make an udi, using the fs udi maker // Old style entry found, make an udi, using the fs udi maker
make_udi(fn, ipath, udi); make_udi(fn, ipath, udi);
} }
LOGDEB1("RclDHistoryEntry::decode: udi [" << (udi) << "]\n" ); LOGDEB1("RclDHistoryEntry::decode: udi [" << udi << "]\n");
return true; return true;
} }
@ -89,54 +89,46 @@ bool RclDHistoryEntry::equal(const DynConfEntry& other)
bool historyEnterDoc(RclDynConf *dncf, const string& udi) bool historyEnterDoc(RclDynConf *dncf, const string& udi)
{ {
LOGDEB1("historyEnterDoc: [" << (udi) << "] into " << (dncf->getFilename()) << "\n" ); LOGDEB1("historyEnterDoc: [" << udi << "] into " << dncf->getFilename() <<
"\n");
RclDHistoryEntry ne(time(0), udi); RclDHistoryEntry ne(time(0), udi);
RclDHistoryEntry scratch; RclDHistoryEntry scratch;
return dncf->insertNew(docHistSubKey, ne, scratch, 200); return dncf->insertNew(docHistSubKey, ne, scratch, 200);
} }
list<RclDHistoryEntry> getDocHistory(RclDynConf* dncf) vector<RclDHistoryEntry> getDocHistory(RclDynConf* dncf)
{ {
return dncf->getList<RclDHistoryEntry>(docHistSubKey); return dncf->getEntries<std::vector, RclDHistoryEntry>(docHistSubKey);
} }
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh) bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
{ {
// Retrieve history list // Retrieve history list
if (!m_hist) if (!m_hist)
return false; return false;
if (m_hlist.empty()) if (m_history.empty())
m_hlist = getDocHistory(m_hist); m_history = getDocHistory(m_hist);
if (num < 0 || num >= (int)m_hlist.size()) if (num < 0 || num >= (int)m_history.size())
return false; return false;
int skip; // We get the history oldest first, but our users expect newest first
if (m_prevnum >= 0 && num >= m_prevnum) { RclDHistoryEntry& hentry = m_history[m_history.size() - 1 - num];
skip = num - m_prevnum;
} else {
skip = num;
m_it = m_hlist.begin();
m_prevtime = -1;
}
m_prevnum = num;
while (skip--)
m_it++;
if (sh) { if (sh) {
if (m_prevtime < 0 || if (m_prevtime < 0 ||
abs (float(m_prevtime) - float(m_it->unixtime)) > 86400) { abs (float(m_prevtime) - float(hentry.unixtime)) > 86400) {
m_prevtime = m_it->unixtime; m_prevtime = hentry.unixtime;
time_t t = (time_t)(m_it->unixtime); time_t t = (time_t)(hentry.unixtime);
*sh = string(ctime(&t)); *sh = string(ctime(&t));
// Get rid of the final \n in ctime // Get rid of the final \n in ctime
sh->erase(sh->length()-1); sh->erase(sh->length()-1);
} else } else {
sh->erase(); sh->erase();
}
} }
// For now history does not store an index id. Use empty doc as ref. // For now history does not store an index id. Use empty doc as ref.
Rcl::Doc idxdoc; Rcl::Doc idxdoc;
bool ret = m_db->getDoc(m_it->udi, idxdoc, doc); bool ret = m_db->getDoc(hentry.udi, idxdoc, doc);
if (!ret || doc.pc == -1) { if (!ret || doc.pc == -1) {
doc.url = "UNKNOWN"; doc.url = "UNKNOWN";
doc.ipath = ""; doc.ipath = "";
@ -156,8 +148,8 @@ Rcl::Db *DocSequenceHistory::getDb()
int DocSequenceHistory::getResCnt() int DocSequenceHistory::getResCnt()
{ {
if (m_hlist.empty()) if (m_history.empty())
m_hlist = getDocHistory(m_hist); m_history = getDocHistory(m_hist);
return int(m_hlist.size()); return int(m_history.size());
} }

View File

@ -18,6 +18,8 @@
#define _DOCSEQHIST_H_INCLUDED_ #define _DOCSEQHIST_H_INCLUDED_
#include <time.h> #include <time.h>
#include <vector>
#include "docseq.h" #include "docseq.h"
#include "dynconf.h" #include "dynconf.h"
@ -45,7 +47,7 @@ class RclDHistoryEntry : public DynConfEntry {
class DocSequenceHistory : public DocSequence { class DocSequenceHistory : public DocSequence {
public: public:
DocSequenceHistory(Rcl::Db *d, RclDynConf *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) {} : DocSequence(t), m_db(d), m_hist(h) {}
virtual ~DocSequenceHistory() {} virtual ~DocSequenceHistory() {}
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0); virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0);
@ -57,11 +59,9 @@ protected:
private: private:
Rcl::Db *m_db; Rcl::Db *m_db;
RclDynConf *m_hist; RclDynConf *m_hist;
int m_prevnum; time_t m_prevtime{-1};
time_t m_prevtime;
std::string m_description; // This is just an nls translated 'doc history' std::string m_description; // This is just an nls translated 'doc history'
std::list<RclDHistoryEntry> m_hlist; std::vector<RclDHistoryEntry> m_history;
std::list<RclDHistoryEntry>::const_iterator m_it;
}; };
extern bool historyEnterDoc(RclDynConf *dncf, const string& udi); extern bool historyEnterDoc(RclDynConf *dncf, const string& udi);

View File

@ -60,13 +60,13 @@ bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
for (it = names.begin(); it != names.end(); it++) { for (it = names.begin(); it != names.end(); it++) {
string oval; string oval;
if (!m_data.get(*it, oval, sk)) { if (!m_data.get(*it, oval, sk)) {
LOGDEB("No data for " << ((*it)) << "\n" ); LOGDEB("No data for " << *it << "\n");
continue; continue;
} }
s.decode(oval); s.decode(oval);
if (s.equal(n)) { if (s.equal(n)) {
LOGDEB("Erasing old entry\n" ); LOGDEB("Erasing old entry\n");
m_data.erase(*it, sk); m_data.erase(*it, sk);
changed = true; changed = true;
} }
@ -96,9 +96,9 @@ bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
string value; string value;
n.encode(value); n.encode(value);
LOGDEB1("Encoded value [" << (value) << "] (" << (value.size()) << ")\n" ); LOGDEB1("Encoded value [" << value << "] (" << value.size() << ")\n");
if (!m_data.set(string(nname), value, sk)) { if (!m_data.set(string(nname), value, sk)) {
LOGERR("RclDHistory::insertNew: set failed\n" ); LOGERR("RclDHistory::insertNew: set failed\n");
return false; return false;
} }
return true; return true;
@ -110,15 +110,12 @@ bool RclDynConf::eraseAll(const string &sk)
LOGDEB("RclDynConf::eraseAll: not writable\n"); LOGDEB("RclDynConf::eraseAll: not writable\n");
return false; return false;
} }
vector<string> names = m_data.getNames(sk); for (const auto& nm : m_data.getNames(sk)) {
vector<string>::const_iterator it; m_data.erase(nm, sk);
for (it = names.begin(); it != names.end(); it++) {
m_data.erase(*it, sk);
} }
return true; return true;
} }
// Specialization for plain strings /////////////////////////////////// // Specialization for plain strings ///////////////////////////////////
bool RclDynConf::enterString(const string sk, const string value, int maxlen) bool RclDynConf::enterString(const string sk, const string value, int maxlen)
@ -132,16 +129,6 @@ bool RclDynConf::enterString(const string sk, const string value, int maxlen)
return insertNew(sk, ne, scratch, maxlen); return insertNew(sk, ne, scratch, maxlen);
} }
list<string> RclDynConf::getStringList(const string sk)
{
list<RclSListEntry> el = getList<RclSListEntry>(sk);
list<string> sl;
for (list<RclSListEntry>::const_iterator it = el.begin();
it != el.end(); it++)
sl.push_back(it->value);
return sl;
}
#else #else
#include <string> #include <string>

View File

@ -41,6 +41,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include <vector>
#include "conftree.h" #include "conftree.h"
#include "base64.h" #include "base64.h"
@ -110,34 +111,55 @@ class RclDynConf {
*/ */
bool insertNew(const std::string& sk, DynConfEntry &n, DynConfEntry &s, bool insertNew(const std::string& sk, DynConfEntry &n, DynConfEntry &s,
int maxlen = -1); int maxlen = -1);
template<typename Tp> std::list<Tp> getList(const std::string& sk);
// Specialized methods for simple string lists, designated by the // General method to extract entries. Maybe there would be a way to
// subkey value // express the fact that Type should derive from DynConfEntry, not
// too sure how. We are just certain (further down) that it does
// have a decode() method. It's up to the user that they call
// insertNew() and getEntries() for the same type...
template <template <class, class> class Container, class Type>
Container<Type, std::allocator<Type>> getEntries(const std::string& sk);
// Specialized methods for simple strings
bool enterString(const std::string sk, const std::string value, bool enterString(const std::string sk, const std::string value,
int maxlen = -1); int maxlen = -1);
std::list<std::string> getStringList(const std::string sk); template <template <class, class> class Container>
Container<std::string, std::allocator<std::string>>
getStringEntries(const std::string& sk);
private: private:
unsigned int m_mlen; unsigned int m_mlen;
ConfSimple m_data; ConfSimple m_data;
}; };
template<typename Tp> std::list<Tp> RclDynConf::getList(const std::string &sk) template <template <class, class> class Container, class Type>
Container<Type, std::allocator<Type>>
RclDynConf::getEntries(const std::string& sk)
{ {
std::list<Tp> mlist; Container<Type, std::allocator<Type>> out;
Tp entry; Type entry;
std::vector<std::string> names = m_data.getNames(sk); std::vector<std::string> names = m_data.getNames(sk);
for (std::vector<std::string>::const_iterator it = names.begin(); for (const auto& name : names) {
it != names.end(); it++) {
std::string value; std::string value;
if (m_data.get(*it, value, sk)) { if (m_data.get(name, value, sk)) {
if (!entry.decode(value)) if (!entry.decode(value))
continue; continue;
mlist.push_front(entry); out.push_back(entry);
} }
} }
return mlist; return std::move(out);
}
template <template <class, class> class Container>
Container<std::string, std::allocator<std::string>>
RclDynConf::getStringEntries(const std::string& sk)
{
std::vector<RclSListEntry> el = getEntries<std::vector, RclSListEntry>(sk);
Container<std::string, std::allocator<std::string>> sl;
for (const auto& entry : el) {
sl.push_back(entry.value);
}
return std::move(sl);
} }
// Defined subkeys. Values in dynconf.cpp // Defined subkeys. Values in dynconf.cpp