|
a/src/qtgui/recollmain.ui.h |
|
b/src/qtgui/recollmain.ui.h |
|
... |
|
... |
27 |
#include <qtimer.h>
|
27 |
#include <qtimer.h>
|
28 |
#include <qstatusbar.h>
|
28 |
#include <qstatusbar.h>
|
29 |
#include <qwindowdefs.h>
|
29 |
#include <qwindowdefs.h>
|
30 |
#include <qapplication.h>
|
30 |
#include <qapplication.h>
|
31 |
|
31 |
|
32 |
#include "rcldb.h"
|
32 |
#include "recoll.h"
|
33 |
#include "rclconfig.h"
|
|
|
34 |
#include "debuglog.h"
|
33 |
#include "debuglog.h"
|
35 |
#include "mimehandler.h"
|
34 |
#include "mimehandler.h"
|
36 |
#include "pathut.h"
|
35 |
#include "pathut.h"
|
37 |
#include "recoll.h"
|
|
|
38 |
#include "smallut.h"
|
36 |
#include "smallut.h"
|
39 |
#include "plaintorich.h"
|
37 |
#include "plaintorich.h"
|
40 |
#include "unacpp.h"
|
|
|
41 |
#include "advsearch.h"
|
38 |
#include "advsearch.h"
|
42 |
#include "rclversion.h"
|
39 |
#include "rclversion.h"
|
43 |
|
40 |
|
44 |
extern "C" int XFlush(void *);
|
41 |
extern "C" int XFlush(void *);
|
45 |
|
42 |
|
|
... |
|
... |
51 |
// with the default window size and font, most of the time.
|
48 |
// with the default window size and font, most of the time.
|
52 |
static const int respagesize = 8;
|
49 |
static const int respagesize = 8;
|
53 |
|
50 |
|
54 |
void RecollMain::init()
|
51 |
void RecollMain::init()
|
55 |
{
|
52 |
{
|
|
|
53 |
reslist_winfirst = -1;
|
56 |
reslist_current = -1;
|
54 |
reslist_current = -1;
|
|
|
55 |
reslist_mouseDrag = false;
|
|
|
56 |
reslist_mouseDown = false;
|
57 |
reslist_winfirst = -1;
|
57 |
reslist_par = -1;
|
|
|
58 |
reslist_car = -1;
|
|
|
59 |
reslist_waitingdbl = false;
|
|
|
60 |
reslist_dblclck = false;
|
|
|
61 |
dostem = false;
|
58 |
curPreview = 0;
|
62 |
curPreview = 0;
|
59 |
asearchform = 0;
|
63 |
asearchform = 0;
|
60 |
reslist_mouseDrag = false;
|
64 |
docsource = 0;
|
61 |
reslist_mouseDown = false;
|
|
|
62 |
reslistTE_waitingdbl = false;
|
|
|
63 |
reslistTE_dblclck = false;
|
|
|
64 |
reslistTE->viewport()->installEventFilter(this);
|
65 |
reslistTE->viewport()->installEventFilter(this);
|
65 |
}
|
66 |
}
|
66 |
|
67 |
|
67 |
// We also want to get rid of the advanced search form and previews
|
68 |
// We also want to get rid of the advanced search form and previews
|
68 |
// when we exit (not our children so that it's not systematically
|
69 |
// when we exit (not our children so that it's not systematically
|
|
... |
|
... |
156 |
default: return "Unknown";
|
157 |
default: return "Unknown";
|
157 |
}
|
158 |
}
|
158 |
}
|
159 |
}
|
159 |
#endif
|
160 |
#endif
|
160 |
|
161 |
|
161 |
// We want to catch ^Q everywhere to mean quit.
|
162 |
// There are a number of events that we want to process. Not sure the
|
|
|
163 |
// ^Q thing is necessary (we have an action for this)?
|
162 |
bool RecollMain::eventFilter( QObject * target, QEvent * event )
|
164 |
bool RecollMain::eventFilter( QObject * target, QEvent * event )
|
163 |
{
|
165 |
{
|
164 |
// LOGDEB(("RecollMain::eventFilter target %p, event %s\n", target,
|
166 |
// LOGDEB(("RecollMain::eventFilter target %p, event %s\n", target,
|
165 |
// eventTypeToStr(int(event->type()))));
|
167 |
// eventTypeToStr(int(event->type()))));
|
166 |
if (event->type() == QEvent::KeyPress) {
|
168 |
if (event->type() == QEvent::KeyPress) {
|
|
... |
|
... |
194 |
void RecollMain::fileExit()
|
196 |
void RecollMain::fileExit()
|
195 |
{
|
197 |
{
|
196 |
LOGDEB1(("RecollMain: fileExit\n"));
|
198 |
LOGDEB1(("RecollMain: fileExit\n"));
|
197 |
if (asearchform)
|
199 |
if (asearchform)
|
198 |
delete asearchform;
|
200 |
delete asearchform;
|
|
|
201 |
// Let the exit handler clean up things
|
199 |
exit(0);
|
202 |
exit(0);
|
200 |
}
|
203 |
}
|
201 |
|
204 |
|
202 |
// This is called on a 100ms timer checks the status of the indexing
|
205 |
// This is called on a 100ms timer checks the status of the indexing
|
203 |
// thread and a possible need to exit
|
206 |
// thread and a possible need to exit
|
|
... |
|
... |
239 |
|
242 |
|
240 |
// Double click in result list: use external viewer to display file
|
243 |
// Double click in result list: use external viewer to display file
|
241 |
void RecollMain::reslistTE_doubleClicked(int par, int)
|
244 |
void RecollMain::reslistTE_doubleClicked(int par, int)
|
242 |
{
|
245 |
{
|
243 |
LOGDEB(("RecollMain::reslistTE_doubleClicked: par %d\n", par));
|
246 |
LOGDEB(("RecollMain::reslistTE_doubleClicked: par %d\n", par));
|
244 |
reslistTE_dblclck = true;
|
247 |
reslist_dblclck = true;
|
245 |
|
248 |
|
246 |
Rcl::Doc doc;
|
249 |
Rcl::Doc doc;
|
247 |
int reldocnum = par - 1;
|
250 |
int reldocnum = par - 1;
|
248 |
if (!rcldb->getDoc(reslist_winfirst + reldocnum, doc, 0))
|
251 |
if (!docsource->getDoc(reslist_winfirst + reldocnum, doc, 0))
|
249 |
return;
|
252 |
return;
|
250 |
|
253 |
|
251 |
// Look for appropriate viewer
|
254 |
// Look for appropriate viewer
|
252 |
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
|
255 |
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
|
253 |
if (cmd.length() == 0) {
|
256 |
if (cmd.length() == 0) {
|
|
... |
|
... |
256 |
+ doc.mimetype.c_str());
|
259 |
+ doc.mimetype.c_str());
|
257 |
return;
|
260 |
return;
|
258 |
}
|
261 |
}
|
259 |
|
262 |
|
260 |
string fn = urltolocalpath(doc.url);
|
263 |
string fn = urltolocalpath(doc.url);
|
|
|
264 |
|
261 |
// Substitute %u (url) and %f (file name) inside prototype command
|
265 |
// Substitute %u (url) and %f (file name) inside prototype command
|
262 |
string ncmd;
|
266 |
string ncmd;
|
263 |
string::const_iterator it1;
|
267 |
string::const_iterator it1;
|
264 |
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
|
268 |
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
|
265 |
if (*it1 == '%') {
|
269 |
if (*it1 == '%') {
|
|
... |
|
... |
284 |
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
|
288 |
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
|
285 |
stb->message(msg, 5000);
|
289 |
stb->message(msg, 5000);
|
286 |
stb->repaint(false);
|
290 |
stb->repaint(false);
|
287 |
XFlush(qt_xdisplay());
|
291 |
XFlush(qt_xdisplay());
|
288 |
}
|
292 |
}
|
|
|
293 |
history->enterDocument(fn, doc.ipath);
|
289 |
system(ncmd.c_str());
|
294 |
system(ncmd.c_str());
|
290 |
}
|
295 |
}
|
291 |
|
296 |
|
292 |
|
297 |
|
293 |
// Display preview for the selected document, and highlight entry. The
|
298 |
// Display preview for the selected document, and highlight entry. The
|
294 |
// paragraph number is doc number in window + 1
|
299 |
// paragraph number is doc number in window + 1
|
295 |
// We don't actually do anything but start a timer because we want to
|
300 |
// We don't actually do anything but start a timer because we want to
|
296 |
// check first if this might be a double click
|
301 |
// check first if this might be a double click
|
297 |
void RecollMain::reslistTE_clicked(int par, int car)
|
302 |
void RecollMain::reslistTE_clicked(int par, int car)
|
298 |
{
|
303 |
{
|
299 |
if (reslistTE_waitingdbl)
|
304 |
if (reslist_waitingdbl)
|
300 |
return;
|
305 |
return;
|
301 |
LOGDEB(("RecollMain::reslistTE_clckd:winfirst %d par %d char %d drg %d\n",
|
306 |
LOGDEB(("RecollMain::reslistTE_clckd:winfirst %d par %d char %d drg %d\n",
|
302 |
reslist_winfirst, par, car, reslist_mouseDrag));
|
307 |
reslist_winfirst, par, car, reslist_mouseDrag));
|
303 |
if (reslist_winfirst == -1 || reslist_mouseDrag)
|
308 |
if (reslist_winfirst == -1 || reslist_mouseDrag)
|
304 |
return;
|
309 |
return;
|
305 |
|
310 |
|
306 |
// remember par and car
|
311 |
// remember par and car
|
307 |
reslistTE_par = par;
|
312 |
reslist_par = par;
|
308 |
reslistTE_car = car;
|
313 |
reslist_car = car;
|
309 |
reslistTE_waitingdbl = true;
|
314 |
reslist_waitingdbl = true;
|
310 |
reslistTE_dblclck = false;
|
315 |
reslist_dblclck = false;
|
311 |
// Wait to see if there's going to be a dblclck
|
316 |
// Wait to see if there's going to be a dblclck
|
312 |
QTimer::singleShot(150, this, SLOT(reslistTE_delayedclick()) );
|
317 |
QTimer::singleShot(150, this, SLOT(reslistTE_delayedclick()) );
|
313 |
}
|
318 |
}
|
314 |
|
319 |
|
|
|
320 |
// This gets called by a timer 100mS after a single click in the
|
|
|
321 |
// result list. We don't want to start a preview if the user has
|
|
|
322 |
// requested a native viewer by double-clicking
|
|
|
323 |
void RecollMain::reslistTE_delayedclick()
|
|
|
324 |
{
|
|
|
325 |
reslist_waitingdbl = false;
|
|
|
326 |
if (reslist_dblclck) {
|
|
|
327 |
reslist_dblclck = false;
|
|
|
328 |
return;
|
|
|
329 |
}
|
|
|
330 |
|
|
|
331 |
int par = reslist_par;
|
|
|
332 |
|
|
|
333 |
if (reslist_current != -1) {
|
|
|
334 |
QColor color("white");
|
|
|
335 |
reslistTE->setParagraphBackgroundColor(reslist_current+1, color);
|
|
|
336 |
}
|
|
|
337 |
QColor color("lightblue");
|
|
|
338 |
reslistTE->setParagraphBackgroundColor(par, color);
|
|
|
339 |
|
|
|
340 |
int reldocnum = par - 1;
|
|
|
341 |
if (curPreview && reslist_current == reldocnum)
|
|
|
342 |
return;
|
|
|
343 |
|
|
|
344 |
reslist_current = reldocnum;
|
|
|
345 |
startPreview(reslist_winfirst + reldocnum);
|
|
|
346 |
}
|
315 |
|
347 |
|
316 |
// User asked to start query. Send it to the db aand call
|
348 |
// User asked to start query. Send it to the db aand call
|
317 |
// listNextPB_clicked to fetch and display the first page of results
|
349 |
// listNextPB_clicked to fetch and display the first page of results
|
318 |
void RecollMain::queryText_returnPressed()
|
350 |
void RecollMain::queryText_returnPressed()
|
319 |
{
|
351 |
{
|
320 |
LOGDEB(("RecollMain::queryText_returnPressed()\n"));
|
352 |
LOGDEB(("RecollMain::queryText_returnPressed()\n"));
|
|
|
353 |
// The db may have been closed at the end of indexing
|
321 |
string reason;
|
354 |
string reason;
|
322 |
if (!maybeOpenDb(reason)) {
|
355 |
if (!maybeOpenDb(reason)) {
|
323 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
356 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
324 |
return;
|
357 |
exit(1);
|
325 |
}
|
358 |
}
|
326 |
if (stemlang.empty())
|
359 |
if (stemlang.empty())
|
327 |
getQueryStemming(dostem, stemlang);
|
360 |
getQueryStemming(dostem, stemlang);
|
328 |
|
361 |
|
329 |
reslist_current = -1;
|
362 |
reslist_current = -1;
|
|
... |
|
... |
333 |
|
366 |
|
334 |
if (!rcldb->setQuery(string((const char *)u8), dostem ?
|
367 |
if (!rcldb->setQuery(string((const char *)u8), dostem ?
|
335 |
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
|
368 |
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
|
336 |
return;
|
369 |
return;
|
337 |
curPreview = 0;
|
370 |
curPreview = 0;
|
|
|
371 |
|
|
|
372 |
if (docsource)
|
|
|
373 |
delete docsource;
|
|
|
374 |
docsource = new DocSequenceDb(rcldb);
|
338 |
listNextPB_clicked();
|
375 |
listNextPB_clicked();
|
339 |
}
|
376 |
}
|
340 |
|
377 |
|
341 |
|
378 |
|
342 |
void RecollMain::Search_clicked()
|
379 |
void RecollMain::Search_clicked()
|
|
... |
|
... |
359 |
|
396 |
|
360 |
|
397 |
|
361 |
// Fill up result list window with next screen of hits
|
398 |
// Fill up result list window with next screen of hits
|
362 |
void RecollMain::listNextPB_clicked()
|
399 |
void RecollMain::listNextPB_clicked()
|
363 |
{
|
400 |
{
|
364 |
if (!rcldb)
|
401 |
if (!docsource)
|
365 |
return;
|
402 |
return;
|
366 |
|
403 |
|
367 |
int percent;
|
404 |
int percent;
|
368 |
Rcl::Doc doc;
|
405 |
Rcl::Doc doc;
|
369 |
|
406 |
|
370 |
// Need to fetch one document before we can get the result count
|
|
|
371 |
rcldb->getDoc(0, doc, &percent);
|
|
|
372 |
int resCnt = rcldb->getResCnt();
|
407 |
int resCnt = docsource->getResCnt();
|
373 |
|
408 |
|
374 |
LOGDEB(("listNextPB_clicked: rescnt %d, winfirst %d\n", resCnt,
|
409 |
LOGDEB(("listNextPB_clicked: rescnt %d, winfirst %d\n", resCnt,
|
375 |
reslist_winfirst));
|
410 |
reslist_winfirst));
|
376 |
|
411 |
|
377 |
// If we are already on the last page, nothing to do:
|
412 |
// If we are already on the last page, nothing to do:
|
|
... |
|
... |
390 |
|
425 |
|
391 |
// Insert results if any in result list window
|
426 |
// Insert results if any in result list window
|
392 |
for (int i = 0; i < last; i++) {
|
427 |
for (int i = 0; i < last; i++) {
|
393 |
doc.erase();
|
428 |
doc.erase();
|
394 |
|
429 |
|
395 |
if (!rcldb->getDoc(reslist_winfirst + i, doc, &percent)) {
|
430 |
if (!docsource->getDoc(reslist_winfirst + i, doc, &percent)) {
|
396 |
if (i == 0)
|
431 |
if (i == 0)
|
397 |
reslist_winfirst = -1;
|
432 |
reslist_winfirst = -1;
|
398 |
break;
|
433 |
break;
|
399 |
}
|
434 |
}
|
400 |
if (i == 0) {
|
435 |
if (i == 0) {
|
|
|
436 |
// We could use a <title> but the textedit doesnt display
|
|
|
437 |
// it prominently
|
401 |
reslistTE->append("<qt><head></head><body><p>");
|
438 |
reslistTE->append("<qt><head></head><body>");
|
|
|
439 |
QString line = "<p><font size=+1><b>";
|
|
|
440 |
line += docsource->title().c_str();
|
|
|
441 |
line += "</b></font><br>";
|
|
|
442 |
reslistTE->append(line);
|
402 |
QString line = tr("<p><b>Displaying results starting at index"
|
443 |
line = tr("<b>Displaying results starting at index"
|
403 |
" %1 (maximum set size %2)</b><br>")
|
444 |
" %1 (maximum set size %2)</b></p>")
|
404 |
.arg(reslist_winfirst+1)
|
445 |
.arg(reslist_winfirst+1)
|
405 |
.arg(resCnt);
|
446 |
.arg(resCnt);
|
406 |
reslistTE->append(line);
|
447 |
reslistTE->append(line);
|
407 |
}
|
448 |
}
|
408 |
|
449 |
|
|
... |
|
... |
510 |
// Execute an advanced search query. The parameters normally come from
|
551 |
// Execute an advanced search query. The parameters normally come from
|
511 |
// the advanced search dialog
|
552 |
// the advanced search dialog
|
512 |
void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
|
553 |
void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
|
513 |
{
|
554 |
{
|
514 |
LOGDEB(("RecollMain::startAdvSearch\n"));
|
555 |
LOGDEB(("RecollMain::startAdvSearch\n"));
|
|
|
556 |
// The db may have been closed at the end of indexing
|
515 |
string reason;
|
557 |
string reason;
|
516 |
if (!maybeOpenDb(reason)) {
|
558 |
if (!maybeOpenDb(reason)) {
|
517 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
559 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
518 |
return;
|
560 |
exit(1);
|
519 |
}
|
561 |
}
|
520 |
|
|
|
521 |
if (stemlang.empty())
|
562 |
if (stemlang.empty())
|
522 |
getQueryStemming(dostem, stemlang);
|
563 |
getQueryStemming(dostem, stemlang);
|
523 |
|
564 |
|
524 |
reslist_current = -1;
|
565 |
reslist_current = -1;
|
525 |
reslist_winfirst = -1;
|
566 |
reslist_winfirst = -1;
|
526 |
|
567 |
|
527 |
if (!rcldb->setQuery(sdata, dostem ?
|
568 |
if (!rcldb->setQuery(sdata, dostem ?
|
528 |
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
|
569 |
Rcl::Db::QO_STEM : Rcl::Db::QO_NONE, stemlang))
|
529 |
return;
|
570 |
return;
|
530 |
curPreview = 0;
|
571 |
curPreview = 0;
|
|
|
572 |
if (docsource)
|
|
|
573 |
delete docsource;
|
|
|
574 |
docsource = new DocSequenceDb(rcldb);
|
531 |
listNextPB_clicked();
|
575 |
listNextPB_clicked();
|
532 |
}
|
|
|
533 |
|
|
|
534 |
|
|
|
535 |
|
|
|
536 |
// This gets called by a timer 100mS after a single click in the
|
|
|
537 |
// result list. We don't want to start a preview if the user has
|
|
|
538 |
// requested a native viewer by double-clicking
|
|
|
539 |
void RecollMain::reslistTE_delayedclick()
|
|
|
540 |
{
|
|
|
541 |
reslistTE_waitingdbl = false;
|
|
|
542 |
if (reslistTE_dblclck) {
|
|
|
543 |
reslistTE_dblclck = false;
|
|
|
544 |
return;
|
|
|
545 |
}
|
|
|
546 |
|
|
|
547 |
int par = reslistTE_par;
|
|
|
548 |
|
|
|
549 |
if (reslist_current != -1) {
|
|
|
550 |
QColor color("white");
|
|
|
551 |
reslistTE->setParagraphBackgroundColor(reslist_current+1, color);
|
|
|
552 |
}
|
|
|
553 |
QColor color("lightblue");
|
|
|
554 |
reslistTE->setParagraphBackgroundColor(par, color);
|
|
|
555 |
|
|
|
556 |
int reldocnum = par - 1;
|
|
|
557 |
if (curPreview && reslist_current == reldocnum)
|
|
|
558 |
return;
|
|
|
559 |
|
|
|
560 |
reslist_current = reldocnum;
|
|
|
561 |
startPreview(reslist_winfirst + reldocnum);
|
|
|
562 |
}
|
576 |
}
|
563 |
|
577 |
|
564 |
|
578 |
|
565 |
/**
|
579 |
/**
|
566 |
* Open a preview window for a given document, or load it into new tab of
|
580 |
* Open a preview window for a given document, or load it into new tab of
|
|
... |
|
... |
569 |
* @param docnum db query index
|
583 |
* @param docnum db query index
|
570 |
*/
|
584 |
*/
|
571 |
void RecollMain::startPreview(int docnum)
|
585 |
void RecollMain::startPreview(int docnum)
|
572 |
{
|
586 |
{
|
573 |
Rcl::Doc doc;
|
587 |
Rcl::Doc doc;
|
574 |
if (!rcldb->getDoc(docnum, doc, 0)) {
|
588 |
if (!docsource->getDoc(docnum, doc, 0)) {
|
575 |
QMessageBox::warning(0, "Recoll",
|
589 |
QMessageBox::warning(0, "Recoll",
|
576 |
tr("Cannot retrieve document info"
|
590 |
tr("Cannot retrieve document info"
|
577 |
" from database"));
|
591 |
" from database"));
|
578 |
return;
|
592 |
return;
|
579 |
}
|
593 |
}
|
|
... |
|
... |
607 |
// Already there
|
621 |
// Already there
|
608 |
return;
|
622 |
return;
|
609 |
}
|
623 |
}
|
610 |
(void)curPreview->addEditorTab();
|
624 |
(void)curPreview->addEditorTab();
|
611 |
}
|
625 |
}
|
612 |
|
626 |
history->enterDocument(fn, doc.ipath);
|
613 |
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
|
627 |
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
|
614 |
}
|
628 |
}
|
615 |
|
629 |
|
616 |
|
630 |
|
617 |
void RecollMain::showAboutDialog()
|
631 |
void RecollMain::showAboutDialog()
|
618 |
{
|
632 |
{
|
619 |
string vstring = string("Recoll ") + rclversion +
|
633 |
string vstring = string("Recoll ") + rclversion +
|
620 |
"<br>" + "http://www.recoll.org";
|
634 |
"<br>" + "http://www.recoll.org";
|
621 |
QMessageBox::information(this, tr("About Recoll"), vstring.c_str());
|
635 |
QMessageBox::information(this, tr("About Recoll"), vstring.c_str());
|
622 |
}
|
636 |
}
|
|
|
637 |
|
|
|
638 |
|
|
|
639 |
void RecollMain::showDocHistory()
|
|
|
640 |
{
|
|
|
641 |
LOGDEB(("RecollMain::showDocHistory\n"));
|
|
|
642 |
reslist_current = -1;
|
|
|
643 |
reslist_winfirst = -1;
|
|
|
644 |
curPreview = 0;
|
|
|
645 |
|
|
|
646 |
if (docsource)
|
|
|
647 |
delete docsource;
|
|
|
648 |
docsource = new DocSequenceHistory(rcldb, history);
|
|
|
649 |
listNextPB_clicked();
|
|
|
650 |
}
|