]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
Fix trailing whitespace in cpp files.
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index 6bfcdcb0328a76c78c783a498c3c9cbe89d90137..7b7189743ecd1de84b5588b48a03cd2c79781c31 100644 (file)
@@ -15,7 +15,6 @@
 
 #include "GuiView.h"
 
-#include "Dialog.h"
 #include "DispatchResult.h"
 #include "FileDialog.h"
 #include "FontLoader.h"
 #include <QSplitter>
 #include <QStackedWidget>
 #include <QStatusBar>
-#if QT_VERSION >= 0x050000
 #include <QSvgRenderer>
-#endif
 #include <QtConcurrentRun>
 #include <QTime>
 #include <QTimer>
@@ -230,7 +227,7 @@ private:
        /// Current ratio between physical pixels and device-independent pixels
        double pixelRatio() const {
 #if QT_VERSION >= 0x050000
-               return devicePixelRatio();
+               return qt_scale_factor * devicePixelRatio();
 #else
                return 1.0;
 #endif
@@ -330,62 +327,6 @@ public:
                delete stack_widget_;
        }
 
-       QMenu * toolBarPopup(GuiView * parent)
-       {
-               // FIXME: translation
-               QMenu * menu = new QMenu(parent);
-               QActionGroup * iconSizeGroup = new QActionGroup(parent);
-
-               QAction * smallIcons = new QAction(iconSizeGroup);
-               smallIcons->setText(qt_("Small-sized icons"));
-               smallIcons->setCheckable(true);
-               QObject::connect(smallIcons, SIGNAL(triggered()),
-                       parent, SLOT(smallSizedIcons()));
-               menu->addAction(smallIcons);
-
-               QAction * normalIcons = new QAction(iconSizeGroup);
-               normalIcons->setText(qt_("Normal-sized icons"));
-               normalIcons->setCheckable(true);
-               QObject::connect(normalIcons, SIGNAL(triggered()),
-                       parent, SLOT(normalSizedIcons()));
-               menu->addAction(normalIcons);
-
-               QAction * bigIcons = new QAction(iconSizeGroup);
-               bigIcons->setText(qt_("Big-sized icons"));
-               bigIcons->setCheckable(true);
-               QObject::connect(bigIcons, SIGNAL(triggered()),
-                       parent, SLOT(bigSizedIcons()));
-               menu->addAction(bigIcons);
-
-               QAction * hugeIcons = new QAction(iconSizeGroup);
-               hugeIcons->setText(qt_("Huge-sized icons"));
-               hugeIcons->setCheckable(true);
-               QObject::connect(hugeIcons, SIGNAL(triggered()),
-                       parent, SLOT(hugeSizedIcons()));
-               menu->addAction(hugeIcons);
-
-               QAction * giantIcons = new QAction(iconSizeGroup);
-               giantIcons->setText(qt_("Giant-sized icons"));
-               giantIcons->setCheckable(true);
-               QObject::connect(giantIcons, SIGNAL(triggered()),
-                       parent, SLOT(giantSizedIcons()));
-               menu->addAction(giantIcons);
-
-               unsigned int cur = parent->iconSize().width();
-               if ( cur == parent->d.smallIconSize)
-                       smallIcons->setChecked(true);
-               else if (cur == parent->d.normalIconSize)
-                       normalIcons->setChecked(true);
-               else if (cur == parent->d.bigIconSize)
-                       bigIcons->setChecked(true);
-               else if (cur == parent->d.hugeIconSize)
-                       hugeIcons->setChecked(true);
-               else if (cur == parent->d.giantIconSize)
-                       giantIcons->setChecked(true);
-
-               return menu;
-       }
-
        void setBackground()
        {
                stack_widget_->setCurrentWidget(bg_widget_);
@@ -442,6 +383,60 @@ public:
                processing_thread_watcher_.setFuture(f);
        }
 
+       QSize iconSize(docstring const & icon_size)
+       {
+               unsigned int size;
+               if (icon_size == "small")
+                       size = smallIconSize;
+               else if (icon_size == "normal")
+                       size = normalIconSize;
+               else if (icon_size == "big")
+                       size = bigIconSize;
+               else if (icon_size == "huge")
+                       size = hugeIconSize;
+               else if (icon_size == "giant")
+                       size = giantIconSize;
+               else
+                       size = icon_size.empty() ? normalIconSize : convert<int>(icon_size);
+
+               if (size < smallIconSize)
+                       size = smallIconSize;
+
+               return QSize(size, size);
+       }
+
+       QSize iconSize(QString const & icon_size)
+       {
+               return iconSize(qstring_to_ucs4(icon_size));
+       }
+
+       string & iconSize(QSize const & qsize)
+       {
+               LATTEST(qsize.width() == qsize.height());
+
+               static string icon_size;
+
+               unsigned int size = qsize.width();
+
+               if (size < smallIconSize)
+                       size = smallIconSize;
+
+               if (size == smallIconSize)
+                       icon_size = "small";
+               else if (size == normalIconSize)
+                       icon_size = "normal";
+               else if (size == bigIconSize)
+                       icon_size = "big";
+               else if (size == hugeIconSize)
+                       icon_size = "huge";
+               else if (size == giantIconSize)
+                       icon_size = "giant";
+               else
+                       icon_size = convert<string>(size);
+
+               return icon_size;
+       }
+
 public:
        GuiView * gv_;
        GuiWorkArea * current_work_area_;
@@ -513,10 +508,13 @@ QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
 
 GuiView::GuiView(int id)
        : d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
