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