--- a/src/qtgui/preview_w.cpp
+++ b/src/qtgui/preview_w.cpp
@@ -33,7 +33,6 @@
#include <qprinter.h>
#include <qprintdialog.h>
#include <qscrollbar.h>
-
#include <qmenu.h>
#include <qtextedit.h>
#include <qprogressdialog.h>
@@ -46,6 +45,8 @@
#include <qwhatsthis.h>
#include <qapplication.h>
#include <qclipboard.h>
+#include <qimage.h>
+#include <qurl.h>
#include "debuglog.h"
#include "pathut.h"
@@ -112,21 +113,6 @@
virtual string startChunk() { return "<pre>";}
};
-PreviewTextEdit::PreviewTextEdit(QWidget* parent,const char* name, Preview *pv)
- : QTextEdit(parent), m_preview(pv), m_dspflds(false)
-{
- setContextMenuPolicy(Qt::CustomContextMenu);
- setObjectName(name);
- connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
- this, SLOT(createPopupMenu(const QPoint&)));
- m_plaintorich = new PlainToRichQtPreview();
-}
-
-PreviewTextEdit::~PreviewTextEdit()
-{
- delete m_plaintorich;
-}
-
void Preview::init()
{
setObjectName("Preview");
@@ -217,6 +203,18 @@
}
prefs.pvwidth = width();
prefs.pvheight = height();
+
+ /* Release all temporary files (but maybe none is actually set) */
+ for (int i = 0; i < pvTab->count(); i++) {
+ QWidget *tw = pvTab->widget(i);
+ if (tw) {
+ PreviewTextEdit *edit =
+ tw->findChild<PreviewTextEdit*>("pvEdit");
+ if (edit) {
+ forgetTempFile(edit->m_tmpfilename);
+ }
+ }
+ }
emit previewExposed(this, m_searchId, -1);
emit previewClosed(this);
QWidget::closeEvent(e);
@@ -249,13 +247,13 @@
(keyEvent->modifiers() & Qt::ShiftModifier)) {
LOGDEB2(("Preview::eventFilter: got Shift-Up\n"));
if (edit)
- emit(showNext(this, m_searchId, edit->m_data.docnum));
+ emit(showNext(this, m_searchId, edit->m_docnum));
return true;
} else if (keyEvent->key() == Qt::Key_Up &&
(keyEvent->modifiers() & Qt::ShiftModifier)) {
LOGDEB2(("Preview::eventFilter: got Shift-Down\n"));
if (edit)
- emit(showPrev(this, m_searchId, edit->m_data.docnum));
+ emit(showPrev(this, m_searchId, edit->m_docnum));
return true;
} else if (keyEvent->key() == Qt::Key_W &&
(keyEvent->modifiers() & Qt::ControlModifier)) {
@@ -459,7 +457,7 @@
edit->installEventFilter(this);
edit->viewport()->installEventFilter(this);
searchTextLine->installEventFilter(this);
- emit(previewExposed(this, m_searchId, edit->m_data.docnum));
+ emit(previewExposed(this, m_searchId, edit->m_docnum));
}
void Preview::closeCurrentTab()
@@ -469,6 +467,9 @@
CancelCheck::instance().setCancel();
return;
}
+ PreviewTextEdit *e = currentEditor();
+ if (e)
+ forgetTempFile(e->m_tmpfilename);
if (pvTab->count() > 1) {
pvTab->removeTab(pvTab->currentIndex());
} else {
@@ -528,9 +529,9 @@
PreviewTextEdit *e = currentEditor();
if (e) {
- e->m_data.url = doc.url;
- e->m_data.ipath = doc.ipath;
- e->m_data.docnum = docnum;
+ e->m_url = doc.url;
+ e->m_ipath = doc.ipath;
+ e->m_docnum = docnum;
}
}
@@ -549,8 +550,8 @@
if (tw) {
PreviewTextEdit *edit =
tw->findChild<PreviewTextEdit*>("pvEdit");
- if (edit && !edit->m_data.url.compare(doc.url) &&
- !edit->m_data.ipath.compare(doc.ipath)) {
+ if (edit && !edit->m_url.compare(doc.url) &&
+ !edit->m_ipath.compare(doc.ipath)) {
pvTab->setCurrentIndex(i);
return true;
}
@@ -586,11 +587,6 @@
threads and we update a progress indicator while they proceed (but we have
no estimate of their total duration).
- An auxiliary thread object is used for short waits. Another option would be
- to use signals/slots and return to the event-loop instead, but this would
- be even more complicated, and we probably don't want the user to click on
- things during this time anyway.
-
It might be possible, but complicated (need modifications in
handler) to implement a kind of bucket brigade, to have the
beginning of the text displayed faster
@@ -601,11 +597,12 @@
int *statusp;
Rcl::Doc& out;
const Rcl::Doc& idoc;
- string filename;
TempDir tmpdir;
int loglevel;
public:
string missing;
+ TempFile imgtmp;
+
LoadThread(int *stp, Rcl::Doc& odoc, const Rcl::Doc& idc)
: statusp(stp), out(odoc), idoc(idc)
{
@@ -624,8 +621,6 @@
return;
}
- // QMessageBox::critical(0, "Recoll", Preview::tr("File does not exist"));
-
FileInterner interner(idoc, theconfig, tmpdir,
FileInterner::FIF_forPreview);
FIMissingStore mst;
@@ -651,6 +646,7 @@
out.text = interner.get_html();
out.mimetype = "text/html";
}
+ imgtmp = interner.get_imgtmp();
} else {
out.mimetype = interner.getMimetype();
interner.getMissingExternal(&mst, missing);
@@ -692,16 +688,6 @@
}
};
-/* A thread to implement short waiting. There must be a better way ! */
-class WaiterThread : public QThread {
- int ms;
- public:
- WaiterThread(int millis) : ms(millis) {}
- virtual void run() {
- msleep(ms);
- }
-};
-
class LoadGuard {
bool *m_bp;
public:
@@ -728,8 +714,8 @@
const int nsteps = 20;
QProgressDialog progress(msg, tr("Cancel"), 0, nsteps, this);
progress.setMinimumDuration(2000);
- WaiterThread waiter(100);
-
+
+ ////////////////////////////////////////////////////////////////////////
// Load and convert document
// idoc came out of the index data (main text and other fields missing).
// foc is the complete one what we are going to extract from storage.
@@ -739,9 +725,7 @@
lthr.start();
int prog;
for (prog = 1;;prog++) {
- waiter.start();
- waiter.wait();
- if (lthr.isFinished())
+ if (lthr.wait(100))
break;
progress.setValue(prog);
qApp->processEvents();
@@ -774,6 +758,7 @@
// Reset config just in case.
theconfig->setKeyDir("");
+ ////////////////////////////////////////////////////////////////////////
// Create preview text: highlight search terms
// We don't do the highlighting for very big texts: too long. We
// should at least do special char escaping, in case a '&' or '<'
@@ -786,7 +771,7 @@
list<QString> qrichlst;
PreviewTextEdit *editor = currentEditor();
editor->setHtml("");
- editor->m_data.format = Qt::RichText;
+ editor->m_format = Qt::RichText;
bool inputishtml = !fdoc.mimetype.compare("text/html");
#if 0
@@ -817,8 +802,7 @@
rthr.start();
for (;;prog++) {
- waiter.start(); waiter.wait();
- if (rthr.isFinished())
+ if (rthr.wait(100))
break;
progress.setValue(nsteps);
qApp->processEvents();
@@ -832,7 +816,7 @@
// Conversion to rich text done
if (CancelCheck::instance().cancelState()) {
if (richlst.size() == 0 || richlst.front().length() == 0) {
- // We cant call closeCurrentTab here as it might delete
+ // We can't call closeCurrentTab here as it might delete
// the object which would be a nasty surprise to our
// caller.
return false;
@@ -860,7 +844,7 @@
qrichlst.push_back(qr);
} else {
editor->setPlainText("");
- editor->m_data.format = Qt::PlainText;
+ editor->m_format = Qt::PlainText;
for (int pos = 0; pos < (int)qr.length(); pos += l) {
l = MIN(CHUNKL, qr.length() - pos);
qrichlst.push_back(qr.mid(pos, l));
@@ -869,6 +853,10 @@
}
#endif
+
+
+ ///////////////////////////////////////////////////////////
+ // Load text into editor window.
prog = 2 * nsteps / 3;
progress.setLabelText(tr("Loading preview text into editor"));
qApp->processEvents();
@@ -881,7 +869,7 @@
editor->append(*it);
// We need to save the rich text for printing, the editor does
// not do it consistently for us.
- editor->m_data.richtxt.append(*it);
+ editor->m_richtxt.append(*it);
if (progress.wasCanceled()) {
editor->append("<b>Cancelled !</b>");
@@ -891,16 +879,54 @@
}
progress.close();
+ editor->m_curdsp = PreviewTextEdit::PTE_DSPTXT;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Finishing steps
// Maybe the text was actually empty ? Switch to fields then. Else free-up
- // the text memory.
+ // the text memory in the loaded document. We still have a copy of the text
+ // in editor->m_richtxt
bool textempty = fdoc.text.empty();
if (!textempty)
fdoc.text.clear();
- editor->m_data.fdoc = fdoc;
+ editor->m_fdoc = fdoc;
if (textempty)
- editor->toggleFields();
-
+ editor->displayFields();
+
+ // If this is an image, display it instead of the text.
+ if (!idoc.mimetype.compare(0, 6, "image/")) {
+ string fn = fileurltolocalpath(idoc.url);
+
+ // If the command wants a file but this is not a file url, or
+ // there is an ipath that it won't understand, we need a temp file:
+ theconfig->setKeyDir(path_getfather(fn));
+ if (fn.empty() || !idoc.ipath.empty()) {
+ TempFile temp = lthr.imgtmp;
+ if (temp.isNotNull()) {
+ LOGDEB1(("Preview: load: got temp file from internfile\n"));
+ } else if (!FileInterner::idocToFile(temp, string(),
+ theconfig, idoc)) {
+ temp.release(); // just in case.
+ }
+ if (temp.isNotNull()) {
+ rememberTempFile(temp);
+ fn = temp->filename();
+ editor->m_tmpfilename = fn;
+ } else {
+ editor->m_tmpfilename.erase();
+ fn.erase();
+ }
+ }
+
+ if (!fn.empty()) {
+ editor->m_image = QImage(fn.c_str());
+ editor->displayImage();
+ }
+ }
+
+
+ // Position the editor so that the first search term is visible
m_haveAnchors = editor->m_plaintorich->lastanchor != 0;
if (searchTextLine->text().length() != 0) {
// If there is a current search string, perform the search
@@ -921,6 +947,7 @@
}
}
+
// Enter document in document history
map<string,string>::const_iterator udit = idoc.meta.find(Rcl::Doc::keyudi);
if (udit != idoc.meta.end())
@@ -932,50 +959,98 @@
return true;
}
+PreviewTextEdit::PreviewTextEdit(QWidget* parent,const char* name, Preview *pv)
+ : QTextEdit(parent), m_preview(pv), m_dspflds(false), m_docnum(-1)
+{
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ setObjectName(name);
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(createPopupMenu(const QPoint&)));
+ m_plaintorich = new PlainToRichQtPreview();
+}
+
+PreviewTextEdit::~PreviewTextEdit()
+{
+ delete m_plaintorich;
+}
+
void PreviewTextEdit::createPopupMenu(const QPoint& pos)
{
LOGDEB1(("PreviewTextEdit::createPopupMenu()\n"));
QMenu *popup = new QMenu(this);
- if (!m_dspflds) {
- popup->addAction(tr("Show fields"), this, SLOT(toggleFields()));
- } else {
- popup->addAction(tr("Show main text"), this, SLOT(toggleFields()));
- }
+ switch (m_curdsp) {
+ case PTE_DSPTXT:
+ popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
+ if (!m_image.isNull())
+ popup->addAction(tr("Show image"), this, SLOT(displayImage()));
+ break;
+ case PTE_DSPFLDS:
+ popup->addAction(tr("Show main text"), this, SLOT(displayText()));
+ if (!m_image.isNull())
+ popup->addAction(tr("Show image"), this, SLOT(displayImage()));
+ break;
+ case PTE_DSPIMG:
+ default:
+ popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
+ popup->addAction(tr("Show main text"), this, SLOT(displayText()));
+ break;
+ }
+ popup->addAction(tr("Select All"), this, SLOT(selectAll()));
+ popup->addAction(tr("Copy"), this, SLOT(copy()));
popup->addAction(tr("Print"), this, SLOT(print()));
popup->popup(mapToGlobal(pos));
}
-// Either display document fields or main text
-void PreviewTextEdit::toggleFields()
-{
- LOGDEB1(("PreviewTextEdit::toggleFields()\n"));
-
- // If currently displaying fields, switch to body text
- if (m_dspflds) {
- if (m_data.format == Qt::PlainText)
- setPlainText(m_data.richtxt);
- else
- setHtml(m_data.richtxt);
- m_dspflds = false;
- return;
- }
-
- // Else display fields
- m_dspflds = true;
+// Display main text
+void PreviewTextEdit::displayText()
+{
+ LOGDEB1(("PreviewTextEdit::displayText()\n"));
+ if (m_format == Qt::PlainText)
+ setPlainText(m_richtxt);
+ else
+ setHtml(m_richtxt);
+ m_curdsp = PTE_DSPTXT;
+}
+
+// Display field values
+void PreviewTextEdit::displayFields()
+{
+ LOGDEB1(("PreviewTextEdit::displayFields()\n"));
+
QString txt = "<html><head></head><body>\n";
- txt += "<b>" + QString::fromLocal8Bit(m_data.url.c_str());
- if (!m_data.ipath.empty())
- txt += "|" + QString::fromUtf8(m_data.ipath.c_str());
+ txt += "<b>" + QString::fromLocal8Bit(m_url.c_str());
+ if (!m_ipath.empty())
+ txt += "|" + QString::fromUtf8(m_ipath.c_str());
txt += "</b><br><br>";
txt += "<dl>\n";
- for (map<string,string>::const_iterator it = m_data.fdoc.meta.begin();
- it != m_data.fdoc.meta.end(); it++) {
- txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> "
- + "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str())
- + "</dd>\n";
+ for (map<string,string>::const_iterator it = m_fdoc.meta.begin();
+ it != m_fdoc.meta.end(); it++) {
+ if (!it->second.empty())
+ txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> "
+ + "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str())
+ + "</dd>\n";
}
txt += "</dl></body></html>";
setHtml(txt);
+ m_curdsp = PTE_DSPFLDS;
+}
+
+void PreviewTextEdit::displayImage()
+{
+ LOGDEB1(("PreviewTextEdit::displayImage()\n"));
+ if (m_image.isNull())
+ displayText();
+
+ setPlainText("");
+ if (m_image.width() > width() ||
+ m_image.height() > height()) {
+ m_image = m_image.scaled(width(), height(), Qt::KeepAspectRatio);
+ }
+ document()->addResource(QTextDocument::ImageResource, QUrl("image"),
+ m_image);
+ QTextCursor cursor = textCursor();
+ cursor.insertImage("image");
+ m_curdsp = PTE_DSPIMG;
}
void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)