]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
Let the tag affect other sides too
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index 7518834ce78db04a6f750bac66b9e3041ade05a0..93099faaf7d5420424ac05cf614c589f32d9cfd9 100644 (file)
 #include "GuiApplication.h"
 #include "GuiCommandBuffer.h"
 #include "GuiCompleter.h"
-#include "GuiWorkArea.h"
 #include "GuiKeySymbol.h"
 #include "GuiToc.h"
 #include "GuiToolbar.h"
+#include "GuiWorkArea.h"
 #include "LayoutBox.h"
 #include "Menus.h"
 #include "TocModel.h"
@@ -49,6 +49,7 @@
 #include "Intl.h"
 #include "Layout.h"
 #include "Lexer.h"
+#include "LyXAction.h"
 #include "LyXFunc.h"
 #include "LyX.h"
 #include "LyXRC.h"
@@ -66,6 +67,7 @@
 #include "support/FileName.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
+#include "support/filetools.h"
 #include "support/ForkedCalls.h"
 #include "support/lassert.h"
 #include "support/lstrings.h"
@@ -74,6 +76,8 @@
 #include "support/Path.h"
 #include "support/Systemcall.h"
 #include "support/Timeout.h"
+#include "support/ProgressInterface.h"
+#include "GuiProgress.h"
 
 #include <QAction>
 #include <QApplication>
 #include <QSplitter>
 #include <QStackedWidget>
 #include <QStatusBar>
+#include <QTime>
 #include <QTimer>
 #include <QToolBar>
 #include <QUrl>
 #include <QScrollBar>
 
+#define EXPORT_in_THREAD 1
+
+
+// QtConcurrent was introduced in Qt 4.4
+#if (QT_VERSION >= 0x040400)
+#include <QFuture>
+#include <QFutureWatcher>
+#include <QtConcurrentRun>
+#endif
+
 #include <boost/bind.hpp>
 
+#include <sstream>
+
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
@@ -137,6 +154,7 @@ public:
                font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
                pain.setFont(font);
                pain.drawText(260, 15, text);
+               setFocusPolicy(Qt::StrongFocus);
        }
 
        void paintEvent(QPaintEvent *)
@@ -147,13 +165,25 @@ public:
                pain.drawPixmap(x, y, splash_);
        }
 
+       void keyPressEvent(QKeyEvent * ev)
+       {
+               KeySymbol sym;
+               setKeySymbol(&sym, ev);
+               if (sym.isOK()) {
+                       guiApp->processKeySym(sym, q_key_state(ev->modifiers()));
+                       ev->accept();
+               } else {
+                       ev->ignore();
+               }
+       }
+
 private:
        QPixmap splash_;
 };
 
 
 /// Toolbar store providing access to individual toolbars by name.
-typedef std::map<std::string, GuiToolbar *> ToolbarMap;
+typedef map<string, GuiToolbar *> ToolbarMap;
 
 typedef boost::shared_ptr<Dialog> DialogPtr;
 
@@ -162,8 +192,8 @@ typedef boost::shared_ptr<Dialog> DialogPtr;
 
 struct GuiView::GuiViewPrivate
 {
-       GuiViewPrivate()
-               : current_work_area_(0), current_main_work_area_(0),
+       GuiViewPrivate(GuiView * gv)
+               : gv_(gv), current_work_area_(0), current_main_work_area_(0),
                layout_(0), autosave_timeout_(5000),
                in_show_(false)
        {
@@ -178,6 +208,7 @@ struct GuiView::GuiViewPrivate
                stack_widget_->addWidget(bg_widget_);
                stack_widget_->addWidget(splitter_);
                setBackground();
+               progress_ = new GuiProgress(gv);
        }
 
        ~GuiViewPrivate()
@@ -185,6 +216,7 @@ struct GuiView::GuiViewPrivate
                delete splitter_;
                delete bg_widget_;
                delete stack_widget_;
+               delete progress_;
        }
 
        QMenu * toolBarPopup(GuiView * parent)
@@ -229,6 +261,7 @@ struct GuiView::GuiViewPrivate
        {
                stack_widget_->setCurrentWidget(bg_widget_);
                bg_widget_->setUpdatesEnabled(true);
+               bg_widget_->setFocus();
        }
 
        TabWorkArea * tabWorkArea(int i)
@@ -252,7 +285,20 @@ struct GuiView::GuiViewPrivate
                return tabWorkArea(0);
        }
 
+#if (QT_VERSION >= 0x040400)
+       void setPreviewFuture(QFuture<docstring> const & f)
+       {
+               if (preview_watcher_.isRunning()) {
+                       // we prefer to cancel this preview in order to keep a snappy
+                       // interface.
+                       return;
+               }
+               preview_watcher_.setFuture(f);
+       }
+#endif
+
 public:
+       GuiView * gv_;
        GuiWorkArea * current_work_area_;
        GuiWorkArea * current_main_work_area_;
        QSplitter * splitter_;
@@ -260,6 +306,7 @@ public:
        BackgroundWidget * bg_widget_;
        /// view's toolbars
        ToolbarMap toolbars_;
+       ProgressInterface* progress_;
        /// The main layout box.
        /** 
         * \warning Don't Delete! The layout box is actually owned by
@@ -271,9 +318,6 @@ public:
         */
        LayoutBox * layout_;
 
-       ///
-       map<string, Inset *> open_insets_;
-
        ///
        map<string, DialogPtr> dialogs_;
 
@@ -289,11 +333,20 @@ public:
 
        ///
        TocModels toc_models_;
