]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
QDialogButtonBox for the remaining dialogs.
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index b325e4b2256a2e69eec1f1d809b168e87b46676b..d1991aa08b22bffde1aaf3e68d8cf74d29349fde 100644 (file)
@@ -157,6 +157,9 @@ public:
                if (!lyxrc.show_banner)
                        return;
                /// The text to be written on top of the pixmap
+               QString const htext = qt_("The Document\nProcessor[[welcome banner]]");
+               QString const htextsize = qt_("1.0[[possibly scale the welcome banner text size]]");
+               /// The text to be written on top of the pixmap
                QString const text = lyx_version ?
                        qt_("version ") + lyx_version : qt_("unknown version");
 #if QT_VERSION >= 0x050000
@@ -178,7 +181,14 @@ public:
                QPainter pain(&splash_);
                pain.setPen(QColor(0, 0, 0));
                qreal const fsize = fontSize();
-               QPointF const position = textPosition();
+               bool ok;
+               int hfsize = 20;
+               qreal locscale = htextsize.toFloat(&ok);
+               if (!ok)
+                       locscale = 1.0;
+               QPointF const position = textPosition(false);
+               QPointF const hposition = textPosition(true);
+               QRectF const hrect(hposition, splashSize());
                LYXERR(Debug::GUI,
                        "widget pixel ratio: " << pixelRatio() <<
                        " splash pixel ratio: " << splashPixelRatio() <<
@@ -190,6 +200,36 @@ public:
                font.setPointSizeF(fsize);
                pain.setFont(font);
                pain.drawText(position, text);
+               // The font used to display the version info
+               font.setStyleHint(QFont::SansSerif);
+               font.setWeight(QFont::Normal);
+               font.setPointSizeF(hfsize);
+               // Check how long the logo gets with the current font
+               // and adapt if the font is running wider than what
+               // we assume
+               QFontMetrics fm(font);
+               // Split the title into lines to measure the longest line
+               // in the current l7n.
+               QStringList titlesegs = htext.split('\n');
+               int wline = 0;
+               int hline = fm.height();
+               QStringList::const_iterator sit;
+               for (sit = titlesegs.constBegin(); sit != titlesegs.constEnd(); ++sit) {
+                       if (fm.width(*sit) > wline)
+                               wline = fm.width(*sit);
+               }
+               // The longest line in the reference font (for English)
+               // is 180. Calculate scale factor from that.
+               double const wscale = wline > 0 ? (180.0 / wline) : 1;
+               // Now do the same for the height (necessary for condensed fonts)
+               double const hscale = (34.0 / hline);
+               // take the lower of the two scale factors.
+               double const scale = min(wscale, hscale);
+               // Now rescale. Also consider l7n's offset factor.
+               font.setPointSizeF(hfsize * scale * locscale);
+
+               pain.setFont(font);
+               pain.drawText(hrect, Qt::AlignLeft, htext);
                setFocusPolicy(Qt::StrongFocus);
        }
 
@@ -237,8 +277,9 @@ private:
                return toqstr(lyxrc.font_sizes[FONT_SIZE_NORMAL]).toDouble();
        }
 
-       QPointF textPosition() const {
-               return QPointF(width_/2 - 18, height_/2 + 45);
+       QPointF textPosition(bool const heading) const {
+               return heading ? QPointF(width_/2 - 18, height_/2 - 45)
+                              : QPointF(width_/2 - 18, height_/2 + 45);
        }
 
        QSize splashSize() const {
@@ -484,13 +525,17 @@ public:
        string processing_format;
 
        static QSet<Buffer const *> busyBuffers;
-       static Buffer::ExportStatus previewAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
-       static Buffer::ExportStatus exportAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
-       static Buffer::ExportStatus compileAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
+       static Buffer::ExportStatus previewAndDestroy(Buffer const * orig,
+                       Buffer * buffer, string const & format);
+       static Buffer::ExportStatus exportAndDestroy(Buffer const * orig,
+                       Buffer * buffer, string const & format);
+       static Buffer::ExportStatus compileAndDestroy(Buffer const * orig,
+                       Buffer * buffer, string const & format);
        static docstring autosaveAndDestroy(Buffer const * orig, Buffer * buffer);
 
        template<class T>
-       static Buffer::ExportStatus runAndDestroy(const T& func, Buffer const * orig, Buffer * buffer, string const & format);
+       static Buffer::ExportStatus runAndDestroy(const T& func,
+                       Buffer const * orig, Buffer * buffer, string const & format);
 
        // TODO syncFunc/previewFunc: use bind
        bool asyncBufferProcessing(string const & argument,
@@ -498,7 +543,8 @@ public:
                                   docstring const & msg,
                                   Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
                                   Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
-                                  Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const);
+                                  Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const,
+                                  bool allow_async);
 
        QVector<GuiWorkArea*> guiWorkAreas();
 };
