2
//C- -------------------------------------------------------------------
4
//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
5
//C- Copyright (c) 2001 AT&T
7
//C- This software is subject to, and may be distributed under, the
8
//C- GNU General Public License, Version 2. The license should have
9
//C- accompanied the software or you may obtain a copy of the license
10
//C- from the Free Software Foundation at http://www.fsf.org .
12
//C- This program is distributed in the hope that it will be useful,
13
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
//C- GNU General Public License for more details.
17
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
18
//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech
19
//C- Software authorized us to replace the original DjVu(r) Reference
20
//C- Library notice by the following text (see doc/lizard2002.djvu):
22
//C- ------------------------------------------------------------------
23
//C- | DjVu (r) Reference Library (v. 3.5)
24
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
25
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
26
//C- | 6,058,214 and patents pending.
28
//C- | This software is subject to, and may be distributed under, the
29
//C- | GNU General Public License, Version 2. The license should have
30
//C- | accompanied the software or you may obtain a copy of the license
31
//C- | from the Free Software Foundation at http://www.fsf.org .
33
//C- | The computer code originally released by LizardTech under this
34
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
35
//C- | ORIGINAL CODE." Subject to any third party intellectual property
36
//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
37
//C- | non-exclusive license to make, use, sell, or otherwise dispose of
38
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
39
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
40
//C- | General Public License. This grant only confers the right to
41
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
42
//C- | the extent such infringement is reasonably necessary to enable
43
//C- | recipient to make, have made, practice, sell, or otherwise dispose
44
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
45
//C- | any greater extent that may be necessary to utilize further
46
//C- | modifications or combinations.
48
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
49
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
50
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
51
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
52
//C- +------------------------------------------------------------------
54
// $Id: qd_search_dialog.cpp,v 1.13 2004/07/07 19:23:36 leonb Exp $
55
// $Name: release_3_5_14 $
61
# pragma implementation
67
#include "ByteStream.h"
69
#include "qd_search_dialog.h"
75
#include <qpushbutton.h>
77
#include <qcheckbox.h>
78
#include <qlineedit.h>
79
#include <qmessagebox.h>
80
#include <qapplication.h>
82
bool QDSearchDialog::all_pages=true;
83
bool QDSearchDialog::case_sensitive=false;
84
bool QDSearchDialog::whole_word=false;
85
bool QDSearchDialog::search_backwards=false;
88
static GList<DjVuTXT::Zone*>
89
search_string(DjVuTXT *txt, QString dat, int &pfrom,
90
bool fwd, bool casep, bool wordp)
92
GList<DjVuTXT::Zone*> res;
94
GUTF8String utext = txt->textUTF8;
95
QString qtext = QStringFromGString(utext);
97
dat = dat.stripWhiteSpace();
111
if (from < 0 || from >= (int)qtext.length())
112
from = qtext.length() - 1;
122
found = qtext.find(dat, from, casep);
124
found = qtext.findRev(dat, from, casep);
127
foundx = found + dat.length();
130
if (found==0 || !qtext[found-1].isLetterOrNumber())
131
if (foundx==(int)qtext.length() || !qtext[foundx].isLetterOrNumber())
134
if (++pfrom >= (int)qtext.length())
141
// Compute indices into utf8 string
144
const char *ctext = (const char*)utext;
147
while (ctext[ui] && ufoundx<0)
149
if (ufound<0 && qi == found)
151
if (ufoundx<0 && qi == foundx)
154
if ( (ctext[ui] & 0xc0) != 0x80)
158
if (ufoundx > ufound && ufound >= 0)
160
txt->page_zone.find_zones(res, ufound, ufoundx);
168
QDSearchDialog::slotSearch(void)
176
if (text->text()=="") return;
180
bool fwd=!back_butt->isChecked();
183
search_butt->setText(tr("&Stop"));
184
text->setEnabled(FALSE);
185
clear_butt->setEnabled(FALSE);
187
// 'asked_once' is useful for one-page searches
188
bool asked_once=false;
189
// 'start_page_num' is for the document search
190
int start_page_num=page_num;
191
// Will be true if no TXT chunks have been found
194
// We want to place 'anno' here because to keep it alive as long
195
// as zone_list is alive.
197
GList<DjVuTXT::Zone *> zone_list;
200
GP<DjVuFile> page_file=doc->get_djvu_file(page_num);
202
if (!page_file->is_all_data_present())
204
GP<DataPool> pool=page_file->get_init_data_pool();
206
// Wait until we have data for this file
207
while(!stop && !page_file->is_all_data_present())
209
int done=5*(20*pool->get_size()/pool->get_length());
212
QString buffer=tr("Loading page %1: %2%...")
215
status_label->setText(buffer);
218
qApp->processEvents(100);
223
page_num=seen_page_num;
227
GP<ByteStream> str=page_file->get_text();
231
anno=DjVuText::create();
233
GP<DjVuTXT> txt=anno->txt;
237
zone_list = search_string(txt, text->text(), page_pos,
238
fwd, case_butt->isChecked(),
239
whole_word_butt->isChecked());
240
if (zone_list.size())
244
// Didn't find anything. Switch to the next page or give up
245
int pages_num=doc->get_pages_num();
246
if (!all_pages_butt->isChecked() ||
247
fwd && page_num>=pages_num-1 ||
252
page_num=seen_page_num;
259
if (all_pages_butt->isChecked())
262
msg=tr("End of document reached. "
263
"Continue from the beginning?");
265
msg=tr("Beginning of document reached. "
266
"Continue from the end?");
271
msg=tr("End of page reached. "
272
"Continue from the beginning?");
274
msg=tr("Beginning of page reached. "
275
"Continue from the end?");
278
if (QMessageBox::information(this, "DjVu", msg,
279
tr("&Yes"), tr("&No"))==0)
281
if (all_pages_butt->isChecked())
286
page_num=doc->get_pages_num();
298
page_num=seen_page_num;
303
// Going to the next page (or rewinding to the other side of
304
// this page if asked to)
317
QString mesg=tr("Page ")+QString::number(page_num+1);
318
status_label->setText(mesg);
321
// Wrapped back and returned
322
if (all_pages_butt->isChecked() && page_num==start_page_num)
324
page_num=seen_page_num;
329
emit sigDisplaySearchResults(seen_page_num=page_num, zone_list);
330
if (zone_list.size()==0)
334
if (all_pages_butt->isChecked())
335
showMessage(this, tr("DjVu Search Failed"),
336
tr("After looking through every page of this document,\n"
337
"we have found that none of them contain\n"
338
"textual information. This means that either the document\n"
339
"creator did not run an OCR engine on this document,\n"
340
"or the OCR engine did not recognize any text.\n"
342
"The search is impossible."),
345
showMessage(this, tr("DjVu Search Failed"),
346
tr("This page does not contain textual information,\n"
347
"which means that either the creator of this document\n"
348
"did not run an OCR engine on it, or the OCR engine\n"
349
"did not recognize any text on this page.\n"
351
"The search is impossible."),
354
showInfo(this, "DjVu", tr("Search string not found"));
358
search_butt->setText(tr("&Find"));
360
QString mesg=tr("Page ")+QString::number(page_num+1);
361
status_label->setText(mesg);
363
text->setEnabled(TRUE);
364
clear_butt->setEnabled(TRUE);
366
catch(const GException & exc)
368
status_label->hide();
370
search_butt->setText(tr("&Find"));
372
QString mesg=tr("Page ")+QString::number(page_num+1);
373
status_label->setText(mesg);
375
text->setEnabled(TRUE);
376
clear_butt->setEnabled(TRUE);
377
showError(this, exc);
382
QDSearchDialog::slotSetPageNum(int page_num_)
384
seen_page_num=page_num_;
388
if (page_num!=page_num_)
390
page_num = seen_page_num;
393
QString mesg=tr("Page ")+QString::number(page_num+1);
394
status_label->setText(mesg);
398
QDSearchDialog::slotTextChanged(const QString & qtext)
400
const char * const str=qtext;
401
search_butt->setEnabled(str && strlen(str));
405
QDSearchDialog::done(int rc)
408
all_pages=all_pages_butt->isChecked();
409
case_sensitive=case_butt->isChecked();
410
whole_word=whole_word_butt->isChecked();
411
search_backwards=back_butt->isChecked();
416
QDSearchDialog::QDSearchDialog(int page_num_, const GP<DjVuDocument> & doc_,
417
QWidget * parent, const char * name, bool modal) :
418
QeDialog(parent, name, modal), page_num(page_num_), doc(doc_)
420
seen_page_num = page_num;
424
setCaption(tr("DjVu: Find"));
426
QWidget * start=startWidget();
429
QVBoxLayout * vlay=new QVBoxLayout(start, 10, 10);
431
QHBoxLayout * hlay=new QHBoxLayout(10);
432
vlay->addLayout(hlay);
433
label=new QLabel(tr("Find: "), start);
434
hlay->addWidget(label);
435
text=new QLineEdit(start, "search_text");
436
label->setBuddy(text);
437
hlay->addWidget(text, 1);
439
hlay=new QHBoxLayout(10);
440
vlay->addLayout(hlay);
442
all_pages_butt=new QCheckBox(tr("Search &all pages"), start, "all_pages_butt");
443
if (doc->get_pages_num()>1)
444
all_pages_butt->setChecked(all_pages);
447
all_pages_butt->setChecked(TRUE);
448
all_pages_butt->setEnabled(FALSE);
450
hlay->addWidget(all_pages_butt);
453
case_butt=new QCheckBox(tr("&Case sensitive"), start, "case_butt");
454
case_butt->setChecked(case_sensitive);
455
hlay->addWidget(case_butt);
458
whole_word_butt=new QCheckBox(tr("&Whole word"), start, "whole_word_butt");
459
whole_word_butt->setChecked(whole_word);
460
hlay->addWidget(whole_word_butt);
463
back_butt=new QCheckBox(tr("Search &backwards"), start, "back_butt");
464
back_butt->setChecked(search_backwards);
465
hlay->addWidget(back_butt);
467
QHBoxLayout * butt_lay=new QHBoxLayout(10);
468
vlay->addLayout(butt_lay);
469
status_label=new QLabel(tr("Loading page WWWWWWW"), start);
470
status_label->setMinimumSize(status_label->sizeHint());
472
QString mesg=tr("Page ")+QString::number(page_num+1);
473
status_label->setText(mesg);
475
butt_lay->addWidget(status_label);
476
butt_lay->addStretch(1);
477
search_butt=new QPushButton(tr("&Find"), start, "search_butt");
478
search_butt->setEnabled(FALSE);
479
butt_lay->addWidget(search_butt);
480
clear_butt=new QPushButton(tr("&Clear"), start, "clear_butt");
481
butt_lay->addWidget(clear_butt);
482
QPushButton * close_butt=new QPushButton(tr("C&lose"), start, "close_butt");
483
butt_lay->addWidget(close_butt);
484
search_butt->setDefault(TRUE);
486
connect(search_butt, SIGNAL(clicked(void)), this, SLOT(slotSearch(void)));
487
connect(clear_butt, SIGNAL(clicked(void)), text, SLOT(clear(void)));
488
connect(close_butt, SIGNAL(clicked(void)), this, SLOT(reject(void)));
490
connect(text, SIGNAL(textChanged(const QString &)),
491
this, SLOT(slotTextChanged(const QString &)));