mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-23 18:24:48 +00:00
Detach Buffer preview and update preview in a new thread. Only for Qt4.4 users. This new feature can be disabled by setting EXPORT_in_THREAD to 0 in GuiView.cpp.
Two things are missing (but are fixable): - the lack of feedback of the background latex compilation - the error list is not shown in case of compilation error. * Buffer: - create a "cloned buffer" type. - Transfer LFUN_MASTER_BUFFER_UPDATE, LFUN_MASTER_BUFFER_VIEW, LFUN_BUFFER_UPDATE and LFUN_BUFFER_VIEW to GuiView. This is good itself as these LFUN are GUI oriented. * GuiView: detach the above LFUNs to a new thread as was already done for autosave. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@32584 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
5ad8d44ce2
commit
4ed0169064
120
src/Buffer.cpp
120
src/Buffer.cpp
@ -147,7 +147,7 @@ class BufferSet : public std::set<Buffer const *> {};
|
||||
class Buffer::Impl
|
||||
{
|
||||
public:
|
||||
Impl(Buffer & parent, FileName const & file, bool readonly);
|
||||
Impl(Buffer & parent, FileName const & file, bool readonly, Buffer const * cloned_buffer);
|
||||
|
||||
~Impl()
|
||||
{
|
||||
@ -258,9 +258,13 @@ public:
|
||||
LYXERR0("Warning: a buffer should not have two parents!");
|
||||
parent_buffer = pb;
|
||||
}
|
||||
private:
|
||||
|
||||
/// So we can force access via the accessors.
|
||||
mutable Buffer const * parent_buffer;
|
||||
|
||||
/// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_
|
||||
/// This one is useful for preview detached in a thread.
|
||||
Buffer const * cloned_buffer_;
|
||||
};
|
||||
|
||||
|
||||
@ -283,22 +287,31 @@ static FileName createBufferTmpDir()
|
||||
}
|
||||
|
||||
|
||||
Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
|
||||
Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_,
|
||||
Buffer const * cloned_buffer)
|
||||
: lyx_clean(true), bak_clean(true), unnamed(false),
|
||||
read_only(readonly_), filename(file), file_fully_loaded(false),
|
||||
toc_backend(&parent), macro_lock(false), timestamp_(0),
|
||||
checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false),
|
||||
parent_buffer(0)
|
||||
parent_buffer(0), cloned_buffer_(cloned_buffer)
|
||||
{
|
||||
if (!cloned_buffer_) {
|
||||
temppath = createBufferTmpDir();
|
||||
lyxvc.setBuffer(&parent);
|
||||
if (use_gui)
|
||||
wa_ = new frontend::WorkAreaManager;
|
||||
return;
|
||||
}
|
||||
temppath = cloned_buffer_->d->temppath;
|
||||
file_fully_loaded = true;
|
||||
params = cloned_buffer_->d->params;
|
||||
inset = static_cast<InsetText *>(cloned_buffer_->d->inset->clone());
|
||||
inset->setBuffer(parent);
|
||||
}
|
||||
|
||||
|
||||
Buffer::Buffer(string const & file, bool readonly)
|
||||
: d(new Impl(*this, FileName(file), readonly)), gui_(0)
|
||||
Buffer::Buffer(string const & file, bool readonly, Buffer const * cloned_buffer)
|
||||
: d(new Impl(*this, FileName(file), readonly, cloned_buffer)), gui_(0)
|
||||
{
|
||||
LYXERR(Debug::INFO, "Buffer::Buffer()");
|
||||
|
||||
@ -343,7 +356,7 @@ Buffer::~Buffer()
|
||||
d->children_positions.clear();
|
||||
d->position_to_children.clear();
|
||||
|
||||
if (!d->temppath.destroyDirectory()) {
|
||||
if (!d->cloned_buffer_ && !d->temppath.destroyDirectory()) {
|
||||
Alert::warning(_("Could not remove temporary directory"),
|
||||
bformat(_("Could not remove the temporary directory %1$s"),
|
||||
from_utf8(d->temppath.absFilename())));
|
||||
@ -358,12 +371,7 @@ Buffer::~Buffer()
|
||||
|
||||
Buffer * Buffer::clone() const
|
||||
{
|
||||
Buffer * clone = new Buffer(fileName().absFilename(), false);
|
||||
clone->d->file_fully_loaded = true;
|
||||
clone->d->params = d->params;
|
||||
clone->d->inset = static_cast<InsetText *>(d->inset->clone());
|
||||
clone->d->inset->setBuffer(*clone);
|
||||
return clone;
|
||||
return new Buffer(fileName().absFilename(), false, this);
|
||||
}
|
||||
|
||||
|
||||
@ -1652,6 +1660,21 @@ void Buffer::markDepClean(string const & name)
|
||||
}
|
||||
|
||||
|
||||
bool Buffer::isExportableFormat(string const & format) const
|
||||
{
|
||||
typedef vector<Format const *> Formats;
|
||||
Formats formats;
|
||||
formats = exportableFormats(true);
|
||||
Formats::const_iterator fit = formats.begin();
|
||||
Formats::const_iterator end = formats.end();
|
||||
for (; fit != end ; ++fit) {
|
||||
if ((*fit)->name() == format)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
|
||||
{
|
||||
if (isInternal()) {
|
||||
@ -1687,27 +1710,6 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_MASTER_BUFFER_UPDATE:
|
||||
case LFUN_MASTER_BUFFER_VIEW:
|
||||
enable = parent() != 0;
|
||||
break;
|
||||
case LFUN_BUFFER_UPDATE:
|
||||
case LFUN_BUFFER_VIEW: {
|
||||
string format = to_utf8(cmd.argument());
|
||||
if (cmd.argument().empty())
|
||||
format = getDefaultOutputFormat();
|
||||
typedef vector<Format const *> Formats;
|
||||
Formats formats;
|
||||
formats = exportableFormats(true);
|
||||
Formats::const_iterator fit = formats.begin();
|
||||
Formats::const_iterator end = formats.end();
|
||||
enable = false;
|
||||
for (; fit != end ; ++fit) {
|
||||
if ((*fit)->name() == format)
|
||||
enable = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LFUN_BUFFER_CHKTEX:
|
||||
enable = isLatex() && !lyxrc.chktex_command.empty();
|
||||
break;
|
||||
@ -1773,10 +1775,6 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_EXPORT: {
|
||||
if (argument == "custom") {
|
||||
lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
|
||||
break;
|
||||
}
|
||||
bool success = doExport(argument, false);
|
||||
dr.setError(success);
|
||||
if (!success)
|
||||
@ -1785,38 +1783,6 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_BUFFER_UPDATE: {
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = getDefaultOutputFormat();
|
||||
doExport(format, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_BUFFER_VIEW: {
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = getDefaultOutputFormat();
|
||||
preview(format);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_MASTER_BUFFER_UPDATE: {
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = masterBuffer()->getDefaultOutputFormat();
|
||||
masterBuffer()->doExport(format, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_MASTER_BUFFER_VIEW: {
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = masterBuffer()->getDefaultOutputFormat();
|
||||
masterBuffer()->preview(format);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_BUILD_PROGRAM:
|
||||
doExport("program", true);
|
||||
break;
|
||||
@ -3132,14 +3098,18 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
|
||||
path = p;
|
||||
}
|
||||
}
|
||||
if (!path.empty())
|
||||
runparams.flavor = theConverters().getFlavor(path);
|
||||
else {
|
||||
Alert::error(_("Couldn't export file"),
|
||||
bformat(_("No information for exporting the format %1$s."),
|
||||
if (path.empty()) {
|
||||
if (!put_in_tempdir) {
|
||||
// Only show this alert if this is an export to a non-temporary
|
||||
// file (not for previewing).
|
||||
Alert::error(_("Couldn't export file"), bformat(
|
||||
_("No information for exporting the format %1$s."),
|
||||
formats.prettyName(format)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
runparams.flavor = theConverters().getFlavor(path);
|
||||
|
||||
} else {
|
||||
backend_format = format;
|
||||
// FIXME: Don't hardcode format names here, but use a flag
|
||||
|
@ -125,7 +125,8 @@ public:
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
explicit Buffer(std::string const & file, bool b = false);
|
||||
explicit Buffer(std::string const & file, bool readonly = false,
|
||||
Buffer const * cloned_buffer = 0);
|
||||
|
||||
/// Destructor
|
||||
~Buffer();
|
||||
@ -512,6 +513,8 @@ public:
|
||||
bool isExportable(std::string const & format) const;
|
||||
///
|
||||
std::vector<Format const *> exportableFormats(bool only_viewable) const;
|
||||
///
|
||||
bool isExportableFormat(std::string const & format) const;
|
||||
|
||||
///
|
||||
typedef std::vector<std::pair<InsetRef *, ParIterator> > References;
|
||||
|
@ -102,6 +102,8 @@
|
||||
#include <QUrl>
|
||||
#include <QScrollBar>
|
||||
|
||||
#define EXPORT_in_THREAD 1
|
||||
|
||||
// QtConcurrent was introduced in Qt 4.4
|
||||
#if (QT_VERSION >= 0x040400)
|
||||
#include <QFuture>
|
||||
@ -300,7 +302,8 @@ public:
|
||||
|
||||
#if (QT_VERSION >= 0x040400)
|
||||
///
|
||||
QFutureWatcher<bool> autosave_watcher_;
|
||||
QFutureWatcher<docstring> autosave_watcher_;
|
||||
QFutureWatcher<docstring> preview_watcher_;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -365,7 +368,9 @@ GuiView::GuiView(int id)
|
||||
|
||||
#if (QT_VERSION >= 0x040400)
|
||||
connect(&d.autosave_watcher_, SIGNAL(finished()), this,
|
||||
SLOT(autoSaveFinished()));
|
||||
SLOT(threadFinished()));
|
||||
connect(&d.preview_watcher_, SIGNAL(finished()), this,
|
||||
SLOT(threadFinished()));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -376,12 +381,12 @@ GuiView::~GuiView()
|
||||
}
|
||||
|
||||
|
||||
void GuiView::autoSaveFinished()
|
||||
void GuiView::threadFinished()
|
||||
{
|
||||
#if (QT_VERSION >= 0x040400)
|
||||
docstring const msg = d.autosave_watcher_.result()
|
||||
? _("Automatic save done.") : _("Automatic save failed!");
|
||||
message(msg);
|
||||
QFutureWatcher<docstring> const * watcher =
|
||||
static_cast<QFutureWatcher<docstring> const *>(sender());
|
||||
message(watcher->result());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1222,7 +1227,7 @@ BufferView const * GuiView::currentBufferView() const
|
||||
}
|
||||
|
||||
|
||||
static bool saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
|
||||
static docstring saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
|
||||
{
|
||||
bool failed = true;
|
||||
FileName const tmp_ret = FileName::tempName("lyxauto");
|
||||
@ -1235,7 +1240,9 @@ static bool saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
|
||||
failed = buffer->writeFile(fname);
|
||||
}
|
||||
delete buffer;
|
||||
return !failed;
|
||||
return failed
|
||||
? _("Automatic save failed!")
|
||||
: _("Automatic save done.");
|
||||
}
|
||||
|
||||
|
||||
@ -1249,7 +1256,7 @@ void GuiView::autoSave()
|
||||
return;
|
||||
|
||||
#if (QT_VERSION >= 0x040400)
|
||||
QFuture<bool> f = QtConcurrent::run(saveAndDestroyBuffer, buffer->clone(),
|
||||
QFuture<docstring> f = QtConcurrent::run(saveAndDestroyBuffer, buffer->clone(),
|
||||
buffer->getAutosaveFilename());
|
||||
d.autosave_watcher_.setFuture(f);
|
||||
#else
|
||||
@ -1296,6 +1303,24 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
|
||||
case LFUN_BUFFER_IMPORT:
|
||||
break;
|
||||
|
||||
case LFUN_MASTER_BUFFER_UPDATE:
|
||||
case LFUN_MASTER_BUFFER_VIEW:
|
||||
enable = doc_buffer && doc_buffer->parent() != 0;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_UPDATE:
|
||||
case LFUN_BUFFER_VIEW: {
|
||||
if (!doc_buffer) {
|
||||
enable = false;
|
||||
break;
|
||||
}
|
||||
string format = to_utf8(cmd.argument());
|
||||
if (cmd.argument().empty())
|
||||
format = doc_buffer->getDefaultOutputFormat();
|
||||
enable = doc_buffer->isExportableFormat(format);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_BUFFER_RELOAD:
|
||||
enable = doc_buffer && !doc_buffer->isUnnamed()
|
||||
&& doc_buffer->fileName().exists()
|
||||
@ -2585,6 +2610,26 @@ bool GuiView::goToFileRow(string const & argument)
|
||||
}
|
||||
|
||||
|
||||
static docstring exportAndDestroy(Buffer * buffer, docstring const & format)
|
||||
{
|
||||
bool const success = buffer->doExport(to_utf8(format), true);
|
||||
delete buffer;
|
||||
return success
|
||||
? bformat(_("Successful export to format: %1$s."), format)
|
||||
: bformat(_("Error exporting to format: %1$s."), format);
|
||||
}
|
||||
|
||||
|
||||
static docstring previewAndDestroy(Buffer * buffer, docstring const & format)
|
||||
{
|
||||
bool const success = buffer->preview(to_utf8(format));
|
||||
delete buffer;
|
||||
return success
|
||||
? bformat(_("Successful preview of format: %1$s."), format)
|
||||
: bformat(_("Error previewing format: %1$s."), format);
|
||||
}
|
||||
|
||||
|
||||
bool GuiView::dispatch(FuncRequest const & cmd)
|
||||
{
|
||||
BufferView * bv = currentBufferView();
|
||||
@ -2603,6 +2648,8 @@ bool GuiView::dispatch(FuncRequest const & cmd)
|
||||
return true;
|
||||
}
|
||||
|
||||
string const argument = to_utf8(cmd.argument());
|
||||
|
||||
switch(cmd.action) {
|
||||
case LFUN_BUFFER_CHILD_OPEN:
|
||||
openChildDocument(to_utf8(cmd.argument()));
|
||||
@ -2612,6 +2659,80 @@ bool GuiView::dispatch(FuncRequest const & cmd)
|
||||
importDocument(to_utf8(cmd.argument()));
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_EXPORT: {
|
||||
if (!doc_buffer)
|
||||
break;
|
||||
if (cmd.argument() == "custom") {
|
||||
lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
|
||||
break;
|
||||
}
|
||||
if (doc_buffer->doExport(argument, false)) {
|
||||
message(bformat(_("Error exporting to format: %1$s."),
|
||||
cmd.argument()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_BUFFER_UPDATE: {
|
||||
if (!doc_buffer)
|
||||
break;
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = doc_buffer->getDefaultOutputFormat();
|
||||
#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
|
||||
QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
|
||||
doc_buffer->clone(), cmd.argument());
|
||||
d.preview_watcher_.setFuture(f);
|
||||
#else
|
||||
doc_buffer->doExport(format, true);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case LFUN_BUFFER_VIEW: {
|
||||
if (!doc_buffer)
|
||||
break;
|
||||
string format = argument;
|
||||
if (argument.empty())
|
||||
format = doc_buffer->getDefaultOutputFormat();
|
||||
#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
|
||||
QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
|
||||
doc_buffer->clone(), cmd.argument());
|
||||
d.preview_watcher_.setFuture(f);
|
||||
#else
|
||||
doc_buffer->preview(format);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case LFUN_MASTER_BUFFER_UPDATE: {
|
||||
if (!doc_buffer)
|
||||
break;
|
||||
string format = argument;
|
||||
Buffer const * master = doc_buffer->masterBuffer();
|
||||
if (argument.empty())
|
||||
format = master->getDefaultOutputFormat();
|
||||
#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
|
||||
QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
|
||||
master->clone(), cmd.argument());
|
||||
d.preview_watcher_.setFuture(f);
|
||||
#else
|
||||
master->doExport(format, true);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case LFUN_MASTER_BUFFER_VIEW: {
|
||||
string format = argument;
|
||||
Buffer const * master = doc_buffer->masterBuffer();
|
||||
if (argument.empty())
|
||||
format = master->getDefaultOutputFormat();
|
||||
#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
|
||||
QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
|
||||
master->clone(), cmd.argument());
|
||||
d.preview_watcher_.setFuture(f);
|
||||
#else
|
||||
master->preview(format);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case LFUN_BUFFER_SWITCH:
|
||||
if (FileName::isAbsolute(to_utf8(cmd.argument()))) {
|
||||
Buffer * buffer =
|
||||
|
@ -180,8 +180,8 @@ private Q_SLOTS:
|
||||
void normalSizedIcons();
|
||||
void bigSizedIcons();
|
||||
|
||||
/// For completion of Buffer autosave thread.
|
||||
void autoSaveFinished();
|
||||
/// For completion of autosave or exporrt threads.
|
||||
void threadFinished();
|
||||
|
||||
private:
|
||||
/// Open given child document in current buffer directory.
|
||||
|
Loading…
Reference in New Issue
Block a user