Implemented better feedback during preview loading
This commit is contained in:
parent
add9ba1234
commit
2936191de6
@ -1,5 +1,5 @@
|
|||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.4 2005-10-20 08:34:51 dockes Exp $ (C) 2005 J.F.Dockes";
|
static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.5 2005-11-16 11:22:51 dockes Exp $ (C) 2005 J.F.Dockes";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ string plaintorich(const string &in, const list<string>& terms,
|
|||||||
// character offset
|
// character offset
|
||||||
splitter.text_to_words(in);
|
splitter.text_to_words(in);
|
||||||
|
|
||||||
|
LOGDEB(("Split done\n"));
|
||||||
|
|
||||||
|
|
||||||
// Rich text output
|
// Rich text output
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>130</width>
|
||||||
<height>30</height>
|
<height>30</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -207,11 +207,13 @@
|
|||||||
<slot>currentChanged( QWidget * tw )</slot>
|
<slot>currentChanged( QWidget * tw )</slot>
|
||||||
<slot>closeCurrentTab()</slot>
|
<slot>closeCurrentTab()</slot>
|
||||||
<slot>setCurTabProps( const Rcl::Doc & doc )</slot>
|
<slot>setCurTabProps( const Rcl::Doc & doc )</slot>
|
||||||
|
<slot>loadFileInCurrentTab( string fn, size_t sz, const Rcl::Doc & idoc )</slot>
|
||||||
</slots>
|
</slots>
|
||||||
<functions>
|
<functions>
|
||||||
<function access="private" specifier="non virtual">init()</function>
|
<function access="private" specifier="non virtual">init()</function>
|
||||||
<function>closeEvent( QCloseEvent * e )</function>
|
<function>closeEvent( QCloseEvent * e )</function>
|
||||||
<function returnType="bool">eventFilter( QObject * target, QEvent * event )</function>
|
<function returnType="bool">eventFilter( QObject * target, QEvent * event )</function>
|
||||||
|
<function returnType="QTextEdit *">getCurrentEditor()</function>
|
||||||
<function returnType="QTextEdit *">addEditorTab()</function>
|
<function returnType="QTextEdit *">addEditorTab()</function>
|
||||||
</functions>
|
</functions>
|
||||||
<layoutdefaults spacing="6" margin="11"/>
|
<layoutdefaults spacing="6" margin="11"/>
|
||||||
|
|||||||
@ -9,8 +9,20 @@
|
|||||||
** These will automatically be called by the form's constructor and
|
** These will automatically be called by the form's constructor and
|
||||||
** destructor.
|
** destructor.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
using std::pair;
|
||||||
|
|
||||||
|
#include <qmessagebox.h>
|
||||||
|
#include <qprogressdialog.h>
|
||||||
|
#include <qthread.h>
|
||||||
|
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
#include "pathut.h"
|
||||||
|
#include "internfile.h"
|
||||||
|
#include "recoll.h"
|
||||||
|
#include "plaintorich.h"
|
||||||
|
|
||||||
void Preview::init()
|
void Preview::init()
|
||||||
{
|
{
|
||||||
@ -83,6 +95,15 @@ void Preview::searchTextLine_textChanged(const QString & text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTextEdit * Preview::getCurrentEditor()
|
||||||
|
{
|
||||||
|
QWidget *tw = pvTab->currentPage();
|
||||||
|
QTextEdit *edit = 0;
|
||||||
|
if (tw) {
|
||||||
|
edit = (QTextEdit*)tw->child("pvEdit");
|
||||||
|
}
|
||||||
|
return edit;
|
||||||
|
}
|
||||||
|
|
||||||
// Perform text search. If next is true, we look for the next match of the
|
// Perform text search. If next is true, we look for the next match of the
|
||||||
// current search, trying to advance and possibly wrapping around. If next is
|
// current search, trying to advance and possibly wrapping around. If next is
|
||||||
@ -91,13 +112,10 @@ void Preview::searchTextLine_textChanged(const QString & text)
|
|||||||
void Preview::doSearch(bool next, bool reverse)
|
void Preview::doSearch(bool next, bool reverse)
|
||||||
{
|
{
|
||||||
LOGDEB1(("Preview::doSearch: next %d rev %d\n", int(next), int(reverse)));
|
LOGDEB1(("Preview::doSearch: next %d rev %d\n", int(next), int(reverse)));
|
||||||
QWidget *tw = pvTab->currentPage();
|
QTextEdit *edit = getCurrentEditor();
|
||||||
QTextEdit *edit = 0;
|
if (edit == 0) {
|
||||||
if (tw) {
|
// ??
|
||||||
if ((edit = (QTextEdit*)tw->child("pvEdit")) == 0) {
|
return;
|
||||||
// ??
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bool matchCase = matchCheck->isChecked();
|
bool matchCase = matchCheck->isChecked();
|
||||||
int mspara, msindex, mepara, meindex;
|
int mspara, msindex, mepara, meindex;
|
||||||
@ -199,8 +217,6 @@ QTextEdit * Preview::addEditorTab()
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
void Preview::setCurTabProps(const Rcl::Doc &doc)
|
void Preview::setCurTabProps(const Rcl::Doc &doc)
|
||||||
{
|
{
|
||||||
QString title = QString::fromUtf8(doc.title.c_str(),
|
QString title = QString::fromUtf8(doc.title.c_str(),
|
||||||
@ -225,3 +241,166 @@ void Preview::setCurTabProps(const Rcl::Doc &doc)
|
|||||||
pvTab->setTabToolTip(pvTab->currentPage(),
|
pvTab->setTabToolTip(pvTab->currentPage(),
|
||||||
QString::fromUtf8(tiptxt.c_str(), tiptxt.length()));
|
QString::fromUtf8(tiptxt.c_str(), tiptxt.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Code for loading a file into an editor window. The operations that
|
||||||
|
we call have no provision to indicate progression, and it would be
|
||||||
|
complicated or impossible to modify them to do so (Ie: for external
|
||||||
|
format converters).
|
||||||
|
|
||||||
|
We implement a complicated and ugly mechanism based on threads to indicate
|
||||||
|
to the user that the app is doing things: lengthy operations are done in
|
||||||
|
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.
|
||||||
|
|
||||||
|
No cancel button is implemented, but this could conceivably be done
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* A thread to to the file reading / format conversion */
|
||||||
|
class LoadThread : public QThread {
|
||||||
|
int *statusp;
|
||||||
|
Rcl::Doc *out;
|
||||||
|
string filename;
|
||||||
|
string ipath;
|
||||||
|
string *mtype;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LoadThread(int *stp, Rcl::Doc *odoc, string fn, string ip, string *mt)
|
||||||
|
: statusp(stp), out(odoc), filename(fn), ipath(ip), mtype(mt)
|
||||||
|
{}
|
||||||
|
virtual void run()
|
||||||
|
{
|
||||||
|
FileInterner interner(filename, rclconfig, tmpdir, mtype);
|
||||||
|
if (interner.internfile(*out, ipath) != FileInterner::FIDone) {
|
||||||
|
*statusp = -1;
|
||||||
|
} else {
|
||||||
|
*statusp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A thread to convert to rich text (mark search terms) */
|
||||||
|
class ToRichThread : public QThread {
|
||||||
|
string ∈
|
||||||
|
list<string> &terms;
|
||||||
|
list<pair<int, int> > &termoffsets;
|
||||||
|
QString &out;
|
||||||
|
public:
|
||||||
|
ToRichThread(string &i, list<string> &trms,
|
||||||
|
list<pair<int, int> > &toffs, QString &o)
|
||||||
|
: in(i), terms(trms), termoffsets(toffs), out(o)
|
||||||
|
{}
|
||||||
|
virtual void run()
|
||||||
|
{
|
||||||
|
string rich = plaintorich(in, terms, termoffsets);
|
||||||
|
out = QString::fromUtf8(rich.c_str(), rich.length());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc)
|
||||||
|
{
|
||||||
|
Rcl::Doc doc = idoc;
|
||||||
|
|
||||||
|
if (doc.title.empty())
|
||||||
|
doc.title = path_getsimple(doc.url);
|
||||||
|
|
||||||
|
setCurTabProps(doc);
|
||||||
|
|
||||||
|
char csz[20];
|
||||||
|
sprintf(csz, "%lu", (unsigned long)sz);
|
||||||
|
QString msg = QString("Loading: %1 (size %2 bytes)")
|
||||||
|
.arg(fn)
|
||||||
|
.arg(csz);
|
||||||
|
|
||||||
|
// Create progress dialog and aux objects
|
||||||
|
const int nsteps = 10;
|
||||||
|
QProgressDialog progress( msg, "", nsteps, this, "Loading", TRUE );
|
||||||
|
QPushButton *pb = new QPushButton("", this);
|
||||||
|
pb->setEnabled(false);
|
||||||
|
progress.setCancelButton(pb);
|
||||||
|
progress.setMinimumDuration(1000);
|
||||||
|
WaiterThread waiter(100);
|
||||||
|
|
||||||
|
// Load and convert file
|
||||||
|
Rcl::Doc fdoc;
|
||||||
|
int status = 1;
|
||||||
|
LoadThread lthr(&status, &fdoc, fn, doc.ipath, &doc.mimetype);
|
||||||
|
lthr.start();
|
||||||
|
int i;
|
||||||
|
for (i = 1;;i++) {
|
||||||
|
waiter.start();
|
||||||
|
waiter.wait();
|
||||||
|
if (lthr.finished())
|
||||||
|
break;
|
||||||
|
progress.setProgress(i , i <= nsteps-1 ? nsteps : i+1);
|
||||||
|
qApp->processEvents();
|
||||||
|
if (i >= 5)
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
if (status != 0) {
|
||||||
|
QMessageBox::warning(0, "Recoll",
|
||||||
|
tr("Can't turn doc into internal rep for ") +
|
||||||
|
doc.mimetype.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOGDEB(("Load file done\n"));
|
||||||
|
|
||||||
|
// Highlight search terms:
|
||||||
|
progress.setLabelText(tr("Creating preview text"));
|
||||||
|
list<string> terms;
|
||||||
|
rcldb->getQueryTerms(terms);
|
||||||
|
list<pair<int, int> > termoffsets;
|
||||||
|
QString str;
|
||||||
|
ToRichThread rthr(fdoc.text, terms, termoffsets, str);
|
||||||
|
rthr.start();
|
||||||
|
|
||||||
|
for (;;i++) {
|
||||||
|
waiter.start();
|
||||||
|
waiter.wait();
|
||||||
|
if (rthr.finished())
|
||||||
|
break;
|
||||||
|
progress.setProgress(i , i <= nsteps-1 ? nsteps : i+1);
|
||||||
|
qApp->processEvents();
|
||||||
|
if (i >= 5)
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
LOGDEB(("Plaintorich done\n"));
|
||||||
|
|
||||||
|
// Load into editor
|
||||||
|
QTextEdit *editor = getCurrentEditor();
|
||||||
|
QStyleSheetItem *item =
|
||||||
|
new QStyleSheetItem(editor->styleSheet(), "termtag" );
|
||||||
|
item->setColor("blue");
|
||||||
|
item->setFontWeight(QFont::Bold);
|
||||||
|
|
||||||
|
progress.setLabelText(tr("Loading preview text into editor"));
|
||||||
|
qApp->processEvents();
|
||||||
|
editor->setText(str);
|
||||||
|
int para = 0, index = 1;
|
||||||
|
if (!termoffsets.empty()) {
|
||||||
|
index = (termoffsets.begin())->first;
|
||||||
|
LOGDEB(("Set cursor position: para %d, character index %d\n",
|
||||||
|
para,index));
|
||||||
|
editor->setCursorPosition(0, index);
|
||||||
|
}
|
||||||
|
editor->ensureCursorVisible();
|
||||||
|
editor->getCursorPosition(¶, &index);
|
||||||
|
|
||||||
|
LOGDEB(("PREVIEW len %d paragraphs: %d. Cpos: %d %d\n",
|
||||||
|
editor->length(), editor->paragraphs(), para, index));
|
||||||
|
}
|
||||||
|
|||||||
@ -566,16 +566,8 @@ void RecollMain::startPreview(int docnum)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStatusBar *stb = statusBar();
|
|
||||||
|
|
||||||
stb->message(tr("Creating preview window"));
|
|
||||||
qApp->processEvents();
|
|
||||||
QTextEdit *editor;
|
|
||||||
if (curPreview == 0) {
|
if (curPreview == 0) {
|
||||||
curPreview = new Preview(0, tr("Preview"));
|
curPreview = new Preview(0, tr("Preview"));
|
||||||
curPreview->setCaption(queryText->text());
|
|
||||||
connect(curPreview, SIGNAL(previewClosed(Preview *)),
|
|
||||||
this, SLOT(previewClosed(Preview *)));
|
|
||||||
if (curPreview == 0) {
|
if (curPreview == 0) {
|
||||||
QMessageBox::warning(0, tr("Warning"),
|
QMessageBox::warning(0, tr("Warning"),
|
||||||
tr("Can't create preview window"),
|
tr("Can't create preview window"),
|
||||||
@ -583,64 +575,16 @@ void RecollMain::startPreview(int docnum)
|
|||||||
QMessageBox::NoButton);
|
QMessageBox::NoButton);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor = curPreview->pvEdit;
|
|
||||||
|
curPreview->setCaption(queryText->text());
|
||||||
|
connect(curPreview, SIGNAL(previewClosed(Preview *)),
|
||||||
|
this, SLOT(previewClosed(Preview *)));
|
||||||
curPreview->show();
|
curPreview->show();
|
||||||
} else {
|
} else {
|
||||||
editor = curPreview->addEditorTab();
|
(void)curPreview->addEditorTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.title.empty())
|
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
|
||||||
doc.title = path_getsimple(doc.url);
|
|
||||||
|
|
||||||
curPreview->setCurTabProps(doc);
|
|
||||||
|
|
||||||
char csz[20];
|
|
||||||
sprintf(csz, "%lu", (unsigned long)st.st_size);
|
|
||||||
QString msg = QString("Loading: %1 (size %2 bytes)")
|
|
||||||
.arg(fn)
|
|
||||||
.arg(csz);
|
|
||||||
stb->message(msg);
|
|
||||||
qApp->processEvents();
|
|
||||||
|
|
||||||
Rcl::Doc fdoc;
|
|
||||||
FileInterner interner(fn, rclconfig, tmpdir, &doc.mimetype);
|
|
||||||
if (interner.internfile(fdoc, doc.ipath) != FileInterner::FIDone) {
|
|
||||||
QMessageBox::warning(0, "Recoll",
|
|
||||||
tr("Can't turn doc into internal rep for ") +
|
|
||||||
doc.mimetype.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stb->message(tr("Creating preview text"));
|
|
||||||
qApp->processEvents();
|
|
||||||
|
|
||||||
list<string> terms;
|
|
||||||
rcldb->getQueryTerms(terms);
|
|
||||||
list<pair<int, int> > termoffsets;
|
|
||||||
string rich = plaintorich(fdoc.text, terms, termoffsets);
|
|
||||||
|
|
||||||
QStyleSheetItem *item =
|
|
||||||
new QStyleSheetItem(editor->styleSheet(), "termtag" );
|
|
||||||
item->setColor("blue");
|
|
||||||
item->setFontWeight(QFont::Bold);
|
|
||||||
|
|
||||||
QString str = QString::fromUtf8(rich.c_str(), rich.length());
|
|
||||||
stb->message(tr("Loading preview text"));
|
|
||||||
qApp->processEvents();
|
|
||||||
|
|
||||||
editor->setText(str);
|
|
||||||
int para = 0, index = 1;
|
|
||||||
if (!termoffsets.empty()) {
|
|
||||||
index = (termoffsets.begin())->first;
|
|
||||||
LOGDEB(("Set cursor position: para %d, character index %d\n",
|
|
||||||
para,index));
|
|
||||||
editor->setCursorPosition(0, index);
|
|
||||||
}
|
|
||||||
editor->ensureCursorVisible();
|
|
||||||
editor->getCursorPosition(¶, &index);
|
|
||||||
LOGDEB(("PREVIEW len %d paragraphs: %d. Cpos: %d %d\n",
|
|
||||||
editor->length(), editor->paragraphs(), para, index));
|
|
||||||
stb->clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user