]> git.lyx.org Git - features.git/commitdiff
Detach Buffer preview and update preview in a new thread. Only for Qt4.4 users. This...
authorAbdelrazak Younes <younes@lyx.org>
Fri, 18 Dec 2009 22:51:06 +0000 (22:51 +0000)
committerAbdelrazak Younes <younes@lyx.org>
Fri, 18 Dec 2009 22:51:06 +0000 (22:51 +0000)
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

src/Buffer.cpp
src/Buffer.h
src/frontends/qt4/GuiView.cpp
src/frontends/qt4/GuiView.h

index 90512f0b63cbab0329fd588e93584ff600bbbd96..b4671076ad053c5e85f60cc07f9401af711b5a0f 100644 (file)
@@ -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)
 {
-       temppath = createBufferTmpDir();
-       lyxvc.setBuffer(&parent);
-       if (use_gui)
-               wa_ = new frontend::WorkAreaManager;
+       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."),
-                                  formats.prettyName(format)));
+               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
index f745aa04b8563cc2fb43eff35324156c2f5966dd..50bdf77bc9df2877eacea889a48b5564cd29f6a7 100644 (file)
@@ -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;
index 1967eacf41a320a92362fa680076d77a1279b513..435db42f2954aa21b86b76d3e3d467658cbaa067 100644 (file)
 #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 = 
index 7a610f0199d76da9f40ed28b2c0e6b4fad68751c..02bb82dfb9d136d67c7043c45ed19275470b561f 100644 (file)
@@ -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.