Switch to unified view

a/src/qtgui/preview_w.cpp b/src/qtgui/preview_w.cpp
...
...
13
 *   along with this program; if not, write to the
13
 *   along with this program; if not, write to the
14
 *   Free Software Foundation, Inc.,
14
 *   Free Software Foundation, Inc.,
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 */
16
 */
17
#include "autoconfig.h"
17
#include "autoconfig.h"
18
19
#include "safeunistd.h"
20
18
21
#include <list>
19
#include <list>
22
#include <utility>
20
#include <utility>
23
21
24
#include <qmessagebox.h>
22
#include <qmessagebox.h>
...
...
43
#include <qapplication.h>
41
#include <qapplication.h>
44
#include <qclipboard.h>
42
#include <qclipboard.h>
45
#include <qimage.h>
43
#include <qimage.h>
46
#include <qurl.h>
44
#include <qurl.h>
47
#include <QShortcut>
45
#include <QShortcut>
46
#include <QTimer>
48
47
49
#include "debuglog.h"
48
#include "debuglog.h"
50
#include "pathut.h"
49
#include "pathut.h"
51
#include "internfile.h"
50
#include "internfile.h"
52
#include "recoll.h"
51
#include "recoll.h"
...
...
68
// Subclass plainToRich to add <termtag>s and anchors to the preview text
67
// Subclass plainToRich to add <termtag>s and anchors to the preview text
69
class PlainToRichQtPreview : public PlainToRich {
68
class PlainToRichQtPreview : public PlainToRich {
70
public:
69
public:
71
70
72
    PlainToRichQtPreview()
71
    PlainToRichQtPreview()
73
  : m_curanchor(1), m_lastanchor(0)
72
        : m_curanchor(1), m_lastanchor(0) {
74
    {
75
    }    
73
    }    
76
    void clear() {
74
    void clear() {
77
  m_curanchor = 1; 
75
        m_curanchor = 1; 
78
  m_lastanchor = 0;
76
        m_lastanchor = 0;
79
  m_groupanchors.clear();
77
        m_groupanchors.clear();
80
  m_groupcuranchors.clear();
78
        m_groupcuranchors.clear();
81
    }
79
    }
82
80
83
    bool haveAnchors()
81
    bool haveAnchors() {
84
    {
85
  return m_lastanchor != 0;
82
        return m_lastanchor != 0;
86
    }
83
    }
87
84
88
    virtual string header() 
85
    virtual string header() {
89
    {
90
  if (!m_inputhtml) {
86
        if (!m_inputhtml) {
91
      switch (prefs.previewPlainPre) {
87
            switch (prefs.previewPlainPre) {
92
      case PrefsPack::PP_BR:
88
            case PrefsPack::PP_BR:
93
      m_eolbr = true;
89
                m_eolbr = true;
94
      return "<qt><head><title></title></head><body>";
90
                return "<qt><head><title></title></head><body>";
95
      case PrefsPack::PP_PRE:
91
            case PrefsPack::PP_PRE:
96
      m_eolbr = false;
92
                m_eolbr = false;
97
      return "<qt><head><title></title></head><body><pre>";
93
                return "<qt><head><title></title></head><body><pre>";
98
      case PrefsPack::PP_PREWRAP:
94
            case PrefsPack::PP_PREWRAP:
99
      m_eolbr = false;
95
                m_eolbr = false;
100
      return "<qt><head><title></title></head><body>"
96
                return "<qt><head><title></title></head><body>"
101
          "<pre style=\"white-space: pre-wrap\">";
97
                    "<pre style=\"white-space: pre-wrap\">";
98
            }
99
        }
100
        return cstr_null;
102
      }
101
    }
103
  }
104
  return cstr_null;
105
    }
106
102
107
    virtual string startMatch(unsigned int grpidx)
103
    virtual string startMatch(unsigned int grpidx) {
108
    {
109
  LOGDEB2(("startMatch, grpidx %u\n", grpidx));
104
        LOGDEB2(("startMatch, grpidx %u\n", grpidx));
110
  grpidx = m_hdata->grpsugidx[grpidx];
105
        grpidx = m_hdata->grpsugidx[grpidx];
111
  LOGDEB2(("startMatch, ugrpidx %u\n", grpidx));
106
        LOGDEB2(("startMatch, ugrpidx %u\n", grpidx));
112
  m_groupanchors[grpidx].push_back(++m_lastanchor);
107
        m_groupanchors[grpidx].push_back(++m_lastanchor);
113
  m_groupcuranchors[grpidx] = 0; 
108
        m_groupcuranchors[grpidx] = 0; 
114
  return string("<span style='color: ").
109
        return string("<span style='color: ").
115
      append((const char *)(prefs.qtermcolor.toUtf8())).
110
            append((const char *)(prefs.qtermcolor.toUtf8())).
116
      append(";font-weight: bold;").
111
            append(";font-weight: bold;").
117
      append("'>").
112
            append("'>").
118
      append("<a name=\"").
113
            append("<a name=\"").
119
      append(termAnchorName(m_lastanchor)).
114
            append(termAnchorName(m_lastanchor)).
120
      append("\">");
115
            append("\">");
121
    }
116
    }
122
117
123
    virtual string endMatch() 
118
    virtual string endMatch() {
124
    {
125
  return string("</a></span>");
119
        return string("</a></span>");
126
    }
120
    }
127
121
128
    virtual string termAnchorName(int i) const
122
    virtual string termAnchorName(int i) const {
129
    {
130
  static const char *termAnchorNameBase = "TRM";
123
        static const char *termAnchorNameBase = "TRM";
131
  char acname[sizeof(termAnchorNameBase) + 20];
124
        char acname[sizeof(termAnchorNameBase) + 20];
132
  sprintf(acname, "%s%d", termAnchorNameBase, i);
125
        sprintf(acname, "%s%d", termAnchorNameBase, i);
133
  return string(acname);
126
        return string(acname);
134
    }
127
    }
135
128
136
    virtual string startChunk() 
129
    virtual string startChunk() { 
137
    { 
138
  return "<pre>";
130
        return "<pre>";
139
    }
131
    }
140
132
141
    int nextAnchorNum(int grpidx)
133
    int nextAnchorNum(int grpidx) {
142
    {
143
  LOGDEB2(("nextAnchorNum: group %d\n", grpidx));
134
        LOGDEB2(("nextAnchorNum: group %d\n", grpidx));
144
  map<unsigned int, unsigned int>::iterator curit = 
135
        map<unsigned int, unsigned int>::iterator curit = 
145
      m_groupcuranchors.find(grpidx);
136
            m_groupcuranchors.find(grpidx);
146
  map<unsigned int, vector<int> >::iterator vecit = 
137
        map<unsigned int, vector<int> >::iterator vecit = 
147
      m_groupanchors.find(grpidx);
138
            m_groupanchors.find(grpidx);
148
  if (grpidx == -1 || curit == m_groupcuranchors.end() ||
139
        if (grpidx == -1 || curit == m_groupcuranchors.end() ||
149
      vecit == m_groupanchors.end()) {
140
            vecit == m_groupanchors.end()) {
150
      if (m_curanchor >= m_lastanchor)
141
            if (m_curanchor >= m_lastanchor)
151
      m_curanchor = 1;
142
                m_curanchor = 1;
152
      else
143
            else
153
      m_curanchor++;
144
                m_curanchor++;
154
  } else {
145
        } else {
155
      if (curit->second >= vecit->second.size() -1)
146
            if (curit->second >= vecit->second.size() -1)
156
      m_groupcuranchors[grpidx] = 0;
147
                m_groupcuranchors[grpidx] = 0;
157
      else 
148
            else 
158
      m_groupcuranchors[grpidx]++;
149
                m_groupcuranchors[grpidx]++;
159
      m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
150
            m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
160
      LOGDEB2(("nextAnchorNum: curanchor now %d\n", m_curanchor));
151
            LOGDEB2(("nextAnchorNum: curanchor now %d\n", m_curanchor));
161
  }
152
        }
162
  return m_curanchor;
153
        return m_curanchor;
163
    }
154
    }
164
155
165
    int prevAnchorNum(int grpidx)
156
    int prevAnchorNum(int grpidx) {
166
    {
167
  map<unsigned int, unsigned int>::iterator curit = 
157
        map<unsigned int, unsigned int>::iterator curit = 
168
      m_groupcuranchors.find(grpidx);
158
            m_groupcuranchors.find(grpidx);
169
  map<unsigned int, vector<int> >::iterator vecit = 
159
        map<unsigned int, vector<int> >::iterator vecit = 
170
      m_groupanchors.find(grpidx);
160
            m_groupanchors.find(grpidx);
171
  if (grpidx == -1 || curit == m_groupcuranchors.end() ||
161
        if (grpidx == -1 || curit == m_groupcuranchors.end() ||
172
      vecit == m_groupanchors.end()) {
162
            vecit == m_groupanchors.end()) {
173
      if (m_curanchor <= 1)
163
            if (m_curanchor <= 1)
174
      m_curanchor = m_lastanchor;
164
                m_curanchor = m_lastanchor;
175
      else
165
            else
176
      m_curanchor--;
166
                m_curanchor--;
177
  } else {
167
        } else {
178
      if (curit->second <= 0)
168
            if (curit->second <= 0)
179
      m_groupcuranchors[grpidx] = vecit->second.size() -1;
169
                m_groupcuranchors[grpidx] = vecit->second.size() -1;
180
      else 
170
            else 
181
      m_groupcuranchors[grpidx]--;
171
                m_groupcuranchors[grpidx]--;
182
      m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
172
            m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
183
  }
173
        }
184
  return m_curanchor;
174
        return m_curanchor;
185
    }
175
    }
186
176
187
    QString curAnchorName() const
177
    QString curAnchorName() const {
188
    {
189
  return QString::fromUtf8(termAnchorName(m_curanchor).c_str());
178
        return QString::fromUtf8(termAnchorName(m_curanchor).c_str());
190
    }
179
    }
191
180
192
private:
181
private:
193
    int m_curanchor;
182
    int m_curanchor;
194
    int m_lastanchor;
183
    int m_lastanchor;
...
...
225
    searchTextCMB = new QComboBox(this);
214
    searchTextCMB = new QComboBox(this);
226
    searchTextCMB->setEditable(true);
215
    searchTextCMB->setEditable(true);
227
    searchTextCMB->setInsertPolicy(QComboBox::NoInsert);
216
    searchTextCMB->setInsertPolicy(QComboBox::NoInsert);
228
    searchTextCMB->setDuplicatesEnabled(false);
217
    searchTextCMB->setDuplicatesEnabled(false);
229
    for (unsigned int i = 0; i < m_hData.ugroups.size(); i++) {
218
    for (unsigned int i = 0; i < m_hData.ugroups.size(); i++) {
230
  QString s;
219
        QString s;
231
  for (unsigned int j = 0; j < m_hData.ugroups[i].size(); j++) {
220
        for (unsigned int j = 0; j < m_hData.ugroups[i].size(); j++) {
232
      s.append(QString::fromUtf8(m_hData.ugroups[i][j].c_str()));
221
            s.append(QString::fromUtf8(m_hData.ugroups[i][j].c_str()));
233
      if (j != m_hData.ugroups[i].size()-1)
222
            if (j != m_hData.ugroups[i].size()-1)
234
      s.append(" ");
223
                s.append(" ");
235
  }
224
        }
236
  searchTextCMB->addItem(s);
225
        searchTextCMB->addItem(s);
237
    }
226
    }
238
    searchTextCMB->setEditText("");
227
    searchTextCMB->setEditText("");
239
    searchTextCMB->setCompleter(0);
228
    searchTextCMB->setCompleter(0);
240
229
241
    layout3->addWidget(searchTextCMB);
230
    layout3->addWidget(searchTextCMB);
...
...
268
    QPushButton * bt = new QPushButton(tr("Close Tab"), this);
257
    QPushButton * bt = new QPushButton(tr("Close Tab"), this);
269
    pvTab->setCornerWidget(bt);
258
    pvTab->setCornerWidget(bt);
270
259
271
    (void)new HelpClient(this);
260
    (void)new HelpClient(this);
272
    HelpClient::installMap((const char *)objectName().toUtf8(), 
261
    HelpClient::installMap((const char *)objectName().toUtf8(), 
273
             "RCL.SEARCH.PREVIEW");
262
                           "RCL.SEARCH.PREVIEW");
274
263
275
    // signals and slots connections
264
    // signals and slots connections
276
    connect(searchTextCMB, SIGNAL(activated(int)), 
265
    connect(searchTextCMB, SIGNAL(activated(int)), 
277
      this, SLOT(searchTextFromIndex(int)));
266
            this, SLOT(searchTextFromIndex(int)));
278
    connect(searchTextCMB, SIGNAL(editTextChanged(const QString&)), 
267
    connect(searchTextCMB, SIGNAL(editTextChanged(const QString&)), 
279
      this, SLOT(searchTextChanged(const QString&)));
268
            this, SLOT(searchTextChanged(const QString&)));
280
    connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
269
    connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
281
    connect(prevButton, SIGNAL(clicked()), this, SLOT(prevPressed()));
270
    connect(prevButton, SIGNAL(clicked()), this, SLOT(prevPressed()));
282
    connect(clearPB, SIGNAL(clicked()), searchTextCMB, SLOT(clearEditText()));
271
    connect(clearPB, SIGNAL(clicked()), searchTextCMB, SLOT(clearEditText()));
283
    connect(pvTab, SIGNAL(currentChanged(int)), 
272
    connect(pvTab, SIGNAL(currentChanged(int)), 
284
      this, SLOT(currentChanged(int)));
273
            this, SLOT(currentChanged(int)));
285
    connect(bt, SIGNAL(clicked()), this, SLOT(closeCurrentTab()));
274
    connect(bt, SIGNAL(clicked()), this, SLOT(closeCurrentTab()));
286
275
287
    connect(new QShortcut(closeKS, this), SIGNAL (activated()), 
276
    connect(new QShortcut(closeKS, this), SIGNAL (activated()), 
288
      this, SLOT (close()));
277
            this, SLOT (close()));
289
    connect(new QShortcut(nextDocInTabKS, this), SIGNAL (activated()), 
278
    connect(new QShortcut(nextDocInTabKS, this), SIGNAL (activated()), 
290
      this, SLOT (emitShowNext()));
279
            this, SLOT (emitShowNext()));
291
    connect(new QShortcut(prevDocInTabKS, this), SIGNAL (activated()), 
280
    connect(new QShortcut(prevDocInTabKS, this), SIGNAL (activated()), 
292
      this, SLOT (emitShowPrev()));
281
            this, SLOT (emitShowPrev()));
293
    connect(new QShortcut(closeTabKS, this), SIGNAL (activated()), 
282
    connect(new QShortcut(closeTabKS, this), SIGNAL (activated()), 
294
      this, SLOT (closeCurrentTab()));
283
            this, SLOT (closeCurrentTab()));
295
    connect(new QShortcut(printTabKS, this), SIGNAL (activated()), 
284
    connect(new QShortcut(printTabKS, this), SIGNAL (activated()), 
296
      this, SIGNAL (printCurrentPreviewRequest()));
285
            this, SIGNAL (printCurrentPreviewRequest()));
297
286
298
    m_dynSearchActive = false;
287
    m_dynSearchActive = false;
299
    m_canBeep = true;
288
    m_canBeep = true;
300
    if (prefs.pvwidth > 100) {
289
    if (prefs.pvwidth > 100) {
301
  resize(prefs.pvwidth, prefs.pvheight);
290
        resize(prefs.pvwidth, prefs.pvheight);
302
    }
291
    }
303
    m_loading = false;
292
    m_loading = false;
304
    currentChanged(pvTab->currentIndex());
293
    currentChanged(pvTab->currentIndex());
305
    m_justCreated = true;
294
    m_justCreated = true;
306
}
295
}
307
296
308
void Preview::emitShowNext()
297
void Preview::emitShowNext()
309
{
298
{
310
    if (m_loading)
299
    if (m_loading)
311
  return;
300
        return;
312
    PreviewTextEdit *edit = currentEditor();
301
    PreviewTextEdit *edit = currentEditor();
313
    if (edit) {
302
    if (edit) {
314
  emit(showNext(this, m_searchId, edit->m_docnum));
303
        emit(showNext(this, m_searchId, edit->m_docnum));
315
    }
304
    }
316
}
305
}
317
306
318
void Preview::emitShowPrev()
307
void Preview::emitShowPrev()
319
{
308
{
320
    if (m_loading)
309
    if (m_loading)
321
  return;
310
        return;
322
    PreviewTextEdit *edit = currentEditor();
311
    PreviewTextEdit *edit = currentEditor();
323
    if (edit) {
312
    if (edit) {
324
  emit(showPrev(this, m_searchId, edit->m_docnum));
313
        emit(showPrev(this, m_searchId, edit->m_docnum));
325
    }
314
    }
326
}
315
}
327
316
328
void Preview::closeEvent(QCloseEvent *e)
317
void Preview::closeEvent(QCloseEvent *e)
329
{
318
{
330
    LOGDEB(("Preview::closeEvent. m_loading %d\n", m_loading));
319
    LOGDEB(("Preview::closeEvent. m_loading %d\n", m_loading));
331
    if (m_loading) {
320
    if (m_loading) {
332
  CancelCheck::instance().setCancel();
321
        CancelCheck::instance().setCancel();
333
  e->ignore();
322
        e->ignore();
334
  return;
323
        return;
335
    }
324
    }
336
    prefs.pvwidth = width();
325
    prefs.pvwidth = width();
337
    prefs.pvheight = height();
326
    prefs.pvheight = height();
338
327
339
    /* Release all temporary files (but maybe none is actually set) */
328
    /* Release all temporary files (but maybe none is actually set) */
340
    for (int i = 0; i < pvTab->count(); i++) {
329
    for (int i = 0; i < pvTab->count(); i++) {
341
        QWidget *tw = pvTab->widget(i);
330
        QWidget *tw = pvTab->widget(i);
342
        if (tw) {
331
        if (tw) {
343
      PreviewTextEdit *edit = 
332
            PreviewTextEdit *edit = 
344
      tw->findChild<PreviewTextEdit*>("pvEdit");
333
                tw->findChild<PreviewTextEdit*>("pvEdit");
345
            if (edit) {
334
            if (edit) {
346
      forgetTempFile(edit->m_tmpfilename);
335
                forgetTempFile(edit->m_tmpfilename);
347
            }
336
            }
348
        }
337
        }
349
    }
338
    }
350
    emit previewExposed(this, m_searchId, -1);
339
    emit previewExposed(this, m_searchId, -1);
351
    emit previewClosed(this);
340
    emit previewClosed(this);
...
...
356
345
357
bool Preview::eventFilter(QObject *target, QEvent *event)
346
bool Preview::eventFilter(QObject *target, QEvent *event)
358
{
347
{
359
    if (event->type() != QEvent::KeyPress) {
348
    if (event->type() != QEvent::KeyPress) {
360
#if 0
349
#if 0
361
    LOGDEB(("Preview::eventFilter(): %s\n", eventTypeToStr(event->type())));
350
        LOGDEB(("Preview::eventFilter(): %s\n", eventTypeToStr(event->type())));
362
  if (event->type() == QEvent::MouseButtonRelease) {
351
        if (event->type() == QEvent::MouseButtonRelease) {
363
      QMouseEvent *mev = (QMouseEvent *)event;
352
            QMouseEvent *mev = (QMouseEvent *)event;
364
      LOGDEB(("Mouse: GlobalY %d y %d\n", mev->globalY(),
353
            LOGDEB(("Mouse: GlobalY %d y %d\n", mev->globalY(),
365
          mev->y()));
354
                    mev->y()));
366
  }
355
        }
367
#endif
356
#endif
368
  return false;
357
        return false;
369
    }
358
    }
370
359
371
    PreviewTextEdit *edit = currentEditor();
360
    PreviewTextEdit *edit = currentEditor();
372
    QKeyEvent *keyEvent = (QKeyEvent *)event;
361
    QKeyEvent *keyEvent = (QKeyEvent *)event;
373
362
374
    if (m_dynSearchActive) {
363
    if (m_dynSearchActive) {
375
  if (keyEvent->key() == Qt::Key_F3) {
364
        if (keyEvent->key() == Qt::Key_F3) {
376
      LOGDEB2(("Preview::eventFilter: got F3\n"));
365
            LOGDEB2(("Preview::eventFilter: got F3\n"));
377
      doSearch(searchTextCMB->currentText(), true, 
366
            doSearch(searchTextCMB->currentText(), true, 
378
           (keyEvent->modifiers() & Qt::ShiftModifier) != 0);
367
                     (keyEvent->modifiers() & Qt::ShiftModifier) != 0);
379
      return true;
368
            return true;
380
  }
369
        }
381
  if (target != searchTextCMB)
370
        if (target != searchTextCMB)
382
      return QApplication::sendEvent(searchTextCMB, event);
371
            return QApplication::sendEvent(searchTextCMB, event);
383
    } else {
372
    } else {
384
  if (edit && 
373
        if (edit && 
385
      (target == edit || target == edit->viewport())) {
374
            (target == edit || target == edit->viewport())) {
386
      if (keyEvent->key() == Qt::Key_Slash ||
375
            if (keyEvent->key() == Qt::Key_Slash ||
387
      (keyEvent->key() == Qt::Key_F &&
376
                (keyEvent->key() == Qt::Key_F &&
388
       (keyEvent->modifiers() & Qt::ControlModifier))) {
377
                 (keyEvent->modifiers() & Qt::ControlModifier))) {
389
      LOGDEB2(("Preview::eventFilter: got / or C-F\n"));
378
                LOGDEB2(("Preview::eventFilter: got / or C-F\n"));
390
      searchTextCMB->setFocus();
379
                searchTextCMB->setFocus();
391
      m_dynSearchActive = true;
380
                m_dynSearchActive = true;
392
      return true;
381
                return true;
393
      } else if (keyEvent->key() == Qt::Key_Space) {
382
            } else if (keyEvent->key() == Qt::Key_Space) {
394
      LOGDEB2(("Preview::eventFilter: got Space\n"));
383
                LOGDEB2(("Preview::eventFilter: got Space\n"));
395
      int value = edit->verticalScrollBar()->value();
384
                int value = edit->verticalScrollBar()->value();
396
      value += edit->verticalScrollBar()->pageStep();
385
                value += edit->verticalScrollBar()->pageStep();
397
      edit->verticalScrollBar()->setValue(value);
386
                edit->verticalScrollBar()->setValue(value);
398
      return true;
387
                return true;
399
      } else if (keyEvent->key() == Qt::Key_Backspace) {
388
            } else if (keyEvent->key() == Qt::Key_Backspace) {
400
      LOGDEB2(("Preview::eventFilter: got Backspace\n"));
389
                LOGDEB2(("Preview::eventFilter: got Backspace\n"));
401
      int value = edit->verticalScrollBar()->value();
390
                int value = edit->verticalScrollBar()->value();
402
      value -= edit->verticalScrollBar()->pageStep();
391
                value -= edit->verticalScrollBar()->pageStep();
403
      edit->verticalScrollBar()->setValue(value);
392
                edit->verticalScrollBar()->setValue(value);
404
      return true;
393
                return true;
405
      }
394
            }
406
  }
395
        }
407
    }
396
    }
408
397
409
    return false;
398
    return false;
410
}
399
}
411
400
412
void Preview::searchTextChanged(const QString & text)
401
void Preview::searchTextChanged(const QString & text)
413
{
402
{
414
    LOGDEB1(("Search line text changed. text: '%s'\n", 
403
    LOGDEB1(("Search line text changed. text: '%s'\n", 
415
       (const char *)text.toUtf8()));
404
             (const char *)text.toUtf8()));
416
    m_searchTextFromIndex = -1;
405
    m_searchTextFromIndex = -1;
417
    if (text.isEmpty()) {
406
    if (text.isEmpty()) {
418
  m_dynSearchActive = false;
407
        m_dynSearchActive = false;
419
  clearPB->setEnabled(false);
408
        clearPB->setEnabled(false);
420
    } else {
409
    } else {
421
  m_dynSearchActive = true;
410
        m_dynSearchActive = true;
422
  clearPB->setEnabled(true);
411
        clearPB->setEnabled(true);
423
  doSearch(text, false, false);
412
        doSearch(text, false, false);
424
    }
413
    }
425
}
414
}
426
415
427
void Preview::searchTextFromIndex(int idx)
416
void Preview::searchTextFromIndex(int idx)
428
{
417
{
...
...
434
{
423
{
435
    LOGDEB2(("Preview::currentEditor()\n"));
424
    LOGDEB2(("Preview::currentEditor()\n"));
436
    QWidget *tw = pvTab->currentWidget();
425
    QWidget *tw = pvTab->currentWidget();
437
    PreviewTextEdit *edit = 0;
426
    PreviewTextEdit *edit = 0;
438
    if (tw) {
427
    if (tw) {
439
  edit = tw->findChild<PreviewTextEdit*>("pvEdit");
428
        edit = tw->findChild<PreviewTextEdit*>("pvEdit");
440
    }
429
    }
441
    return edit;
430
    return edit;
442
}
431
}
443
432
444
// Save current document to file
433
// Save current document to file
445
void Preview::emitSaveDocToFile()
434
void Preview::emitSaveDocToFile()
446
{
435
{
447
    PreviewTextEdit *ce = currentEditor();
436
    PreviewTextEdit *ce = currentEditor();
448
    if (ce && !ce->m_dbdoc.url.empty()) {
437
    if (ce && !ce->m_dbdoc.url.empty()) {
449
  emit saveDocToFile(ce->m_dbdoc);
438
        emit saveDocToFile(ce->m_dbdoc);
450
    }
439
    }
451
}
440
}
452
441
453
// Perform text search. If next is true, we look for the next match of the
442
// Perform text search. If next is true, we look for the next match of the
454
// current search, trying to advance and possibly wrapping around. If next is
443
// current search, trying to advance and possibly wrapping around. If next is
455
// false, the search string has been modified, we search for the new string, 
444
// false, the search string has been modified, we search for the new string, 
456
// starting from the current position
445
// starting from the current position
457
void Preview::doSearch(const QString &_text, bool next, bool reverse, 
446
void Preview::doSearch(const QString &_text, bool next, bool reverse, 
458
             bool wordOnly)
447
                       bool wordOnly)
459
{
448
{
460
    LOGDEB(("Preview::doSearch: text [%s] idx %d next %d rev %d word %d\n", 
449
    LOGDEB(("Preview::doSearch: text [%s] idx %d next %d rev %d word %d\n", 
461
      (const char *)_text.toUtf8(), m_searchTextFromIndex, int(next), 
450
            (const char *)_text.toUtf8(), m_searchTextFromIndex, int(next), 
462
      int(reverse), int(wordOnly)));
451
            int(reverse), int(wordOnly)));
463
    QString text = _text;
452
    QString text = _text;
464
453
465
    bool matchCase = matchCheck->isChecked();
454
    bool matchCase = matchCheck->isChecked();
466
    PreviewTextEdit *edit = currentEditor();
455
    PreviewTextEdit *edit = currentEditor();
467
    if (edit == 0) {
456
    if (edit == 0) {
468
  // ??
457
        // ??
469
  return;
458
        return;
470
    }
459
    }
471
460
472
    if (text.isEmpty() || m_searchTextFromIndex != -1) {
461
    if (text.isEmpty() || m_searchTextFromIndex != -1) {
473
  if (!edit->m_plaintorich->haveAnchors()) {
462
        if (!edit->m_plaintorich->haveAnchors()) {
474
      LOGDEB(("NO ANCHORS\n"));
463
            LOGDEB(("NO ANCHORS\n"));
475
      return;
464
            return;
476
  }
465
        }
477
  // The combobox indices are equal to the search ugroup indices
466
        // The combobox indices are equal to the search ugroup indices
478
  // in hldata, that's how we built the list.
467
        // in hldata, that's how we built the list.
479
  if (reverse) {
468
        if (reverse) {
480
      edit->m_plaintorich->prevAnchorNum(m_searchTextFromIndex);
469
            edit->m_plaintorich->prevAnchorNum(m_searchTextFromIndex);
481
  } else {
470
        } else {
482
      edit->m_plaintorich->nextAnchorNum(m_searchTextFromIndex);
471
            edit->m_plaintorich->nextAnchorNum(m_searchTextFromIndex);
483
  }
472
        }
484
  QString aname = edit->m_plaintorich->curAnchorName();
473
        QString aname = edit->m_plaintorich->curAnchorName();
485
  LOGDEB(("Calling scrollToAnchor(%s)\n", (const char *)aname.toUtf8()));
474
        LOGDEB(("Calling scrollToAnchor(%s)\n", (const char *)aname.toUtf8()));
486
  edit->scrollToAnchor(aname);
475
        edit->scrollToAnchor(aname);
487
  // Position the cursor approximately at the anchor (top of
476
        // Position the cursor approximately at the anchor (top of
488
  // viewport) so that searches start from here
477
        // viewport) so that searches start from here
489
  QTextCursor cursor = edit->cursorForPosition(QPoint(0, 0));
478
        QTextCursor cursor = edit->cursorForPosition(QPoint(0, 0));
490
  edit->setTextCursor(cursor);
479
        edit->setTextCursor(cursor);
491
  return;
480
        return;
492
    }
481
    }
493
482
494
    // If next is false, the user added characters to the current
483
    // If next is false, the user added characters to the current
495
    // search string.  We need to reset the cursor position to the
484
    // search string.  We need to reset the cursor position to the
496
    // start of the previous match, else incremental search is going
485
    // start of the previous match, else incremental search is going
497
    // to look for the next occurrence instead of trying to lenghten
486
    // to look for the next occurrence instead of trying to lenghten
498
    // the current match
487
    // the current match
499
    if (!next) {
488
    if (!next) {
500
  QTextCursor cursor = edit->textCursor();
489
        QTextCursor cursor = edit->textCursor();
501
  cursor.setPosition(cursor.anchor(), QTextCursor::KeepAnchor);
490
        cursor.setPosition(cursor.anchor(), QTextCursor::KeepAnchor);
502
  edit->setTextCursor(cursor);
491
        edit->setTextCursor(cursor);
503
    }
492
    }
504
    Chrono chron;
493
    Chrono chron;
505
    LOGDEB(("Preview::doSearch: first find call\n"));
494
    LOGDEB(("Preview::doSearch: first find call\n"));
506
    QTextDocument::FindFlags flags = 0;
495
    QTextDocument::FindFlags flags = 0;
507
    if (reverse)
496
    if (reverse)
508
  flags |= QTextDocument::FindBackward;
497
        flags |= QTextDocument::FindBackward;
509
    if (wordOnly)
498
    if (wordOnly)
510
  flags |= QTextDocument::FindWholeWords;
499
        flags |= QTextDocument::FindWholeWords;
511
    if (matchCase)
500
    if (matchCase)
512
  flags |= QTextDocument::FindCaseSensitively;
501
        flags |= QTextDocument::FindCaseSensitively;
513
    bool found = edit->find(text, flags);
502
    bool found = edit->find(text, flags);
514
    LOGDEB(("Preview::doSearch: first find call return: found %d %.2f S\n", 
503
    LOGDEB(("Preview::doSearch: first find call return: found %d %.2f S\n", 
515
            found, chron.secs()));
504
            found, chron.secs()));
516
    // If not found, try to wrap around. 
505
    // If not found, try to wrap around. 
517
    if (!found) { 
506
    if (!found) { 
518
  LOGDEB(("Preview::doSearch: wrapping around\n"));
507
        LOGDEB(("Preview::doSearch: wrapping around\n"));
519
  if (reverse) {
508
        if (reverse) {
520
      edit->moveCursor (QTextCursor::End);
509
            edit->moveCursor (QTextCursor::End);
521
  } else {
510
        } else {
522
      edit->moveCursor (QTextCursor::Start);
511
            edit->moveCursor (QTextCursor::Start);
523
  }
512
        }
524
  LOGDEB(("Preview::doSearch: 2nd find call\n"));
513
        LOGDEB(("Preview::doSearch: 2nd find call\n"));
525
        chron.restart();
514
        chron.restart();
526
  found = edit->find(text, flags);
515
        found = edit->find(text, flags);
527
  LOGDEB(("Preview::doSearch: 2nd find call return found %d %.2f S\n",
516
        LOGDEB(("Preview::doSearch: 2nd find call return found %d %.2f S\n",
528
                found, chron.secs()));
517
                found, chron.secs()));
529
    }
518
    }
530
519
531
    if (found) {
520
    if (found) {
532
  m_canBeep = true;
521
        m_canBeep = true;
533
    } else {
522
    } else {
534
  if (m_canBeep)
523
        if (m_canBeep)
535
      QApplication::beep();
524
            QApplication::beep();
536
  m_canBeep = false;
525
        m_canBeep = false;
537
    }
526
    }
538
    LOGDEB(("Preview::doSearch: return\n"));
527
    LOGDEB(("Preview::doSearch: return\n"));
539
}
528
}
540
529
541
void Preview::nextPressed()
530
void Preview::nextPressed()
...
...
554
void Preview::currentChanged(int index)
543
void Preview::currentChanged(int index)
555
{
544
{
556
    LOGDEB2(("PreviewTextEdit::currentChanged\n"));
545
    LOGDEB2(("PreviewTextEdit::currentChanged\n"));
557
    QWidget *tw = pvTab->widget(index);
546
    QWidget *tw = pvTab->widget(index);
558
    PreviewTextEdit *edit = 
547
    PreviewTextEdit *edit = 
559
  tw->findChild<PreviewTextEdit*>("pvEdit");
548
        tw->findChild<PreviewTextEdit*>("pvEdit");
560
    LOGDEB1(("Preview::currentChanged(). Editor: %p\n", edit));
549
    LOGDEB1(("Preview::currentChanged(). Editor: %p\n", edit));
561
    
550
    
562
    if (edit == 0) {
551
    if (edit == 0) {
563
  LOGERR(("Editor child not found\n"));
552
        LOGERR(("Editor child not found\n"));
564
  return;
553
        return;
565
    }
554
    }
566
    edit->setFocus();
555
    edit->setFocus();
567
    // Disconnect the print signal and reconnect it to the current editor
556
    // Disconnect the print signal and reconnect it to the current editor
568
    LOGDEB(("Disconnecting reconnecting print signal\n"));
557
    LOGDEB(("Disconnecting reconnecting print signal\n"));
569
    disconnect(this, SIGNAL(printCurrentPreviewRequest()), 0, 0);
558
    disconnect(this, SIGNAL(printCurrentPreviewRequest()), 0, 0);
...
...
576
565
577
void Preview::closeCurrentTab()
566
void Preview::closeCurrentTab()
578
{
567
{
579
    LOGDEB1(("Preview::closeCurrentTab: m_loading %d\n", m_loading));
568
    LOGDEB1(("Preview::closeCurrentTab: m_loading %d\n", m_loading));
580
    if (m_loading) {
569
    if (m_loading) {
581
  CancelCheck::instance().setCancel();
570
        CancelCheck::instance().setCancel();
582
  return;
571
        return;
583
    }
572
    }
584
    PreviewTextEdit *e = currentEditor();
573
    PreviewTextEdit *e = currentEditor();
585
    if (e)
574
    if (e)
586
  forgetTempFile(e->m_tmpfilename);
575
        forgetTempFile(e->m_tmpfilename);
587
    if (pvTab->count() > 1) {
576
    if (pvTab->count() > 1) {
588
  pvTab->removeTab(pvTab->currentIndex());
577
        pvTab->removeTab(pvTab->currentIndex());
589
    } else {
578
    } else {
590
  close();
579
        close();
591
    }
580
    }
592
}
581
}
593
582
594
PreviewTextEdit *Preview::addEditorTab()
583
PreviewTextEdit *Preview::addEditorTab()
595
{
584
{
...
...
609
{
598
{
610
    LOGDEB1(("Preview::setCurTabProps\n"));
599
    LOGDEB1(("Preview::setCurTabProps\n"));
611
    QString title;
600
    QString title;
612
    string ctitle;
601
    string ctitle;
613
    if (doc.getmeta(Rcl::Doc::keytt, &ctitle) && !ctitle.empty()) {
602
    if (doc.getmeta(Rcl::Doc::keytt, &ctitle) && !ctitle.empty()) {
614
  title = QString::fromUtf8(ctitle.c_str(), ctitle.length());
603
        title = QString::fromUtf8(ctitle.c_str(), ctitle.length());
615
    } else {
604
    } else {
616
        title = QString::fromLocal8Bit(path_getsimple(doc.url).c_str());
605
        title = QString::fromLocal8Bit(path_getsimple(doc.url).c_str());
617
    }
606
    }
618
    if (title.length() > 20) {
607
    if (title.length() > 20) {
619
  title = title.left(10) + "..." + title.right(10);
608
        title = title.left(10) + "..." + title.right(10);
620
    }
609
    }
621
    int curidx = pvTab->currentIndex();
610
    int curidx = pvTab->currentIndex();
622
    pvTab->setTabText(curidx, title);
611
    pvTab->setTabText(curidx, title);
623
612
624
    char datebuf[100];
613
    char datebuf[100];
625
    datebuf[0] = 0;
614
    datebuf[0] = 0;
626
    if (!doc.fmtime.empty() || !doc.dmtime.empty()) {
615
    if (!doc.fmtime.empty() || !doc.dmtime.empty()) {
627
  time_t mtime = doc.dmtime.empty() ? 
616
        time_t mtime = doc.dmtime.empty() ? 
628
      atoll(doc.fmtime.c_str()) : atoll(doc.dmtime.c_str());
617
            atoll(doc.fmtime.c_str()) : atoll(doc.dmtime.c_str());
629
  struct tm *tm = localtime(&mtime);
618
        struct tm *tm = localtime(&mtime);
630
  strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S", tm);
619
        strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S", tm);
631
    }
620
    }
632
    LOGDEB(("Doc.url: [%s]\n", doc.url.c_str()));
621
    LOGDEB(("Doc.url: [%s]\n", doc.url.c_str()));
633
    string url;
622
    string url;
634
    printableUrl(theconfig->getDefCharset(), doc.url, url);
623
    printableUrl(theconfig->getDefCharset(), doc.url, url);
635
    string tiptxt = url + string("\n");
624
    string tiptxt = url + string("\n");
636
    tiptxt += doc.mimetype + " " + string(datebuf) + "\n";
625
    tiptxt += doc.mimetype + " " + string(datebuf) + "\n";
637
    if (!ctitle.empty())
626
    if (!ctitle.empty())
638
  tiptxt += ctitle + "\n";
627
        tiptxt += ctitle + "\n";
639
    pvTab->setTabToolTip(curidx,
628
    pvTab->setTabToolTip(curidx,
640
           QString::fromUtf8(tiptxt.c_str(), tiptxt.length()));
629
                         QString::fromUtf8(tiptxt.c_str(), tiptxt.length()));
641
630
642
    PreviewTextEdit *e = currentEditor();
631
    PreviewTextEdit *e = currentEditor();
643
    if (e) {
632
    if (e) {
644
  e->m_url = doc.url;
633
        e->m_url = doc.url;
645
  e->m_ipath = doc.ipath;
634
        e->m_ipath = doc.ipath;
646
  e->m_docnum = docnum;
635
        e->m_docnum = docnum;
647
    }
636
    }
648
}
637
}
649
638
650
bool Preview::makeDocCurrent(const Rcl::Doc& doc, int docnum, bool sametab)
639
bool Preview::makeDocCurrent(const Rcl::Doc& doc, int docnum, bool sametab)
651
{
640
{
652
    LOGDEB(("Preview::makeDocCurrent: %s\n", doc.url.c_str()));
641
    LOGDEB(("Preview::makeDocCurrent: %s\n", doc.url.c_str()));
653
642
654
    if (m_loading) {
643
    if (m_loading) {
655
  LOGERR(("Already loading\n"));
644
        LOGERR(("Already loading\n"));
656
  return false;
645
        return false;
657
    }
646
    }
658
647
659
    /* Check if we already have this page */
648
    /* Check if we already have this page */
660
    for (int i = 0; i < pvTab->count(); i++) {
649
    for (int i = 0; i < pvTab->count(); i++) {
661
        QWidget *tw = pvTab->widget(i);
650
        QWidget *tw = pvTab->widget(i);
662
        if (tw) {
651
        if (tw) {
663
      PreviewTextEdit *edit = 
652
            PreviewTextEdit *edit = 
664
      tw->findChild<PreviewTextEdit*>("pvEdit");
653
                tw->findChild<PreviewTextEdit*>("pvEdit");
665
            if (edit && !edit->m_url.compare(doc.url) && 
654
            if (edit && !edit->m_url.compare(doc.url) && 
666
                !edit->m_ipath.compare(doc.ipath)) {
655
                !edit->m_ipath.compare(doc.ipath)) {
667
                pvTab->setCurrentIndex(i);
656
                pvTab->setCurrentIndex(i);
668
                return true;
657
                return true;
669
            }
658
            }
670
        }
659
        }
671
    }
660
    }
672
661
673
    // if just created the first tab was created during init
662
    // if just created the first tab was created during init
674
    if (!sametab && !m_justCreated && !addEditorTab()) {
663
    if (!sametab && !m_justCreated && !addEditorTab()) {
675
  return false;
664
        return false;
676
    }
665
    }
677
    m_justCreated = false;
666
    m_justCreated = false;
678
    if (!loadDocInCurrentTab(doc, docnum)) {
667
    if (!loadDocInCurrentTab(doc, docnum)) {
679
  closeCurrentTab();
668
        closeCurrentTab();
680
  return false;
669
        return false;
681
    }
670
    }
682
    raise();
671
    raise();
683
    return true;
672
    return true;
684
}
673
}
685
void Preview::togglePlainPre()
674
void Preview::togglePlainPre()
686
{
675
{
687
    switch (prefs.previewPlainPre) {
676
    switch (prefs.previewPlainPre) {
688
    case PrefsPack::PP_BR:
677
    case PrefsPack::PP_BR:
689
  prefs.previewPlainPre = PrefsPack::PP_PRE;
678
        prefs.previewPlainPre = PrefsPack::PP_PRE;
690
  break;
679
        break;
691
    case PrefsPack::PP_PRE:
680
    case PrefsPack::PP_PRE:
692
  prefs.previewPlainPre = PrefsPack::PP_BR;
681
        prefs.previewPlainPre = PrefsPack::PP_BR;
693
  break;
682
        break;
694
    case PrefsPack::PP_PREWRAP:
683
    case PrefsPack::PP_PREWRAP:
695
    default:
684
    default:
696
  prefs.previewPlainPre = PrefsPack::PP_PRE;
685
        prefs.previewPlainPre = PrefsPack::PP_PRE;
697
  break;
686
        break;
698
    }
687
    }
699
    
688
    
700
    PreviewTextEdit *editor = currentEditor();
689
    PreviewTextEdit *editor = currentEditor();
701
    if (editor)
690
    if (editor)
702
  loadDocInCurrentTab(editor->m_dbdoc, editor->m_docnum);
691
        loadDocInCurrentTab(editor->m_dbdoc, editor->m_docnum);
703
}
692
}
704
693
705
void Preview::emitWordSelect(QString word)
694
void Preview::emitWordSelect(QString word)
706
{
695
{
707
    emit(wordSelect(word));
696
    emit(wordSelect(word));
...
...
727
class LoadThread : public QThread {
716
class LoadThread : public QThread {
728
    int *statusp;
717
    int *statusp;
729
    Rcl::Doc& out;
718
    Rcl::Doc& out;
730
    const Rcl::Doc& idoc;
719
    const Rcl::Doc& idoc;
731
    int loglevel;
720
    int loglevel;
732
 public: 
721
public: 
733
    string missing;
722
    string missing;
734
    TempFile imgtmp;
723
    TempFile imgtmp;
735
724
736
    LoadThread(int *stp, Rcl::Doc& odoc, const Rcl::Doc& idc) 
725
    LoadThread(int *stp, Rcl::Doc& odoc, const Rcl::Doc& idc) 
737
  : statusp(stp), out(odoc), idoc(idc)
726
        : statusp(stp), out(odoc), idoc(idc)
738
  {
727
        {
739
      loglevel = DebugLog::getdbl()->getlevel();
728
            loglevel = DebugLog::getdbl()->getlevel();
740
  }
729
        }
741
    ~LoadThread() {
730
    ~LoadThread() {
742
    }
731
    }
743
    virtual void run() {
732
    virtual void run() {
744
  DebugLog::getdbl()->setloglevel(loglevel);
733
        DebugLog::getdbl()->setloglevel(loglevel);
745
746
  FileInterner interner(idoc, theconfig, FileInterner::FIF_forPreview);
734
        FileInterner interner(idoc, theconfig, FileInterner::FIF_forPreview);
747
  FIMissingStore mst;
735
        FIMissingStore mst;
748
  interner.setMissingStore(&mst);
736
        interner.setMissingStore(&mst);
749
  // Even when previewHtml is set, we don't set the interner's
737
        // Even when previewHtml is set, we don't set the interner's
750
  // target mtype to html because we do want the html filter to
738
        // target mtype to html because we do want the html filter to
751
  // do its work: we won't use the text/plain, but we want the
739
        // do its work: we won't use the text/plain, but we want the
752
  // text/html to be converted to utf-8 (for highlight processing)
740
        // text/html to be converted to utf-8 (for highlight processing)
753
  try {
741
        try {
754
            string ipath = idoc.ipath;
742
            string ipath = idoc.ipath;
755
      FileInterner::Status ret = interner.internfile(out, ipath);
743
            FileInterner::Status ret = interner.internfile(out, ipath);
756
      if (ret == FileInterner::FIDone || ret == FileInterner::FIAgain) {
744
            if (ret == FileInterner::FIDone || ret == FileInterner::FIAgain) {
757
      // FIAgain is actually not nice here. It means that the record
745
                // FIAgain is actually not nice here. It means that the record
758
      // for the *file* of a multidoc was selected. Actually this
746
                // for the *file* of a multidoc was selected. Actually this
759
      // shouldn't have had a preview link at all, but we don't know
747
                // shouldn't have had a preview link at all, but we don't know
760
      // how to handle it now. Better to show the first doc than
748
                // how to handle it now. Better to show the first doc than
761
      // a mysterious error. Happens when the file name matches a
749
                // a mysterious error. Happens when the file name matches a
762
      // a search term.
750
                // a search term.
763
      *statusp = 0;
751
                *statusp = 0;
764
      // If we prefer html and it is available, replace the
752
                // If we prefer html and it is available, replace the
765
      // text/plain document text
753
                // text/plain document text
766
      if (prefs.previewHtml && !interner.get_html().empty()) {
754
                if (prefs.previewHtml && !interner.get_html().empty()) {
767
          out.text = interner.get_html();
755
                    out.text = interner.get_html();
768
          out.mimetype = "text/html";
756
                    out.mimetype = "text/html";
769
      }
757
                }
770
      imgtmp = interner.get_imgtmp();
758
                imgtmp = interner.get_imgtmp();
771
      } else {
759
            } else {
772
      out.mimetype = interner.getMimetype();
760
                out.mimetype = interner.getMimetype();
773
      mst.getMissingExternal(missing);
761
                mst.getMissingExternal(missing);
774
      *statusp = -1;
762
                *statusp = -1;
775
      }
763
            }
776
  } catch (CancelExcept) {
764
        } catch (CancelExcept) {
777
      *statusp = -1;
765
            *statusp = -1;
778
  }
766
        }
779
    }
767
    }
780
};
768
};
781
769
782
770
783
// Insert into editor by chunks so that the top becomes visible
771
// Insert into editor by chunks so that the top becomes visible
...
...
790
    string &in;
778
    string &in;
791
    const HighlightData &hdata;
779
    const HighlightData &hdata;
792
    list<string> &out;
780
    list<string> &out;
793
    int loglevel;
781
    int loglevel;
794
    PlainToRichQtPreview *ptr;
782
    PlainToRichQtPreview *ptr;
795
 public:
783
public:
796
    ToRichThread(string &i, const HighlightData& hd, list<string> &o, 
784
    ToRichThread(string &i, const HighlightData& hd, list<string> &o, 
797
       PlainToRichQtPreview *_ptr)
785
                 PlainToRichQtPreview *_ptr)
798
  : in(i), hdata(hd), out(o), ptr(_ptr)
786
        : in(i), hdata(hd), out(o), ptr(_ptr)
799
    {
787
        {
800
      loglevel = DebugLog::getdbl()->getlevel();
788
            loglevel = DebugLog::getdbl()->getlevel();
801
    }
789
        }
802
    virtual void run()
790
    virtual void run()
803
    {
791
        {
804
  DebugLog::getdbl()->setloglevel(loglevel);
792
            DebugLog::getdbl()->setloglevel(loglevel);
805
  try {
793
            try {
806
      ptr->plaintorich(in, out, hdata, CHUNKL);
794
                ptr->plaintorich(in, out, hdata, CHUNKL);
807
  } catch (CancelExcept) {
795
            } catch (CancelExcept) {
808
  }
796
            }
809
    }
797
        }
810
};
798
};
811
799
812
class LoadGuard {
800
class LoadGuard {
813
    bool *m_bp;
801
    bool *m_bp;
814
public:
802
public:
...
...
824
    CancelCheck::instance().setCancel(false);
812
    CancelCheck::instance().setCancel(false);
825
813
826
    setCurTabProps(idoc, docnum);
814
    setCurTabProps(idoc, docnum);
827
815
828
    QString msg = QString("Loading: %1 (size %2 bytes)")
816
    QString msg = QString("Loading: %1 (size %2 bytes)")
829
  .arg(QString::fromLocal8Bit(idoc.url.c_str()))
817
        .arg(QString::fromLocal8Bit(idoc.url.c_str()))
830
  .arg(QString::fromUtf8(idoc.fbytes.c_str()));
818
        .arg(QString::fromUtf8(idoc.fbytes.c_str()));
831
819
832
    // Create progress dialog and aux objects
833
    const int nsteps = 20;
834
    QProgressDialog progress(msg, tr("Cancel"), 0, nsteps, this);
820
    QProgressDialog progress(msg, tr("Cancel"), 0, 0, this);
835
    progress.setMinimumDuration(2000);
821
    progress.setMinimumDuration(2000);
822
    QEventLoop loop;
823
    QTimer tT;
824
    tT.setSingleShot(true);
825
    connect(&tT, SIGNAL(timeout()), &loop, SLOT(quit()));
836
826
837
    ////////////////////////////////////////////////////////////////////////
827
    ////////////////////////////////////////////////////////////////////////
838
    // Load and convert document
828
    // Load and convert document
839
    // idoc came out of the index data (main text and some fields missing). 
829
    // idoc came out of the index data (main text and some fields missing). 
840
    // fdoc is the complete one what we are going to extract from storage.
830
    // fdoc is the complete one what we are going to extract from storage.
841
    Rcl::Doc fdoc;
831
    Rcl::Doc fdoc;
842
    int status = 1;
832
    int status = 1;
843
    LoadThread lthr(&status, fdoc, idoc);
833
    LoadThread lthr(&status, fdoc, idoc);
834
    connect(&lthr, SIGNAL(finished()), &loop, SLOT(quit()));
835
844
    lthr.start();
836
    lthr.start();
845
    int prog;
837
    for (int i = 0;;i++) {
846
    for (prog = 1;;prog++) {
838
        tT.start(1000); 
847
  if (lthr.wait(100))
839
        loop.exec();
848
      break;
840
        if (lthr.isFinished())
849
  progress.setValue(prog);
841
            break;
850
  qApp->processEvents();
851
  if (progress.wasCanceled()) {
842
        if (progress.wasCanceled()) {
852
      CancelCheck::instance().setCancel();
843
            CancelCheck::instance().setCancel();
853
  }
844
        }
854
  if (prog >= 5)
845
        if (i == 2)
855
      sleep(1);
846
            progress.show();
856
    }
847
    }
857
848
858
    LOGDEB(("loadDocInCurrentTab: after file load: cancel %d status %d"
849
    LOGDEB(("loadDocInCurrentTab: after file load: cancel %d status %d"
859
      " text length %d\n", 
850
            " text length %d\n", 
860
      CancelCheck::instance().cancelState(), status, fdoc.text.length()));
851
            CancelCheck::instance().cancelState(), status, fdoc.text.length()));
861
852
862
    if (CancelCheck::instance().cancelState())
853
    if (CancelCheck::instance().cancelState())
863
  return false;
854
        return false;
864
    if (status != 0) {
855
    if (status != 0) {
856
        progress.close();
865
        QString explain;
857
        QString explain;
866
  if (!lthr.missing.empty()) {
858
        if (!lthr.missing.empty()) {
867
            explain = QString::fromUtf8("<br>") +
859
            explain = QString::fromUtf8("<br>") +
868
                tr("Missing helper program: ") +
860
                tr("Missing helper program: ") +
869
                QString::fromLocal8Bit(lthr.missing.c_str());
861
                QString::fromLocal8Bit(lthr.missing.c_str());
870
      QMessageBox::warning(0, "Recoll",
862
            QMessageBox::warning(0, "Recoll",
871
               tr("Can't turn doc into internal "
863
                                 tr("Can't turn doc into internal "
872
                  "representation for ") +
864
                                    "representation for ") +
873
               fdoc.mimetype.c_str() + explain);
865
                                 fdoc.mimetype.c_str() + explain);
874
        } else {
866
        } else {
875
      QMessageBox::warning(0, "Recoll", 
867
            QMessageBox::warning(0, "Recoll", 
876
                tr("Error while loading file"));
868
                                 tr("Error while loading file"));
877
  }
869
        }
878
870
879
  return false;
871
        return false;
880
    }
872
    }
881
    // Reset config just in case.
873
    // Reset config just in case.
882
    theconfig->setKeyDir("");
874
    theconfig->setKeyDir("");
883
875
884
    ////////////////////////////////////////////////////////////////////////
876
    ////////////////////////////////////////////////////////////////////////
885
    // Create preview text: highlight search terms
877
    // Create preview text: highlight search terms
886
    // We don't do the highlighting for very big texts: too long. We
878
    // We don't do the highlighting for very big texts: too long. We
887
    // should at least do special char escaping, in case a '&' or '<'
879
    // should at least do special char escaping, in case a '&' or '<'
888
    // somehow slipped through previous processing.
880
    // somehow slipped through previous processing.
889
    bool highlightTerms = fdoc.text.length() < 
881
    bool highlightTerms = fdoc.text.length() < 
890
  (unsigned long)prefs.maxhltextmbs * 1024 * 1024;
882
        (unsigned long)prefs.maxhltextmbs * 1024 * 1024;
891
883
892
    // Final text is produced in chunks so that we can display the top
884
    // Final text is produced in chunks so that we can display the top
893
    // while still inserting at bottom
885
    // while still inserting at bottom
894
    list<QString> qrichlst;
886
    list<QString> qrichlst;
895
    PreviewTextEdit *editor = currentEditor();
887
    PreviewTextEdit *editor = currentEditor();
...
...
903
    // relatively limited html support (text sometimes get hidden by
895
    // relatively limited html support (text sometimes get hidden by
904
    // images).
896
    // images).
905
#if 0
897
#if 0
906
    string path = fileurltolocalpath(idoc.url);
898
    string path = fileurltolocalpath(idoc.url);
907
    if (!path.empty()) {
899
    if (!path.empty()) {
908
  path = path_getfather(path);
900
        path = path_getfather(path);
909
  QStringList paths(QString::fromLocal8Bit(path.c_str()));
901
        QStringList paths(QString::fromLocal8Bit(path.c_str()));
910
  editor->setSearchPaths(paths);
902
        editor->setSearchPaths(paths);
911
    }
903
    }
912
#endif
904
#endif
913
905
914
    editor->setHtml("");
906
    editor->setHtml("");
915
    editor->m_format = Qt::RichText;
907
    editor->m_format = Qt::RichText;
...
...
917
909
918
#if 0
910
#if 0
919
    // For testing qtextedit bugs...
911
    // For testing qtextedit bugs...
920
    highlightTerms = true;
912
    highlightTerms = true;
921
    const char *textlist[] =
913
    const char *textlist[] =
922
    {
914
        {
923
        "Du plain text avec un\n <termtag>termtag</termtag> fin de ligne:",
915
            "Du plain text avec un\n <termtag>termtag</termtag> fin de ligne:",
924
        "texte apres le tag\n",
916
            "texte apres le tag\n",
925
    };
917
        };
926
    const int listl = sizeof(textlist) / sizeof(char*);
918
    const int listl = sizeof(textlist) / sizeof(char*);
927
    for (int i = 0 ; i < listl ; i++)
919
    for (int i = 0 ; i < listl ; i++)
928
        qrichlst.push_back(QString::fromUtf8(textlist[i]));
920
        qrichlst.push_back(QString::fromUtf8(textlist[i]));
929
#else
921
#else
930
    if (highlightTerms) {
922
    if (highlightTerms) {
931
  progress.setLabelText(tr("Creating preview text"));
923
        progress.setLabelText(tr("Creating preview text"));
932
  qApp->processEvents();
924
        qApp->processEvents();
933
925
934
  if (inputishtml) {
926
        if (inputishtml) {
935
      LOGDEB1(("Preview: got html %s\n", fdoc.text.c_str()));
927
            LOGDEB1(("Preview: got html %s\n", fdoc.text.c_str()));
936
      editor->m_plaintorich->set_inputhtml(true);
928
            editor->m_plaintorich->set_inputhtml(true);
937
  } else {
929
        } else {
938
      LOGDEB1(("Preview: got plain %s\n", fdoc.text.c_str()));
930
            LOGDEB1(("Preview: got plain %s\n", fdoc.text.c_str()));
939
      editor->m_plaintorich->set_inputhtml(false);
931
            editor->m_plaintorich->set_inputhtml(false);
940
  }
932
        }
941
  list<string> richlst;
933
        list<string> richlst;
942
  ToRichThread rthr(fdoc.text, m_hData, richlst, editor->m_plaintorich);
934
        ToRichThread rthr(fdoc.text, m_hData, richlst, editor->m_plaintorich);
935
        connect(&rthr, SIGNAL(finished()), &loop, SLOT(quit()));
943
  rthr.start();
936
        rthr.start();
944
937
945
  for (;;prog++) {
938
        for (;;) {
946
      if (rthr.wait(100))
939
            tT.start(1000); 
947
      break;
940
            loop.exec();
948
      progress.setValue(nsteps);
941
            if (rthr.isFinished())
949
      qApp->processEvents();
942
                break;
950
      if (progress.wasCanceled()) {
943
            if (progress.wasCanceled()) {
951
      CancelCheck::instance().setCancel();
944
                CancelCheck::instance().setCancel();
952
      }
945
            }
953
      if (prog >= 5)
946
        }
954
      sleep(1);
955
  }
956
947
957
  // Conversion to rich text done
948
        // Conversion to rich text done
958
  if (CancelCheck::instance().cancelState()) {
949
        if (CancelCheck::instance().cancelState()) {
959
      if (richlst.size() == 0 || richlst.front().length() == 0) {
950
            if (richlst.size() == 0 || richlst.front().length() == 0) {
960
      // We can't call closeCurrentTab here as it might delete
951
                // We can't call closeCurrentTab here as it might delete
961
      // the object which would be a nasty surprise to our
952
                // the object which would be a nasty surprise to our
962
      // caller.
953
                // caller.
963
      return false;
954
                return false;
964
      } else {
955
            } else {
965
      richlst.back() += "<b>Cancelled !</b>";
956
                richlst.back() += "<b>Cancelled !</b>";
966
      }
957
            }
967
  }
958
        }
968
  // Convert C++ string list to QString list
959
        // Convert C++ string list to QString list
969
  for (list<string>::iterator it = richlst.begin(); 
960
        for (list<string>::iterator it = richlst.begin(); 
970
       it != richlst.end(); it++) {
961
             it != richlst.end(); it++) {
971
      qrichlst.push_back(QString::fromUtf8(it->c_str(), it->length()));
962
            qrichlst.push_back(QString::fromUtf8(it->c_str(), it->length()));
972
  }
963
        }
973
    } else {
964
    } else {
974
  LOGDEB(("Preview: no hilighting\n"));
965
        LOGDEB(("Preview: no hilighting\n"));
975
  // No plaintorich() call.  In this case, either the text is
966
        // No plaintorich() call.  In this case, either the text is
976
  // html and the html quoting is hopefully correct, or it's
967
        // html and the html quoting is hopefully correct, or it's
977
  // plain-text and there is no need to escape special
968
        // plain-text and there is no need to escape special
978
  // characters. We'd still want to split in chunks (so that the
969
        // characters. We'd still want to split in chunks (so that the
979
  // top is displayed faster), but we must not cut tags, and
970
        // top is displayed faster), but we must not cut tags, and
980
  // it's too difficult on html. For text we do the splitting on
971
        // it's too difficult on html. For text we do the splitting on
981
  // a QString to avoid utf8 issues.
972
        // a QString to avoid utf8 issues.
982
  QString qr = QString::fromUtf8(fdoc.text.c_str(), fdoc.text.length());
973
        QString qr = QString::fromUtf8(fdoc.text.c_str(), fdoc.text.length());
983
  int l = 0;
974
        int l = 0;
984
  if (inputishtml) {
975
        if (inputishtml) {
985
      qrichlst.push_back(qr);
976
            qrichlst.push_back(qr);
986
  } else {
977
        } else {
987
            editor->setPlainText("");
978
            editor->setPlainText("");
988
            editor->m_format = Qt::PlainText;
979
            editor->m_format = Qt::PlainText;
989
      for (int pos = 0; pos < (int)qr.length(); pos += l) {
980
            for (int pos = 0; pos < (int)qr.length(); pos += l) {
990
      l = MIN(CHUNKL, qr.length() - pos);
981
                l = MIN(CHUNKL, qr.length() - pos);
991
      qrichlst.push_back(qr.mid(pos, l));
982
                qrichlst.push_back(qr.mid(pos, l));
992
      }
983
            }
993
  }
984
        }
994
    }
985
    }
995
#endif
986
#endif
996
997
987
998
988
999
    ///////////////////////////////////////////////////////////
989
    ///////////////////////////////////////////////////////////
1000
    // Load text into editor window.
990
    // Load text into editor window.
1001
    prog = 2 * nsteps / 3;
1002
    progress.setLabelText(tr("Loading preview text into editor"));
991
    progress.setLabelText(tr("Loading preview text into editor"));
1003
    qApp->processEvents();
992
    qApp->processEvents();
1004
    int instep = 0;
1005
    for (list<QString>::iterator it = qrichlst.begin(); 
993
    for (list<QString>::iterator it = qrichlst.begin(); 
1006
   it != qrichlst.end(); it++, prog++, instep++) {
994
         it != qrichlst.end(); it++) {
1007
  progress.setValue(prog);
1008
  qApp->processEvents();
995
        qApp->processEvents();
1009
996
1010
  editor->append(*it);
997
        editor->append(*it);
1011
        // We need to save the rich text for printing, the editor does
998
        // We need to save the rich text for printing, the editor does
1012
        // not do it consistently for us.
999
        // not do it consistently for us.
1013
        editor->m_richtxt.append(*it);
1000
        editor->m_richtxt.append(*it);
1014
1001
1015
  if (progress.wasCanceled()) {
1002
        if (progress.wasCanceled()) {
1016
            editor->append("<b>Cancelled !</b>");
1003
            editor->append("<b>Cancelled !</b>");
1017
      LOGDEB(("loadDocInCurrentTab: cancelled in editor load\n"));
1004
            LOGDEB(("loadDocInCurrentTab: cancelled in editor load\n"));
1018
      break;
1005
            break;
1019
  }
1006
        }
1020
    }
1007
    }
1021
1008
1022
    progress.close();
1009
    progress.close();
1023
    editor->m_curdsp = PreviewTextEdit::PTE_DSPTXT;
1010
    editor->m_curdsp = PreviewTextEdit::PTE_DSPTXT;
1024
1011
...
...
1036
    if (textempty)
1023
    if (textempty)
1037
        editor->displayFields();
1024
        editor->displayFields();
1038
1025
1039
    // If this is an image, display it instead of the text.
1026
    // If this is an image, display it instead of the text.
1040
    if (!idoc.mimetype.compare(0, 6, "image/")) {
1027
    if (!idoc.mimetype.compare(0, 6, "image/")) {
1041
  string fn = fileurltolocalpath(idoc.url);
1028
        string fn = fileurltolocalpath(idoc.url);
1042
1029
1043
  // If the command wants a file but this is not a file url, or
1030
        // If the command wants a file but this is not a file url, or
1044
  // there is an ipath that it won't understand, we need a temp file:
1031
        // there is an ipath that it won't understand, we need a temp file:
1045
  theconfig->setKeyDir(path_getfather(fn));
1032
        theconfig->setKeyDir(path_getfather(fn));
1046
  if (fn.empty() || !idoc.ipath.empty()) {
1033
        if (fn.empty() || !idoc.ipath.empty()) {
1047
      TempFile temp = lthr.imgtmp;
1034
            TempFile temp = lthr.imgtmp;
1048
      if (temp) {
1035
            if (temp) {
1049
      LOGDEB1(("Preview: load: got temp file from internfile\n"));
1036
                LOGDEB1(("Preview: load: got temp file from internfile\n"));
1050
      } else if (!FileInterner::idocToFile(temp, string(), 
1037
            } else if (!FileInterner::idocToFile(temp, string(), 
1051
                       theconfig, idoc)) {
1038
                                                 theconfig, idoc)) {
1052
      temp.reset(); // just in case.
1039
                temp.reset(); // just in case.
1040
            }
1041
            if (temp) {
1042
                rememberTempFile(temp);
1043
                fn = temp->filename();
1044
                editor->m_tmpfilename = fn;
1045
            } else {
1046
                editor->m_tmpfilename.erase();
1047
                fn.erase();
1048
            }
1049
        }
1050
1051
        if (!fn.empty()) {
1052
            editor->m_image = QImage(fn.c_str());
1053
            if (!editor->m_image.isNull())
1054
                editor->displayImage();
1055
        }
1053
      }
1056
    }
1054
      if (temp) {
1055
      rememberTempFile(temp);
1056
      fn = temp->filename();
1057
      editor->m_tmpfilename = fn;
1058
      } else {
1059
      editor->m_tmpfilename.erase();
1060
      fn.erase();
1061
      }
1062
  }
1063
1064
  if (!fn.empty()) {
1065
      editor->m_image = QImage(fn.c_str());
1066
      if (!editor->m_image.isNull())
1067
      editor->displayImage();
1068
  }
1069
     }
1070
1057
1071
1058
1072
    // Position the editor so that the first search term is visible
1059
    // Position the editor so that the first search term is visible
1073
    if (searchTextCMB->currentText().length() != 0) {
1060
    if (searchTextCMB->currentText().length() != 0) {
1074
  // If there is a current search string, perform the search
1061
        // If there is a current search string, perform the search
1075
  m_canBeep = true;
1062
        m_canBeep = true;
1076
  doSearch(searchTextCMB->currentText(), true, false);
1063
        doSearch(searchTextCMB->currentText(), true, false);
1077
    } else {
1064
    } else {
1078
  // Position to the first query term
1065
        // Position to the first query term
1079
  if (editor->m_plaintorich->haveAnchors()) {
1066
        if (editor->m_plaintorich->haveAnchors()) {
1080
      QString aname = editor->m_plaintorich->curAnchorName();
1067
            QString aname = editor->m_plaintorich->curAnchorName();
1081
      LOGDEB2(("Call movetoanchor(%s)\n", (const char *)aname.toUtf8()));
1068
            LOGDEB2(("Call movetoanchor(%s)\n", (const char *)aname.toUtf8()));
1082
      editor->scrollToAnchor(aname);
1069
            editor->scrollToAnchor(aname);
1083
      // Position the cursor approximately at the anchor (top of
1070
            // Position the cursor approximately at the anchor (top of
1084
      // viewport) so that searches start from here
1071
            // viewport) so that searches start from here
1085
      QTextCursor cursor = editor->cursorForPosition(QPoint(0, 0));
1072
            QTextCursor cursor = editor->cursorForPosition(QPoint(0, 0));
1086
      editor->setTextCursor(cursor);
1073
            editor->setTextCursor(cursor);
1087
  }
1074
        }
1088
    }
1075
    }
1089
1076
1090
1077
1091
    // Enter document in document history
1078
    // Enter document in document history
1092
    string udi;
1079
    string udi;
...
...
1106
      m_dspflds(false), m_docnum(-1) 
1093
      m_dspflds(false), m_docnum(-1) 
1107
{
1094
{
1108
    setContextMenuPolicy(Qt::CustomContextMenu);
1095
    setContextMenuPolicy(Qt::CustomContextMenu);
1109
    setObjectName(nm);
1096
    setObjectName(nm);
1110
    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
1097
    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
1111
      this, SLOT(createPopupMenu(const QPoint&)));
1098
            this, SLOT(createPopupMenu(const QPoint&)));
1112
    setOpenExternalLinks(false);
1099
    setOpenExternalLinks(false);
1113
    setOpenLinks(false);
1100
    setOpenLinks(false);
1114
}
1101
}
1115
1102
1116
PreviewTextEdit::~PreviewTextEdit()
1103
PreviewTextEdit::~PreviewTextEdit()
...
...
1122
{
1109
{
1123
    LOGDEB1(("PreviewTextEdit::createPopupMenu()\n"));
1110
    LOGDEB1(("PreviewTextEdit::createPopupMenu()\n"));
1124
    QMenu *popup = new QMenu(this);
1111
    QMenu *popup = new QMenu(this);
1125
    switch (m_curdsp) {
1112
    switch (m_curdsp) {
1126
    case PTE_DSPTXT:
1113
    case PTE_DSPTXT:
1127
  popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
1114
        popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
1128
  if (!m_image.isNull())
1115
        if (!m_image.isNull())
1129
      popup->addAction(tr("Show image"), this, SLOT(displayImage()));
1116
            popup->addAction(tr("Show image"), this, SLOT(displayImage()));
1130
  break;
1117
        break;
1131
    case PTE_DSPFLDS:
1118
    case PTE_DSPFLDS:
1132
  popup->addAction(tr("Show main text"), this, SLOT(displayText()));
1119
        popup->addAction(tr("Show main text"), this, SLOT(displayText()));
1133
  if (!m_image.isNull())
1120
        if (!m_image.isNull())
1134
      popup->addAction(tr("Show image"), this, SLOT(displayImage()));
1121
            popup->addAction(tr("Show image"), this, SLOT(displayImage()));
1135
  break;
1122
        break;
1136
    case PTE_DSPIMG:
1123
    case PTE_DSPIMG:
1137
    default:
1124
    default:
1138
  popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
1125
        popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
1139
  popup->addAction(tr("Show main text"), this, SLOT(displayText()));
1126
        popup->addAction(tr("Show main text"), this, SLOT(displayText()));
1140
  break;
1127
        break;
1141
    }
1128
    }
1142
    popup->addAction(tr("Select All"), this, SLOT(selectAll()));
1129
    popup->addAction(tr("Select All"), this, SLOT(selectAll()));
1143
    popup->addAction(tr("Copy"), this, SLOT(copy()));
1130
    popup->addAction(tr("Copy"), this, SLOT(copy()));
1144
    popup->addAction(tr("Print"), this, SLOT(print()));
1131
    popup->addAction(tr("Print"), this, SLOT(print()));
1145
    if (prefs.previewPlainPre) {
1132
    if (prefs.previewPlainPre) {
1146
  popup->addAction(tr("Fold lines"), m_preview, SLOT(togglePlainPre()));
1133
        popup->addAction(tr("Fold lines"), m_preview, SLOT(togglePlainPre()));
1147
    } else {
1134
    } else {
1148
  popup->addAction(tr("Preserve indentation"), 
1135
        popup->addAction(tr("Preserve indentation"), 
1149
           m_preview, SLOT(togglePlainPre()));
1136
                         m_preview, SLOT(togglePlainPre()));
1150
    }
1137
    }
1151
    // Need to check ipath until we fix the internfile bug that always
1138
    // Need to check ipath until we fix the internfile bug that always
1152
    // has it convert to html for top level docs
1139
    // has it convert to html for top level docs
1153
    if (!m_dbdoc.url.empty() && !m_dbdoc.ipath.empty())
1140
    if (!m_dbdoc.url.empty() && !m_dbdoc.ipath.empty())
1154
  popup->addAction(tr("Save document to file"), 
1141
        popup->addAction(tr("Save document to file"), 
1155
           m_preview, SLOT(emitSaveDocToFile()));
1142
                         m_preview, SLOT(emitSaveDocToFile()));
1156
    popup->popup(mapToGlobal(pos));
1143
    popup->popup(mapToGlobal(pos));
1157
}
1144
}
1158
1145
1159
// Display main text
1146
// Display main text
1160
void PreviewTextEdit::displayText()
1147
void PreviewTextEdit::displayText()
1161
{
1148
{
1162
    LOGDEB1(("PreviewTextEdit::displayText()\n"));
1149
    LOGDEB1(("PreviewTextEdit::displayText()\n"));
1163
    if (m_format == Qt::PlainText)
1150
    if (m_format == Qt::PlainText)
1164
  setPlainText(m_richtxt);
1151
        setPlainText(m_richtxt);
1165
    else
1152
    else
1166
  setHtml(m_richtxt);
1153
        setHtml(m_richtxt);
1167
    m_curdsp = PTE_DSPTXT;
1154
    m_curdsp = PTE_DSPTXT;
1168
}
1155
}
1169
1156
1170
// Display field values
1157
// Display field values
1171
void PreviewTextEdit::displayFields()
1158
void PreviewTextEdit::displayFields()
...
...
1173
    LOGDEB1(("PreviewTextEdit::displayFields()\n"));
1160
    LOGDEB1(("PreviewTextEdit::displayFields()\n"));
1174
1161
1175
    QString txt = "<html><head></head><body>\n";
1162
    QString txt = "<html><head></head><body>\n";
1176
    txt += "<b>" + QString::fromLocal8Bit(m_url.c_str());
1163
    txt += "<b>" + QString::fromLocal8Bit(m_url.c_str());
1177
    if (!m_ipath.empty())
1164
    if (!m_ipath.empty())
1178
  txt += "|" + QString::fromUtf8(m_ipath.c_str());
1165
        txt += "|" + QString::fromUtf8(m_ipath.c_str());
1179
    txt += "</b><br><br>";
1166
    txt += "</b><br><br>";
1180
    txt += "<dl>\n";
1167
    txt += "<dl>\n";
1181
    for (map<string,string>::const_iterator it = m_fdoc.meta.begin();
1168
    for (map<string,string>::const_iterator it = m_fdoc.meta.begin();
1182
   it != m_fdoc.meta.end(); it++) {
1169
         it != m_fdoc.meta.end(); it++) {
1183
  if (!it->second.empty())
1170
        if (!it->second.empty())
1184
      txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> " 
1171
            txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> " 
1185
      + "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str()) 
1172
                + "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str()) 
1186
      + "</dd>\n";
1173
                + "</dd>\n";
1187
    }
1174
    }
1188
    txt += "</dl></body></html>";
1175
    txt += "</dl></body></html>";
1189
    setHtml(txt);
1176
    setHtml(txt);
1190
    m_curdsp = PTE_DSPFLDS;
1177
    m_curdsp = PTE_DSPFLDS;
1191
}
1178
}
1192
1179
1193
void PreviewTextEdit::displayImage()
1180
void PreviewTextEdit::displayImage()
1194
{
1181
{
1195
    LOGDEB1(("PreviewTextEdit::displayImage()\n"));
1182
    LOGDEB1(("PreviewTextEdit::displayImage()\n"));
1196
    if (m_image.isNull())
1183
    if (m_image.isNull())
1197
  displayText();
1184
        displayText();
1198
1185
1199
    setPlainText("");
1186
    setPlainText("");
1200
    if (m_image.width() > width() || 
1187
    if (m_image.width() > width() || 
1201
  m_image.height() > height()) {
1188
        m_image.height() > height()) {
1202
  m_image = m_image.scaled(width(), height(), Qt::KeepAspectRatio);
1189
        m_image = m_image.scaled(width(), height(), Qt::KeepAspectRatio);
1203
    }
1190
    }
1204
    document()->addResource(QTextDocument::ImageResource, QUrl("image"), 
1191
    document()->addResource(QTextDocument::ImageResource, QUrl("image"), 
1205
              m_image);
1192
                            m_image);
1206
    QTextCursor cursor = textCursor();
1193
    QTextCursor cursor = textCursor();
1207
    cursor.insertImage("image");
1194
    cursor.insertImage("image");
1208
    m_curdsp = PTE_DSPIMG;
1195
    m_curdsp = PTE_DSPIMG;
1209
}
1196
}
1210
1197
1211
void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
1198
void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
1212
{
1199
{
1213
    LOGDEB2(("PreviewTextEdit::mouseDoubleClickEvent\n"));
1200
    LOGDEB2(("PreviewTextEdit::mouseDoubleClickEvent\n"));
1214
    QTextEdit::mouseDoubleClickEvent(event);
1201
    QTextEdit::mouseDoubleClickEvent(event);
1215
    if (textCursor().hasSelection() && m_preview)
1202
    if (textCursor().hasSelection() && m_preview)
1216
  m_preview->emitWordSelect(textCursor().selectedText());
1203
        m_preview->emitWordSelect(textCursor().selectedText());
1217
}
1204
}
1218
1205
1219
void PreviewTextEdit::print()
1206
void PreviewTextEdit::print()
1220
{
1207
{
1221
    LOGDEB(("PreviewTextEdit::print\n"));
1208
    LOGDEB(("PreviewTextEdit::print\n"));
1222
    if (!m_preview)
1209
    if (!m_preview)
1223
        return;
1210
        return;
1224
  
1211
        
1225
#ifndef QT_NO_PRINTER
1212
#ifndef QT_NO_PRINTER
1226
    QPrinter printer;
1213
    QPrinter printer;
1227
    QPrintDialog *dialog = new QPrintDialog(&printer, this);
1214
    QPrintDialog *dialog = new QPrintDialog(&printer, this);
1228
    dialog->setWindowTitle(tr("Print Current Preview"));
1215
    dialog->setWindowTitle(tr("Print Current Preview"));
1229
    if (dialog->exec() != QDialog::Accepted)
1216
    if (dialog->exec() != QDialog::Accepted)