-         command_execute_(false)
+         command_execute_(false), minibuffer_focus_(false)
 {
+       connect(this, SIGNAL(bufferViewChanged()),
+               this, SLOT(onBufferViewChanged()));
+
        // GuiToolbars *must* be initialised before the menu bar.
-       normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
+       setIconSize(QSize(d.normalIconSize, d.normalIconSize)); // at least on Mac the default is 32 otherwise, which is huge
        constructToolbars();
 
        // set ourself as the current view. This is needed for the menu bar
@@ -531,7 +529,8 @@ GuiView::GuiView(int id)
 
        // Start autosave timer
        if (lyxrc.autosave) {
-               d.autosave_timeout_.timeout.connect(bind(&GuiView::autoSave, this));
+               // The connection is closed when this is destroyed.
+               d.autosave_timeout_.timeout.connect([this](){ autoSave();});
                d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
                d.autosave_timeout_.start();
        }
@@ -553,7 +552,7 @@ GuiView::GuiView(int id)
 #endif
 
 #endif
-       resetWindowTitleAndIconText();
+       resetWindowTitle();
 
        // use tabbed dock area for multiple docks
        // (such as "source" and "messages")
@@ -572,11 +571,28 @@ GuiView::GuiView(int id)
        busyanim->start();
        busylabel->hide();
 
-       connect(&d.processing_thread_watcher_, SIGNAL(started()), 
+       connect(&d.processing_thread_watcher_, SIGNAL(started()),
                busylabel, SLOT(show()));
-       connect(&d.processing_thread_watcher_, SIGNAL(finished()), 
+       connect(&d.processing_thread_watcher_, SIGNAL(finished()),
                busylabel, SLOT(hide()));
 
+       QFontMetrics const fm(statusBar()->fontMetrics());
+       int const roheight = max(int(d.normalIconSize), fm.height());
+       QSize const rosize(roheight, roheight);
+       QPixmap readonly = QIcon(getPixmap("images/", "emblem-readonly", "svgz,png")).pixmap(rosize);
+       read_only_ = new QLabel(statusBar());
+       read_only_->setPixmap(readonly);
+       read_only_->setScaledContents(true);
+       read_only_->setAlignment(Qt::AlignCenter);
+       read_only_->hide();
+       statusBar()->addPermanentWidget(read_only_);
+
+       version_control_ = new QLabel(statusBar());
+       version_control_->setAlignment(Qt::AlignCenter);
+       version_control_->setFrameStyle(QFrame::StyledPanel);
+       version_control_->hide();
+       statusBar()->addPermanentWidget(version_control_);
+
        statusBar()->setSizeGripEnabled(true);
        updateStatusBar();
 
@@ -591,6 +607,11 @@ GuiView::GuiView(int id)
        connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)),
                SLOT(doShowDialog(QString const &, QString const &, Inset *)));
 
+       // set custom application bars context menu, e.g. tool bar and menu bar
+       setContextMenuPolicy(Qt::CustomContextMenu);
+       connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
+               SLOT(toolBarPopup(const QPoint &)));
+
        // Forbid too small unresizable window because it can happen
        // with some window manager under X11.
        setMinimumSize(300, 200);
@@ -632,7 +653,7 @@ QVector<GuiWorkArea*> GuiView::GuiViewPrivate::guiWorkAreas()
 static void handleExportStatus(GuiView * view, Buffer::ExportStatus status,
        string const & format)
 {
-       docstring const fmt = formats.prettyName(format);
+       docstring const fmt = theFormats().prettyName(format);
        docstring msg;
        switch (status) {
        case Buffer::ExportSuccess:
@@ -670,7 +691,7 @@ void GuiView::processingThreadFinished()
 
        Buffer::ExportStatus const status = watcher->result();
        handleExportStatus(this, status, d.processing_format);
-       
+
        updateToolbars();
        BufferView const * const bv = currentBufferView();
        if (bv && !bv->buffer().errorList("Export").empty()) {
@@ -693,6 +714,7 @@ void GuiView::autoSaveThreadFinished()
 void GuiView::saveLayout() const
 {
        QSettings settings;
+       settings.setValue("zoom", lyxrc.currentZoom);
        settings.beginGroup("views");
        settings.beginGroup(QString::number(id_));
 #if defined(Q_WS_X11) || defined(QPA_XCB)
@@ -702,7 +724,7 @@ void GuiView::saveLayout() const
        settings.setValue("geometry", saveGeometry());
 #endif
        settings.setValue("layout", saveState(0));
-       settings.setValue("icon_size", iconSize());
+       settings.setValue("icon_size", toqstr(d.iconSize(iconSize())));
 }
 
 
@@ -722,6 +744,8 @@ void GuiView::saveUISettings() const
 bool GuiView::restoreLayout()
 {
        QSettings settings;
+       lyxrc.currentZoom = settings.value("zoom", lyxrc.zoom).toInt();
+       lyx::dispatch(FuncRequest(LFUN_BUFFER_ZOOM, convert<docstring>(lyxrc.currentZoom)));
        settings.beginGroup("views");
        settings.beginGroup(QString::number(id_));
        QString const icon_key = "icon_size";
@@ -729,17 +753,7 @@ bool GuiView::restoreLayout()
                return false;
 
        //code below is skipped when when ~/.config/LyX is (re)created
-       QSize icon_size = settings.value(icon_key).toSize();
-       // Check whether session size changed.
-       if (icon_size.width() != int(d.smallIconSize) &&
-           icon_size.width() != int(d.normalIconSize) &&
-           icon_size.width() != int(d.bigIconSize) &&
-           icon_size.width() != int(d.hugeIconSize) &&
-           icon_size.width() != int(d.giantIconSize)) {
-               icon_size.setWidth(d.normalIconSize);
-               icon_size.setHeight(d.normalIconSize);
-       }
-       setIconSize(icon_size);
+       setIconSize(d.iconSize(settings.value(icon_key).toString()));
 
 #if defined(Q_WS_X11) || defined(QPA_XCB)
        QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
@@ -770,7 +784,7 @@ bool GuiView::restoreLayout()
 
        if (!restoreState(settings.value("layout").toByteArray(), 0))
                initToolbars();
-       
+
        // init the toolbars that have not been restored
        Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
        Toolbars::Infos::iterator end = guiApp->toolbars().end();
@@ -780,6 +794,9 @@ bool GuiView::restoreLayout()
                        initToolbar(cit->name);
        }
 
+       // update lock (all) toolbars positions
+       updateLockToolbars();
+
        updateDialogs();
        return true;
 }
@@ -796,6 +813,17 @@ GuiToolbar * GuiView::toolbar(string const & name)
 }
 
 
+void GuiView::updateLockToolbars()
+{
+       toolbarsMovable_ = false;
+       for (ToolbarInfo const & info : guiApp->toolbars()) {
+               GuiToolbar * tb = toolbar(info.name);
+               if (tb && tb->isMovable())
+                       toolbarsMovable_ = true;
+       }
+}
+
+
 void GuiView::constructToolbars()
 {
        ToolbarMap::iterator it = d.toolbars_.begin();
@@ -863,6 +891,8 @@ void GuiView::initToolbar(string const & name)
 
        if (visibility & Toolbars::ON)
                tb->setVisible(true);
+
+       tb->setMovable(true);
 }
 
 
@@ -904,12 +934,6 @@ void GuiView::focusInEvent(QFocusEvent * e)
 }
 
 
