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