@@ -508,7 +554,8 @@ QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
 
 GuiView::GuiView(int id)
        : d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
-         command_execute_(false), minibuffer_focus_(false), devel_mode_(false)
+         command_execute_(false), minibuffer_focus_(false), toolbarsMovable_(true),
+         devel_mode_(false)
 {
        connect(this, SIGNAL(bufferViewChanged()),
                this, SLOT(onBufferViewChanged()));
@@ -701,6 +748,9 @@ static void handleExportStatus(GuiView * view, Buffer::ExportStatus status,
        case Buffer::PreviewError:
                msg = bformat(_("Error while previewing format: %1$s"), fmt);
                break;
+       case Buffer::ExportKilled:
+               msg = bformat(_("Conversion cancelled while previewing format: %1$s"), fmt);
+               break;
        }
        view->message(msg);
 }
@@ -725,7 +775,19 @@ void GuiView::processingThreadFinished()
                errors("Export");
                return;
        }
-       errors(d.last_export_format);
+
+       bool const error = (status != Buffer::ExportSuccess &&
+                           status != Buffer::PreviewSuccess &&
+                           status != Buffer::ExportCancel);
+       if (error && bv) {
+               ErrorList & el = bv->buffer().errorList(d.last_export_format);
+               // at this point, we do not know if buffer-view or
+               // master-buffer-view was called. If there was an export error,
+               // and the current buffer's error log is empty, we guess that
+               // it must be master-buffer-view that was called so we set
+               // from_master=true.
+               errors(d.last_export_format, el.empty());
+       }
 }
 
 
@@ -741,7 +803,7 @@ void GuiView::autoSaveThreadFinished()
 void GuiView::saveLayout() const
 {
        QSettings settings;
-       settings.setValue("zoom", lyxrc.currentZoom);
+       settings.setValue("zoom_ratio", zoom_ratio_);
        settings.setValue("devel_mode", devel_mode_);
        settings.beginGroup("views");
        settings.beginGroup(QString::number(id_));
@@ -758,21 +820,28 @@ void GuiView::saveLayout() const
 
 void GuiView::saveUISettings() const
 {
+       QSettings settings;
+
        // Save the toolbar private states
        ToolbarMap::iterator end = d.toolbars_.end();
        for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
-               it->second->saveSession();
+               it->second->saveSession(settings);
        // Now take care of all other dialogs
        map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
        for (; it!= d.dialogs_.end(); ++it)
-               it->second->saveSession();
+               it->second->saveSession(settings);
 }
 
 
 bool GuiView::restoreLayout()
 {
        QSettings settings;
-       lyxrc.currentZoom = settings.value("zoom", lyxrc.zoom).toInt();
+       zoom_ratio_ = settings.value("zoom_ratio", 1.0).toDouble();
+       // Actual zoom value: default zoom + fractional offset
+       int zoom = lyxrc.defaultZoom * zoom_ratio_;
+       if (zoom < static_cast<int>(zoom_min_))
+               zoom = zoom_min_;
+       lyxrc.currentZoom = zoom;
        devel_mode_ = settings.value("devel_mode", devel_mode_).toBool();
        settings.beginGroup("views");
        settings.beginGroup(QString::number(id_));
@@ -1680,27 +1749,17 @@ void GuiView::errors(string const & error_type, bool from_master)
        if (!bv)
                return;
 
-#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);
-       if (el.empty()) {
-           el = bv->buffer().masterBuffer()->errorList(error_type);
-           from_master = true;
-       }
-#else
        ErrorList const & el = from_master ?
                bv->buffer().masterBuffer()->errorList(error_type) :
                bv->buffer().errorList(error_type);
-#endif
 
        if (el.empty())
                return;
 
-       string data = error_type;
+       string err = error_type;
        if (from_master)
-               data = "from_master|" + error_type;
-       showDialog("errorlist", data);
+               err = "from_master|" + error_type;
+       showDialog("errorlist", err);
 }
 
 
@@ -1725,7 +1784,7 @@ void GuiView::structureChanged()
 }
 
 