-QMenu * GuiView::createPopupMenu()
-{
-       return d.toolBarPopup(this);
-}
-
-
 void GuiView::showEvent(QShowEvent * e)
 {
        LYXERR(Debug::GUI, "Passed Geometry "
@@ -966,7 +990,7 @@ void GuiView::closeEvent(QCloseEvent * close_event)
        LYXERR(Debug::DEBUG, "GuiView::closeEvent()");
 
        if (!GuiViewPrivate::busyBuffers.isEmpty()) {
-               Alert::warning(_("Exit LyX"), 
+               Alert::warning(_("Exit LyX"),
                        _("LyX could not be closed because documents are being processed by LyX."));
                close_event->setAccepted(false);
                return;
@@ -1097,36 +1121,6 @@ void GuiView::updateStatusBarMessage(QString const & str)
 }
 
 
-void GuiView::smallSizedIcons()
-{
-       setIconSize(QSize(d.smallIconSize, d.smallIconSize));
-}
-
-
-void GuiView::normalSizedIcons()
-{
-       setIconSize(QSize(d.normalIconSize, d.normalIconSize));
-}
-
-
-void GuiView::bigSizedIcons()
-{
-       setIconSize(QSize(d.bigIconSize, d.bigIconSize));
-}
-
-
-void GuiView::hugeSizedIcons()
-{
-       setIconSize(QSize(d.hugeIconSize, d.hugeIconSize));
-}
-
-
-void GuiView::giantSizedIcons()
-{
-       setIconSize(QSize(d.giantIconSize, d.giantIconSize));
-}
-
-
 void GuiView::clearMessage()
 {
        // FIXME: This code was introduced in r19643 to fix bug #4123. However,
@@ -1144,37 +1138,64 @@ void GuiView::updateWindowTitle(GuiWorkArea * wa)
        if (wa != d.current_work_area_
                || wa->bufferView().buffer().isInternal())
                return;
-       setWindowTitle(qt_("LyX: ") + wa->windowTitle());
-       setWindowIconText(wa->windowIconText());
-#if (QT_VERSION >= 0x040400)
-       // Sets the path for the window: this is used by OSX to 
+       Buffer const & buf = wa->bufferView().buffer();
+       // Set the windows title
+       docstring title = buf.fileName().displayName(130) + from_ascii("[*]");
+       if (buf.notifiesExternalModification()) {
+               title = bformat(_("%1$s (modified externally)"), title);
+               // If the external modification status has changed, then maybe the status of
+               // buffer-save has changed too.
+               updateToolbars();
+       }
+#ifndef Q_WS_MAC
+       title += from_ascii(" - LyX");
+#endif
+       setWindowTitle(toqstr(title));
+       // Sets the path for the window: this is used by OSX to
        // allow a context click on the title bar showing a menu
        // with the path up to the file
-       setWindowFilePath(toqstr(wa->bufferView().buffer().absFileName()));
-#endif
+       setWindowFilePath(toqstr(buf.absFileName()));
+       // Tell Qt whether the current document is changed
+       setWindowModified(!buf.isClean());
+
+       if (buf.hasReadonlyFlag())
+               read_only_->show();
+       else
+               read_only_->hide();
+
+       if (buf.lyxvc().inUse()) {
+               version_control_->show();
+               version_control_->setText(toqstr(buf.lyxvc().vcstatus()));
+       } else
+               version_control_->hide();
 }
 
 
 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
 {
        if (d.current_work_area_)
-               QObject::disconnect(d.current_work_area_, SIGNAL(busy(bool)),
-                       this, SLOT(setBusy(bool)));
+               // disconnect the current work area from all slots
+               QObject::disconnect(d.current_work_area_, 0, this, 0);
        disconnectBuffer();
        disconnectBufferView();
        connectBufferView(wa->bufferView());
        connectBuffer(wa->bufferView().buffer());
        d.current_work_area_ = wa;
        QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
-               this, SLOT(updateWindowTitle(GuiWorkArea *)));
-       QObject::connect(wa, SIGNAL(busy(bool)), this, SLOT(setBusy(bool)));
-       updateWindowTitle(wa);
-
-       structureChanged();
+                        this, SLOT(updateWindowTitle(GuiWorkArea *)));
+       QObject::connect(wa, SIGNAL(busy(bool)),
+                        this, SLOT(setBusy(bool)));
+       // connection of a signal to a signal
+       QObject::connect(wa, SIGNAL(bufferViewChanged()),
+                        this, SIGNAL(bufferViewChanged()));
+       Q_EMIT updateWindowTitle(wa);
+       Q_EMIT bufferViewChanged();
+}
 
-       // The document settings needs to be reinitialised.
-       updateDialog("document", "");
 
+void GuiView::onBufferViewChanged()
+{
+       structureChanged();
        // Buffer-dependent dialogs must be updated. This is done here because
        // some dialogs require buffer()->text.
        updateDialogs();
@@ -1192,11 +1213,9 @@ void GuiView::on_lastWorkAreaRemoved()
                return;
 
        // Reset and updates the dialogs.
-       d.toc_models_.reset(0);
-       updateDialog("document", "");
-       updateDialogs();
+       Q_EMIT bufferViewChanged();
 
-       resetWindowTitleAndIconText();
+       resetWindowTitle();
        updateStatusBar();
 
        if (lyxrc.open_buffers_in_tabs)
@@ -1274,19 +1293,10 @@ bool GuiView::event(QEvent * e)
                        cap::saveSelection(old_view->currentBufferView()->cursor());
                }
                guiApp->setCurrentView(this);
-               if (d.current_work_area_) {
-                       BufferView & bv = d.current_work_area_->bufferView();
-                       connectBufferView(bv);
-                       connectBuffer(bv.buffer());
-                       // The document structure, name and dialogs might have
-                       // changed in another view.
-                       structureChanged();
-                       // The document settings needs to be reinitialised.
-                       updateDialog("document", "");
-                       updateDialogs();
-               } else {
-                       resetWindowTitleAndIconText();
-               }
+               if (d.current_work_area_)
+                       on_currentWorkAreaChanged(d.current_work_area_);
+               else
+                       resetWindowTitle();
                setFocus();
                return QMainWindow::event(e);
        }
@@ -1312,10 +1322,9 @@ bool GuiView::event(QEvent * e)
        }
 }
 
