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