From 57cdece63944e827c15b90ab71791057e7cf3899 Mon Sep 17 00:00:00 2001 From: dockes Date: Sat, 22 Apr 2006 06:27:37 +0000 Subject: [PATCH] turn-off abst. build for fname search (no terms) + prototype query expansion (xapian e-set on chosen doc) + dbl-click in preview adds term to ssearch --- src/qtgui/main.cpp | 13 ++++++---- src/qtgui/preview/preview.ui | 3 +++ src/qtgui/preview/preview.ui.h | 16 ++++++++++++ src/qtgui/rclmain.cpp | 45 +++++++++++++++++++++++++++++----- src/qtgui/rclmain.h | 2 ++ src/qtgui/rclreslist.cpp | 12 +++++++-- src/qtgui/rclreslist.h | 4 ++- src/qtgui/ssearchb.ui | 1 + src/qtgui/ssearchb.ui.h | 4 +++ src/rcldb/rcldb.cpp | 41 +++++++++++++++++++++++-------- src/rcldb/rcldb.h | 15 +++++++++--- src/rcldb/searchdata.h | 6 ++++- 12 files changed, 133 insertions(+), 29 deletions(-) diff --git a/src/qtgui/main.cpp b/src/qtgui/main.cpp index 17cbeb8a..bb1d8313 100644 --- a/src/qtgui/main.cpp +++ b/src/qtgui/main.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: main.cpp,v 1.42 2006-04-19 08:26:08 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: main.cpp,v 1.43 2006-04-22 06:27:37 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -80,11 +80,14 @@ bool maybeOpenDb(string &reason, bool force) return false; } - int qopts = 0; - if (prefs.queryBuildAbstract) + int qopts = Rcl::Db::QO_NONE; + if (prefs.queryBuildAbstract) { qopts |= Rcl::Db::QO_BUILD_ABSTRACT; - if (prefs.queryReplaceAbstract) - qopts |= Rcl::Db::QO_REPLACE_ABSTRACT; + if (prefs.queryReplaceAbstract) + qopts |= Rcl::Db::QO_REPLACE_ABSTRACT; + } + if (prefs.queryStemLang.length() > 0) + qopts |= Rcl::Db::QO_STEM; if (force) rcldb->close(); rcldb->rmQueryDb(""); diff --git a/src/qtgui/preview/preview.ui b/src/qtgui/preview/preview.ui index 9d213b94..8b6c264e 100644 --- a/src/qtgui/preview/preview.ui +++ b/src/qtgui/preview/preview.ui @@ -196,9 +196,11 @@ bool dynSearchActive; bool canBeep; void *tabData; + QWidget *currentW; previewClosed(QWidget *) + wordSelect(QString) searchTextLine_textChanged( const QString & text ) @@ -208,6 +210,7 @@ currentChanged( QWidget * tw ) closeCurrentTab() setCurTabProps( const string & fn, const Rcl::Doc & doc ) + textDoubleClicked(int, int) init() diff --git a/src/qtgui/preview/preview.ui.h b/src/qtgui/preview/preview.ui.h index 3365fe1a..ba09a5c6 100644 --- a/src/qtgui/preview/preview.ui.h +++ b/src/qtgui/preview/preview.ui.h @@ -71,6 +71,7 @@ void Preview::init() canBeep = true; tabData = new list; TABDATA->push_back(TabData(pvTab->currentPage())); + currentW = 0; } void Preview::destroy() @@ -223,6 +224,7 @@ void Preview::prevPressed() void Preview::currentChanged(QWidget * tw) { QWidget *edit = (QWidget *)tw->child("pvEdit"); + currentW = tw; LOGDEB1(("Preview::currentChanged(). Editor: %p\n", edit)); if (edit == 0) { @@ -231,9 +233,23 @@ void Preview::currentChanged(QWidget * tw) tw->installEventFilter(this); edit->installEventFilter(this); edit->setFocus(); + connect(edit, SIGNAL(doubleClicked(int, int)), + this, SLOT(textDoubleClicked(int, int))); } } +void Preview::textDoubleClicked(int, int) +{ + if (!currentW) + return; + QTextEdit *edit = (QTextEdit *)currentW->child("pvEdit"); + if (edit == 0) { + LOGERR(("Editor child not found\n")); + return; + } + if (edit->hasSelectedText()) + emit(wordSelect(edit->selectedText())); +} void Preview::closeCurrentTab() { diff --git a/src/qtgui/rclmain.cpp b/src/qtgui/rclmain.cpp index 5d65f27a..422f2746 100644 --- a/src/qtgui/rclmain.cpp +++ b/src/qtgui/rclmain.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rclmain.cpp,v 1.23 2006-04-20 09:20:09 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rclmain.cpp,v 1.24 2006-04-22 06:27:37 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -95,8 +95,8 @@ void RclMain::init() m_history = new RclDHistory(historyfile); connect(sSearch, SIGNAL(startSearch(Rcl::AdvSearchData)), this, SLOT(startAdvSearch(Rcl::AdvSearchData))); - connect(sSearch, SIGNAL(clearSearch()), - resList, SLOT(resetSearch())); + connect(sSearch, SIGNAL(clearSearch()), resList, SLOT(resetSearch())); + connect(resList, SIGNAL(docExpand(int)), this, SLOT(docExpand(int))); nextPageAction->setIconSet(createIconSet("nextpage.png")); prevPageAction->setIconSet(createIconSet("prevpage.png")); @@ -289,9 +289,16 @@ void RclMain::startAdvSearch(Rcl::AdvSearchData sdata) resList->resetSearch(); - if (!rcldb->setQuery(sdata, prefs.queryStemLang.length() > 0 ? - Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, - prefs.queryStemLang.ascii())) + int qopts = 0; + if (prefs.queryBuildAbstract && !sdata.fileNameOnly()) { + qopts |= Rcl::Db::QO_BUILD_ABSTRACT; + if (prefs.queryReplaceAbstract) + qopts |= Rcl::Db::QO_REPLACE_ABSTRACT; + } + if (!prefs.queryStemLang.length() == 0) + qopts |= Rcl::Db::QO_STEM; + + if (!rcldb->setQuery(sdata, qopts, prefs.queryStemLang.ascii())) return; curPreview = 0; @@ -409,6 +416,8 @@ void RclMain::startPreview(int docnum) curPreview->setCaption(resList->getDescription()); connect(curPreview, SIGNAL(previewClosed(QWidget *)), this, SLOT(previewClosed(QWidget *))); + connect(curPreview, SIGNAL(wordSelect(QString)), + this, SLOT(ssearchAddTerm(QString))); curPreview->show(); } else { if (curPreview->makeDocCurrent(fn, doc)) { @@ -422,6 +431,13 @@ void RclMain::startPreview(int docnum) curPreview->closeCurrentTab(); } +void RclMain::ssearchAddTerm(QString term) +{ + QString text = sSearch->queryText->text(); + text += QString::fromLatin1(" ") + term; + sSearch->queryText->setText(text); +} + void RclMain::startNativeViewer(int docnum) { Rcl::Doc doc; @@ -495,6 +511,23 @@ void RclMain::startManual() startHelpBrowser(); } +void RclMain::docExpand(int docnum) +{ + Rcl::Doc doc; + if (!resList->getDoc(docnum, doc)) + return; + list terms; + terms = rcldb->expand(doc); + QString text = sSearch->queryText->text(); + for (list::iterator it = terms.begin(); it != terms.end(); it++) { + text += QString::fromLatin1(" \"") + + QString::fromUtf8((*it).c_str()) + QString::fromLatin1("\""); + } + sSearch->queryText->setText(text); + sSearch->setAnyTermMode(); + sSearch->startSimpleSearch(); +} + void RclMain::showDocHistory() { LOGDEB(("RclMain::showDocHistory\n")); diff --git a/src/qtgui/rclmain.h b/src/qtgui/rclmain.h index aec4e138..1440a4a7 100644 --- a/src/qtgui/rclmain.h +++ b/src/qtgui/rclmain.h @@ -60,6 +60,8 @@ public slots: virtual void setUIPrefs(); virtual void enableNextPage(bool); virtual void enablePrevPage(bool); + virtual void docExpand(int); + virtual void ssearchAddTerm(QString); protected: Preview *curPreview; advsearch *asearchform; diff --git a/src/qtgui/rclreslist.cpp b/src/qtgui/rclreslist.cpp index 101de7a5..037ae803 100644 --- a/src/qtgui/rclreslist.cpp +++ b/src/qtgui/rclreslist.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rclreslist.cpp,v 1.13 2006-04-20 09:20:09 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rclreslist.cpp,v 1.14 2006-04-22 06:27:37 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #include @@ -294,7 +294,7 @@ void RclResList::showResultPage() if (!doc.fbytes.empty()) fsize = atol(doc.fbytes.c_str()); string sizebuf; - if (dsize >= 0) { + if (dsize > 0) { sizebuf = displayableBytes(dsize); if (fsize > 10 * dsize && fsize - dsize > 1000) sizebuf += string(" / ") + displayableBytes(fsize); @@ -438,6 +438,7 @@ QPopupMenu *RclResList::createPopupMenu(const QPoint& pos) popup->insertItem(tr("&Edit"), this, SLOT(menuEdit())); popup->insertItem(tr("&Copy File Name"), this, SLOT(menuCopyFN())); popup->insertItem(tr("Copy &Url"), this, SLOT(menuCopyURL())); + popup->insertItem(tr("&More like this"), this, SLOT(menuExpand())); return popup; } @@ -467,6 +468,13 @@ void RclResList::menuCopyURL() QClipboard::Selection); } } +void RclResList::menuExpand() +{ + Rcl::Doc doc; + if (rcldb && getDoc(m_docnum, doc)) { + emit docExpand(m_docnum); + } +} QString RclResList::getDescription() { diff --git a/src/qtgui/rclreslist.h b/src/qtgui/rclreslist.h index 9c4c60ea..1ab86296 100644 --- a/src/qtgui/rclreslist.h +++ b/src/qtgui/rclreslist.h @@ -1,6 +1,6 @@ #ifndef _RCLRESLIST_H_INCLUDED_ #define _RCLRESLIST_H_INCLUDED_ -/* @(#$Id: rclreslist.h,v 1.6 2006-04-20 09:20:10 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: rclreslist.h,v 1.7 2006-04-22 06:27:37 dockes Exp $ (C) 2005 J.F.Dockes */ #include #include @@ -33,6 +33,7 @@ class RclResList : public QTextBrowser virtual void menuEdit(); virtual void menuCopyFN(); virtual void menuCopyURL(); + virtual void menuExpand(); signals: void nextPageAvailable(bool); @@ -40,6 +41,7 @@ class RclResList : public QTextBrowser void docEditClicked(int); void docPreviewClicked(int); void headerClicked(); + void docExpand(int); protected: void keyPressEvent(QKeyEvent *e); diff --git a/src/qtgui/ssearchb.ui b/src/qtgui/ssearchb.ui index b84450bc..0c90c12e 100644 --- a/src/qtgui/ssearchb.ui +++ b/src/qtgui/ssearchb.ui @@ -147,6 +147,7 @@ init() completion() event( QEvent * evt ) + setAnyTermMode() diff --git a/src/qtgui/ssearchb.ui.h b/src/qtgui/ssearchb.ui.h index 04b1884a..84c840cd 100644 --- a/src/qtgui/ssearchb.ui.h +++ b/src/qtgui/ssearchb.ui.h @@ -75,6 +75,10 @@ void SSearchBase::startSimpleSearch() emit startSearch(sdata); } +void SSearchBase::setAnyTermMode() +{ + searchTypCMB->setCurrentItem(0); +} // Complete last word in input by querying db for all possible terms. void SSearchBase::completion() diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index 5e254455..fadfa113 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.69 2006-04-19 08:26:08 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.70 2006-04-22 06:27:37 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -128,7 +128,7 @@ class Native { }; Db::Db() - : m_qOpts(0) + : m_qOpts(QO_NONE) { m_ndb = new Native; } @@ -786,7 +786,7 @@ static void stringToXapianQueries(const string &iq, const string& stemlang, Native *m_ndb, list &pqueries, - Db::QueryOpts opts = Db::QO_NONE) + unsigned int opts = Db::QO_NONE) { string qstring = iq; @@ -855,8 +855,7 @@ static void stringToXapianQueries(const string &iq, } // Prepare query out of "advanced search" data -bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, - const string& stemlang) +bool Db::setQuery(AdvSearchData &sdata, int opts, const string& stemlang) { LOGDEB(("Db::setQuery: adv:\n")); LOGDEB((" allwords: %s\n", sdata.allwords.c_str())); @@ -873,6 +872,7 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, LOGDEB((" searched file types: %s\n", ft.c_str())); if (!sdata.topdir.empty()) LOGDEB((" restricted to: %s\n", sdata.topdir.c_str())); + LOGDEB((" Options: 0x%x\n", opts)); m_filterTopDir = sdata.topdir; m_dbindices.clear(); @@ -882,6 +882,8 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, list pqueries; Xapian::Query xq; + m_qOpts = opts; + if (!sdata.filename.empty()) { LOGDEB((" filename search\n")); // File name search, with possible wildcards. @@ -929,7 +931,7 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, } if (!sdata.allwords.empty()) { - stringToXapianQueries(sdata.allwords, stemlang, m_ndb, pqueries, opts); + stringToXapianQueries(sdata.allwords, stemlang, m_ndb, pqueries, m_qOpts); if (!pqueries.empty()) { Xapian::Query nq = Xapian::Query(Xapian::Query::OP_AND, pqueries.begin(), @@ -941,7 +943,7 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, } if (!sdata.orwords.empty()) { - stringToXapianQueries(sdata.orwords, stemlang, m_ndb, pqueries, opts); + stringToXapianQueries(sdata.orwords, stemlang, m_ndb, pqueries, m_qOpts); if (!pqueries.empty()) { Xapian::Query nq = Xapian::Query(Xapian::Query::OP_OR, pqueries.begin(), @@ -953,7 +955,7 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, } if (!sdata.orwords1.empty()) { - stringToXapianQueries(sdata.orwords1, stemlang, m_ndb, pqueries, opts); + stringToXapianQueries(sdata.orwords1, stemlang, m_ndb, pqueries, m_qOpts); if (!pqueries.empty()) { Xapian::Query nq = Xapian::Query(Xapian::Query::OP_OR, pqueries.begin(), @@ -1101,7 +1103,7 @@ bool Native::dbDataToRclDoc(std::string &data, Doc &doc, int qopts, Xapian::docid docid, const list& terms) { - LOGDEB1(("Db::dbDataToRclDoc: data: %s\n", data.c_str())); + LOGDEB1(("Db::dbDataToRclDoc: opts %x data: %s\n", qopts, data.c_str())); ConfSimple parms(&data); if (!parms.ok()) return false; @@ -1118,7 +1120,7 @@ bool Native::dbDataToRclDoc(std::string &data, Doc &doc, doc.abstract = doc.abstract.substr(rclSyntAbs.length()); syntabs = true; } - if ((qopts && Db::QO_BUILD_ABSTRACT) && !terms.empty()) { + if ((qopts & Db::QO_BUILD_ABSTRACT) && !terms.empty()) { LOGDEB1(("dbDataToRclDoc:: building abstract from position data\n")); if (doc.abstract.empty() || syntabs || (qopts & Db::QO_REPLACE_ABSTRACT)) @@ -1127,6 +1129,7 @@ bool Native::dbDataToRclDoc(std::string &data, Doc &doc, parms.get(string("ipath"), doc.ipath); parms.get(string("fbytes"), doc.fbytes); parms.get(string("dbytes"), doc.dbytes); + doc.xdocid = docid; return true; } @@ -1295,6 +1298,24 @@ bool Db::getDoc(const string &fn, const string &ipath, Doc &doc, int *pc) return false; } +list Db::expand(const Doc &doc) +{ + list res; + if (!m_ndb || !m_ndb->enquire) { + LOGERR(("Db::expand: no query opened\n")); + return res; + } + Xapian::RSet rset; + rset.add_document(Xapian::docid(doc.xdocid)); + Xapian::ESet eset = m_ndb->enquire->get_eset(10, rset); + LOGDEB(("ESet terms:\n")); + for (Xapian::ESetIterator it = eset.begin(); it != eset.end(); it++) { + LOGDEB((" [%s]\n", (*it).c_str())); + res.push_back(*it); + } + return res; +} + // Width of a sample extract around a query term // // We build a possibly full size but sparsely populated (only around diff --git a/src/rcldb/rcldb.h b/src/rcldb/rcldb.h index 236ce227..3fdb5a0b 100644 --- a/src/rcldb/rcldb.h +++ b/src/rcldb/rcldb.h @@ -16,7 +16,7 @@ */ #ifndef _DB_H_INCLUDED_ #define _DB_H_INCLUDED_ -/* @(#$Id: rcldb.h,v 1.33 2006-04-19 08:26:08 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: rcldb.h,v 1.34 2006-04-22 06:27:37 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -77,9 +77,11 @@ class Doc { // The following fields don't go to the db record - string text; // text is split and indexed + string text; // During indexing only: text returned by input handler will + // be split and indexed int pc; // used by sortseq, convenience + unsigned long xdocid; // Opaque: rcldb doc identifier. void erase() { url.erase(); @@ -96,6 +98,8 @@ class Doc { dbytes.erase(); text.erase(); + pc = 0; + xdocid = 0; } }; @@ -114,7 +118,7 @@ class Db { enum QueryOpts {QO_NONE=0, QO_STEM = 1, QO_BUILD_ABSTRACT = 2, QO_REPLACE_ABSTRACT = 4}; - bool open(const string &dbdir, OpenMode mode, int qops = 0); + bool open(const string &dbdir, OpenMode mode, int qops = QO_NONE); bool close(); bool isopen(); @@ -130,7 +134,7 @@ class Db { // Query-related functions // Parse query string and initialize query - bool setQuery(AdvSearchData &q, QueryOpts opts = QO_NONE, + bool setQuery(AdvSearchData &q, int opts = QO_NONE, const string& stemlang = "english"); bool getQueryTerms(list& terms); @@ -156,6 +160,9 @@ class Db { /** Get document for given filename and ipath */ bool getDoc(const string &fn, const string &ipath, Doc &doc, int *percent); + /** Expand query */ + list expand(const Doc &doc); + /** Get results count for current query */ int getResCnt(); diff --git a/src/rcldb/searchdata.h b/src/rcldb/searchdata.h index 24afb286..c68c6099 100644 --- a/src/rcldb/searchdata.h +++ b/src/rcldb/searchdata.h @@ -1,6 +1,6 @@ #ifndef _SEARCHDATA_H_INCLUDED_ #define _SEARCHDATA_H_INCLUDED_ -/* @(#$Id: searchdata.h,v 1.1 2006-04-19 08:26:08 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: searchdata.h,v 1.2 2006-04-22 06:27:37 dockes Exp $ (C) 2004 J.F.Dockes */ namespace Rcl { /** @@ -29,6 +29,10 @@ class AdvSearchData { filename.erase(); description.erase(); } + bool fileNameOnly() { + return allwords.empty() && phrase.empty() && orwords.empty() && + orwords1.empty() && nowords.empty(); + } }; }