]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiView.cpp
no need to cast anymore
[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 #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 * wa)
709 {
710         BOOST_ASSERT(wa);
711
712         // Changing work area can result from opening a file so
713         // update the toc in any case.
714         updateToc();
715
716         d.current_work_area_ = wa;
717         for (int i = 0; i != d.splitter_->count(); ++i) {
718                 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
719                         return;
720         }
721 }
722
723
724 void GuiView::removeWorkArea(GuiWorkArea * wa)
725 {
726         BOOST_ASSERT(wa);
727         if (wa == d.current_work_area_) {
728                 disconnectBuffer();
729                 disconnectBufferView();
730                 hideBufferDependent();
731                 d.current_work_area_ = 0;
732         }
733
734         // removing a work area often results from closing a file so
735         // update the toc in any case.
736         updateToc();
737
738         for (int i = 0; i != d.splitter_->count(); ++i) {
739                 TabWorkArea * twa = d.tabWorkArea(i);
740                 if (!twa->removeWorkArea(wa))
741                         // Not found in this tab group.
742                         continue;
743
744                 // We found and removed the GuiWorkArea.
745                 if (!twa->count()) {
746                         // No more WorkAreas in this tab group, so delete it.
747                         delete twa;
748                         break;
749                 }
750
751                 if (d.current_work_area_)
752                         // This means that we are not closing the current GuiWorkArea;
753                         break;
754
755                 // Switch to the next GuiWorkArea in the found TabWorkArea.
756                 d.current_work_area_ = twa->currentWorkArea();
757                 break;
758         }
759
760         if (d.splitter_->count() == 0)
761                 // No more work area, switch to the background widget.
762                 d.setBackground();
763 }
764
765
766 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
767 {
768         d.layout_ = layout;
769 }
770
771
772 void GuiView::updateLayoutList()
773 {
774         if (d.layout_)
775                 d.layout_->updateContents(false);
776 }
777
778
779 void GuiView::updateToolbars()
780 {
781         if (d.current_work_area_) {
782                 bool const math =
783                         d.current_work_area_->bufferView().cursor().inMathed();
784                 bool const table =
785                         lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
786                 bool const review =
787                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
788                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
789
790                 d.toolbars_->update(math, table, review);
791         } else
792                 d.toolbars_->update(false, false, false);
793
794         // update read-only status of open dialogs.
795         checkStatus();
796 }
797
798
799 Buffer * GuiView::buffer()
800 {
801         if (d.current_work_area_)
802                 return &d.current_work_area_->bufferView().buffer();
803         return 0;
804 }
805
806
807 Buffer const * GuiView::buffer() const
808 {
809         if (d.current_work_area_)
810                 return &d.current_work_area_->bufferView().buffer();
811         return 0;
812 }
813
814
815 void GuiView::setBuffer(Buffer * newBuffer)
816 {
817         BOOST_ASSERT(newBuffer);
818         setBusy(true);
819
820         GuiWorkArea * wa = workArea(*newBuffer);
821         if (wa == 0) {
822                 updateLabels(*newBuffer->masterBuffer());
823                 wa = addWorkArea(*newBuffer);
824         } else {
825                 //Disconnect the old buffer...there's no new one.
826                 disconnectBuffer();
827         }
828         connectBuffer(*newBuffer);
829         connectBufferView(wa->bufferView());
830         setCurrentWorkArea(wa);
831
832         setBusy(false);
833 }
834
835
836 void GuiView::connectBuffer(Buffer & buf)
837 {
838         buf.setGuiDelegate(this);
839 }
840
841
842 void GuiView::disconnectBuffer()
843 {
844         if (d.current_work_area_)
845                 d.current_work_area_->bufferView().setGuiDelegate(0);
846 }
847
848
849 void GuiView::connectBufferView(BufferView & bv)
850 {
851         bv.setGuiDelegate(this);
852 }
853
854
855 void GuiView::disconnectBufferView()
856 {
857         if (d.current_work_area_)
858                 d.current_work_area_->bufferView().setGuiDelegate(0);
859 }
860
861
862 void GuiView::errors(string const & error_type)
863 {
864         ErrorList & el = buffer()->errorList(error_type);
865         if (!el.empty())
866                 showDialog("errorlist", error_type);
867 }
868
869
870 void GuiView::updateDialog(string const & name, string const & data)
871 {
872         if (!isDialogVisible(name))
873                 return;
874
875         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
876         if (it == d.dialogs_.end())
877                 return;
878
879         Dialog * const dialog = it->second.get();
880         if (dialog->isVisibleView())
881                 dialog->updateData(data);
882 }
883
884
885 BufferView * GuiView::view()
886 {
887         return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
888 }
889
890
891 void GuiView::updateToc()
892 {
893         updateDialog("toc", "");
894 }
895
896
897 void GuiView::updateEmbeddedFiles()
898 {
899         updateDialog("embedding", "");
900 }
901
902
903 void GuiView::autoSave()
904 {
905         LYXERR(Debug::INFO, "Running autoSave()");
906
907         if (buffer())
908                 view()->buffer().autoSave();
909 }
910
911
912 void GuiView::resetAutosaveTimers()
913 {
914         if (lyxrc.autosave)
915                 d.autosave_timeout_.restart();
916 }
917
918
919 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
920 {
921         FuncStatus flag;
922         bool enable = true;
923         Buffer * buf = buffer();
924
925         /* In LyX/Mac, when a dialog is open, the menus of the
926            application can still be accessed without giving focus to
927            the main window. In this case, we want to disable the menu
928            entries that are buffer-related.
929
930            Note that this code is not perfect, as bug 1941 attests:
931            http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
932         */
933         if (cmd.origin == FuncRequest::MENU && !hasFocus())
934                 buf = 0;
935
936         switch(cmd.action) {
937         case LFUN_TOOLBAR_TOGGLE:
938                 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
939                 break;
940
941         case LFUN_DIALOG_TOGGLE:
942                 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
943                 // fall through to set "enable"
944         case LFUN_DIALOG_SHOW: {
945                 string const name = cmd.getArg(0);
946                 if (!buf)
947                         enable = name == "aboutlyx"
948                                 || name == "file" //FIXME: should be removed.
949                                 || name == "prefs"
950                                 || name == "texinfo";
951                 else if (name == "print")
952                         enable = buf->isExportable("dvi")
953                                 && lyxrc.print_command != "none";
954                 else if (name == "character") {
955                         if (!view())
956                                 enable = false;
957                         else {
958                                 InsetCode ic = view()->cursor().inset().lyxCode();
959                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
960                         }
961                 }
962                 else if (name == "latexlog")
963                         enable = FileName(buf->logName()).isReadableFile();
964                 else if (name == "spellchecker")
965 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
966                         enable = !buf->isReadonly();
967 #else
968                         enable = false;
969 #endif
970                 else if (name == "vclog")
971                         enable = buf->lyxvc().inUse();
972                 break;
973         }
974
975         case LFUN_DIALOG_UPDATE: {
976                 string const name = cmd.getArg(0);
977                 if (!buf)
978                         enable = name == "prefs";
979                 break;
980         }
981
982         case LFUN_INSET_APPLY: {
983                 if (!buf) {
984                         enable = false;
985                         break;
986                 }
987                 string const name = cmd.getArg(0);
988                 Inset * inset = getOpenInset(name);
989                 if (inset) {
990                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
991                         FuncStatus fs;
992                         if (!inset->getStatus(view()->cursor(), fr, fs)) {
993                                 // Every inset is supposed to handle this
994                                 BOOST_ASSERT(false);
995                         }
996                         flag |= fs;
997                 } else {
998                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
999                         flag |= getStatus(fr);
1000                 }
1001                 enable = flag.enabled();
1002                 break;
1003         }
1004
1005         default:
1006                 if (!view()) {
1007                         enable = false;
1008                         break;
1009                 }
1010         }
1011
1012         if (!enable)
1013                 flag.enabled(false);
1014
1015         return flag;
1016 }
1017
1018
1019 bool GuiView::dispatch(FuncRequest const & cmd)
1020 {
1021         BufferView * bv = view();       
1022         // By default we won't need any update.
1023         if (bv)
1024                 bv->cursor().updateFlags(Update::None);
1025
1026         switch(cmd.action) {
1027                 case LFUN_BUFFER_SWITCH:
1028                         setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1029                         break;
1030
1031                 case LFUN_BUFFER_NEXT:
1032                         setBuffer(theBufferList().next(buffer()));
1033                         break;
1034
1035                 case LFUN_BUFFER_PREVIOUS:
1036                         setBuffer(theBufferList().previous(buffer()));
1037                         break;
1038
1039                 case LFUN_COMMAND_EXECUTE: {
1040                         bool const show_it = cmd.argument() != "off";
1041                         d.toolbars_->showCommandBuffer(show_it);
1042                         break;
1043                 }
1044                 case LFUN_DROP_LAYOUTS_CHOICE:
1045                         if (d.layout_)
1046                                 d.layout_->showPopup();
1047                         break;
1048
1049                 case LFUN_MENU_OPEN:
1050                         d.menubar_->openByName(toqstr(cmd.argument()));
1051                         break;
1052
1053                 case LFUN_TOOLBAR_TOGGLE: {
1054                         string const name = cmd.getArg(0);
1055                         bool const allowauto = cmd.getArg(1) == "allowauto";
1056                         // it is possible to get current toolbar status like this,...
1057                         // but I decide to obey the order of ToolbarBackend::flags
1058                         // and disregard real toolbar status.
1059                         // toolbars_->saveToolbarInfo();
1060                         //
1061                         // toggle state on/off/auto
1062                         d.toolbars_->toggleToolbarState(name, allowauto);
1063                         // update toolbar
1064                         updateToolbars();
1065
1066                         ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1067                         if (!tbi) {
1068                                 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1069                                 break;
1070                         }
1071                         docstring state;
1072                         if (tbi->flags & ToolbarInfo::ON)
1073                                 state = _("on");
1074                         else if (tbi->flags & ToolbarInfo::OFF)
1075                                 state = _("off");
1076                         else if (tbi->flags & ToolbarInfo::AUTO)
1077                                 state = _("auto");
1078
1079                         message(bformat(_("Toolbar \"%1$s\" state set to %2$s"), 
1080                                            _(tbi->gui_name), state));
1081                         break;
1082                 }
1083
1084                 case LFUN_DIALOG_UPDATE: {
1085                         string const name = to_utf8(cmd.argument());
1086                         // Can only update a dialog connected to an existing inset
1087                         Inset * inset = getOpenInset(name);
1088                         if (inset) {
1089                                 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1090                                 inset->dispatch(view()->cursor(), fr);
1091                         } else if (name == "paragraph") {
1092                                 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1093                         } else if (name == "prefs") {
1094                                 updateDialog(name, string());
1095                         }
1096                         break;
1097                 }
1098
1099                 case LFUN_DIALOG_TOGGLE: {
1100                         if (isDialogVisible(cmd.getArg(0)))
1101                                 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1102                         else
1103                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1104                         break;
1105                 }
1106
1107                 case LFUN_DIALOG_DISCONNECT_INSET:
1108                         disconnectDialog(to_utf8(cmd.argument()));
1109                         break;
1110
1111                 case LFUN_DIALOG_HIDE: {
1112                         if (quitting)
1113                                 break;
1114                         guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1115                         break;
1116                 }
1117
1118                 case LFUN_DIALOG_SHOW: {
1119                         string const name = cmd.getArg(0);
1120                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1121
1122                         if (name == "character") {
1123                                 data = freefont2string();
1124                                 if (!data.empty())
1125                                         showDialog("character", data);
1126                         } else if (name == "latexlog") {
1127                                 Buffer::LogType type; 
1128                                 string const logfile = buffer()->logName(&type);
1129                                 switch (type) {
1130                                 case Buffer::latexlog:
1131                                         data = "latex ";
1132                                         break;
1133                                 case Buffer::buildlog:
1134                                         data = "literate ";
1135                                         break;
1136                                 }
1137                                 data += Lexer::quoteString(logfile);
1138                                 showDialog("log", data);
1139                         } else if (name == "vclog") {
1140                                 string const data = "vc " +
1141                                         Lexer::quoteString(buffer()->lyxvc().getLogFile());
1142                                 showDialog("log", data);
1143                         } else
1144                                 showDialog(name, data);
1145                         break;
1146                 }
1147
1148                 case LFUN_INSET_APPLY: {
1149                         string const name = cmd.getArg(0);
1150                         Inset * inset = getOpenInset(name);
1151                         if (inset) {
1152                                 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1153                                 inset->dispatch(view()->cursor(), fr);
1154                         } else {
1155                                 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1156                                 lyx::dispatch(fr);
1157                         }
1158                         break;
1159                 }
1160
1161                 default:
1162                         return false;
1163         }
1164
1165         return true;
1166 }
1167
1168
1169 Buffer const * GuiView::updateInset(Inset const * inset)
1170 {
1171         if (!d.current_work_area_)
1172                 return 0;
1173
1174         if (inset)
1175                 d.current_work_area_->scheduleRedraw();
1176
1177         return &d.current_work_area_->bufferView().buffer();
1178 }
1179
1180
1181 void GuiView::restartCursor()
1182 {
1183         /* When we move around, or type, it's nice to be able to see
1184          * the cursor immediately after the keypress.
1185          */
1186         if (d.current_work_area_)
1187                 d.current_work_area_->startBlinkingCursor();
1188
1189         // Take this occasion to update the toobars and layout list.
1190         updateLayoutList();
1191         updateToolbars();
1192 }
1193
1194 namespace {
1195
1196 // This list should be kept in sync with the list of insets in
1197 // src/insets/Inset.cpp.  I.e., if a dialog goes with an inset, the
1198 // dialog should have the same name as the inset.
1199
1200 char const * const dialognames[] = {
1201 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1202 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1203 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1204 "mathdelimiter", "mathmatrix", "note", "paragraph",
1205 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1206
1207 #ifdef HAVE_LIBAIKSAURUS
1208 "thesaurus",
1209 #endif
1210
1211 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1212
1213 char const * const * const end_dialognames =
1214         dialognames + (sizeof(dialognames) / sizeof(char *));
1215
1216 class cmpCStr {
1217 public:
1218         cmpCStr(char const * name) : name_(name) {}
1219         bool operator()(char const * other) {
1220                 return strcmp(other, name_) == 0;
1221         }
1222 private:
1223         char const * name_;
1224 };
1225
1226
1227 bool isValidName(string const & name)
1228 {
1229         return std::find_if(dialognames, end_dialognames,
1230                             cmpCStr(name.c_str())) != end_dialognames;
1231 }
1232
1233 } // namespace anon
1234
1235
1236 void GuiView::resetDialogs()
1237 {
1238         // Make sure that no LFUN uses any LyXView.
1239         theLyXFunc().setLyXView(0);
1240         d.toolbars_->init();
1241         d.menubar_->init();
1242         if (d.layout_)
1243                 d.layout_->updateContents(true);
1244         // Now update controls with current buffer.
1245         theLyXFunc().setLyXView(this);
1246         restartCursor();
1247 }
1248
1249
1250 Dialog * GuiView::find_or_build(string const & name)
1251 {
1252         if (!isValidName(name))
1253                 return 0;
1254
1255         std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1256
1257         if (it != d.dialogs_.end())
1258                 return it->second.get();
1259
1260         d.dialogs_[name].reset(build(name));
1261         return d.dialogs_[name].get();
1262 }
1263
1264
1265 void GuiView::showDialog(string const & name, string const & data,
1266         Inset * inset)
1267 {
1268         if (d.in_show_)
1269                 return;
1270
1271         d.in_show_ = true;
1272         Dialog * dialog = find_or_build(name);
1273         if (dialog) {
1274                 dialog->showData(data);
1275                 if (inset)
1276                         d.open_insets_[name] = inset;
1277         }
1278         d.in_show_ = false;
1279 }
1280
1281
1282 bool GuiView::isDialogVisible(string const & name) const
1283 {
1284         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1285         if (it == d.dialogs_.end())
1286                 return false;
1287         return it->second.get()->isVisibleView();
1288 }
1289
1290
1291 void GuiView::hideDialog(string const & name, Inset * inset)
1292 {
1293         // Don't send the signal if we are quitting, because on MSVC it is
1294         // destructed before the cut stack in CutAndPaste.cpp, and this method
1295         // is called from some inset destructor if the cut stack is not empty
1296         // on exit.
1297         if (quitting)
1298                 return;
1299
1300         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1301         if (it == d.dialogs_.end())
1302                 return;
1303
1304         if (inset && inset != getOpenInset(name))
1305                 return;
1306
1307         Dialog * const dialog = it->second.get();
1308         if (dialog->isVisibleView())
1309                 dialog->hide();
1310         d.open_insets_[name] = 0;
1311 }
1312
1313
1314 void GuiView::disconnectDialog(string const & name)
1315 {
1316         if (!isValidName(name))
1317                 return;
1318
1319         if (d.open_insets_.find(name) != d.open_insets_.end())
1320                 d.open_insets_[name] = 0;
1321 }
1322
1323
1324 Inset * GuiView::getOpenInset(string const & name) const
1325 {
1326         if (!isValidName(name))
1327                 return 0;
1328
1329         std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1330         return it == d.open_insets_.end() ? 0 : it->second;
1331 }
1332
1333
1334 void GuiView::hideAll() const
1335 {
1336         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1337         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1338
1339         for(; it != end; ++it)
1340                 it->second->hide();
1341 }
1342
1343
1344 void GuiView::hideBufferDependent() const
1345 {
1346         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1347         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1348
1349         for(; it != end; ++it) {
1350                 Dialog * dialog = it->second.get();
1351                 if (dialog->isBufferDependent())
1352                         dialog->hide();
1353         }
1354 }
1355
1356
1357 void GuiView::updateBufferDependent(bool switched) const
1358 {
1359         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1360         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1361
1362         for(; it != end; ++it) {
1363                 Dialog * dialog = it->second.get();
1364                 if (switched && dialog->isBufferDependent()) {
1365                         if (dialog->isVisibleView() && dialog->initialiseParams(""))
1366                                 dialog->updateView();
1367                         else
1368                                 dialog->hide();
1369                 } else {
1370                         // A bit clunky, but the dialog will request
1371                         // that the kernel provides it with the necessary
1372                         // data.
1373                         dialog->updateDialog();
1374                 }
1375         }
1376 }
1377
1378
1379 void GuiView::checkStatus()
1380 {
1381         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1382         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1383
1384         for(; it != end; ++it) {
1385                 Dialog * const dialog = it->second.get();
1386                 if (dialog && dialog->isVisibleView())
1387                         dialog->checkStatus();
1388         }
1389 }
1390
1391
1392
1393 // will be replaced by a proper factory...
1394 Dialog * createGuiAbout(GuiView & lv);
1395 Dialog * createGuiBibitem(GuiView & lv);
1396 Dialog * createGuiBibtex(GuiView & lv);
1397 Dialog * createGuiBox(GuiView & lv);
1398 Dialog * createGuiBranch(GuiView & lv);
1399 Dialog * createGuiChanges(GuiView & lv);
1400 Dialog * createGuiCharacter(GuiView & lv);
1401 Dialog * createGuiCitation(GuiView & lv);
1402 Dialog * createGuiDelimiter(GuiView & lv);
1403 Dialog * createGuiDocument(GuiView & lv);
1404 Dialog * createGuiErrorList(GuiView & lv);
1405 Dialog * createGuiERT(GuiView & lv);
1406 Dialog * createGuiExternal(GuiView & lv);
1407 Dialog * createGuiFloat(GuiView & lv);
1408 Dialog * createGuiGraphics(GuiView & lv);
1409 Dialog * createGuiInclude(GuiView & lv);
1410 Dialog * createGuiIndex(GuiView & lv);
1411 Dialog * createGuiLabel(GuiView & lv);
1412 Dialog * createGuiListings(GuiView & lv);
1413 Dialog * createGuiLog(GuiView & lv);
1414 Dialog * createGuiMathMatrix(GuiView & lv);
1415 Dialog * createGuiNomenclature(GuiView & lv);
1416 Dialog * createGuiNote(GuiView & lv);
1417 Dialog * createGuiParagraph(GuiView & lv);
1418 Dialog * createGuiPreferences(GuiView & lv);
1419 Dialog * createGuiPrint(GuiView & lv);
1420 Dialog * createGuiRef(GuiView & lv);
1421 Dialog * createGuiSearch(GuiView & lv);
1422 Dialog * createGuiSendTo(GuiView & lv);
1423 Dialog * createGuiShowFile(GuiView & lv);
1424 Dialog * createGuiSpellchecker(GuiView & lv);
1425 Dialog * createGuiTabularCreate(GuiView & lv);
1426 Dialog * createGuiTabular(GuiView & lv);
1427 Dialog * createGuiTexInfo(GuiView & lv);
1428 Dialog * createGuiToc(GuiView & lv);
1429 Dialog * createGuiThesaurus(GuiView & lv);
1430 Dialog * createGuiHyperlink(GuiView & lv);
1431 Dialog * createGuiVSpace(GuiView & lv);
1432 Dialog * createGuiViewSource(GuiView & lv);
1433 Dialog * createGuiWrap(GuiView & lv);
1434
1435
1436 Dialog * GuiView::build(string const & name)
1437 {
1438         BOOST_ASSERT(isValidName(name));
1439
1440         if (name == "aboutlyx")
1441                 return createGuiAbout(*this);
1442         if (name == "bibitem")
1443                 return createGuiBibitem(*this);
1444         if (name == "bibtex")
1445                 return createGuiBibtex(*this);
1446         if (name == "box")
1447                 return createGuiBox(*this);
1448         if (name == "branch")
1449                 return createGuiBranch(*this);
1450         if (name == "changes")
1451                 return createGuiChanges(*this);
1452         if (name == "character")
1453                 return createGuiCharacter(*this);
1454         if (name == "citation")
1455                 return createGuiCitation(*this);
1456         if (name == "document")
1457                 return createGuiDocument(*this);
1458         if (name == "errorlist")
1459                 return createGuiErrorList(*this);
1460         if (name == "ert")
1461                 return createGuiERT(*this);
1462         if (name == "external")
1463                 return createGuiExternal(*this);
1464         if (name == "file")
1465                 return createGuiShowFile(*this);
1466         if (name == "findreplace")
1467                 return createGuiSearch(*this);
1468         if (name == "float")
1469                 return createGuiFloat(*this);
1470         if (name == "graphics")
1471                 return createGuiGraphics(*this);
1472         if (name == "include")
1473                 return createGuiInclude(*this);
1474         if (name == "index")
1475                 return createGuiIndex(*this);
1476         if (name == "nomenclature")
1477                 return createGuiNomenclature(*this);
1478         if (name == "label")
1479                 return createGuiLabel(*this);
1480         if (name == "log")
1481                 return createGuiLog(*this);
1482         if (name == "view-source")
1483                 return createGuiViewSource(*this);
1484         if (name == "mathdelimiter")
1485                 return createGuiDelimiter(*this);
1486         if (name == "mathmatrix")
1487                 return createGuiMathMatrix(*this);
1488         if (name == "note")
1489                 return createGuiNote(*this);
1490         if (name == "paragraph")
1491                 return createGuiParagraph(*this);
1492         if (name == "prefs")
1493                 return createGuiPreferences(*this);
1494         if (name == "print")
1495                 return createGuiPrint(*this);
1496         if (name == "ref")
1497                 return createGuiRef(*this);
1498         if (name == "sendto")
1499                 return createGuiSendTo(*this);
1500         if (name == "spellchecker")
1501                 return createGuiSpellchecker(*this);
1502         if (name == "tabular")
1503                 return createGuiTabular(*this);
1504         if (name == "tabularcreate")
1505                 return createGuiTabularCreate(*this);
1506         if (name == "texinfo")
1507                 return createGuiTexInfo(*this);
1508 #ifdef HAVE_LIBAIKSAURUS
1509         if (name == "thesaurus")
1510                 return createGuiThesaurus(*this);
1511 #endif
1512         if (name == "toc")
1513                 return createGuiToc(*this);
1514         if (name == "href")
1515                 return createGuiHyperlink(*this);
1516         if (name == "vspace")
1517                 return createGuiVSpace(*this);
1518         if (name == "wrap")
1519                 return createGuiWrap(*this);
1520         if (name == "listings")
1521                 return createGuiListings(*this);
1522
1523         return 0;
1524 }
1525
1526
1527 } // namespace frontend
1528 } // namespace lyx
1529
1530 #include "GuiView_moc.cpp"