+
+#if (QT_VERSION >= 0x040400)
+       ///
+       QFutureWatcher<docstring> autosave_watcher_;
+       QFutureWatcher<docstring> preview_watcher_;
+#else
+       struct DummyWatcher { bool isRunning(){return false;} }; 
+       DummyWatcher preview_watcher_;
+#endif
 };
 
 
 GuiView::GuiView(int id)
-       : d(*new GuiViewPrivate), id_(id), closing_(false)
+       : d(*new GuiViewPrivate(this)), id_(id), closing_(false)
 {
        // GuiToolbars *must* be initialised before the menu bar.
        normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
@@ -302,7 +355,7 @@ GuiView::GuiView(int id)
        // set ourself as the current view. This is needed for the menu bar
        // filling, at least for the static special menu item on Mac. Otherwise
        // they are greyed out.
-       theLyXFunc().setLyXView(this);
+       guiApp->setCurrentView(this);
        
        // Fill up the menu bar.
        guiApp->menus().fillMenuBar(menuBar(), this, true);
@@ -331,6 +384,17 @@ GuiView::GuiView(int id)
        setAcceptDrops(true);
 
        statusBar()->setSizeGripEnabled(true);
+       updateStatusBar();
+
+#if (QT_VERSION >= 0x040400)
+       connect(&d.autosave_watcher_, SIGNAL(finished()), this,
+               SLOT(threadFinished()));
+       connect(&d.preview_watcher_, SIGNAL(finished()), this,
+               SLOT(threadFinished()));
+#endif
+
+       connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)),
+               SLOT(doShowDialog(QString const &, QString const &, Inset *)));
 
        // Forbid too small unresizable window because it can happen
        // with some window manager under X11.
@@ -358,6 +422,16 @@ GuiView::~GuiView()
 }
 
 
+void GuiView::threadFinished()
+{
+#if (QT_VERSION >= 0x040400)
+       QFutureWatcher<docstring> const * watcher =
+               static_cast<QFutureWatcher<docstring> const *>(sender());
+       message(watcher->result());
+#endif
+}
+
+
 void GuiView::saveLayout() const
 {
        QSettings settings;
@@ -409,6 +483,8 @@ bool GuiView::restoreLayout()
                dialog->prepareView();
        if ((dialog = findOrBuild("view-source", true)))
                dialog->prepareView();
+       if ((dialog = findOrBuild("progress", true)))
+               dialog->prepareView();
 
        if (!restoreState(settings.value("layout").toByteArray(), 0))
                initToolbars();
@@ -460,7 +536,7 @@ void GuiView::initToolbars()
                if (!tb)
                        continue;
                int const visibility = guiApp->toolbars().defaultVisibility(cit->name);
-               bool newline = true;
+               bool newline = !(visibility & Toolbars::SAMEROW);
                tb->setVisible(false);
                tb->setVisibility(visibility);
 
@@ -473,7 +549,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::BOTTOM) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::BottomToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::BottomToolBarArea);
 #endif
                        addToolBar(Qt::BottomToolBarArea, tb);
                }
@@ -481,7 +558,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::LEFT) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::LeftToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::LeftToolBarArea);
 #endif
                        addToolBar(Qt::LeftToolBarArea, tb);
                }
@@ -489,7 +567,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::RIGHT) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::RightToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::RightToolBarArea);
 #endif
                        addToolBar(Qt::RightToolBarArea, tb);
                }
@@ -509,12 +588,22 @@ TocModels & GuiView::tocModels()
 void GuiView::setFocus()
 {
        LYXERR(Debug::DEBUG, "GuiView::setFocus()" << this);
+       QMainWindow::setFocus();
+}
+
+
+void GuiView::focusInEvent(QFocusEvent * e)
+{
+       LYXERR(Debug::DEBUG, "GuiView::focusInEvent()" << this);
+       QMainWindow::focusInEvent(e);
        // Make sure LyXFunc points to the correct view.
        guiApp->setCurrentView(this);
-       theLyXFunc().setLyXView(this);
-       QMainWindow::setFocus();
-       if (d.current_work_area_)
-               d.current_work_area_->setFocus();
+       if (currentMainWorkArea())
+               currentMainWorkArea()->setFocus();
+       else if (currentWorkArea())
+               currentWorkArea()->setFocus();
+       else
+               d.bg_widget_->setFocus();
 }
 
 
@@ -608,13 +697,42 @@ void GuiView::dropEvent(QDropEvent * event)
        for (int i = 0; i != files.size(); ++i) {
                string const file = os::internal_path(fromqstr(
                        files.at(i).toLocalFile()));
-               if (!file.empty()) {
-                       // Asynchronously post the event. DropEvent usually come
-                       // from the BufferView. But reloading a file might close
-                       // the BufferView from within its own event handler.
-                       guiApp->dispatchDelayed(FuncRequest(LFUN_FILE_OPEN, file));
-                       event->accept();
+               if (file.empty())
+                       continue;
+
+               string const ext = support::getExtension(file);
+               vector<const Format *> found_formats;
+
+               // Find all formats that have the correct extension.
+               vector<const Format *> const & import_formats 
+                       = theConverters().importableFormats();
+               vector<const Format *>::const_iterator it = import_formats.begin();
+               for (; it != import_formats.end(); ++it)
+                       if ((*it)->extension() == ext)
+                               found_formats.push_back(*it);
+
+               FuncRequest cmd;
+               if (found_formats.size() >= 1) {
+                       if (found_formats.size() > 1) {
+                               //FIXME: show a dialog to choose the correct importable format
+                               LYXERR(Debug::FILES,
+                                       "Multiple importable formats found, selecting first");
+                       }
+                       string const arg = found_formats[0]->name() + " " + file;
+                       cmd = FuncRequest(LFUN_BUFFER_IMPORT, arg);
+               } 
+               else {
+                       //FIXME: do we have to explicitly check whether it's a lyx file?
+                       LYXERR(Debug::FILES,
+                               "No formats found, trying to open it as a lyx file");
+                       cmd = FuncRequest(LFUN_FILE_OPEN, file);
                }
+
+               // Asynchronously post the event. DropEvent usually comes
+               // from the BufferView. But reloading a file might close
+               // the BufferView from within its own event handler.
+               guiApp->dispatchDelayed(cmd);
+               event->accept();
        }
 }
 
