Switch to unified view

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 &in;
584
    string &in;
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;