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