@@ -623,8 +741,15 @@ void GuiView::message(docstring const & str)
 {
        if (ForkedProcess::iAmAChild())
                return;
+       
+       // call is moved to GUI-thread by GuiProgress
+       d.progress_->appendMessage(toqstr(str));
+}
 
-       statusBar()->showMessage(toqstr(str));
+
+void GuiView::updateMessage(QString const & str)
+{
+       statusBar()->showMessage(str);
        d.statusbar_timer_.stop();
        d.statusbar_timer_.start(3000);
 }
@@ -650,17 +775,20 @@ void GuiView::bigSizedIcons()
 
 void GuiView::clearMessage()
 {
-       if (!hasFocus())
-               return;
-       theLyXFunc().setLyXView(this);
-       statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+       // FIXME: This code was introduced in r19643 to fix bug #4123. However,
+       // the hasFocus function mostly returns false, even if the focus is on
+       // a workarea in this view.
+       //if (!hasFocus())
+       //      return;
+       showMessage();
        d.statusbar_timer_.stop();
 }
 
 
 void GuiView::updateWindowTitle(GuiWorkArea * wa)
 {
-       if (wa != d.current_work_area_)
+       if (wa != d.current_work_area_
+           || wa->bufferView().buffer().isInternal())
                return;
        setWindowTitle(qt_("LyX: ") + wa->windowTitle());
        setWindowIconText(wa->windowIconText());
@@ -705,6 +833,7 @@ void GuiView::on_lastWorkAreaRemoved()
        updateDialogs();
 
        resetWindowTitleAndIconText();
+       updateStatusBar();
 
        if (lyxrc.open_buffers_in_tabs)
                // Nothing more to do, the window should stay open.
@@ -730,14 +859,21 @@ void GuiView::updateStatusBar()
        if (d.statusbar_timer_.isActive())
                return;
 
-       theLyXFunc().setLyXView(this);
-       statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+       showMessage();
 }
 
 
-bool GuiView::hasFocus() const
+void GuiView::showMessage()
 {
-       return qApp->activeWindow() == this;
+       QString msg = toqstr(theGuiApp()->viewStatusMessage());
+       if (msg.isEmpty()) {
+               BufferView const * bv = currentBufferView();
+               if (bv)
+                       msg = toqstr(bv->cursor().currentState());
+               else
+                       msg = qt_("Welcome to LyX!");
+       }
+       statusBar()->showMessage(msg);
 }
 
 
@@ -761,12 +897,17 @@ bool GuiView::event(QEvent * e)
        //      break;
 
        case QEvent::WindowActivate: {
-               if (this == guiApp->currentView()) {
+               GuiView * old_view = guiApp->currentView();
+               if (this == old_view) {
                        setFocus();
                        return QMainWindow::event(e);
                }
+               if (old_view && old_view->currentBufferView()) {
+                       // save current selection to the selection buffer to allow
+                       // middle-button paste in this window.
+                       cap::saveSelection(old_view->currentBufferView()->cursor());
+               }
                guiApp->setCurrentView(this);
-               theLyXFunc().setLyXView(this);
                if (d.current_work_area_) {
                        BufferView & bv = d.current_work_area_->bufferView();
                        connectBufferView(bv);
@@ -800,26 +941,7 @@ bool GuiView::event(QEvent * e)
                        }
                }
 #endif
-
-               if (d.current_work_area_)
-                       // Nothing special to do.
-                       return QMainWindow::event(e);
-
-               QKeyEvent * ke = static_cast<QKeyEvent*>(e);
-               // Let Qt handle menu access and the Tab keys to navigate keys to navigate
-               // between controls.
-               if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab 
-                       || ke->key() == Qt::Key_Backtab)
-                       return QMainWindow::event(e);
-
-               // Allow processing of shortcuts that are allowed even when no Buffer
-               // is viewed.
-               theLyXFunc().setLyXView(this);
-               KeySymbol sym;
-               setKeySymbol(&sym, ke);
-               theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
-               e->accept();
-               return true;
+               return QMainWindow::event(e);
        }
 
        default:
@@ -1039,7 +1161,7 @@ void GuiView::updateToolbars()
 
 void GuiView::setBuffer(Buffer * newBuffer)
 {
-       LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << std::endl);
+       LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << endl);
        LASSERT(newBuffer, return);
        setBusy(true);
 
@@ -1098,7 +1220,7 @@ void GuiView::errors(string const & error_type, bool from_master)
 }
 
 
-void GuiView::updateTocItem(std::string const & type, DocIterator const & dit)
+void GuiView::updateTocItem(string const & type, DocIterator const & dit)
 {
        d.toc_models_.updateItem(toqstr(type), dit);
 }
@@ -1156,12 +1278,43 @@ BufferView const * GuiView::currentBufferView() const
 }
 
 
+#if (QT_VERSION >= 0x040400)
+static docstring saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
+{
+       bool failed = true;
+       FileName const tmp_ret = FileName::tempName("lyxauto");
+       if (!tmp_ret.empty()) {
+               if (buffer->writeFile(tmp_ret))
+                       failed = !tmp_ret.moveTo(fname);
+       }
+       if (failed) {
+               // failed to write/rename tmp_ret so try writing direct
+               failed = buffer->writeFile(fname);
+       }
+       delete buffer;
+       return failed
+               ? _("Automatic save failed!")
+               : _("Automatic save done.");
+}
+#endif
+
+
 void GuiView::autoSave()
 {
        LYXERR(Debug::INFO, "Running autoSave()");
 
-       if (documentBufferView())
-               documentBufferView()->buffer().autoSave();
+       Buffer * buffer = documentBufferView()
+               ? &documentBufferView()->buffer() : 0;
+       if (!buffer)
+               return;
+
+#if (QT_VERSION >= 0x040400)
+       QFuture<docstring> f = QtConcurrent::run(saveAndDestroyBuffer, buffer->clone(),
+               buffer->getAutosaveFilename());
+       d.autosave_watcher_.setFuture(f);
+#else
+       buffer->autoSave();
+#endif
 }
 
 
@@ -1180,6 +1333,15 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        Buffer * doc_buffer = documentBufferView()
                ? &(documentBufferView()->buffer()) : 0;
 
+       // Check whether we need a buffer
+       if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
+               // no, exit directly
+               flag.message(from_utf8(N_("Command not allowed with"
+                                   "out any document open")));
+               flag.setEnabled(false);
+               return true;
+       }
+
        if (cmd.origin == FuncRequest::TOC) {
                GuiToc * toc = static_cast<GuiToc*>(findOrBuild("toc", false));
                FuncStatus fs;
@@ -1191,6 +1353,28 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        }
 
        switch(cmd.action) {
+       case LFUN_BUFFER_IMPORT:
+               break;
+
+       case LFUN_MASTER_BUFFER_UPDATE:
+       case LFUN_MASTER_BUFFER_VIEW: 
+               enable = doc_buffer && doc_buffer->parent() != 0
+                       && !d.preview_watcher_.isRunning();
+               break;
+
+       case LFUN_BUFFER_UPDATE:
+       case LFUN_BUFFER_VIEW: {
+               if (!doc_buffer || d.preview_watcher_.isRunning()) {
+                       enable = false;
+                       break;
+               }
+               string format = to_utf8(cmd.argument());
+               if (cmd.argument().empty())
+                       format = doc_buffer->getDefaultOutputFormat();
+               enable = doc_buffer->isExportableFormat(format);
+               break;
+       }
+
        case LFUN_BUFFER_RELOAD:
                enable = doc_buffer && !doc_buffer->isUnnamed()
                        && doc_buffer->fileName().exists()
@@ -1198,14 +1382,41 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                           || doc_buffer->isExternallyModified(Buffer::timestamp_method));
                break;
 
+       case LFUN_BUFFER_CHILD_OPEN:
+               enable = doc_buffer;
+               break;
+
        case LFUN_BUFFER_WRITE:
                enable = doc_buffer && (doc_buffer->isUnnamed() || !doc_buffer->isClean());
                break;
 
+       //FIXME: This LFUN should be moved to GuiApplication.
+       case LFUN_BUFFER_WRITE_ALL: {
+               // We enable the command only if there are some modified buffers
+               Buffer * first = theBufferList().first();
+               enable = false;
+               if (!first)
+                       break;
+               Buffer * b = first;
+               // We cannot use a for loop as the buffer list is a cycle.
+               do {
+                       if (!b->isClean()) {
+                               enable = true;
+                               break;
+                       }
+                       b = theBufferList().next(b);
+               } while (b != first); 
+               break;
+       }
+
        case LFUN_BUFFER_WRITE_AS:
                enable = doc_buffer;
                break;
 
+       case LFUN_BUFFER_CLOSE:
+               enable = doc_buffer;
+               break;
+
        case LFUN_BUFFER_CLOSE_ALL:
                enable = theBufferList().last() != theBufferList().first();
                break;
@@ -1228,6 +1439,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        flag.setOnOff(t->isVisible());
                break;
 
+       case LFUN_DROP_LAYOUTS_CHOICE:
+               enable = buf; 
+               break;
+
        case LFUN_UI_TOGGLE:
                flag.setOnOff(isFullScreen());
                break;
@@ -1248,7 +1463,9 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        enable = name == "aboutlyx"
                                || name == "file" //FIXME: should be removed.
                                || name == "prefs"
-                               || name == "texinfo";
+                               || name == "texinfo"
+                               || name == "progress"
+                               || name == "compare";
                else if (name == "print")
                        enable = doc_buffer->isExportable("dvi")
                                && lyxrc.print_command != "none";
@@ -1285,25 +1502,6 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                // Nothing to check.
                break;
 
-       case LFUN_INSET_APPLY: {
-               string const name = cmd.getArg(0);
-               Inset * inset = getOpenInset(name);
-               if (inset) {
-                       FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
-                       FuncStatus fs;
-                       if (!inset->getStatus(currentBufferView()->cursor(), fr, fs)) {
-                               // Every inset is supposed to handle this
-                               LASSERT(false, break);
-                       }
-                       flag |= fs;
-               } else {
-                       FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
-                       flag |= lyx::getStatus(fr);
-               }
-               enable = flag.enabled();
-               break;
-       }
-
        case LFUN_COMPLETION_INLINE:
                if (!d.current_work_area_
                    || !d.current_work_area_->completer().inlinePossible(
@@ -1380,6 +1578,9 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
        case LFUN_VC_UNDO_LAST:
                enable = doc_buffer && doc_buffer->lyxvc().undoLastEnabled();
                break;
+       case LFUN_VC_REPO_UPDATE:
+               enable = doc_buffer && doc_buffer->lyxvc().inUse();
+               break;
        case LFUN_VC_COMMAND: {
                if (cmd.argument().empty())
                        enable = false;
@@ -1388,6 +1589,9 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
        }
 
+       case LFUN_SERVER_GOTO_FILE_ROW:
+               break;
+
        default:
                return false;
        }
@@ -1576,7 +1780,7 @@ static bool import(GuiView * lv, FileName const & filename,
                                          formats.extension(loader_format));
                lv->currentBufferView()->insertPlaintextFile(FileName(filename2),
                        as_paragraphs);
-               theLyXFunc().setLyXView(lv);
+               guiApp->setCurrentView(lv);
                lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
        }
 
