implemented advanced search history feature
This commit is contained in:
parent
303da79621
commit
2296a8d287
20 changed files with 736 additions and 97 deletions
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
kchmviewer --url $2 $1
|
|
@ -146,6 +146,7 @@ filters/rcldia
|
|||
filters/rcldjvu
|
||||
filters/rcldoc
|
||||
filters/rcldvi
|
||||
filters/rclepub
|
||||
filters/rclexecm.py
|
||||
filters/rclfb2
|
||||
filters/rclgaim
|
||||
|
@ -292,6 +293,8 @@ qtgui/
|
|||
qtgui/advsearch.ui
|
||||
qtgui/advsearch_w.cpp
|
||||
qtgui/advsearch_w.h
|
||||
qtgui/advshist.cpp
|
||||
qtgui/advshist.h
|
||||
qtgui/confgui/
|
||||
qtgui/confgui/confgui.cpp
|
||||
qtgui/confgui/confgui.h
|
||||
|
|
|
@ -27,18 +27,12 @@
|
|||
#include <qtooltip.h>
|
||||
#include <qwhatsthis.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <QShortcut>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using std::list;
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::unique;
|
||||
#endif /* NO_NAMESPACES */
|
||||
using namespace std;
|
||||
|
||||
#include "recoll.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_rtranslations;
|
||||
|
||||
|
||||
void AdvSearch::init()
|
||||
{
|
||||
(void)new HelpClient(this);
|
||||
|
@ -83,6 +76,9 @@ void AdvSearch::init()
|
|||
connect(addClausePB, SIGNAL(clicked()), this, SLOT(addClause()));
|
||||
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(2, tr("Any clause"));
|
||||
|
||||
|
@ -92,7 +88,7 @@ void AdvSearch::init()
|
|||
}
|
||||
// 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();
|
||||
it != prefs.advSearchClauses.end(); it++) {
|
||||
if (cit != m_clauseWins.end()) {
|
||||
|
@ -109,6 +105,8 @@ void AdvSearch::init()
|
|||
int minyear, maxyear;
|
||||
if (rcldb) {
|
||||
rcldb->maxYearSpan(&minyear, &maxyear);
|
||||
minDateDTE->setDisplayFormat("dd.MM.yyyy");
|
||||
maxDateDTE->setDisplayFormat("dd.MM.yyyy");
|
||||
minDateDTE->setDate(QDate(minyear, 1, 1));
|
||||
maxDateDTE->setDate(QDate(maxyear, 12, 31));
|
||||
}
|
||||
|
@ -158,7 +156,7 @@ void AdvSearch::saveCnf()
|
|||
{
|
||||
// Save my state
|
||||
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++) {
|
||||
prefs.advSearchClauses.push_back((*cit)->sTpCMB->currentIndex());
|
||||
}
|
||||
|
@ -170,12 +168,6 @@ bool AdvSearch::close()
|
|||
return QWidget::close();
|
||||
}
|
||||
|
||||
void AdvSearch::delAFiltypPB_clicked()
|
||||
{
|
||||
yesFiltypsLB->selectAll();
|
||||
delFiltypPB_clicked();
|
||||
}
|
||||
|
||||
void AdvSearch::addClause()
|
||||
{
|
||||
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
|
||||
void AdvSearch::delFiltypPB_clicked()
|
||||
{
|
||||
|
@ -329,6 +327,12 @@ void AdvSearch::saveFileTypes()
|
|||
rwSettings(true);
|
||||
}
|
||||
|
||||
void AdvSearch::browsePB_clicked()
|
||||
{
|
||||
QString dir = myGetFileName(true);
|
||||
subtreeCMB->setEditText(dir);
|
||||
}
|
||||
|
||||
size_t AdvSearch::stringToSize(QString qsize)
|
||||
{
|
||||
size_t size = size_t(-1);
|
||||
|
@ -361,7 +365,7 @@ void AdvSearch::runSearch()
|
|||
SCLT_AND : SCLT_OR, stemLang));
|
||||
bool hasclause = false;
|
||||
|
||||
for (list<SearchClauseW*>::iterator it = m_clauseWins.begin();
|
||||
for (vector<SearchClauseW*>::iterator it = m_clauseWins.begin();
|
||||
it != m_clauseWins.end(); it++) {
|
||||
SearchDataClause *cl;
|
||||
if ((cl = (*it)->getClause())) {
|
||||
|
@ -441,12 +445,121 @@ void AdvSearch::runSearch()
|
|||
prefs.asearchSubdirHist.push_back(subtreeCMB->itemText(index));
|
||||
}
|
||||
saveCnf();
|
||||
|
||||
g_advshistory && g_advshistory->push(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);
|
||||
subtreeCMB->setEditText(dir);
|
||||
if (sdata->m_tp == SCLT_OR)
|
||||
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_
|
||||
#define _ADVSEARCH_W_H_INCLUDED_
|
||||
#include <list>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <qvariant.h>
|
||||
#include <qdialog.h>
|
||||
|
||||
|
@ -24,6 +26,7 @@
|
|||
#include "recoll.h"
|
||||
#include "refcntr.h"
|
||||
#include "searchdata.h"
|
||||
#include "advshist.h"
|
||||
|
||||
class QDialog;
|
||||
|
||||
|
@ -53,19 +56,22 @@ public slots:
|
|||
virtual void restrictFtCB_toggled(bool);
|
||||
virtual void restrictCtCB_toggled(bool);
|
||||
virtual void runSearch();
|
||||
virtual void fromSearch(RefCntr<Rcl::SearchData> sdata);
|
||||
virtual void browsePB_clicked();
|
||||
virtual void saveFileTypes();
|
||||
virtual void delClause();
|
||||
virtual void addClause();
|
||||
virtual void addClause(int);
|
||||
virtual bool close();
|
||||
virtual void slotHistoryNext();
|
||||
virtual void slotHistoryPrev();
|
||||
|
||||
signals:
|
||||
void startSearch(RefCntr<Rcl::SearchData>);
|
||||
|
||||
private:
|
||||
virtual void init();
|
||||
std::list<SearchClauseW *> m_clauseWins;
|
||||
std::vector<SearchClauseW *> m_clauseWins;
|
||||
QStringList m_ignTypes;
|
||||
bool m_ignByCats;
|
||||
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 "pathut.h"
|
||||
#include "base64.h"
|
||||
#include "advshist.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QFileDialog>
|
||||
|
||||
RclDynConf *g_dynconf;
|
||||
AdvSearchHist *g_advshistory;
|
||||
|
||||
// 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
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "dynconf.h"
|
||||
extern RclDynConf *g_dynconf;
|
||||
|
||||
#include "advshist.h"
|
||||
extern AdvSearchHist *g_advshistory;
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using std::string;
|
||||
using std::list;
|
||||
|
|
|
@ -338,6 +338,7 @@ int main(int argc, char **argv)
|
|||
QMessageBox::critical(0, "Recoll", msg);
|
||||
exit(1);
|
||||
}
|
||||
g_advshistory = new AdvSearchHist;
|
||||
|
||||
// fprintf(stderr, "History done\n");
|
||||
rwSettings(false);
|
||||
|
|
|
@ -1855,7 +1855,10 @@ void RclMain::eraseDocHistory()
|
|||
void RclMain::eraseSearchHistory()
|
||||
{
|
||||
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
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
#ifndef _RECOLL_H_INCLUDED_
|
||||
#define _RECOLL_H_INCLUDED_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rclconfig.h"
|
||||
|
@ -51,4 +52,8 @@ class Aspell;
|
|||
extern Aspell *aspell;
|
||||
#endif
|
||||
|
||||
inline std::string qs2utf8s(const QString& qs)
|
||||
{
|
||||
return std::string((const char *)qs.toUtf8());
|
||||
}
|
||||
#endif /* _RECOLL_H_INCLUDED_ */
|
||||
|
|
|
@ -7,10 +7,13 @@ LANGUAGE = C++
|
|||
@QMAKE_ENABLE_ZEITGEIST@QT += dbus
|
||||
@QMAKE_ENABLE_ZEITGEIST@QMAKE_CXXFLAGS += -DUSE_ZEITGEIST
|
||||
|
||||
QT += xml
|
||||
|
||||
CONFIG += qt warn_on thread release
|
||||
|
||||
HEADERS += \
|
||||
advsearch_w.h \
|
||||
advshist.h \
|
||||
confgui/confgui.h \
|
||||
confgui/confguiindex.h \
|
||||
crontool.h \
|
||||
|
@ -34,6 +37,7 @@ HEADERS += \
|
|||
|
||||
SOURCES += \
|
||||
advsearch_w.cpp \
|
||||
advshist.cpp \
|
||||
confgui/confgui.cpp \
|
||||
confgui/confguiindex.cpp \
|
||||
crontool.cpp \
|
||||
|
@ -54,7 +58,6 @@ SOURCES += \
|
|||
viewaction_w.cpp \
|
||||
|
||||
|
||||
|
||||
FORMS = \
|
||||
advsearch.ui \
|
||||
crontool.ui \
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "autoconfig.h"
|
||||
|
||||
#include "recoll.h"
|
||||
#include "debuglog.h"
|
||||
|
||||
#include "searchclause_w.h"
|
||||
|
||||
|
@ -28,6 +29,8 @@
|
|||
#include <qtooltip.h>
|
||||
#include <qwhatsthis.h>
|
||||
|
||||
using namespace Rcl;
|
||||
|
||||
/*
|
||||
* Constructs a SearchClauseW as a child of 'parent', with the
|
||||
* 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"));
|
||||
}
|
||||
|
||||
using namespace Rcl;
|
||||
|
||||
// Translate my window state into an Rcl search clause
|
||||
SearchDataClause *
|
||||
SearchClauseW::getClause()
|
||||
SearchDataClause *SearchClauseW::getClause()
|
||||
{
|
||||
if (wordsLE->text().isEmpty())
|
||||
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
|
||||
// spinbox and field spec
|
||||
void SearchClauseW::tpChange(int index)
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
SearchClauseW(QWidget* parent = 0);
|
||||
~SearchClauseW();
|
||||
Rcl::SearchDataClause *getClause();
|
||||
void setFromClause(Rcl::SearchDataClauseSimple *cl);
|
||||
void clear();
|
||||
|
||||
QComboBox* sTpCMB;
|
||||
QComboBox* fldCMB;
|
||||
|
|
|
@ -25,22 +25,17 @@
|
|||
#include "smallut.h"
|
||||
#include "debuglog.h"
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
// Well known keys for history and external indexes.
|
||||
const string docHistSubKey = "docs";
|
||||
const string allEdbsSk = "allExtDbs";
|
||||
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,
|
||||
int maxlen)
|
||||
int maxlen)
|
||||
{
|
||||
// Is this doc already in list ? If it is we remove the old entry
|
||||
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>::const_iterator it;
|
||||
for (it = names.begin(); it != names.end(); it++) {
|
||||
m_data.erase(*it, sk);
|
||||
m_data.erase(*it, sk);
|
||||
}
|
||||
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)
|
||||
{
|
||||
RclSListEntry ne(value);
|
||||
RclSListEntry scratch;
|
||||
return insertNew(sk, ne, scratch, maxlen);
|
||||
}
|
||||
|
||||
list<string> RclDynConf::getStringList(const string sk)
|
||||
{
|
||||
list<RclSListEntry> el = getList<RclSListEntry>(sk);
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
* encodings which depend on the data stored. Under each section, the keys
|
||||
* 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>
|
||||
|
@ -41,67 +44,95 @@
|
|||
#include <utility>
|
||||
|
||||
#include "conftree.h"
|
||||
#include "base64.h"
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
// Entry interface.
|
||||
/** Interface for a stored object. */
|
||||
class DynConfEntry {
|
||||
public:
|
||||
virtual ~DynConfEntry() {}
|
||||
virtual bool decode(const string &value) = 0;
|
||||
virtual bool encode(string& value) = 0;
|
||||
/** Decode object-as-string coming out from storage */
|
||||
virtual bool decode(const std::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;
|
||||
};
|
||||
|
||||
|
||||
/** String storage generic object */
|
||||
/** Stored object specialization for generic string storage */
|
||||
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);
|
||||
RclSListEntry()
|
||||
{
|
||||
}
|
||||
RclSListEntry(const std::string& v)
|
||||
: value(v)
|
||||
{
|
||||
}
|
||||
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 */
|
||||
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();}
|
||||
RclDynConf(const std::string &fn)
|
||||
: m_data(fn.c_str())
|
||||
{
|
||||
}
|
||||
bool ok()
|
||||
{
|
||||
return m_data.getStatus() == ConfSimple::STATUS_RW;
|
||||
}
|
||||
std::string getFilename()
|
||||
{
|
||||
return m_data.getFilename();
|
||||
}
|
||||
|
||||
// Generic methods
|
||||
bool eraseAll(const string& sk);
|
||||
bool insertNew(const string& sk, DynConfEntry &n, DynConfEntry &s,
|
||||
bool eraseAll(const std::string& sk);
|
||||
|
||||
/** 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);
|
||||
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
|
||||
// subkey value
|
||||
bool enterString(const string sk, const string value, int maxlen = -1);
|
||||
list<string> getStringList(const string sk);
|
||||
bool enterString(const std::string sk, const std::string value, int maxlen = -1);
|
||||
std::list<std::string> getStringList(const std::string sk);
|
||||
|
||||
private:
|
||||
unsigned int m_mlen;
|
||||
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;
|
||||
vector<string> names = m_data.getNames(sk);
|
||||
for (vector<string>::const_iterator it = names.begin();
|
||||
std::vector<std::string> names = m_data.getNames(sk);
|
||||
for (std::vector<std::string>::const_iterator it = names.begin();
|
||||
it != names.end(); it++) {
|
||||
string value;
|
||||
std::string value;
|
||||
if (m_data.get(*it, value, sk)) {
|
||||
if (!entry.decode(value))
|
||||
continue;
|
||||
|
@ -113,10 +144,12 @@ template<typename Tp> list<Tp> RclDynConf::getList(const string &sk)
|
|||
|
||||
// Defined subkeys. Values in dynconf.cpp
|
||||
// History
|
||||
extern const string docHistSubKey;
|
||||
extern const std::string docHistSubKey;
|
||||
// All external indexes
|
||||
extern const string allEdbsSk;
|
||||
extern const std::string allEdbsSk;
|
||||
// Active external indexes
|
||||
extern const string actEdbsSk;
|
||||
extern const std::string actEdbsSk;
|
||||
// Advanced search history
|
||||
extern const std::string advSearchHistSk;
|
||||
|
||||
#endif /* _DYNCONF_H_INCLUDED_ */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include "xapian.h"
|
||||
|
@ -44,6 +45,7 @@ using namespace std;
|
|||
#include "synfamily.h"
|
||||
#include "stemdb.h"
|
||||
#include "expansiondbs.h"
|
||||
#include "base64.h"
|
||||
|
||||
namespace Rcl {
|
||||
|
||||
|
@ -253,6 +255,112 @@ bool SearchData::clausesToQuery(Rcl::Db &db, SClType tp,
|
|||
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)
|
||||
{
|
||||
LOGDEB(("SearchData::toNativeQuery: stemlang [%s]\n", m_stemlang.c_str()));
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "hldata.h"
|
||||
|
||||
class RclConfig;
|
||||
class AdvSearch;
|
||||
|
||||
namespace Rcl {
|
||||
|
||||
|
@ -77,6 +78,12 @@ public:
|
|||
if (m_tp != SCLT_OR && m_tp != SCLT_AND)
|
||||
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();}
|
||||
|
||||
/** Make pristine */
|
||||
|
@ -136,6 +143,12 @@ public:
|
|||
std::string getDescription() {return m_description;}
|
||||
void setDescription(const std::string& d) {m_description = d;}
|
||||
|
||||
virtual string asXML();
|
||||
void setTp(SClType tp)
|
||||
{
|
||||
m_tp = tp;
|
||||
}
|
||||
friend class ::AdvSearch;
|
||||
private:
|
||||
// Combine type. Only SCLT_AND or SCLT_OR here
|
||||
SClType m_tp;
|
||||
|
@ -196,7 +209,7 @@ public:
|
|||
virtual std::string getReason() const {return m_reason;}
|
||||
virtual void getTerms(HighlightData & hldata) const = 0;
|
||||
|
||||
SClType getTp()
|
||||
SClType getTp() const
|
||||
{
|
||||
return m_tp;
|
||||
}
|
||||
|
@ -326,6 +339,10 @@ public:
|
|||
}
|
||||
|
||||
virtual bool toNativeQuery(Rcl::Db &, void *, int maxexp, int maxcl);
|
||||
virtual int getslack() const
|
||||
{
|
||||
return m_slack;
|
||||
}
|
||||
private:
|
||||
int m_slack;
|
||||
};
|
||||
|
|
|
@ -91,7 +91,7 @@ bool base64_decode(const string& in, string& out)
|
|||
{
|
||||
int io = 0, state = 0, ch = 0;
|
||||
unsigned int ii = 0;
|
||||
out.erase();
|
||||
out.clear();
|
||||
size_t ilen = in.length();
|
||||
out.reserve(ilen);
|
||||
|
||||
|
@ -217,7 +217,7 @@ void base64_encode(const string &in, string &out)
|
|||
unsigned char input[3];
|
||||
unsigned char output[4];
|
||||
|
||||
out.erase();
|
||||
out.clear();
|
||||
|
||||
int srclength = in.length();
|
||||
int sidx = 0;
|
||||
|
|
|
@ -20,5 +20,18 @@
|
|||
|
||||
void base64_encode(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_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue