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