@@ -1693,7 +1897,7 @@ void GuiView::newDocument(string const & filename, bool from_template)
        
        Buffer * b;
        if (filename.empty())
-               b = newUnnamedFile(templatefile, initpath);
+               b = newUnnamedFile(initpath, to_utf8(_("newfile")), templatefile);
        else
                b = newFile(filename, templatefile, true);
 
@@ -1933,6 +2137,7 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa)
 bool GuiView::closeBuffer()
 {
        GuiWorkArea * wa = currentMainWorkArea();
+       setCurrentWorkArea(wa);
        Buffer & buf = wa->bufferView().buffer();
        return wa && closeWorkArea(wa, !buf.parent());
 }
@@ -2000,14 +2205,31 @@ bool GuiView::closeWorkAreaAll()
 
 bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer)
 {
+       if (!wa)
+               return false;
+
        Buffer & buf = wa->bufferView().buffer();
 
+       if (close_buffer)
+               return closeBuffer(buf);
+       else {
+               if (!inMultiTabs(wa))
+                       if (!saveBufferIfNeeded(buf, true))
+                               return false;
+               removeWorkArea(wa);
+               return true;
+       }
+}
+
+
+bool GuiView::closeBuffer(Buffer & buf)
+{
        // If we are in a close_event all children will be closed in some time,
        // so no need to do it here. This will ensure that the children end up
        // in the session file in the correct order. If we close the master
        // buffer, we can close or release the child buffers here too.
-       if (close_buffer && !closing_) {
-               vector<Buffer *> clist = buf.getChildren();
+       if (!closing_) {
+               vector<Buffer *> clist = buf.getChildren(false);
                for (vector<Buffer *>::const_iterator it = clist.begin();
                         it != clist.end(); ++it) {
                        // If a child is dirty, do not close
@@ -2028,18 +2250,8 @@ bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer)
        for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
                theLyXFunc().gotoBookmark(i+1, false, false);
 
-       // if we are only hiding the buffer and there are multiple views
-       // of the buffer, then we do not need to ensure a clean buffer.
-       bool const allow_dirty = inMultiTabs(wa) && !close_buffer;
-
-       if (allow_dirty || saveBufferIfNeeded(buf, !close_buffer)) {
-               // save in sessions if requested
-               // do not save childs if their master
-               // is opened as well
-               if (!close_buffer)
-                       removeWorkArea(wa);
-               else
-                       theBufferList().release(&buf);
+       if (saveBufferIfNeeded(buf, false)) {
+               theBufferList().release(&buf);
                return true;
        }
        return false;
@@ -2114,7 +2326,7 @@ bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
                buf.removeAutosaveFile();
                if (hiding)
                        // revert all changes
-                       buf.loadLyXFile(buf.fileName());
+                       buf.reload();
                buf.markClean();
                break;
        case 2:
@@ -2211,27 +2423,33 @@ static bool ensureBufferClean(Buffer * buffer)
 void GuiView::reloadBuffer()
 {
        Buffer * buf = &documentBufferView()->buffer();
-       FileName filename = buf->fileName();
-       // The user has already confirmed that the changes, if any, should
-       // be discarded. So we just release the Buffer and don't call closeBuffer();
-       theBufferList().release(buf);
-       buf = loadDocument(filename);
-       docstring const disp_fn = makeDisplayPath(filename.absFilename());
-       docstring str;
-       if (buf) {
-               buf->updateLabels();
-               setBuffer(buf);
-               buf->errors("Parse");
-               str = bformat(_("Document %1$s reloaded."), disp_fn);
-       } else {
-               str = bformat(_("Could not reload document %1$s"), disp_fn);
+       buf->reload();
+}
+
+
+void GuiView::checkExternallyModifiedBuffers()
+{
+       BufferList::iterator bit = theBufferList().begin();
+       BufferList::iterator const bend = theBufferList().end();
+       for (; bit != bend; ++bit) {
+               if ((*bit)->fileName().exists()
+                   && (*bit)->isExternallyModified(Buffer::checksum_method)) {
+                       docstring text = bformat(_("Document \n%1$s\n has been externally modified."
+                                       " Reload now? Any local changes will be lost."),
+                                       from_utf8((*bit)->absFileName()));
+                       int const ret = Alert::prompt(_("Reload externally changed document?"),
+                                               text, 0, 1, _("&Reload"), _("&Cancel"));
+                       if (!ret)
+                               (*bit)->reload();
+               }
        }
-       message(str);
 }
 
 
 void GuiView::dispatchVC(FuncRequest const & cmd)
 {
+       // message for statusbar
+       string msg;
        Buffer * buffer = documentBufferView()
                ? &(documentBufferView()->buffer()) : 0;
 
@@ -2249,8 +2467,9 @@ void GuiView::dispatchVC(FuncRequest const & cmd)
                if (!buffer || !ensureBufferClean(buffer))
                        break;
                if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
-                       message(from_utf8(buffer->lyxvc().checkIn()));
-                       reloadBuffer();
+                       msg = buffer->lyxvc().checkIn();
+                       if (!msg.empty())
+                               reloadBuffer();
                }
                break;
 
@@ -2258,7 +2477,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd)
                if (!buffer || !ensureBufferClean(buffer))
                        break;
                if (buffer->lyxvc().inUse()) {
-                       message(from_utf8(buffer->lyxvc().checkOut()));
+                       msg = buffer->lyxvc().checkOut();
                        reloadBuffer();
                }
                break;
@@ -2273,7 +2492,7 @@ void GuiView::dispatchVC(FuncRequest const & cmd)
                                frontend::Alert::error(_("Revision control error."),
                                _("Error when setting the locking property."));
                        } else {
-                               message(from_utf8(res));
+                               msg = res;
                                reloadBuffer();
                        }
                }
@@ -2291,6 +2510,14 @@ void GuiView::dispatchVC(FuncRequest const & cmd)
                reloadBuffer();
                break;
 
+       case LFUN_VC_REPO_UPDATE:
+               LASSERT(buffer, return);
+               if (ensureBufferClean(buffer)) {
+                       msg = buffer->lyxvc().repoUpdate();
+                       checkExternallyModifiedBuffers();
+               }
+               break;
+
        case LFUN_VC_COMMAND: {
                string flag = cmd.getArg(0);
                if (buffer && contains(flag, 'R') && !ensureBufferClean(buffer))
@@ -2332,10 +2559,129 @@ void GuiView::dispatchVC(FuncRequest const & cmd)
 
                break;
                }
+       default:
+               break;
        }
+
+       if (!msg.empty())
+               message(from_utf8(msg));
 }
 
 