-void GuiView::resetWindowTitleAndIconText()
+void GuiView::resetWindowTitle()
 {
        setWindowTitle(qt_("LyX"));
-       setWindowIconText(qt_("LyX"));
 }
 
 bool GuiView::focusNextPrevChild(bool /*next*/)
@@ -1344,7 +1353,7 @@ void GuiView::setBusy(bool busy)
                return;
        }
        QApplication::restoreOverrideCursor();
-       updateLayoutList();     
+       updateLayoutList();
 }
 
 
@@ -1358,18 +1367,18 @@ void GuiView::resetCommandExecute()
 double GuiView::pixelRatio() const
 {
 #if QT_VERSION >= 0x050000
-       return devicePixelRatio();
+       return qt_scale_factor * devicePixelRatio();
 #else
        return 1.0;
 #endif
 }
-       
-       
+
+
 GuiWorkArea * GuiView::workArea(int index)
 {
        if (TabWorkArea * twa = d.currentTabWorkArea())
                if (index < twa->count())
-                       return dynamic_cast<GuiWorkArea *>(twa->widget(index));
+                       return twa->workArea(index);
        return 0;
 }
 
@@ -1442,6 +1451,7 @@ void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
        if (!wa) {
                d.current_work_area_ = 0;
                d.setBackground();
+               Q_EMIT bufferViewChanged();
                return;
        }
 
@@ -1457,7 +1467,7 @@ void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
 
        theGuiApp()->setCurrentView(this);
        d.current_work_area_ = wa;
-       
+
        // We need to reset this now, because it will need to be
        // right if the tabWorkArea gets reset in the for loop. We
        // will change it back if we aren't in that case.
@@ -1466,14 +1476,14 @@ void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
 
        for (int i = 0; i != d.splitter_->count(); ++i) {
                if (d.tabWorkArea(i)->setCurrentWorkArea(wa)) {
-                       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea() 
+                       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea()
                                << ", Current main wa: " << currentMainWorkArea());
                        return;
                }
        }
-       
+
        d.current_main_work_area_ = old_cmwa;
-       
+
        LYXERR(Debug::DEBUG, "This is not a tabbed wa");
        on_currentWorkAreaChanged(wa);
        BufferView & bv = wa->bufferView();
@@ -1564,6 +1574,10 @@ void GuiView::updateToolbars()
                        context |= Toolbars::IPA;
                if (command_execute_)
                        context |= Toolbars::MINIBUFFER;
+               if (minibuffer_focus_) {
+                       context |= Toolbars::MINIBUFFER_FOCUS;
+                       minibuffer_focus_ = false;
+               }
 
                for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
                        it->second->update(context);
@@ -1573,11 +1587,11 @@ void GuiView::updateToolbars()
 }
 
 
-void GuiView::setBuffer(Buffer * newBuffer)
+void GuiView::setBuffer(Buffer * newBuffer, bool switch_to)
 {
        LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << endl);
        LASSERT(newBuffer, return);
-       
+
        GuiWorkArea * wa = workArea(*newBuffer);
        if (wa == 0) {
                setBusy(true);
@@ -1596,7 +1610,8 @@ void GuiView::setBuffer(Buffer * newBuffer)
        }
        connectBuffer(*newBuffer);
        connectBufferView(wa->bufferView());
-       setCurrentWorkArea(wa);
+       if (switch_to)
+               setCurrentWorkArea(wa);
 }
 
 
@@ -1664,6 +1679,12 @@ void GuiView::updateTocItem(string const & type, DocIterator const & dit)
 
 void GuiView::structureChanged()
 {
+       // This is called from the Buffer, which has no way to ensure that cursors
+       // in BufferView remain valid.
+       if (documentBufferView())
+               documentBufferView()->cursor().sanitize();
+       // FIXME: This is slightly expensive, though less than the tocBackend update
+       // (#9880). This also resets the view in the Toc Widget (#6675).
        d.toc_models_.reset(documentBufferView());
        // Navigator needs more than a simple update in this case. It needs to be
        // rebuilt.
@@ -1812,15 +1833,13 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                string format = to_utf8(cmd.argument());
                if (cmd.argument().empty())
                        format = doc_buffer->params().getDefaultOutputFormat();
-               enable = doc_buffer->params().isExportableFormat(format);
+               enable = doc_buffer->params().isExportable(format, true);
                break;
        }
 
        case LFUN_BUFFER_RELOAD:
                enable = doc_buffer && !doc_buffer->isUnnamed()
-                       && doc_buffer->fileName().exists()
-                       && (!doc_buffer->isClean()
-                          || doc_buffer->isExternallyModified(Buffer::timestamp_method));
+                       && doc_buffer->fileName().exists() && !doc_buffer->isClean();
                break;
 
        case LFUN_BUFFER_CHILD_OPEN:
@@ -1850,6 +1869,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
        }
 
+       case LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR:
+               enable = doc_buffer && doc_buffer->notifiesExternalModification();
+               break;
+
        case LFUN_BUFFER_WRITE_AS:
        case LFUN_BUFFER_EXPORT_AS:
                enable = doc_buffer != 0;
@@ -1890,6 +1913,27 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
        }
 
+       case LFUN_TOOLBAR_MOVABLE: {
+               string const name = cmd.getArg(0);
+               // use negation since locked == !movable
+               if (name == "*")
+                       // toolbar name * locks all toolbars
+                       flag.setOnOff(!toolbarsMovable_);
+               else if (GuiToolbar * t = toolbar(name))
+                       flag.setOnOff(!(t->isMovable()));
+               else {
+                       enable = false;
+                       docstring const msg =
+                               bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name));
+                       flag.message(msg);
+               }
+               break;
+       }
+
+       case LFUN_ICON_SIZE:
+               flag.setOnOff(d.iconSize(cmd.argument()) == iconSize());
+               break;
+
        case LFUN_DROP_LAYOUTS_CHOICE:
                enable = buf != 0;
                break;
@@ -1929,7 +1973,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                else if (name == "latexlog")
                        enable = FileName(doc_buffer->logName()).isReadableFile();
                else if (name == "spellchecker")
-                       enable = theSpellChecker() 
+                       enable = theSpellChecker()
                                && !doc_buffer->isReadonly()
                                && !doc_buffer->text().empty();
                else if (name == "vclog")
@@ -1987,12 +2031,35 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
 
        case LFUN_BUFFER_ZOOM_OUT:
