]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiView.cpp
89fa9618ca0d6caaefc2e36f480e23e93aabd7b6
[lyx.git] / src / frontends / qt4 / GuiView.cpp
1 /**
2  * \file GuiView.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author John Levon
8  * \author Abdelrazak Younes
9  * \author Peter Kümmel
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiView.h"
17
18 #include "Dialog.h"
19 #include "FileDialog.h"
20 #include "GuiApplication.h"
21 #include "GuiWorkArea.h"
22 #include "GuiKeySymbol.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
25 #include "Menus.h"
26
27 #include "qt_helpers.h"
28
29 #include "frontends/alert.h"
30
31 #include "buffer_funcs.h"
32 #include "Buffer.h"
33 #include "BufferList.h"
34 #include "BufferParams.h"
35 #include "BufferView.h"
36 #include "Converter.h"
37 #include "Cursor.h"
38 #include "ErrorList.h"
39 #include "Format.h"
40 #include "FuncStatus.h"
41 #include "FuncRequest.h"
42 #include "support/gettext.h"
43 #include "Intl.h"
44 #include "Layout.h"
45 #include "Lexer.h"
46 #include "LyXFunc.h"
47 #include "LyX.h"
48 #include "LyXRC.h"
49 #include "LyXVC.h"
50 #include "Paragraph.h"
51 #include "TextClass.h"
52 #include "Text.h"
53 #include "ToolbarBackend.h"
54 #include "version.h"
55
56 #include "support/debug.h"
57 #include "support/FileFilterList.h"
58 #include "support/FileName.h"
59 #include "support/filetools.h"
60 #include "support/ForkedCalls.h"
61 #include "support/lstrings.h"
62 #include "support/os.h"
63 #include "support/Package.h"
64 #include "support/Timeout.h"
65
66 #include <QAction>
67 #include <QApplication>
68 #include <QCloseEvent>
69 #include <QDebug>
70 #include <QDesktopWidget>
71 #include <QDragEnterEvent>
72 #include <QDropEvent>
73 #include <QList>
74 #include <QMenu>
75 #include <QMenuBar>
76 #include <QPainter>
77 #include <QPixmap>
78 #include <QPoint>
79 #include <QPushButton>
80 #include <QSettings>
81 #include <QShowEvent>
82 #include <QSplitter>
83 #include <QStackedWidget>
84 #include <QStatusBar>
85 #include <QTimer>
86 #include <QToolBar>
87 #include <QUrl>
88 #include <QScrollBar>
89
90 #include <boost/assert.hpp>
91 #include <boost/bind.hpp>
92
93 #ifdef HAVE_SYS_TIME_H
94 # include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 # include <unistd.h>
98 #endif
99
100 using namespace std;
101 using namespace lyx::support;
102
103 namespace lyx {
104 namespace frontend {
105
106 namespace {
107
108 class BackgroundWidget : public QWidget
109 {
110 public:
111         BackgroundWidget()
112         {
113                 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
114                 /// The text to be written on top of the pixmap
115                 QString const text = lyx_version ? lyx_version : qt_("unknown version");
116                 splash_ = QPixmap(":/images/banner.png");
117
118                 QPainter pain(&splash_);
119                 pain.setPen(QColor(255, 255, 0));
120                 QFont font;
121                 // The font used to display the version info
122                 font.setStyleHint(QFont::SansSerif);
123                 font.setWeight(QFont::Bold);
124                 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
125                 pain.setFont(font);
126                 pain.drawText(260, 270, text);
127         }
128
129         void paintEvent(QPaintEvent *)
130         {
131                 int x = (width() - splash_.width()) / 2;
132                 int y = (height() - splash_.height()) / 2;
133                 QPainter pain(this);
134                 pain.drawPixmap(x, y, splash_);
135         }
136
137 private:
138         QPixmap splash_;
139 };
140
141 } // namespace anon
142
143
144 typedef boost::shared_ptr<Dialog> DialogPtr;
145
146 struct GuiView::GuiViewPrivate
147 {
148         GuiViewPrivate()
149                 : current_work_area_(0), layout_(0), autosave_timeout_(5000),
150                 in_show_(false)
151         {
152                 // hardcode here the platform specific icon size
153                 smallIconSize = 14;     // scaling problems
154                 normalIconSize = 20;    // ok, default
155                 bigIconSize = 26;               // better for some math icons
156
157                 splitter_ = new QSplitter;
158                 bg_widget_ = new BackgroundWidget;
159                 stack_widget_ = new QStackedWidget;
160                 stack_widget_->addWidget(bg_widget_);
161                 stack_widget_->addWidget(splitter_);
162                 setBackground();
163         }
164
165         ~GuiViewPrivate()
166         {
167                 delete splitter_;
168                 delete bg_widget_;
169                 delete stack_widget_;
170                 delete toolbars_;
171         }
172
173         QMenu * toolBarPopup(GuiView * parent)
174         {
175                 // FIXME: translation
176                 QMenu * menu = new QMenu(parent);
177                 QActionGroup * iconSizeGroup = new QActionGroup(parent);
178
179                 QAction * smallIcons = new QAction(iconSizeGroup);
180                 smallIcons->setText(qt_("Small-sized icons"));
181                 smallIcons->setCheckable(true);
182                 QObject::connect(smallIcons, SIGNAL(triggered()),
183                         parent, SLOT(smallSizedIcons()));
184                 menu->addAction(smallIcons);
185
186                 QAction * normalIcons = new QAction(iconSizeGroup);
187                 normalIcons->setText(qt_("Normal-sized icons"));
188                 normalIcons->setCheckable(true);
189                 QObject::connect(normalIcons, SIGNAL(triggered()),
190                         parent, SLOT(normalSizedIcons()));
191                 menu->addAction(normalIcons);
192
193                 QAction * bigIcons = new QAction(iconSizeGroup);
194                 bigIcons->setText(qt_("Big-sized icons"));
195                 bigIcons->setCheckable(true);
196                 QObject::connect(bigIcons, SIGNAL(triggered()),
197                         parent, SLOT(bigSizedIcons()));
198                 menu->addAction(bigIcons);
199
200                 unsigned int cur = parent->iconSize().width();
201                 if ( cur == parent->d.smallIconSize)
202                         smallIcons->setChecked(true);
203                 else if (cur == parent->d.normalIconSize)
204                         normalIcons->setChecked(true);
205                 else if (cur == parent->d.bigIconSize)
206                         bigIcons->setChecked(true);
207
208                 return menu;
209         }
210
211         void setBackground()
212         {
213                 stack_widget_->setCurrentWidget(bg_widget_);
214                 bg_widget_->setUpdatesEnabled(true);
215         }
216
217         TabWorkArea * tabWorkArea(int i)
218         {
219                 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
220         }
221
222         TabWorkArea * currentTabWorkArea()
223         {
224                 if (splitter_->count() == 1)
225                         // The first TabWorkArea is always the first one, if any.
226                         return tabWorkArea(0);
227
228                 for (int i = 0; i != splitter_->count(); ++i) {
229                         TabWorkArea * twa = tabWorkArea(i);
230                         if (current_work_area_ == twa->currentWorkArea())
231                                 return twa;
232                 }
233
234                 // None has the focus so we just take the first one.
235                 return tabWorkArea(0);
236         }
237
238 public:
239         GuiWorkArea * current_work_area_;
240         QSplitter * splitter_;
241         QStackedWidget * stack_widget_;
242         BackgroundWidget * bg_widget_;
243         /// view's toolbars
244         GuiToolbars * toolbars_;
245         /// The main layout box.
246         /** 
247          * \warning Don't Delete! The layout box is actually owned by
248          * whichever toolbar contains it. All the GuiView class needs is a
249          * means of accessing it.
250          *
251          * FIXME: replace that with a proper model so that we are not limited
252          * to only one dialog.
253          */
254         GuiLayoutBox * layout_;
255
256         ///
257         map<string, Inset *> open_insets_;
258
259         ///
260         map<string, DialogPtr> dialogs_;
261
262         unsigned int smallIconSize;
263         unsigned int normalIconSize;
264         unsigned int bigIconSize;
265         ///
266         QTimer statusbar_timer_;
267         /// auto-saving of buffers
268         Timeout autosave_timeout_;
269         /// flag against a race condition due to multiclicks, see bug #1119
270         bool in_show_;
271 };
272
273
274 GuiView::GuiView(int id)
275         : d(*new GuiViewPrivate), id_(id)
276 {
277         // GuiToolbars *must* be initialised before the menu bar.
278         d.toolbars_ = new GuiToolbars(*this);
279
280         // Fill up the menu bar.
281         guiApp->menus().fillMenuBar(menuBar(), this);
282
283         setCentralWidget(d.stack_widget_);
284
285         // Start autosave timer
286         if (lyxrc.autosave) {
287                 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
288                 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
289                 d.autosave_timeout_.start();
290         }
291         connect(&d.statusbar_timer_, SIGNAL(timeout()),
292                 this, SLOT(clearMessage()));
293
294         // We don't want to keep the window in memory if it is closed.
295         setAttribute(Qt::WA_DeleteOnClose, true);
296
297 #ifndef Q_WS_MACX
298         // assign an icon to main form. We do not do it under Qt/Mac,
299         // since the icon is provided in the application bundle.
300         setWindowIcon(QPixmap(":/images/lyx.png"));
301 #endif
302
303         // For Drag&Drop.
304         setAcceptDrops(true);
305
306         statusBar()->setSizeGripEnabled(true);
307
308         // Forbid too small unresizable window because it can happen
309         // with some window manager under X11.
310         setMinimumSize(300, 200);
311
312         if (!lyxrc.allow_geometry_session)
313                 // No session handling, default to a sane size.
314                 setGeometry(50, 50, 690, 510);
315
316         // Now take care of session management.
317         QSettings settings;
318         QString const key = "view-" + QString::number(id_);
319 #ifdef Q_WS_X11
320         QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
321         QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
322         resize(size);
323         move(pos);
324 #else
325         if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
326                 setGeometry(50, 50, 690, 510);
327 #endif
328         setIconSize(settings.value(key + "/icon_size").toSize());
329 }
330
331
332 GuiView::~GuiView()
333 {
334         delete &d;
335 }
336
337
338 void GuiView::setFocus()
339 {
340         if (d.current_work_area_)
341                 d.current_work_area_->setFocus();
342         else
343                 QWidget::setFocus();
344 }
345
346
347 QMenu * GuiView::createPopupMenu()
348 {
349         return d.toolBarPopup(this);
350 }
351
352
353 void GuiView::showEvent(QShowEvent * e)
354 {
355         LYXERR(Debug::GUI, "Passed Geometry "
356                 << size().height() << "x" << size().width()
357                 << "+" << pos().x() << "+" << pos().y());
358
359         if (d.splitter_->count() == 0)
360                 // No work area, switch to the background widget.
361                 d.setBackground();
362
363         QMainWindow::showEvent(e);
364 }
365
366
367 void GuiView::closeEvent(QCloseEvent * close_event)
368 {
369         while (Buffer * b = buffer()) {
370                 if (b->parent()) {
371                         // This is a child document, just close the tab after saving
372                         // but keep the file loaded.
373                         if (!saveBuffer(*b)) {
374                                 close_event->ignore();
375                                 return;
376                         }
377                         removeWorkArea(d.current_work_area_);
378                         continue;
379                 }
380
381                 std::vector<int> const & ids = guiApp->viewIds();
382                 for (size_type i = 0; i != ids.size(); ++i) {
383                         if (id_ == ids[i])
384                                 continue;
385                         if (guiApp->view(ids[i]).workArea(*b)) {
386                                 // FIXME 1: should we put an alert box here that the buffer
387                                 // is viewed elsewhere?
388                                 // FIXME 2: should we try to save this buffer in any case?
389                                 //saveBuffer(b);
390
391                                 // This buffer is also opened in another view, so
392                                 // but close the associated work area nevertheless.
393                                 removeWorkArea(d.current_work_area_);
394                                 // but don't close it.
395                                 b = 0;
396                                 break;
397                         }
398                 }
399                 if (b && !closeBuffer(*b)) {
400                         close_event->ignore();
401                         return;
402                 }
403         }
404
405         // Make sure that no LFUN use this close to be closed View.
406         theLyXFunc().setLyXView(0);
407
408         // Save toolbars configuration
409         if (isFullScreen()) {
410                 d.toolbars_->toggleFullScreen(!isFullScreen());
411                 updateToolbars();
412         }
413
414         // Make sure the timer time out will not trigger a statusbar update.
415         d.statusbar_timer_.stop();
416
417         // Saving fullscreen requires additional tweaks in the toolbar code.
418         // It wouldn't also work under linux natively.
419         if (lyxrc.allow_geometry_session && !isFullScreen()) {
420                 QSettings settings;
421                 QString const key = "view-" + QString::number(id_);
422 #ifdef Q_WS_X11
423                 settings.setValue(key + "/pos", pos());
424                 settings.setValue(key + "/size", size());
425 #else
426                 settings.setValue(key + "/geometry", saveGeometry());
427 #endif
428                 settings.setValue(key + "/icon_size", iconSize());
429                 d.toolbars_->saveToolbarInfo();
430                 // Now take care of all other dialogs:
431                 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
432                 for (; it!= d.dialogs_.end(); ++it)
433                         it->second->saveSession();
434         }
435
436         guiApp->unregisterView(id_);
437         close_event->accept();
438 }
439
440
441 void GuiView::dragEnterEvent(QDragEnterEvent * event)
442 {
443         if (event->mimeData()->hasUrls())
444                 event->accept();
445         /// \todo Ask lyx-devel is this is enough:
446         /// if (event->mimeData()->hasFormat("text/plain"))
447         ///     event->acceptProposedAction();
448 }
449
450
451 void GuiView::dropEvent(QDropEvent* event)
452 {
453         QList<QUrl> files = event->mimeData()->urls();
454         if (files.isEmpty())
455                 return;
456
457         LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
458         for (int i = 0; i != files.size(); ++i) {
459                 string const file = os::internal_path(fromqstr(
460                         files.at(i).toLocalFile()));
461                 if (!file.empty())
462                         lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
463         }
464 }
465
466
467 void GuiView::message(docstring const & str)
468 {
469         if (ForkedProcess::iAmAChild())
470                 return;
471
472         statusBar()->showMessage(toqstr(str));
473         d.statusbar_timer_.stop();
474         d.statusbar_timer_.start(3000);
475 }
476
477
478 void GuiView::smallSizedIcons()
479 {
480         setIconSize(QSize(d.smallIconSize, d.smallIconSize));
481 }
482
483
484 void GuiView::normalSizedIcons()
485 {
486         setIconSize(QSize(d.normalIconSize, d.normalIconSize));
487 }
488
489
490 void GuiView::bigSizedIcons()
491 {
492         setIconSize(QSize(d.bigIconSize, d.bigIconSize));
493 }
494
495
496 void GuiView::clearMessage()
497 {
498         if (!hasFocus())
499                 return;
500         theLyXFunc().setLyXView(this);
501         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
502         d.statusbar_timer_.stop();
503 }
504
505
506 void GuiView::updateWindowTitle(GuiWorkArea * wa)
507 {
508         if (wa != d.current_work_area_)
509                 return;
510         setWindowTitle(qt_("LyX: ") + wa->windowTitle());
511         setWindowIconText(wa->windowIconText());
512 }
513
514
515 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
516 {
517         disconnectBuffer();
518         disconnectBufferView();
519         connectBufferView(wa->bufferView());
520         connectBuffer(wa->bufferView().buffer());
521         d.current_work_area_ = wa;
522         QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
523                 this, SLOT(updateWindowTitle(GuiWorkArea *)));
524         updateWindowTitle(wa);
525
526         updateToc();
527         // Buffer-dependent dialogs should be updated or
528         // hidden. This should go here because some dialogs (eg ToC)
529         // require bv_->text.
530         updateBufferDependent(true);
531         updateToolbars();
532         updateLayoutList();
533         updateStatusBar();
534 }
535
536
537 void GuiView::on_lastWorkAreaRemoved()
538 {
539 #ifdef Q_WS_MAC
540         // On Mac close the view if there is no Tab open anymore,
541         // but only if no splitter is visible
542         if (d.splitter_->count() == 1) {
543                 TabWorkArea * twa = qobject_cast<TabWorkArea *>(d.splitter_->widget(0));
544                 if (twa && twa->count() == 0) {
545                         // close the view, as no tab is open anymore
546                         QTimer::singleShot(0, this, SLOT(close()));
547                 }
548         }
549 #endif
550 }
551
552
553 void GuiView::updateStatusBar()
554 {
555         // let the user see the explicit message
556         if (d.statusbar_timer_.isActive())
557                 return;
558
559         theLyXFunc().setLyXView(this);
560         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
561 }
562
563
564 bool GuiView::hasFocus() const
565 {
566         return qApp->activeWindow() == this;
567 }
568
569
570 bool GuiView::event(QEvent * e)
571 {
572         switch (e->type())
573         {
574         // Useful debug code:
575         //case QEvent::ActivationChange:
576         //case QEvent::WindowDeactivate:
577         //case QEvent::Paint:
578         //case QEvent::Enter:
579         //case QEvent::Leave:
580         //case QEvent::HoverEnter:
581         //case QEvent::HoverLeave:
582         //case QEvent::HoverMove:
583         //case QEvent::StatusTip:
584         //case QEvent::DragEnter:
585         //case QEvent::DragLeave:
586         //case QEvent::Drop:
587         //      break;
588
589         case QEvent::WindowActivate: {
590                 if (this == guiApp->currentView()) {
591                         setFocus();
592                         return QMainWindow::event(e);
593                 }
594                 guiApp->setCurrentView(*this);
595                 if (d.current_work_area_) {
596                         BufferView & bv = d.current_work_area_->bufferView();
597                         connectBufferView(bv);
598                         connectBuffer(bv.buffer());
599                         // The document structure, name and dialogs might have
600                         // changed in another view.
601                         updateBufferDependent(true);
602                         updateToolbars();
603                         updateLayoutList();
604                         updateStatusBar();
605                 } else {
606                         setWindowTitle(qt_("LyX"));
607                         setWindowIconText(qt_("LyX"));
608                 }
609                 setFocus();
610                 return QMainWindow::event(e);
611         }
612
613         case QEvent::ShortcutOverride: {
614                 if (d.current_work_area_)
615                         // Nothing special to do.
616                         return QMainWindow::event(e);
617
618                 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
619
620                 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
621                 // between controls.
622                 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab 
623                         || ke->key() == Qt::Key_Backtab)
624                         return QMainWindow::event(e);
625
626                 // Allow processing of shortcuts that are allowed even when no Buffer
627                 // is viewed.
628                 theLyXFunc().setLyXView(this);
629                 KeySymbol sym;
630                 setKeySymbol(&sym, ke);
631                 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
632                 e->accept();
633                 return true;
634         }
635
636         default:
637                 return QMainWindow::event(e);
638         }
639 }
640
641
642 bool GuiView::focusNextPrevChild(bool /*next*/)
643 {
644         setFocus();
645         return true;
646 }
647
648
649 void GuiView::setBusy(bool busy)
650 {
651         if (d.current_work_area_) {
652                 d.current_work_area_->setUpdatesEnabled(!busy);
653                 if (busy)
654                         d.current_work_area_->stopBlinkingCursor();
655                 else
656                         d.current_work_area_->startBlinkingCursor();
657         }
658
659         if (busy)
660                 QApplication::setOverrideCursor(Qt::WaitCursor);
661         else
662                 QApplication::restoreOverrideCursor();
663 }
664
665
666 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
667 {
668         GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
669
670         if (tbinfo.flags & ToolbarInfo::TOP) {
671                 if (newline)
672                         addToolBarBreak(Qt::TopToolBarArea);
673                 addToolBar(Qt::TopToolBarArea, toolBar);
674         }
675
676         if (tbinfo.flags & ToolbarInfo::BOTTOM) {
677 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
678 #if (QT_VERSION >= 0x040202)
679                 if (newline)
680                         addToolBarBreak(Qt::BottomToolBarArea);
681 #endif
682                 addToolBar(Qt::BottomToolBarArea, toolBar);
683         }
684
685         if (tbinfo.flags & ToolbarInfo::LEFT) {
686 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
687 #if (QT_VERSION >= 0x040202)
688                 if (newline)
689                         addToolBarBreak(Qt::LeftToolBarArea);
690 #endif
691                 addToolBar(Qt::LeftToolBarArea, toolBar);
692         }
693
694         if (tbinfo.flags & ToolbarInfo::RIGHT) {
695 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
696 #if (QT_VERSION >= 0x040202)
697                 if (newline)
698                         addToolBarBreak(Qt::RightToolBarArea);
699 #endif
700                 addToolBar(Qt::RightToolBarArea, toolBar);
701         }
702
703         // The following does not work so I cannot restore to exact toolbar location
704         /*
705         ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
706         toolBar->move(tbinfo.posx, tbinfo.posy);
707         */
708
709         return toolBar;
710 }
711
712
713 GuiWorkArea * GuiView::workArea(Buffer & buffer)
714 {
715         if (TabWorkArea * twa = d.currentTabWorkArea())
716                 return twa->workArea(buffer);
717         return 0;
718 }
719
720
721 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
722 {
723         // Automatically create a TabWorkArea if there are none yet.
724         TabWorkArea * tab_widget = d.splitter_->count() 
725                 ? d.currentTabWorkArea() : addTabWorkArea();
726         return tab_widget->addWorkArea(buffer, *this);
727 }
728
729
730 TabWorkArea * GuiView::addTabWorkArea()
731 {
732         TabWorkArea * twa = new TabWorkArea;
733         QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
734                 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
735         QObject::connect(twa, SIGNAL(lastWorkAreaRemoved()),
736                          this, SLOT(on_lastWorkAreaRemoved()));
737
738         d.splitter_->addWidget(twa);
739         d.stack_widget_->setCurrentWidget(d.splitter_);
740         return twa;
741 }
742
743
744 GuiWorkArea const * GuiView::currentWorkArea() const
745 {
746         return d.current_work_area_;
747 }
748
749
750 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
751 {
752         BOOST_ASSERT(wa);
753
754         // Changing work area can result from opening a file so
755         // update the toc in any case.
756         updateToc();
757
758         d.current_work_area_ = wa;
759         for (int i = 0; i != d.splitter_->count(); ++i) {
760                 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
761                         return;
762         }
763 }
764
765
766 void GuiView::removeWorkArea(GuiWorkArea * wa)
767 {
768         BOOST_ASSERT(wa);
769         if (wa == d.current_work_area_) {
770                 disconnectBuffer();
771                 disconnectBufferView();
772                 hideBufferDependent();
773                 d.current_work_area_ = 0;
774         }
775
776         for (int i = 0; i != d.splitter_->count(); ++i) {
777                 TabWorkArea * twa = d.tabWorkArea(i);
778                 if (!twa->removeWorkArea(wa))
779                         // Not found in this tab group.
780                         continue;
781
782                 // We found and removed the GuiWorkArea.
783                 if (!twa->count()) {
784                         // No more WorkAreas in this tab group, so delete it.
785                         delete twa;
786                         break;
787                 }
788
789                 if (d.current_work_area_)
790                         // This means that we are not closing the current GuiWorkArea;
791                         break;
792
793                 // Switch to the next GuiWorkArea in the found TabWorkArea.
794                 d.current_work_area_ = twa->currentWorkArea();
795                 break;
796         }
797
798         if (d.splitter_->count() == 0)
799                 // No more work area, switch to the background widget.
800                 d.setBackground();
801 }
802
803
804 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
805 {
806         d.layout_ = layout;
807 }
808
809
810 void GuiView::updateLayoutList()
811 {
812         if (d.layout_)
813                 d.layout_->updateContents(false);
814 }
815
816
817 void GuiView::updateToolbars()
818 {
819         if (d.current_work_area_) {
820                 bool const math =
821                         d.current_work_area_->bufferView().cursor().inMathed();
822                 bool const table =
823                         lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
824                 bool const review =
825                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
826                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
827                 bool const mathmacrotemplate =
828                         lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
829
830                 d.toolbars_->update(math, table, review, mathmacrotemplate);
831         } else
832                 d.toolbars_->update(false, false, false, false);
833
834         // update read-only status of open dialogs.
835         checkStatus();
836 }
837
838
839 Buffer * GuiView::buffer()
840 {
841         if (d.current_work_area_)
842                 return &d.current_work_area_->bufferView().buffer();
843         return 0;
844 }
845
846
847 Buffer const * GuiView::buffer() const
848 {
849         if (d.current_work_area_)
850                 return &d.current_work_area_->bufferView().buffer();
851         return 0;
852 }
853
854
855 void GuiView::setBuffer(Buffer * newBuffer)
856 {
857         BOOST_ASSERT(newBuffer);
858         setBusy(true);
859
860         GuiWorkArea * wa = workArea(*newBuffer);
861         if (wa == 0) {
862                 updateLabels(*newBuffer->masterBuffer());
863                 wa = addWorkArea(*newBuffer);
864         } else {
865                 //Disconnect the old buffer...there's no new one.
866                 disconnectBuffer();
867         }
868         connectBuffer(*newBuffer);
869         connectBufferView(wa->bufferView());
870         setCurrentWorkArea(wa);
871
872         setBusy(false);
873 }
874
875
876 void GuiView::connectBuffer(Buffer & buf)
877 {
878         buf.setGuiDelegate(this);
879 }
880
881
882 void GuiView::disconnectBuffer()
883 {
884         if (d.current_work_area_)
885                 d.current_work_area_->bufferView().setGuiDelegate(0);
886 }
887
888
889 void GuiView::connectBufferView(BufferView & bv)
890 {
891         bv.setGuiDelegate(this);
892 }
893
894
895 void GuiView::disconnectBufferView()
896 {
897         if (d.current_work_area_)
898                 d.current_work_area_->bufferView().setGuiDelegate(0);
899 }
900
901
902 void GuiView::errors(string const & error_type)
903 {
904         ErrorList & el = buffer()->errorList(error_type);
905         if (!el.empty())
906                 showDialog("errorlist", error_type);
907 }
908
909
910 void GuiView::updateDialog(string const & name, string const & data)
911 {
912         if (!isDialogVisible(name))
913                 return;
914
915         map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
916         if (it == d.dialogs_.end())
917                 return;
918
919         Dialog * const dialog = it->second.get();
920         if (dialog->isVisibleView())
921                 dialog->updateData(data);
922 }
923
924
925 BufferView * GuiView::view()
926 {
927         return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
928 }
929
930
931 void GuiView::updateToc()
932 {
933         updateDialog("toc", "");
934 }
935
936
937 void GuiView::updateEmbeddedFiles()
938 {
939         updateDialog("embedding", "");
940 }
941
942
943 void GuiView::autoSave()
944 {
945         LYXERR(Debug::INFO, "Running autoSave()");
946
947         if (buffer())
948                 view()->buffer().autoSave();
949 }
950
951
952 void GuiView::resetAutosaveTimers()
953 {
954         if (lyxrc.autosave)
955                 d.autosave_timeout_.restart();
956 }
957
958
959 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
960 {
961         FuncStatus flag;
962         bool enable = true;
963         Buffer * buf = buffer();
964
965         /* In LyX/Mac, when a dialog is open, the menus of the
966            application can still be accessed without giving focus to
967            the main window. In this case, we want to disable the menu
968            entries that are buffer-related.
969
970            Note that this code is not perfect, as bug 1941 attests:
971            http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
972         */
973         if (cmd.origin == FuncRequest::MENU && !hasFocus())
974                 buf = 0;
975
976         switch(cmd.action) {
977         case LFUN_BUFFER_WRITE:
978                 enable = buf && (buf->isUnnamed() || !buf->isClean());
979                 break;
980
981         case LFUN_BUFFER_WRITE_AS:
982                 enable = buf;
983                 break;
984
985         case LFUN_SPLIT_VIEW:
986                 enable = buf;
987                 break;
988
989         case LFUN_CLOSE_TAB_GROUP:
990                 enable = d.currentTabWorkArea();
991                 break;
992
993         case LFUN_TOOLBAR_TOGGLE:
994                 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
995                 break;
996
997         case LFUN_DIALOG_TOGGLE:
998                 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
999                 // fall through to set "enable"
1000         case LFUN_DIALOG_SHOW: {
1001                 string const name = cmd.getArg(0);
1002                 if (!buf)
1003                         enable = name == "aboutlyx"
1004                                 || name == "file" //FIXME: should be removed.
1005                                 || name == "prefs"
1006                                 || name == "texinfo";
1007                 else if (name == "print")
1008                         enable = buf->isExportable("dvi")
1009                                 && lyxrc.print_command != "none";
1010                 else if (name == "character") {
1011                         if (!view())
1012                                 enable = false;
1013                         else {
1014                                 InsetCode ic = view()->cursor().inset().lyxCode();
1015                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1016                         }
1017                 }
1018                 else if (name == "symbols") {
1019                         if (!view() || view()->cursor().inMathed())
1020                                 enable = false;
1021                         else {
1022                                 InsetCode ic = view()->cursor().inset().lyxCode();
1023                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1024                         }
1025                 }
1026                 else if (name == "latexlog")
1027                         enable = FileName(buf->logName()).isReadableFile();
1028                 else if (name == "spellchecker")
1029 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1030                         enable = !buf->isReadonly();
1031 #else
1032                         enable = false;
1033 #endif
1034                 else if (name == "vclog")
1035                         enable = buf->lyxvc().inUse();
1036                 break;
1037         }
1038
1039         case LFUN_DIALOG_UPDATE: {
1040                 string const name = cmd.getArg(0);
1041                 if (!buf)
1042                         enable = name == "prefs";
1043                 break;
1044         }
1045
1046         case LFUN_INSET_APPLY: {
1047                 if (!buf) {
1048                         enable = false;
1049                         break;
1050                 }
1051                 string const name = cmd.getArg(0);
1052                 Inset * inset = getOpenInset(name);
1053                 if (inset) {
1054                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1055                         FuncStatus fs;
1056                         if (!inset->getStatus(view()->cursor(), fr, fs)) {
1057                                 // Every inset is supposed to handle this
1058                                 BOOST_ASSERT(false);
1059                         }
1060                         flag |= fs;
1061                 } else {
1062                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1063                         flag |= getStatus(fr);
1064                 }
1065                 enable = flag.enabled();
1066                 break;
1067         }
1068
1069         case LFUN_COMPLETION_INLINE:
1070                 if (!d.current_work_area_
1071                     || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1072                     enable = false;
1073                 break;
1074
1075         case LFUN_COMPLETION_POPUP:
1076                 if (!d.current_work_area_
1077                     || !d.current_work_area_->completer().popupPossible(view()->cursor()))
1078                     enable = false;
1079                 break;
1080
1081         case LFUN_COMPLETION_COMPLETE:
1082                 if (!d.current_work_area_
1083                         || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1084                     enable = false;
1085                 break;
1086
1087         default:
1088                 if (!view()) {
1089                         enable = false;
1090                         break;
1091                 }
1092         }
1093
1094         if (!enable)
1095                 flag.enabled(false);
1096
1097         return flag;
1098 }
1099
1100
1101 static FileName selectTemplateFile()
1102 {
1103         FileDialog dlg(qt_("Select template file"));
1104         dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1105         dlg.setButton1(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1106
1107         FileDialog::Result result =
1108                 dlg.open(toqstr(lyxrc.template_path),
1109                              FileFilterList(_("LyX Documents (*.lyx)")));
1110
1111         if (result.first == FileDialog::Later)
1112                 return FileName();
1113         if (result.second.isEmpty())
1114                 return FileName();
1115         return FileName(fromqstr(result.second));
1116 }
1117
1118
1119 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1120 {
1121         setBusy(true);
1122
1123         Buffer * newBuffer = checkAndLoadLyXFile(filename);
1124
1125         if (!newBuffer) {
1126                 message(_("Document not loaded."));
1127                 setBusy(false);
1128                 return 0;
1129         }
1130         
1131         setBuffer(newBuffer);
1132
1133         // scroll to the position when the file was last closed
1134         if (lyxrc.use_lastfilepos) {
1135                 LastFilePosSection::FilePos filepos =
1136                         LyX::ref().session().lastFilePos().load(filename);
1137                 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1138         }
1139
1140         if (tolastfiles)
1141                 LyX::ref().session().lastFiles().add(filename);
1142
1143         setBusy(false);
1144         return newBuffer;
1145 }
1146
1147
1148 void GuiView::openDocument(string const & fname)
1149 {
1150         string initpath = lyxrc.document_path;
1151
1152         if (buffer()) {
1153                 string const trypath = buffer()->filePath();
1154                 // If directory is writeable, use this as default.
1155                 if (FileName(trypath).isDirWritable())
1156                         initpath = trypath;
1157         }
1158
1159         string filename;
1160
1161         if (fname.empty()) {
1162                 FileDialog dlg(qt_("Select document to open"), LFUN_FILE_OPEN);
1163                 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1164                 dlg.setButton2(qt_("Examples|#E#e"),
1165                                 toqstr(addPath(package().system_support().absFilename(), "examples")));
1166
1167                 FileDialog::Result result =
1168                         dlg.open(toqstr(initpath), FileFilterList(_("LyX Documents (*.lyx)")));
1169
1170                 if (result.first == FileDialog::Later)
1171                         return;
1172
1173                 filename = fromqstr(result.second);
1174
1175                 // check selected filename
1176                 if (filename.empty()) {
1177                         message(_("Canceled."));
1178                         return;
1179                 }
1180         } else
1181                 filename = fname;
1182
1183         // get absolute path of file and add ".lyx" to the filename if
1184         // necessary. 
1185         FileName const fullname = 
1186                         fileSearch(string(), filename, "lyx", support::may_not_exist);
1187         if (!fullname.empty())
1188                 filename = fullname.absFilename();
1189
1190         // if the file doesn't exist, let the user create one
1191         if (!fullname.exists()) {
1192                 // the user specifically chose this name. Believe him.
1193                 Buffer * const b = newFile(filename, string(), true);
1194                 if (b)
1195                         setBuffer(b);
1196                 return;
1197         }
1198
1199         docstring const disp_fn = makeDisplayPath(filename);
1200         message(bformat(_("Opening document %1$s..."), disp_fn));
1201
1202         docstring str2;
1203         Buffer * buf = loadDocument(fullname);
1204         if (buf) {
1205                 updateLabels(*buf);
1206                 
1207                 setBuffer(buf);
1208                 buf->errors("Parse");
1209                 str2 = bformat(_("Document %1$s opened."), disp_fn);
1210         } else {
1211                 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1212         }
1213         message(str2);
1214 }
1215
1216 // FIXME: clean that
1217 static bool import(GuiView * lv, FileName const & filename,
1218         string const & format, ErrorList & errorList)
1219 {
1220         FileName const lyxfile(support::changeExtension(filename.absFilename(), ".lyx"));
1221
1222         string loader_format;
1223         vector<string> loaders = theConverters().loaders();
1224         if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1225                 for (vector<string>::const_iterator it = loaders.begin();
1226                      it != loaders.end(); ++it) {
1227                         if (!theConverters().isReachable(format, *it))
1228                                 continue;
1229
1230                         string const tofile =
1231                                 support::changeExtension(filename.absFilename(),
1232                                 formats.extension(*it));
1233                         if (!theConverters().convert(0, filename, FileName(tofile),
1234                                 filename, format, *it, errorList))
1235                                 return false;
1236                         loader_format = *it;
1237                         break;
1238                 }
1239                 if (loader_format.empty()) {
1240                         frontend::Alert::error(_("Couldn't import file"),
1241                                      bformat(_("No information for importing the format %1$s."),
1242                                          formats.prettyName(format)));
1243                         return false;
1244                 }
1245         } else
1246                 loader_format = format;
1247
1248         if (loader_format == "lyx") {
1249                 Buffer * buf = lv->loadDocument(lyxfile);
1250                 if (!buf)
1251                         return false;
1252                 updateLabels(*buf);
1253                 lv->setBuffer(buf);
1254                 buf->errors("Parse");
1255         } else {
1256                 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1257                 if (!b)
1258                         return false;
1259                 lv->setBuffer(b);
1260                 bool as_paragraphs = loader_format == "textparagraph";
1261                 string filename2 = (loader_format == format) ? filename.absFilename()
1262                         : support::changeExtension(filename.absFilename(),
1263                                           formats.extension(loader_format));
1264                 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1265                 theLyXFunc().setLyXView(lv);
1266                 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1267         }
1268
1269         return true;
1270 }
1271
1272
1273 void GuiView::importDocument(string const & argument)
1274 {
1275         string format;
1276         string filename = split(argument, format, ' ');
1277
1278         LYXERR(Debug::INFO, format << " file: " << filename);
1279
1280         // need user interaction
1281         if (filename.empty()) {
1282                 string initpath = lyxrc.document_path;
1283
1284                 Buffer const * buf = buffer();
1285                 if (buf) {
1286                         string const trypath = buf->filePath();
1287                         // If directory is writeable, use this as default.
1288                         if (FileName(trypath).isDirWritable())
1289                                 initpath = trypath;
1290                 }
1291
1292                 docstring const text = bformat(_("Select %1$s file to import"),
1293                         formats.prettyName(format));
1294
1295                 FileDialog dlg(toqstr(text), LFUN_BUFFER_IMPORT);
1296                 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1297                 dlg.setButton2(qt_("Examples|#E#e"),
1298                         toqstr(addPath(package().system_support().absFilename(), "examples")));
1299
1300                 docstring filter = formats.prettyName(format);
1301                 filter += " (*.";
1302                 // FIXME UNICODE
1303                 filter += from_utf8(formats.extension(format));
1304                 filter += ')';
1305
1306                 FileDialog::Result result =
1307                         dlg.open(toqstr(initpath), FileFilterList(filter));
1308
1309                 if (result.first == FileDialog::Later)
1310                         return;
1311
1312                 filename = fromqstr(result.second);
1313
1314                 // check selected filename
1315                 if (filename.empty())
1316                         message(_("Canceled."));
1317         }
1318
1319         if (filename.empty())
1320                 return;
1321
1322         // get absolute path of file
1323         FileName const fullname(makeAbsPath(filename));
1324
1325         FileName const lyxfile(support::changeExtension(fullname.absFilename(), ".lyx"));
1326
1327         // Check if the document already is open
1328         Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1329         if (buf) {
1330                 setBuffer(buf);
1331                 if (!closeBuffer()) {
1332                         message(_("Canceled."));
1333                         return;
1334                 }
1335         }
1336
1337         docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1338
1339         // if the file exists already, and we didn't do
1340         // -i lyx thefile.lyx, warn
1341         if (lyxfile.exists() && fullname != lyxfile) {
1342
1343                 docstring text = bformat(_("The document %1$s already exists.\n\n"
1344                         "Do you want to overwrite that document?"), displaypath);
1345                 int const ret = Alert::prompt(_("Overwrite document?"),
1346                         text, 0, 1, _("&Overwrite"), _("&Cancel"));
1347
1348                 if (ret == 1) {
1349                         message(_("Canceled."));
1350                         return;
1351                 }
1352         }
1353
1354         message(bformat(_("Importing %1$s..."), displaypath));
1355         ErrorList errorList;
1356         if (import(this, fullname, format, errorList))
1357                 message(_("imported."));
1358         else
1359                 message(_("file not imported!"));
1360
1361         // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1362 }
1363
1364
1365 void GuiView::newDocument(string const & filename, bool from_template)
1366 {
1367         FileName initpath(lyxrc.document_path);
1368         Buffer * buf = buffer();
1369         if (buf) {
1370                 FileName const trypath(buf->filePath());
1371                 // If directory is writeable, use this as default.
1372                 if (trypath.isDirWritable())
1373                         initpath = trypath;
1374         }
1375
1376         string templatefile = from_template ?
1377                 selectTemplateFile().absFilename() : string();
1378         Buffer * b;
1379         if (filename.empty())
1380                 b = newUnnamedFile(templatefile, initpath);
1381         else
1382                 b = newFile(filename, templatefile, true);
1383
1384         if (b)
1385                 setBuffer(b);
1386         // Ensure the cursor is correctly positionned on screen.
1387         view()->showCursor();
1388 }
1389
1390
1391 void GuiView::insertLyXFile(docstring const & fname)
1392 {
1393         BufferView * bv = view();
1394         if (!bv)
1395                 return;
1396
1397         // FIXME UNICODE
1398         FileName filename(to_utf8(fname));
1399         
1400         if (!filename.empty()) {
1401                 bv->insertLyXFile(filename);
1402                 return;
1403         }
1404
1405         // Launch a file browser
1406         // FIXME UNICODE
1407         string initpath = lyxrc.document_path;
1408         string const trypath = bv->buffer().filePath();
1409         // If directory is writeable, use this as default.
1410         if (FileName(trypath).isDirWritable())
1411                 initpath = trypath;
1412
1413         // FIXME UNICODE
1414         FileDialog dlg(qt_("Select LyX document to insert"), LFUN_FILE_INSERT);
1415         dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1416         dlg.setButton2(qt_("Examples|#E#e"),
1417                 toqstr(addPath(package().system_support().absFilename(),
1418                 "examples")));
1419
1420         FileDialog::Result result =
1421                 dlg.open(toqstr(initpath),
1422                              FileFilterList(_("LyX Documents (*.lyx)")));
1423
1424         if (result.first == FileDialog::Later)
1425                 return;
1426
1427         // FIXME UNICODE
1428         filename.set(fromqstr(result.second));
1429
1430         // check selected filename
1431         if (filename.empty()) {
1432                 // emit message signal.
1433                 message(_("Canceled."));
1434                 return;
1435         }
1436
1437         bv->insertLyXFile(filename);
1438 }
1439
1440
1441 void GuiView::insertPlaintextFile(docstring const & fname,
1442         bool asParagraph)
1443 {
1444         BufferView * bv = view();
1445         if (!bv)
1446                 return;
1447
1448         // FIXME UNICODE
1449         FileName filename(to_utf8(fname));
1450         
1451         if (!filename.empty()) {
1452                 bv->insertPlaintextFile(filename, asParagraph);
1453                 return;
1454         }
1455
1456         FileDialog dlg(qt_("Select file to insert"), (asParagraph ?
1457                 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1458
1459         FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
1460                 FileFilterList());
1461
1462         if (result.first == FileDialog::Later)
1463                 return;
1464
1465         // FIXME UNICODE
1466         filename.set(fromqstr(result.second));
1467
1468         // check selected filename
1469         if (filename.empty()) {
1470                 // emit message signal.
1471                 message(_("Canceled."));
1472                 return;
1473         }
1474
1475         bv->insertPlaintextFile(filename, asParagraph);
1476 }
1477
1478
1479 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1480 {
1481         FileName fname = b.fileName();
1482         FileName const oldname = fname;
1483
1484         if (!newname.empty()) {
1485                 // FIXME UNICODE
1486                 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1487         } else {
1488                 // Switch to this Buffer.
1489                 setBuffer(&b);
1490
1491                 /// No argument? Ask user through dialog.
1492                 // FIXME UNICODE
1493                 FileDialog dlg(qt_("Choose a filename to save document as"),
1494                                    LFUN_BUFFER_WRITE_AS);
1495                 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1496                 dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1497
1498                 if (!isLyXFilename(fname.absFilename()))
1499                         fname.changeExtension(".lyx");
1500
1501                 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1502
1503                 FileDialog::Result result =
1504                         dlg.save(toqstr(fname.onlyPath().absFilename()),
1505                                      filter,
1506                                      toqstr(fname.onlyFileName()));
1507
1508                 if (result.first == FileDialog::Later)
1509                         return false;
1510
1511                 fname.set(fromqstr(result.second));
1512
1513                 if (fname.empty())
1514                         return false;
1515
1516                 if (!isLyXFilename(fname.absFilename()))
1517                         fname.changeExtension(".lyx");
1518         }
1519
1520         if (FileName(fname).exists()) {
1521                 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1522                 docstring text = bformat(_("The document %1$s already "
1523                                            "exists.\n\nDo you want to "
1524                                            "overwrite that document?"), 
1525                                          file);
1526                 int const ret = Alert::prompt(_("Overwrite document?"),
1527                         text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1528                 switch (ret) {
1529                 case 0: break;
1530                 case 1: return renameBuffer(b, docstring());
1531                 case 2: return false;
1532                 }
1533         }
1534
1535         // Ok, change the name of the buffer
1536         b.setFileName(fname.absFilename());
1537         b.markDirty();
1538         bool unnamed = b.isUnnamed();
1539         b.setUnnamed(false);
1540         b.saveCheckSum(fname);
1541
1542         if (!saveBuffer(b)) {
1543                 b.setFileName(oldname.absFilename());
1544                 b.setUnnamed(unnamed);
1545                 b.saveCheckSum(oldname);
1546                 return false;
1547         }
1548
1549         return true;
1550 }
1551
1552
1553 bool GuiView::saveBuffer(Buffer & b)
1554 {
1555         if (b.isUnnamed())
1556                 return renameBuffer(b, docstring());
1557
1558         if (b.save()) {
1559                 LyX::ref().session().lastFiles().add(b.fileName());
1560                 return true;
1561         }
1562
1563         // Switch to this Buffer.
1564         setBuffer(&b);
1565
1566         // FIXME: we don't tell the user *WHY* the save failed !!
1567         docstring const file = makeDisplayPath(b.absFileName(), 30);
1568         docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1569                                    "Do you want to rename the document and "
1570                                    "try again?"), file);
1571         int const ret = Alert::prompt(_("Rename and save?"),
1572                 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1573         switch (ret) {
1574         case 0:
1575                 if (!renameBuffer(b, docstring()))
1576                         return false;
1577                 break;
1578         case 1:
1579                 break;
1580         case 2:
1581                 return false;
1582         }
1583
1584         return saveBuffer(b);
1585 }
1586
1587
1588 bool GuiView::closeBuffer()
1589 {
1590         Buffer * buf = buffer();
1591         return buf && closeBuffer(*buf);
1592 }
1593
1594
1595 bool GuiView::closeBuffer(Buffer & buf)
1596 {
1597         // goto bookmark to update bookmark pit.
1598         //FIXME: we should update only the bookmarks related to this buffer!
1599         for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
1600                 theLyXFunc().gotoBookmark(i+1, false, false);
1601
1602         if (buf.isClean() || buf.paragraphs().empty()) {
1603                 if (buf.masterBuffer() == &buf)
1604                         LyX::ref().session().lastOpened().add(buf.fileName());
1605                 theBufferList().release(&buf);
1606                 return true;
1607         }
1608         // Switch to this Buffer.
1609         setBuffer(&buf);
1610
1611         docstring file;
1612         // FIXME: Unicode?
1613         if (buf.isUnnamed())
1614                 file = from_utf8(buf.fileName().onlyFileName());
1615         else
1616                 file = buf.fileName().displayName(30);
1617
1618         // Bring this window to top before asking questions.
1619         raise();
1620         activateWindow();
1621
1622         docstring const text = bformat(_("The document %1$s has unsaved changes."
1623                 "\n\nDo you want to save the document or discard the changes?"), file);
1624         int const ret = Alert::prompt(_("Save changed document?"),
1625                 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1626
1627         switch (ret) {
1628         case 0:
1629                 if (!saveBuffer(buf))
1630                         return false;
1631                 break;
1632         case 1:
1633                 // if we crash after this we could
1634                 // have no autosave file but I guess
1635                 // this is really improbable (Jug)
1636                 removeAutosaveFile(buf.absFileName());
1637                 break;
1638         case 2:
1639                 return false;
1640         }
1641
1642         // save file names to .lyx/session
1643         // if master/slave are both open, do not save slave since it
1644         // will be automatically loaded when the master is loaded
1645         if (buf.masterBuffer() == &buf)
1646                 LyX::ref().session().lastOpened().add(buf.fileName());
1647
1648         theBufferList().release(&buf);
1649         return true;
1650 }
1651
1652
1653 bool GuiView::dispatch(FuncRequest const & cmd)
1654 {
1655         BufferView * bv = view();       
1656         // By default we won't need any update.
1657         if (bv)
1658                 bv->cursor().updateFlags(Update::None);
1659
1660         switch(cmd.action) {
1661                 case LFUN_BUFFER_IMPORT:
1662                         importDocument(to_utf8(cmd.argument()));
1663                         break;
1664
1665                 case LFUN_BUFFER_SWITCH:
1666                         setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1667                         break;
1668
1669                 case LFUN_BUFFER_NEXT:
1670                         setBuffer(theBufferList().next(buffer()));
1671                         break;
1672
1673                 case LFUN_BUFFER_PREVIOUS:
1674                         setBuffer(theBufferList().previous(buffer()));
1675                         break;
1676
1677                 case LFUN_COMMAND_EXECUTE: {
1678                         bool const show_it = cmd.argument() != "off";
1679                         d.toolbars_->showCommandBuffer(show_it);
1680                         break;
1681                 }
1682                 case LFUN_DROP_LAYOUTS_CHOICE:
1683                         if (d.layout_)
1684                                 d.layout_->showPopup();
1685                         break;
1686
1687                 case LFUN_MENU_OPEN:
1688                         if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument()), *this))
1689                                 menu->exec(QCursor::pos());
1690                         break;
1691
1692                 case LFUN_FILE_INSERT:
1693                         insertLyXFile(cmd.argument());
1694                         break;
1695                 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1696                         insertPlaintextFile(cmd.argument(), true);
1697                         break;
1698
1699                 case LFUN_FILE_INSERT_PLAINTEXT:
1700                         insertPlaintextFile(cmd.argument(), false);
1701                         break;
1702
1703                 case LFUN_BUFFER_WRITE:
1704                         if (bv)
1705                                 saveBuffer(bv->buffer());
1706                         break;
1707
1708                 case LFUN_BUFFER_WRITE_AS:
1709                         if (bv)
1710                                 renameBuffer(bv->buffer(), cmd.argument());
1711                         break;
1712
1713                 case LFUN_BUFFER_WRITE_ALL: {
1714                         Buffer * first = theBufferList().first();
1715                         if (!first)
1716                                 break;
1717                         message(_("Saving all documents..."));
1718                         // We cannot use a for loop as the buffer list cycles.
1719                         Buffer * b = first;
1720                         do {
1721                                 if (b->isClean())
1722                                         continue;
1723                                 saveBuffer(*b);
1724                                 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1725                                 b = theBufferList().next(b);
1726                         } while (b != first); 
1727                         message(_("All documents saved."));
1728                         break;
1729                 }
1730
1731                 case LFUN_TOOLBAR_TOGGLE: {
1732                         string const name = cmd.getArg(0);
1733                         bool const allowauto = cmd.getArg(1) == "allowauto";
1734                         // it is possible to get current toolbar status like this,...
1735                         // but I decide to obey the order of ToolbarBackend::flags
1736                         // and disregard real toolbar status.
1737                         // toolbars_->saveToolbarInfo();
1738                         //
1739                         // toggle state on/off/auto
1740                         d.toolbars_->toggleToolbarState(name, allowauto);
1741                         // update toolbar
1742                         updateToolbars();
1743
1744                         ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1745                         if (!tbi) {
1746                                 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1747                                 break;
1748                         }
1749                         docstring state;
1750                         if (tbi->flags & ToolbarInfo::ON)
1751                                 state = _("on");
1752                         else if (tbi->flags & ToolbarInfo::OFF)
1753                                 state = _("off");
1754                         else if (tbi->flags & ToolbarInfo::AUTO)
1755                                 state = _("auto");
1756
1757                         message(bformat(_("Toolbar \"%1$s\" state set to %2$s"), 
1758                                            _(tbi->gui_name), state));
1759                         break;
1760                 }
1761
1762                 case LFUN_DIALOG_UPDATE: {
1763                         string const name = to_utf8(cmd.argument());
1764                         // Can only update a dialog connected to an existing inset
1765                         Inset * inset = getOpenInset(name);
1766                         if (inset) {
1767                                 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1768                                 inset->dispatch(view()->cursor(), fr);
1769                         } else if (name == "paragraph") {
1770                                 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1771                         } else if (name == "prefs") {
1772                                 updateDialog(name, string());
1773                         }
1774                         break;
1775                 }
1776
1777                 case LFUN_DIALOG_TOGGLE: {
1778                         if (isDialogVisible(cmd.getArg(0)))
1779                                 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1780                         else
1781                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1782                         break;
1783                 }
1784
1785                 case LFUN_DIALOG_DISCONNECT_INSET:
1786                         disconnectDialog(to_utf8(cmd.argument()));
1787                         break;
1788
1789                 case LFUN_DIALOG_HIDE: {
1790                         guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1791                         break;
1792                 }
1793
1794                 case LFUN_DIALOG_SHOW: {
1795                         string const name = cmd.getArg(0);
1796                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1797
1798                         if (name == "character") {
1799                                 data = freefont2string();
1800                                 if (!data.empty())
1801                                         showDialog("character", data);
1802                         } else if (name == "latexlog") {
1803                                 Buffer::LogType type; 
1804                                 string const logfile = buffer()->logName(&type);
1805                                 switch (type) {
1806                                 case Buffer::latexlog:
1807                                         data = "latex ";
1808                                         break;
1809                                 case Buffer::buildlog:
1810                                         data = "literate ";
1811                                         break;
1812                                 }
1813                                 data += Lexer::quoteString(logfile);
1814                                 showDialog("log", data);
1815                         } else if (name == "vclog") {
1816                                 string const data = "vc " +
1817                                         Lexer::quoteString(buffer()->lyxvc().getLogFile());
1818                                 showDialog("log", data);
1819                         } else if (name == "symbols") {
1820                                 data = bv->cursor().getEncoding()->name();
1821                                 if (!data.empty())
1822                                         showDialog("symbols", data);
1823                         } else
1824                                 showDialog(name, data);
1825                         break;
1826                 }
1827
1828                 case LFUN_INSET_APPLY: {
1829                         string const name = cmd.getArg(0);
1830                         Inset * inset = getOpenInset(name);
1831                         if (inset) {
1832                                 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1833                                 inset->dispatch(view()->cursor(), fr);
1834                         } else {
1835                                 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1836                                 lyx::dispatch(fr);
1837                         }
1838                         break;
1839                 }
1840
1841                 case LFUN_UI_TOGGLE:
1842                         lfunUiToggle(cmd);
1843                         // Make sure the keyboard focus stays in the work area.
1844                         setFocus();
1845                         break;
1846
1847                 case LFUN_COMPLETION_INLINE:
1848                         if (d.current_work_area_)
1849                                 d.current_work_area_->completer().showInline();
1850                         break;
1851
1852                 case LFUN_SPLIT_VIEW:
1853                         if (Buffer * buf = buffer()) {
1854                                 string const orientation = cmd.getArg(0);
1855                                 d.splitter_->setOrientation(orientation == "vertical"
1856                                         ? Qt::Vertical : Qt::Horizontal);
1857                                 TabWorkArea * twa = addTabWorkArea();
1858                                 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1859                                 setCurrentWorkArea(wa);
1860                         }
1861                         break;
1862
1863                 case LFUN_CLOSE_TAB_GROUP:
1864                         if (TabWorkArea * twa = d.currentTabWorkArea()) {
1865                                 delete twa;
1866                                 twa = d.currentTabWorkArea();
1867                                 // Switch to the next GuiWorkArea in the found TabWorkArea.
1868                                 d.current_work_area_ = twa? twa->currentWorkArea() : 0;
1869                                 if (d.splitter_->count() == 0)
1870                                         // No more work area, switch to the background widget.
1871                                         d.setBackground();
1872                         }
1873                         break;
1874                         
1875                 case LFUN_COMPLETION_POPUP:
1876                         if (d.current_work_area_)
1877                                 d.current_work_area_->completer().showPopup();
1878                         break;
1879
1880
1881                 case LFUN_COMPLETION_COMPLETE:
1882                         if (d.current_work_area_)
1883                                 d.current_work_area_->completer().tab();
1884                         break;
1885
1886                 default:
1887                         return false;
1888         }
1889
1890         return true;
1891 }
1892
1893
1894 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1895 {
1896         string const arg = cmd.getArg(0);
1897         if (arg == "scrollbar") {
1898                 // hide() is of no help
1899                 if (d.current_work_area_->verticalScrollBarPolicy() ==
1900                         Qt::ScrollBarAlwaysOff)
1901
1902                         d.current_work_area_->setVerticalScrollBarPolicy(
1903                                 Qt::ScrollBarAsNeeded);
1904                 else
1905                         d.current_work_area_->setVerticalScrollBarPolicy(
1906                                 Qt::ScrollBarAlwaysOff);
1907                 return;
1908         }
1909         if (arg == "statusbar") {
1910                 statusBar()->setVisible(!statusBar()->isVisible());
1911                 return;
1912         }
1913         if (arg == "menubar") {
1914                 menuBar()->setVisible(!menuBar()->isVisible());
1915                 return;
1916         }
1917 #if QT_VERSION >= 0x040300
1918         if (arg == "frame") {
1919                 int l, t, r, b;
1920                 getContentsMargins(&l, &t, &r, &b);
1921                 //are the frames in default state?
1922                 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1923                 if (l == 0) {
1924                         setContentsMargins(-2, -2, -2, -2);
1925                 } else {
1926                         setContentsMargins(0, 0, 0, 0);
1927                 }
1928                 return;
1929         }
1930 #endif
1931         if (arg != "fullscreen") {
1932                 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1933                 return;
1934         }
1935
1936         if (lyxrc.full_screen_toolbars)
1937                 d.toolbars_->toggleFullScreen(!isFullScreen());
1938
1939         if (isFullScreen()) {
1940                 for (int i = 0; i != d.splitter_->count(); ++i)
1941                         d.tabWorkArea(i)->setFullScreen(false);
1942 #if QT_VERSION >= 0x040300
1943                 setContentsMargins(0, 0, 0, 0);
1944 #endif
1945                 showNormal();
1946                 menuBar()->show();
1947                 statusBar()->show();
1948         } else {
1949                 for (int i = 0; i != d.splitter_->count(); ++i)
1950                         d.tabWorkArea(i)->setFullScreen(true);
1951 #if QT_VERSION >= 0x040300
1952                 setContentsMargins(-2, -2, -2, -2);
1953 #endif
1954                 showFullScreen();
1955                 statusBar()->hide();
1956                 menuBar()->hide();
1957         }
1958 }
1959
1960
1961 Buffer const * GuiView::updateInset(Inset const * inset)
1962 {
1963         if (!d.current_work_area_)
1964                 return 0;
1965
1966         if (inset)
1967                 d.current_work_area_->scheduleRedraw();
1968
1969         return &d.current_work_area_->bufferView().buffer();
1970 }
1971
1972
1973 void GuiView::restartCursor()
1974 {
1975         /* When we move around, or type, it's nice to be able to see
1976          * the cursor immediately after the keypress.
1977          */
1978         if (d.current_work_area_)
1979                 d.current_work_area_->startBlinkingCursor();
1980
1981         // Take this occasion to update the other GUI elements.
1982         updateLayoutList();
1983         updateToolbars();
1984         updateStatusBar();
1985 }
1986
1987
1988 void GuiView::updateCompletion(Cursor & cur, bool start, bool keep)
1989 {
1990         if (d.current_work_area_)
1991                 d.current_work_area_->completer().updateVisibility(cur, start, keep);
1992 }
1993
1994 namespace {
1995
1996 // This list should be kept in sync with the list of insets in
1997 // src/insets/Inset.cpp.  I.e., if a dialog goes with an inset, the
1998 // dialog should have the same name as the inset.
1999
2000 char const * const dialognames[] = {
2001 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
2002 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
2003 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
2004 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print", 
2005 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
2006
2007 #ifdef HAVE_LIBAIKSAURUS
2008 "thesaurus",
2009 #endif
2010
2011 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
2012
2013 char const * const * const end_dialognames =
2014         dialognames + (sizeof(dialognames) / sizeof(char *));
2015
2016 class cmpCStr {
2017 public:
2018         cmpCStr(char const * name) : name_(name) {}
2019         bool operator()(char const * other) {
2020                 return strcmp(other, name_) == 0;
2021         }
2022 private:
2023         char const * name_;
2024 };
2025
2026
2027 bool isValidName(string const & name)
2028 {
2029         return find_if(dialognames, end_dialognames,
2030                             cmpCStr(name.c_str())) != end_dialognames;
2031 }
2032
2033 } // namespace anon
2034
2035
2036 void GuiView::resetDialogs()
2037 {
2038         // Make sure that no LFUN uses any LyXView.
2039         theLyXFunc().setLyXView(0);
2040         // FIXME: the "math panels" toolbar takes an awful lot of time to
2041         // initialise so we don't do that for the time being.
2042         //d.toolbars_->init();
2043         guiApp->menus().fillMenuBar(menuBar(), this);
2044         if (d.layout_)
2045                 d.layout_->updateContents(true);
2046         // Now update controls with current buffer.
2047         theLyXFunc().setLyXView(this);
2048         restartCursor();
2049 }
2050
2051
2052 Dialog * GuiView::find_or_build(string const & name)
2053 {
2054         if (!isValidName(name))
2055                 return 0;
2056
2057         map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2058
2059         if (it != d.dialogs_.end())
2060                 return it->second.get();
2061
2062         Dialog * dialog = build(name);
2063         d.dialogs_[name].reset(dialog);
2064         if (lyxrc.allow_geometry_session)
2065                 dialog->restoreSession();
2066         return dialog;
2067 }
2068
2069
2070 void GuiView::showDialog(string const & name, string const & data,
2071         Inset * inset)
2072 {
2073         if (d.in_show_)
2074                 return;
2075
2076         d.in_show_ = true;
2077         Dialog * dialog = find_or_build(name);
2078         if (dialog) {
2079                 dialog->showData(data);
2080                 if (inset)
2081                         d.open_insets_[name] = inset;
2082         }
2083         d.in_show_ = false;
2084 }
2085
2086
2087 bool GuiView::isDialogVisible(string const & name) const
2088 {
2089         map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2090         if (it == d.dialogs_.end())
2091                 return false;
2092         return it->second.get()->isVisibleView();
2093 }
2094
2095
2096 void GuiView::hideDialog(string const & name, Inset * inset)
2097 {
2098         map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2099         if (it == d.dialogs_.end())
2100                 return;
2101
2102         if (inset && inset != getOpenInset(name))
2103                 return;
2104
2105         Dialog * const dialog = it->second.get();
2106         if (dialog->isVisibleView())
2107                 dialog->hideView();
2108         d.open_insets_[name] = 0;
2109 }
2110
2111
2112 void GuiView::disconnectDialog(string const & name)
2113 {
2114         if (!isValidName(name))
2115                 return;
2116
2117         if (d.open_insets_.find(name) != d.open_insets_.end())
2118                 d.open_insets_[name] = 0;
2119 }
2120
2121
2122 Inset * GuiView::getOpenInset(string const & name) const
2123 {
2124         if (!isValidName(name))
2125                 return 0;
2126
2127         map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2128         return it == d.open_insets_.end() ? 0 : it->second;
2129 }
2130
2131
2132 void GuiView::hideAll() const
2133 {
2134         map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
2135         map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2136
2137         for(; it != end; ++it)
2138                 it->second->hideView();
2139 }
2140
2141
2142 void GuiView::hideBufferDependent() const
2143 {
2144         map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
2145         map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2146
2147         for(; it != end; ++it) {
2148                 Dialog * dialog = it->second.get();
2149                 if (dialog->isBufferDependent())
2150                         dialog->hideView();
2151         }
2152 }
2153
2154
2155 void GuiView::updateBufferDependent(bool switched) const
2156 {
2157         map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
2158         map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2159
2160         for(; it != end; ++it) {
2161                 Dialog * dialog = it->second.get();
2162                 if (!dialog->isVisibleView())
2163                         continue;
2164                 if (switched && dialog->isBufferDependent()) {
2165                         if (dialog->initialiseParams(""))
2166                                 dialog->updateView();
2167                         else
2168                                 dialog->hideView();
2169                 } else {
2170                         // A bit clunky, but the dialog will request
2171                         // that the kernel provides it with the necessary
2172                         // data.
2173                         dialog->updateDialog();
2174                 }
2175         }
2176 }
2177
2178
2179 void GuiView::checkStatus()
2180 {
2181         map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
2182         map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2183
2184         for(; it != end; ++it) {
2185                 Dialog * const dialog = it->second.get();
2186                 if (dialog && dialog->isVisibleView())
2187                         dialog->checkStatus();
2188         }
2189 }
2190
2191
2192
2193 // will be replaced by a proper factory...
2194 Dialog * createGuiAbout(GuiView & lv);
2195 Dialog * createGuiBibitem(GuiView & lv);
2196 Dialog * createGuiBibtex(GuiView & lv);
2197 Dialog * createGuiBox(GuiView & lv);
2198 Dialog * createGuiBranch(GuiView & lv);
2199 Dialog * createGuiChanges(GuiView & lv);
2200 Dialog * createGuiCharacter(GuiView & lv);
2201 Dialog * createGuiCitation(GuiView & lv);
2202 Dialog * createGuiDelimiter(GuiView & lv);
2203 Dialog * createGuiDocument(GuiView & lv);
2204 Dialog * createGuiErrorList(GuiView & lv);
2205 Dialog * createGuiERT(GuiView & lv);
2206 Dialog * createGuiExternal(GuiView & lv);
2207 Dialog * createGuiFloat(GuiView & lv);
2208 Dialog * createGuiGraphics(GuiView & lv);
2209 Dialog * createGuiInclude(GuiView & lv);
2210 Dialog * createGuiLabel(GuiView & lv);
2211 Dialog * createGuiListings(GuiView & lv);
2212 Dialog * createGuiLog(GuiView & lv);
2213 Dialog * createGuiMathMatrix(GuiView & lv);
2214 Dialog * createGuiNomenclature(GuiView & lv);
2215 Dialog * createGuiNote(GuiView & lv);
2216 Dialog * createGuiParagraph(GuiView & lv);
2217 Dialog * createGuiPreferences(GuiView & lv);
2218 Dialog * createGuiPrint(GuiView & lv);
2219 Dialog * createGuiRef(GuiView & lv);
2220 Dialog * createGuiSearch(GuiView & lv);
2221 Dialog * createGuiSendTo(GuiView & lv);
2222 Dialog * createGuiShowFile(GuiView & lv);
2223 Dialog * createGuiSpellchecker(GuiView & lv);
2224 Dialog * createGuiSymbols(GuiView & lv);
2225 Dialog * createGuiTabularCreate(GuiView & lv);
2226 Dialog * createGuiTabular(GuiView & lv);
2227 Dialog * createGuiTexInfo(GuiView & lv);
2228 Dialog * createGuiToc(GuiView & lv);
2229 Dialog * createGuiThesaurus(GuiView & lv);
2230 Dialog * createGuiHyperlink(GuiView & lv);
2231 Dialog * createGuiVSpace(GuiView & lv);
2232 Dialog * createGuiViewSource(GuiView & lv);
2233 Dialog * createGuiWrap(GuiView & lv);
2234
2235
2236 Dialog * GuiView::build(string const & name)
2237 {
2238         BOOST_ASSERT(isValidName(name));
2239
2240         if (name == "aboutlyx")
2241                 return createGuiAbout(*this);
2242         if (name == "bibitem")
2243                 return createGuiBibitem(*this);
2244         if (name == "bibtex")
2245                 return createGuiBibtex(*this);
2246         if (name == "box")
2247                 return createGuiBox(*this);
2248         if (name == "branch")
2249                 return createGuiBranch(*this);
2250         if (name == "changes")
2251                 return createGuiChanges(*this);
2252         if (name == "character")
2253                 return createGuiCharacter(*this);
2254         if (name == "citation")
2255                 return createGuiCitation(*this);
2256         if (name == "document")
2257                 return createGuiDocument(*this);
2258         if (name == "errorlist")
2259                 return createGuiErrorList(*this);
2260         if (name == "ert")
2261                 return createGuiERT(*this);
2262         if (name == "external")
2263                 return createGuiExternal(*this);
2264         if (name == "file")
2265                 return createGuiShowFile(*this);
2266         if (name == "findreplace")
2267                 return createGuiSearch(*this);
2268         if (name == "float")
2269                 return createGuiFloat(*this);
2270         if (name == "graphics")
2271                 return createGuiGraphics(*this);
2272         if (name == "include")
2273                 return createGuiInclude(*this);
2274         if (name == "nomenclature")
2275                 return createGuiNomenclature(*this);
2276         if (name == "label")
2277                 return createGuiLabel(*this);
2278         if (name == "log")
2279                 return createGuiLog(*this);
2280         if (name == "view-source")
2281                 return createGuiViewSource(*this);
2282         if (name == "mathdelimiter")
2283                 return createGuiDelimiter(*this);
2284         if (name == "mathmatrix")
2285                 return createGuiMathMatrix(*this);
2286         if (name == "note")
2287                 return createGuiNote(*this);
2288         if (name == "paragraph")
2289                 return createGuiParagraph(*this);
2290         if (name == "prefs")
2291                 return createGuiPreferences(*this);
2292         if (name == "print")
2293                 return createGuiPrint(*this);
2294         if (name == "ref")
2295                 return createGuiRef(*this);
2296         if (name == "sendto")
2297                 return createGuiSendTo(*this);
2298         if (name == "spellchecker")
2299                 return createGuiSpellchecker(*this);
2300         if (name == "symbols")
2301                 return createGuiSymbols(*this);
2302         if (name == "tabular")
2303                 return createGuiTabular(*this);
2304         if (name == "tabularcreate")
2305                 return createGuiTabularCreate(*this);
2306         if (name == "texinfo")
2307                 return createGuiTexInfo(*this);
2308 #ifdef HAVE_LIBAIKSAURUS
2309         if (name == "thesaurus")
2310                 return createGuiThesaurus(*this);
2311 #endif
2312         if (name == "toc")
2313                 return createGuiToc(*this);
2314         if (name == "href")
2315                 return createGuiHyperlink(*this);
2316         if (name == "vspace")
2317                 return createGuiVSpace(*this);
2318         if (name == "wrap")
2319                 return createGuiWrap(*this);
2320         if (name == "listings")
2321                 return createGuiListings(*this);
2322
2323         return 0;
2324 }
2325
2326
2327 } // namespace frontend
2328 } // namespace lyx
2329
2330 #include "GuiView_moc.cpp"