+void GuiView::openChildDocument(string const & fname)
+{
+       LASSERT(documentBufferView(), return);
+       Buffer & buffer = documentBufferView()->buffer();
+       FileName const filename = support::makeAbsPath(fname, buffer.filePath());
+       documentBufferView()->saveBookmark(false);
+       Buffer * child = 0;
+       bool parsed = false;
+       if (theBufferList().exists(filename)) {
+               child = theBufferList().getBuffer(filename);
+       } else {
+               message(bformat(_("Opening child document %1$s..."),
+               makeDisplayPath(filename.absFilename())));
+               child = loadDocument(filename, false);
+               parsed = true;
+       }
+       if (!child)
+               return;
+
+       // Set the parent name of the child document.
+       // This makes insertion of citations and references in the child work,
+       // when the target is in the parent or another child document.
+       child->setParent(&buffer);
+       child->masterBuffer()->updateLabels();
+       setBuffer(child);
+       if (parsed)
+               child->errors("Parse");
+}
+
+
+bool GuiView::goToFileRow(string const & argument)
+{
+       string file_name;
+       int row;
+       size_t i = argument.find_last_of(' ');
+       if (i != string::npos) {
+               file_name = os::internal_path(trim(argument.substr(0, i)));
+               istringstream is(argument.substr(i + 1));
+               is >> row;
+               if (is.fail())
+                       i = string::npos;
+       }
+       if (i == string::npos) {
+               LYXERR0("Wrong argument: " << argument);
+               return false;
+       }
+       Buffer * buf = 0;
+       string const abstmp = package().temp_dir().absFilename();
+       string const realtmp = package().temp_dir().realPath();
+       // We have to use os::path_prefix_is() here, instead of
+       // simply prefixIs(), because the file name comes from
+       // an external application and may need case adjustment.
+       if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
+               || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
+               // Needed by inverse dvi search. If it is a file
+               // in tmpdir, call the apropriated function.
+               // If tmpdir is a symlink, we may have the real
+               // path passed back, so we correct for that.
+               if (!prefixIs(file_name, abstmp))
+                       file_name = subst(file_name, realtmp, abstmp);
+               buf = theBufferList().getBufferFromTmp(file_name);
+       } else {
+               // Must replace extension of the file to be .lyx
+               // and get full path
+               FileName const s = fileSearch(string(),
+                                             support::changeExtension(file_name, ".lyx"), "lyx");
+               // Either change buffer or load the file
+               if (theBufferList().exists(s))
+                       buf = theBufferList().getBuffer(s);
+               else if (s.exists()) {
+                       buf = loadDocument(s);
+                       buf->updateLabels();
+                       buf->errors("Parse");
+               } else {
+                       message(bformat(
+                                       _("File does not exist: %1$s"),
+                                       makeDisplayPath(file_name)));
+                       return false;
+               }
+       }
+       setBuffer(buf);
+       documentBufferView()->setCursorFromRow(row);
+       return true;
+}
+
+
+#if (QT_VERSION >= 0x040400)
+static docstring exportAndDestroy(Buffer * buffer, string const & format)
+{
+       bool const update_unincluded =
+                               buffer->params().maintain_unincluded_children
+                               && !buffer->params().getIncludedChildren().empty();
+       bool const success = buffer->doExport(format, true, update_unincluded);
+       delete buffer;
+       return success
+               ? bformat(_("Successful export to format: %1$s"), from_utf8(format))
+               : bformat(_("Error exporting to format: %1$s"), from_utf8(format));
+}
+
+
+static docstring previewAndDestroy(Buffer * buffer, string const & format)
+{
+       bool const update_unincluded =
+                               buffer->params().maintain_unincluded_children
+                               && !buffer->params().getIncludedChildren().empty();
+       bool const success = buffer->preview(format, update_unincluded);
+       delete buffer;
+       return success
+               ? bformat(_("Successful preview of format: %1$s"), from_utf8(format))
+               : bformat(_("Error previewing format: %1$s"), from_utf8(format));
+}
+#endif
+
+
 bool GuiView::dispatch(FuncRequest const & cmd)
 {
        BufferView * bv = currentBufferView();
@@ -2354,11 +2700,104 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                return true;
        }
 