-               enable = doc_buffer && lyxrc.zoom > 10;
+       case LFUN_BUFFER_ZOOM_IN: {
+               // only diff between these two is that the default for ZOOM_OUT
+               // is a neg. number
+               bool const neg_zoom =
+                       convert<int>(cmd.argument()) < 0 ||
+                       (cmd.action() == LFUN_BUFFER_ZOOM_OUT && cmd.argument().empty());
+               if (lyxrc.currentZoom <= zoom_min_ && neg_zoom) {
+                       docstring const msg =
+                               bformat(_("Zoom level cannot be less than %1$d%."), zoom_min_);
+                       flag.message(msg);
+                       enable = false;
+               } else
+                       enable = doc_buffer;
                break;
+       }
 
-       case LFUN_BUFFER_ZOOM_IN:
-               enable = doc_buffer != 0;
+       case LFUN_BUFFER_ZOOM: {
+               bool const less_than_min_zoom =
+                       !cmd.argument().empty() && convert<int>(cmd.argument()) < zoom_min_;
+               if (lyxrc.currentZoom <= zoom_min_ && less_than_min_zoom) {
+                       docstring const msg =
+                               bformat(_("Zoom level cannot be less than %1$d%."), zoom_min_);
+                       flag.message(msg);
+                       enable = false;
+               }
+               else
+                       enable = doc_buffer;
                break;
+       }
 
        case LFUN_BUFFER_MOVE_NEXT:
        case LFUN_BUFFER_MOVE_PREVIOUS:
@@ -2026,12 +2093,13 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                enable = doc_buffer && doc_buffer->lyxvc().checkOutEnabled();
                break;
        case LFUN_VC_LOCKING_TOGGLE:
-               enable = doc_buffer && !doc_buffer->isReadonly()
+               enable = doc_buffer && !doc_buffer->hasReadonlyFlag()
                        && doc_buffer->lyxvc().lockingToggleEnabled();
                flag.setOnOff(enable && doc_buffer->lyxvc().locking());
                break;
        case LFUN_VC_REVERT:
-               enable = doc_buffer && doc_buffer->lyxvc().inUse() && !doc_buffer->isReadonly();
+               enable = doc_buffer && doc_buffer->lyxvc().inUse()
+                       && !doc_buffer->hasReadonlyFlag();
                break;
        case LFUN_VC_UNDO_LAST:
                enable = doc_buffer && doc_buffer->lyxvc().undoLastEnabled();
@@ -2051,6 +2119,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
 
        case LFUN_SERVER_GOTO_FILE_ROW:
+       case LFUN_LYX_ACTIVATE:
                break;
        case LFUN_FORWARD_SEARCH:
                enable = !(lyxrc.forward_search_dvi.empty() && lyxrc.forward_search_pdf.empty());
@@ -2137,8 +2206,7 @@ void GuiView::openDocument(string const & fname)
        if (fname.empty()) {
                FileDialog dlg(qt_("Select document to open"));
                dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-               dlg.setButton2(qt_("Examples|#E#e"),
-                               toqstr(addPath(package().system_support().absFileName(), "examples")));
+               dlg.setButton2(qt_("Examples|#E#e"), toqstr(lyxrc.example_path));
 
                QStringList const filter(qt_("LyX Documents (*.lyx)"));
                FileDialog::Result result =
@@ -2215,7 +2283,7 @@ static bool import(GuiView * lv, FileName const & filename,
 
                        string const tofile =
                                support::changeExtension(filename.absFileName(),
-                               formats.extension(*it));
+                               theFormats().extension(*it));
                        if (!theConverters().convert(0, filename, FileName(tofile),
                                filename, format, *it, errorList))
                                return false;
@@ -2225,7 +2293,7 @@ static bool import(GuiView * lv, FileName const & filename,
                if (loader_format.empty()) {
                        frontend::Alert::error(_("Couldn't import file"),
                                         bformat(_("No information for importing the format %1$s."),
-                                        formats.prettyName(format)));
+                                        theFormats().prettyName(format)));
                        return false;
                }
        } else
@@ -2243,7 +2311,7 @@ static bool import(GuiView * lv, FileName const & filename,
                bool as_paragraphs = loader_format == "textparagraph";
                string filename2 = (loader_format == format) ? filename.absFileName()
                        : support::changeExtension(filename.absFileName(),
-                                         formats.extension(loader_format));
+                                         theFormats().extension(loader_format));
                lv->currentBufferView()->insertPlaintextFile(FileName(filename2),
                        as_paragraphs);
                guiApp->setCurrentView(lv);
@@ -2272,17 +2340,16 @@ void GuiView::importDocument(string const & argument)
                }
 
                docstring const text = bformat(_("Select %1$s file to import"),
-                       formats.prettyName(format));
+                       theFormats().prettyName(format));
 
                FileDialog dlg(toqstr(text));
                dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-               dlg.setButton2(qt_("Examples|#E#e"),
-                       toqstr(addPath(package().system_support().absFileName(), "examples")));
+               dlg.setButton2(qt_("Examples|#E#e"), toqstr(lyxrc.example_path));
 
-               docstring filter = formats.prettyName(format);
+               docstring filter = theFormats().prettyName(format);
                filter += " (*.{";
                // FIXME UNICODE
-               filter += from_utf8(formats.extensions(format));
+               filter += from_utf8(theFormats().extensions(format));
                filter += "})";
 
                FileDialog::Result result =
@@ -2410,9 +2477,7 @@ void GuiView::insertLyXFile(docstring const & fname)
                // FIXME UNICODE
                FileDialog dlg(qt_("Select LyX document to insert"));
                dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-               dlg.setButton2(qt_("Examples|#E#e"),
-                       toqstr(addPath(package().system_support().absFileName(),
-                       "examples")));
+               dlg.setButton2(qt_("Examples|#E#e"), toqstr(lyxrc.example_path));
 
                FileDialog::Result result = dlg.open(toqstr(initpath),
                                         QStringList(qt_("LyX Documents (*.lyx)")));
@@ -2564,15 +2629,6 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname, RenameKind kin
 }
 
 
