|
a/src/qtgui/preview_w.cpp |
|
b/src/qtgui/preview_w.cpp |
1 |
#ifndef lint
|
1 |
#ifndef lint
|
2 |
static char rcsid[] = "@(#$Id: preview_w.cpp,v 1.27 2007-09-08 17:25:49 dockes Exp $ (C) 2005 J.F.Dockes";
|
2 |
static char rcsid[] = "@(#$Id: preview_w.cpp,v 1.28 2007-10-18 10:39:41 dockes Exp $ (C) 2005 J.F.Dockes";
|
3 |
#endif
|
3 |
#endif
|
4 |
/*
|
4 |
/*
|
5 |
* This program is free software; you can redistribute it and/or modify
|
5 |
* This program is free software; you can redistribute it and/or modify
|
6 |
* it under the terms of the GNU General Public License as published by
|
6 |
* it under the terms of the GNU General Public License as published by
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
... |
|
... |
33 |
#include <qpushbutton.h>
|
33 |
#include <qpushbutton.h>
|
34 |
#include <qtabwidget.h>
|
34 |
#include <qtabwidget.h>
|
35 |
#if (QT_VERSION < 0x040000)
|
35 |
#if (QT_VERSION < 0x040000)
|
36 |
#include <qtextedit.h>
|
36 |
#include <qtextedit.h>
|
37 |
#include <qprogressdialog.h>
|
37 |
#include <qprogressdialog.h>
|
|
|
38 |
#define THRFINISHED finished
|
38 |
#else
|
39 |
#else
|
39 |
#include <q3textedit.h>
|
40 |
#include <q3textedit.h>
|
40 |
#include <q3progressdialog.h>
|
41 |
#include <q3progressdialog.h>
|
41 |
#include <q3stylesheet.h>
|
42 |
#include <q3stylesheet.h>
|
|
|
43 |
#define THRFINISHED isFinished
|
42 |
#endif
|
44 |
#endif
|
43 |
#include <qevent.h>
|
45 |
#include <qevent.h>
|
44 |
#include <qlabel.h>
|
46 |
#include <qlabel.h>
|
45 |
#include <qlineedit.h>
|
47 |
#include <qlineedit.h>
|
46 |
#include <qcheckbox.h>
|
48 |
#include <qcheckbox.h>
|
|
... |
|
... |
579 |
|
581 |
|
580 |
/* A thread to convert to rich text (mark search terms) */
|
582 |
/* A thread to convert to rich text (mark search terms) */
|
581 |
class ToRichThread : public QThread {
|
583 |
class ToRichThread : public QThread {
|
582 |
string ∈
|
584 |
string ∈
|
583 |
const HiliteData &hdata;
|
585 |
const HiliteData &hdata;
|
584 |
QString &out;
|
586 |
list<string> &out;
|
585 |
int loglevel;
|
587 |
int loglevel;
|
586 |
public:
|
588 |
public:
|
587 |
ToRichThread(string &i, const HiliteData& hd, QString &o)
|
589 |
ToRichThread(string &i, const HiliteData& hd, list<string> &o)
|
588 |
: in(i), hdata(hd), out(o)
|
590 |
: in(i), hdata(hd), out(o)
|
589 |
{
|
591 |
{
|
590 |
loglevel = DebugLog::getdbl()->getlevel();
|
592 |
loglevel = DebugLog::getdbl()->getlevel();
|
591 |
}
|
593 |
}
|
592 |
virtual void run()
|
594 |
virtual void run()
|
593 |
{
|
595 |
{
|
594 |
DebugLog::getdbl()->setloglevel(loglevel);
|
596 |
DebugLog::getdbl()->setloglevel(loglevel);
|
595 |
string rich;
|
|
|
596 |
try {
|
597 |
try {
|
597 |
plaintorich(in, rich, hdata, false, true);
|
598 |
plaintorich(in, out, hdata, false, true);
|
598 |
} catch (CancelExcept) {
|
599 |
} catch (CancelExcept) {
|
599 |
}
|
600 |
}
|
600 |
out = QString::fromUtf8(rich.c_str(), rich.length());
|
|
|
601 |
}
|
601 |
}
|
602 |
};
|
602 |
};
|
603 |
|
603 |
|
604 |
/* A thread to implement short waiting. There must be a better way ! */
|
604 |
/* A thread to implement short waiting. There must be a better way ! */
|
605 |
class WaiterThread : public QThread {
|
605 |
class WaiterThread : public QThread {
|
|
... |
|
... |
663 |
lthr.start();
|
663 |
lthr.start();
|
664 |
int prog;
|
664 |
int prog;
|
665 |
for (prog = 1;;prog++) {
|
665 |
for (prog = 1;;prog++) {
|
666 |
waiter.start();
|
666 |
waiter.start();
|
667 |
waiter.wait();
|
667 |
waiter.wait();
|
668 |
#if (QT_VERSION < 0x040000)
|
668 |
if (lthr.THRFINISHED ())
|
669 |
if (lthr.finished())
|
|
|
670 |
break;
|
669 |
break;
|
671 |
#else
|
|
|
672 |
if (lthr.isFinished())
|
|
|
673 |
break;
|
|
|
674 |
#endif
|
|
|
675 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
670 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
676 |
qApp->processEvents();
|
671 |
qApp->processEvents();
|
677 |
if (progress.wasCanceled()) {
|
672 |
if (progress.wasCanceled()) {
|
678 |
CancelCheck::instance().setCancel();
|
673 |
CancelCheck::instance().setCancel();
|
679 |
}
|
674 |
}
|
|
... |
|
... |
701 |
return false;
|
696 |
return false;
|
702 |
}
|
697 |
}
|
703 |
// Reset config just in case.
|
698 |
// Reset config just in case.
|
704 |
rclconfig->setKeyDir("");
|
699 |
rclconfig->setKeyDir("");
|
705 |
|
700 |
|
706 |
// Create preview text: highlight search terms (if not too big):
|
701 |
// Create preview text: highlight search terms
|
707 |
QString richTxt;
|
|
|
708 |
|
|
|
709 |
// We don't do the highlighting for very big texts: too long. We
|
702 |
// We don't do the highlighting for very big texts: too long. We
|
710 |
// should at least do special char escaping, in case a '&' or '<'
|
703 |
// should at least do special char escaping, in case a '&' or '<'
|
711 |
// somehow slipped through previous processing.
|
704 |
// somehow slipped through previous processing.
|
712 |
bool highlightTerms = fdoc.text.length() < (unsigned long)prefs.maxhltextmbs * 1024 * 1024;
|
705 |
bool highlightTerms = fdoc.text.length() <
|
713 |
int beaconPos = -1;
|
706 |
(unsigned long)prefs.maxhltextmbs * 1024 * 1024;
|
|
|
707 |
// Final text is produced in chunks so that we can display the top
|
|
|
708 |
// while still inserting at bottom
|
|
|
709 |
list<QString> qrichlst;
|
|
|
710 |
|
714 |
if (highlightTerms) {
|
711 |
if (highlightTerms) {
|
715 |
progress.setLabelText(tr("Creating preview text"));
|
712 |
progress.setLabelText(tr("Creating preview text"));
|
716 |
qApp->processEvents();
|
713 |
qApp->processEvents();
|
|
|
714 |
list<string> richlst;
|
717 |
ToRichThread rthr(fdoc.text, m_hData, richTxt);
|
715 |
ToRichThread rthr(fdoc.text, m_hData, richlst);
|
718 |
rthr.start();
|
716 |
rthr.start();
|
719 |
|
717 |
|
720 |
for (;;prog++) {
|
718 |
for (;;prog++) {
|
721 |
waiter.start(); waiter.wait();
|
719 |
waiter.start(); waiter.wait();
|
722 |
#if (QT_VERSION < 0x040000)
|
720 |
if (rthr.THRFINISHED ())
|
723 |
if (rthr.finished())
|
|
|
724 |
break;
|
721 |
break;
|
725 |
#else
|
|
|
726 |
if (rthr.isFinished())
|
|
|
727 |
break;
|
|
|
728 |
#endif
|
|
|
729 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
722 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
730 |
qApp->processEvents();
|
723 |
qApp->processEvents();
|
731 |
if (progress.wasCanceled()) {
|
724 |
if (progress.wasCanceled()) {
|
732 |
CancelCheck::instance().setCancel();
|
725 |
CancelCheck::instance().setCancel();
|
733 |
}
|
726 |
}
|
|
... |
|
... |
735 |
sleep(1);
|
728 |
sleep(1);
|
736 |
}
|
729 |
}
|
737 |
|
730 |
|
738 |
// Conversion to rich text done
|
731 |
// Conversion to rich text done
|
739 |
if (CancelCheck::instance().cancelState()) {
|
732 |
if (CancelCheck::instance().cancelState()) {
|
740 |
if (richTxt.length() == 0) {
|
733 |
if (richlst.size() == 0 || richlst.front().length() == 0) {
|
741 |
// We cant call closeCurrentTab here as it might delete
|
734 |
// We cant call closeCurrentTab here as it might delete
|
742 |
// the object which would be a nasty surprise to our
|
735 |
// the object which would be a nasty surprise to our
|
743 |
// caller.
|
736 |
// caller.
|
744 |
return false;
|
737 |
return false;
|
745 |
} else {
|
738 |
} else {
|
746 |
richTxt += "<b>Cancelled !</b>";
|
739 |
richlst.back() += "<b>Cancelled !</b>";
|
747 |
}
|
740 |
}
|
748 |
}
|
741 |
}
|
749 |
beaconPos = richTxt.find(QString::fromUtf8(firstTermBeacon));
|
742 |
// Convert to QString list
|
|
|
743 |
for (list<string>::iterator it = richlst.begin();
|
|
|
744 |
it != richlst.end(); it++) {
|
|
|
745 |
qrichlst.push_back(QString::fromUtf8(it->c_str(), it->length()));
|
|
|
746 |
}
|
750 |
} else {
|
747 |
} else {
|
751 |
// Note that in the case were we don't call plaintorich, the
|
748 |
// No plaintorich() call.
|
752 |
// text will no be identified as richtxt/html (no <html> or
|
749 |
// In this case, the text will no be identified as
|
753 |
// <qt> etc. at the beginning), and there is no need to escape
|
750 |
// richtxt/html (no <html> or <qt> etc. at the beginning), and
|
754 |
// special characters
|
751 |
// there is no need to escape special characters.
|
|
|
752 |
// Also we need to split in chunks (so that the top is displayed faster),
|
|
|
753 |
// and we must do it on a QString (to avoid utf8 issues).
|
755 |
richTxt = QString::fromUtf8(fdoc.text.c_str(), fdoc.text.length());
|
754 |
QString qr = QString::fromUtf8(fdoc.text.c_str(), fdoc.text.length());
|
|
|
755 |
int l = 0;
|
|
|
756 |
for (int pos = 0; pos < (int)qr.length(); pos += l) {
|
|
|
757 |
l = MIN(CHUNKL, qr.length() - pos);
|
|
|
758 |
qrichlst.push_back(qr.mid(pos, l));
|
|
|
759 |
}
|
756 |
}
|
760 |
}
|
757 |
|
761 |
|
758 |
m_haveAnchors = (beaconPos != -1);
|
|
|
759 |
LOGDEB(("LoadFileInCurrentTab: rich: cancel %d txtln %d, hasAnchors %d "
|
|
|
760 |
"(beaconPos %d)\n",
|
|
|
761 |
CancelCheck::instance().cancelState(), richTxt.length(),
|
|
|
762 |
m_haveAnchors, beaconPos));
|
|
|
763 |
|
|
|
764 |
// Load into editor
|
762 |
// Load into editor
|
765 |
// Do it in several chunks
|
|
|
766 |
QTextEdit *editor = getCurrentEditor();
|
763 |
QTextEdit *editor = getCurrentEditor();
|
767 |
editor->setText("");
|
764 |
editor->setText("");
|
768 |
if (highlightTerms) {
|
765 |
if (highlightTerms) {
|
769 |
QStyleSheetItem *item =
|
766 |
QStyleSheetItem *item =
|
770 |
new QStyleSheetItem(editor->styleSheet(), "termtag" );
|
767 |
new QStyleSheetItem(editor->styleSheet(), "termtag" );
|
|
... |
|
... |
773 |
}
|
770 |
}
|
774 |
|
771 |
|
775 |
prog = 2 * nsteps / 3;
|
772 |
prog = 2 * nsteps / 3;
|
776 |
progress.setLabelText(tr("Loading preview text into editor"));
|
773 |
progress.setLabelText(tr("Loading preview text into editor"));
|
777 |
qApp->processEvents();
|
774 |
qApp->processEvents();
|
778 |
int l = 0;
|
775 |
int instep = 0;
|
779 |
for (int pos = 0; pos < (int)richTxt.length(); pos += l, prog++) {
|
776 |
for (list<QString>::iterator it = qrichlst.begin();
|
|
|
777 |
it != qrichlst.end(); it++, prog++, instep++) {
|
780 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
778 |
progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1);
|
781 |
qApp->processEvents();
|
779 |
qApp->processEvents();
|
782 |
|
780 |
if (it->find(QString::fromUtf8(firstTermBeacon)) != -1)
|
783 |
l = MIN(CHUNKL, richTxt.length() - pos);
|
781 |
m_haveAnchors = true;
|
784 |
// Avoid breaking inside a tag. Our tags are short (ie: <br>)
|
782 |
|
785 |
if (pos + l != (int)richTxt.length()) {
|
783 |
editor->append(*it);
|
786 |
for (int i = -15; i < 0; i++) {
|
784 |
|
787 |
if (richTxt[pos+l+i] == '<') {
|
|
|
788 |
l = l+i;
|
|
|
789 |
break;
|
|
|
790 |
}
|
|
|
791 |
}
|
|
|
792 |
}
|
|
|
793 |
editor->append(richTxt.mid(pos, l));
|
|
|
794 |
// Stay at top
|
785 |
// Stay at top
|
795 |
if (pos < 5) {
|
786 |
if (instep < 5) {
|
796 |
editor->setCursorPosition(0,0);
|
787 |
editor->setCursorPosition(0,0);
|
797 |
editor->ensureCursorVisible();
|
788 |
editor->ensureCursorVisible();
|
798 |
}
|
789 |
}
|
799 |
|
790 |
|
800 |
if (progress.wasCanceled()) {
|
791 |
if (progress.wasCanceled()) {
|
801 |
editor->append("<b>Cancelled !</b>");
|
792 |
editor->append("<b>Cancelled !</b>");
|
802 |
LOGDEB(("LoadFileInCurrentTab: cancelled in editor load\n"));
|
793 |
LOGDEB(("LoadFileInCurrentTab: cancelled in editor load\n"));
|
803 |
break;
|
794 |
break;
|
804 |
}
|
795 |
}
|
805 |
}
|
796 |
}
|
|
|
797 |
|
|
|
798 |
|
806 |
progress.close();
|
799 |
progress.close();
|
807 |
|
800 |
|
808 |
if (searchTextLine->text().length() != 0) {
|
801 |
if (searchTextLine->text().length() != 0) {
|
809 |
// If there is a current search string, perform the search
|
802 |
// If there is a current search string, perform the search
|
810 |
m_canBeep = true;
|
803 |
m_canBeep = true;
|