-void GuiView::updateDialog(string const & name, string const & data)
+void GuiView::updateDialog(string const & name, string const & sdata)
 {
        if (!isDialogVisible(name))
                return;
@@ -1736,7 +1795,7 @@ void GuiView::updateDialog(string const & name, string const & data)
 
        Dialog * const dialog = it->second.get();
        if (dialog->isVisibleView())
-               dialog->initialiseParams(data);
+               dialog->initialiseParams(sdata);
 }
 
 
@@ -1849,6 +1908,15 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        case LFUN_BUFFER_IMPORT:
                break;
 
+       case LFUN_MASTER_BUFFER_EXPORT:
+               enable = doc_buffer
+                       && (doc_buffer->parent() != 0
+                           || doc_buffer->hasChildren())
+                       && !d.processing_thread_watcher_.isRunning()
+                       // this launches a dialog, which would be in the wrong Buffer
+                       && !(::lyx::operator==(cmd.argument(), "custom"));
+               break;
+
        case LFUN_MASTER_BUFFER_UPDATE:
        case LFUN_MASTER_BUFFER_VIEW:
                enable = doc_buffer
@@ -1872,7 +1940,8 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 
        case LFUN_BUFFER_RELOAD:
                enable = doc_buffer && !doc_buffer->isUnnamed()
-                       && doc_buffer->fileName().exists() && !doc_buffer->isClean();
+                       && doc_buffer->fileName().exists()
+                       && (!doc_buffer->isClean() || doc_buffer->notifiesExternalModification());
                break;
 
        case LFUN_BUFFER_CHILD_OPEN:
@@ -1906,11 +1975,29 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                enable = doc_buffer && doc_buffer->notifiesExternalModification();
                break;
 
-       case LFUN_BUFFER_WRITE_AS:
+       case LFUN_BUFFER_EXPORT: {
+               if (!doc_buffer || d.processing_thread_watcher_.isRunning()) {
+                       enable = false;
+                       break;
+               }
+               return doc_buffer->getStatus(cmd, flag);
+               break;
+       }
+
        case LFUN_BUFFER_EXPORT_AS:
+               if (!doc_buffer || d.processing_thread_watcher_.isRunning()) {
+                       enable = false;
+                       break;
+               }
+               // fall through
+       case LFUN_BUFFER_WRITE_AS:
                enable = doc_buffer != 0;
                break;
 
+       case LFUN_EXPORT_CANCEL:
+               enable = d.processing_thread_watcher_.isRunning();
+               break;
+
        case LFUN_BUFFER_CLOSE:
        case LFUN_VIEW_CLOSE:
                enable = doc_buffer != 0;
@@ -1920,6 +2007,23 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                enable = theBufferList().last() != theBufferList().first();
                break;
 
+       case LFUN_BUFFER_CHKTEX: {
+               // hide if we have no checktex command
+               if (lyxrc.chktex_command.empty()) {
+                       flag.setUnknown(true);
+                       enable = false;
+                       break;
+               }
+               if (!doc_buffer || !doc_buffer->params().isLatex()
+                   || d.processing_thread_watcher_.isRunning()) {
+                       // grey out, don't hide
+                       enable = false;
+                       break;
+               }
+               enable = true;
+               break;
+       }
+
        case LFUN_VIEW_SPLIT:
                if (cmd.getArg(0) == "vertical")
                        enable = doc_buffer && (d.splitter_->count() == 1 ||
@@ -2186,8 +2290,8 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 static FileName selectTemplateFile()
 {
        FileDialog dlg(qt_("Select template file"));
-       dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-       dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
+       dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
+       dlg.setButton2(qt_("&Templates"), toqstr(lyxrc.template_path));
 
        FileDialog::Result result = dlg.open(toqstr(lyxrc.template_path),
                                 QStringList(qt_("LyX Documents (*.lyx)")));
@@ -2221,8 +2325,10 @@ Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
        setBuffer(newBuffer);
        newBuffer->errors("Parse");
 
-       if (tolastfiles)
+       if (tolastfiles) {
                theSession().lastFiles().add(filename);
+               theSession().writeFile();
+  }
 
        return newBuffer;
 }
@@ -2243,8 +2349,8 @@ 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(lyxrc.example_path));
+               dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
+               dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
 
                QStringList const filter(qt_("LyX Documents (*.lyx)"));
                FileDialog::Result result =
@@ -2322,8 +2428,8 @@ static bool import(GuiView * lv, FileName const & filename,
                        string const tofile =
                                support::changeExtension(filename.absFileName(),
                                theFormats().extension(*it));
-                       if (!theConverters().convert(0, filename, FileName(tofile),
-                               filename, format, *it, errorList))
+                       if (theConverters().convert(0, filename, FileName(tofile),
+                               filename, format, *it, errorList) != Converters::SUCCESS)
                                return false;
                        loader_format = *it;
                        break;
@@ -2381,8 +2487,8 @@ void GuiView::importDocument(string const & argument)
                        theFormats().prettyName(format));
 
                FileDialog dlg(toqstr(text));
-               dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-               dlg.setButton2(qt_("Examples|#E#e"), toqstr(lyxrc.example_path));
+               dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
+               dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
 
                docstring filter = theFormats().prettyName(format);
                filter += " (*.{";
@@ -2514,8 +2620,8 @@ 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(lyxrc.example_path));
+               dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
+               dlg.setButton2(qt_("&Examples"), toqstr(lyxrc.example_path));
 
                FileDialog::Result result = dlg.open(toqstr(initpath),
                                         QStringList(qt_("LyX Documents (*.lyx)")));
@@ -2554,8 +2660,8 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname, RenameKind kin
                // No argument? Ask user through dialog.
                // FIXME UNICODE
                FileDialog dlg(qt_("Choose a filename to save document as"));
-               dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
-               dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
+               dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
+               dlg.setButton2(qt_("&Templates"), toqstr(lyxrc.template_path));
 
                if (!isLyXFileName(fname.absFileName()))
                        fname.changeExtension(".lyx");
@@ -2672,7 +2778,7 @@ bool GuiView::exportBufferAs(Buffer & b, docstring const & iformat)
        FileName fname = b.fileName();
 
        FileDialog dlg(qt_("Choose a filename to export the document as"));
-       dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
+       dlg.setButton1(qt_("D&ocuments"), toqstr(lyxrc.document_path));
 
        QStringList types;
        QString const anyformat = qt_("Guess from extension (*.*)");
@@ -2761,6 +2867,7 @@ bool GuiView::saveBuffer(Buffer & b, FileName const & fn)
        bool const success = (fn.empty() ? b.save() : b.saveAs(fn));
        if (success) {
                theSession().lastFiles().add(b.fileName());
+               theSession().writeFile();
                return true;
        }
 
@@ -3168,6 +3275,7 @@ static bool ensureBufferClean(Buffer * buffer)
 
 bool GuiView::reloadBuffer(Buffer & buf)
 {
+       currentBufferView()->cursor().reset();
        Buffer::ReadStatus status = buf.reload();
        return status == Buffer::ReadSuccess;
 }
@@ -3409,7 +3517,7 @@ void GuiView::openChildDocument(string const & fname)
 bool GuiView::goToFileRow(string const & argument)
 {
        string file_name;
-       int row;
+       int row = -1;
        size_t i = argument.find_last_of(' ');
        if (i != string::npos) {
                file_name = os::internal_path(trim(argument.substr(0, i)));
@@ -3484,7 +3592,8 @@ void GuiView::toolBarPopup(const QPoint & /*pos*/)
 
 
 template<class T>
-Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffer const * orig, Buffer * clone, string const & format)
+Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func,
+               Buffer const * orig, Buffer * clone, string const & format)
 {
        Buffer::ExportStatus const status = func(format);
 
@@ -3497,23 +3606,29 @@ Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffe
 }
 
 
-Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
+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;
+       Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const =
+                       &Buffer::doExport;
        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 GuiView::GuiViewPrivate::exportAndDestroy(
+               Buffer const * orig, Buffer * clone, string const & format)
 {
-       Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const = &Buffer::doExport;
+       Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const =
+                       &Buffer::doExport;
        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 GuiView::GuiViewPrivate::previewAndDestroy(
+               Buffer const * orig, Buffer * clone, string const & format)
 {
-       Buffer::ExportStatus (Buffer::* mem_func)(std::string const &) const = &Buffer::preview;
+       Buffer::ExportStatus (Buffer::* mem_func)(std::string const &) const =
+                       &Buffer::preview;
        return runAndDestroy(lyx::bind(mem_func, clone, _1), orig, clone, format);
 }
 
@@ -3524,7 +3639,8 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
                           docstring const & msg,
                           Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
                           Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
-                          Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const)
+                          Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const,
+                          bool allow_async)
 {
        if (!used_buffer)
                return false;
@@ -3538,25 +3654,40 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
                gv_->message(msg);
        }
 #if EXPORT_in_THREAD
-       GuiViewPrivate::busyBuffers.insert(used_buffer);
-       Buffer * cloned_buffer = used_buffer->cloneFromMaster();
-       if (!cloned_buffer) {
-               Alert::error(_("Export Error"),
-                            _("Error cloning the Buffer."));
-               return false;
+       if (allow_async) {
+               GuiViewPrivate::busyBuffers.insert(used_buffer);
+               Buffer * cloned_buffer = used_buffer->cloneWithChildren();
+               if (!cloned_buffer) {
+                       Alert::error(_("Export Error"),
+                                    _("Error cloning the Buffer."));
+                       return false;
+               }
+               QFuture<Buffer::ExportStatus> f = QtConcurrent::run(
+                                       asyncFunc,
+                                       used_buffer,
+                                       cloned_buffer,
+                                       format);
+               setPreviewFuture(f);
+               last_export_format = used_buffer->params().bufferFormat();
+               (void) syncFunc;
+               (void) previewFunc;
+               // We are asynchronous, so we don't know here anything about the success
+               return true;
+       } else {
+               Buffer::ExportStatus status;
+               if (syncFunc) {
+                       status = (used_buffer->*syncFunc)(format, false);
+               } else if (previewFunc) {
+                       status = (used_buffer->*previewFunc)(format);
+               } else
+                       return false;
+               handleExportStatus(gv_, status, format);
+               (void) asyncFunc;
+               return (status == Buffer::ExportSuccess
+                               || status == Buffer::PreviewSuccess);
        }
-       QFuture<Buffer::ExportStatus> f = QtConcurrent::run(
-                               asyncFunc,
-                               used_buffer,
-                               cloned_buffer,
-                               format);
-       setPreviewFuture(f);
-       last_export_format = used_buffer->params().bufferFormat();
-       (void) syncFunc;
-       (void) previewFunc;
-       // We are asynchronous, so we don't know here anything about the success
-       return true;
 #else
+       (void) allow_async;
        Buffer::ExportStatus status;
        if (syncFunc) {
                status = (used_buffer->*syncFunc)(format, true);
@@ -3638,11 +3769,19 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        importDocument(to_utf8(cmd.argument()));
                        break;
 
+               case LFUN_MASTER_BUFFER_EXPORT:
+                       if (doc_buffer)
+                               doc_buffer = const_cast<Buffer *>(doc_buffer->masterBuffer());
+                       // fall through
                case LFUN_BUFFER_EXPORT: {
                        if (!doc_buffer)
                                break;
                        // GCC only sees strfwd.h when building merged
                        if (::lyx::operator==(cmd.argument(), "custom")) {
+                               // LFUN_MASTER_BUFFER_EXPORT is not enabled for this case,
+                               // so the following test should not be needed.
+                               // In principle, we could try to switch to such a view...
+                               // if (cmd.action() == LFUN_BUFFER_EXPORT)
                                dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"), dr);
                                break;
                        }
@@ -3669,7 +3808,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                _("Exporting ..."),
                                                &GuiViewPrivate::exportAndDestroy,
                                                &Buffer::doExport,
-                                               0);
+                                               0, cmd.allowAsync());
                        // TODO Inform user about success
                        break;
                }
@@ -3689,7 +3828,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                _("Exporting ..."),
                                                &GuiViewPrivate::compileAndDestroy,
                                                &Buffer::doExport,
