]> git.lyx.org Git - features.git/blobdiff - src/frontends/qt4/GuiView.cpp
Fix monolithic build
[features.git] / src / frontends / qt4 / GuiView.cpp
index 3198e0310772bdcc1cb2b0cae091b30df37fea54..bb8da339d45400cd56726ea2c491609f958ed3af 100644 (file)
@@ -76,7 +76,7 @@
 #include "support/lstrings.h"
 #include "support/os.h"
 #include "support/Package.h"
-#include "support/Path.h"
+#include "support/PathChanger.h"
 #include "support/Systemcall.h"
 #include "support/Timeout.h"
 #include "support/ProgressInterface.h"
 #include <QDesktopWidget>
 #include <QDragEnterEvent>
 #include <QDropEvent>
+#include <QFuture>
+#include <QFutureWatcher>
 #include <QLabel>
 #include <QList>
 #include <QMenu>
 #include <QMenuBar>
+#include <QMimeData>
 #include <QMovie>
 #include <QPainter>
 #include <QPixmap>
 #include <QPixmapCache>
 #include <QPoint>
 #include <QPushButton>
+#include <QScrollBar>
 #include <QSettings>
 #include <QShowEvent>
 #include <QSplitter>
 #include <QStackedWidget>
 #include <QStatusBar>
+#include <QtConcurrentRun>
 #include <QTime>
 #include <QTimer>
 #include <QToolBar>
 #include <QUrl>
-#include <QScrollBar>
 
 
 
 #define EXPORT_in_THREAD 1
 
-// QtConcurrent was introduced in Qt 4.4
-#if (QT_VERSION >= 0x040400)
-#include <QFuture>
-#include <QFutureWatcher>
-#include <QtConcurrentRun>
-#endif
 
 #include "support/bind.h"
 
@@ -238,7 +236,7 @@ struct GuiView::GuiViewPrivate
                // TODO cleanup, remove the singleton, handle multiple Windows?
                progress_ = ProgressInterface::instance();
                if (!dynamic_cast<GuiProgress*>(progress_)) {
-                       progress_ = new GuiProgress();  // TODO who deletes it
+                       progress_ = new GuiProgress;  // TODO who deletes it
                        ProgressInterface::setInstance(progress_);
                }
                QObject::connect(
@@ -330,7 +328,18 @@ struct GuiView::GuiViewPrivate
                return tabWorkArea(0);
        }
 
-#if (QT_VERSION >= 0x040400)
+       int countWorkAreasOf(Buffer & buf)
+       {
+               int areas = tabWorkAreaCount();
+               int count = 0;
+               for (int i = 0; i != areas;  ++i) {
+                       TabWorkArea * twa = tabWorkArea(i);
+                       if (twa->workArea(buf))
+                               ++count;
+               }
+               return count;
+       }
+
        void setPreviewFuture(QFuture<Buffer::ExportStatus> const & f)
        {
                if (processing_thread_watcher_.isRunning()) {
@@ -340,7 +349,6 @@ struct GuiView::GuiViewPrivate
                }
                processing_thread_watcher_.setFuture(f);
        }
-#endif
 
 public:
        GuiView * gv_;
@@ -379,17 +387,12 @@ public:
        ///
        TocModels toc_models_;
 
-#if (QT_VERSION >= 0x040400)
        ///
        QFutureWatcher<docstring> autosave_watcher_;
        QFutureWatcher<Buffer::ExportStatus> processing_thread_watcher_;
        ///
        string last_export_format;
        string processing_format;
-#else
-       struct DummyWatcher { bool isRunning(){return false;} };
-       DummyWatcher processing_thread_watcher_;
-#endif
 
        static QSet<Buffer const *> busyBuffers;
        static Buffer::ExportStatus previewAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
@@ -455,18 +458,15 @@ GuiView::GuiView(int id)
 #endif
 
 #endif
+       resetWindowTitleAndIconText();
 
-#if (QT_VERSION >= 0x040300)
        // use tabbed dock area for multiple docks
        // (such as "source" and "messages")
        setDockOptions(QMainWindow::ForceTabbedDocks);