+       string const argument = to_utf8(cmd.argument());
+
        switch(cmd.action) {
+               case LFUN_BUFFER_CHILD_OPEN:
+                       openChildDocument(to_utf8(cmd.argument()));
+                       break;
+
                case LFUN_BUFFER_IMPORT:
                        importDocument(to_utf8(cmd.argument()));
                        break;
 
+               case LFUN_BUFFER_EXPORT: {
+                       if (!doc_buffer)
+                               break;
+                       if (cmd.argument() == "custom") {
+                               lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
+                               break;
+                       }
+                       if (doc_buffer->doExport(argument, false)) {
+                               message(bformat(_("Error exporting to format: %1$s."),
+                                       cmd.argument()));
+                       }
+                       break;
+               }
+
+               case LFUN_BUFFER_UPDATE: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       if (argument.empty())
+                               format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       d.progress_->clearMessages();
+                       message(_("Exporting ..."));
+                       QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+                               doc_buffer->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               doc_buffer->params().maintain_unincluded_children
+                               && !doc_buffer->params().getIncludedChildren().empty();
+                       doc_buffer->doExport(format, true, update_unincluded);
+#endif
+                       break;
+               }
+               case LFUN_BUFFER_VIEW: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       if (argument.empty())
+                               format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       d.progress_->clearMessages();
+                       message(_("Previewing ..."));
+                       QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+                               doc_buffer->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               doc_buffer->params().maintain_unincluded_children
+                               && !doc_buffer->params().getIncludedChildren().empty();
+                       doc_buffer->preview(format, update_unincluded);
+#endif
+                       break;
+               }
+               case LFUN_MASTER_BUFFER_UPDATE: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       Buffer const * master = doc_buffer->masterBuffer();
+                       if (argument.empty())
+                               format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+                               master->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               master->params().maintain_unincluded_children
+                               && !master->params().getIncludedChildren().empty();
+                       master->doExport(format, true);
+#endif
+                       break;
+               }
+               case LFUN_MASTER_BUFFER_VIEW: {
+                       string format = argument;
+                       Buffer const * master = doc_buffer->masterBuffer();
+                       if (argument.empty())
+                               format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+                               master->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       master->preview(format);
+#endif
+                       break;
+               }
                case LFUN_BUFFER_SWITCH:
                        if (FileName::isAbsolute(to_utf8(cmd.argument()))) {
                                Buffer * buffer = 
@@ -2366,7 +2805,7 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                if (buffer)
                                        setBuffer(buffer);
                                else
-                                       bv->cursor().message(_("Document not loaded"));
+                                       message(_("Document not loaded"));
                        }
                        break;
 
@@ -2417,8 +2856,10 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        int const ret = Alert::prompt(_("Revert to saved document?"),
                                text, 1, 1, _("&Revert"), _("&Cancel"));
 
-                       if (ret == 0)
+                       if (ret == 0) {
+                               doc_buffer->markClean();
                                reloadBuffer();
+                       }
                        break;
                }
 
@@ -2450,6 +2891,14 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        break;
                }
 
