separated code from design by subclassing recollmain
This commit is contained in:
parent
8513847790
commit
eed200a4bd
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#$Id: main.cpp,v 1.30 2006-01-20 10:01:59 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
static char rcsid[] = "@(#$Id: main.cpp,v 1.31 2006-01-20 12:46:50 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
@ -28,7 +28,7 @@ using Rcl::AdvSearchData;
|
||||
#include "history.h"
|
||||
#include "debuglog.h"
|
||||
|
||||
#include "recollmain.h"
|
||||
#include "rclmain.h"
|
||||
|
||||
static const char *recoll_datadir = RECOLL_DATADIR;
|
||||
|
||||
@ -39,7 +39,7 @@ string tmpdir;
|
||||
string iconsdir;
|
||||
RclDHistory *history;
|
||||
static string dbdir;
|
||||
static RecollMain *mainWindow;
|
||||
static RclMainBase *mainWindow;
|
||||
static string recollsharedir;
|
||||
|
||||
/////////////////////////
|
||||
@ -147,7 +147,7 @@ int main( int argc, char ** argv )
|
||||
rwSettings(false);
|
||||
|
||||
// Create main window and set its size to previous session's
|
||||
RecollMain w;
|
||||
RclMain w;
|
||||
mainWindow = &w;
|
||||
QSize s(prefs_mainwidth, prefs_mainheight);
|
||||
w.resize(s);
|
||||
|
||||
864
src/qtgui/rclmain.cpp
Normal file
864
src/qtgui/rclmain.cpp
Normal file
@ -0,0 +1,864 @@
|
||||
/****************************************************************************
|
||||
** ui.h extension file, included from the uic-generated form implementation.
|
||||
**
|
||||
** If you want to add, delete, or rename functions or slots, use
|
||||
** Qt Designer to update this file, preserving your code.
|
||||
**
|
||||
** You should not define a constructor or destructor in this file.
|
||||
** Instead, write your code in functions called init() and destroy().
|
||||
** These will automatically be called by the form's constructor and
|
||||
** destructor.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <utility>
|
||||
#ifndef NO_NAMESPACES
|
||||
using std::pair;
|
||||
#endif /* NO_NAMESPACES */
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qcstring.h>
|
||||
#include <qtabwidget.h>
|
||||
#include <qtimer.h>
|
||||
#include <qstatusbar.h>
|
||||
#include <qwindowdefs.h>
|
||||
#include <qcheckbox.h>
|
||||
#include <qfontdialog.h>
|
||||
#include <qspinbox.h>
|
||||
#include <qcombobox.h>
|
||||
#include <qtextedit.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qaction.h>
|
||||
#include <qpushbutton.h>
|
||||
#include <qimage.h>
|
||||
|
||||
#include "recoll.h"
|
||||
#include "debuglog.h"
|
||||
#include "mimehandler.h"
|
||||
#include "pathut.h"
|
||||
#include "smallut.h"
|
||||
#include "plaintorich.h"
|
||||
#include "advsearch.h"
|
||||
#include "rclversion.h"
|
||||
#include "sortseq.h"
|
||||
#include "uiprefs.h"
|
||||
|
||||
#include "rclmain.h"
|
||||
#include "moc_rclmain.cpp"
|
||||
|
||||
extern "C" int XFlush(void *);
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(A,B) ((A) < (B) ? (A) : (B))
|
||||
#endif
|
||||
|
||||
void RclMain::init()
|
||||
{
|
||||
reslist_winfirst = -1;
|
||||
reslist_mouseDrag = false;
|
||||
reslist_mouseDown = false;
|
||||
reslist_par = -1;
|
||||
reslist_car = -1;
|
||||
reslist_waitingdbl = false;
|
||||
reslist_dblclck = false;
|
||||
curPreview = 0;
|
||||
asearchform = 0;
|
||||
sortform = 0;
|
||||
docsource = 0;
|
||||
sortwidth = 0;
|
||||
uiprefs = 0;
|
||||
|
||||
// We manage pgup/down, but let ie the arrows for the editor to process
|
||||
reslistTE->installEventFilter(this);
|
||||
reslistTE->viewport()->installEventFilter(this);
|
||||
// reslistTE->viewport()->setFocusPolicy(QWidget::NoFocus);
|
||||
|
||||
// Set the focus to the search terms entry:
|
||||
queryText->setFocus();
|
||||
|
||||
// Set result list font according to user preferences.
|
||||
if (prefs_reslistfontfamily.length()) {
|
||||
QFont nfont(prefs_reslistfontfamily, prefs_reslistfontsize);
|
||||
reslistTE->setFont(nfont);
|
||||
}
|
||||
}
|
||||
|
||||
// We also want to get rid of the advanced search form and previews
|
||||
// when we exit (not our children so that it's not systematically
|
||||
// created over the main form).
|
||||
bool RclMain::close(bool)
|
||||
{
|
||||
fileExit();
|
||||
return false;
|
||||
}
|
||||
|
||||
//#define SHOWEVENTS
|
||||
#if defined(SHOWEVENTS)
|
||||
static const char *eventTypeToStr(int tp)
|
||||
{
|
||||
switch (tp) {
|
||||
case 0: return "None";
|
||||
case 1: return "Timer";
|
||||
case 2: return "MouseButtonPress";
|
||||
case 3: return "MouseButtonRelease";
|
||||
case 4: return "MouseButtonDblClick";
|
||||
case 5: return "MouseMove";
|
||||
case 6: return "KeyPress";
|
||||
case 7: return "KeyRelease";
|
||||
case 8: return "FocusIn";
|
||||
case 9: return "FocusOut";
|
||||
case 10: return "Enter";
|
||||
case 11: return "Leave";
|
||||
case 12: return "Paint";
|
||||
case 13: return "Move";
|
||||
case 14: return "Resize";
|
||||
case 15: return "Create";
|
||||
case 16: return "Destroy";
|
||||
case 17: return "Show";
|
||||
case 18: return "Hide";
|
||||
case 19: return "Close";
|
||||
case 20: return "Quit";
|
||||
case 21: return "Reparent";
|
||||
case 22: return "ShowMinimized";
|
||||
case 23: return "ShowNormal";
|
||||
case 24: return "WindowActivate";
|
||||
case 25: return "WindowDeactivate";
|
||||
case 26: return "ShowToParent";
|
||||
case 27: return "HideToParent";
|
||||
case 28: return "ShowMaximized";
|
||||
case 29: return "ShowFullScreen";
|
||||
case 30: return "Accel";
|
||||
case 31: return "Wheel";
|
||||
case 32: return "AccelAvailable";
|
||||
case 33: return "CaptionChange";
|
||||
case 34: return "IconChange";
|
||||
case 35: return "ParentFontChange";
|
||||
case 36: return "ApplicationFontChange";
|
||||
case 37: return "ParentPaletteChange";
|
||||
case 38: return "ApplicationPaletteChange";
|
||||
case 39: return "PaletteChange";
|
||||
case 40: return "Clipboard";
|
||||
case 42: return "Speech";
|
||||
case 50: return "SockAct";
|
||||
case 51: return "AccelOverride";
|
||||
case 52: return "DeferredDelete";
|
||||
case 60: return "DragEnter";
|
||||
case 61: return "DragMove";
|
||||
case 62: return "DragLeave";
|
||||
case 63: return "Drop";
|
||||
case 64: return "DragResponse";
|
||||
case 70: return "ChildInserted";
|
||||
case 71: return "ChildRemoved";
|
||||
case 72: return "LayoutHint";
|
||||
case 73: return "ShowWindowRequest";
|
||||
case 74: return "WindowBlocked";
|
||||
case 75: return "WindowUnblocked";
|
||||
case 80: return "ActivateControl";
|
||||
case 81: return "DeactivateControl";
|
||||
case 82: return "ContextMenu";
|
||||
case 83: return "IMStart";
|
||||
case 84: return "IMCompose";
|
||||
case 85: return "IMEnd";
|
||||
case 86: return "Accessibility";
|
||||
case 87: return "TabletMove";
|
||||
case 88: return "LocaleChange";
|
||||
case 89: return "LanguageChange";
|
||||
case 90: return "LayoutDirectionChange";
|
||||
case 91: return "Style";
|
||||
case 92: return "TabletPress";
|
||||
case 93: return "TabletRelease";
|
||||
case 94: return "OkRequest";
|
||||
case 95: return "HelpRequest";
|
||||
case 96: return "WindowStateChange";
|
||||
case 97: return "IconDrag";
|
||||
case 1000: return "User";
|
||||
case 65535: return "MaxUser";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 RclMain::eventFilter( QObject * target, QEvent * event )
|
||||
{
|
||||
#if defined(SHOWEVENTS)
|
||||
LOGDEB(("RclMain::eventFilter target %p, event %s\n", target,
|
||||
eventTypeToStr(int(event->type()))));
|
||||
#endif
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = (QKeyEvent *)event;
|
||||
if (keyEvent->key() == Key_Q && (keyEvent->state() & ControlButton)) {
|
||||
recollNeedsExit = 1;
|
||||
} else if (keyEvent->key() == Key_Prior) {
|
||||
resPageUpOrBack();
|
||||
return true;
|
||||
} else if (keyEvent->key() == Key_Next) {
|
||||
resPageDownOrNext();
|
||||
return true;
|
||||
}
|
||||
} else if (target == reslistTE->viewport()) {
|
||||
// We don't want btdown+drag+btup to be a click ! So monitor
|
||||
// mouse events
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
LOGDEB1(("reslistTE: MouseMove\n"));
|
||||
if (reslist_mouseDown)
|
||||
reslist_mouseDrag = true;
|
||||
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||
LOGDEB1(("reslistTE: MouseButtonPress\n"));
|
||||
reslist_mouseDown = true;
|
||||
reslist_mouseDrag = false;
|
||||
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||
LOGDEB1(("reslistTE: MouseButtonRelease\n"));
|
||||
reslist_mouseDown = false;
|
||||
} else if (event->type() == QEvent::MouseButtonDblClick) {
|
||||
LOGDEB1(("reslistTE: MouseButtonDblClick\n"));
|
||||
reslist_mouseDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(target, event);
|
||||
}
|
||||
|
||||
void RclMain::fileExit()
|
||||
{
|
||||
LOGDEB1(("RclMain: fileExit\n"));
|
||||
if (asearchform)
|
||||
delete asearchform;
|
||||
// Let the exit handler clean up things
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// This is called on a 100ms timer checks the status of the indexing
|
||||
// thread and a possible need to exit
|
||||
void RclMain::periodic100()
|
||||
{
|
||||
static int toggle;
|
||||
// Check if indexing thread done
|
||||
if (indexingstatus) {
|
||||
statusBar()->message("");
|
||||
indexingstatus = false;
|
||||
// Make sure we reopen the db to get the results.
|
||||
LOGINFO(("Indexing done: closing query database\n"));
|
||||
rcldb->close();
|
||||
} else if (indexingdone == 0) {
|
||||
if (toggle < 9) {
|
||||
statusBar()->message(tr("Indexing in progress"));
|
||||
} else {
|
||||
statusBar()->message("");
|
||||
}
|
||||
if (toggle >= 10)
|
||||
toggle = 0;
|
||||
toggle++;
|
||||
}
|
||||
if (recollNeedsExit)
|
||||
fileExit();
|
||||
}
|
||||
|
||||
void RclMain::fileStart_IndexingAction_activated()
|
||||
{
|
||||
if (indexingdone == 1)
|
||||
startindexing = 1;
|
||||
}
|
||||
|
||||
// Note that all our 'urls' are like : file://...
|
||||
static string urltolocalpath(string url)
|
||||
{
|
||||
return url.substr(7, string::npos);
|
||||
}
|
||||
|
||||
// Translate paragraph number in list window to doc number. This depends on
|
||||
// how we format the title etc..
|
||||
int RclMain::reldocnumfromparnum(int par)
|
||||
{
|
||||
std::map<int,int>::iterator it = pageParaToReldocnums.find(par);
|
||||
int rdn;
|
||||
if (it != pageParaToReldocnums.end()) {
|
||||
rdn = it->second;
|
||||
} else {
|
||||
rdn = -1;
|
||||
}
|
||||
LOGDEB1(("reldocnumfromparnum: par %d reldoc %d\n", par, rdn));
|
||||
return rdn;
|
||||
}
|
||||
|
||||
// Double click in result list: use external viewer to display file
|
||||
void RclMain::reslistTE_doubleClicked(int par, int)
|
||||
{
|
||||
LOGDEB(("RclMain::reslistTE_doubleClicked: par %d\n", par));
|
||||
reslist_dblclck = true;
|
||||
int reldocnum = reldocnumfromparnum(par);
|
||||
if (reldocnum < 0)
|
||||
return;
|
||||
startNativeViewer(reslist_winfirst + reldocnum);
|
||||
}
|
||||
|
||||
|
||||
// Display preview for the selected document, and highlight entry. The
|
||||
// paragraph number is doc number in window + 1
|
||||
// We don't actually do anything but start a timer because we want to
|
||||
// check first if this might be a double click
|
||||
void RclMain::reslistTE_clicked(int par, int car)
|
||||
{
|
||||
if (reslist_waitingdbl)
|
||||
return;
|
||||
LOGDEB(("RclMain::reslistTE_clicked:wfirst %d par %d char %d drg %d\n",
|
||||
reslist_winfirst, par, car, reslist_mouseDrag));
|
||||
if (reslist_winfirst == -1 || reslist_mouseDrag)
|
||||
return;
|
||||
|
||||
// remember par and car
|
||||
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 RclMain::reslistTE_delayedclick()
|
||||
{
|
||||
LOGDEB(("RclMain::reslistTE_delayedclick:\n"));
|
||||
reslist_waitingdbl = false;
|
||||
if (reslist_dblclck) {
|
||||
LOGDEB1(("RclMain::reslistTE_delayedclick: dbleclick\n"));
|
||||
reslist_dblclck = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int par = reslist_par;
|
||||
|
||||
// Erase everything back to white
|
||||
{
|
||||
QColor color("white");
|
||||
for (int i = 1; i < reslistTE->paragraphs(); i++)
|
||||
reslistTE->setParagraphBackgroundColor(i, color);
|
||||
}
|
||||
|
||||
// Color the new active paragraph
|
||||
QColor color("lightblue");
|
||||
reslistTE->setParagraphBackgroundColor(par, color);
|
||||
|
||||
// Document number
|
||||
int reldocnum = reldocnumfromparnum(par);
|
||||
|
||||
if (reldocnum < 0) {
|
||||
// Bad number: must have clicked on header. Show details of query
|
||||
QString desc = tr("Query details") + ": " +
|
||||
QString::fromUtf8(currentQueryData.description.c_str());
|
||||
QMessageBox::information(this, tr("Query details"), desc);
|
||||
return;
|
||||
} else {
|
||||
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 RclMain::startSimpleSearch()
|
||||
{
|
||||
LOGDEB(("RclMain::queryText_returnPressed()\n"));
|
||||
// The db may have been closed at the end of indexing
|
||||
Rcl::AdvSearchData sdata;
|
||||
|
||||
QCString u8 = queryText->text().utf8();
|
||||
if (allTermsCB->isChecked())
|
||||
sdata.allwords = u8;
|
||||
else
|
||||
sdata.orwords = u8;
|
||||
|
||||
startAdvSearch(sdata);
|
||||
}
|
||||
|
||||
// Execute an advanced search query. The parameters normally come from
|
||||
// the advanced search dialog
|
||||
void RclMain::startAdvSearch(Rcl::AdvSearchData sdata)
|
||||
{
|
||||
LOGDEB(("RclMain::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()));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
reslist_winfirst = -1;
|
||||
|
||||
if (!rcldb->setQuery(sdata, prefs_queryStemLang.length() > 0 ?
|
||||
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE,
|
||||
prefs_queryStemLang.ascii()))
|
||||
return;
|
||||
curPreview = 0;
|
||||
if (docsource)
|
||||
delete docsource;
|
||||
|
||||
if (sortwidth > 0) {
|
||||
DocSequenceDb myseq(rcldb, tr("Query results"));
|
||||
docsource = new DocSeqSorted(myseq, sortwidth, sortspecs,
|
||||
tr("Query results (sorted)"));
|
||||
} else {
|
||||
docsource = new DocSequenceDb(rcldb, tr("Query results"));
|
||||
}
|
||||
currentQueryData = sdata;
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
// Page Up/Down: we don't try to check if current paragraph is last or
|
||||
// first. We just page up/down and check if viewport moved. If it did,
|
||||
// fair enough, else we go to next/previous result page.
|
||||
void RclMain::resPageUpOrBack()
|
||||
{
|
||||
int vpos = reslistTE->contentsY();
|
||||
reslistTE->moveCursor(QTextEdit::MovePgUp, false);
|
||||
if (vpos == reslistTE->contentsY())
|
||||
resultPageBack();
|
||||
}
|
||||
void RclMain::resPageDownOrNext()
|
||||
{
|
||||
int vpos = reslistTE->contentsY();
|
||||
reslistTE->moveCursor(QTextEdit::MovePgDown, false);
|
||||
LOGDEB(("RclMain::resPageDownOrNext: vpos before %d, after %d\n",
|
||||
vpos, reslistTE->contentsY()));
|
||||
if (vpos == reslistTE->contentsY())
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
// Show previous page of results. We just set the current number back
|
||||
// 2 pages and show next page.
|
||||
void RclMain::resultPageBack()
|
||||
{
|
||||
if (reslist_winfirst <= 0)
|
||||
return;
|
||||
reslist_winfirst -= 2 * prefs_respagesize;
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
|
||||
// Fill up result list window with next screen of hits
|
||||
void RclMain::showResultPage()
|
||||
{
|
||||
if (!docsource)
|
||||
return;
|
||||
|
||||
int percent;
|
||||
Rcl::Doc doc;
|
||||
|
||||
int resCnt = docsource->getResCnt();
|
||||
|
||||
LOGDEB(("showResultPage: rescnt %d, winfirst %d\n", resCnt,
|
||||
reslist_winfirst));
|
||||
|
||||
pageParaToReldocnums.clear();
|
||||
|
||||
// If we are already on the last page, nothing to do:
|
||||
if (reslist_winfirst >= 0 &&
|
||||
(reslist_winfirst + prefs_respagesize > resCnt)) {
|
||||
nextPageAction->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reslist_winfirst < 0) {
|
||||
reslist_winfirst = 0;
|
||||
prevPageAction->setEnabled(false);
|
||||
} else {
|
||||
prevPageAction->setEnabled(true);
|
||||
reslist_winfirst += prefs_respagesize;
|
||||
}
|
||||
|
||||
bool gotone = false;
|
||||
reslistTE->clear();
|
||||
|
||||
int last = MIN(resCnt-reslist_winfirst, prefs_respagesize);
|
||||
|
||||
|
||||
// Insert results if any in result list window. We have to send
|
||||
// the text to the widgets, because we need the paragraph number
|
||||
// each time we add a result paragraph (its diffult and
|
||||
// error-prone to compute the paragraph numbers in parallel. We
|
||||
// would like to disable updates while we're doing this, but
|
||||
// couldn't find a way to make it work, the widget seems to become
|
||||
// confused if appended while updates are disabled
|
||||
// reslistTE->setUpdatesEnabled(false);
|
||||
for (int i = 0; i < last; i++) {
|
||||
string sh;
|
||||
doc.erase();
|
||||
|
||||
if (!docsource->getDoc(reslist_winfirst + i, doc, &percent, &sh)) {
|
||||
// This may very well happen for history if the doc has
|
||||
// been removed since. So don't treat it as fatal.
|
||||
doc.abstract = string(tr("Unavailable document").utf8());
|
||||
}
|
||||
if (i == 0) {
|
||||
// Display header
|
||||
// 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>\n")
|
||||
.arg(reslist_winfirst+1)
|
||||
.arg(resCnt);
|
||||
reslistTE->append(line);
|
||||
}
|
||||
|
||||
gotone = true;
|
||||
|
||||
// Result list entry display: this must be exactly one paragraph
|
||||
// TOBEDONE
|
||||
// - move abstract/keywords to Detail window ?
|
||||
// - keywords matched ?
|
||||
// - language ?
|
||||
// - size ?
|
||||
|
||||
string result;
|
||||
if (!sh.empty())
|
||||
result += string("<p><b>") + sh + "</p>\n<p>";
|
||||
else
|
||||
result = "<p>";
|
||||
|
||||
string img_name;
|
||||
if (prefs_showicons) {
|
||||
string iconname = rclconfig->getMimeIconName(doc.mimetype);
|
||||
if (iconname.empty())
|
||||
iconname = "document";
|
||||
string imgfile = iconsdir + "/" + iconname + ".png";
|
||||
|
||||
LOGDEB1(("Img file; %s\n", imgfile.c_str()));
|
||||
QImage image(imgfile.c_str());
|
||||
if (!image.isNull()) {
|
||||
img_name = string("img_") + iconname;
|
||||
QMimeSourceFactory::defaultFactory()->
|
||||
setImage(img_name.c_str(), image);
|
||||
}
|
||||
}
|
||||
|
||||
char perbuf[10];
|
||||
sprintf(perbuf, "%3d%%", percent);
|
||||
if (doc.title.empty())
|
||||
doc.title = path_getsimple(doc.url);
|
||||
char datebuf[100];
|
||||
datebuf[0] = 0;
|
||||
if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
|
||||
time_t mtime = doc.dmtime.empty() ?
|
||||
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
|
||||
struct tm *tm = localtime(&mtime);
|
||||
strftime(datebuf, 99,
|
||||
"<i>Modified:</i> %Y-%m-%d %H:%M:%S", tm);
|
||||
}
|
||||
string abst = escapeHtml(doc.abstract);
|
||||
LOGDEB1(("Abstract: {%s}\n", abst.c_str()));
|
||||
if (!img_name.empty()) {
|
||||
result += "<img source=\"" + img_name + "\" align=\"left\">";
|
||||
}
|
||||
result += string(perbuf) + " <b>" + doc.title + "</b><br>" +
|
||||
doc.mimetype + " " +
|
||||
(datebuf[0] ? string(datebuf) + "<br>" : string("<br>")) +
|
||||
(!abst.empty() ? abst + "<br>" : string("")) +
|
||||
(!doc.keywords.empty() ? doc.keywords + "<br>" : string("")) +
|
||||
"<i>" + doc.url + +"</i><br></p>\n";
|
||||
|
||||
QString str = QString::fromUtf8(result.c_str(), result.length());
|
||||
reslistTE->append(str);
|
||||
|
||||
pageParaToReldocnums[reslistTE->paragraphs()-1] = i;
|
||||
}
|
||||
|
||||
if (gotone) {
|
||||
reslistTE->append("</body></qt>");
|
||||
reslistTE->setCursorPosition(0,0);
|
||||
reslistTE->ensureCursorVisible();
|
||||
} else {
|
||||
// Restore first in win parameter that we shouln't have incremented
|
||||
reslistTE->append(tr("<p>"
|
||||
/*"<img align=\"left\" source=\"myimage\">"*/
|
||||
"<b>No results found</b>"
|
||||
"<br>"));
|
||||
reslist_winfirst -= prefs_respagesize;
|
||||
if (reslist_winfirst < 0)
|
||||
reslist_winfirst = -1;
|
||||
}
|
||||
|
||||
//reslistTE->setUpdatesEnabled(true);reslistTE->sync();reslistTE->repaint();
|
||||
|
||||
#if 0
|
||||
{
|
||||
FILE *fp = fopen("/tmp/reslistdebug", "w");
|
||||
if (fp) {
|
||||
const char *text = (const char *)reslistTE->text().utf8();
|
||||
//const char *text = alltext.c_str();
|
||||
fwrite(text, 1, strlen(text), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (reslist_winfirst < 0 ||
|
||||
(reslist_winfirst >= 0 &&
|
||||
reslist_winfirst + prefs_respagesize >= resCnt)) {
|
||||
nextPageAction->setEnabled(false);
|
||||
} else {
|
||||
nextPageAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// If a preview (toplevel) window gets closed by the user, we need to
|
||||
// clean up because there is no way to reopen it. And check the case
|
||||
// where the current one is closed
|
||||
void RclMain::previewClosed(QWidget *w)
|
||||
{
|
||||
if (w == (QWidget *)curPreview) {
|
||||
LOGDEB(("Active preview closed\n"));
|
||||
curPreview = 0;
|
||||
} else {
|
||||
LOGDEB(("Old preview closed\n"));
|
||||
}
|
||||
delete w;
|
||||
}
|
||||
|
||||
// Open advanced search dialog.
|
||||
void RclMain::showAdvSearchDialog()
|
||||
{
|
||||
if (asearchform == 0) {
|
||||
asearchform = new advsearch(0, tr("Advanced search"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
asearchform->setSizeGripEnabled(FALSE);
|
||||
connect(asearchform, SIGNAL(startSearch(Rcl::AdvSearchData)),
|
||||
this, SLOT(startAdvSearch(Rcl::AdvSearchData)));
|
||||
asearchform->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
asearchform->close();
|
||||
asearchform->show();
|
||||
}
|
||||
}
|
||||
|
||||
void RclMain::showSortDialog()
|
||||
{
|
||||
if (sortform == 0) {
|
||||
sortform = new SortForm(0, tr("Sort criteria"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
sortform->setSizeGripEnabled(FALSE);
|
||||
connect(sortform, SIGNAL(sortDataChanged(int, RclSortSpec)),
|
||||
this, SLOT(sortDataChanged(int, RclSortSpec)));
|
||||
sortform->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
sortform->close();
|
||||
sortform->show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RclMain::showUIPrefs()
|
||||
{
|
||||
if (uiprefs == 0) {
|
||||
uiprefs = new UIPrefsDialog(0, tr("User interface preferences"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
uiprefs->setSizeGripEnabled(FALSE);
|
||||
connect(uiprefs, SIGNAL(uiprefsDone()), this, SLOT(setUIPrefs()));
|
||||
uiprefs->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
uiprefs->close();
|
||||
uiprefs->show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a preview window for a given document, or load it into new tab of
|
||||
* existing window.
|
||||
*
|
||||
* @param docnum db query index
|
||||
*/
|
||||
void RclMain::startPreview(int docnum)
|
||||
{
|
||||
Rcl::Doc doc;
|
||||
if (!docsource->getDoc(docnum, doc, 0)) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("Cannot retrieve document info"
|
||||
" from database"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check file exists in file system
|
||||
string fn = urltolocalpath(doc.url);
|
||||
struct stat st;
|
||||
if (stat(fn.c_str(), &st) < 0) {
|
||||
QMessageBox::warning(0, "Recoll", tr("Cannot access document file: ") +
|
||||
fn.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (curPreview == 0) {
|
||||
curPreview = new Preview(0, tr("Preview"));
|
||||
if (curPreview == 0) {
|
||||
QMessageBox::warning(0, tr("Warning"),
|
||||
tr("Can't create preview window"),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::NoButton);
|
||||
return;
|
||||
}
|
||||
|
||||
curPreview->setCaption(queryText->text());
|
||||
connect(curPreview, SIGNAL(previewClosed(Widget *)),
|
||||
this, SLOT(previewClosed(Widget *)));
|
||||
curPreview->show();
|
||||
} else {
|
||||
if (curPreview->makeDocCurrent(fn, doc)) {
|
||||
// Already there
|
||||
return;
|
||||
}
|
||||
(void)curPreview->addEditorTab();
|
||||
}
|
||||
history->enterDocument(fn, doc.ipath);
|
||||
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
|
||||
}
|
||||
|
||||
void RclMain::startNativeViewer(int docnum)
|
||||
{
|
||||
Rcl::Doc doc;
|
||||
if (!docsource->getDoc(docnum, doc, 0, 0)) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("Cannot retrieve document info"
|
||||
" from database"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for appropriate viewer
|
||||
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
|
||||
if (cmd.length() == 0) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("No external viewer configured for mime type ")
|
||||
+ doc.mimetype.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
string fn = urltolocalpath(doc.url);
|
||||
|
||||
// Substitute %u (url) and %f (file name) inside prototype command
|
||||
string ncmd;
|
||||
string::const_iterator it1;
|
||||
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
|
||||
if (*it1 == '%') {
|
||||
if (++it1 == cmd.end()) {
|
||||
ncmd += '%';
|
||||
break;
|
||||
}
|
||||
if (*it1 == '%')
|
||||
ncmd += '%';
|
||||
if (*it1 == 'u')
|
||||
ncmd += "'" + doc.url + "'";
|
||||
if (*it1 == 'f')
|
||||
ncmd += "'" + fn + "'";
|
||||
} else {
|
||||
ncmd += *it1;
|
||||
}
|
||||
}
|
||||
|
||||
ncmd += " &";
|
||||
QStatusBar *stb = statusBar();
|
||||
if (stb) {
|
||||
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
|
||||
stb->message(msg, 5000);
|
||||
stb->repaint(false);
|
||||
XFlush(qt_xdisplay());
|
||||
}
|
||||
history->enterDocument(fn, doc.ipath);
|
||||
system(ncmd.c_str());
|
||||
}
|
||||
|
||||
|
||||
void RclMain::showAboutDialog()
|
||||
{
|
||||
string vstring = string("Recoll ") + rclversion +
|
||||
"<br>" + "http://www.recoll.org";
|
||||
QMessageBox::information(this, tr("About Recoll"), vstring.c_str());
|
||||
}
|
||||
|
||||
void RclMain::startManual()
|
||||
{
|
||||
startHelpBrowser();
|
||||
}
|
||||
|
||||
void RclMain::showDocHistory()
|
||||
{
|
||||
LOGDEB(("RclMain::showDocHistory\n"));
|
||||
reslist_winfirst = -1;
|
||||
curPreview = 0;
|
||||
if (docsource)
|
||||
delete docsource;
|
||||
|
||||
if (sortwidth > 0) {
|
||||
DocSequenceHistory myseq(rcldb, history, tr("Document history"));
|
||||
docsource = new DocSeqSorted(myseq, sortwidth, sortspecs,
|
||||
tr("Document history (sorted)"));
|
||||
} else {
|
||||
docsource = new DocSequenceHistory(rcldb, history,
|
||||
tr("Document history"));
|
||||
}
|
||||
currentQueryData.erase();
|
||||
currentQueryData.description = tr("History data").utf8();
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
|
||||
void RclMain::searchTextChanged(const QString & text)
|
||||
{
|
||||
if (text.isEmpty()) {
|
||||
searchPB->setEnabled(false);
|
||||
clearqPB->setEnabled(false);
|
||||
} else {
|
||||
searchPB->setEnabled(true);
|
||||
clearqPB->setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RclMain::sortDataChanged(int cnt, RclSortSpec spec)
|
||||
{
|
||||
LOGDEB(("RclMain::sortDataChanged\n"));
|
||||
sortwidth = cnt;
|
||||
sortspecs = spec;
|
||||
}
|
||||
|
||||
// This could be handled inside the dialog's accept(), but we may want to
|
||||
// do something (ie: redisplay reslist?)
|
||||
void RclMain::setUIPrefs()
|
||||
{
|
||||
if (!uiprefs)
|
||||
return;
|
||||
LOGDEB(("Recollmain::setUIPrefs\n"));
|
||||
prefs_showicons = uiprefs->useIconsCB->isChecked();
|
||||
prefs_respagesize = uiprefs->pageLenSB->value();
|
||||
|
||||
prefs_reslistfontfamily = uiprefs->reslistFontFamily;
|
||||
prefs_reslistfontsize = uiprefs->reslistFontSize;
|
||||
if (prefs_reslistfontfamily.length()) {
|
||||
QFont nfont(prefs_reslistfontfamily, prefs_reslistfontsize);
|
||||
reslistTE->setFont(nfont);
|
||||
} else {
|
||||
reslistTE->setFont(this->font());
|
||||
}
|
||||
|
||||
if (uiprefs->stemLangCMB->currentItem() == 0) {
|
||||
prefs_queryStemLang = "";
|
||||
} else {
|
||||
prefs_queryStemLang = uiprefs->stemLangCMB->currentText();
|
||||
}
|
||||
}
|
||||
80
src/qtgui/rclmain.h
Normal file
80
src/qtgui/rclmain.h
Normal file
@ -0,0 +1,80 @@
|
||||
#ifndef RCLMAIN_H
|
||||
#define RCLMAIN_H
|
||||
|
||||
#include <qvariant.h>
|
||||
#include <qmainwindow.h>
|
||||
#include "sortseq.h"
|
||||
#include "preview.h"
|
||||
#include "recoll.h"
|
||||
#include "advsearch.h"
|
||||
#include "sort.h"
|
||||
#include "uiprefs.h"
|
||||
#include "rcldb.h"
|
||||
|
||||
#include "recollmain.h"
|
||||
|
||||
class RclMain : public RclMainBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RclMain(QWidget* parent = 0, const char* name = 0,
|
||||
WFlags fl = WType_TopLevel)
|
||||
: RclMainBase(parent,name,fl) {
|
||||
init();
|
||||
}
|
||||
~RclMain() {}
|
||||
|
||||
virtual bool close( bool );
|
||||
|
||||
public slots:
|
||||
virtual void fileExit();
|
||||
virtual void periodic100();
|
||||
virtual void fileStart_IndexingAction_activated();
|
||||
virtual void reslistTE_doubleClicked( int par, int );
|
||||
virtual void reslistTE_clicked( int par, int car );
|
||||
virtual void reslistTE_delayedclick();
|
||||
virtual void startSimpleSearch();
|
||||
virtual void startAdvSearch( Rcl::AdvSearchData sdata );
|
||||
virtual void resPageUpOrBack();
|
||||
virtual void resPageDownOrNext();
|
||||
virtual void resultPageBack();
|
||||
virtual void showResultPage();
|
||||
virtual void previewClosed( QWidget * w );
|
||||
virtual void showAdvSearchDialog();
|
||||
virtual void showSortDialog();
|
||||
virtual void showAboutDialog();
|
||||
virtual void startManual();
|
||||
virtual void showDocHistory();
|
||||
virtual void searchTextChanged( const QString & text );
|
||||
virtual void sortDataChanged( int cnt, RclSortSpec spec );
|
||||
virtual void showUIPrefs();
|
||||
virtual void setUIPrefs();
|
||||
|
||||
protected:
|
||||
int reslist_winfirst;
|
||||
bool reslist_mouseDrag;
|
||||
bool reslist_mouseDown;
|
||||
int reslist_par;
|
||||
int reslist_car;
|
||||
bool reslist_waitingdbl;
|
||||
bool reslist_dblclck;
|
||||
Preview *curPreview;
|
||||
advsearch *asearchform;
|
||||
Rcl::AdvSearchData currentQueryData;
|
||||
SortForm *sortform;
|
||||
UIPrefsDialog *uiprefs;
|
||||
int sortwidth;
|
||||
RclSortSpec sortspecs;
|
||||
DocSequence *docsource;
|
||||
std::map<int,int> pageParaToReldocnums;
|
||||
|
||||
private:
|
||||
virtual void init();
|
||||
virtual bool eventFilter( QObject * target, QEvent * event );
|
||||
virtual int reldocnumfromparnum( int par );
|
||||
virtual void startPreview( int docnum );
|
||||
virtual void startNativeViewer( int docnum );
|
||||
};
|
||||
|
||||
#endif // RCLMAIN_H
|
||||
@ -4,14 +4,18 @@ LANGUAGE = C++
|
||||
CONFIG += qt warn_on thread release debug
|
||||
|
||||
SOURCES += main.cpp \
|
||||
rclmain.cpp \
|
||||
idxthread.cpp \
|
||||
plaintorich.cpp
|
||||
|
||||
HEADERS = rclmain.h
|
||||
|
||||
FORMS = recollmain.ui \
|
||||
advsearch.ui \
|
||||
preview/preview.ui \
|
||||
sort.ui \
|
||||
uiprefs.ui
|
||||
advsearch.ui \
|
||||
preview/preview.ui \
|
||||
sort.ui \
|
||||
uiprefs.ui
|
||||
|
||||
|
||||
IMAGES = images/filenew \
|
||||
images/fileopen \
|
||||
|
||||
@ -17,10 +17,6 @@
|
||||
<source>Could not open database in </source>
|
||||
<translation>Impossible d'ouvrir la base dans</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>. Starting indexation</source>
|
||||
<translation type="obsolete">. Démarrage de l'indexation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>.
|
||||
Click Cancel if you want to edit the configuration file before indexation starts, or Ok to let it proceed.</source>
|
||||
@ -65,10 +61,6 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<source>Alt+C</source>
|
||||
<translation>Alt+C</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close Tab</source>
|
||||
<translation type="obsolete">Fermer la tabulation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>Effacer</translation>
|
||||
@ -87,75 +79,15 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RecollMain</name>
|
||||
<message>
|
||||
<source>recoll</source>
|
||||
<translation type="obsolete">recoll</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search</source>
|
||||
<translation>Rechercher</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>Effacer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+S</source>
|
||||
<translation>Ctrl+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Previous page</source>
|
||||
<translation>Page précedente</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Next page</source>
|
||||
<translation>Page suivante</translation>
|
||||
</message>
|
||||
<name>RclMain</name>
|
||||
<message>
|
||||
<source>Advanced search</source>
|
||||
<translation>Recherche avancée</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&File</source>
|
||||
<translation>&Fichier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Exit</source>
|
||||
<translation>Quitter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>E&xit</source>
|
||||
<translation>&Quitter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Start Indexing</source>
|
||||
<translation>Commencer l'indexation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Help</source>
|
||||
<translation type="obsolete">Aide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>About Recoll</source>
|
||||
<translation>À propos de Recoll</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Tools</source>
|
||||
<translation>&Outils</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Help</source>
|
||||
<translation>&Aide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+Q</source>
|
||||
<translation type="obsolete">Ctrl+Q</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Doc History</source>
|
||||
<translation type="obsolete">Historique documents</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Indexing in progress</source>
|
||||
<translation>Indexation en cours</translation>
|
||||
@ -168,10 +100,6 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<source>Executing: [</source>
|
||||
<translation>Exécution de: [</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><b>Displaying results starting at index %1 (maximum set size %2)</b></p></source>
|
||||
<translation type="obsolete"><b>Affichage des résultats à partir de l'indice %1 (taille maximum estimée %2)</b></p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot retrieve document info from database</source>
|
||||
<translation>Impossible d'accéder au document dans la base</translation>
|
||||
@ -193,8 +121,93 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<translation>Impossible de créer la fenetre de visualisation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Recoll</source>
|
||||
<translation></translation>
|
||||
<source><b>Displaying results starting at index %1 (maximum set size %2)</b></p>
|
||||
</source>
|
||||
<translation><b>Affichage des résultats à partir de l'index %1 (nombre maximum %2)</b></p>
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort criteria</source>
|
||||
<translation>Critères de tri</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>User interface preferences</source>
|
||||
<translation>Préférences pour l'interface utilisateur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query results</source>
|
||||
<translation>Résultats de la recherche</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query results (sorted)</source>
|
||||
<translation>Résultats de la recherche (triés)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Document history</source>
|
||||
<translation>Historique des documents consultés</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Document history (sorted)</source>
|
||||
<translation>Historique des documents consultés (trié)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query details</source>
|
||||
<translation>Détail de la recherche</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unavailable document</source>
|
||||
<translation>Document inaccessible</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>History data</source>
|
||||
<translation>Données d'historique</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RclMainBase</name>
|
||||
<message>
|
||||
<source>Search</source>
|
||||
<translation>Rechercher</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>Effacer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+S</source>
|
||||
<translation>Ctrl+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Previous page</source>
|
||||
<translation>Page précedente</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Next page</source>
|
||||
<translation>Page suivante</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&File</source>
|
||||
<translation>&Fichier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Exit</source>
|
||||
<translation>Quitter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>E&xit</source>
|
||||
<translation>&Quitter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Start Indexing</source>
|
||||
<translation>Commencer l'indexation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Tools</source>
|
||||
<translation>&Outils</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Help</source>
|
||||
<translation>&Aide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Erase search entry</source>
|
||||
@ -236,10 +249,6 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<source>Result list</source>
|
||||
<translation>Liste de résultats</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Toolbar_2</source>
|
||||
<translation type="obsolete">Toolbar_2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Start &Indexing</source>
|
||||
<translation>Démarrer l'&Indexation</translation>
|
||||
@ -288,20 +297,6 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<source>&Query configuration</source>
|
||||
<translation>Configuration pour la &recherche</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><b>Displaying results starting at index %1 (maximum set size %2)</b></p>
|
||||
</source>
|
||||
<translation><b>Affichage des résultats à partir de l'index %1 (nombre maximum %2)</b></p>
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort criteria</source>
|
||||
<translation>Critères de tri</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>User interface preferences</source>
|
||||
<translation>Préférences pour l'interface utilisateur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>User manual</source>
|
||||
<translation>Manuel</translation>
|
||||
@ -311,32 +306,12 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<translation>&Manuel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query results</source>
|
||||
<translation>Résultats de la recherche</translation>
|
||||
<source>Recoll</source>
|
||||
<translation>Recoll</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query results (sorted)</source>
|
||||
<translation>Résultats de la recherche (triés)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Document history</source>
|
||||
<translation>Historique des documents consultés</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Document history (sorted)</source>
|
||||
<translation>Historique des documents consultés (trié)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Query details</source>
|
||||
<translation>Détail de la recherche</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unavailable document</source>
|
||||
<translation>Document inaccessible</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>History data</source>
|
||||
<translation>Données d'historique</translation>
|
||||
<source>About Recoll</source>
|
||||
<translation>À propos de Recoll</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -463,14 +438,6 @@ Click Cancel if you want to edit the configuration file before indexation starts
|
||||
<source>Searched file types</source>
|
||||
<translation>Type de fichier recherché</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>--------></source>
|
||||
<translation type="obsolete">--------></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><---------</source>
|
||||
<translation type="obsolete"><---------</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ignored file types</source>
|
||||
<translation>Types de fichier ignorés</translation>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
|
||||
<class>RecollMain</class>
|
||||
<class>RclMainBase</class>
|
||||
<widget class="QMainWindow">
|
||||
<property name="name">
|
||||
<cstring>RecollMain</cstring>
|
||||
<cstring>RclMainBase</cstring>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@ -346,61 +346,61 @@
|
||||
<connection>
|
||||
<sender>fileExitAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>fileExit()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>fileStart_IndexingAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>fileStart_IndexingAction_activated()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>searchPB</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>startSimpleSearch()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>queryText</sender>
|
||||
<signal>returnPressed()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>startSimpleSearch()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>reslistTE</sender>
|
||||
<signal>doubleClicked(int,int)</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>reslistTE_doubleClicked(int,int)</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>reslistTE</sender>
|
||||
<signal>clicked(int,int)</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>reslistTE_clicked(int,int)</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>helpAbout_RecollAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showAboutDialog()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>userManualAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>startManual()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>toolsDoc_HistoryAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showDocHistory()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>queryText</sender>
|
||||
<signal>textChanged(const QString&)</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>searchTextChanged(const QString&)</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
@ -412,61 +412,37 @@
|
||||
<connection>
|
||||
<sender>toolsAdvanced_SearchAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showAdvSearchDialog()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>toolsSort_parametersAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showSortDialog()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>prevPageAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>resultPageBack()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>nextPageAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showResultPage()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>preferencesQuery_PrefsAction</sender>
|
||||
<signal>activated()</signal>
|
||||
<receiver>RecollMain</receiver>
|
||||
<receiver>RclMainBase</receiver>
|
||||
<slot>showUIPrefs()</slot>
|
||||
</connection>
|
||||
</connections>
|
||||
<includes>
|
||||
<include location="local" impldecl="in declaration">sortseq.h</include>
|
||||
<include location="local" impldecl="in declaration">preview.h</include>
|
||||
<include location="local" impldecl="in declaration">recoll.h</include>
|
||||
<include location="local" impldecl="in declaration">advsearch.h</include>
|
||||
<include location="local" impldecl="in declaration">sort.h</include>
|
||||
<include location="local" impldecl="in declaration">uiprefs.h</include>
|
||||
<include location="local" impldecl="in declaration">rcldb.h</include>
|
||||
<include location="local" impldecl="in implementation">recollmain.ui.h</include>
|
||||
</includes>
|
||||
<variables>
|
||||
<variable>int reslist_winfirst;</variable>
|
||||
<variable>bool reslist_mouseDrag;</variable>
|
||||
<variable>bool reslist_mouseDown;</variable>
|
||||
<variable>int reslist_par;</variable>
|
||||
<variable>int reslist_car;</variable>
|
||||
<variable>bool reslist_waitingdbl;</variable>
|
||||
<variable>bool reslist_dblclck;</variable>
|
||||
<variable>Preview *curPreview;</variable>
|
||||
<variable>advsearch *asearchform;</variable>
|
||||
<variable>Rcl::AdvSearchData currentQueryData;</variable>
|
||||
<variable>SortForm *sortform;</variable>
|
||||
<variable>UIPrefsDialog *uiprefs;</variable>
|
||||
<variable>int sortwidth;</variable>
|
||||
<variable>RclSortSpec sortspecs;</variable>
|
||||
<variable>DocSequence *docsource;</variable>
|
||||
<variable>std::map<int,int> pageParaToReldocnums;</variable>
|
||||
</variables>
|
||||
<slots>
|
||||
<slot>fileExit()</slot>
|
||||
@ -476,29 +452,21 @@
|
||||
<slot>reslistTE_clicked( int par, int car )</slot>
|
||||
<slot>reslistTE_delayedclick()</slot>
|
||||
<slot>startSimpleSearch()</slot>
|
||||
<slot>startAdvSearch( Rcl::AdvSearchData sdata )</slot>
|
||||
<slot>resPageUpOrBack()</slot>
|
||||
<slot>resPageDownOrNext()</slot>
|
||||
<slot>resultPageBack()</slot>
|
||||
<slot>showResultPage()</slot>
|
||||
<slot>previewClosed( Preview * w )</slot>
|
||||
<slot>previewClosed( QWidget * w )</slot>
|
||||
<slot>showAdvSearchDialog()</slot>
|
||||
<slot>showSortDialog()</slot>
|
||||
<slot>showAboutDialog()</slot>
|
||||
<slot>startManual()</slot>
|
||||
<slot>showDocHistory()</slot>
|
||||
<slot>searchTextChanged( const QString & text )</slot>
|
||||
<slot>sortDataChanged( int cnt, RclSortSpec spec )</slot>
|
||||
<slot>showUIPrefs()</slot>
|
||||
<slot>setUIPrefs()</slot>
|
||||
</slots>
|
||||
<functions>
|
||||
<function access="private">init()</function>
|
||||
<function returnType="bool">close( bool )</function>
|
||||
<function access="private" returnType="bool">eventFilter( QObject * target, QEvent * event )</function>
|
||||
<function access="private" returnType="int">reldocnumfromparnum( int par )</function>
|
||||
<function access="private">startPreview( int docnum )</function>
|
||||
<function access="private">startNativeViewer( int docnum )</function>
|
||||
</functions>
|
||||
<pixmapinproject/>
|
||||
<layoutdefaults spacing="6" margin="11"/>
|
||||
|
||||
@ -9,848 +9,63 @@
|
||||
** These will automatically be called by the form's constructor and
|
||||
** destructor.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <utility>
|
||||
#ifndef NO_NAMESPACES
|
||||
using std::pair;
|
||||
#endif /* NO_NAMESPACES */
|
||||
|
||||
#include <qmessagebox.h>
|
||||
#include <qcstring.h>
|
||||
#include <qtabwidget.h>
|
||||
#include <qtimer.h>
|
||||
#include <qstatusbar.h>
|
||||
#include <qwindowdefs.h>
|
||||
#include <qapplication.h>
|
||||
#include <qcheckbox.h>
|
||||
#include <qfontdialog.h>
|
||||
#include <qspinbox.h>
|
||||
#include <qcombobox.h>
|
||||
|
||||
#include "recoll.h"
|
||||
#include "debuglog.h"
|
||||
#include "mimehandler.h"
|
||||
#include "pathut.h"
|
||||
#include "smallut.h"
|
||||
#include "plaintorich.h"
|
||||
#include "advsearch.h"
|
||||
#include "rclversion.h"
|
||||
#include "sortseq.h"
|
||||
#include "uiprefs.h"
|
||||
|
||||
extern "C" int XFlush(void *);
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(A,B) ((A) < (B) ? (A) : (B))
|
||||
#endif
|
||||
|
||||
void RecollMain::init()
|
||||
void RclMainBase::fileExit()
|
||||
{
|
||||
reslist_winfirst = -1;
|
||||
reslist_mouseDrag = false;
|
||||
reslist_mouseDown = false;
|
||||
reslist_par = -1;
|
||||
reslist_car = -1;
|
||||
reslist_waitingdbl = false;
|
||||
reslist_dblclck = false;
|
||||
curPreview = 0;
|
||||
asearchform = 0;
|
||||
sortform = 0;
|
||||
docsource = 0;
|
||||
sortwidth = 0;
|
||||
uiprefs = 0;
|
||||
|
||||
// We manage pgup/down, but let ie the arrows for the editor to process
|
||||
reslistTE->installEventFilter(this);
|
||||
reslistTE->viewport()->installEventFilter(this);
|
||||
// reslistTE->viewport()->setFocusPolicy(QWidget::NoFocus);
|
||||
|
||||
// Set the focus to the search terms entry:
|
||||
queryText->setFocus();
|
||||
|
||||
// Set result list font according to user preferences.
|
||||
if (prefs_reslistfontfamily.length()) {
|
||||
QFont nfont(prefs_reslistfontfamily, prefs_reslistfontsize);
|
||||
reslistTE->setFont(nfont);
|
||||
}
|
||||
}
|
||||
|
||||
// We also want to get rid of the advanced search form and previews
|
||||
// when we exit (not our children so that it's not systematically
|
||||
// created over the main form).
|
||||
bool RecollMain::close(bool)
|
||||
void RclMainBase::periodic100()
|
||||
{
|
||||
fileExit();
|
||||
return false;
|
||||
}
|
||||
|
||||
//#define SHOWEVENTS
|
||||
#if defined(SHOWEVENTS)
|
||||
static const char *eventTypeToStr(int tp)
|
||||
void RclMainBase::fileStart_IndexingAction_activated()
|
||||
{
|
||||
switch (tp) {
|
||||
case 0: return "None";
|
||||
case 1: return "Timer";
|
||||
case 2: return "MouseButtonPress";
|
||||
case 3: return "MouseButtonRelease";
|
||||
case 4: return "MouseButtonDblClick";
|
||||
case 5: return "MouseMove";
|
||||
case 6: return "KeyPress";
|
||||
case 7: return "KeyRelease";
|
||||
case 8: return "FocusIn";
|
||||
case 9: return "FocusOut";
|
||||
case 10: return "Enter";
|
||||
case 11: return "Leave";
|
||||
case 12: return "Paint";
|
||||
case 13: return "Move";
|
||||
case 14: return "Resize";
|
||||
case 15: return "Create";
|
||||
case 16: return "Destroy";
|
||||
case 17: return "Show";
|
||||
case 18: return "Hide";
|
||||
case 19: return "Close";
|
||||
case 20: return "Quit";
|
||||
case 21: return "Reparent";
|
||||
case 22: return "ShowMinimized";
|
||||
case 23: return "ShowNormal";
|
||||
case 24: return "WindowActivate";
|
||||
case 25: return "WindowDeactivate";
|
||||
case 26: return "ShowToParent";
|
||||
case 27: return "HideToParent";
|
||||
case 28: return "ShowMaximized";
|
||||
case 29: return "ShowFullScreen";
|
||||
case 30: return "Accel";
|
||||
case 31: return "Wheel";
|
||||
case 32: return "AccelAvailable";
|
||||
case 33: return "CaptionChange";
|
||||
case 34: return "IconChange";
|
||||
case 35: return "ParentFontChange";
|
||||
case 36: return "ApplicationFontChange";
|
||||
case 37: return "ParentPaletteChange";
|
||||
case 38: return "ApplicationPaletteChange";
|
||||
case 39: return "PaletteChange";
|
||||
case 40: return "Clipboard";
|
||||
case 42: return "Speech";
|
||||
case 50: return "SockAct";
|
||||
case 51: return "AccelOverride";
|
||||
case 52: return "DeferredDelete";
|
||||
case 60: return "DragEnter";
|
||||
case 61: return "DragMove";
|
||||
case 62: return "DragLeave";
|
||||
case 63: return "Drop";
|
||||
case 64: return "DragResponse";
|
||||
case 70: return "ChildInserted";
|
||||
case 71: return "ChildRemoved";
|
||||
case 72: return "LayoutHint";
|
||||
case 73: return "ShowWindowRequest";
|
||||
case 74: return "WindowBlocked";
|
||||
case 75: return "WindowUnblocked";
|
||||
case 80: return "ActivateControl";
|
||||
case 81: return "DeactivateControl";
|
||||
case 82: return "ContextMenu";
|
||||
case 83: return "IMStart";
|
||||
case 84: return "IMCompose";
|
||||
case 85: return "IMEnd";
|
||||
case 86: return "Accessibility";
|
||||
case 87: return "TabletMove";
|
||||
case 88: return "LocaleChange";
|
||||
case 89: return "LanguageChange";
|
||||
case 90: return "LayoutDirectionChange";
|
||||
case 91: return "Style";
|
||||
case 92: return "TabletPress";
|
||||
case 93: return "TabletRelease";
|
||||
case 94: return "OkRequest";
|
||||
case 95: return "HelpRequest";
|
||||
case 96: return "WindowStateChange";
|
||||
case 97: return "IconDrag";
|
||||
case 1000: return "User";
|
||||
case 65535: return "MaxUser";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 )
|
||||
void RclMainBase::reslistTE_doubleClicked( int , int )
|
||||
{
|
||||
#if defined(SHOWEVENTS)
|
||||
LOGDEB(("RecollMain::eventFilter target %p, event %s\n", target,
|
||||
eventTypeToStr(int(event->type()))));
|
||||
#endif
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = (QKeyEvent *)event;
|
||||
if (keyEvent->key() == Key_Q && (keyEvent->state() & ControlButton)) {
|
||||
recollNeedsExit = 1;
|
||||
} else if (keyEvent->key() == Key_Prior) {
|
||||
resPageUpOrBack();
|
||||
return true;
|
||||
} else if (keyEvent->key() == Key_Next) {
|
||||
resPageDownOrNext();
|
||||
return true;
|
||||
}
|
||||
} else if (target == reslistTE->viewport()) {
|
||||
// We don't want btdown+drag+btup to be a click ! So monitor
|
||||
// mouse events
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
LOGDEB1(("reslistTE: MouseMove\n"));
|
||||
if (reslist_mouseDown)
|
||||
reslist_mouseDrag = true;
|
||||
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||
LOGDEB1(("reslistTE: MouseButtonPress\n"));
|
||||
reslist_mouseDown = true;
|
||||
reslist_mouseDrag = false;
|
||||
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||
LOGDEB1(("reslistTE: MouseButtonRelease\n"));
|
||||
reslist_mouseDown = false;
|
||||
} else if (event->type() == QEvent::MouseButtonDblClick) {
|
||||
LOGDEB1(("reslistTE: MouseButtonDblClick\n"));
|
||||
reslist_mouseDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(target, event);
|
||||
}
|
||||
|
||||
void RecollMain::fileExit()
|
||||
void RclMainBase::reslistTE_clicked( int , int )
|
||||
{
|
||||
LOGDEB1(("RecollMain: fileExit\n"));
|
||||
if (asearchform)
|
||||
delete asearchform;
|
||||
// Let the exit handler clean up things
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// This is called on a 100ms timer checks the status of the indexing
|
||||
// thread and a possible need to exit
|
||||
void RecollMain::periodic100()
|
||||
void RclMainBase::reslistTE_delayedclick()
|
||||
{
|
||||
static int toggle;
|
||||
// Check if indexing thread done
|
||||
if (indexingstatus) {
|
||||
statusBar()->message("");
|
||||
indexingstatus = false;
|
||||
// Make sure we reopen the db to get the results.
|
||||
LOGINFO(("Indexing done: closing query database\n"));
|
||||
rcldb->close();
|
||||
} else if (indexingdone == 0) {
|
||||
if (toggle < 9) {
|
||||
statusBar()->message(tr("Indexing in progress"));
|
||||
} else {
|
||||
statusBar()->message("");
|
||||
}
|
||||
if (toggle >= 10)
|
||||
toggle = 0;
|
||||
toggle++;
|
||||
}
|
||||
if (recollNeedsExit)
|
||||
fileExit();
|
||||
}
|
||||
|
||||
void RecollMain::fileStart_IndexingAction_activated()
|
||||
void RclMainBase::startSimpleSearch()
|
||||
{
|
||||
if (indexingdone == 1)
|
||||
startindexing = 1;
|
||||
}
|
||||
|
||||
// Note that all our 'urls' are like : file://...
|
||||
static string urltolocalpath(string url)
|
||||
void RclMainBase::resPageUpOrBack()
|
||||
{
|
||||
return url.substr(7, string::npos);
|
||||
}
|
||||
|
||||
// Translate paragraph number in list window to doc number. This depends on
|
||||
// how we format the title etc..
|
||||
int RecollMain::reldocnumfromparnum(int par)
|
||||
void RclMainBase::resPageDownOrNext()
|
||||
{
|
||||
std::map<int,int>::iterator it = pageParaToReldocnums.find(par);
|
||||
int rdn;
|
||||
if (it != pageParaToReldocnums.end()) {
|
||||
rdn = it->second;
|
||||
} else {
|
||||
rdn = -1;
|
||||
}
|
||||
LOGDEB1(("reldocnumfromparnum: par %d reldoc %d\n", par, rdn));
|
||||
return rdn;
|
||||
}
|
||||
|
||||
// Double click in result list: use external viewer to display file
|
||||
void RecollMain::reslistTE_doubleClicked(int par, int)
|
||||
void RclMainBase::resultPageBack()
|
||||
{
|
||||
LOGDEB(("RecollMain::reslistTE_doubleClicked: par %d\n", par));
|
||||
reslist_dblclck = true;
|
||||
int reldocnum = reldocnumfromparnum(par);
|
||||
if (reldocnum < 0)
|
||||
return;
|
||||
startNativeViewer(reslist_winfirst + reldocnum);
|
||||
}
|
||||
|
||||
|
||||
// Display preview for the selected document, and highlight entry. The
|
||||
// paragraph number is doc number in window + 1
|
||||
// We don't actually do anything but start a timer because we want to
|
||||
// check first if this might be a double click
|
||||
void RecollMain::reslistTE_clicked(int par, int car)
|
||||
void RclMainBase::showResultPage()
|
||||
{
|
||||
if (reslist_waitingdbl)
|
||||
return;
|
||||
LOGDEB(("RecollMain::reslistTE_clicked:wfirst %d par %d char %d drg %d\n",
|
||||
reslist_winfirst, par, car, reslist_mouseDrag));
|
||||
if (reslist_winfirst == -1 || reslist_mouseDrag)
|
||||
return;
|
||||
|
||||
// remember par and car
|
||||
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()
|
||||
void RclMainBase::previewClosed( QWidget * )
|
||||
{
|
||||
LOGDEB(("RecollMain::reslistTE_delayedclick:\n"));
|
||||
reslist_waitingdbl = false;
|
||||
if (reslist_dblclck) {
|
||||
LOGDEB1(("RecollMain::reslistTE_delayedclick: dbleclick\n"));
|
||||
reslist_dblclck = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int par = reslist_par;
|
||||
|
||||
// Erase everything back to white
|
||||
{
|
||||
QColor color("white");
|
||||
for (int i = 1; i < reslistTE->paragraphs(); i++)
|
||||
reslistTE->setParagraphBackgroundColor(i, color);
|
||||
}
|
||||
|
||||
// Color the new active paragraph
|
||||
QColor color("lightblue");
|
||||
reslistTE->setParagraphBackgroundColor(par, color);
|
||||
|
||||
// Document number
|
||||
int reldocnum = reldocnumfromparnum(par);
|
||||
|
||||
if (reldocnum < 0) {
|
||||
// Bad number: must have clicked on header. Show details of query
|
||||
QString desc = tr("Query details") + ": " +
|
||||
QString::fromUtf8(currentQueryData.description.c_str());
|
||||
QMessageBox::information(this, tr("Query details"), desc);
|
||||
return;
|
||||
} else {
|
||||
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::startSimpleSearch()
|
||||
void RclMainBase::showAdvSearchDialog()
|
||||
{
|
||||
LOGDEB(("RecollMain::queryText_returnPressed()\n"));
|
||||
// The db may have been closed at the end of indexing
|
||||
Rcl::AdvSearchData sdata;
|
||||
|
||||
QCString u8 = queryText->text().utf8();
|
||||
if (allTermsCB->isChecked())
|
||||
sdata.allwords = u8;
|
||||
else
|
||||
sdata.orwords = u8;
|
||||
|
||||
startAdvSearch(sdata);
|
||||
}
|
||||
|
||||
// Execute an advanced search query. The parameters normally come from
|
||||
// the advanced search dialog
|
||||
void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
|
||||
void RclMainBase::showSortDialog()
|
||||
{
|
||||
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()));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
reslist_winfirst = -1;
|
||||
|
||||
if (!rcldb->setQuery(sdata, prefs_queryStemLang.length() > 0 ?
|
||||
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE,
|
||||
prefs_queryStemLang.ascii()))
|
||||
return;
|
||||
curPreview = 0;
|
||||
if (docsource)
|
||||
delete docsource;
|
||||
|
||||
if (sortwidth > 0) {
|
||||
DocSequenceDb myseq(rcldb, tr("Query results"));
|
||||
docsource = new DocSeqSorted(myseq, sortwidth, sortspecs,
|
||||
tr("Query results (sorted)"));
|
||||
} else {
|
||||
docsource = new DocSequenceDb(rcldb, tr("Query results"));
|
||||
}
|
||||
currentQueryData = sdata;
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
// Page Up/Down: we don't try to check if current paragraph is last or
|
||||
// first. We just page up/down and check if viewport moved. If it did,
|
||||
// fair enough, else we go to next/previous result page.
|
||||
void RecollMain::resPageUpOrBack()
|
||||
void RclMainBase::showAboutDialog()
|
||||
{
|
||||
int vpos = reslistTE->contentsY();
|
||||
reslistTE->moveCursor(QTextEdit::MovePgUp, false);
|
||||
if (vpos == reslistTE->contentsY())
|
||||
resultPageBack();
|
||||
}
|
||||
void RecollMain::resPageDownOrNext()
|
||||
void RclMainBase::startManual()
|
||||
{
|
||||
int vpos = reslistTE->contentsY();
|
||||
reslistTE->moveCursor(QTextEdit::MovePgDown, false);
|
||||
LOGDEB(("RecollMain::resPageDownOrNext: vpos before %d, after %d\n",
|
||||
vpos, reslistTE->contentsY()));
|
||||
if (vpos == reslistTE->contentsY())
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
// Show previous page of results. We just set the current number back
|
||||
// 2 pages and show next page.
|
||||
void RecollMain::resultPageBack()
|
||||
void RclMainBase::showDocHistory()
|
||||
{
|
||||
if (reslist_winfirst <= 0)
|
||||
return;
|
||||
reslist_winfirst -= 2 * prefs_respagesize;
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
|
||||
// Fill up result list window with next screen of hits
|
||||
void RecollMain::showResultPage()
|
||||
void RclMainBase::searchTextChanged( const QString & )
|
||||
{
|
||||
if (!docsource)
|
||||
return;
|
||||
|
||||
int percent;
|
||||
Rcl::Doc doc;
|
||||
|
||||
int resCnt = docsource->getResCnt();
|
||||
|
||||
LOGDEB(("showResultPage: rescnt %d, winfirst %d\n", resCnt,
|
||||
reslist_winfirst));
|
||||
|
||||
pageParaToReldocnums.clear();
|
||||
|
||||
// If we are already on the last page, nothing to do:
|
||||
if (reslist_winfirst >= 0 &&
|
||||
(reslist_winfirst + prefs_respagesize > resCnt)) {
|
||||
nextPageAction->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reslist_winfirst < 0) {
|
||||
reslist_winfirst = 0;
|
||||
prevPageAction->setEnabled(false);
|
||||
} else {
|
||||
prevPageAction->setEnabled(true);
|
||||
reslist_winfirst += prefs_respagesize;
|
||||
}
|
||||
|
||||
bool gotone = false;
|
||||
reslistTE->clear();
|
||||
|
||||
int last = MIN(resCnt-reslist_winfirst, prefs_respagesize);
|
||||
|
||||
|
||||
// Insert results if any in result list window. We have to send
|
||||
// the text to the widgets, because we need the paragraph number
|
||||
// each time we add a result paragraph (its diffult and
|
||||
// error-prone to compute the paragraph numbers in parallel. We
|
||||
// would like to disable updates while we're doing this, but
|
||||
// couldn't find a way to make it work, the widget seems to become
|
||||
// confused if appended while updates are disabled
|
||||
// reslistTE->setUpdatesEnabled(false);
|
||||
for (int i = 0; i < last; i++) {
|
||||
string sh;
|
||||
doc.erase();
|
||||
|
||||
if (!docsource->getDoc(reslist_winfirst + i, doc, &percent, &sh)) {
|
||||
// This may very well happen for history if the doc has
|
||||
// been removed since. So don't treat it as fatal.
|
||||
doc.abstract = string(tr("Unavailable document").utf8());
|
||||
}
|
||||
if (i == 0) {
|
||||
// Display header
|
||||
// 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>\n")
|
||||
.arg(reslist_winfirst+1)
|
||||
.arg(resCnt);
|
||||
reslistTE->append(line);
|
||||
}
|
||||
|
||||
gotone = true;
|
||||
|
||||
// Result list entry display: this must be exactly one paragraph
|
||||
// TOBEDONE
|
||||
// - move abstract/keywords to Detail window ?
|
||||
// - keywords matched ?
|
||||
// - language ?
|
||||
// - size ?
|
||||
|
||||
string result;
|
||||
if (!sh.empty())
|
||||
result += string("<p><b>") + sh + "</p>\n<p>";
|
||||
else
|
||||
result = "<p>";
|
||||
|
||||
string img_name;
|
||||
if (prefs_showicons) {
|
||||
string iconname = rclconfig->getMimeIconName(doc.mimetype);
|
||||
if (iconname.empty())
|
||||
iconname = "document";
|
||||
string imgfile = iconsdir + "/" + iconname + ".png";
|
||||
|
||||
LOGDEB1(("Img file; %s\n", imgfile.c_str()));
|
||||
QImage image(imgfile.c_str());
|
||||
if (!image.isNull()) {
|
||||
img_name = string("img_") + iconname;
|
||||
QMimeSourceFactory::defaultFactory()->
|
||||
setImage(img_name.c_str(), image);
|
||||
}
|
||||
}
|
||||
|
||||
char perbuf[10];
|
||||
sprintf(perbuf, "%3d%%", percent);
|
||||
if (doc.title.empty())
|
||||
doc.title = path_getsimple(doc.url);
|
||||
char datebuf[100];
|
||||
datebuf[0] = 0;
|
||||
if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
|
||||
time_t mtime = doc.dmtime.empty() ?
|
||||
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
|
||||
struct tm *tm = localtime(&mtime);
|
||||
strftime(datebuf, 99,
|
||||
"<i>Modified:</i> %Y-%m-%d %H:%M:%S", tm);
|
||||
}
|
||||
string abst = escapeHtml(doc.abstract);
|
||||
LOGDEB1(("Abstract: {%s}\n", abst.c_str()));
|
||||
if (!img_name.empty()) {
|
||||
result += "<img source=\"" + img_name + "\" align=\"left\">";
|
||||
}
|
||||
result += string(perbuf) + " <b>" + doc.title + "</b><br>" +
|
||||
doc.mimetype + " " +
|
||||
(datebuf[0] ? string(datebuf) + "<br>" : string("<br>")) +
|
||||
(!abst.empty() ? abst + "<br>" : string("")) +
|
||||
(!doc.keywords.empty() ? doc.keywords + "<br>" : string("")) +
|
||||
"<i>" + doc.url + +"</i><br></p>\n";
|
||||
|
||||
QString str = QString::fromUtf8(result.c_str(), result.length());
|
||||
reslistTE->append(str);
|
||||
|
||||
pageParaToReldocnums[reslistTE->paragraphs()-1] = i;
|
||||
}
|
||||
|
||||
if (gotone) {
|
||||
reslistTE->append("</body></qt>");
|
||||
reslistTE->setCursorPosition(0,0);
|
||||
reslistTE->ensureCursorVisible();
|
||||
} else {
|
||||
// Restore first in win parameter that we shouln't have incremented
|
||||
reslistTE->append(tr("<p>"
|
||||
/*"<img align=\"left\" source=\"myimage\">"*/
|
||||
"<b>No results found</b>"
|
||||
"<br>"));
|
||||
reslist_winfirst -= prefs_respagesize;
|
||||
if (reslist_winfirst < 0)
|
||||
reslist_winfirst = -1;
|
||||
}
|
||||
|
||||
//reslistTE->setUpdatesEnabled(true);reslistTE->sync();reslistTE->repaint();
|
||||
|
||||
#if 0
|
||||
{
|
||||
FILE *fp = fopen("/tmp/reslistdebug", "w");
|
||||
if (fp) {
|
||||
const char *text = (const char *)reslistTE->text().utf8();
|
||||
//const char *text = alltext.c_str();
|
||||
fwrite(text, 1, strlen(text), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (reslist_winfirst < 0 ||
|
||||
(reslist_winfirst >= 0 &&
|
||||
reslist_winfirst + prefs_respagesize >= resCnt)) {
|
||||
nextPageAction->setEnabled(false);
|
||||
} else {
|
||||
nextPageAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// If a preview (toplevel) window gets closed by the user, we need to
|
||||
// clean up because there is no way to reopen it. And check the case
|
||||
// where the current one is closed
|
||||
void RecollMain::previewClosed(Preview *w)
|
||||
void RclMainBase::showUIPrefs()
|
||||
{
|
||||
if (w == curPreview) {
|
||||
LOGDEB(("Active preview closed\n"));
|
||||
curPreview = 0;
|
||||
} else {
|
||||
LOGDEB(("Old preview closed\n"));
|
||||
}
|
||||
delete w;
|
||||
}
|
||||
|
||||
// Open advanced search dialog.
|
||||
void RecollMain::showAdvSearchDialog()
|
||||
void RclMainBase::setUIPrefs()
|
||||
{
|
||||
if (asearchform == 0) {
|
||||
asearchform = new advsearch(0, tr("Advanced search"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
asearchform->setSizeGripEnabled(FALSE);
|
||||
connect(asearchform, SIGNAL(startSearch(Rcl::AdvSearchData)),
|
||||
this, SLOT(startAdvSearch(Rcl::AdvSearchData)));
|
||||
asearchform->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
asearchform->close();
|
||||
asearchform->show();
|
||||
}
|
||||
}
|
||||
|
||||
void RecollMain::showSortDialog()
|
||||
{
|
||||
if (sortform == 0) {
|
||||
sortform = new SortForm(0, tr("Sort criteria"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
sortform->setSizeGripEnabled(FALSE);
|
||||
connect(sortform, SIGNAL(sortDataChanged(int, RclSortSpec)),
|
||||
this, SLOT(sortDataChanged(int, RclSortSpec)));
|
||||
sortform->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
sortform->close();
|
||||
sortform->show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RecollMain::showUIPrefs()
|
||||
{
|
||||
if (uiprefs == 0) {
|
||||
uiprefs = new UIPrefsDialog(0, tr("User interface preferences"), FALSE,
|
||||
WStyle_Customize | WStyle_NormalBorder |
|
||||
WStyle_Title | WStyle_SysMenu);
|
||||
uiprefs->setSizeGripEnabled(FALSE);
|
||||
connect(uiprefs, SIGNAL(uiprefsDone()), this, SLOT(setUIPrefs()));
|
||||
uiprefs->show();
|
||||
} else {
|
||||
// Close and reopen, in hope that makes us visible...
|
||||
uiprefs->close();
|
||||
uiprefs->show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a preview window for a given document, or load it into new tab of
|
||||
* existing window.
|
||||
*
|
||||
* @param docnum db query index
|
||||
*/
|
||||
void RecollMain::startPreview(int docnum)
|
||||
{
|
||||
Rcl::Doc doc;
|
||||
if (!docsource->getDoc(docnum, doc, 0)) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("Cannot retrieve document info"
|
||||
" from database"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check file exists in file system
|
||||
string fn = urltolocalpath(doc.url);
|
||||
struct stat st;
|
||||
if (stat(fn.c_str(), &st) < 0) {
|
||||
QMessageBox::warning(0, "Recoll", tr("Cannot access document file: ") +
|
||||
fn.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (curPreview == 0) {
|
||||
curPreview = new Preview(0, tr("Preview"));
|
||||
if (curPreview == 0) {
|
||||
QMessageBox::warning(0, tr("Warning"),
|
||||
tr("Can't create preview window"),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::NoButton);
|
||||
return;
|
||||
}
|
||||
|
||||
curPreview->setCaption(queryText->text());
|
||||
connect(curPreview, SIGNAL(previewClosed(Preview *)),
|
||||
this, SLOT(previewClosed(Preview *)));
|
||||
curPreview->show();
|
||||
} else {
|
||||
if (curPreview->makeDocCurrent(fn, doc)) {
|
||||
// Already there
|
||||
return;
|
||||
}
|
||||
(void)curPreview->addEditorTab();
|
||||
}
|
||||
history->enterDocument(fn, doc.ipath);
|
||||
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
|
||||
}
|
||||
|
||||
void RecollMain::startNativeViewer(int docnum)
|
||||
{
|
||||
Rcl::Doc doc;
|
||||
if (!docsource->getDoc(docnum, doc, 0, 0)) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("Cannot retrieve document info"
|
||||
" from database"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for appropriate viewer
|
||||
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
|
||||
if (cmd.length() == 0) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("No external viewer configured for mime type ")
|
||||
+ doc.mimetype.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
string fn = urltolocalpath(doc.url);
|
||||
|
||||
// Substitute %u (url) and %f (file name) inside prototype command
|
||||
string ncmd;
|
||||
string::const_iterator it1;
|
||||
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
|
||||
if (*it1 == '%') {
|
||||
if (++it1 == cmd.end()) {
|
||||
ncmd += '%';
|
||||
break;
|
||||
}
|
||||
if (*it1 == '%')
|
||||
ncmd += '%';
|
||||
if (*it1 == 'u')
|
||||
ncmd += "'" + doc.url + "'";
|
||||
if (*it1 == 'f')
|
||||
ncmd += "'" + fn + "'";
|
||||
} else {
|
||||
ncmd += *it1;
|
||||
}
|
||||
}
|
||||
|
||||
ncmd += " &";
|
||||
QStatusBar *stb = statusBar();
|
||||
if (stb) {
|
||||
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
|
||||
stb->message(msg, 5000);
|
||||
stb->repaint(false);
|
||||
XFlush(qt_xdisplay());
|
||||
}
|
||||
history->enterDocument(fn, doc.ipath);
|
||||
system(ncmd.c_str());
|
||||
}
|
||||
|
||||
|
||||
void RecollMain::showAboutDialog()
|
||||
{
|
||||
string vstring = string("Recoll ") + rclversion +
|
||||
"<br>" + "http://www.recoll.org";
|
||||
QMessageBox::information(this, tr("About Recoll"), vstring.c_str());
|
||||
}
|
||||
|
||||
void RecollMain::startManual()
|
||||
{
|
||||
startHelpBrowser();
|
||||
}
|
||||
|
||||
void RecollMain::showDocHistory()
|
||||
{
|
||||
LOGDEB(("RecollMain::showDocHistory\n"));
|
||||
reslist_winfirst = -1;
|
||||
curPreview = 0;
|
||||
if (docsource)
|
||||
delete docsource;
|
||||
|
||||
if (sortwidth > 0) {
|
||||
DocSequenceHistory myseq(rcldb, history, tr("Document history"));
|
||||
docsource = new DocSeqSorted(myseq, sortwidth, sortspecs,
|
||||
tr("Document history (sorted)"));
|
||||
} else {
|
||||
docsource = new DocSequenceHistory(rcldb, history,
|
||||
tr("Document history"));
|
||||
}
|
||||
currentQueryData.erase();
|
||||
currentQueryData.description = tr("History data").utf8();
|
||||
showResultPage();
|
||||
}
|
||||
|
||||
|
||||
void RecollMain::searchTextChanged(const QString & text)
|
||||
{
|
||||
if (text.isEmpty()) {
|
||||
searchPB->setEnabled(false);
|
||||
clearqPB->setEnabled(false);
|
||||
} else {
|
||||
searchPB->setEnabled(true);
|
||||
clearqPB->setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RecollMain::sortDataChanged(int cnt, RclSortSpec spec)
|
||||
{
|
||||
LOGDEB(("RecollMain::sortDataChanged\n"));
|
||||
sortwidth = cnt;
|
||||
sortspecs = spec;
|
||||
}
|
||||
|
||||
// This could be handled inside the dialog's accept(), but we may want to
|
||||
// do something (ie: redisplay reslist?)
|
||||
void RecollMain::setUIPrefs()
|
||||
{
|
||||
if (!uiprefs)
|
||||
return;
|
||||
LOGDEB(("Recollmain::setUIPrefs\n"));
|
||||
prefs_showicons = uiprefs->useIconsCB->isChecked();
|
||||
prefs_respagesize = uiprefs->pageLenSB->value();
|
||||
|
||||
prefs_reslistfontfamily = uiprefs->reslistFontFamily;
|
||||
prefs_reslistfontsize = uiprefs->reslistFontSize;
|
||||
if (prefs_reslistfontfamily.length()) {
|
||||
QFont nfont(prefs_reslistfontfamily, prefs_reslistfontsize);
|
||||
reslistTE->setFont(nfont);
|
||||
} else {
|
||||
reslistTE->setFont(this->font());
|
||||
}
|
||||
|
||||
if (uiprefs->stemLangCMB->currentItem() == 0) {
|
||||
prefs_queryStemLang = "";
|
||||
} else {
|
||||
prefs_queryStemLang = uiprefs->stemLangCMB->currentText();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user