-#endif
 
        // For Drag&Drop.
        setAcceptDrops(true);
 
-#if (QT_VERSION >= 0x040400)
-
        // add busy indicator to statusbar
        QLabel * busylabel = new QLabel(statusBar());
        statusBar()->addPermanentWidget(busylabel);
@@ -492,8 +492,6 @@ GuiView::GuiView(int id)
        connect(&d.processing_thread_watcher_, SIGNAL(finished()), this,
                SLOT(processingThreadFinished()));
 
-#endif
-
        connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)),
                SLOT(doShowDialog(QString const &, QString const &, Inset *)));
 
@@ -564,8 +562,6 @@ static void handleExportStatus(GuiView * view, Buffer::ExportStatus status,
 }
 
 
-#if QT_VERSION >= 0x040400
-
 void GuiView::processingThreadStarted()
 {
 }
@@ -597,23 +593,6 @@ void GuiView::autoSaveThreadFinished()
        updateToolbars();
 }
 
-#else
-
-void GuiView::processingThreadStarted()
-{
-}
-
-
-void GuiView::processingThreadFinished()
-{
-}
-
-
-void GuiView::autoSaveThreadFinished()
-{
-}
-#endif
-
 
 void GuiView::saveLayout() const
 {
@@ -753,29 +732,20 @@ void GuiView::initToolbars()
                }
 
                if (visibility & Toolbars::BOTTOM) {
-                       // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
-#if (QT_VERSION >= 0x040202)
                        if (newline)
                                addToolBarBreak(Qt::BottomToolBarArea);
-#endif
                        addToolBar(Qt::BottomToolBarArea, tb);
                }
 
                if (visibility & Toolbars::LEFT) {
-                       // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
-#if (QT_VERSION >= 0x040202)
                        if (newline)
                                addToolBarBreak(Qt::LeftToolBarArea);
-#endif
                        addToolBar(Qt::LeftToolBarArea, tb);
                }
 
                if (visibility & Toolbars::RIGHT) {
-                       // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
-#if (QT_VERSION >= 0x040202)
                        if (newline)
                                addToolBarBreak(Qt::RightToolBarArea);
-#endif
                        addToolBar(Qt::RightToolBarArea, tb);
                }
 
@@ -1022,8 +992,9 @@ void GuiView::updateWindowTitle(GuiWorkArea * wa)
 
 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
 {
-       QObject::disconnect(d.current_work_area_, SIGNAL(busy(bool)),
-               this, SLOT(setBusy(bool)));
+       if (d.current_work_area_)
+               QObject::disconnect(d.current_work_area_, SIGNAL(busy(bool)),
+                       this, SLOT(setBusy(bool)));
        disconnectBuffer();
        disconnectBufferView();
        connectBufferView(wa->bufferView());
@@ -1154,9 +1125,7 @@ bool GuiView::event(QEvent * e)
        }
 
        case QEvent::ShortcutOverride: {
-
-// See bug 4888
-#if (!defined Q_WS_X11) || (QT_VERSION >= 0x040500)
+               // See bug 4888
                if (isFullScreen() && menuBar()->isHidden()) {
                        QKeyEvent * ke = static_cast<QKeyEvent*>(e);
                        // FIXME: we should also try to detect special LyX shortcut such as
@@ -1168,7 +1137,6 @@ bool GuiView::event(QEvent * e)
                                return QMainWindow::event(e);
                        }
                }
-#endif
                return QMainWindow::event(e);
        }
 
@@ -1404,12 +1372,14 @@ void GuiView::updateToolbars()
                        lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onOff(true);
                bool const mathmacrotemplate =
                        lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
+               bool const ipa =
+                       lyx::getStatus(FuncRequest(LFUN_IN_IPA)).enabled();
 
                for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
-                       it->second->update(math, table, review, mathmacrotemplate);
+                       it->second->update(math, table, review, mathmacrotemplate, ipa);
        } else
                for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
-                       it->second->update(false, false, false, false);
+                       it->second->update(false, false, false, false, false);
 }
 
 
