implemented advanced search history feature
This commit is contained in:
parent
9ccb862666
commit
816980a1c4
@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
kchmviewer --url $2 $1
|
|
||||||
@ -146,6 +146,7 @@ filters/rcldia
|
|||||||
filters/rcldjvu
|
filters/rcldjvu
|
||||||
filters/rcldoc
|
filters/rcldoc
|
||||||
filters/rcldvi
|
filters/rcldvi
|
||||||
|
filters/rclepub
|
||||||
filters/rclexecm.py
|
filters/rclexecm.py
|
||||||
filters/rclfb2
|
filters/rclfb2
|
||||||
filters/rclgaim
|
filters/rclgaim
|
||||||
@ -292,6 +293,8 @@ qtgui/
|
|||||||
qtgui/advsearch.ui
|
qtgui/advsearch.ui
|
||||||
qtgui/advsearch_w.cpp
|
qtgui/advsearch_w.cpp
|
||||||
qtgui/advsearch_w.h
|
qtgui/advsearch_w.h
|
||||||
|
qtgui/advshist.cpp
|
||||||
|
qtgui/advshist.h
|
||||||
qtgui/confgui/
|
qtgui/confgui/
|
||||||
qtgui/confgui/confgui.cpp
|
qtgui/confgui/confgui.cpp
|
||||||
qtgui/confgui/confgui.h
|
qtgui/confgui/confgui.h
|
||||||
|
|||||||
@ -27,18 +27,12 @@
|
|||||||
#include <qtooltip.h>
|
#include <qtooltip.h>
|
||||||
#include <qwhatsthis.h>
|
#include <qwhatsthis.h>
|
||||||
#include <qmessagebox.h>
|
#include <qmessagebox.h>
|
||||||
|
#include <QShortcut>
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
using namespace std;
|
||||||
#ifndef NO_NAMESPACES
|
|
||||||
using std::list;
|
|
||||||
using std::string;
|
|
||||||
using std::map;
|
|
||||||
using std::unique;
|
|
||||||
#endif /* NO_NAMESPACES */
|
|
||||||
|
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
@ -52,7 +46,6 @@ static const unsigned int iclausescnt = sizeof(initclausetypes) / sizeof(int);
|
|||||||
static map<QString,QString> cat_translations;
|
static map<QString,QString> cat_translations;
|
||||||
static map<QString,QString> cat_rtranslations;
|
static map<QString,QString> cat_rtranslations;
|
||||||
|
|
||||||
|
|
||||||
void AdvSearch::init()
|
void AdvSearch::init()
|
||||||
{
|
{
|
||||||
(void)new HelpClient(this);
|
(void)new HelpClient(this);
|
||||||
@ -83,6 +76,9 @@ void AdvSearch::init()
|
|||||||
connect(addClausePB, SIGNAL(clicked()), this, SLOT(addClause()));
|
connect(addClausePB, SIGNAL(clicked()), this, SLOT(addClause()));
|
||||||
connect(delClausePB, SIGNAL(clicked()), this, SLOT(delClause()));
|
connect(delClausePB, SIGNAL(clicked()), this, SLOT(delClause()));
|
||||||
|
|
||||||
|
new QShortcut(QKeySequence(Qt::Key_Up), this, SLOT(slotHistoryNext()));;
|
||||||
|
new QShortcut(QKeySequence(Qt::Key_Down), this, SLOT(slotHistoryPrev()));
|
||||||
|
|
||||||
conjunctCMB->insertItem(1, tr("All clauses"));
|
conjunctCMB->insertItem(1, tr("All clauses"));
|
||||||
conjunctCMB->insertItem(2, tr("Any clause"));
|
conjunctCMB->insertItem(2, tr("Any clause"));
|
||||||
|
|
||||||
@ -92,7 +88,7 @@ void AdvSearch::init()
|
|||||||
}
|
}
|
||||||
// Tune initial state according to last saved
|
// Tune initial state according to last saved
|
||||||
{
|
{
|
||||||
std::list<SearchClauseW *>::iterator cit = m_clauseWins.begin();
|
vector<SearchClauseW *>::iterator cit = m_clauseWins.begin();
|
||||||
for (vector<int>::iterator it = prefs.advSearchClauses.begin();
|
for (vector<int>::iterator it = prefs.advSearchClauses.begin();
|
||||||
it != prefs.advSearchClauses.end(); it++) {
|
it != prefs.advSearchClauses.end(); it++) {
|
||||||
if (cit != m_clauseWins.end()) {
|
if (cit != m_clauseWins.end()) {
|
||||||
@ -109,6 +105,8 @@ void AdvSearch::init()
|
|||||||
int minyear, maxyear;
|
int minyear, maxyear;
|
||||||
if (rcldb) {
|
if (rcldb) {
|
||||||
rcldb->maxYearSpan(&minyear, &maxyear);
|
rcldb->maxYearSpan(&minyear, &maxyear);
|
||||||
|
minDateDTE->setDisplayFormat("dd.MM.yyyy");
|
||||||
|
maxDateDTE->setDisplayFormat("dd.MM.yyyy");
|
||||||
minDateDTE->setDate(QDate(minyear, 1, 1));
|
minDateDTE->setDate(QDate(minyear, 1, 1));
|
||||||
maxDateDTE->setDate(QDate(maxyear, 12, 31));
|
maxDateDTE->setDate(QDate(maxyear, 12, 31));
|
||||||
}
|
}
|
||||||
@ -158,7 +156,7 @@ void AdvSearch::saveCnf()
|
|||||||
{
|
{
|
||||||
// Save my state
|
// Save my state
|
||||||
prefs.advSearchClauses.clear();
|
prefs.advSearchClauses.clear();
|
||||||
for (std::list<SearchClauseW *>::iterator cit = m_clauseWins.begin();
|
for (vector<SearchClauseW *>::iterator cit = m_clauseWins.begin();
|
||||||
cit != m_clauseWins.end(); cit++) {
|
cit != m_clauseWins.end(); cit++) {
|
||||||
prefs.advSearchClauses.push_back((*cit)->sTpCMB->currentIndex());
|
prefs.advSearchClauses.push_back((*cit)->sTpCMB->currentIndex());
|
||||||
}
|
}
|
||||||
@ -170,12 +168,6 @@ bool AdvSearch::close()
|
|||||||
return QWidget::close();
|
return QWidget::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSearch::delAFiltypPB_clicked()
|
|
||||||
{
|
|
||||||
yesFiltypsLB->selectAll();
|
|
||||||
delFiltypPB_clicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSearch::addClause()
|
void AdvSearch::addClause()
|
||||||
{
|
{
|
||||||
addClause(0);
|
addClause(0);
|
||||||
@ -208,6 +200,12 @@ void AdvSearch::delClause()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSearch::delAFiltypPB_clicked()
|
||||||
|
{
|
||||||
|
yesFiltypsLB->selectAll();
|
||||||
|
delFiltypPB_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
// Move selected file types from the searched to the ignored box
|
// Move selected file types from the searched to the ignored box
|
||||||
void AdvSearch::delFiltypPB_clicked()
|
void AdvSearch::delFiltypPB_clicked()
|
||||||
{
|
{
|
||||||
@ -329,6 +327,12 @@ void AdvSearch::saveFileTypes()
|
|||||||
rwSettings(true);
|
rwSettings(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSearch::browsePB_clicked()
|
||||||
|
{
|
||||||
|
QString dir = myGetFileName(true);
|
||||||
|
subtreeCMB->setEditText(dir);
|
||||||
|
}
|
||||||
|
|
||||||
size_t AdvSearch::stringToSize(QString qsize)
|
size_t AdvSearch::stringToSize(QString qsize)
|
||||||
{
|
{
|
||||||
size_t size = size_t(-1);
|
size_t size = size_t(-1);
|
||||||
@ -361,7 +365,7 @@ void AdvSearch::runSearch()
|
|||||||
SCLT_AND : SCLT_OR, stemLang));
|
SCLT_AND : SCLT_OR, stemLang));
|
||||||
bool hasclause = false;
|
bool hasclause = false;
|
||||||
|
|
||||||
for (list<SearchClauseW*>::iterator it = m_clauseWins.begin();
|
for (vector<SearchClauseW*>::iterator it = m_clauseWins.begin();
|
||||||
it != m_clauseWins.end(); it++) {
|
it != m_clauseWins.end(); it++) {
|
||||||
SearchDataClause *cl;
|
SearchDataClause *cl;
|
||||||
if ((cl = (*it)->getClause())) {
|
if ((cl = (*it)->getClause())) {
|
||||||
@ -441,12 +445,121 @@ void AdvSearch::runSearch()
|
|||||||
prefs.asearchSubdirHist.push_back(subtreeCMB->itemText(index));
|
prefs.asearchSubdirHist.push_back(subtreeCMB->itemText(index));
|
||||||
}
|
}
|
||||||
saveCnf();
|
saveCnf();
|
||||||
|
g_advshistory && g_advshistory->push(sdata);
|
||||||
emit startSearch(sdata);
|
emit startSearch(sdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSearch::browsePB_clicked()
|
|
||||||
|
// Set up fields from existing search data, which must be compatible
|
||||||
|
// with what we can do...
|
||||||
|
void AdvSearch::fromSearch(RefCntr<SearchData> sdata)
|
||||||
{
|
{
|
||||||
QString dir = myGetFileName(true);
|
if (sdata->m_tp == SCLT_OR)
|
||||||
subtreeCMB->setEditText(dir);
|
conjunctCMB->setCurrentIndex(1);
|
||||||
|
else
|
||||||
|
conjunctCMB->setCurrentIndex(0);
|
||||||
|
|
||||||
|
while (sdata->m_query.size() > m_clauseWins.size()) {
|
||||||
|
addClause();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < sdata->m_query.size(); i++) {
|
||||||
|
// Set fields from clause
|
||||||
|
if (sdata->m_query[i]->getTp() == SCLT_SUB) {
|
||||||
|
LOGERR(("AdvSearch::fromSearch: SUB clause found !\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SearchDataClauseSimple *cs =
|
||||||
|
dynamic_cast<SearchDataClauseSimple*>(sdata->m_query[i]);
|
||||||
|
m_clauseWins[i]->setFromClause(cs);
|
||||||
|
}
|
||||||
|
for (unsigned int i = sdata->m_query.size(); i < m_clauseWins.size(); i++) {
|
||||||
|
m_clauseWins[i]->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
restrictCtCB->setChecked(0);
|
||||||
|
if (!sdata->m_filetypes.empty()) {
|
||||||
|
restrictFtCB_toggled(1);
|
||||||
|
delAFiltypPB_clicked();
|
||||||
|
for (unsigned int i = 0; i < sdata->m_filetypes.size(); i++) {
|
||||||
|
QString ft = QString::fromUtf8(sdata->m_filetypes[i].c_str());
|
||||||
|
QList<QListWidgetItem *> lst =
|
||||||
|
noFiltypsLB->findItems(ft, Qt::MatchExactly);
|
||||||
|
if (!lst.isEmpty()) {
|
||||||
|
int row = noFiltypsLB->row(lst[0]);
|
||||||
|
QListWidgetItem *item = noFiltypsLB->takeItem(row);
|
||||||
|
yesFiltypsLB->insertItem(0, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yesFiltypsLB->sortItems();
|
||||||
|
} else {
|
||||||
|
addAFiltypPB_clicked();
|
||||||
|
restrictFtCB_toggled(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdata->m_haveDates) {
|
||||||
|
filterDatesCB->setChecked(1);
|
||||||
|
DateInterval &di(sdata->m_dates);
|
||||||
|
QDate mindate(di.y1, di.m1, di.d1);
|
||||||
|
QDate maxdate(di.y2, di.m2, di.d2);
|
||||||
|
minDateDTE->setDate(mindate);
|
||||||
|
maxDateDTE->setDate(maxdate);
|
||||||
|
} else {
|
||||||
|
filterDatesCB->setChecked(0);
|
||||||
|
QDate date;
|
||||||
|
minDateDTE->setDate(date);
|
||||||
|
maxDateDTE->setDate(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdata->m_maxSize != (size_t)-1 || sdata->m_minSize != (size_t)-1) {
|
||||||
|
filterSizesCB->setChecked(1);
|
||||||
|
QString sz;
|
||||||
|
if (sdata->m_minSize != (size_t)-1) {
|
||||||
|
sz.setNum(sdata->m_minSize);
|
||||||
|
minSizeLE->setText(sz);
|
||||||
|
} else {
|
||||||
|
minSizeLE->setText("");
|
||||||
|
}
|
||||||
|
if (sdata->m_maxSize != (size_t)-1) {
|
||||||
|
sz.setNum(sdata->m_maxSize);
|
||||||
|
maxSizeLE->setText(sz);
|
||||||
|
} else {
|
||||||
|
maxSizeLE->setText("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filterSizesCB->setChecked(0);
|
||||||
|
minSizeLE->setText("");
|
||||||
|
maxSizeLE->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sdata->m_dirspecs.empty()) {
|
||||||
|
// Can only use one entry
|
||||||
|
QString qdir = QString::fromLocal8Bit(sdata->m_dirspecs[0].dir.c_str());
|
||||||
|
subtreeCMB->setEditText(qdir);
|
||||||
|
direxclCB->setChecked(sdata->m_dirspecs[0].exclude);
|
||||||
|
} else {
|
||||||
|
subtreeCMB->setEditText("");
|
||||||
|
direxclCB->setChecked(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSearch::slotHistoryNext()
|
||||||
|
{
|
||||||
|
if (g_advshistory == 0)
|
||||||
|
return;
|
||||||
|
RefCntr<Rcl::SearchData> sd = g_advshistory->getnewer();
|
||||||
|
if (sd.isNull())
|
||||||
|
return;
|
||||||
|
fromSearch(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSearch::slotHistoryPrev()
|
||||||
|
{
|
||||||
|
if (g_advshistory == 0)
|
||||||
|
return;
|
||||||
|
RefCntr<Rcl::SearchData> sd = g_advshistory->getolder();
|
||||||
|
if (sd.isNull())
|
||||||
|
return;
|
||||||
|
fromSearch(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef _ADVSEARCH_W_H_INCLUDED_
|
#ifndef _ADVSEARCH_W_H_INCLUDED_
|
||||||
#define _ADVSEARCH_W_H_INCLUDED_
|
#define _ADVSEARCH_W_H_INCLUDED_
|
||||||
#include <list>
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qdialog.h>
|
#include <qdialog.h>
|
||||||
|
|
||||||
@ -24,6 +26,7 @@
|
|||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
#include "refcntr.h"
|
#include "refcntr.h"
|
||||||
#include "searchdata.h"
|
#include "searchdata.h"
|
||||||
|
#include "advshist.h"
|
||||||
|
|
||||||
class QDialog;
|
class QDialog;
|
||||||
|
|
||||||
@ -53,19 +56,22 @@ public slots:
|
|||||||
virtual void restrictFtCB_toggled(bool);
|
virtual void restrictFtCB_toggled(bool);
|
||||||
virtual void restrictCtCB_toggled(bool);
|
virtual void restrictCtCB_toggled(bool);
|
||||||
virtual void runSearch();
|
virtual void runSearch();
|
||||||
|
virtual void fromSearch(RefCntr<Rcl::SearchData> sdata);
|
||||||
virtual void browsePB_clicked();
|
virtual void browsePB_clicked();
|
||||||
virtual void saveFileTypes();
|
virtual void saveFileTypes();
|
||||||
virtual void delClause();
|
virtual void delClause();
|
||||||
virtual void addClause();
|
virtual void addClause();
|
||||||
virtual void addClause(int);
|
virtual void addClause(int);
|
||||||
virtual bool close();
|
virtual bool close();
|
||||||
|
virtual void slotHistoryNext();
|
||||||
|
virtual void slotHistoryPrev();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void startSearch(RefCntr<Rcl::SearchData>);
|
void startSearch(RefCntr<Rcl::SearchData>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void init();
|
virtual void init();
|
||||||
std::list<SearchClauseW *> m_clauseWins;
|
std::vector<SearchClauseW *> m_clauseWins;
|
||||||
QStringList m_ignTypes;
|
QStringList m_ignTypes;
|
||||||
bool m_ignByCats;
|
bool m_ignByCats;
|
||||||
void saveCnf();
|
void saveCnf();
|
||||||
|
|||||||
253
src/qtgui/advshist.cpp
Normal file
253
src/qtgui/advshist.cpp
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/* Copyright (C) 2005 J.F.Dockes
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
#include "advshist.h"
|
||||||
|
#include "guiutils.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
|
||||||
|
#include <QtXml/QXmlDefaultHandler>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Rcl;
|
||||||
|
|
||||||
|
class SDHXMLHandler : public QXmlDefaultHandler {
|
||||||
|
public:
|
||||||
|
SDHXMLHandler()
|
||||||
|
: slack(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool startElement(const QString & /* namespaceURI */,
|
||||||
|
const QString & /* localName */,
|
||||||
|
const QString &qName,
|
||||||
|
const QXmlAttributes &attributes);
|
||||||
|
bool endElement(const QString & /* namespaceURI */,
|
||||||
|
const QString & /* localName */,
|
||||||
|
const QString &qName);
|
||||||
|
bool characters(const QString &str)
|
||||||
|
{
|
||||||
|
currentText += str;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The object we set up
|
||||||
|
RefCntr<SearchData> sd;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resetTemps()
|
||||||
|
{
|
||||||
|
currentText = whatclause = "";
|
||||||
|
text.clear();
|
||||||
|
field.clear();
|
||||||
|
slack = 0;
|
||||||
|
d = m = y = di.d1 = di.m1 = di.y1 = di.d2 = di.m2 = di.y2 = 0;
|
||||||
|
hasdates = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary data while parsing.
|
||||||
|
QString currentText;
|
||||||
|
QString whatclause;
|
||||||
|
string field, text;
|
||||||
|
int slack;
|
||||||
|
int d, m, y;
|
||||||
|
DateInterval di;
|
||||||
|
bool hasdates;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool SDHXMLHandler::startElement(const QString & /* namespaceURI */,
|
||||||
|
const QString & /* localName */,
|
||||||
|
const QString &qName,
|
||||||
|
const QXmlAttributes &)
|
||||||
|
{
|
||||||
|
LOGDEB2(("SDHXMLHandler::startElement: name [%s]\n",
|
||||||
|
(const char *)qName.toAscii()));
|
||||||
|
if (qName == "SD") {
|
||||||
|
resetTemps();
|
||||||
|
// A new search descriptor. Allocate data structure
|
||||||
|
sd = RefCntr<SearchData>(new SearchData);
|
||||||
|
if (sd.isNull()) {
|
||||||
|
LOGERR(("SDHXMLHandler::startElement: out of memory\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDHXMLHandler::endElement(const QString & /* namespaceURI */,
|
||||||
|
const QString & /* localName */,
|
||||||
|
const QString &qName)
|
||||||
|
{
|
||||||
|
LOGDEB2(("SDHXMLHandler::endElement: name [%s]\n",
|
||||||
|
(const char *)qName.toAscii()));
|
||||||
|
|
||||||
|
if (qName == "CLT") {
|
||||||
|
if (currentText == "OR") {
|
||||||
|
sd->setTp(SCLT_OR);
|
||||||
|
}
|
||||||
|
} else if (qName == "CT") {
|
||||||
|
whatclause = currentText.trimmed();
|
||||||
|
} else if (qName == "F") {
|
||||||
|
field = base64_decode(qs2utf8s(currentText.trimmed()));
|
||||||
|
} else if (qName == "T") {
|
||||||
|
text = base64_decode(qs2utf8s(currentText.trimmed()));
|
||||||
|
} else if (qName == "S") {
|
||||||
|
slack = atoi((const char *)currentText.toAscii());
|
||||||
|
} else if (qName == "C") {
|
||||||
|
SearchDataClauseSimple *c;
|
||||||
|
if (whatclause == "AND" || whatclause.isEmpty()) {
|
||||||
|
c = new SearchDataClauseSimple(SCLT_AND, text, field);
|
||||||
|
} else if (whatclause == "OR") {
|
||||||
|
c = new SearchDataClauseSimple(SCLT_OR, text, field);
|
||||||
|
} else if (whatclause == "EX") {
|
||||||
|
c = new SearchDataClauseSimple(SCLT_EXCL, text, field);
|
||||||
|
} else if (whatclause == "FN") {
|
||||||
|
c = new SearchDataClauseFilename(text);
|
||||||
|
} else if (whatclause == "PH") {
|
||||||
|
c = new SearchDataClauseDist(SCLT_PHRASE, text, slack, field);
|
||||||
|
} else if (whatclause == "NE") {
|
||||||
|
c = new SearchDataClauseDist(SCLT_NEAR, text, slack, field);
|
||||||
|
} else {
|
||||||
|
LOGERR(("Bad clause type [%s]\n", qs2utf8s(whatclause).c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sd->addClause(c);
|
||||||
|
whatclause = "";
|
||||||
|
text.clear();
|
||||||
|
field.clear();
|
||||||
|
slack = 0;
|
||||||
|
} else if (qName == "D") {
|
||||||
|
d = atoi((const char *)currentText.toAscii());
|
||||||
|
} else if (qName == "M") {
|
||||||
|
m = atoi((const char *)currentText.toAscii());
|
||||||
|
} else if (qName == "Y") {
|
||||||
|
y = atoi((const char *)currentText.toAscii());
|
||||||
|
} else if (qName == "DMI") {
|
||||||
|
di.d1 = d;
|
||||||
|
di.m1 = m;
|
||||||
|
di.y1 = y;
|
||||||
|
hasdates = true;
|
||||||
|
} else if (qName == "DMA") {
|
||||||
|
di.d2 = d;
|
||||||
|
di.m2 = m;
|
||||||
|
di.y2 = y;
|
||||||
|
hasdates = true;
|
||||||
|
} else if (qName == "MIS") {
|
||||||
|
sd->setMinSize(atoll((const char *)currentText.toAscii()));
|
||||||
|
} else if (qName == "MAS") {
|
||||||
|
sd->setMaxSize(atoll((const char *)currentText.toAscii()));
|
||||||
|
} else if (qName == "ST") {
|
||||||
|
string types = (const char *)currentText.toAscii();
|
||||||
|
vector<string> vt;
|
||||||
|
stringToTokens(types, vt);
|
||||||
|
for (unsigned int i = 0; i < vt.size(); i++)
|
||||||
|
sd->addFiletype(vt[i]);
|
||||||
|
} else if (qName == "IT") {
|
||||||
|
string types = (const char *)currentText.toAscii();
|
||||||
|
vector<string> vt;
|
||||||
|
stringToTokens(types, vt);
|
||||||
|
for (unsigned int i = 0; i < vt.size(); i++)
|
||||||
|
sd->remFiletype(vt[i]);
|
||||||
|
} else if (qName == "YD") {
|
||||||
|
string d;
|
||||||
|
base64_decode((const char*)currentText.trimmed().toAscii(), d);
|
||||||
|
sd->addDirSpec(d);
|
||||||
|
} else if (qName == "ND") {
|
||||||
|
string d;
|
||||||
|
base64_decode((const char*)currentText.trimmed().toAscii(), d);
|
||||||
|
sd->addDirSpec(d, true);
|
||||||
|
} else if (qName == "SD") {
|
||||||
|
// Closing current search descriptor. Finishing touches...
|
||||||
|
if (hasdates)
|
||||||
|
sd->setDateSpan(&di);
|
||||||
|
resetTemps();
|
||||||
|
}
|
||||||
|
currentText.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AdvSearchHist::AdvSearchHist()
|
||||||
|
{
|
||||||
|
read();
|
||||||
|
m_current = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvSearchHist::~AdvSearchHist()
|
||||||
|
{
|
||||||
|
for (vector<RefCntr<SearchData> >::iterator it = m_entries.begin();
|
||||||
|
it != m_entries.end(); it++) {
|
||||||
|
it->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCntr<Rcl::SearchData> AdvSearchHist::getolder()
|
||||||
|
{
|
||||||
|
m_current++;
|
||||||
|
if (m_current >= int(m_entries.size())) {
|
||||||
|
m_current--;
|
||||||
|
return RefCntr<Rcl::SearchData>();
|
||||||
|
}
|
||||||
|
return m_entries[m_current];
|
||||||
|
}
|
||||||
|
|
||||||
|
RefCntr<Rcl::SearchData> AdvSearchHist::getnewer()
|
||||||
|
{
|
||||||
|
if (m_current == -1 || m_current == 0 || m_entries.empty())
|
||||||
|
return RefCntr<Rcl::SearchData>();
|
||||||
|
return m_entries[--m_current];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdvSearchHist::push(RefCntr<SearchData> sd)
|
||||||
|
{
|
||||||
|
m_entries.insert(m_entries.begin(), sd);
|
||||||
|
if (m_current != -1)
|
||||||
|
m_current++;
|
||||||
|
|
||||||
|
string xml = sd->asXML();
|
||||||
|
g_dynconf->enterString(advSearchHistSk, xml, 100);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdvSearchHist::read()
|
||||||
|
{
|
||||||
|
if (!g_dynconf)
|
||||||
|
return false;
|
||||||
|
list<string> lxml = g_dynconf->getStringList(advSearchHistSk);
|
||||||
|
|
||||||
|
for (list<string>::const_iterator it = lxml.begin(); it != lxml.end();
|
||||||
|
it++) {
|
||||||
|
SDHXMLHandler handler;
|
||||||
|
QXmlSimpleReader reader;
|
||||||
|
reader.setContentHandler(&handler);
|
||||||
|
reader.setErrorHandler(&handler);
|
||||||
|
QXmlInputSource xmlInputSource;
|
||||||
|
xmlInputSource.setData(QString::fromUtf8(it->c_str()));
|
||||||
|
if (!reader.parse(xmlInputSource)) {
|
||||||
|
LOGERR(("AdvSearchHist::read: parse failed for [%s]\n",
|
||||||
|
it->c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_entries.push_back(handler.sd);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSearchHist::clear()
|
||||||
|
{
|
||||||
|
g_dynconf->eraseAll(advSearchHistSk);
|
||||||
|
}
|
||||||
43
src/qtgui/advshist.h
Normal file
43
src/qtgui/advshist.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* Copyright (C) 2005 J.F.Dockes
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _ADVSHIST_H_INCLUDED_
|
||||||
|
#define _ADVSHIST_H_INCLUDED_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "recoll.h"
|
||||||
|
#include "refcntr.h"
|
||||||
|
#include "searchdata.h"
|
||||||
|
|
||||||
|
class AdvSearchHist {
|
||||||
|
public:
|
||||||
|
AdvSearchHist();
|
||||||
|
~AdvSearchHist();
|
||||||
|
RefCntr<Rcl::SearchData> getolder();
|
||||||
|
RefCntr<Rcl::SearchData> getnewer();
|
||||||
|
bool push(RefCntr<Rcl::SearchData>);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool read();
|
||||||
|
|
||||||
|
int m_current;
|
||||||
|
std::vector<RefCntr<Rcl::SearchData> > m_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _ADVSHIST_H_INCLUDED_
|
||||||
@ -25,12 +25,14 @@
|
|||||||
#include "guiutils.h"
|
#include "guiutils.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
#include "advshist.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
|
||||||
RclDynConf *g_dynconf;
|
RclDynConf *g_dynconf;
|
||||||
|
AdvSearchHist *g_advshistory;
|
||||||
|
|
||||||
// The table should not be necessary, but I found no css way to get
|
// The table should not be necessary, but I found no css way to get
|
||||||
// qt 4.6 qtextedit to clear the margins after the float img without
|
// qt 4.6 qtextedit to clear the margins after the float img without
|
||||||
|
|||||||
@ -27,6 +27,9 @@
|
|||||||
#include "dynconf.h"
|
#include "dynconf.h"
|
||||||
extern RclDynConf *g_dynconf;
|
extern RclDynConf *g_dynconf;
|
||||||
|
|
||||||
|
#include "advshist.h"
|
||||||
|
extern AdvSearchHist *g_advshistory;
|
||||||
|
|
||||||
#ifndef NO_NAMESPACES
|
#ifndef NO_NAMESPACES
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::list;
|
using std::list;
|
||||||
|
|||||||
@ -338,6 +338,7 @@ int main(int argc, char **argv)
|
|||||||
QMessageBox::critical(0, "Recoll", msg);
|
QMessageBox::critical(0, "Recoll", msg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
g_advshistory = new AdvSearchHist;
|
||||||
|
|
||||||
// fprintf(stderr, "History done\n");
|
// fprintf(stderr, "History done\n");
|
||||||
rwSettings(false);
|
rwSettings(false);
|
||||||
|
|||||||
@ -1855,7 +1855,10 @@ void RclMain::eraseDocHistory()
|
|||||||
void RclMain::eraseSearchHistory()
|
void RclMain::eraseSearchHistory()
|
||||||
{
|
{
|
||||||
prefs.ssearchHistory.clear();
|
prefs.ssearchHistory.clear();
|
||||||
sSearch->queryText->clear();
|
if (sSearch)
|
||||||
|
sSearch->queryText->clear();
|
||||||
|
if (g_advshistory)
|
||||||
|
g_advshistory->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the uiprefs dialog is ok'd
|
// Called when the uiprefs dialog is ok'd
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef _RECOLL_H_INCLUDED_
|
#ifndef _RECOLL_H_INCLUDED_
|
||||||
#define _RECOLL_H_INCLUDED_
|
#define _RECOLL_H_INCLUDED_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
@ -51,4 +52,8 @@ class Aspell;
|
|||||||
extern Aspell *aspell;
|
extern Aspell *aspell;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
inline std::string qs2utf8s(const QString& qs)
|
||||||
|
{
|
||||||
|
return std::string((const char *)qs.toUtf8());
|
||||||
|
}
|
||||||
#endif /* _RECOLL_H_INCLUDED_ */
|
#endif /* _RECOLL_H_INCLUDED_ */
|
||||||
|
|||||||
@ -7,10 +7,13 @@ LANGUAGE = C++
|
|||||||
@QMAKE_ENABLE_ZEITGEIST@QT += dbus
|
@QMAKE_ENABLE_ZEITGEIST@QT += dbus
|
||||||
@QMAKE_ENABLE_ZEITGEIST@QMAKE_CXXFLAGS += -DUSE_ZEITGEIST
|
@QMAKE_ENABLE_ZEITGEIST@QMAKE_CXXFLAGS += -DUSE_ZEITGEIST
|
||||||
|
|
||||||
|
QT += xml
|
||||||
|
|
||||||
CONFIG += qt warn_on thread release
|
CONFIG += qt warn_on thread release
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
advsearch_w.h \
|
advsearch_w.h \
|
||||||
|
advshist.h \
|
||||||
confgui/confgui.h \
|
confgui/confgui.h \
|
||||||
confgui/confguiindex.h \
|
confgui/confguiindex.h \
|
||||||
crontool.h \
|
crontool.h \
|
||||||
@ -34,6 +37,7 @@ HEADERS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
advsearch_w.cpp \
|
advsearch_w.cpp \
|
||||||
|
advshist.cpp \
|
||||||
confgui/confgui.cpp \
|
confgui/confgui.cpp \
|
||||||
confgui/confguiindex.cpp \
|
confgui/confguiindex.cpp \
|
||||||
crontool.cpp \
|
crontool.cpp \
|
||||||
@ -54,7 +58,6 @@ SOURCES += \
|
|||||||
viewaction_w.cpp \
|
viewaction_w.cpp \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FORMS = \
|
FORMS = \
|
||||||
advsearch.ui \
|
advsearch.ui \
|
||||||
crontool.ui \
|
crontool.ui \
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
|
||||||
#include "searchclause_w.h"
|
#include "searchclause_w.h"
|
||||||
|
|
||||||
@ -28,6 +29,8 @@
|
|||||||
#include <qtooltip.h>
|
#include <qtooltip.h>
|
||||||
#include <qwhatsthis.h>
|
#include <qwhatsthis.h>
|
||||||
|
|
||||||
|
using namespace Rcl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructs a SearchClauseW as a child of 'parent', with the
|
* Constructs a SearchClauseW as a child of 'parent', with the
|
||||||
* name 'name' and widget flags set to 'f'.
|
* name 'name' and widget flags set to 'f'.
|
||||||
@ -100,11 +103,8 @@ void SearchClauseW::languageChange()
|
|||||||
proxSlackSB->setToolTip(tr("Number of additional words that may be interspersed with the chosen ones"));
|
proxSlackSB->setToolTip(tr("Number of additional words that may be interspersed with the chosen ones"));
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Rcl;
|
|
||||||
|
|
||||||
// Translate my window state into an Rcl search clause
|
// Translate my window state into an Rcl search clause
|
||||||
SearchDataClause *
|
SearchDataClause *SearchClauseW::getClause()
|
||||||
SearchClauseW::getClause()
|
|
||||||
{
|
{
|
||||||
if (wordsLE->text().isEmpty())
|
if (wordsLE->text().isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
@ -134,6 +134,61 @@ SearchClauseW::getClause()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SearchClauseW::setFromClause(SearchDataClauseSimple *cl)
|
||||||
|
{
|
||||||
|
LOGDEB(("SearchClauseW::setFromClause\n"));
|
||||||
|
switch(cl->getTp()) {
|
||||||
|
case SCLT_OR: tpChange(0); break;
|
||||||
|
case SCLT_AND: tpChange(1); break;
|
||||||
|
case SCLT_EXCL: tpChange(2); break;
|
||||||
|
case SCLT_PHRASE: tpChange(3); break;
|
||||||
|
case SCLT_NEAR: tpChange(4); break;
|
||||||
|
case SCLT_FILENAME: tpChange(5); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
LOGDEB(("SearchClauseW::setFromClause: calling erase\n"));
|
||||||
|
clear();
|
||||||
|
|
||||||
|
QString text = QString::fromUtf8(cl->gettext().c_str());
|
||||||
|
QString field = QString::fromUtf8(cl->getfield().c_str());
|
||||||
|
|
||||||
|
switch(cl->getTp()) {
|
||||||
|
case SCLT_OR: case SCLT_AND: case SCLT_EXCL:
|
||||||
|
case SCLT_PHRASE: case SCLT_NEAR:
|
||||||
|
if (!field.isEmpty()) {
|
||||||
|
int idx = fldCMB->findText(field);
|
||||||
|
if (field >= 0) {
|
||||||
|
fldCMB->setCurrentIndex(idx);
|
||||||
|
} else {
|
||||||
|
fldCMB->setEditText(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case SCLT_FILENAME:
|
||||||
|
wordsLE->setText(text);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cl->getTp()) {
|
||||||
|
case SCLT_PHRASE: case SCLT_NEAR:
|
||||||
|
{
|
||||||
|
SearchDataClauseDist *cls = dynamic_cast<SearchDataClauseDist*>(cl);
|
||||||
|
proxSlackSB->setValue(cls->getslack());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchClauseW::clear()
|
||||||
|
{
|
||||||
|
wordsLE->setText("");
|
||||||
|
fldCMB->setCurrentIndex(0);
|
||||||
|
proxSlackSB->setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle combobox change: may need to enable/disable the distance
|
// Handle combobox change: may need to enable/disable the distance
|
||||||
// spinbox and field spec
|
// spinbox and field spec
|
||||||
void SearchClauseW::tpChange(int index)
|
void SearchClauseW::tpChange(int index)
|
||||||
|
|||||||
@ -37,6 +37,8 @@ public:
|
|||||||
SearchClauseW(QWidget* parent = 0);
|
SearchClauseW(QWidget* parent = 0);
|
||||||
~SearchClauseW();
|
~SearchClauseW();
|
||||||
Rcl::SearchDataClause *getClause();
|
Rcl::SearchDataClause *getClause();
|
||||||
|
void setFromClause(Rcl::SearchDataClauseSimple *cl);
|
||||||
|
void clear();
|
||||||
|
|
||||||
QComboBox* sTpCMB;
|
QComboBox* sTpCMB;
|
||||||
QComboBox* fldCMB;
|
QComboBox* fldCMB;
|
||||||
|
|||||||
@ -25,22 +25,17 @@
|
|||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
|
||||||
#ifndef NO_NAMESPACES
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Well known keys for history and external indexes.
|
// Well known keys for history and external indexes.
|
||||||
const string docHistSubKey = "docs";
|
const string docHistSubKey = "docs";
|
||||||
const string allEdbsSk = "allExtDbs";
|
const string allEdbsSk = "allExtDbs";
|
||||||
const string actEdbsSk = "actExtDbs";
|
const string actEdbsSk = "actExtDbs";
|
||||||
|
const string advSearchHistSk = "advSearchHist";
|
||||||
|
|
||||||
|
|
||||||
// @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,
|
bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
|
||||||
int maxlen)
|
int maxlen)
|
||||||
{
|
{
|
||||||
// Is this doc already in list ? If it is we remove the old entry
|
// Is this doc already in list ? If it is we remove the old entry
|
||||||
vector<string> names = m_data.getNames(sk);
|
vector<string> names = m_data.getNames(sk);
|
||||||
@ -98,37 +93,21 @@ bool RclDynConf::eraseAll(const string &sk)
|
|||||||
vector<string> names = m_data.getNames(sk);
|
vector<string> names = m_data.getNames(sk);
|
||||||
vector<string>::const_iterator it;
|
vector<string>::const_iterator it;
|
||||||
for (it = names.begin(); it != names.end(); it++) {
|
for (it = names.begin(); it != names.end(); it++) {
|
||||||
m_data.erase(*it, sk);
|
m_data.erase(*it, sk);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generic string list specialization ///////////////////////////////////
|
// Specialization for plain strings ///////////////////////////////////
|
||||||
|
|
||||||
// Encode/decode simple string. base64 used to avoid problems with
|
|
||||||
// strange chars
|
|
||||||
bool RclSListEntry::encode(string& enc)
|
|
||||||
{
|
|
||||||
base64_encode(value, enc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
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)
|
bool RclDynConf::enterString(const string sk, const string value, int maxlen)
|
||||||
{
|
{
|
||||||
RclSListEntry ne(value);
|
RclSListEntry ne(value);
|
||||||
RclSListEntry scratch;
|
RclSListEntry scratch;
|
||||||
return insertNew(sk, ne, scratch, maxlen);
|
return insertNew(sk, ne, scratch, maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
list<string> RclDynConf::getStringList(const string sk)
|
list<string> RclDynConf::getStringList(const string sk)
|
||||||
{
|
{
|
||||||
list<RclSListEntry> el = getList<RclSListEntry>(sk);
|
list<RclSListEntry> el = getList<RclSListEntry>(sk);
|
||||||
|
|||||||
@ -34,6 +34,9 @@
|
|||||||
* encodings which depend on the data stored. Under each section, the keys
|
* encodings which depend on the data stored. Under each section, the keys
|
||||||
* are sequential numeric, so this basically manages a set of lists.
|
* are sequential numeric, so this basically manages a set of lists.
|
||||||
*
|
*
|
||||||
|
* The code ensures that a a given value (as defined by the
|
||||||
|
* DynConfEntry::equal() method is only stored once. If undesirable,
|
||||||
|
* equal() should always return false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -41,67 +44,95 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "conftree.h"
|
#include "conftree.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
#ifndef NO_NAMESPACES
|
/** Interface for a stored object. */
|
||||||
using namespace std;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Entry interface.
|
|
||||||
class DynConfEntry {
|
class DynConfEntry {
|
||||||
public:
|
public:
|
||||||
virtual ~DynConfEntry() {}
|
/** Decode object-as-string coming out from storage */
|
||||||
virtual bool decode(const string &value) = 0;
|
virtual bool decode(const std::string &value) = 0;
|
||||||
virtual bool encode(string& value) = 0;
|
/** Encode object state into state for storing */
|
||||||
|
virtual bool encode(std::string& value) = 0;
|
||||||
|
/** Compare objects */
|
||||||
virtual bool equal(const DynConfEntry &other) = 0;
|
virtual bool equal(const DynConfEntry &other) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Stored object specialization for generic string storage */
|
||||||
/** String storage generic object */
|
|
||||||
class RclSListEntry : public DynConfEntry {
|
class RclSListEntry : public DynConfEntry {
|
||||||
public:
|
public:
|
||||||
RclSListEntry() {}
|
RclSListEntry()
|
||||||
RclSListEntry(const string& v) : value(v) {}
|
{
|
||||||
virtual ~RclSListEntry() {}
|
}
|
||||||
virtual bool decode(const string &enc);
|
RclSListEntry(const std::string& v)
|
||||||
virtual bool encode(string& enc);
|
: value(v)
|
||||||
virtual bool equal(const DynConfEntry& other);
|
{
|
||||||
|
}
|
||||||
|
virtual bool decode(const std::string &enc)
|
||||||
|
{
|
||||||
|
base64_decode(enc, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool encode(std::string& enc)
|
||||||
|
{
|
||||||
|
base64_encode(value, enc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool equal(const DynConfEntry& other)
|
||||||
|
{
|
||||||
|
const RclSListEntry& e = dynamic_cast<const RclSListEntry&>(other);
|
||||||
|
return e.value == value;
|
||||||
|
}
|
||||||
|
|
||||||
string value;
|
std::string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The dynamic configuration class */
|
/** The dynamic configuration class */
|
||||||
class RclDynConf {
|
class RclDynConf {
|
||||||
public:
|
public:
|
||||||
RclDynConf(const string &fn)
|
RclDynConf(const std::string &fn)
|
||||||
: m_data(fn.c_str()) {}
|
: m_data(fn.c_str())
|
||||||
bool ok() {return m_data.getStatus() == ConfSimple::STATUS_RW;}
|
{
|
||||||
string getFilename() {return m_data.getFilename();}
|
}
|
||||||
|
bool ok()
|
||||||
|
{
|
||||||
|
return m_data.getStatus() == ConfSimple::STATUS_RW;
|
||||||
|
}
|
||||||
|
std::string getFilename()
|
||||||
|
{
|
||||||
|
return m_data.getFilename();
|
||||||
|
}
|
||||||
|
|
||||||
// Generic methods
|
// Generic methods
|
||||||
bool eraseAll(const string& sk);
|
bool eraseAll(const std::string& sk);
|
||||||
bool insertNew(const string& sk, DynConfEntry &n, DynConfEntry &s,
|
|
||||||
|
/** Insert new entry for section sk
|
||||||
|
* @param sk section this is for
|
||||||
|
* @param n new entry
|
||||||
|
* @param s a scratch entry used for decoding and comparisons,
|
||||||
|
* avoiding templating the routine for the actual entry type.
|
||||||
|
*/
|
||||||
|
bool insertNew(const std::string& sk, DynConfEntry &n, DynConfEntry &s,
|
||||||
int maxlen = -1);
|
int maxlen = -1);
|
||||||
template<typename Tp> list<Tp> getList(const string& sk);
|
template<typename Tp> std::list<Tp> getList(const std::string& sk);
|
||||||
|
|
||||||
// Specialized methods for simple string lists, designated by the
|
// Specialized methods for simple string lists, designated by the
|
||||||
// subkey value
|
// subkey value
|
||||||
bool enterString(const string sk, const string value, int maxlen = -1);
|
bool enterString(const std::string sk, const std::string value, int maxlen = -1);
|
||||||
list<string> getStringList(const string sk);
|
std::list<std::string> getStringList(const std::string sk);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_mlen;
|
unsigned int m_mlen;
|
||||||
ConfSimple m_data;
|
ConfSimple m_data;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Tp> list<Tp> RclDynConf::getList(const string &sk)
|
template<typename Tp> std::list<Tp> RclDynConf::getList(const std::string &sk)
|
||||||
{
|
{
|
||||||
list<Tp> mlist;
|
std::list<Tp> mlist;
|
||||||
Tp entry;
|
Tp entry;
|
||||||
vector<string> names = m_data.getNames(sk);
|
std::vector<std::string> names = m_data.getNames(sk);
|
||||||
for (vector<string>::const_iterator it = names.begin();
|
for (std::vector<std::string>::const_iterator it = names.begin();
|
||||||
it != names.end(); it++) {
|
it != names.end(); it++) {
|
||||||
string value;
|
std::string value;
|
||||||
if (m_data.get(*it, value, sk)) {
|
if (m_data.get(*it, value, sk)) {
|
||||||
if (!entry.decode(value))
|
if (!entry.decode(value))
|
||||||
continue;
|
continue;
|
||||||
@ -113,10 +144,12 @@ template<typename Tp> list<Tp> RclDynConf::getList(const string &sk)
|
|||||||
|
|
||||||
// Defined subkeys. Values in dynconf.cpp
|
// Defined subkeys. Values in dynconf.cpp
|
||||||
// History
|
// History
|
||||||
extern const string docHistSubKey;
|
extern const std::string docHistSubKey;
|
||||||
// All external indexes
|
// All external indexes
|
||||||
extern const string allEdbsSk;
|
extern const std::string allEdbsSk;
|
||||||
// Active external indexes
|
// Active external indexes
|
||||||
extern const string actEdbsSk;
|
extern const std::string actEdbsSk;
|
||||||
|
// Advanced search history
|
||||||
|
extern const std::string advSearchHistSk;
|
||||||
|
|
||||||
#endif /* _DYNCONF_H_INCLUDED_ */
|
#endif /* _DYNCONF_H_INCLUDED_ */
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include "xapian.h"
|
#include "xapian.h"
|
||||||
@ -44,6 +45,7 @@ using namespace std;
|
|||||||
#include "synfamily.h"
|
#include "synfamily.h"
|
||||||
#include "stemdb.h"
|
#include "stemdb.h"
|
||||||
#include "expansiondbs.h"
|
#include "expansiondbs.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
namespace Rcl {
|
namespace Rcl {
|
||||||
|
|
||||||
@ -253,6 +255,112 @@ bool SearchData::clausesToQuery(Rcl::Db &db, SClType tp,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string tpToString(SClType tp)
|
||||||
|
{
|
||||||
|
switch (tp) {
|
||||||
|
case SCLT_AND: return "AND";
|
||||||
|
case SCLT_OR: return "OR";
|
||||||
|
case SCLT_EXCL: return "EX";
|
||||||
|
case SCLT_FILENAME: return "FN";
|
||||||
|
case SCLT_PHRASE: return "PH";
|
||||||
|
case SCLT_NEAR: return "NE";
|
||||||
|
case SCLT_SUB: return "SU"; // Unsupported actually
|
||||||
|
default: return "UN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string SearchData::asXML()
|
||||||
|
{
|
||||||
|
LOGDEB(("SearchData::asXML\n"));
|
||||||
|
ostringstream os;
|
||||||
|
|
||||||
|
// Searchdata
|
||||||
|
os << "<SD>" << endl;
|
||||||
|
|
||||||
|
// Clause list
|
||||||
|
os << "<CL>" << endl;
|
||||||
|
if (m_tp != SCLT_AND)
|
||||||
|
os << "<CLT>" << tpToString(m_tp) << "</CLT>" << endl;
|
||||||
|
for (unsigned int i = 0; i < m_query.size(); i++) {
|
||||||
|
SearchDataClause *c = m_query[i];
|
||||||
|
if (c->getTp() == SCLT_SUB) {
|
||||||
|
LOGERR(("SearchData::asXML: can't do subclauses !\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SearchDataClauseSimple *cl =
|
||||||
|
dynamic_cast<SearchDataClauseSimple*>(c);
|
||||||
|
os << "<C>" << endl;
|
||||||
|
if (cl->getTp() != SCLT_AND) {
|
||||||
|
os << "<CT>" << tpToString(cl->getTp()) << "</CT>" << endl;
|
||||||
|
}
|
||||||
|
if (cl->getTp() != SCLT_FILENAME && !cl->getfield().empty()) {
|
||||||
|
os << "<F>" << base64_encode(cl->getfield()) << "</F>" << endl;
|
||||||
|
}
|
||||||
|
os << "<T>" << base64_encode(cl->gettext()) << "</T>" << endl;
|
||||||
|
if (cl->getTp() == SCLT_NEAR || cl->getTp() == SCLT_PHRASE) {
|
||||||
|
SearchDataClauseDist *cld =
|
||||||
|
dynamic_cast<SearchDataClauseDist*>(cl);
|
||||||
|
os << "<S>" << cld->getslack() << "</S>" << endl;
|
||||||
|
}
|
||||||
|
os << "</C>" << endl;
|
||||||
|
}
|
||||||
|
os << "</CL>" << endl;
|
||||||
|
|
||||||
|
if (m_haveDates) {
|
||||||
|
if (m_dates.y1 > 0) {
|
||||||
|
os << "<DMI>" <<
|
||||||
|
"<D>" << m_dates.d1 << "</D>" <<
|
||||||
|
"<M>" << m_dates.m1 << "</M>" <<
|
||||||
|
"<Y>" << m_dates.y1 << "</Y>"
|
||||||
|
<< "</DMI>" << endl;
|
||||||
|
}
|
||||||
|
if (m_dates.y2 > 0) {
|
||||||
|
os << "<DMA>" <<
|
||||||
|
"<D>" << m_dates.d2 << "</D>" <<
|
||||||
|
"<M>" << m_dates.m2 << "</M>" <<
|
||||||
|
"<Y>" << m_dates.y2 << "</Y>"
|
||||||
|
<< "</DMA>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (m_minSize != size_t(-1)) {
|
||||||
|
os << "<MIS>" << m_minSize << "</MIS>" << endl;
|
||||||
|
}
|
||||||
|
if (m_maxSize != size_t(-1)) {
|
||||||
|
os << "<MAS>" << m_maxSize << "</MAS>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_filetypes.empty()) {
|
||||||
|
os << "<ST>";
|
||||||
|
for (vector<string>::iterator it = m_filetypes.begin();
|
||||||
|
it != m_filetypes.end(); it++) {
|
||||||
|
os << *it << " ";
|
||||||
|
}
|
||||||
|
os << "</ST>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_nfiletypes.empty()) {
|
||||||
|
os << "<IT>";
|
||||||
|
for (vector<string>::iterator it = m_nfiletypes.begin();
|
||||||
|
it != m_nfiletypes.end(); it++) {
|
||||||
|
os << *it << " ";
|
||||||
|
}
|
||||||
|
os << "</IT>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vector<DirSpec>::const_iterator dit = m_dirspecs.begin();
|
||||||
|
dit != m_dirspecs.end(); dit++) {
|
||||||
|
if (dit->exclude) {
|
||||||
|
os << "<ND>" << base64_encode(dit->dir) << "</ND>" << endl;
|
||||||
|
} else {
|
||||||
|
os << "<YD>" << base64_encode(dit->dir) << "</YD>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "</SD>";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
bool SearchData::toNativeQuery(Rcl::Db &db, void *d, int maxexp, int maxcl)
|
bool SearchData::toNativeQuery(Rcl::Db &db, void *d, int maxexp, int maxcl)
|
||||||
{
|
{
|
||||||
LOGDEB(("SearchData::toNativeQuery: stemlang [%s]\n", m_stemlang.c_str()));
|
LOGDEB(("SearchData::toNativeQuery: stemlang [%s]\n", m_stemlang.c_str()));
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
#include "hldata.h"
|
#include "hldata.h"
|
||||||
|
|
||||||
class RclConfig;
|
class RclConfig;
|
||||||
|
class AdvSearch;
|
||||||
|
|
||||||
namespace Rcl {
|
namespace Rcl {
|
||||||
|
|
||||||
@ -77,6 +78,12 @@ public:
|
|||||||
if (m_tp != SCLT_OR && m_tp != SCLT_AND)
|
if (m_tp != SCLT_OR && m_tp != SCLT_AND)
|
||||||
m_tp = SCLT_OR;
|
m_tp = SCLT_OR;
|
||||||
}
|
}
|
||||||
|
SearchData()
|
||||||
|
: m_tp(SCLT_AND), m_haveDates(false), m_maxSize(size_t(-1)),
|
||||||
|
m_minSize(size_t(-1)), m_haveWildCards(false), m_stemlang("english")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~SearchData() {erase();}
|
~SearchData() {erase();}
|
||||||
|
|
||||||
/** Make pristine */
|
/** Make pristine */
|
||||||
@ -136,6 +143,12 @@ public:
|
|||||||
std::string getDescription() {return m_description;}
|
std::string getDescription() {return m_description;}
|
||||||
void setDescription(const std::string& d) {m_description = d;}
|
void setDescription(const std::string& d) {m_description = d;}
|
||||||
|
|
||||||
|
virtual string asXML();
|
||||||
|
void setTp(SClType tp)
|
||||||
|
{
|
||||||
|
m_tp = tp;
|
||||||
|
}
|
||||||
|
friend class ::AdvSearch;
|
||||||
private:
|
private:
|
||||||
// Combine type. Only SCLT_AND or SCLT_OR here
|
// Combine type. Only SCLT_AND or SCLT_OR here
|
||||||
SClType m_tp;
|
SClType m_tp;
|
||||||
@ -196,7 +209,7 @@ public:
|
|||||||
virtual std::string getReason() const {return m_reason;}
|
virtual std::string getReason() const {return m_reason;}
|
||||||
virtual void getTerms(HighlightData & hldata) const = 0;
|
virtual void getTerms(HighlightData & hldata) const = 0;
|
||||||
|
|
||||||
SClType getTp()
|
SClType getTp() const
|
||||||
{
|
{
|
||||||
return m_tp;
|
return m_tp;
|
||||||
}
|
}
|
||||||
@ -326,6 +339,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool toNativeQuery(Rcl::Db &, void *, int maxexp, int maxcl);
|
virtual bool toNativeQuery(Rcl::Db &, void *, int maxexp, int maxcl);
|
||||||
|
virtual int getslack() const
|
||||||
|
{
|
||||||
|
return m_slack;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
int m_slack;
|
int m_slack;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -91,7 +91,7 @@ bool base64_decode(const string& in, string& out)
|
|||||||
{
|
{
|
||||||
int io = 0, state = 0, ch = 0;
|
int io = 0, state = 0, ch = 0;
|
||||||
unsigned int ii = 0;
|
unsigned int ii = 0;
|
||||||
out.erase();
|
out.clear();
|
||||||
size_t ilen = in.length();
|
size_t ilen = in.length();
|
||||||
out.reserve(ilen);
|
out.reserve(ilen);
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ void base64_encode(const string &in, string &out)
|
|||||||
unsigned char input[3];
|
unsigned char input[3];
|
||||||
unsigned char output[4];
|
unsigned char output[4];
|
||||||
|
|
||||||
out.erase();
|
out.clear();
|
||||||
|
|
||||||
int srclength = in.length();
|
int srclength = in.length();
|
||||||
int sidx = 0;
|
int sidx = 0;
|
||||||
|
|||||||
@ -20,5 +20,18 @@
|
|||||||
|
|
||||||
void base64_encode(const std::string& in, std::string& out);
|
void base64_encode(const std::string& in, std::string& out);
|
||||||
bool base64_decode(const std::string& in, std::string& out);
|
bool base64_decode(const std::string& in, std::string& out);
|
||||||
|
inline std::string base64_encode(const std::string& in)
|
||||||
|
{
|
||||||
|
std::string o;
|
||||||
|
base64_encode(in, o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
inline std::string base64_decode(const std::string& in)
|
||||||
|
{
|
||||||
|
std::string o;
|
||||||
|
if (base64_decode(in, o))
|
||||||
|
return o;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _BASE64_H_INCLUDED_ */
|
#endif /* _BASE64_H_INCLUDED_ */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user