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();
+ }
};
}