diff --git a/.hgignore b/.hgignore index 39713dc7..eb520974 100644 --- a/.hgignore +++ b/.hgignore @@ -7,6 +7,7 @@ syntax: glob src/Makefile src/autom4te.cache src/bincimapmime/alldeps +src/common/alldeps src/common/autoconfig.h src/common/rclversion.h src/config.log @@ -19,20 +20,19 @@ src/desktop/unity-lens-recoll/config.status src/desktop/unity-lens-recoll/data/recoll.lens src/desktop/unity-lens-recoll/data/unity-lens-recoll.service src/doc/user/HTML.manifest -src/doc/user/index.html src/doc/user/RCL.INDEXING.CONFIG.html -src/doc/user/RCL.INDEXING.html src/doc/user/RCL.INDEXING.MONITOR.html src/doc/user/RCL.INDEXING.PERIODIC.html src/doc/user/RCL.INDEXING.STORAGE.html src/doc/user/RCL.INDEXING.WEBQUEUE.html +src/doc/user/RCL.INDEXING.html src/doc/user/RCL.INSTALL.BUILDING.html src/doc/user/RCL.INSTALL.CONFIG.html src/doc/user/RCL.INSTALL.EXTERNAL.html src/doc/user/RCL.INSTALL.html -src/doc/user/RCL.INTRODUCTION.html src/doc/user/RCL.INTRODUCTION.RECOLL.html src/doc/user/RCL.INTRODUCTION.SEARCH.html +src/doc/user/RCL.INTRODUCTION.html src/doc/user/RCL.KICKER-APPLET.html src/doc/user/RCL.PROGRAM.API.html src/doc/user/RCL.PROGRAM.FIELDS.html @@ -44,7 +44,6 @@ src/doc/user/RCL.SEARCH.COMPLEX.html src/doc/user/RCL.SEARCH.CUSTOM.html src/doc/user/RCL.SEARCH.DESKTOP.html src/doc/user/RCL.SEARCH.HISTORY.html -src/doc/user/RCL.SEARCH.html src/doc/user/RCL.SEARCH.KIO.html src/doc/user/RCL.SEARCH.LANG.html src/doc/user/RCL.SEARCH.MULTIDB.html @@ -54,9 +53,11 @@ src/doc/user/RCL.SEARCH.SORT.html src/doc/user/RCL.SEARCH.TERMEXPLORER.html src/doc/user/RCL.SEARCH.TIPS.html src/doc/user/RCL.SEARCH.WILDCARDS.html +src/doc/user/RCL.SEARCH.html src/doc/user/RCL.SEARCHKCL.html -src/doc/user/RCL.SEARCHKIO.html src/doc/user/RCL.SEARCHKIO.SEARCHABLEDOCS.html +src/doc/user/RCL.SEARCHKIO.html +src/doc/user/index.html src/doc/user/usermanual-xml.html src/doc/user/usermanual.aux src/doc/user/usermanual.html @@ -73,6 +74,7 @@ src/filters/rcllatinclass.pyc src/index/alldeps src/index/alldeps.stamp src/index/recollindex +src/internfile/alldeps src/kde/kioslave/kio_recoll/builddir src/lib/alldeps src/lib/librecoll.a @@ -98,6 +100,7 @@ src/query/xadump src/recollinstall src/sampleconf/rclmon.sh src/sampleconf/recoll.conf +src/utils/alldeps tests/config/aspdict.en.rws tests/config/history tests/config/idxstatus.txt diff --git a/src/python/recoll/pyrecoll.cpp b/src/python/recoll/pyrecoll.cpp index b83879f8..c10b47dc 100644 --- a/src/python/recoll/pyrecoll.cpp +++ b/src/python/recoll/pyrecoll.cpp @@ -206,7 +206,8 @@ SearchData_addclause(recoll_SearchDataObject* self, PyObject *args, case 'E': if (strcasecmp(tp, "excl")) goto defaultcase; - cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, qs, fld?fld:""); + cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, qs, fld?fld:""); + cl->setexclude(true); break; case 'n': case 'N': diff --git a/src/qtgui/advshist.cpp b/src/qtgui/advshist.cpp index 9703c030..5f08d18f 100644 --- a/src/qtgui/advshist.cpp +++ b/src/qtgui/advshist.cpp @@ -57,6 +57,7 @@ private: slack = 0; d = m = y = di.d1 = di.m1 = di.y1 = di.d2 = di.m2 = di.y2 = 0; hasdates = false; + exclude = false; } // Temporary data while parsing. @@ -67,6 +68,7 @@ private: int d, m, y; DateInterval di; bool hasdates; + bool exclude; }; bool SDHXMLHandler::startElement(const QString & /* namespaceURI */, @@ -101,6 +103,8 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */, } } else if (qName == "CT") { whatclause = currentText.trimmed(); + } else if (qName == "NEG") { + exclude = true; } else if (qName == "F") { field = base64_decode(qs2utf8s(currentText.trimmed())); } else if (qName == "T") { @@ -111,16 +115,24 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */, SearchDataClause *c; if (whatclause == "AND" || whatclause.isEmpty()) { c = new SearchDataClauseSimple(SCLT_AND, text, field); + c->setexclude(exclude); } else if (whatclause == "OR") { c = new SearchDataClauseSimple(SCLT_OR, text, field); + c->setexclude(exclude); } else if (whatclause == "EX") { - c = new SearchDataClauseSimple(SCLT_EXCL, text, field); + // Compat with old hist. We don't generete EX (SCLT_EXCL) anymore + // it's replaced with OR + exclude flag + c = new SearchDataClauseSimple(SCLT_OR, text, field); + c->setexclude(true); } else if (whatclause == "FN") { c = new SearchDataClauseFilename(text); + c->setexclude(exclude); } else if (whatclause == "PH") { c = new SearchDataClauseDist(SCLT_PHRASE, text, slack, field); + c->setexclude(exclude); } else if (whatclause == "NE") { c = new SearchDataClauseDist(SCLT_NEAR, text, slack, field); + c->setexclude(exclude); } else { LOGERR(("Bad clause type [%s]\n", qs2utf8s(whatclause).c_str())); return false; @@ -130,6 +142,7 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */, text.clear(); field.clear(); slack = 0; + exclude = false; } else if (qName == "D") { d = atoi((const char *)currentText.toAscii()); } else if (qName == "M") { diff --git a/src/qtgui/searchclause_w.cpp b/src/qtgui/searchclause_w.cpp index 4fb90a44..c7999c31 100644 --- a/src/qtgui/searchclause_w.cpp +++ b/src/qtgui/searchclause_w.cpp @@ -119,7 +119,12 @@ SearchDataClause *SearchClauseW::getClause() case 1: return new SearchDataClauseSimple(SCLT_AND, text, field); case 2: - return new SearchDataClauseSimple(SCLT_EXCL, text, field); + { + SearchDataClauseSimple *cl = + new SearchDataClauseSimple(SCLT_OR, text, field); + cl->setexclude(true); + return cl; + } case 3: return new SearchDataClauseDist(SCLT_PHRASE, text, proxSlackSB->value(), field); @@ -139,9 +144,8 @@ void SearchClauseW::setFromClause(SearchDataClauseSimple *cl) { LOGDEB(("SearchClauseW::setFromClause\n")); switch(cl->getTp()) { - case SCLT_OR: tpChange(0); break; + case SCLT_OR: if (cl->getexclude()) tpChange(2); else 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; @@ -154,7 +158,7 @@ void SearchClauseW::setFromClause(SearchDataClauseSimple *cl) QString field = QString::fromUtf8(cl->getfield().c_str()); switch(cl->getTp()) { - case SCLT_OR: case SCLT_AND: case SCLT_EXCL: + case SCLT_OR: case SCLT_AND: case SCLT_PHRASE: case SCLT_NEAR: if (!field.isEmpty()) { int idx = fldCMB->findText(field); diff --git a/src/query/recollq.cpp b/src/query/recollq.cpp index 22a9da63..d16b3e73 100644 --- a/src/query/recollq.cpp +++ b/src/query/recollq.cpp @@ -168,6 +168,9 @@ int recollq(RclConfig **cfp, int argc, char **argv) Usage(); while (**argv) switch (*(*argv)++) { + case '-': + // -- : end of options + goto endopts; case 'A': op_flags |= OPT_A; break; case 'a': op_flags |= OPT_a; break; case 'b': op_flags |= OPT_b; break; @@ -216,6 +219,7 @@ int recollq(RclConfig **cfp, int argc, char **argv) } b1: argc--; argv++; } +endopts: string reason; *cfp = recollinit(0, 0, reason, &a_config); diff --git a/src/query/wasatorcl.cpp b/src/query/wasatorcl.cpp index a418d265..35edf380 100644 --- a/src/query/wasatorcl.cpp +++ b/src/query/wasatorcl.cpp @@ -195,39 +195,32 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config, // dir filtering special case nclause = new Rcl::SearchDataClausePath((*it)->m_value, (*it)->m_exclude); - } else if ((*it)->m_exclude) { - if (wasa->m_op != WasaQuery::OP_AND) { + } else { + if ((*it)->m_exclude && wasa->m_op != WasaQuery::OP_AND) { LOGERR(("wasaQueryToRcl: excl clause inside OR list!\n")); continue; } - // Note: have to add dquotes which will be translated to - // phrase if there are several words in there. Not pretty - // but should work. If there is actually a single - // word, it will not be taken as a phrase, and - // stem-expansion will work normally - // Have to do this because searchdata has nothing like and_not - nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, - string("\"") + - (*it)->m_value + "\"", - (*it)->m_fieldspec); - } else { // I'm not sure I understand the phrase/near detection // thereafter anymore, maybe it would be better to have an // explicit flag. Mods can only be set after a double // quote. if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) { - Rcl::SClType tp = Rcl::SCLT_PHRASE; - if (mods & WasaQuery::WQM_PROX) { - tp = Rcl::SCLT_NEAR; - } + + Rcl::SClType tp = (mods & WasaQuery::WQM_PROX) ? + Rcl::SCLT_NEAR : + Rcl::SCLT_PHRASE; nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value, (*it)->m_slack, (*it)->m_fieldspec); } else { - nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND, - (*it)->m_value, - (*it)->m_fieldspec); + Rcl::SClType tp = (*it)->m_exclude ? + Rcl::SCLT_OR: + Rcl::SCLT_AND; + nclause = + new Rcl::SearchDataClauseSimple(tp, (*it)->m_value, + (*it)->m_fieldspec); } + nclause->setexclude((*it)->m_exclude); } if (nclause == 0) { diff --git a/src/rcldb/searchdata.cpp b/src/rcldb/searchdata.cpp index 01f2a282..694aab2d 100644 --- a/src/rcldb/searchdata.cpp +++ b/src/rcldb/searchdata.cpp @@ -128,7 +128,7 @@ bool SearchData::clausesToQuery(Rcl::Db &db, SClType tp, // addClause()) Xapian::Query::op op; if (tp == SCLT_AND) { - if ((*it)->m_tp == SCLT_EXCL || (*it)->getexclude()) { + if ((*it)->getexclude()) { op = Xapian::Query::OP_AND_NOT; } else { op = Xapian::Query::OP_AND; @@ -388,7 +388,7 @@ bool SearchData::maybeAddAutoPhrase(Rcl::Db& db, double freqThreshold) // Add clause to current list. OR lists cant have EXCL clauses. bool SearchData::addClause(SearchDataClause* cl) { - if (m_tp == SCLT_OR && (cl->m_tp == SCLT_EXCL || cl->getexclude())) { + if (m_tp == SCLT_OR && cl->getexclude()) { LOGERR(("SearchData::addClause: cant add EXCL to OR list\n")); m_reason = "No Negative (AND_NOT) clauses allowed in OR queries"; return false; @@ -1075,7 +1075,7 @@ bool SearchDataClauseSimple::processUserString(Rcl::Db &db, const string &iq, return true; } -// Translate a simple OR, AND, or EXCL search clause. +// Translate a simple OR or AND search clause. bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p) { LOGDEB2(("SearchDataClauseSimple::toNativeQuery: stemlang [%s]\n", @@ -1087,9 +1087,7 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p) Xapian::Query::op op; switch (m_tp) { case SCLT_AND: op = Xapian::Query::OP_AND; break; - // EXCL will be set with AND_NOT in the list. So it's an OR list here - case SCLT_OR: - case SCLT_EXCL: op = Xapian::Query::OP_OR; break; + case SCLT_OR: op = Xapian::Query::OP_OR; break; default: LOGERR(("SearchDataClauseSimple: bad m_tp %d\n", m_tp)); return false; diff --git a/src/rcldb/searchdata.h b/src/rcldb/searchdata.h index 258a8ca1..b3dc7b80 100644 --- a/src/rcldb/searchdata.h +++ b/src/rcldb/searchdata.h @@ -41,7 +41,7 @@ namespace Rcl { /** Search clause types */ enum SClType { SCLT_AND, - SCLT_OR, SCLT_EXCL, SCLT_FILENAME, SCLT_PHRASE, SCLT_NEAR, SCLT_PATH, + SCLT_OR, SCLT_FILENAME, SCLT_PHRASE, SCLT_NEAR, SCLT_PATH, SCLT_SUB }; @@ -283,6 +283,10 @@ public: { return m_exclude; } + virtual void setexclude(bool onoff) + { + m_exclude = onoff; + } friend class SearchData; protected: diff --git a/src/rcldb/searchdataxml.cpp b/src/rcldb/searchdataxml.cpp index d7841d5b..f2d90641 100644 --- a/src/rcldb/searchdataxml.cpp +++ b/src/rcldb/searchdataxml.cpp @@ -38,7 +38,6 @@ 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"; @@ -65,8 +64,8 @@ string SearchData::asXML() LOGERR(("SearchData::asXML: can't do subclauses !\n")); continue; } - //if (c->getexclude()) - // os << "" << endl; + if (c->getexclude()) + os << "" << endl; if (c->getTp() == SCLT_PATH) { // Keep these apart, for compat with the older history format SearchDataClausePath *cl =