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