-                                               0);
+                                               0, cmd.allowAsync());
                        break;
                }
                case LFUN_BUFFER_VIEW: {
@@ -3698,7 +3837,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                _("Previewing ..."),
                                                &GuiViewPrivate::previewAndDestroy,
                                                0,
-                                               &Buffer::preview);
+                                               &Buffer::preview, cmd.allowAsync());
                        break;
                }
                case LFUN_MASTER_BUFFER_UPDATE: {
@@ -3707,7 +3846,7 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                docstring(),
                                                &GuiViewPrivate::compileAndDestroy,
                                                &Buffer::doExport,
-                                               0);
+                                               0, cmd.allowAsync());
                        break;
                }
                case LFUN_MASTER_BUFFER_VIEW: {
@@ -3715,7 +3854,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                                                (doc_buffer ? doc_buffer->masterBuffer() : 0),
                                                docstring(),
                                                &GuiViewPrivate::previewAndDestroy,
-                                               0, &Buffer::preview);
+                                               0, &Buffer::preview, cmd.allowAsync());
+                       break;
+               }
+               case LFUN_EXPORT_CANCEL: {
+                       Systemcall::killscript();
                        break;
                }
                case LFUN_BUFFER_SWITCH: {
@@ -3778,6 +3921,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                        gotoNextOrPreviousBuffer(PREVBUFFER, true);
                        break;
 
+               case LFUN_BUFFER_CHKTEX:
+                       LASSERT(doc_buffer, break);
+                       doc_buffer->runChktex();
+                       break;
+
                case LFUN_COMMAND_EXECUTE: {
                        command_execute_ = true;
                        minibuffer_focus_ = true;
@@ -3829,8 +3977,11 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
                case LFUN_BUFFER_RELOAD: {
                        LASSERT(doc_buffer, break);
 
+                       // drop changes?
+                       bool drop = (cmd.argument() == "dump");
+
                        int ret = 0;
-                       if (!doc_buffer->isClean()) {
+                       if (!drop && !doc_buffer->isClean()) {
                                docstring const file =
                                        makeDisplayPath(doc_buffer->absFileName(), 20);
                                if (doc_buffer->notifiesExternalModification()) {
@@ -3986,43 +4137,39 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 
                case LFUN_DIALOG_SHOW: {
                        string const name = cmd.getArg(0);
-                       string data = trim(to_utf8(cmd.argument()).substr(name.size()));
+                       string sdata = trim(to_utf8(cmd.argument()).substr(name.size()));
 
-                       if (name == "character") {
-                               data = freefont2string();
-                               if (!data.empty())
-                                       showDialog("character", data);
-                       } else if (name == "latexlog") {
-                               // getStatus checks that
+                       if (name == "latexlog") {
+                               // gettatus checks that
                                LATTEST(doc_buffer);
                                Buffer::LogType type;
                                string const logfile = doc_buffer->logName(&type);
                                switch (type) {
                                case Buffer::latexlog:
-                                       data = "latex ";
+                                       sdata = "latex ";
                                        break;
                                case Buffer::buildlog:
-                                       data = "literate ";
+                                       sdata = "literate ";
                                        break;
                                }
-                               data += Lexer::quoteString(logfile);
-                               showDialog("log", data);
+                               sdata += Lexer::quoteString(logfile);
+                               showDialog("log", sdata);
                        } else if (name == "vclog") {
                                // getStatus checks that
                                LATTEST(doc_buffer);
-                               string const data = "vc " +
+                               string const sdata2 = "vc " +
                                        Lexer::quoteString(doc_buffer->lyxvc().getLogFile());
-                               showDialog("log", data);
+                               showDialog("log", sdata2);
                        } else if (name == "symbols") {
-                               data = bv->cursor().getEncoding()->name();
-                               if (!data.empty())
-                                       showDialog("symbols", data);
+                               sdata = bv->cursor().getEncoding()->name();
+                               if (!sdata.empty())
+                                       showDialog("symbols", sdata);
                        // bug 5274
                        } else if (name == "prefs" && isFullScreen()) {
                                lfunUiToggle("fullscreen");
-                               showDialog("prefs", data);
+                               showDialog("prefs", sdata);
                        } else
-                               showDialog(name, data);
+                               showDialog(name, sdata);
                        break;
                }
 
@@ -4114,36 +4261,37 @@ 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)
-                                       zoom = lyxrc.zoom;
+                                       zoom_ratio_ = 1.0;
                                else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
-                                       zoom += 20;
+                                       zoom_ratio_ += 0.1;
                                else
-                                       zoom -= 20;
+                                       zoom_ratio_ -= 0.1;
                        } else {
                                if (cmd.action() == LFUN_BUFFER_ZOOM)
-                                       zoom = convert<int>(cmd.argument());
+                                       zoom_ratio_ = convert<int>(cmd.argument()) / double(lyxrc.defaultZoom);
                                else if (cmd.action() == LFUN_BUFFER_ZOOM_IN)
-                                       zoom += convert<int>(cmd.argument());
+                                       zoom_ratio_ += convert<int>(cmd.argument()) / 100.0;
                                else
-                                       zoom -= convert<int>(cmd.argument());
+                                       zoom_ratio_ -= convert<int>(cmd.argument()) / 100.0;
                        }
 
+                       // Actual zoom value: default zoom + fractional extra value
+                       int zoom = lyxrc.defaultZoom * zoom_ratio_;
                        if (zoom < static_cast<int>(zoom_min_))
                                zoom = zoom_min_;
 
                        lyxrc.currentZoom = zoom;
 
-                       dr.setMessage(bformat(_("Zoom level is now %1$d%"), lyxrc.currentZoom));
+                       dr.setMessage(bformat(_("Zoom level is now %1$d% (default value: %2$d%)"),
+                                             lyxrc.currentZoom, lyxrc.defaultZoom));
 
                        // The global QPixmapCache is used in GuiPainter to cache text
                        // painting so we must reset it.
                        QPixmapCache::clear();
                        guiApp->fontLoader().update();
-                       lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
+                       dr.screenUpdate(Update::Force | Update::FitCursor);
                        break;
                }
 
@@ -4339,19 +4487,19 @@ Buffer const * GuiView::updateInset(Inset const * inset)
                        continue;
                Buffer const * buffer = &(wa->bufferView().buffer());
                if (inset_buffer == buffer)
-                       wa->scheduleRedraw();
+                       wa->scheduleRedraw(true);
        }
        return inset_buffer;
 }
 
 
-void GuiView::restartCursor()
+void GuiView::restartCaret()
 {
        /* When we move around, or type, it's nice to be able to see
-        * the cursor immediately after the keypress.
+        * the caret immediately after the keypress.
         */
        if (d.current_work_area_)
-               d.current_work_area_->startBlinkingCursor();
+               d.current_work_area_->startBlinkingCaret();
 
        // Take this occasion to update the other GUI elements.
        updateDialogs();
@@ -4420,7 +4568,7 @@ void GuiView::resetDialogs()
        // Now update controls with current buffer.
        guiApp->setCurrentView(this);
        restoreLayout();
-       restartCursor();
+       restartCaret();
 }
 
 
@@ -4447,10 +4595,10 @@ Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
 }
 
 
-void GuiView::showDialog(string const & name, string const & data,
+void GuiView::showDialog(string const & name, string const & sdata,
        Inset * inset)
 {
-       triggerShowDialog(toqstr(name), toqstr(data), inset);
+       triggerShowDialog(toqstr(name), toqstr(sdata), inset);
 }
 
 
@@ -4461,14 +4609,14 @@ void GuiView::doShowDialog(QString const & qname, QString const & qdata,
                return;
 
        const string name = fromqstr(qname);
-       const string data = fromqstr(qdata);
+       const string sdata = fromqstr(qdata);
 
        d.in_show_ = true;
        try {
                Dialog * dialog = findOrBuild(name, false);
                if (dialog) {
                        bool const visible = dialog->isVisibleView();
-                       dialog->showData(data);
+                       dialog->showData(sdata);
                        if (inset && currentBufferView())
                                currentBufferView()->editInset(name, inset);
                        // We only set the focus to the new dialog if it was not yet
@@ -4691,7 +4839,6 @@ SEMenu::SEMenu(QWidget * parent)
                parent, SLOT(disableShellEscape()));
 }
 
-
 } // namespace frontend
 } // namespace lyx