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