@@ -1472,7 +1442,7 @@ void GuiView::errors(string const & error_type, bool from_master)
        if (!bv)
                return;
 
-#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+#if EXPORT_in_THREAD
        // We are called with from_master == false by default, so we
        // have to figure out whether that is the case or not.
        ErrorList & el = bv->buffer().errorList(error_type);
@@ -1554,7 +1524,6 @@ BufferView const * GuiView::currentBufferView() const
 }
 
 
-#if (QT_VERSION >= 0x040400)
 docstring GuiView::GuiViewPrivate::autosaveAndDestroy(
        Buffer const * orig, Buffer * clone)
 {
@@ -1565,7 +1534,6 @@ docstring GuiView::GuiViewPrivate::autosaveAndDestroy(
                ? _("Automatic save done.")
                : _("Automatic save failed!");
 }
-#endif
 
 
 void GuiView::autoSave()
@@ -1579,14 +1547,10 @@ void GuiView::autoSave()
                return;
        }
 
-#if (QT_VERSION >= 0x040400)
        GuiViewPrivate::busyBuffers.insert(buffer);
        QFuture<docstring> f = QtConcurrent::run(GuiViewPrivate::autosaveAndDestroy,
                buffer, buffer->cloneBufferOnly());
        d.autosave_watcher_.setFuture(f);
-#else
-       buffer->autoSave();
-#endif
        resetAutosaveTimers();
 }
 
@@ -1685,6 +1649,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
 
        case LFUN_BUFFER_CLOSE:
+       case LFUN_VIEW_CLOSE:
                enable = doc_buffer;
                break;
 
@@ -1692,7 +1657,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                enable = theBufferList().last() != theBufferList().first();
                break;
 
-       case LFUN_SPLIT_VIEW:
+       case LFUN_VIEW_SPLIT:
                if (cmd.getArg(0) == "vertical")
                        enable = doc_buffer && (d.splitter_->count() == 1 ||
                                         d.splitter_->orientation() == Qt::Vertical);
@@ -1701,8 +1666,8 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                                         d.splitter_->orientation() == Qt::Horizontal);
                break;
 
