1st version of doc history

This commit is contained in:
dockes 2005-11-25 10:02:36 +00:00
parent 46e82f550a
commit 0667b2fe08
7 changed files with 253 additions and 91 deletions

View File

@ -7,12 +7,13 @@ all: depend $(LIBS)
OBJS = base64.o conftree.o csguess.o debuglog.o \
execmd.o wipedir.o \
fstreewalk.o mh_html.o mh_mail.o mh_exec.o mh_text.o htmlparse.o \
fstreewalk.o mh_html.o mh_mail.o mh_exec.o mh_text.o history.o \
htmlparse.o \
idfile.o indexer.o internfile.o md5.o \
mimehandler.o mimeparse.o mimetype.o myhtmlparse.o pathhash.o pathut.o \
rclconfig.o rcldb.o rclinit.o readfile.o smallut.o \
textsplit.o transcode.o \
unacpp.o unac.o
unacpp.o unac.o docseq.o
SRCS = ../utils/conftree.cpp ../index/csguess.cpp ../utils/debuglog.cpp \
../utils/execmd.cpp ../utils/idfile.cpp ../utils/md5.cpp \
../utils/wipedir.cpp ../utils/fstreewalk.cpp \
@ -24,7 +25,8 @@ SRCS = ../utils/conftree.cpp ../index/csguess.cpp ../utils/debuglog.cpp \
../common/rclconfig.cpp ../common/rcldb.cpp ../common/rclinit.cpp \
../utils/base64.cpp ../utils/readfile.cpp ../utils/smallut.cpp \
../common/textsplit.cpp ../utils/transcode.cpp \
../common/unacpp.cpp ../unac/unac.c
../common/unacpp.cpp ../unac/unac.c ../query/history.cpp \
../query/docseq.cpp
librcl.a : $(OBJS)
ar ru librcl.a $(OBJS)
@ -46,6 +48,10 @@ wipedir.o : ../utils/wipedir.cpp
$(CXX) $(CXXFLAGS) -c $<
fstreewalk.o : ../utils/fstreewalk.cpp
$(CXX) $(CXXFLAGS) -c $<
history.o : ../query/history.cpp
$(CXX) $(CXXFLAGS) -c $<
docseq.o : ../query/docseq.cpp
$(CXX) $(CXXFLAGS) -c $<
mh_html.o : ../common/mh_html.cpp
$(CXX) $(CXXFLAGS) -c $<
mh_exec.o : ../common/mh_exec.cpp

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: main.cpp,v 1.17 2005-11-24 07:16:16 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: main.cpp,v 1.18 2005-11-25 10:02:36 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
#include <unistd.h>
@ -24,6 +24,7 @@ using Rcl::AdvSearchData;
#include "smallut.h"
#include "wipedir.h"
#include "rclinit.h"
#include "history.h"
#include "recollmain.h"
@ -33,12 +34,13 @@ int recollNeedsExit;
string tmpdir;
bool showicons;
string iconsdir;
RclQHistory *history;
void getQueryStemming(bool &dostem, std::string &stemlang)
{
string param;
if (rclconfig->getConfParam("querystemming", param))
dostem = ConfTree::stringToBool(param);
dostem = stringToBool(param);
else
dostem = false;
if (!rclconfig->getConfParam("querystemminglanguage", stemlang))
@ -128,23 +130,8 @@ int main( int argc, char ** argv )
w.resize(s);
#if 0
// Once tried to set a lighter background but this doesn;t seem to work
// (no inheritance from buttons and popups)
QPalette palette = w.palette();
palette.setColor(QColorGroup::Background, QColor(239,239,239));
w.setPalette(palette);
#endif
// Connect exit handlers etc..
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
QTimer *timer = new QTimer(&a);
w.connect(timer, SIGNAL(timeout()), &w, SLOT(periodic100()));
timer->start(100);
string reason;
rclconfig = recollinit(recollCleanup, sigcleanup, reason);
if (!rclconfig || !rclconfig->ok()) {
QString msg = a.translate("Main", "Configuration problem: ");
msg += reason;
@ -177,10 +164,20 @@ int main( int argc, char ** argv )
exit(1);
}
string historyfile = rclconfig->getConfDir();
path_cat(historyfile, "history");
history = new RclQHistory(historyfile);
dbdir = path_tildexpand(dbdir);
rcldb = new Rcl::Db;
// Connect exit handlers etc..
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
QTimer *timer = new QTimer(&a);
w.connect(timer, SIGNAL(timeout()), &w, SLOT(periodic100()));
timer->start(100);
if (!rcldb || !rcldb->open(dbdir, Rcl::Db::DbRO)) {
startindexing = 1;
QMessageBox::information(0, "Recoll",

View File

@ -1,24 +1,27 @@
#ifndef _RECOLL_H_INCLUDED_
#define _RECOLL_H_INCLUDED_
/* @(#$Id: recoll.h,v 1.5 2005-11-16 15:07:20 dockes Exp $ (C) 2004 J.F.Dockes */
/* @(#$Id: recoll.h,v 1.6 2005-11-25 10:02:36 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string>
#include <list>
#include "rclconfig.h"
#include "rcldb.h"
#include "idxthread.h"
#include "history.h"
#include "docseq.h"
// Misc declarations in need of sharing between the UI files
extern void recollCleanup();
extern bool maybeOpenDb(std::string &reason);
extern void getQueryStemming(bool &dostem, std::string &stemlang);
extern bool maybeOpenDb(std::string &reason);
extern RclConfig *rclconfig;
extern Rcl::Db *rcldb;
extern std::string tmpdir;
extern bool showicons;
extern string iconsdir;
extern RclQHistory *history;
extern int recollNeedsExit;
#endif /* _RECOLL_H_INCLUDED_ */

View File

@ -186,6 +186,9 @@
<separator/>
<action name="fileExitAction"/>
</item>
<item text="&amp;Tools" name="Tools">
<action name="toolsDoc_HistoryAction"/>
</item>
<separator/>
<item text="&amp;Help" name="Help">
<separator/>
@ -231,6 +234,17 @@
<string>About Recoll</string>
</property>
</action>
<action>
<property name="name">
<cstring>toolsDoc_HistoryAction</cstring>
</property>
<property name="text">
<string>Doc History</string>
</property>
<property name="menuText">
<string>Doc History</string>
</property>
</action>
</actions>
<connections>
<connection>
@ -299,6 +313,12 @@
<receiver>RecollMain</receiver>
<slot>showAboutDialog()</slot>
</connection>
<connection>
<sender>toolsDoc_HistoryAction</sender>
<signal>activated()</signal>
<receiver>RecollMain</receiver>
<slot>showDocHistory()</slot>
</connection>
</connections>
<includes>
<include location="local" impldecl="in declaration">preview.h</include>
@ -311,14 +331,15 @@
<variable>int reslist_current;</variable>
<variable>bool reslist_mouseDrag;</variable>
<variable>bool reslist_mouseDown;</variable>
<variable>int reslistTE_par;</variable>
<variable>int reslistTE_car;</variable>
<variable>bool reslistTE_waitingdbl;</variable>
<variable>bool reslistTE_dblclck;</variable>
<variable>int reslist_par;</variable>
<variable>int reslist_car;</variable>
<variable>bool reslist_waitingdbl;</variable>
<variable>bool reslist_dblclck;</variable>
<variable>bool dostem;</variable>
<variable>std::string stemlang;</variable>
<variable>Preview *curPreview;</variable>
<variable>advsearch *asearchform;</variable>
<variable>DocSequence *docsource;</variable>
</variables>
<slots>
<slot>fileExit()</slot>
@ -326,6 +347,7 @@
<slot>fileStart_IndexingAction_activated()</slot>
<slot>reslistTE_doubleClicked( int par, int )</slot>
<slot>reslistTE_clicked( int par, int car )</slot>
<slot>reslistTE_delayedclick()</slot>
<slot>queryText_returnPressed()</slot>
<slot>Search_clicked()</slot>
<slot>clearqPB_clicked()</slot>
@ -334,8 +356,8 @@
<slot>previewClosed( Preview * w )</slot>
<slot>advSearchPB_clicked()</slot>
<slot>startAdvSearch( Rcl::AdvSearchData sdata )</slot>
<slot>reslistTE_delayedclick()</slot>
<slot>showAboutDialog()</slot>
<slot>showDocHistory()</slot>
</slots>
<functions>
<function access="private">init()</function>

View File

@ -29,15 +29,12 @@ using std::pair;
#include <qwindowdefs.h>
#include <qapplication.h>
#include "rcldb.h"
#include "rclconfig.h"
#include "recoll.h"
#include "debuglog.h"
#include "mimehandler.h"
#include "pathut.h"
#include "recoll.h"
#include "smallut.h"
#include "plaintorich.h"
#include "unacpp.h"
#include "advsearch.h"
#include "rclversion.h"
@ -53,14 +50,18 @@ static const int respagesize = 8;
void RecollMain::init()
{
reslist_current = -1;
reslist_winfirst = -1;
curPreview = 0;
asearchform = 0;
reslist_current = -1;
reslist_mouseDrag = false;
reslist_mouseDown = false;
reslistTE_waitingdbl = false;
reslistTE_dblclck = false;
reslist_par = -1;
reslist_car = -1;
reslist_waitingdbl = false;
reslist_dblclck = false;
dostem = false;
curPreview = 0;
asearchform = 0;
docsource = 0;
reslistTE->viewport()->installEventFilter(this);
}
@ -158,7 +159,8 @@ static const char *eventTypeToStr(int tp)
}
#endif
// We want to catch ^Q everywhere to mean quit.
// There are a number of events that we want to process. Not sure the
// ^Q thing is necessary (we have an action for this)?
bool RecollMain::eventFilter( QObject * target, QEvent * event )
{
// LOGDEB(("RecollMain::eventFilter target %p, event %s\n", target,
@ -196,6 +198,7 @@ void RecollMain::fileExit()
LOGDEB1(("RecollMain: fileExit\n"));
if (asearchform)
delete asearchform;
// Let the exit handler clean up things
exit(0);
}
@ -241,11 +244,11 @@ static string urltolocalpath(string url)
void RecollMain::reslistTE_doubleClicked(int par, int)
{
LOGDEB(("RecollMain::reslistTE_doubleClicked: par %d\n", par));
reslistTE_dblclck = true;
reslist_dblclck = true;
Rcl::Doc doc;
int reldocnum = par - 1;
if (!rcldb->getDoc(reslist_winfirst + reldocnum, doc, 0))
if (!docsource->getDoc(reslist_winfirst + reldocnum, doc, 0))
return;
// Look for appropriate viewer
@ -258,6 +261,7 @@ void RecollMain::reslistTE_doubleClicked(int par, int)
}
string fn = urltolocalpath(doc.url);
// Substitute %u (url) and %f (file name) inside prototype command
string ncmd;
string::const_iterator it1;
@ -286,6 +290,7 @@ void RecollMain::reslistTE_doubleClicked(int par, int)
stb->repaint(false);
XFlush(qt_xdisplay());
}
history->enterDocument(fn, doc.ipath);
system(ncmd.c_str());
}
@ -296,7 +301,7 @@ void RecollMain::reslistTE_doubleClicked(int par, int)
// check first if this might be a double click
void RecollMain::reslistTE_clicked(int par, int car)
{
if (reslistTE_waitingdbl)
if (reslist_waitingdbl)
return;
LOGDEB(("RecollMain::reslistTE_clckd:winfirst %d par %d char %d drg %d\n",
reslist_winfirst, par, car, reslist_mouseDrag));
@ -304,24 +309,52 @@ void RecollMain::reslistTE_clicked(int par, int car)
return;
// remember par and car
reslistTE_par = par;
reslistTE_car = car;
reslistTE_waitingdbl = true;
reslistTE_dblclck = false;
reslist_par = par;
reslist_car = car;
reslist_waitingdbl = true;
reslist_dblclck = false;
// Wait to see if there's going to be a dblclck
QTimer::singleShot(150, this, SLOT(reslistTE_delayedclick()) );
}
// This gets called by a timer 100mS after a single click in the
// result list. We don't want to start a preview if the user has
// requested a native viewer by double-clicking
void RecollMain::reslistTE_delayedclick()
{
reslist_waitingdbl = false;
if (reslist_dblclck) {
reslist_dblclck = false;
return;
}
int par = reslist_par;
if (reslist_current != -1) {
QColor color("white");
reslistTE->setParagraphBackgroundColor(reslist_current+1, color);
}
QColor color("lightblue");
reslistTE->setParagraphBackgroundColor(par, color);
int reldocnum = par - 1;
if (curPreview && reslist_current == reldocnum)
return;
reslist_current = reldocnum;
startPreview(reslist_winfirst + reldocnum);
}
// User asked to start query. Send it to the db aand call
// listNextPB_clicked to fetch and display the first page of results
void RecollMain::queryText_returnPressed()
{
LOGDEB(("RecollMain::queryText_returnPressed()\n"));
// The db may have been closed at the end of indexing
string reason;
if (!maybeOpenDb(reason)) {
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
return;
exit(1);
}
if (stemlang.empty())
getQueryStemming(dostem, stemlang);
@ -335,6 +368,10 @@ void RecollMain::queryText_returnPressed()
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
return;
curPreview = 0;
if (docsource)
delete docsource;
docsource = new DocSequenceDb(rcldb);
listNextPB_clicked();
}
@ -361,15 +398,13 @@ void RecollMain::listPrevPB_clicked()
// Fill up result list window with next screen of hits
void RecollMain::listNextPB_clicked()
{
if (!rcldb)
if (!docsource)
return;
int percent;
Rcl::Doc doc;
// Need to fetch one document before we can get the result count
rcldb->getDoc(0, doc, &percent);
int resCnt = rcldb->getResCnt();
int resCnt = docsource->getResCnt();
LOGDEB(("listNextPB_clicked: rescnt %d, winfirst %d\n", resCnt,
reslist_winfirst));
@ -392,15 +427,21 @@ void RecollMain::listNextPB_clicked()
for (int i = 0; i < last; i++) {
doc.erase();
if (!rcldb->getDoc(reslist_winfirst + i, doc, &percent)) {
if (!docsource->getDoc(reslist_winfirst + i, doc, &percent)) {
if (i == 0)
reslist_winfirst = -1;
break;
}
if (i == 0) {
reslistTE->append("<qt><head></head><body><p>");
QString line = tr("<p><b>Displaying results starting at index"
" %1 (maximum set size %2)</b><br>")
// We could use a <title> but the textedit doesnt display
// it prominently
reslistTE->append("<qt><head></head><body>");
QString line = "<p><font size=+1><b>";
line += docsource->title().c_str();
line += "</b></font><br>";
reslistTE->append(line);
line = tr("<b>Displaying results starting at index"
" %1 (maximum set size %2)</b></p>")
.arg(reslist_winfirst+1)
.arg(resCnt);
reslistTE->append(line);
@ -512,12 +553,12 @@ void RecollMain::advSearchPB_clicked()
void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
{
LOGDEB(("RecollMain::startAdvSearch\n"));
// The db may have been closed at the end of indexing
string reason;
if (!maybeOpenDb(reason)) {
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
return;
exit(1);
}
if (stemlang.empty())
getQueryStemming(dostem, stemlang);
@ -528,40 +569,13 @@ void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
return;
curPreview = 0;
if (docsource)
delete docsource;
docsource = new DocSequenceDb(rcldb);
listNextPB_clicked();
}
// This gets called by a timer 100mS after a single click in the
// result list. We don't want to start a preview if the user has
// requested a native viewer by double-clicking
void RecollMain::reslistTE_delayedclick()
{
reslistTE_waitingdbl = false;
if (reslistTE_dblclck) {
reslistTE_dblclck = false;
return;
}
int par = reslistTE_par;
if (reslist_current != -1) {
QColor color("white");
reslistTE->setParagraphBackgroundColor(reslist_current+1, color);
}
QColor color("lightblue");
reslistTE->setParagraphBackgroundColor(par, color);
int reldocnum = par - 1;
if (curPreview && reslist_current == reldocnum)
return;
reslist_current = reldocnum;
startPreview(reslist_winfirst + reldocnum);
}
/**
* Open a preview window for a given document, or load it into new tab of
* existing window.
@ -571,7 +585,7 @@ void RecollMain::reslistTE_delayedclick()
void RecollMain::startPreview(int docnum)
{
Rcl::Doc doc;
if (!rcldb->getDoc(docnum, doc, 0)) {
if (!docsource->getDoc(docnum, doc, 0)) {
QMessageBox::warning(0, "Recoll",
tr("Cannot retrieve document info"
" from database"));
@ -609,7 +623,7 @@ void RecollMain::startPreview(int docnum)
}
(void)curPreview->addEditorTab();
}
history->enterDocument(fn, doc.ipath);
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
}
@ -620,3 +634,17 @@ void RecollMain::showAboutDialog()
"<br>" + "http://www.recoll.org";
QMessageBox::information(this, tr("About Recoll"), vstring.c_str());
}
void RecollMain::showDocHistory()
{
LOGDEB(("RecollMain::showDocHistory\n"));
reslist_current = -1;
reslist_winfirst = -1;
curPreview = 0;
if (docsource)
delete docsource;
docsource = new DocSequenceHistory(rcldb, history);
listNextPB_clicked();
}

53
src/query/docseq.cpp Normal file
View File

@ -0,0 +1,53 @@
#ifndef lint
static char rcsid[] = "@(#$Id: docseq.cpp,v 1.1 2005-11-25 10:02:36 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
#include "docseq.h"
bool DocSequenceDb::getDoc(int num, Rcl::Doc &doc, int *percent)
{
return db ? db->getDoc(num, doc, percent) : false;
}
int DocSequenceDb::getResCnt()
{
if (!db)
return -1;
// Need to fetch one document before we can get the result count
Rcl::Doc doc;
int percent;
db->getDoc(0, doc, &percent);
return db->getResCnt();
}
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, int *percent) {
// Retrieve history list
if (!hist)
return false;
if (hlist.empty())
hlist = hist->getDocHistory();
if (num < 0 || num >= (int)hlist.size())
return false;
int skip;
if (prevnum >= 0 && num >= prevnum) {
skip = num - prevnum;
} else {
skip = num;
it = hlist.begin();
}
prevnum = num;
while (skip--)
it++;
if (percent)
*percent = 100;
return db->getDoc((*it).first, (*it).second, doc);
}
int DocSequenceHistory::getResCnt()
{
if (hlist.empty())
hlist = hist->getDocHistory();
return hlist.size();
}

53
src/query/docseq.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef _DOCSEQ_H_INCLUDED_
#define _DOCSEQ_H_INCLUDED_
/* @(#$Id: docseq.h,v 1.1 2005-11-25 10:02:36 dockes Exp $ (C) 2004 J.F.Dockes */
#include "rcldb.h"
#include "history.h"
/** Interface for a list of documents coming from some source.
The result list display data may come from different sources (ie:
history or Db query). We have an interface to make things cleaner.
*/
class DocSequence {
public:
virtual bool getDoc(int num, Rcl::Doc &doc, int *percent) = 0;
virtual int getResCnt() = 0;
virtual std::string title() = 0;
};
/** A DocSequence from a Db query (there should be one active for this
to make sense */
class DocSequenceDb : public DocSequence {
public:
DocSequenceDb(Rcl::Db *d) : db(d) {}
virtual ~DocSequenceDb() {}
virtual bool getDoc(int num, Rcl::Doc &doc, int *percent);
virtual int getResCnt();
virtual std::string title() {return string("Query results");}
private:
Rcl::Db *db;
};
/** A DocSequence coming from the history file */
class DocSequenceHistory : public DocSequence {
public:
DocSequenceHistory(Rcl::Db *d, RclQHistory *h)
: db(d), hist(h), prevnum(-1) {}
virtual ~DocSequenceHistory() {}
virtual bool getDoc(int num, Rcl::Doc &doc, int *percent);
virtual int getResCnt();
virtual std::string title() {return string("Document history");}
private:
Rcl::Db *db;
RclQHistory *hist;
int prevnum;
std::list< std::pair<std::string, std::string> > hlist;
std::list< std::pair<std::string, std::string> >::const_iterator it;
};
#endif /* _DOCSEQ_H_INCLUDED_ */