+               case LFUN_BUFFER_CLOSE:
+                       closeBuffer();
+                       break;
+
+               case LFUN_BUFFER_CLOSE_ALL:
+                       closeBufferAll();
+                       break;
+
                case LFUN_TOOLBAR_TOGGLE: {
                        string const name = cmd.getArg(0);
                        if (GuiToolbar * t = toolbar(name))
@@ -2459,9 +2908,13 @@ bool GuiView::dispatch(FuncRequest const & cmd)
 
                case LFUN_DIALOG_UPDATE: {
                        string const name = to_utf8(cmd.argument());
-                       // Can only update a dialog connected to an existing inset
-                       Inset * inset = getOpenInset(name);
-                       if (inset) {
+                       if (currentBufferView()) {
+                               Inset * inset = currentBufferView()->editedInset(name);
+                               // Can only update a dialog connected to an existing inset
+                               if (!inset)
+                                       break;
+                               // FIXME: get rid of this indirection; GuiView ask the inset
+                               // if he is kind enough to update itself...
                                FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
                                inset->dispatch(currentBufferView()->cursor(), fr);
                        } else if (name == "paragraph") {
@@ -2532,28 +2985,6 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        message(cmd.argument());
                        break;
 
-               case LFUN_INSET_APPLY: {
-                       string const name = cmd.getArg(0);
-                       Inset * inset = getOpenInset(name);
-                       if (inset) {
-                               // put cursor in front of inset.
-                               if (!currentBufferView()->setCursorFromInset(inset)) {
-                                       LASSERT(false, break);
-                               }
-                               BufferView * bv = currentBufferView();
-                               // useful if we are called from a dialog.
-                               bv->cursor().beginUndoGroup();
-                               bv->cursor().recordUndo();
-                               FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
-                               inset->dispatch(bv->cursor(), fr);
-                               bv->cursor().endUndoGroup();
-                       } else {
-                               FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
-                               lyx::dispatch(fr);
-                       }
-                       break;
-               }
-
                case LFUN_UI_TOGGLE:
                        lfunUiToggle(cmd);
                        // Make sure the keyboard focus stays in the work area.
@@ -2638,6 +3069,7 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                case LFUN_VC_REGISTER:
                case LFUN_VC_CHECK_IN:
                case LFUN_VC_CHECK_OUT:
+               case LFUN_VC_REPO_UPDATE:
                case LFUN_VC_LOCKING_TOGGLE:
                case LFUN_VC_REVERT:
                case LFUN_VC_UNDO_LAST:
@@ -2645,6 +3077,10 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        dispatchVC(cmd);
                        break;
 
+               case LFUN_SERVER_GOTO_FILE_ROW:
+                       goToFileRow(to_utf8(cmd.argument()));
+                       break;
+
                default:
                        dispatched = false;
                        break;
@@ -2787,13 +3223,13 @@ namespace {
 
 char const * const dialognames[] = {
 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
-"citation", "document", "errorlist", "ert", "external", "file", "findreplace",
-"findreplaceadv", "float", "graphics", "href", "include", "index",
-"index_print", "info", "listings", "label", "log", "mathdelimiter",
+"citation", "compare", "document", "errorlist", "ert", "external", "file",
+"findreplace", "findreplaceadv", "float", "graphics", "href", "include",
+"index", "index_print", "info", "listings", "label", "log", "mathdelimiter",
 "mathmatrix", "mathspace", "nomenclature", "nomencl_print", "note",
 "paragraph", "phantom", "prefs", "print", "ref", "sendto", "space",
 "spellchecker", "symbols", "tabular", "tabularcreate", "thesaurus", "texinfo",
-"toc", "view-source", "vspace", "wrap" };
+"toc", "view-source", "vspace", "wrap", "progress"};
 
 char const * const * const end_dialognames =
        dialognames + (sizeof(dialognames) / sizeof(char *));
@@ -2821,14 +3257,14 @@ bool isValidName(string const & name)
 void GuiView::resetDialogs()
 {
        // Make sure that no LFUN uses any LyXView.
-       theLyXFunc().setLyXView(0);
+       guiApp->setCurrentView(0);
        saveLayout();
        menuBar()->clear();
        constructToolbars();
        guiApp->menus().fillMenuBar(menuBar(), this, false);
        d.layout_->updateContents(true);
        // Now update controls with current buffer.
-       theLyXFunc().setLyXView(this);
+       guiApp->setCurrentView(this);
        restoreLayout();
        restartCursor();
 }
@@ -2859,17 +3295,27 @@ Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
 
 void GuiView::showDialog(string const & name, string const & data,
        Inset * inset)
+{
+       triggerShowDialog(toqstr(name), toqstr(data), inset);
+}
+
+
+void GuiView::doShowDialog(QString const & qname, QString const & qdata,
+       Inset * inset)
 {
        if (d.in_show_)
                return;
 
+       const string name = fromqstr(qname);
+       const string data = fromqstr(qdata);
+
        d.in_show_ = true;
        try {
                Dialog * dialog = findOrBuild(name, false);
                if (dialog) {
                        dialog->showData(data);
-                       if (inset)
-                               d.open_insets_[name] = inset;
+                       if (inset && currentBufferView())
+                               currentBufferView()->editInset(name, inset);
                }
        }
        catch (ExceptionMessage const & ex) {
@@ -2895,13 +3341,15 @@ void GuiView::hideDialog(string const & name, Inset * inset)
        if (it == d.dialogs_.end())
                return;
 
-       if (inset && inset != getOpenInset(name))
+       if (inset && currentBufferView()
+               && inset != currentBufferView()->editedInset(name))
                return;
 
        Dialog * const dialog = it->second.get();
        if (dialog->isVisibleView())
                dialog->hideView();
-       d.open_insets_[name] = 0;
+       if (currentBufferView())
+               currentBufferView()->editInset(name, 0);
 }
 
 
@@ -2909,19 +3357,8 @@ void GuiView::disconnectDialog(string const & name)
 {
        if (!isValidName(name))
                return;
-
-       if (d.open_insets_.find(name) != d.open_insets_.end())
-               d.open_insets_[name] = 0;
-}
-
-
-Inset * GuiView::getOpenInset(string const & name) const
-{
-       if (!isValidName(name))
-               return 0;
-
-       map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
-       return it == d.open_insets_.end() ? 0 : it->second;
+       if (currentBufferView())
+               currentBufferView()->editInset(name, 0);
 }
 
 
@@ -2942,8 +3379,12 @@ void GuiView::updateDialogs()
 
        for(; it != end; ++it) {
                Dialog * dialog = it->second.get();
-               if (dialog && dialog->isVisibleView())
-                       dialog->checkStatus();
+               if (dialog) {
+                       if (dialog->isBufferDependent() && !documentBufferView())
+                               hideDialog(fromqstr(dialog->name()), 0);
+                       else if (dialog->isVisibleView())
+                               dialog->checkStatus();
+               }
        }
        updateToolbars();
        updateLayoutList();
@@ -2959,6 +3400,7 @@ Dialog * createGuiBranch(GuiView & lv);
 Dialog * createGuiChanges(GuiView & lv);
 Dialog * createGuiCharacter(GuiView & lv);
 Dialog * createGuiCitation(GuiView & lv);
+Dialog * createGuiCompare(GuiView & lv);
 Dialog * createGuiDelimiter(GuiView & lv);
 Dialog * createGuiDocument(GuiView & lv);
 Dialog * createGuiErrorList(GuiView & lv);
@@ -2999,6 +3441,8 @@ Dialog * createGuiHyperlink(GuiView & lv);
 Dialog * createGuiVSpace(GuiView & lv);
 Dialog * createGuiViewSource(GuiView & lv);
 Dialog * createGuiWrap(GuiView & lv);
+Dialog * createGuiProgressView(GuiView & lv);
+
 
 
 Dialog * GuiView::build(string const & name)
@@ -3021,6 +3465,8 @@ Dialog * GuiView::build(string const & name)
                return createGuiCharacter(*this);
        if (name == "citation")
                return createGuiCitation(*this);
+       if (name == "compare")
+               return createGuiCompare(*this);
        if (name == "document")
                return createGuiDocument(*this);
        if (name == "errorlist")
@@ -3101,6 +3547,8 @@ Dialog * GuiView::build(string const & name)
                return createGuiVSpace(*this);
        if (name == "wrap")
                return createGuiWrap(*this);
+       if (name == "progress")
+               return createGuiProgressView(*this);
 
        return 0;
 }