-       case LFUN_CLOSE_TAB_GROUP:
-               enable = d.currentTabWorkArea();
+       case LFUN_TAB_GROUP_CLOSE:
+               enable = d.tabWorkAreaCount() > 1;
                break;
 
        case LFUN_TOOLBAR_TOGGLE: {
@@ -1839,6 +1804,12 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        case LFUN_VC_REGISTER:
                enable = doc_buffer && !doc_buffer->lyxvc().inUse();
                break;
+       case LFUN_VC_RENAME:
+               enable = doc_buffer && doc_buffer->lyxvc().renameEnabled();
+               break;
+       case LFUN_VC_COPY:
+               enable = doc_buffer && doc_buffer->lyxvc().copyEnabled();
+               break;
        case LFUN_VC_CHECK_IN:
                enable = doc_buffer && doc_buffer->lyxvc().checkInEnabled();
                break;
@@ -1993,7 +1964,8 @@ void GuiView::openDocument(string const & fname)
 
        // if the file doesn't exist and isn't already open (bug 6645),
        // let the user create one
-       if (!fullname.exists() && !theBufferList().exists(fullname)) {
+       if (!fullname.exists() && !theBufferList().exists(fullname) &&
+           !LyXVC::file_not_found_hook(fullname)) {
                // the user specifically chose this name. Believe him.
                Buffer * const b = newFile(filename, string(), true);
                if (b)
@@ -2026,8 +1998,9 @@ static bool import(GuiView * lv, FileName const & filename,
        string loader_format;
        vector<string> loaders = theConverters().loaders();
        if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
-               for (vector<string>::const_iterator it = loaders.begin();
-                        it != loaders.end(); ++it) {
+               vector<string>::const_iterator it = loaders.begin();
+               vector<string>::const_iterator en = loaders.end();
+               for (; it != en; ++it) {
                        if (!theConverters().isReachable(format, *it))
                                continue;
 
@@ -2242,7 +2215,7 @@ void GuiView::insertLyXFile(docstring const & fname)
 }
 
 
-bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
+bool GuiView::renameBuffer(Buffer & b, docstring const & newname, RenameKind kind)
 {
        FileName fname = b.fileName();
        FileName const oldname = fname;
@@ -2286,8 +2259,9 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
        // if there is already a Buffer open with this name, we do not want
        // to have another one. (the second test makes sure we're not just
        // trying to overwrite ourselves, which is fine.)
-       if (theBufferList().exists(fname) && fname != oldname) {
-               docstring const text = 
+       if (theBufferList().exists(fname) && fname != oldname
+                 && theBufferList().getBuffer(fname) != &b) {
+               docstring const text =
                        bformat(_("The file\n%1$s\nis already open in your current session.\n"
                            "Please close it before attempting to overwrite it.\n"
                            "Do you want to choose a new filename?"),
@@ -2295,30 +2269,77 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
                int const ret = Alert::prompt(_("Chosen File Already Open"),
                        text, 0, 1, _("&Rename"), _("&Cancel"));
                switch (ret) {
-               case 0: return renameBuffer(b, docstring());
+               case 0: return renameBuffer(b, docstring(), kind);
                case 1: return false;
                }
                //return false;
        }
-       
-       if (FileName(fname).exists()) {
+
+       bool const existsLocal = fname.exists();
+       bool const existsInVC = LyXVC::fileInVC(fname);
+       if (existsLocal || existsInVC) {
                docstring const file = makeDisplayPath(fname.absFileName(), 30);
-               docstring const text = bformat(_("The document %1$s already "
-                                          "exists.\n\nDo you want to "
-                                          "overwrite that document?"),
-                                        file);
-               int const ret = Alert::prompt(_("Overwrite document?"),
-                       text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
-               switch (ret) {
-               case 0: break;
-               case 1: return renameBuffer(b, docstring());
-               case 2: return false;
+               if (kind != LV_WRITE_AS && existsInVC) {
+                       // renaming to a name that is already in VC
+                       // would not work
+                       docstring text = bformat(_("The document %1$s "
+                                       "is already registered.\n\n"
+                                       "Do you want to choose a new name?"),
+                               file);
+                       docstring const title = (kind == LV_VC_RENAME) ?
+                               _("Rename document?") : _("Copy document?");
+                       docstring const button = (kind == LV_VC_RENAME) ?
+                               _("&Rename") : _("&Copy");
+                       int const ret = Alert::prompt(title, text, 0, 1,
+                               button, _("&Cancel"));
+                       switch (ret) {
+                       case 0: return renameBuffer(b, docstring(), kind);
+                       case 1: return false;
+                       }
+               }
+
+               if (existsLocal) {
+                       docstring text = bformat(_("The document %1$s "
+                                       "already exists.\n\n"
+                                       "Do you want to overwrite that document?"),
+                               file);
+                       int const ret = Alert::prompt(_("Overwrite document?"),
+                                       text, 0, 2, _("&Overwrite"),
+                                       _("&Rename"), _("&Cancel"));
+                       switch (ret) {
+                       case 0: break;
+                       case 1: return renameBuffer(b, docstring(), kind);
+                       case 2: return false;
+                       }
                }
        }
 
+       switch (kind) {
+       case LV_VC_RENAME: {
+               string msg = b.lyxvc().rename(fname);
+               if (msg.empty())
+                       return false;
+               message(from_utf8(msg));
+               break;
+       }
+       case LV_VC_COPY: {
+               string msg = b.lyxvc().copy(fname);
+               if (msg.empty())
+                       return false;
+               message(from_utf8(msg));
+               break;
+       }
+       case LV_WRITE_AS:
+               break;
+       }
+       // LyXVC created the file already in case of LV_VC_RENAME or
+       // LV_VC_COPY, but call saveBuffer() nevertheless to get
+       // relative paths of included stuff right if we moved e.g. from
+       // /a/b.lyx to /a/c/b.lyx.
+
        bool const saved = saveBuffer(b, fname);
        if (saved)
-               b.reload();
+               b.reload(false);
        return saved;
 }
 
@@ -2398,7 +2419,8 @@ bool GuiView::exportBufferAs(Buffer & b)
 }
 
 
-bool GuiView::saveBuffer(Buffer & b) {
+bool GuiView::saveBuffer(Buffer & b)
+{
        return saveBuffer(b, FileName());
 }
 
@@ -2409,7 +2431,7 @@ bool GuiView::saveBuffer(Buffer & b, FileName const & fn)
                return true;
 
        if (fn.empty() && b.isUnnamed())
-                       return renameBuffer(b, docstring());
+               return renameBuffer(b, docstring());
 
        bool success;
        if (fn.empty())
@@ -2443,7 +2465,7 @@ bool GuiView::saveBuffer(Buffer & b, FileName const & fn)
                return false;
        }
 
-       return saveBuffer(b);
+       return saveBuffer(b, fn);
 }
 
 
@@ -2453,10 +2475,45 @@ bool GuiView::hideWorkArea(GuiWorkArea * wa)
 }
 
 
+// We only want to close the buffer if it is not visible in other workareas
+// of the same view, nor in other views, and if this is not a child
 bool GuiView::closeWorkArea(GuiWorkArea * wa)
 {
        Buffer & buf = wa->bufferView().buffer();
-       return closeWorkArea(wa, !buf.parent());
+
+       bool last_wa = d.countWorkAreasOf(buf) == 1
+               && !inOtherView(buf) && !buf.parent();
+
+       bool close_buffer = last_wa;
+
+       if (last_wa) {
+               if (lyxrc.close_buffer_with_last_view == "yes")
+                       ; // Nothing to do
+               else if (lyxrc.close_buffer_with_last_view == "no")
+                       close_buffer = false;
+               else {
+                       docstring file;
+                       if (buf.isUnnamed())
+                               file = from_utf8(buf.fileName().onlyFileName());
+                       else
+                               file = buf.fileName().displayName(30);
+                       docstring const text = bformat(
+                               _("Last view on document %1$s is being closed.\n"
+                                 "Would you like to close or hide the document?\n"
+                                 "\n"
+                                 "Hidden documents can be displayed back through\n"
+                                 "the menu: View->Hidden->...\n"
+                                 "\n"
+                                 "To remove this question, set your preference in:\n"
+                                 "  Tools->Preferences->Look&Feel->UserInterface\n"
+                               ), file);
+                       int ret = Alert::prompt(_("Close or hide document?"),
+                               text, 0, 1, _("&Close"), _("&Hide"));
+                       close_buffer = (ret == 0);
+               }
+       }
+
+       return closeWorkArea(wa, close_buffer);
 }
 
 
@@ -2805,12 +2862,48 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
                }
                break;
 
+       case LFUN_VC_RENAME:
+       case LFUN_VC_COPY: {
+               if (!buffer || !ensureBufferClean(buffer))
+                       break;
+               if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+                       if (buffer->lyxvc().isCheckInWithConfirmation()) {
+                               // Some changes are not yet committed.
+                               // We test here and not in getStatus(), since
+                               // this test is expensive.
+                               string log;
+                               LyXVC::CommandResult ret =
+                                       buffer->lyxvc().checkIn(log);
+                               dr.setMessage(log);
+                               if (ret == LyXVC::ErrorCommand ||
+                                   ret == LyXVC::VCSuccess)
+                                       reloadBuffer(*buffer);
+                               if (buffer->lyxvc().isCheckInWithConfirmation()) {
+                                       frontend::Alert::error(
+                                               _("Revision control error."),
+                                               _("Document could not be checked in."));
+                                       break;
+                               }
+                       }
+                       RenameKind const kind = (cmd.action() == LFUN_VC_RENAME) ?
+                               LV_VC_RENAME : LV_VC_COPY;
+                       renameBuffer(*buffer, cmd.argument(), kind);
+               }
+               break;
+       }
+
        case LFUN_VC_CHECK_IN:
                if (!buffer || !ensureBufferClean(buffer))
                        break;
                if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
-                       dr.setMessage(buffer->lyxvc().checkIn());
-                       if (!dr.message().empty())
+                       string log;
+                       LyXVC::CommandResult ret = buffer->lyxvc().checkIn(log);
+                       dr.setMessage(log);
+                       // Only skip reloading if the checkin was cancelled or
+                       // an error occured before the real checkin VCS command
+                       // was executed, since the VCS might have changed the
+                       // file even if it could not checkin successfully.
+                       if (ret == LyXVC::ErrorCommand || ret == LyXVC::VCSuccess)
                                reloadBuffer(*buffer);
                }
                break;
@@ -3029,7 +3122,6 @@ bool GuiView::goToFileRow(string const & argument)
 }
 
 
-#if (QT_VERSION >= 0x040400)
 template<class T>
 Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffer const * orig, Buffer * clone, string const & format)
 {
@@ -3047,49 +3139,23 @@ Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffe
 Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
 {
        Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const = &Buffer::doExport;
-       return runAndDestroy(bind(mem_func, clone, _1, true), orig, clone, format);
+       return runAndDestroy(lyx::bind(mem_func, clone, _1, true), orig, clone, format);
 }
 
 
 Buffer::ExportStatus GuiView::GuiViewPrivate::exportAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
 {
        Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const = &Buffer::doExport;
-       return runAndDestroy(bind(mem_func, clone, _1, false), orig, clone, format);
+       return runAndDestroy(lyx::bind(mem_func, clone, _1, false), orig, clone, format);
 }
 
 
 Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
 {
        Buffer::ExportStatus (Buffer::* mem_func)(std::string const &) const = &Buffer::preview;
-       return runAndDestroy(bind(mem_func, clone, _1), orig, clone, format);
+       return runAndDestroy(lyx::bind(mem_func, clone, _1), orig, clone, format);
 }
 
-#else
-
-// not used, but the linker needs them
-
-Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(
-               Buffer const *, Buffer *, string const &)
-{
-       return Buffer::ExportSuccess;
-}
-
-
-Buffer::ExportStatus GuiView::GuiViewPrivate::exportAndDestroy(
-               Buffer const *, Buffer *, string const &)
-{
-       return Buffer::ExportSuccess;
-}
-
-
-Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(
-               Buffer const *, Buffer *, string const &)
-{
-       return Buffer::ExportSuccess;
-}
-
-#endif
-
 
 bool GuiView::GuiViewPrivate::asyncBufferProcessing(
                           string const & argument,
@@ -3106,18 +3172,18 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
        if (format.empty())
                format = used_buffer->params().getDefaultOutputFormat();
        processing_format = format;
-#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+#if EXPORT_in_THREAD
        if (!msg.empty()) {
                progress_->clearMessages();
                gv_->message(msg);
        }
        GuiViewPrivate::busyBuffers.insert(used_buffer);
-  Buffer * cloned_buffer = used_buffer->cloneFromMaster();
-  if (!cloned_buffer) {
-      Alert::error(_("Export Error"), 
-                   _("Error cloning the Buffer."));
-      return false;
-  }
+       Buffer * cloned_buffer = used_buffer->cloneFromMaster();
+       if (!cloned_buffer) {
+               Alert::error(_("Export Error"),
+                            _("Error cloning the Buffer."));
+               return false;
+       }
        QFuture<Buffer::ExportStatus> f = QtConcurrent::run(
                                asyncFunc,
                                used_buffer,
@@ -3220,13 +3286,6 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"), dr);
                                break;
                        }
-#if QT_VERSION < 0x040400
-                       if (!doc_buffer->doExport(argument, false)) {
-                               dr.setError(true);
-                               dr.setMessage(bformat(_("Error exporting to format: %1$s"),
-                                       cmd.argument()));
-                       }
-#else
                        /* TODO/Review: Is it a problem to also export the children?
                                        See the update_unincluded flag */
                        d.asyncBufferProcessing(argument,
@@ -3236,7 +3295,6 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                &Buffer::doExport,
                                                0);
                        // TODO Inform user about success
-#endif
                        break;
                }
 
@@ -3540,7 +3598,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        break;
                }
 
-               case LFUN_SPLIT_VIEW: {
+               case LFUN_VIEW_SPLIT: {
                        LASSERT(doc_buffer, break);
                        string const orientation = cmd.getArg(0);
                        d.splitter_->setOrientation(orientation == "vertical"
@@ -3550,7 +3608,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        setCurrentWorkArea(wa);
                        break;
                }
-               case LFUN_CLOSE_TAB_GROUP:
+               case LFUN_TAB_GROUP_CLOSE:
                        if (TabWorkArea * twa = d.currentTabWorkArea()) {
                                closeTabWorkArea(twa);
                                d.current_work_area_ = 0;
@@ -3565,6 +3623,21 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        }
                        break;
 
+               case LFUN_VIEW_CLOSE:
+                       if (TabWorkArea * twa = d.currentTabWorkArea()) {
+                               closeWorkArea(twa->currentWorkArea());
+                               d.current_work_area_ = 0;
+                               twa = d.currentTabWorkArea();
+                               // Switch to the next GuiWorkArea in the found TabWorkArea.
+                               if (twa) {
+                                       // Make sure the work area is up to date.
+                                       setCurrentWorkArea(twa->currentWorkArea());
+                               } else {
+                                       setCurrentWorkArea(0);
+                               }
+                       }
+                       break;
+
                case LFUN_COMPLETION_INLINE:
                        if (d.current_work_area_)
                                d.current_work_area_->completer().showInline();
@@ -3616,6 +3689,8 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        break;
 
                case LFUN_VC_REGISTER:
+               case LFUN_VC_RENAME:
+               case LFUN_VC_COPY:
                case LFUN_VC_CHECK_IN:
                case LFUN_VC_CHECK_OUT:
                case LFUN_VC_REPO_UPDATE:
@@ -3639,6 +3714,8 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                        doc_buffer->absFileName(),
                                                "tex")).mangledFileName()
                                : doc_buffer->latexName();
+                       string const fulltexname = 
+                               support::makeAbsPath(texname, doc_master->temppath()).absFileName();
                        string const mastername =
                                removeExtension(doc_master->latexName());
                        FileName const dviname(addName(path.absFileName(),
@@ -3674,6 +3751,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        string texrow = convert<string>(row);
 
                        command = subst(command, "$$n", texrow);
+                       command = subst(command, "$$f", fulltexname);
                        command = subst(command, "$$t", texname);
                        command = subst(command, "$$o", outname);
 
@@ -3716,7 +3794,6 @@ bool GuiView::lfunUiToggle(string const & ui_component)
        } else if (ui_component == "menubar") {
                menuBar()->setVisible(!menuBar()->isVisible());
        } else
-#if QT_VERSION >= 0x040300
        if (ui_component == "frame") {
                int l, t, r, b;
                getContentsMargins(&l, &t, &r, &b);
@@ -3728,7 +3805,6 @@ bool GuiView::lfunUiToggle(string const & ui_component)
                        setContentsMargins(0, 0, 0, 0);
                }
        } else
-#endif
        if (ui_component == "fullscreen") {
                toggleFullScreen();
        } else
@@ -3742,9 +3818,7 @@ void GuiView::toggleFullScreen()
        if (isFullScreen()) {
                for (int i = 0; i != d.splitter_->count(); ++i)
                        d.tabWorkArea(i)->setFullScreen(false);
-#if QT_VERSION >= 0x040300
                setContentsMargins(0, 0, 0, 0);
-#endif
                setWindowState(windowState() ^ Qt::WindowFullScreen);
                restoreLayout();
                menuBar()->show();
@@ -3754,9 +3828,7 @@ void GuiView::toggleFullScreen()
                hideDialogs("prefs", 0);
                for (int i = 0; i != d.splitter_->count(); ++i)
                        d.tabWorkArea(i)->setFullScreen(true);
-#if QT_VERSION >= 0x040300
                setContentsMargins(-2, -2, -2, -2);
-#endif
                saveLayout();
                setWindowState(windowState() ^ Qt::WindowFullScreen);
                statusBar()->hide();