GUI: show image rather than metadata when previewing an image doc. Metadata still accessible through popup menu
This commit is contained in:
parent
631121e24e
commit
2f6328fb47
@ -57,7 +57,34 @@ void snapshotConfig()
|
|||||||
thestableconfig = new RclConfig(*theconfig);
|
thestableconfig = new RclConfig(*theconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PTMutexInit thetempfileslock;
|
||||||
|
static vector<TempFile> o_tempfiles;
|
||||||
|
/* Keep an array of temporary files for deletion at exit. It happens that we
|
||||||
|
erase some of them before exiting (ie: when closing a preview tab), we don't
|
||||||
|
reuse the array holes for now */
|
||||||
|
void rememberTempFile(TempFile temp)
|
||||||
|
{
|
||||||
|
PTMutexLocker locker(thetempfileslock);
|
||||||
|
o_tempfiles.push_back(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forgetTempFile(string &fn)
|
||||||
|
{
|
||||||
|
if (fn.empty())
|
||||||
|
return;
|
||||||
|
PTMutexLocker locker(thetempfileslock);
|
||||||
|
for (vector<TempFile>::iterator it = o_tempfiles.begin();
|
||||||
|
it != o_tempfiles.end(); it++) {
|
||||||
|
if ((*it).isNotNull() && !fn.compare((*it)->filename())) {
|
||||||
|
it->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn.erase();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rcl::Db *rcldb;
|
Rcl::Db *rcldb;
|
||||||
|
|
||||||
#ifdef RCL_USE_ASPELL
|
#ifdef RCL_USE_ASPELL
|
||||||
Aspell *aspell;
|
Aspell *aspell;
|
||||||
#endif
|
#endif
|
||||||
@ -119,9 +146,14 @@ static void recollCleanup()
|
|||||||
deleteZ(rcldb);
|
deleteZ(rcldb);
|
||||||
deleteZ(theconfig);
|
deleteZ(theconfig);
|
||||||
// deleteZ(thestableconfig);
|
// deleteZ(thestableconfig);
|
||||||
|
|
||||||
|
PTMutexLocker locker(thetempfileslock);
|
||||||
|
o_tempfiles.clear();
|
||||||
|
|
||||||
#ifdef RCL_USE_ASPELL
|
#ifdef RCL_USE_ASPELL
|
||||||
deleteZ(aspell);
|
deleteZ(aspell);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOGDEB2(("recollCleanup: done\n"));
|
LOGDEB2(("recollCleanup: done\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,4 +354,3 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,6 @@ using std::pair;
|
|||||||
#include <qprinter.h>
|
#include <qprinter.h>
|
||||||
#include <qprintdialog.h>
|
#include <qprintdialog.h>
|
||||||
#include <qscrollbar.h>
|
#include <qscrollbar.h>
|
||||||
|
|
||||||
#include <qmenu.h>
|
#include <qmenu.h>
|
||||||
#include <qtextedit.h>
|
#include <qtextedit.h>
|
||||||
#include <qprogressdialog.h>
|
#include <qprogressdialog.h>
|
||||||
@ -46,6 +45,8 @@ using std::pair;
|
|||||||
#include <qwhatsthis.h>
|
#include <qwhatsthis.h>
|
||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
#include <qclipboard.h>
|
#include <qclipboard.h>
|
||||||
|
#include <qimage.h>
|
||||||
|
#include <qurl.h>
|
||||||
|
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
#include "pathut.h"
|
#include "pathut.h"
|
||||||
@ -112,21 +113,6 @@ public:
|
|||||||
virtual string startChunk() { return "<pre>";}
|
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()
|
void Preview::init()
|
||||||
{
|
{
|
||||||
setObjectName("Preview");
|
setObjectName("Preview");
|
||||||
@ -217,6 +203,18 @@ void Preview::closeEvent(QCloseEvent *e)
|
|||||||
}
|
}
|
||||||
prefs.pvwidth = width();
|
prefs.pvwidth = width();
|
||||||
prefs.pvheight = height();
|
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 previewExposed(this, m_searchId, -1);
|
||||||
emit previewClosed(this);
|
emit previewClosed(this);
|
||||||
QWidget::closeEvent(e);
|
QWidget::closeEvent(e);
|
||||||
@ -249,13 +247,13 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
|
|||||||
(keyEvent->modifiers() & Qt::ShiftModifier)) {
|
(keyEvent->modifiers() & Qt::ShiftModifier)) {
|
||||||
LOGDEB2(("Preview::eventFilter: got Shift-Up\n"));
|
LOGDEB2(("Preview::eventFilter: got Shift-Up\n"));
|
||||||
if (edit)
|
if (edit)
|
||||||
emit(showNext(this, m_searchId, edit->m_data.docnum));
|
emit(showNext(this, m_searchId, edit->m_docnum));
|
||||||
return true;
|
return true;
|
||||||
} else if (keyEvent->key() == Qt::Key_Up &&
|
} else if (keyEvent->key() == Qt::Key_Up &&
|
||||||
(keyEvent->modifiers() & Qt::ShiftModifier)) {
|
(keyEvent->modifiers() & Qt::ShiftModifier)) {
|
||||||
LOGDEB2(("Preview::eventFilter: got Shift-Down\n"));
|
LOGDEB2(("Preview::eventFilter: got Shift-Down\n"));
|
||||||
if (edit)
|
if (edit)
|
||||||
emit(showPrev(this, m_searchId, edit->m_data.docnum));
|
emit(showPrev(this, m_searchId, edit->m_docnum));
|
||||||
return true;
|
return true;
|
||||||
} else if (keyEvent->key() == Qt::Key_W &&
|
} else if (keyEvent->key() == Qt::Key_W &&
|
||||||
(keyEvent->modifiers() & Qt::ControlModifier)) {
|
(keyEvent->modifiers() & Qt::ControlModifier)) {
|
||||||
@ -459,7 +457,7 @@ void Preview::currentChanged(QWidget * tw)
|
|||||||
edit->installEventFilter(this);
|
edit->installEventFilter(this);
|
||||||
edit->viewport()->installEventFilter(this);
|
edit->viewport()->installEventFilter(this);
|
||||||
searchTextLine->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()
|
void Preview::closeCurrentTab()
|
||||||
@ -469,6 +467,9 @@ void Preview::closeCurrentTab()
|
|||||||
CancelCheck::instance().setCancel();
|
CancelCheck::instance().setCancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PreviewTextEdit *e = currentEditor();
|
||||||
|
if (e)
|
||||||
|
forgetTempFile(e->m_tmpfilename);
|
||||||
if (pvTab->count() > 1) {
|
if (pvTab->count() > 1) {
|
||||||
pvTab->removeTab(pvTab->currentIndex());
|
pvTab->removeTab(pvTab->currentIndex());
|
||||||
} else {
|
} else {
|
||||||
@ -528,9 +529,9 @@ void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum)
|
|||||||
|
|
||||||
PreviewTextEdit *e = currentEditor();
|
PreviewTextEdit *e = currentEditor();
|
||||||
if (e) {
|
if (e) {
|
||||||
e->m_data.url = doc.url;
|
e->m_url = doc.url;
|
||||||
e->m_data.ipath = doc.ipath;
|
e->m_ipath = doc.ipath;
|
||||||
e->m_data.docnum = docnum;
|
e->m_docnum = docnum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,8 +550,8 @@ bool Preview::makeDocCurrent(const Rcl::Doc& doc, int docnum, bool sametab)
|
|||||||
if (tw) {
|
if (tw) {
|
||||||
PreviewTextEdit *edit =
|
PreviewTextEdit *edit =
|
||||||
tw->findChild<PreviewTextEdit*>("pvEdit");
|
tw->findChild<PreviewTextEdit*>("pvEdit");
|
||||||
if (edit && !edit->m_data.url.compare(doc.url) &&
|
if (edit && !edit->m_url.compare(doc.url) &&
|
||||||
!edit->m_data.ipath.compare(doc.ipath)) {
|
!edit->m_ipath.compare(doc.ipath)) {
|
||||||
pvTab->setCurrentIndex(i);
|
pvTab->setCurrentIndex(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -586,11 +587,6 @@ void Preview::emitWordSelect(QString word)
|
|||||||
threads and we update a progress indicator while they proceed (but we have
|
threads and we update a progress indicator while they proceed (but we have
|
||||||
no estimate of their total duration).
|
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
|
It might be possible, but complicated (need modifications in
|
||||||
handler) to implement a kind of bucket brigade, to have the
|
handler) to implement a kind of bucket brigade, to have the
|
||||||
beginning of the text displayed faster
|
beginning of the text displayed faster
|
||||||
@ -601,11 +597,12 @@ class LoadThread : public QThread {
|
|||||||
int *statusp;
|
int *statusp;
|
||||||
Rcl::Doc& out;
|
Rcl::Doc& out;
|
||||||
const Rcl::Doc& idoc;
|
const Rcl::Doc& idoc;
|
||||||
string filename;
|
|
||||||
TempDir tmpdir;
|
TempDir tmpdir;
|
||||||
int loglevel;
|
int loglevel;
|
||||||
public:
|
public:
|
||||||
string missing;
|
string missing;
|
||||||
|
TempFile imgtmp;
|
||||||
|
|
||||||
LoadThread(int *stp, Rcl::Doc& odoc, const Rcl::Doc& idc)
|
LoadThread(int *stp, Rcl::Doc& odoc, const Rcl::Doc& idc)
|
||||||
: statusp(stp), out(odoc), idoc(idc)
|
: statusp(stp), out(odoc), idoc(idc)
|
||||||
{
|
{
|
||||||
@ -624,8 +621,6 @@ class LoadThread : public QThread {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// QMessageBox::critical(0, "Recoll", Preview::tr("File does not exist"));
|
|
||||||
|
|
||||||
FileInterner interner(idoc, theconfig, tmpdir,
|
FileInterner interner(idoc, theconfig, tmpdir,
|
||||||
FileInterner::FIF_forPreview);
|
FileInterner::FIF_forPreview);
|
||||||
FIMissingStore mst;
|
FIMissingStore mst;
|
||||||
@ -651,6 +646,7 @@ class LoadThread : public QThread {
|
|||||||
out.text = interner.get_html();
|
out.text = interner.get_html();
|
||||||
out.mimetype = "text/html";
|
out.mimetype = "text/html";
|
||||||
}
|
}
|
||||||
|
imgtmp = interner.get_imgtmp();
|
||||||
} else {
|
} else {
|
||||||
out.mimetype = interner.getMimetype();
|
out.mimetype = interner.getMimetype();
|
||||||
interner.getMissingExternal(&mst, missing);
|
interner.getMissingExternal(&mst, missing);
|
||||||
@ -692,16 +688,6 @@ class ToRichThread : public QThread {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 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 {
|
class LoadGuard {
|
||||||
bool *m_bp;
|
bool *m_bp;
|
||||||
public:
|
public:
|
||||||
@ -728,8 +714,8 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
const int nsteps = 20;
|
const int nsteps = 20;
|
||||||
QProgressDialog progress(msg, tr("Cancel"), 0, nsteps, this);
|
QProgressDialog progress(msg, tr("Cancel"), 0, nsteps, this);
|
||||||
progress.setMinimumDuration(2000);
|
progress.setMinimumDuration(2000);
|
||||||
WaiterThread waiter(100);
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Load and convert document
|
// Load and convert document
|
||||||
// idoc came out of the index data (main text and other fields missing).
|
// 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.
|
// foc is the complete one what we are going to extract from storage.
|
||||||
@ -739,9 +725,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
lthr.start();
|
lthr.start();
|
||||||
int prog;
|
int prog;
|
||||||
for (prog = 1;;prog++) {
|
for (prog = 1;;prog++) {
|
||||||
waiter.start();
|
if (lthr.wait(100))
|
||||||
waiter.wait();
|
|
||||||
if (lthr.isFinished())
|
|
||||||
break;
|
break;
|
||||||
progress.setValue(prog);
|
progress.setValue(prog);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
@ -774,6 +758,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
// Reset config just in case.
|
// Reset config just in case.
|
||||||
theconfig->setKeyDir("");
|
theconfig->setKeyDir("");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Create preview text: highlight search terms
|
// Create preview text: highlight search terms
|
||||||
// We don't do the highlighting for very big texts: too long. We
|
// We don't do the highlighting for very big texts: too long. We
|
||||||
// should at least do special char escaping, in case a '&' or '<'
|
// should at least do special char escaping, in case a '&' or '<'
|
||||||
@ -786,7 +771,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
list<QString> qrichlst;
|
list<QString> qrichlst;
|
||||||
PreviewTextEdit *editor = currentEditor();
|
PreviewTextEdit *editor = currentEditor();
|
||||||
editor->setHtml("");
|
editor->setHtml("");
|
||||||
editor->m_data.format = Qt::RichText;
|
editor->m_format = Qt::RichText;
|
||||||
bool inputishtml = !fdoc.mimetype.compare("text/html");
|
bool inputishtml = !fdoc.mimetype.compare("text/html");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -817,8 +802,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
rthr.start();
|
rthr.start();
|
||||||
|
|
||||||
for (;;prog++) {
|
for (;;prog++) {
|
||||||
waiter.start(); waiter.wait();
|
if (rthr.wait(100))
|
||||||
if (rthr.isFinished())
|
|
||||||
break;
|
break;
|
||||||
progress.setValue(nsteps);
|
progress.setValue(nsteps);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
@ -832,7 +816,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
// Conversion to rich text done
|
// Conversion to rich text done
|
||||||
if (CancelCheck::instance().cancelState()) {
|
if (CancelCheck::instance().cancelState()) {
|
||||||
if (richlst.size() == 0 || richlst.front().length() == 0) {
|
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
|
// the object which would be a nasty surprise to our
|
||||||
// caller.
|
// caller.
|
||||||
return false;
|
return false;
|
||||||
@ -860,7 +844,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
qrichlst.push_back(qr);
|
qrichlst.push_back(qr);
|
||||||
} else {
|
} else {
|
||||||
editor->setPlainText("");
|
editor->setPlainText("");
|
||||||
editor->m_data.format = Qt::PlainText;
|
editor->m_format = Qt::PlainText;
|
||||||
for (int pos = 0; pos < (int)qr.length(); pos += l) {
|
for (int pos = 0; pos < (int)qr.length(); pos += l) {
|
||||||
l = MIN(CHUNKL, qr.length() - pos);
|
l = MIN(CHUNKL, qr.length() - pos);
|
||||||
qrichlst.push_back(qr.mid(pos, l));
|
qrichlst.push_back(qr.mid(pos, l));
|
||||||
@ -869,6 +853,10 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Load text into editor window.
|
||||||
prog = 2 * nsteps / 3;
|
prog = 2 * nsteps / 3;
|
||||||
progress.setLabelText(tr("Loading preview text into editor"));
|
progress.setLabelText(tr("Loading preview text into editor"));
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
@ -881,7 +869,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
editor->append(*it);
|
editor->append(*it);
|
||||||
// We need to save the rich text for printing, the editor does
|
// We need to save the rich text for printing, the editor does
|
||||||
// not do it consistently for us.
|
// not do it consistently for us.
|
||||||
editor->m_data.richtxt.append(*it);
|
editor->m_richtxt.append(*it);
|
||||||
|
|
||||||
if (progress.wasCanceled()) {
|
if (progress.wasCanceled()) {
|
||||||
editor->append("<b>Cancelled !</b>");
|
editor->append("<b>Cancelled !</b>");
|
||||||
@ -891,16 +879,54 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
progress.close();
|
progress.close();
|
||||||
|
editor->m_curdsp = PreviewTextEdit::PTE_DSPTXT;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Finishing steps
|
||||||
|
|
||||||
// Maybe the text was actually empty ? Switch to fields then. Else free-up
|
// 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();
|
bool textempty = fdoc.text.empty();
|
||||||
if (!textempty)
|
if (!textempty)
|
||||||
fdoc.text.clear();
|
fdoc.text.clear();
|
||||||
editor->m_data.fdoc = fdoc;
|
editor->m_fdoc = fdoc;
|
||||||
if (textempty)
|
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;
|
m_haveAnchors = editor->m_plaintorich->lastanchor != 0;
|
||||||
if (searchTextLine->text().length() != 0) {
|
if (searchTextLine->text().length() != 0) {
|
||||||
// If there is a current search string, perform the search
|
// If there is a current search string, perform the search
|
||||||
@ -921,6 +947,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Enter document in document history
|
// Enter document in document history
|
||||||
map<string,string>::const_iterator udit = idoc.meta.find(Rcl::Doc::keyudi);
|
map<string,string>::const_iterator udit = idoc.meta.find(Rcl::Doc::keyudi);
|
||||||
if (udit != idoc.meta.end())
|
if (udit != idoc.meta.end())
|
||||||
@ -932,50 +959,98 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
|
|||||||
return true;
|
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)
|
void PreviewTextEdit::createPopupMenu(const QPoint& pos)
|
||||||
{
|
{
|
||||||
LOGDEB1(("PreviewTextEdit::createPopupMenu()\n"));
|
LOGDEB1(("PreviewTextEdit::createPopupMenu()\n"));
|
||||||
QMenu *popup = new QMenu(this);
|
QMenu *popup = new QMenu(this);
|
||||||
if (!m_dspflds) {
|
switch (m_curdsp) {
|
||||||
popup->addAction(tr("Show fields"), this, SLOT(toggleFields()));
|
case PTE_DSPTXT:
|
||||||
} else {
|
popup->addAction(tr("Show fields"), this, SLOT(displayFields()));
|
||||||
popup->addAction(tr("Show main text"), this, SLOT(toggleFields()));
|
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->addAction(tr("Print"), this, SLOT(print()));
|
||||||
popup->popup(mapToGlobal(pos));
|
popup->popup(mapToGlobal(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either display document fields or main text
|
// Display main text
|
||||||
void PreviewTextEdit::toggleFields()
|
void PreviewTextEdit::displayText()
|
||||||
{
|
{
|
||||||
LOGDEB1(("PreviewTextEdit::toggleFields()\n"));
|
LOGDEB1(("PreviewTextEdit::displayText()\n"));
|
||||||
|
if (m_format == Qt::PlainText)
|
||||||
|
setPlainText(m_richtxt);
|
||||||
|
else
|
||||||
|
setHtml(m_richtxt);
|
||||||
|
m_curdsp = PTE_DSPTXT;
|
||||||
|
}
|
||||||
|
|
||||||
// If currently displaying fields, switch to body text
|
// Display field values
|
||||||
if (m_dspflds) {
|
void PreviewTextEdit::displayFields()
|
||||||
if (m_data.format == Qt::PlainText)
|
{
|
||||||
setPlainText(m_data.richtxt);
|
LOGDEB1(("PreviewTextEdit::displayFields()\n"));
|
||||||
else
|
|
||||||
setHtml(m_data.richtxt);
|
|
||||||
m_dspflds = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else display fields
|
|
||||||
m_dspflds = true;
|
|
||||||
QString txt = "<html><head></head><body>\n";
|
QString txt = "<html><head></head><body>\n";
|
||||||
txt += "<b>" + QString::fromLocal8Bit(m_data.url.c_str());
|
txt += "<b>" + QString::fromLocal8Bit(m_url.c_str());
|
||||||
if (!m_data.ipath.empty())
|
if (!m_ipath.empty())
|
||||||
txt += "|" + QString::fromUtf8(m_data.ipath.c_str());
|
txt += "|" + QString::fromUtf8(m_ipath.c_str());
|
||||||
txt += "</b><br><br>";
|
txt += "</b><br><br>";
|
||||||
txt += "<dl>\n";
|
txt += "<dl>\n";
|
||||||
for (map<string,string>::const_iterator it = m_data.fdoc.meta.begin();
|
for (map<string,string>::const_iterator it = m_fdoc.meta.begin();
|
||||||
it != m_data.fdoc.meta.end(); it++) {
|
it != m_fdoc.meta.end(); it++) {
|
||||||
txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> "
|
if (!it->second.empty())
|
||||||
+ "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str())
|
txt += "<dt>" + QString::fromUtf8(it->first.c_str()) + "</dt> "
|
||||||
+ "</dd>\n";
|
+ "<dd>" + QString::fromUtf8(escapeHtml(it->second).c_str())
|
||||||
|
+ "</dd>\n";
|
||||||
}
|
}
|
||||||
txt += "</dl></body></html>";
|
txt += "</dl></body></html>";
|
||||||
setHtml(txt);
|
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)
|
void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
|
|||||||
@ -22,49 +22,33 @@
|
|||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qwidget.h>
|
#include <qwidget.h>
|
||||||
#include <qtextedit.h>
|
#include <qtextedit.h>
|
||||||
|
#include <qimage.h>
|
||||||
|
|
||||||
#include "rcldb.h"
|
#include "rcldb.h"
|
||||||
#include "refcntr.h"
|
#include "refcntr.h"
|
||||||
#include "plaintorich.h"
|
#include "plaintorich.h"
|
||||||
|
#include "rclmain_w.h"
|
||||||
|
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class PreviewTextEdit;
|
|
||||||
class Preview;
|
|
||||||
|
|
||||||
// We keep a list of data associated to each tab
|
|
||||||
class TabData {
|
|
||||||
public:
|
|
||||||
string url; // filename for this tab
|
|
||||||
string ipath; // Internal doc path inside file
|
|
||||||
int docnum; // Index of doc in db search results.
|
|
||||||
// doc out of internfile (previous fields come from the index) with
|
|
||||||
// main text erased (for space).
|
|
||||||
Rcl::Doc fdoc;
|
|
||||||
// Saved rich (or plain actually) text: the textedit seems to
|
|
||||||
// sometimes (but not always) return its text stripped of tags, so
|
|
||||||
// this is needed (for printing for example)
|
|
||||||
QString richtxt;
|
|
||||||
Qt::TextFormat format;
|
|
||||||
TabData()
|
|
||||||
: docnum(-1)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Preview;
|
class Preview;
|
||||||
class PlainToRichQtPreview;
|
class PlainToRichQtPreview;
|
||||||
|
|
||||||
class PreviewTextEdit : public QTextEdit {
|
class PreviewTextEdit : public QTextEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT;
|
||||||
public:
|
public:
|
||||||
PreviewTextEdit(QWidget* parent, const char* name, Preview *pv);
|
PreviewTextEdit(QWidget* parent, const char* name, Preview *pv);
|
||||||
virtual ~PreviewTextEdit();
|
virtual ~PreviewTextEdit();
|
||||||
void moveToAnchor(const QString& name);
|
void moveToAnchor(const QString& name);
|
||||||
|
enum DspType {PTE_DSPTXT, PTE_DSPFLDS, PTE_DSPIMG};
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void toggleFields();
|
virtual void displayFields();
|
||||||
|
virtual void displayText();
|
||||||
|
virtual void displayImage();
|
||||||
virtual void print();
|
virtual void print();
|
||||||
virtual void createPopupMenu(const QPoint& pos);
|
virtual void createPopupMenu(const QPoint& pos);
|
||||||
friend class Preview;
|
friend class Preview;
|
||||||
@ -74,8 +58,25 @@ protected:
|
|||||||
private:
|
private:
|
||||||
PlainToRichQtPreview *m_plaintorich;
|
PlainToRichQtPreview *m_plaintorich;
|
||||||
Preview *m_preview;
|
Preview *m_preview;
|
||||||
TabData m_data;
|
|
||||||
bool m_dspflds;
|
bool m_dspflds;
|
||||||
|
string m_url; // filename for this tab
|
||||||
|
string m_ipath; // Internal doc path inside file
|
||||||
|
int m_docnum; // Index of doc in db search results.
|
||||||
|
// doc out of internfile (previous fields come from the index) with
|
||||||
|
// main text erased (for space).
|
||||||
|
Rcl::Doc m_fdoc;
|
||||||
|
// Saved rich (or plain actually) text: the textedit seems to
|
||||||
|
// sometimes (but not always) return its text stripped of tags, so
|
||||||
|
// this is needed (for printing for example)
|
||||||
|
QString m_richtxt;
|
||||||
|
Qt::TextFormat m_format;
|
||||||
|
// Temporary file name (possibly, if displaying image). The
|
||||||
|
// TempFile itself is kept inside main.cpp (because that's where
|
||||||
|
// signal cleanup happens), but we use its name to ask for release
|
||||||
|
// when the tab is closed.
|
||||||
|
string m_tmpfilename;
|
||||||
|
QImage m_image;
|
||||||
|
DspType m_curdsp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -475,7 +475,6 @@ bool RclMain::close()
|
|||||||
void RclMain::fileExit()
|
void RclMain::fileExit()
|
||||||
{
|
{
|
||||||
LOGDEB(("RclMain: fileExit\n"));
|
LOGDEB(("RclMain: fileExit\n"));
|
||||||
m_tempfiles.clear();
|
|
||||||
// Don't save geometry if we're currently fullscreened
|
// Don't save geometry if we're currently fullscreened
|
||||||
if (!isFullScreen()) {
|
if (!isFullScreen()) {
|
||||||
prefs.mainwidth = width();
|
prefs.mainwidth = width();
|
||||||
@ -996,7 +995,7 @@ void RclMain::saveDocToFile(Rcl::Doc doc)
|
|||||||
QString::fromLocal8Bit(path_home().c_str())
|
QString::fromLocal8Bit(path_home().c_str())
|
||||||
);
|
);
|
||||||
string tofile((const char *)s.toLocal8Bit());
|
string tofile((const char *)s.toLocal8Bit());
|
||||||
TempFile temp; // not used
|
TempFile temp; // not used because tofile is set.
|
||||||
if (!FileInterner::idocToFile(temp, tofile, theconfig, doc)) {
|
if (!FileInterner::idocToFile(temp, tofile, theconfig, doc)) {
|
||||||
QMessageBox::warning(0, "Recoll",
|
QMessageBox::warning(0, "Recoll",
|
||||||
tr("Cannot extract document or create "
|
tr("Cannot extract document or create "
|
||||||
@ -1028,20 +1027,6 @@ static bool lookForHtmlBrowser(string &exefile)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to file path if url is like file://
|
|
||||||
static string fileurltolocalpath(string url)
|
|
||||||
{
|
|
||||||
if (url.find("file://") == 0)
|
|
||||||
url = url.substr(7, string::npos);
|
|
||||||
else
|
|
||||||
return string();
|
|
||||||
string::size_type pos;
|
|
||||||
if ((pos = url.find_last_of("#")) != string::npos) {
|
|
||||||
url.erase(pos);
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RclMain::startNativeViewer(Rcl::Doc doc)
|
void RclMain::startNativeViewer(Rcl::Doc doc)
|
||||||
{
|
{
|
||||||
// Look for appropriate viewer
|
// Look for appropriate viewer
|
||||||
@ -1151,7 +1136,7 @@ void RclMain::startNativeViewer(Rcl::Doc doc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
istempfile = true;
|
istempfile = true;
|
||||||
m_tempfiles.push_back(temp);
|
rememberTempFile(temp);
|
||||||
fn = temp->filename();
|
fn = temp->filename();
|
||||||
url = string("file://") + fn;
|
url = string("file://") + fn;
|
||||||
}
|
}
|
||||||
@ -1176,7 +1161,7 @@ void RclMain::startNativeViewer(Rcl::Doc doc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!temp.isNull()) {
|
if (!temp.isNull()) {
|
||||||
m_tempfiles.push_back(temp);
|
rememberTempFile(temp);
|
||||||
fn = temp->filename();
|
fn = temp->filename();
|
||||||
url = string("file://") + fn;
|
url = string("file://") + fn;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qmainwindow.h>
|
#include <qmainwindow.h>
|
||||||
|
|
||||||
#include "sortseq.h"
|
#include "sortseq.h"
|
||||||
#include "preview_w.h"
|
#include "preview_w.h"
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
@ -122,7 +123,6 @@ private:
|
|||||||
QTimer *periodictimer;
|
QTimer *periodictimer;
|
||||||
ResTable *restable;
|
ResTable *restable;
|
||||||
|
|
||||||
vector<TempFile> m_tempfiles;
|
|
||||||
vector<ExecCmd*> m_viewers;
|
vector<ExecCmd*> m_viewers;
|
||||||
map<QString, QAction*> m_stemLangToId;
|
map<QString, QAction*> m_stemLangToId;
|
||||||
vector<string> m_catgbutvec;
|
vector<string> m_catgbutvec;
|
||||||
|
|||||||
@ -36,6 +36,8 @@ extern RclConfig *theconfig;
|
|||||||
extern RclConfig *thestableconfig;
|
extern RclConfig *thestableconfig;
|
||||||
extern PTMutexInit thestableconfiglock;
|
extern PTMutexInit thestableconfiglock;
|
||||||
extern void snapshotConfig();
|
extern void snapshotConfig();
|
||||||
|
extern void rememberTempFile(TempFile);
|
||||||
|
extern void forgetTempFile(string &fn);
|
||||||
|
|
||||||
extern Rcl::Db *rcldb;
|
extern Rcl::Db *rcldb;
|
||||||
extern int recollNeedsExit;
|
extern int recollNeedsExit;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user