]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiView.cpp
46c59a38047bbbf4f7d0d7692b44792efcf5f2dc
[features.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 #include "Dialog.h"
18
19 #include "GuiApplication.h"
20 #include "GuiWorkArea.h"
21 #include "GuiKeySymbol.h"
22 #include "GuiMenubar.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
25
26 #include "qt_helpers.h"
27
28 #include "buffer_funcs.h"
29 #include "Buffer.h"
30 #include "BufferList.h"
31 #include "BufferParams.h"
32 #include "BufferView.h"
33 #include "Cursor.h"
34 #include "debug.h"
35 #include "ErrorList.h"
36 #include "FuncRequest.h"
37 #include "gettext.h"
38 #include "Intl.h"
39 #include "Layout.h"
40 #include "Lexer.h"
41 #include "LyXFunc.h"
42 #include "LyX.h"
43 #include "LyXRC.h"
44 #include "LyXVC.h"
45 #include "MenuBackend.h"
46 #include "Paragraph.h"
47 #include "TextClass.h"
48 #include "Text.h"
49 #include "ToolbarBackend.h"
50 #include "version.h"
51
52 #include "support/FileName.h"
53 #include "support/lstrings.h"
54 #include "support/os.h"
55 #include "support/Timeout.h"
56
57 #include <QAction>
58 #include <QApplication>
59 #include <QCloseEvent>
60 #include <QDebug>
61 #include <QDesktopWidget>
62 #include <QDragEnterEvent>
63 #include <QDropEvent>
64 #include <QList>
65 #include <QMenu>
66 #include <QPainter>
67 #include <QPixmap>
68 #include <QPoint>
69 #include <QPushButton>
70 #include <QSettings>
71 #include <QShowEvent>
72 #include <QSplitter>
73 #include <QStackedWidget>
74 #include <QStatusBar>
75 #include <QTimer>
76 #include <QToolBar>
77 #include <QUrl>
78
79 #include <boost/assert.hpp>
80 #include <boost/bind.hpp>
81
82 #ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
84 #endif
85 #ifdef HAVE_UNISTD_H
86 # include <unistd.h>
87 #endif
88
89 using std::endl;
90 using std::string;
91 using std::vector;
92
93 namespace lyx {
94
95 extern bool quitting;
96
97 namespace frontend {
98
99 using support::bformat;
100 using support::FileName;
101 using support::trim;
102
103 namespace {
104
105 class BackgroundWidget : public QWidget
106 {
107 public:
108         BackgroundWidget()
109         {
110                 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
111                 /// The text to be written on top of the pixmap
112                 QString const text = lyx_version ? lyx_version : qt_("unknown version");
113                 splash_ = QPixmap(":/images/banner.png");
114
115                 QPainter pain(&splash_);
116                 pain.setPen(QColor(255, 255, 0));
117                 QFont font;
118                 // The font used to display the version info
119                 font.setStyleHint(QFont::SansSerif);
120                 font.setWeight(QFont::Bold);
121                 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
122                 pain.setFont(font);
123                 pain.drawText(260, 270, text);
124         }
125
126         void paintEvent(QPaintEvent *)
127         {
128                 int x = (width() - splash_.width()) / 2;
129                 int y = (height() - splash_.height()) / 2;
130                 QPainter pain(this);
131                 pain.drawPixmap(x, y, splash_);
132         }
133
134 private:
135         QPixmap splash_;
136 };
137
138 } // namespace anon
139
140
141 typedef boost::shared_ptr<Dialog> DialogPtr;
142
143 struct GuiView::GuiViewPrivate
144 {
145         GuiViewPrivate()
146                 : current_work_area_(0), layout_(0),
147                 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
148         {
149                 // hardcode here the platform specific icon size
150                 smallIconSize = 14;     // scaling problems
151                 normalIconSize = 20;    // ok, default
152                 bigIconSize = 26;               // better for some math icons
153
154                 splitter_ = new QSplitter;
155                 bg_widget_ = new BackgroundWidget;
156                 stack_widget_ = new QStackedWidget;
157                 stack_widget_->addWidget(bg_widget_);
158                 stack_widget_->addWidget(splitter_);
159                 setBackground();
160         }
161
162         ~GuiViewPrivate()
163         {
164                 delete splitter_;
165                 delete bg_widget_;
166                 delete stack_widget_;
167                 delete menubar_;
168                 delete toolbars_;
169         }
170
171         QMenu * toolBarPopup(GuiView * parent)
172         {
173                 // FIXME: translation
174                 QMenu * menu = new QMenu(parent);
175                 QActionGroup * iconSizeGroup = new QActionGroup(parent);
176
177                 QAction * smallIcons = new QAction(iconSizeGroup);
178                 smallIcons->setText(qt_("Small-sized icons"));
179                 smallIcons->setCheckable(true);
180                 QObject::connect(smallIcons, SIGNAL(triggered()),
181                         parent, SLOT(smallSizedIcons()));
182                 menu->addAction(smallIcons);
183
184                 QAction * normalIcons = new QAction(iconSizeGroup);
185                 normalIcons->setText(qt_("Normal-sized icons"));
186                 normalIcons->setCheckable(true);
187                 QObject::connect(normalIcons, SIGNAL(triggered()),
188                         parent, SLOT(normalSizedIcons()));
189                 menu->addAction(normalIcons);
190
191                 QAction * bigIcons = new QAction(iconSizeGroup);
192                 bigIcons->setText(qt_("Big-sized icons"));
193                 bigIcons->setCheckable(true);
194                 QObject::connect(bigIcons, SIGNAL(triggered()),
195                         parent, SLOT(bigSizedIcons()));
196                 menu->addAction(bigIcons);
197
198                 unsigned int cur = parent->iconSize().width();
199                 if ( cur == parent->d.smallIconSize)
200                         smallIcons->setChecked(true);
201                 else if (cur == parent->d.normalIconSize)
202                         normalIcons->setChecked(true);
203                 else if (cur == parent->d.bigIconSize)
204                         bigIcons->setChecked(true);
205
206                 return menu;
207         }
208
209         void setBackground()
210         {
211                 stack_widget_->setCurrentWidget(bg_widget_);
212                 bg_widget_->setUpdatesEnabled(true);
213         }
214
215         TabWorkArea * tabWorkArea(int i)
216         {
217                 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
218         }
219
220         TabWorkArea * currentTabWorkArea()
221         {
222                 if (splitter_->count() == 1)
223                         // The first TabWorkArea is always the first one, if any.
224                         return tabWorkArea(0);
225
226                 TabWorkArea * tab_widget = 0;
227                 for (int i = 0; i != splitter_->count(); ++i) {
228                         QWidget * w = splitter_->widget(i);
229                         if (!w->hasFocus())
230                                 continue;
231                         tab_widget = dynamic_cast<TabWorkArea *>(w);
232                         if (tab_widget)
233                                 break;
234                 }
235
236                 return tab_widget;
237         }
238
239 public:
240         GuiWorkArea * current_work_area_;
241         QSplitter * splitter_;
242         QStackedWidget * stack_widget_;
243         BackgroundWidget * bg_widget_;
244         /// view's menubar
245         GuiMenubar * menubar_;
246         /// view's toolbars
247         GuiToolbars * toolbars_;
248         /// The main layout box.
249         /** 
250          * \warning Don't Delete! The layout box is actually owned by
251          * whichever toolbar contains it. All the GuiView class needs is a
252          * means of accessing it.
253          *
254          * FIXME: replace that with a proper model so that we are not limited
255          * to only one dialog.
256          */
257         GuiLayoutBox * layout_;
258
259         ///
260         std::map<std::string, Inset *> open_insets_;
261
262         ///
263         std::map<std::string, DialogPtr> dialogs_;
264
265         unsigned int smallIconSize;
266         unsigned int normalIconSize;
267         unsigned int bigIconSize;
268         ///
269         QTimer statusbar_timer_;
270         /// are we quitting by the menu?
271         bool quitting_by_menu_;
272         /// auto-saving of buffers
273         Timeout autosave_timeout_;
274         /// flag against a race condition due to multiclicks, see bug #1119
275         bool in_show_;
276 };
277
278
279 GuiView::GuiView(int id)
280         : d(*new GuiViewPrivate), id_(id)
281 {
282         // GuiToolbars *must* be initialised before GuiMenubar.
283         d.toolbars_ = new GuiToolbars(*this);
284         d.menubar_ = new GuiMenubar(this, menubackend);
285
286         setCentralWidget(d.stack_widget_);
287
288         // Start autosave timer
289         if (lyxrc.autosave) {
290                 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
291                 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
292                 d.autosave_timeout_.start();
293         }
294         connect(&d.statusbar_timer_, SIGNAL(timeout()),
295                 this, SLOT(clearMessage()));
296
297         // Qt bug? signal lastWindowClosed does not work
298         setAttribute(Qt::WA_QuitOnClose, false);
299         setAttribute(Qt::WA_DeleteOnClose, true);
300 #ifndef Q_WS_MACX
301         // assign an icon to main form. We do not do it under Qt/Mac,
302         // since the icon is provided in the application bundle.
303         setWindowIcon(QPixmap(":/images/lyx.png"));
304 #endif
305
306         // For Drag&Drop.
307         setAcceptDrops(true);
308
309         statusBar()->setSizeGripEnabled(true);
310
311         // Forbid too small unresizable window because it can happen
312         // with some window manager under X11.
313         setMinimumSize(300, 200);
314
315         if (!lyxrc.allow_geometry_session)
316                 // No session handling, default to a sane size.
317                 setGeometry(50, 50, 690, 510);
318
319         // Now take care of session management.
320         QSettings settings;
321         QString const key = "view-" + QString::number(id_);
322 #ifdef Q_WS_X11
323         QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
324         QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
325         resize(size);
326         move(pos);
327 #else
328         if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
329                 setGeometry(50, 50, 690, 510);
330 #endif
331         setIconSize(settings.value(key + "/icon_size").toSize());
332 }
333
334
335 GuiView::~GuiView()
336 {
337         delete &d;
338 }
339
340
341 void GuiView::close()
342 {
343         d.quitting_by_menu_ = true;
344         d.current_work_area_ = 0;
345         for (int i = 0; i != d.splitter_->count(); ++i) {
346                 TabWorkArea * twa = d.tabWorkArea(i);
347                 if (twa)
348                         twa->closeAll();
349         }
350         QMainWindow::close();
351         d.quitting_by_menu_ = false;
352 }
353
354
355 void GuiView::setFocus()
356 {
357         if (d.current_work_area_)
358                 d.current_work_area_->setFocus();
359         else
360                 QWidget::setFocus();
361 }
362
363
364 QMenu * GuiView::createPopupMenu()
365 {
366         return d.toolBarPopup(this);
367 }
368
369
370 void GuiView::showEvent(QShowEvent * e)
371 {
372         LYXERR(Debug::GUI, "Passed Geometry "
373                 << size().height() << "x" << size().width()
374                 << "+" << pos().x() << "+" << pos().y());
375
376         if (d.splitter_->count() == 0)
377                 // No work area, switch to the background widget.
378                 d.setBackground();
379
380         QMainWindow::showEvent(e);
381 }
382
383
384 void GuiView::closeEvent(QCloseEvent * close_event)
385 {
386         // we may have been called through the close window button
387         // which bypasses the LFUN machinery.
388         if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
389                 if (!theBufferList().quitWriteAll()) {
390                         close_event->ignore();
391                         return;
392                 }
393         }
394
395         // Make sure that no LFUN use this close to be closed View.
396         theLyXFunc().setLyXView(0);
397         // Make sure the timer time out will not trigger a statusbar update.
398         d.statusbar_timer_.stop();
399
400         if (lyxrc.allow_geometry_session) {
401                 QSettings settings;
402                 QString const key = "view-" + QString::number(id_);
403 #ifdef Q_WS_X11
404                 settings.setValue(key + "/pos", pos());
405                 settings.setValue(key + "/size", size());
406 #else
407                 settings.setValue(key + "/geometry", saveGeometry());
408 #endif
409                 settings.setValue(key + "/icon_size", iconSize());
410                 d.toolbars_->saveToolbarInfo();
411         }
412
413         guiApp->unregisterView(id_);
414         if (guiApp->viewCount() > 0) {
415                 // Just close the window and do nothing else if this is not the
416                 // last window.
417                 close_event->accept();
418                 return;
419         }
420
421         quitting = true;
422
423         // this is the place where we leave the frontend.
424         // it is the only point at which we start quitting.
425         close_event->accept();
426         // quit the event loop
427         qApp->quit();
428 }
429
430
431 void GuiView::dragEnterEvent(QDragEnterEvent * event)
432 {
433         if (event->mimeData()->hasUrls())
434                 event->accept();
435         /// \todo Ask lyx-devel is this is enough:
436         /// if (event->mimeData()->hasFormat("text/plain"))
437         ///     event->acceptProposedAction();
438 }
439
440
441 void GuiView::dropEvent(QDropEvent* event)
442 {
443         QList<QUrl> files = event->mimeData()->urls();
444         if (files.isEmpty())
445                 return;
446
447         LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
448         for (int i = 0; i != files.size(); ++i) {
449                 string const file = support::os::internal_path(fromqstr(
450                         files.at(i).toLocalFile()));
451                 if (!file.empty())
452                         dispatch(FuncRequest(LFUN_FILE_OPEN, file));
453         }
454 }
455
456
457 void GuiView::message(docstring const & str)
458 {
459         statusBar()->showMessage(toqstr(str));
460         d.statusbar_timer_.stop();
461         d.statusbar_timer_.start(3000);
462 }
463
464
465 void GuiView::smallSizedIcons()
466 {
467         setIconSize(QSize(d.smallIconSize, d.smallIconSize));
468 }
469
470
471 void GuiView::normalSizedIcons()
472 {
473         setIconSize(QSize(d.normalIconSize, d.normalIconSize));
474 }
475
476
477 void GuiView::bigSizedIcons()
478 {
479         setIconSize(QSize(d.bigIconSize, d.bigIconSize));
480 }
481
482
483 void GuiView::clearMessage()
484 {
485         if (!hasFocus())
486                 return;
487         theLyXFunc().setLyXView(this);
488         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
489         d.statusbar_timer_.stop();
490 }
491
492
493 void GuiView::updateWindowTitle(GuiWorkArea * wa)
494 {
495         if (wa != d.current_work_area_)
496                 return;
497         setWindowTitle(qt_("LyX: ") + wa->windowTitle());
498         setWindowIconText(wa->windowIconText());
499 }
500
501
502 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
503 {
504         disconnectBuffer();
505         disconnectBufferView();
506         connectBufferView(wa->bufferView());
507         connectBuffer(wa->bufferView().buffer());
508         d.current_work_area_ = wa;
509         QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
510                 this, SLOT(updateWindowTitle(GuiWorkArea *)));
511         updateWindowTitle(wa);
512
513         updateToc();
514         // Buffer-dependent dialogs should be updated or
515         // hidden. This should go here because some dialogs (eg ToC)
516         // require bv_->text.
517         updateBufferDependent(true);
518         updateToolbars();
519         updateLayoutList();
520         updateStatusBar();
521 }
522
523
524 void GuiView::updateStatusBar()
525 {
526         // let the user see the explicit message
527         if (d.statusbar_timer_.isActive())
528                 return;
529
530         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
531 }
532
533
534 bool GuiView::hasFocus() const
535 {
536         return qApp->activeWindow() == this;
537 }
538
539
540 bool GuiView::event(QEvent * e)
541 {
542         switch (e->type())
543         {
544         // Useful debug code:
545         //case QEvent::ActivationChange:
546         //case QEvent::WindowDeactivate:
547         //case QEvent::Paint:
548         //case QEvent::Enter:
549         //case QEvent::Leave:
550         //case QEvent::HoverEnter:
551         //case QEvent::HoverLeave:
552         //case QEvent::HoverMove:
553         //case QEvent::StatusTip:
554         //case QEvent::DragEnter:
555         //case QEvent::DragLeave:
556         //case QEvent::Drop:
557         //      break;
558
559         case QEvent::WindowActivate: {
560                 guiApp->setCurrentView(*this);
561                 if (d.current_work_area_) {
562                         BufferView & bv = d.current_work_area_->bufferView();
563                         connectBufferView(bv);
564                         connectBuffer(bv.buffer());
565                         // The document structure, name and dialogs might have
566                         // changed in another view.
567                         updateBufferDependent(true);
568                 } else {
569                         setWindowTitle(qt_("LyX"));
570                         setWindowIconText(qt_("LyX"));
571                 }
572                 return QMainWindow::event(e);
573         }
574         case QEvent::ShortcutOverride: {
575                 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
576                 if (!d.current_work_area_) {
577                         theLyXFunc().setLyXView(this);
578                         KeySymbol sym;
579                         setKeySymbol(&sym, ke);
580                         theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
581                         e->accept();
582                         return true;
583                 }
584                 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
585                         KeySymbol sym;
586                         setKeySymbol(&sym, ke);
587                         d.current_work_area_->processKeySym(sym, NoModifier);
588                         e->accept();
589                         return true;
590                 }
591         }
592         default:
593                 return QMainWindow::event(e);
594         }
595 }
596
597
598 bool GuiView::focusNextPrevChild(bool /*next*/)
599 {
600         setFocus();
601         return true;
602 }
603
604
605 void GuiView::setBusy(bool yes)
606 {
607         if (d.current_work_area_) {
608                 d.current_work_area_->setUpdatesEnabled(!yes);
609                 if (yes)
610                         d.current_work_area_->stopBlinkingCursor();
611                 else
612                         d.current_work_area_->startBlinkingCursor();
613         }
614
615         if (yes)
616                 QApplication::setOverrideCursor(Qt::WaitCursor);
617         else
618                 QApplication::restoreOverrideCursor();
619 }
620
621
622 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
623 {
624         GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
625
626         if (tbinfo.flags & ToolbarInfo::TOP) {
627                 if (newline)
628                         addToolBarBreak(Qt::TopToolBarArea);
629                 addToolBar(Qt::TopToolBarArea, toolBar);
630         }
631
632         if (tbinfo.flags & ToolbarInfo::BOTTOM) {
633 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
634 #if (QT_VERSION >= 0x040202)
635                 if (newline)
636                         addToolBarBreak(Qt::BottomToolBarArea);
637 #endif
638                 addToolBar(Qt::BottomToolBarArea, toolBar);
639         }
640
641         if (tbinfo.flags & ToolbarInfo::LEFT) {
642 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
643 #if (QT_VERSION >= 0x040202)
644                 if (newline)
645                         addToolBarBreak(Qt::LeftToolBarArea);
646 #endif
647                 addToolBar(Qt::LeftToolBarArea, toolBar);
648         }
649
650         if (tbinfo.flags & ToolbarInfo::RIGHT) {
651 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
652 #if (QT_VERSION >= 0x040202)
653                 if (newline)
654                         addToolBarBreak(Qt::RightToolBarArea);
655 #endif
656                 addToolBar(Qt::RightToolBarArea, toolBar);
657         }
658
659         // The following does not work so I cannot restore to exact toolbar location
660         /*
661         ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
662         toolBar->move(tbinfo.posx, tbinfo.posy);
663         */
664
665         return toolBar;
666 }
667
668
669 GuiWorkArea * GuiView::workArea(Buffer & buffer)
670 {
671         for (int i = 0; i != d.splitter_->count(); ++i) {
672                 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
673                 if (wa)
674                         return wa;
675         }
676         return 0;
677 }
678
679
680 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
681 {
682
683         // Automatically create a TabWorkArea if there are none yet.
684         if (!d.splitter_->count())
685                 addTabWorkArea();
686
687         TabWorkArea * tab_widget = d.currentTabWorkArea();
688         return tab_widget->addWorkArea(buffer, *this);
689 }
690
691
692 void GuiView::addTabWorkArea()
693 {
694         TabWorkArea * twa = new TabWorkArea;
695         QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
696                 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
697         d.splitter_->addWidget(twa);
698         d.stack_widget_->setCurrentWidget(d.splitter_);
699 }
700
701
702 GuiWorkArea const * GuiView::currentWorkArea() const
703 {
704         return d.current_work_area_;
705 }
706
707
708 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
709 {
710         BOOST_ASSERT(work_area);
711
712         // Changing work area can result from opening a file so
713         // update the toc in any case.
714         updateToc();
715
716         GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
717         d.current_work_area_ = wa;
718         for (int i = 0; i != d.splitter_->count(); ++i) {
719                 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
720                         return;
721         }
722 }
723
724
725 void GuiView::removeWorkArea(GuiWorkArea * work_area)
726 {
727         BOOST_ASSERT(work_area);
728         GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
729         if (gwa == d.current_work_area_) {
730                 disconnectBuffer();
731                 disconnectBufferView();
732                 hideBufferDependent();
733                 d.current_work_area_ = 0;
734         }
735
736         // removing a work area often results from closing a file so
737         // update the toc in any case.
738         updateToc();
739
740         for (int i = 0; i != d.splitter_->count(); ++i) {
741                 TabWorkArea * twa = d.tabWorkArea(i);
742                 if (!twa->removeWorkArea(gwa))
743                         // Not found in this tab group.
744                         continue;
745
746                 // We found and removed the GuiWorkArea.
747                 if (!twa->count()) {
748                         // No more WorkAreas in this tab group, so delete it.
749                         delete twa;
750                         break;
751                 }
752
753                 if (d.current_work_area_)
754                         // This means that we are not closing the current GuiWorkArea;
755                         break;
756
757                 // Switch to the next GuiWorkArea in the found TabWorkArea.
758                 d.current_work_area_ = twa->currentWorkArea();
759                 break;
760         }
761
762         if (d.splitter_->count() == 0)
763                 // No more work area, switch to the background widget.
764                 d.setBackground();
765 }
766
767
768 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
769 {
770         d.layout_ = layout;
771 }
772
773
774 void GuiView::updateLayoutList()
775 {
776         if (d.layout_)
777                 d.layout_->updateContents(false);
778 }
779
780
781 void GuiView::updateToolbars()
782 {
783         if (d.current_work_area_) {
784                 bool const math =
785                         d.current_work_area_->bufferView().cursor().inMathed();
786                 bool const table =
787                         lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
788                 bool const review =
789                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
790                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
791
792                 d.toolbars_->update(math, table, review);
793         } else
794                 d.toolbars_->update(false, false, false);
795
796         // update read-only status of open dialogs.
797         checkStatus();
798 }
799
800
801 Buffer * GuiView::buffer()
802 {
803         if (d.current_work_area_)
804                 return &d.current_work_area_->bufferView().buffer();
805         return 0;
806 }
807
808
809 Buffer const * GuiView::buffer() const
810 {
811         if (d.current_work_area_)
812                 return &d.current_work_area_->bufferView().buffer();
813         return 0;
814 }
815
816
817 void GuiView::setBuffer(Buffer * newBuffer)
818 {
819         BOOST_ASSERT(newBuffer);
820         setBusy(true);
821
822         GuiWorkArea * wa = workArea(*newBuffer);
823         if (wa == 0) {
824                 updateLabels(*newBuffer->masterBuffer());
825                 wa = addWorkArea(*newBuffer);
826         } else {
827                 //Disconnect the old buffer...there's no new one.
828                 disconnectBuffer();
829         }
830         connectBuffer(*newBuffer);
831         connectBufferView(wa->bufferView());
832         setCurrentWorkArea(wa);
833
834         setBusy(false);
835 }
836
837
838 void GuiView::connectBuffer(Buffer & buf)
839 {
840         buf.setGuiDelegate(this);
841 }
842
843
844 void GuiView::disconnectBuffer()
845 {
846         if (d.current_work_area_)
847                 d.current_work_area_->bufferView().setGuiDelegate(0);
848 }
849
850
851 void GuiView::connectBufferView(BufferView & bv)
852 {
853         bv.setGuiDelegate(this);
854 }
855
856
857 void GuiView::disconnectBufferView()
858 {
859         if (d.current_work_area_)
860                 d.current_work_area_->bufferView().setGuiDelegate(0);
861 }
862
863
864 void GuiView::errors(string const & error_type)
865 {
866         ErrorList & el = buffer()->errorList(error_type);
867         if (!el.empty())
868                 showDialog("errorlist", error_type);
869 }
870
871
872 void GuiView::updateDialog(string const & name, string const & data)
873 {
874         if (!isDialogVisible(name))
875                 return;
876
877         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
878         if (it == d.dialogs_.end())
879                 return;
880
881         Dialog * const dialog = it->second.get();
882         if (dialog->isVisibleView())
883                 dialog->updateData(data);
884 }
885
886
887 BufferView * GuiView::view()
888 {
889         return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
890 }
891
892
893 void GuiView::updateToc()
894 {
895         updateDialog("toc", "");
896 }
897
898
899 void GuiView::updateEmbeddedFiles()
900 {
901         updateDialog("embedding", "");
902 }
903
904
905 void GuiView::autoSave()
906 {
907         LYXERR(Debug::INFO, "Running autoSave()");
908
909         if (buffer())
910                 view()->buffer().autoSave();
911 }
912
913
914 void GuiView::resetAutosaveTimers()
915 {
916         if (lyxrc.autosave)
917                 d.autosave_timeout_.restart();
918 }
919
920
921 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
922 {
923         FuncStatus flag;
924         bool enable = true;
925         Buffer * buf = buffer();
926
927         /* In LyX/Mac, when a dialog is open, the menus of the
928            application can still be accessed without giving focus to
929            the main window. In this case, we want to disable the menu
930            entries that are buffer-related.
931
932            Note that this code is not perfect, as bug 1941 attests:
933            http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
934         */
935         if (cmd.origin == FuncRequest::MENU && !hasFocus())
936                 buf = 0;
937
938         switch(cmd.action) {
939         case LFUN_TOOLBAR_TOGGLE:
940                 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
941                 break;
942
943         case LFUN_DIALOG_TOGGLE:
944                 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
945                 // fall through to set "enable"
946         case LFUN_DIALOG_SHOW: {
947                 string const name = cmd.getArg(0);
948                 if (!buf)
949                         enable = name == "aboutlyx"
950                                 || name == "file" //FIXME: should be removed.
951                                 || name == "prefs"
952                                 || name == "texinfo";
953                 else if (name == "print")
954                         enable = buf->isExportable("dvi")
955                                 && lyxrc.print_command != "none";
956                 else if (name == "character") {
957                         if (!view())
958                                 enable = false;
959                         else {
960                                 InsetCode ic = view()->cursor().inset().lyxCode();
961                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
962                         }
963                 }
964                 else if (name == "latexlog")
965                         enable = FileName(buf->logName()).isReadableFile();
966                 else if (name == "spellchecker")
967 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
968                         enable = !buf->isReadonly();
969 #else
970                         enable = false;
971 #endif
972                 else if (name == "vclog")
973                         enable = buf->lyxvc().inUse();
974                 break;
975         }
976
977         case LFUN_DIALOG_UPDATE: {
978                 string const name = cmd.getArg(0);
979                 if (!buf)
980                         enable = name == "prefs";
981                 break;
982         }
983
984         case LFUN_INSET_APPLY: {
985                 if (!buf) {
986                         enable = false;
987                         break;
988                 }
989                 string const name = cmd.getArg(0);
990                 Inset * inset = getOpenInset(name);
991                 if (inset) {
992                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
993                         FuncStatus fs;
994                         if (!inset->getStatus(view()->cursor(), fr, fs)) {
995                                 // Every inset is supposed to handle this
996                                 BOOST_ASSERT(false);
997                         }
998                         flag |= fs;
999                 } else {
1000                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1001                         flag |= getStatus(fr);
1002                 }
1003                 enable = flag.enabled();
1004                 break;
1005         }
1006
1007         default:
1008                 if (!view()) {
1009                         enable = false;
1010                         break;
1011                 }
1012         }
1013
1014         if (!enable)
1015                 flag.enabled(false);
1016
1017         return flag;
1018 }
1019
1020
1021 bool GuiView::dispatch(FuncRequest const & cmd, bool propagate)
1022 {
1023         BufferView * bv = view();       
1024         // By default we won't need any update.
1025         if (bv)
1026                 bv->cursor().updateFlags(Update::None);
1027
1028         switch(cmd.action) {
1029                 case LFUN_BUFFER_SWITCH:
1030                         setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1031                         break;
1032
1033                 case LFUN_BUFFER_NEXT:
1034                         setBuffer(theBufferList().next(buffer()));
1035                         break;
1036
1037                 case LFUN_BUFFER_PREVIOUS:
1038                         setBuffer(theBufferList().previous(buffer()));
1039                         break;
1040
1041                 case LFUN_COMMAND_EXECUTE: {
1042                         bool const show_it = cmd.argument() != "off";
1043                         d.toolbars_->showCommandBuffer(show_it);
1044                         break;
1045                 }
1046                 case LFUN_DROP_LAYOUTS_CHOICE:
1047                         if (d.layout_)
1048                                 d.layout_->showPopup();
1049                         break;
1050
1051                 case LFUN_MENU_OPEN:
1052                         d.menubar_->openByName(toqstr(cmd.argument()));
1053                         break;
1054
1055                 case LFUN_TOOLBAR_TOGGLE: {
1056                         string const name = cmd.getArg(0);
1057                         bool const allowauto = cmd.getArg(1) == "allowauto";
1058                         // it is possible to get current toolbar status like this,...
1059                         // but I decide to obey the order of ToolbarBackend::flags
1060                         // and disregard real toolbar status.
1061                         // toolbars_->saveToolbarInfo();
1062                         //
1063                         // toggle state on/off/auto
1064                         d.toolbars_->toggleToolbarState(name, allowauto);
1065                         // update toolbar
1066                         updateToolbars();
1067
1068                         ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1069                         if (!tbi) {
1070                                 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1071                                 break;
1072                         }
1073                         docstring state;
1074                         if (tbi->flags & ToolbarInfo::ON)
1075                                 state = _("on");
1076                         else if (tbi->flags & ToolbarInfo::OFF)
1077                                 state = _("off");
1078                         else if (tbi->flags & ToolbarInfo::AUTO)
1079                                 state = _("auto");
1080
1081                         message(bformat(_("Toolbar \"%1$s\" state set to %2$s"), 
1082                                            _(tbi->gui_name), state));
1083                         break;
1084                 }
1085
1086                 case LFUN_DIALOG_UPDATE: {
1087                         string const name = to_utf8(cmd.argument());
1088                         // Can only update a dialog connected to an existing inset
1089                         Inset * inset = getOpenInset(name);
1090                         if (inset) {
1091                                 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1092                                 inset->dispatch(view()->cursor(), fr);
1093                         } else if (name == "paragraph") {
1094                                 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1095                         } else if (name == "prefs") {
1096                                 updateDialog(name, string());
1097                         }
1098                         break;
1099                 }
1100
1101                 case LFUN_DIALOG_TOGGLE: {
1102                         if (isDialogVisible(cmd.getArg(0)))
1103                                 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1104                         else
1105                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1106                         break;
1107                 }
1108
1109                 case LFUN_DIALOG_DISCONNECT_INSET:
1110                         disconnectDialog(to_utf8(cmd.argument()));
1111                         break;
1112
1113                 case LFUN_DIALOG_HIDE: {
1114                         if (quitting)
1115                                 break;
1116                         guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1117                         break;
1118                 }
1119
1120                 case LFUN_DIALOG_SHOW: {
1121                         string const name = cmd.getArg(0);
1122                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1123
1124                         if (name == "character") {
1125                                 data = freefont2string();
1126                                 if (!data.empty())
1127                                         showDialog("character", data);
1128                         } else if (name == "latexlog") {
1129                                 Buffer::LogType type; 
1130                                 string const logfile = buffer()->logName(&type);
1131                                 switch (type) {
1132                                 case Buffer::latexlog:
1133                                         data = "latex ";
1134                                         break;
1135                                 case Buffer::buildlog:
1136                                         data = "literate ";
1137                                         break;
1138                                 }
1139                                 data += Lexer::quoteString(logfile);
1140                                 showDialog("log", data);
1141                         } else if (name == "vclog") {
1142                                 string const data = "vc " +
1143                                         Lexer::quoteString(buffer()->lyxvc().getLogFile());
1144                                 showDialog("log", data);
1145                         } else
1146                                 showDialog(name, data);
1147                         break;
1148                 }
1149
1150                 case LFUN_INSET_APPLY: {
1151                         string const name = cmd.getArg(0);
1152                         Inset * inset = getOpenInset(name);
1153                         if (inset) {
1154                                 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1155                                 inset->dispatch(view()->cursor(), fr);
1156                         } else {
1157                                 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1158                                 lyx::dispatch(fr);
1159                         }
1160                         break;
1161                 }
1162
1163                 default:
1164                         if (propagate) {
1165                                 theLyXFunc().setLyXView(this);
1166                                 lyx::dispatch(cmd);
1167                         }
1168                         return false;
1169         }
1170
1171         if (bv) {
1172                 bv->processUpdateFlags(bv->cursor().result().update());
1173                 // We won't need any new update.
1174                 bv->cursor().updateFlags(Update::None);
1175         }
1176         return true;
1177 }
1178
1179
1180 Buffer const * GuiView::updateInset(Inset const * inset)
1181 {
1182         if (!d.current_work_area_)
1183                 return 0;
1184
1185         if (inset)
1186                 d.current_work_area_->scheduleRedraw();
1187
1188         return &d.current_work_area_->bufferView().buffer();
1189 }
1190
1191
1192 void GuiView::restartCursor()
1193 {
1194         /* When we move around, or type, it's nice to be able to see
1195          * the cursor immediately after the keypress.
1196          */
1197         if (d.current_work_area_)
1198                 d.current_work_area_->startBlinkingCursor();
1199
1200         // Take this occasion to update the toobars and layout list.
1201         updateLayoutList();
1202         updateToolbars();
1203 }
1204
1205 namespace {
1206
1207 // This list should be kept in sync with the list of insets in
1208 // src/insets/Inset.cpp.  I.e., if a dialog goes with an inset, the
1209 // dialog should have the same name as the inset.
1210
1211 char const * const dialognames[] = {
1212 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1213 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1214 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1215 "mathdelimiter", "mathmatrix", "note", "paragraph",
1216 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1217
1218 #ifdef HAVE_LIBAIKSAURUS
1219 "thesaurus",
1220 #endif
1221
1222 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1223
1224 char const * const * const end_dialognames =
1225         dialognames + (sizeof(dialognames) / sizeof(char *));
1226
1227 class cmpCStr {
1228 public:
1229         cmpCStr(char const * name) : name_(name) {}
1230         bool operator()(char const * other) {
1231                 return strcmp(other, name_) == 0;
1232         }
1233 private:
1234         char const * name_;
1235 };
1236
1237
1238 bool isValidName(string const & name)
1239 {
1240         return std::find_if(dialognames, end_dialognames,
1241                             cmpCStr(name.c_str())) != end_dialognames;
1242 }
1243
1244 } // namespace anon
1245
1246
1247 void GuiView::resetDialogs()
1248 {
1249         // Make sure that no LFUN uses any LyXView.
1250         theLyXFunc().setLyXView(0);
1251         d.toolbars_->init();
1252         d.menubar_->init();
1253         if (d.layout_)
1254                 d.layout_->updateContents(true);
1255         // Now update controls with current buffer.
1256         theLyXFunc().setLyXView(this);
1257         restartCursor();
1258 }
1259
1260
1261 Dialog * GuiView::find_or_build(string const & name)
1262 {
1263         if (!isValidName(name))
1264                 return 0;
1265
1266         std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1267
1268         if (it != d.dialogs_.end())
1269                 return it->second.get();
1270
1271         d.dialogs_[name].reset(build(name));
1272         return d.dialogs_[name].get();
1273 }
1274
1275
1276 void GuiView::showDialog(string const & name, string const & data,
1277         Inset * inset)
1278 {
1279         if (d.in_show_)
1280                 return;
1281
1282         d.in_show_ = true;
1283         Dialog * dialog = find_or_build(name);
1284         if (dialog) {
1285                 dialog->showData(data);
1286                 if (inset)
1287                         d.open_insets_[name] = inset;
1288         }
1289         d.in_show_ = false;
1290 }
1291
1292
1293 bool GuiView::isDialogVisible(string const & name) const
1294 {
1295         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1296         if (it == d.dialogs_.end())
1297                 return false;
1298         return it->second.get()->isVisibleView();
1299 }
1300
1301
1302 void GuiView::hideDialog(string const & name, Inset * inset)
1303 {
1304         // Don't send the signal if we are quitting, because on MSVC it is
1305         // destructed before the cut stack in CutAndPaste.cpp, and this method
1306         // is called from some inset destructor if the cut stack is not empty
1307         // on exit.
1308         if (quitting)
1309                 return;
1310
1311         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1312         if (it == d.dialogs_.end())
1313                 return;
1314
1315         if (inset && inset != getOpenInset(name))
1316                 return;
1317
1318         Dialog * const dialog = it->second.get();
1319         if (dialog->isVisibleView())
1320                 dialog->hide();
1321         d.open_insets_[name] = 0;
1322 }
1323
1324
1325 void GuiView::disconnectDialog(string const & name)
1326 {
1327         if (!isValidName(name))
1328                 return;
1329
1330         if (d.open_insets_.find(name) != d.open_insets_.end())
1331                 d.open_insets_[name] = 0;
1332 }
1333
1334
1335 Inset * GuiView::getOpenInset(string const & name) const
1336 {
1337         if (!isValidName(name))
1338                 return 0;
1339
1340         std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1341         return it == d.open_insets_.end() ? 0 : it->second;
1342 }
1343
1344
1345 void GuiView::hideAll() const
1346 {
1347         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1348         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1349
1350         for(; it != end; ++it)
1351                 it->second->hide();
1352 }
1353
1354
1355 void GuiView::hideBufferDependent() const
1356 {
1357         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1358         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1359
1360         for(; it != end; ++it) {
1361                 Dialog * dialog = it->second.get();
1362                 if (dialog->isBufferDependent())
1363                         dialog->hide();
1364         }
1365 }
1366
1367
1368 void GuiView::updateBufferDependent(bool switched) const
1369 {
1370         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1371         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1372
1373         for(; it != end; ++it) {
1374                 Dialog * dialog = it->second.get();
1375                 if (switched && dialog->isBufferDependent()) {
1376                         if (dialog->isVisibleView() && dialog->initialiseParams(""))
1377                                 dialog->updateView();
1378                         else
1379                                 dialog->hide();
1380                 } else {
1381                         // A bit clunky, but the dialog will request
1382                         // that the kernel provides it with the necessary
1383                         // data.
1384                         dialog->updateDialog();
1385                 }
1386         }
1387 }
1388
1389
1390 void GuiView::checkStatus()
1391 {
1392         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1393         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1394
1395         for(; it != end; ++it) {
1396                 Dialog * const dialog = it->second.get();
1397                 if (dialog && dialog->isVisibleView())
1398                         dialog->checkStatus();
1399         }
1400 }
1401
1402
1403
1404 // will be replaced by a proper factory...
1405 Dialog * createGuiAbout(GuiView & lv);
1406 Dialog * createGuiBibitem(GuiView & lv);
1407 Dialog * createGuiBibtex(GuiView & lv);
1408 Dialog * createGuiBox(GuiView & lv);
1409 Dialog * createGuiBranch(GuiView & lv);
1410 Dialog * createGuiChanges(GuiView & lv);
1411 Dialog * createGuiCharacter(GuiView & lv);
1412 Dialog * createGuiCitation(GuiView & lv);
1413 Dialog * createGuiDelimiter(GuiView & lv);
1414 Dialog * createGuiDocument(GuiView & lv);
1415 Dialog * createGuiErrorList(GuiView & lv);
1416 Dialog * createGuiERT(GuiView & lv);
1417 Dialog * createGuiExternal(GuiView & lv);
1418 Dialog * createGuiFloat(GuiView & lv);
1419 Dialog * createGuiGraphics(GuiView & lv);
1420 Dialog * createGuiInclude(GuiView & lv);
1421 Dialog * createGuiIndex(GuiView & lv);
1422 Dialog * createGuiLabel(GuiView & lv);
1423 Dialog * createGuiListings(GuiView & lv);
1424 Dialog * createGuiLog(GuiView & lv);
1425 Dialog * createGuiMathMatrix(GuiView & lv);
1426 Dialog * createGuiNomenclature(GuiView & lv);
1427 Dialog * createGuiNote(GuiView & lv);
1428 Dialog * createGuiParagraph(GuiView & lv);
1429 Dialog * createGuiPreferences(GuiView & lv);
1430 Dialog * createGuiPrint(GuiView & lv);
1431 Dialog * createGuiRef(GuiView & lv);
1432 Dialog * createGuiSearch(GuiView & lv);
1433 Dialog * createGuiSendTo(GuiView & lv);
1434 Dialog * createGuiShowFile(GuiView & lv);
1435 Dialog * createGuiSpellchecker(GuiView & lv);
1436 Dialog * createGuiTabularCreate(GuiView & lv);
1437 Dialog * createGuiTabular(GuiView & lv);
1438 Dialog * createGuiTexInfo(GuiView & lv);
1439 Dialog * createGuiToc(GuiView & lv);
1440 Dialog * createGuiThesaurus(GuiView & lv);
1441 Dialog * createGuiHyperlink(GuiView & lv);
1442 Dialog * createGuiVSpace(GuiView & lv);
1443 Dialog * createGuiViewSource(GuiView & lv);
1444 Dialog * createGuiWrap(GuiView & lv);
1445
1446
1447 Dialog * GuiView::build(string const & name)
1448 {
1449         BOOST_ASSERT(isValidName(name));
1450
1451         if (name == "aboutlyx")
1452                 return createGuiAbout(*this);
1453         if (name == "bibitem")
1454                 return createGuiBibitem(*this);
1455         if (name == "bibtex")
1456                 return createGuiBibtex(*this);
1457         if (name == "box")
1458                 return createGuiBox(*this);
1459         if (name == "branch")
1460                 return createGuiBranch(*this);
1461         if (name == "changes")
1462                 return createGuiChanges(*this);
1463         if (name == "character")
1464                 return createGuiCharacter(*this);
1465         if (name == "citation")
1466                 return createGuiCitation(*this);
1467         if (name == "document")
1468                 return createGuiDocument(*this);
1469         if (name == "errorlist")
1470                 return createGuiErrorList(*this);
1471         if (name == "ert")
1472                 return createGuiERT(*this);
1473         if (name == "external")
1474                 return createGuiExternal(*this);
1475         if (name == "file")
1476                 return createGuiShowFile(*this);
1477         if (name == "findreplace")
1478                 return createGuiSearch(*this);
1479         if (name == "float")
1480                 return createGuiFloat(*this);
1481         if (name == "graphics")
1482                 return createGuiGraphics(*this);
1483         if (name == "include")
1484                 return createGuiInclude(*this);
1485         if (name == "index")
1486                 return createGuiIndex(*this);
1487         if (name == "nomenclature")
1488                 return createGuiNomenclature(*this);
1489         if (name == "label")
1490                 return createGuiLabel(*this);
1491         if (name == "log")
1492                 return createGuiLog(*this);
1493         if (name == "view-source")
1494                 return createGuiViewSource(*this);
1495         if (name == "mathdelimiter")
1496                 return createGuiDelimiter(*this);
1497         if (name == "mathmatrix")
1498                 return createGuiMathMatrix(*this);
1499         if (name == "note")
1500                 return createGuiNote(*this);
1501         if (name == "paragraph")
1502                 return createGuiParagraph(*this);
1503         if (name == "prefs")
1504                 return createGuiPreferences(*this);
1505         if (name == "print")
1506                 return createGuiPrint(*this);
1507         if (name == "ref")
1508                 return createGuiRef(*this);
1509         if (name == "sendto")
1510                 return createGuiSendTo(*this);
1511         if (name == "spellchecker")
1512                 return createGuiSpellchecker(*this);
1513         if (name == "tabular")
1514                 return createGuiTabular(*this);
1515         if (name == "tabularcreate")
1516                 return createGuiTabularCreate(*this);
1517         if (name == "texinfo")
1518                 return createGuiTexInfo(*this);
1519 #ifdef HAVE_LIBAIKSAURUS
1520         if (name == "thesaurus")
1521                 return createGuiThesaurus(*this);
1522 #endif
1523         if (name == "toc")
1524                 return createGuiToc(*this);
1525         if (name == "href")
1526                 return createGuiHyperlink(*this);
1527         if (name == "vspace")
1528                 return createGuiVSpace(*this);
1529         if (name == "wrap")
1530                 return createGuiWrap(*this);
1531         if (name == "listings")
1532                 return createGuiListings(*this);
1533
1534         return 0;
1535 }
1536
1537
1538 } // namespace frontend
1539 } // namespace lyx
1540
1541 #include "GuiView_moc.cpp"