-struct PrettyNameComparator
-{
-       bool operator()(Format const *first, Format const *second) const {
-               return compare_no_case(translateIfPossible(from_ascii(first->prettyname())),
-                                      translateIfPossible(from_ascii(second->prettyname()))) <= 0;
-       }
-};
-
-
 bool GuiView::exportBufferAs(Buffer & b, docstring const & iformat)
 {
        FileName fname = b.fileName();
@@ -2583,28 +2639,25 @@ bool GuiView::exportBufferAs(Buffer & b, docstring const & iformat)
        QStringList types;
        QString const anyformat = qt_("Guess from extension (*.*)");
        types << anyformat;
-       Formats::const_iterator it = formats.begin();
+
        vector<Format const *> export_formats;
-       for (; it != formats.end(); ++it)
-               if (it->documentFormat())
-                       export_formats.push_back(&(*it));
-       PrettyNameComparator cmp;
-       sort(export_formats.begin(), export_formats.end(), cmp);
-       vector<Format const *>::const_iterator fit = export_formats.begin();
+       for (Format const & f : theFormats())
+               if (f.documentFormat())
+                       export_formats.push_back(&f);
+       sort(export_formats.begin(), export_formats.end(), Format::formatSorter);
        map<QString, string> fmap;
        QString filter;
        string ext;
-       for (; fit != export_formats.end(); ++fit) {
-               docstring const loc_prettyname =
-                       translateIfPossible(from_utf8((*fit)->prettyname()));
+       for (Format const * f : export_formats) {
+               docstring const loc_prettyname = translateIfPossible(f->prettyname());
                QString const loc_filter = toqstr(bformat(from_ascii("%1$s (*.%2$s)"),
                                                     loc_prettyname,
-                                                    from_ascii((*fit)->extension())));
+                                                    from_ascii(f->extension())));
                types << loc_filter;
-               fmap[loc_filter] = (*fit)->name();
-               if (from_ascii((*fit)->name()) == iformat) {
+               fmap[loc_filter] = f->name();
+               if (from_ascii(f->name()) == iformat) {
                        filter = loc_filter;
-                       ext = (*fit)->extension();
+                       ext = f->extension();
                }
        }
        string ofname = fname.onlyFileName();
@@ -2621,7 +2674,7 @@ bool GuiView::exportBufferAs(Buffer & b, docstring const & iformat)
        string fmt_name;
        fname.set(fromqstr(result.second));
        if (filter == anyformat)
-               fmt_name = formats.getFormatFromExtension(fname.extension());
+               fmt_name = theFormats().getFormatFromExtension(fname.extension());
        else
                fmt_name = fmap[filter];
        LYXERR(Debug::FILES, "filter=" << fromqstr(filter)
@@ -2749,9 +2802,13 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa)
 bool GuiView::closeBuffer()
 {
        GuiWorkArea * wa = currentMainWorkArea();
+       // coverity complained about this
+       // it seems unnecessary, but perhaps is worth the check
+       LASSERT(wa, return false);
+
        setCurrentWorkArea(wa);
        Buffer & buf = wa->bufferView().buffer();
-       return wa && closeWorkArea(wa, !buf.parent());
+       return closeWorkArea(wa, !buf.parent());
 }
 
 
@@ -2760,7 +2817,7 @@ void GuiView::writeSession() const {
        for (int i = 0; i < d.splitter_->count(); ++i) {
                TabWorkArea * twa = d.tabWorkArea(i);
                for (int j = 0; j < twa->count(); ++j) {
-                       GuiWorkArea * wa = static_cast<GuiWorkArea *>(twa->widget(j));
+                       GuiWorkArea * wa = twa->workArea(j);
                        Buffer & buf = wa->bufferView().buffer();
                        theSession().lastOpened().add(buf.fileName(), wa == active_wa);
                }
@@ -2823,7 +2880,7 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer)
        Buffer & buf = wa->bufferView().buffer();
 
        if (GuiViewPrivate::busyBuffers.contains(&buf)) {
-               Alert::warning(_("Close document"), 
+               Alert::warning(_("Close document"),
                        _("Document could not be closed because it is being processed by LyX."));
                return false;
        }
@@ -2924,11 +2981,17 @@ bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
        setBuffer(&buf);
 
        docstring file;
+       bool exists;
        // FIXME: Unicode?
-       if (buf.isUnnamed())
+       if (buf.isUnnamed()) {
                file = from_utf8(buf.fileName().onlyFileName());
-       else
-               file = buf.fileName().displayName(30);
+               exists = false;
+       } else {
+               FileName filename = buf.fileName();
+               filename.refresh();
+               file = filename.displayName(30);
+               exists = filename.exists();
+       }
 
        // Bring this window to top before asking questions.
        raise();
@@ -2944,10 +3007,17 @@ bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
                if (ret == 1)
                        ++ret;
        } else {
-               docstring const text = bformat(_("The document %1$s has unsaved changes."
-                       "\n\nDo you want to save the document or discard the changes?"), file);
-               ret = Alert::prompt(_("Save changed document?"),
-                       text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
+               docstring const text = exists ?
+                       bformat(_("The document %1$s has unsaved changes."
+                                 "\n\nDo you want to save the document or "
+                                 "discard the changes?"), file) :
+                       bformat(_("The document %1$s has not been saved yet."
+                                 "\n\nDo you want to save the document or "
+                                 "discard it entirely?"), file);
+               docstring const title = exists ?
+                       _("Save changed document?") : _("Save document?");
+               ret = Alert::prompt(title, text, 0, 2,
+                                   _("&Save"), _("&Discard"), _("&Cancel"));
        }
 
        switch (ret) {
@@ -3005,7 +3075,7 @@ void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np, bool const move)
 {
        if (!documentBufferView())
                return;
-       
+
        if (TabWorkArea * twa = d.currentTabWorkArea()) {
                Buffer * const curbuf = &documentBufferView()->buffer();
                int nwa = twa->count();
@@ -3071,8 +3141,7 @@ void GuiView::checkExternallyModifiedBuffers()
        BufferList::iterator const bend = theBufferList().end();
        for (; bit != bend; ++bit) {
                Buffer * buf = *bit;
-               if (buf->fileName().exists()
-                       && buf->isExternallyModified(Buffer::checksum_method)) {
+               if (buf->fileName().exists() && buf->isChecksumModified()) {
                        docstring text = bformat(_("Document \n%1$s\n has been externally modified."
                                        " Reload now? Any local changes will be lost."),
                                        from_utf8(buf->absFileName()));
@@ -3106,7 +3175,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
        case LFUN_VC_COPY: {
                if (!buffer || !ensureBufferClean(buffer))
                        break;
-               if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+               if (buffer->lyxvc().inUse() && !buffer->hasReadonlyFlag()) {
                        if (buffer->lyxvc().isCheckInWithConfirmation()) {
                                // Some changes are not yet committed.
                                // We test here and not in getStatus(), since
@@ -3135,7 +3204,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
        case LFUN_VC_CHECK_IN:
                if (!buffer || !ensureBufferClean(buffer))
                        break;
-               if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+               if (buffer->lyxvc().inUse() && !buffer->hasReadonlyFlag()) {
                        string log;
                        LyXVC::CommandResult ret = buffer->lyxvc().checkIn(log);
                        dr.setMessage(log);
@@ -3159,7 +3228,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
 
        case LFUN_VC_LOCKING_TOGGLE:
                LASSERT(buffer, return);
-               if (!ensureBufferClean(buffer) || buffer->isReadonly())
+               if (!ensureBufferClean(buffer) || buffer->hasReadonlyFlag())
                        break;
                if (buffer->lyxvc().inUse()) {
                        string res = buffer->lyxvc().lockingToggle();
@@ -3239,7 +3308,6 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
                }
 
        case LFUN_VC_COMPARE: {
-
                if (cmd.argument().empty()) {
                        lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "comparehistory"));
                        break;
@@ -3247,6 +3315,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr)
 
                string rev1 = cmd.getArg(0);
                string f1, f2;
+               LATTEST(buffer)
 
                // f1
                if (!buffer->lyxvc().prepareFileRevision(rev1, f1))
@@ -3357,8 +3426,23 @@ bool GuiView::goToFileRow(string const & argument)
                return false;
        }
        setBuffer(buf);
-       documentBufferView()->setCursorFromRow(row);
-       return true;
+       bool success = documentBufferView()->setCursorFromRow(row);
+       if (!success) {
+               LYXERR(Debug::LATEX,
+                      "setCursorFromRow: invalid position for row " << row);
+               frontend::Alert::error(_("Inverse Search Failed"),
+                                      _("Invalid position requested by inverse search.\n"
+                                        "You may need to update the viewed document."));
+       }
+       return success;
+}
+
+
+void GuiView::toolBarPopup(const QPoint & /*pos*/)
+{
+       QMenu * menu = new QMenu;
+       menu = guiApp->menus().menu(toqstr("context-toolbars"), * this);
+       menu->exec(QCursor::pos());
 }
 
 
@@ -3438,15 +3522,14 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
 #else
        Buffer::ExportStatus status;
        if (syncFunc) {
-               // TODO check here if it breaks exporting with Qt < 4.4
                status = (used_buffer->*syncFunc)(format, true);
        } else if (previewFunc) {
-               status = (used_buffer->*previewFunc)(format); 
+               status = (used_buffer->*previewFunc)(format);
        } else
                return false;
        handleExportStatus(gv_, status, format);
        (void) asyncFunc;
-       return (status == Buffer::ExportSuccess 
+       return (status == Buffer::ExportSuccess
                        || status == Buffer::PreviewSuccess);
 #endif
 }
@@ -3521,22 +3604,30 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                case LFUN_BUFFER_EXPORT: {
                        if (!doc_buffer)
                                break;
-                       FileName target_dir = doc_buffer->fileName().onlyPath();
-                       string const dest = cmd.getArg(1);
-                       if (!dest.empty() && FileName::isAbsolute(dest))
-                               target_dir = FileName(support::onlyPath(dest));
                        // GCC only sees strfwd.h when building merged
                        if (::lyx::operator==(cmd.argument(), "custom")) {
                                dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"), dr);
                                break;
                        }
-                       if (!target_dir.isDirWritable()) {
-                               exportBufferAs(*doc_buffer, cmd.argument());
+
+                       string const dest = cmd.getArg(1);
+                       FileName target_dir;
+                       if (!dest.empty() && FileName::isAbsolute(dest))
+                               target_dir = FileName(support::onlyPath(dest));
+                       else
+                               target_dir = doc_buffer->fileName().onlyPath();
+
+                       string const format = (argument.empty() || argument == "default") ?
+                               doc_buffer->params().getDefaultOutputFormat() : argument;
+
+                       if ((dest.empty() && doc_buffer->isUnnamed())
+                           || !target_dir.isDirWritable()) {
+                               exportBufferAs(*doc_buffer, from_utf8(format));
                                break;
                        }
                        /* TODO/Review: Is it a problem to also export the children?
                                        See the update_unincluded flag */
-                       d.asyncBufferProcessing(argument,
+                       d.asyncBufferProcessing(format,
                                                doc_buffer,
                                                _("Exporting ..."),
                                                &GuiViewPrivate::exportAndDestroy,
@@ -3652,6 +3743,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 
                case LFUN_COMMAND_EXECUTE: {
                        command_execute_ = true;
+                       minibuffer_focus_ = true;
                        break;
                }
                case LFUN_DROP_LAYOUTS_CHOICE:
@@ -3674,14 +3766,14 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                dr.setMessage(_("Absolute filename expected."));
                                break;
                        }
-                       
+
                        FileName filename(fname);
                        if (fname.empty()) {
                                FileDialog dlg(qt_("Select file to insert"));
 
                                FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
                                        QStringList(qt_("All Files (*)")));
-                               
+
                                if (result.first == FileDialog::Later || result.second.isEmpty()) {
                                        dr.setMessage(_("Canceled."));
                                        break;
@@ -3704,11 +3796,21 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        if (!doc_buffer->isClean()) {
                                docstring const file =
                                        makeDisplayPath(doc_buffer->absFileName(), 20);
-                               docstring text = bformat(_("Any changes will be lost. "
-                                       "Are you sure you want to revert to the saved version "
-                                       "of the document %1$s?"), file);
-                               ret = Alert::prompt(_("Revert to saved document?"),
-                                       text, 1, 1, _("&Revert"), _("&Cancel"));
+                               if (doc_buffer->notifiesExternalModification()) {
+                                       docstring text = _("The current version will be lost. "
+                                           "Are you sure you want to load the version on disk "
+                                           "of the document %1$s?");
+                                       ret = Alert::prompt(_("Reload saved document?"),
+                                                           bformat(text, file), 1, 1,
+                                                           _("&Reload"), _("&Cancel"));
+                               } else {
+                                       docstring text = _("Any changes will be lost. "
+                                           "Are you sure you want to revert to the saved version "
+                                           "of the document %1$s?");
+                                       ret = Alert::prompt(_("Revert to saved document?"),
+                                                           bformat(text, file), 1, 1,
+                                                           _("&Revert"), _("&Cancel"));
+                               }
                        }
 
                        if (ret == 0) {
@@ -3747,6 +3849,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        break;
                }
 
+               case LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR:
+                       LASSERT(doc_buffer, break);
+                       doc_buffer->clearExternalModification();
+                       break;
+
                case LFUN_BUFFER_CLOSE:
                        closeBuffer();
                        break;
@@ -3762,6 +3869,40 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        break;
                }
 
+               case LFUN_TOOLBAR_MOVABLE: {
+                       string const name = cmd.getArg(0);
+                       if (name == "*") {
+                               // toggle (all) toolbars movablility
+                               toolbarsMovable_ = !toolbarsMovable_;
+                               for (ToolbarInfo const & ti : guiApp->toolbars()) {
+                                       GuiToolbar * tb = toolbar(ti.name);
+                                       if (tb && tb->isMovable() != toolbarsMovable_)
+                                               // toggle toolbar movablity if it does not fit lock
+                                               // (all) toolbars positions state silent = true, since
+                                               // status bar notifications are slow
+                                               tb->movable(true);
+                               }
+                               if (toolbarsMovable_)
+                                       dr.setMessage(_("Toolbars unlocked."));
+                               else
+                                       dr.setMessage(_("Toolbars locked."));
+                       } else if (GuiToolbar * t = toolbar(name)) {
+                               // toggle current toolbar movablity
+                               t->movable();
+                               // update lock (all) toolbars positions
+                               updateLockToolbars();
+                       }
+                       break;
+               }
+
+               case LFUN_ICON_SIZE: {
+                       QSize size = d.iconSize(cmd.argument());
+                       setIconSize(size);
+                       dr.setMessage(bformat(_("Icon size set to %1$dx%2$d."),
+                                               size.width(), size.height()));
+                       break;
+               }
+
                case LFUN_DIALOG_UPDATE: {
                        string const name = to_utf8(cmd.argument());
                        if (name == "prefs" || name == "document")
@@ -3807,6 +3948,8 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                if (!data.empty())
                                        showDialog("character", data);
                        } else if (name == "latexlog") {
+                               // getStatus checks that
+                               LATTEST(doc_buffer);
                                Buffer::LogType type;
                                string const logfile = doc_buffer->logName(&type);
                                switch (type) {
@@ -3820,6 +3963,8 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                data += Lexer::quoteString(logfile);
                                showDialog("log", data);
                        } else if (name == "vclog") {
+                               // getStatus checks that
+                               LATTEST(doc_buffer);
                                string const data = "vc " +
                                        Lexer::quoteString(doc_buffer->lyxvc().getLogFile());
                                showDialog("log", data);
@@ -3923,16 +4068,31 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 
                case LFUN_BUFFER_ZOOM_IN:
                case LFUN_BUFFER_ZOOM_OUT:
+               case LFUN_BUFFER_ZOOM: {
+                       // use a signed temp to avoid overflow
+                       int zoom = lyxrc.currentZoom;
                        if (cmd.argument().empty()) {
-                               if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
-                                       lyxrc.zoom += 20;
+                               if (cmd.action() == LFUN_BUFFER_ZOOM)
+                                       zoom = lyxrc.zoom;
+                               else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
+                                       zoom += 20;
                                else
-                                       lyxrc.zoom -= 20;
-                       } else
-                               lyxrc.zoom += convert<int>(cmd.argument());
+                                       zoom -= 20;
+                       } else {
+                               if (cmd.action() == LFUN_BUFFER_ZOOM)
+                                       zoom = convert<int>(cmd.argument());
+                               else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
+                                       zoom += convert<int>(cmd.argument());
+                               else
+                                       zoom -= convert<int>(cmd.argument());
+                       }
 
-                       if (lyxrc.zoom < 10)
-                               lyxrc.zoom = 10;
+                       if (zoom < static_cast<int>(zoom_min_))
+                               zoom = zoom_min_;
+
+                       lyxrc.currentZoom = zoom;
+
+                       dr.setMessage(bformat(_("Zoom level is now %1$d%"), lyxrc.currentZoom));
 
                        // The global QPixmapCache is used in GuiPainter to cache text
                        // painting so we must reset it.
@@ -3940,6 +4100,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        guiApp->fontLoader().update();
                        lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
                        break;
+               }
 
                case LFUN_VC_REGISTER:
                case LFUN_VC_RENAME:
@@ -3956,10 +4117,18 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        break;
 
                case LFUN_SERVER_GOTO_FILE_ROW:
-                       goToFileRow(to_utf8(cmd.argument()));
+                       if(goToFileRow(to_utf8(cmd.argument())))
+                               dr.screenUpdate(Update::Force | Update::FitCursor);
+                       break;
+
+               case LFUN_LYX_ACTIVATE:
+                       activateWindow();
                        break;
 
                case LFUN_FORWARD_SEARCH: {
+                       // it seems safe to assume we have a document buffer, since
+                       // getStatus wants one.
+                       LATTEST(doc_buffer);
                        Buffer const * doc_master = doc_buffer->masterBuffer();
                        FileName const path(doc_master->temppath());
                        string const texname = doc_master->isChild(doc_buffer)
@@ -3967,7 +4136,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                        doc_buffer->absFileName(),
                                                "tex")).mangledFileName()
                                : doc_buffer->latexName();
-                       string const fulltexname = 
+                       string const fulltexname =
                                support::makeAbsPath(texname, doc_master->temppath()).absFileName();
                        string const mastername =
                                removeExtension(doc_master->latexName());
@@ -4012,7 +4181,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 
                case LFUN_SPELLING_CONTINUOUSLY:
                        lyxrc.spellcheck_continuously = !lyxrc.spellcheck_continuously;
-                       dr.screenUpdate(Update::Force | Update::FitCursor);
+                       dr.screenUpdate(Update::Force);
                        break;
 
                default:
@@ -4032,7 +4201,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
        bv = currentBufferView();
 
        // Clear non-empty selections
-        // (e.g. from a "char-forward-select" followed by "char-backward-select")
+       // (e.g. from a "char-forward-select" followed by "char-backward-select")
        if (bv) {
                Cursor & cur = bv->cursor();
                if ((cur.selection() && cur.selBegin() == cur.selEnd())) {