3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * \author Abdelrazak Younes
11 * Full author contact details are available in file CREDITS.
19 #include "FileDialog.h"
20 #include "GuiApplication.h"
21 #include "GuiWorkArea.h"
22 #include "GuiKeySymbol.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
27 #include "qt_helpers.h"
29 #include "frontends/alert.h"
31 #include "buffer_funcs.h"
33 #include "BufferList.h"
34 #include "BufferParams.h"
35 #include "BufferView.h"
36 #include "Converter.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "support/gettext.h"
49 #include "Paragraph.h"
50 #include "TextClass.h"
52 #include "ToolbarBackend.h"
55 #include "support/debug.h"
56 #include "support/FileFilterList.h"
57 #include "support/FileName.h"
58 #include "support/filetools.h"
59 #include "support/ForkedCalls.h"
60 #include "support/lstrings.h"
61 #include "support/os.h"
62 #include "support/Package.h"
63 #include "support/Timeout.h"
66 #include <QApplication>
67 #include <QCloseEvent>
69 #include <QDesktopWidget>
70 #include <QDragEnterEvent>
78 #include <QPushButton>
82 #include <QStackedWidget>
89 #include <boost/assert.hpp>
90 #include <boost/bind.hpp>
92 #ifdef HAVE_SYS_TIME_H
93 # include <sys/time.h>
100 using namespace lyx::support;
104 extern bool quitting;
110 class BackgroundWidget : public QWidget
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 ? lyx_version : qt_("unknown version");
118 splash_ = QPixmap(":/images/banner.png");
120 QPainter pain(&splash_);
121 pain.setPen(QColor(255, 255, 0));
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()));
128 pain.drawText(260, 270, text);
131 void paintEvent(QPaintEvent *)
133 int x = (width() - splash_.width()) / 2;
134 int y = (height() - splash_.height()) / 2;
136 pain.drawPixmap(x, y, splash_);
146 typedef boost::shared_ptr<Dialog> DialogPtr;
148 struct GuiView::GuiViewPrivate
151 : current_work_area_(0), layout_(0),
152 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
154 // hardcode here the platform specific icon size
155 smallIconSize = 14; // scaling problems
156 normalIconSize = 20; // ok, default
157 bigIconSize = 26; // better for some math icons
159 splitter_ = new QSplitter;
160 bg_widget_ = new BackgroundWidget;
161 stack_widget_ = new QStackedWidget;
162 stack_widget_->addWidget(bg_widget_);
163 stack_widget_->addWidget(splitter_);
171 delete stack_widget_;
175 QMenu * toolBarPopup(GuiView * parent)
177 // FIXME: translation
178 QMenu * menu = new QMenu(parent);
179 QActionGroup * iconSizeGroup = new QActionGroup(parent);
181 QAction * smallIcons = new QAction(iconSizeGroup);
182 smallIcons->setText(qt_("Small-sized icons"));
183 smallIcons->setCheckable(true);
184 QObject::connect(smallIcons, SIGNAL(triggered()),
185 parent, SLOT(smallSizedIcons()));
186 menu->addAction(smallIcons);
188 QAction * normalIcons = new QAction(iconSizeGroup);
189 normalIcons->setText(qt_("Normal-sized icons"));
190 normalIcons->setCheckable(true);
191 QObject::connect(normalIcons, SIGNAL(triggered()),
192 parent, SLOT(normalSizedIcons()));
193 menu->addAction(normalIcons);
195 QAction * bigIcons = new QAction(iconSizeGroup);
196 bigIcons->setText(qt_("Big-sized icons"));
197 bigIcons->setCheckable(true);
198 QObject::connect(bigIcons, SIGNAL(triggered()),
199 parent, SLOT(bigSizedIcons()));
200 menu->addAction(bigIcons);
202 unsigned int cur = parent->iconSize().width();
203 if ( cur == parent->d.smallIconSize)
204 smallIcons->setChecked(true);
205 else if (cur == parent->d.normalIconSize)
206 normalIcons->setChecked(true);
207 else if (cur == parent->d.bigIconSize)
208 bigIcons->setChecked(true);
215 stack_widget_->setCurrentWidget(bg_widget_);
216 bg_widget_->setUpdatesEnabled(true);
219 TabWorkArea * tabWorkArea(int i)
221 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
224 TabWorkArea * currentTabWorkArea()
226 if (splitter_->count() == 1)
227 // The first TabWorkArea is always the first one, if any.
228 return tabWorkArea(0);
230 TabWorkArea * tab_widget = 0;
231 for (int i = 0; i != splitter_->count(); ++i) {
232 QWidget * w = splitter_->widget(i);
235 tab_widget = dynamic_cast<TabWorkArea *>(w);
244 GuiWorkArea * current_work_area_;
245 QSplitter * splitter_;
246 QStackedWidget * stack_widget_;
247 BackgroundWidget * bg_widget_;
249 GuiToolbars * toolbars_;
250 /// The main layout box.
252 * \warning Don't Delete! The layout box is actually owned by
253 * whichever toolbar contains it. All the GuiView class needs is a
254 * means of accessing it.
256 * FIXME: replace that with a proper model so that we are not limited
257 * to only one dialog.
259 GuiLayoutBox * layout_;
262 map<string, Inset *> open_insets_;
265 map<string, DialogPtr> dialogs_;
267 unsigned int smallIconSize;
268 unsigned int normalIconSize;
269 unsigned int bigIconSize;
271 QTimer statusbar_timer_;
272 /// are we quitting by the menu?
273 bool quitting_by_menu_;
274 /// auto-saving of buffers
275 Timeout autosave_timeout_;
276 /// flag against a race condition due to multiclicks, see bug #1119
281 GuiView::GuiView(int id)
282 : d(*new GuiViewPrivate), id_(id)
284 // GuiToolbars *must* be initialised before the menu bar.
285 d.toolbars_ = new GuiToolbars(*this);
287 // Fill up the menu bar.
288 guiApp->menus().fillMenuBar(this);
290 setCentralWidget(d.stack_widget_);
292 // Start autosave timer
293 if (lyxrc.autosave) {
294 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
295 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
296 d.autosave_timeout_.start();
298 connect(&d.statusbar_timer_, SIGNAL(timeout()),
299 this, SLOT(clearMessage()));
301 // Qt bug? signal lastWindowClosed does not work
302 setAttribute(Qt::WA_QuitOnClose, false);
303 setAttribute(Qt::WA_DeleteOnClose, true);
305 // assign an icon to main form. We do not do it under Qt/Mac,
306 // since the icon is provided in the application bundle.
307 setWindowIcon(QPixmap(":/images/lyx.png"));
311 setAcceptDrops(true);
313 statusBar()->setSizeGripEnabled(true);
315 // Forbid too small unresizable window because it can happen
316 // with some window manager under X11.
317 setMinimumSize(300, 200);
319 if (!lyxrc.allow_geometry_session)
320 // No session handling, default to a sane size.
321 setGeometry(50, 50, 690, 510);
323 // Now take care of session management.
325 QString const key = "view-" + QString::number(id_);
327 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
328 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
332 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
333 setGeometry(50, 50, 690, 510);
335 setIconSize(settings.value(key + "/icon_size").toSize());
345 void GuiView::close()
347 d.quitting_by_menu_ = true;
348 d.current_work_area_ = 0;
349 for (int i = 0; i != d.splitter_->count(); ++i) {
350 TabWorkArea * twa = d.tabWorkArea(i);
354 QMainWindow::close();
355 d.quitting_by_menu_ = false;
359 void GuiView::setFocus()
361 if (d.current_work_area_)
362 d.current_work_area_->setFocus();
368 QMenu * GuiView::createPopupMenu()
370 return d.toolBarPopup(this);
374 void GuiView::showEvent(QShowEvent * e)
376 LYXERR(Debug::GUI, "Passed Geometry "
377 << size().height() << "x" << size().width()
378 << "+" << pos().x() << "+" << pos().y());
380 if (d.splitter_->count() == 0)
381 // No work area, switch to the background widget.
384 QMainWindow::showEvent(e);
388 void GuiView::closeEvent(QCloseEvent * close_event)
390 // we may have been called through the close window button
391 // which bypasses the LFUN machinery.
392 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
393 if (!quitWriteAll()) {
394 close_event->ignore();
399 // Make sure that no LFUN use this close to be closed View.
400 theLyXFunc().setLyXView(0);
401 // Make sure the timer time out will not trigger a statusbar update.
402 d.statusbar_timer_.stop();
404 if (lyxrc.allow_geometry_session) {
406 QString const key = "view-" + QString::number(id_);
408 settings.setValue(key + "/pos", pos());
409 settings.setValue(key + "/size", size());
411 settings.setValue(key + "/geometry", saveGeometry());
413 settings.setValue(key + "/icon_size", iconSize());
414 d.toolbars_->saveToolbarInfo();
415 // Now take care of all other dialogs:
416 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
417 for (; it!= d.dialogs_.end(); ++it)
418 it->second->saveSession();
421 guiApp->unregisterView(id_);
422 if (guiApp->viewCount() > 0) {
423 // Just close the window and do nothing else if this is not the
425 close_event->accept();
431 // this is the place where we leave the frontend.
432 // it is the only point at which we start quitting.
433 close_event->accept();
434 // quit the event loop
439 void GuiView::dragEnterEvent(QDragEnterEvent * event)
441 if (event->mimeData()->hasUrls())
443 /// \todo Ask lyx-devel is this is enough:
444 /// if (event->mimeData()->hasFormat("text/plain"))
445 /// event->acceptProposedAction();
449 void GuiView::dropEvent(QDropEvent* event)
451 QList<QUrl> files = event->mimeData()->urls();
455 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
456 for (int i = 0; i != files.size(); ++i) {
457 string const file = os::internal_path(fromqstr(
458 files.at(i).toLocalFile()));
460 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
465 void GuiView::message(docstring const & str)
467 if (ForkedProcess::iAmAChild())
470 statusBar()->showMessage(toqstr(str));
471 d.statusbar_timer_.stop();
472 d.statusbar_timer_.start(3000);
476 void GuiView::smallSizedIcons()
478 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
482 void GuiView::normalSizedIcons()
484 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
488 void GuiView::bigSizedIcons()
490 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
494 void GuiView::clearMessage()
498 theLyXFunc().setLyXView(this);
499 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
500 d.statusbar_timer_.stop();
504 void GuiView::updateWindowTitle(GuiWorkArea * wa)
506 if (wa != d.current_work_area_)
508 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
509 setWindowIconText(wa->windowIconText());
513 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
516 disconnectBufferView();
517 connectBufferView(wa->bufferView());
518 connectBuffer(wa->bufferView().buffer());
519 d.current_work_area_ = wa;
520 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
521 this, SLOT(updateWindowTitle(GuiWorkArea *)));
522 updateWindowTitle(wa);
525 // Buffer-dependent dialogs should be updated or
526 // hidden. This should go here because some dialogs (eg ToC)
527 // require bv_->text.
528 updateBufferDependent(true);
535 void GuiView::updateStatusBar()
537 // let the user see the explicit message
538 if (d.statusbar_timer_.isActive())
541 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
545 bool GuiView::hasFocus() const
547 return qApp->activeWindow() == this;
551 bool GuiView::event(QEvent * e)
555 // Useful debug code:
556 //case QEvent::ActivationChange:
557 //case QEvent::WindowDeactivate:
558 //case QEvent::Paint:
559 //case QEvent::Enter:
560 //case QEvent::Leave:
561 //case QEvent::HoverEnter:
562 //case QEvent::HoverLeave:
563 //case QEvent::HoverMove:
564 //case QEvent::StatusTip:
565 //case QEvent::DragEnter:
566 //case QEvent::DragLeave:
570 case QEvent::WindowActivate: {
571 guiApp->setCurrentView(*this);
572 if (d.current_work_area_) {
573 BufferView & bv = d.current_work_area_->bufferView();
574 connectBufferView(bv);
575 connectBuffer(bv.buffer());
576 // The document structure, name and dialogs might have
577 // changed in another view.
578 updateBufferDependent(true);
583 setWindowTitle(qt_("LyX"));
584 setWindowIconText(qt_("LyX"));
586 return QMainWindow::event(e);
589 case QEvent::ShortcutOverride: {
590 if (d.current_work_area_)
591 // Nothing special to do.
592 return QMainWindow::event(e);
594 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
596 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
598 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
599 || ke->key() == Qt::Key_Backtab)
600 return QMainWindow::event(e);
602 // Allow processing of shortcuts that are allowed even when no Buffer
604 theLyXFunc().setLyXView(this);
606 setKeySymbol(&sym, ke);
607 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
613 return QMainWindow::event(e);
618 bool GuiView::focusNextPrevChild(bool /*next*/)
625 void GuiView::setBusy(bool busy)
627 if (d.current_work_area_) {
628 d.current_work_area_->setUpdatesEnabled(!busy);
630 d.current_work_area_->stopBlinkingCursor();
632 d.current_work_area_->startBlinkingCursor();
636 QApplication::setOverrideCursor(Qt::WaitCursor);
638 QApplication::restoreOverrideCursor();
642 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
644 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
646 if (tbinfo.flags & ToolbarInfo::TOP) {
648 addToolBarBreak(Qt::TopToolBarArea);
649 addToolBar(Qt::TopToolBarArea, toolBar);
652 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
653 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
654 #if (QT_VERSION >= 0x040202)
656 addToolBarBreak(Qt::BottomToolBarArea);
658 addToolBar(Qt::BottomToolBarArea, toolBar);
661 if (tbinfo.flags & ToolbarInfo::LEFT) {
662 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
663 #if (QT_VERSION >= 0x040202)
665 addToolBarBreak(Qt::LeftToolBarArea);
667 addToolBar(Qt::LeftToolBarArea, toolBar);
670 if (tbinfo.flags & ToolbarInfo::RIGHT) {
671 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
672 #if (QT_VERSION >= 0x040202)
674 addToolBarBreak(Qt::RightToolBarArea);
676 addToolBar(Qt::RightToolBarArea, toolBar);
679 // The following does not work so I cannot restore to exact toolbar location
681 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
682 toolBar->move(tbinfo.posx, tbinfo.posy);
689 GuiWorkArea * GuiView::workArea(Buffer & buffer)
691 for (int i = 0; i != d.splitter_->count(); ++i) {
692 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
700 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
703 // Automatically create a TabWorkArea if there are none yet.
704 if (!d.splitter_->count())
707 TabWorkArea * tab_widget = d.currentTabWorkArea();
708 return tab_widget->addWorkArea(buffer, *this);
712 void GuiView::addTabWorkArea()
714 TabWorkArea * twa = new TabWorkArea;
715 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
716 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
717 d.splitter_->addWidget(twa);
718 d.stack_widget_->setCurrentWidget(d.splitter_);
722 GuiWorkArea const * GuiView::currentWorkArea() const
724 return d.current_work_area_;
728 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
732 // Changing work area can result from opening a file so
733 // update the toc in any case.
736 d.current_work_area_ = wa;
737 for (int i = 0; i != d.splitter_->count(); ++i) {
738 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
744 void GuiView::removeWorkArea(GuiWorkArea * wa)
747 if (wa == d.current_work_area_) {
749 disconnectBufferView();
750 hideBufferDependent();
751 d.current_work_area_ = 0;
754 for (int i = 0; i != d.splitter_->count(); ++i) {
755 TabWorkArea * twa = d.tabWorkArea(i);
756 if (!twa->removeWorkArea(wa))
757 // Not found in this tab group.
760 // We found and removed the GuiWorkArea.
762 // No more WorkAreas in this tab group, so delete it.
767 if (d.current_work_area_)
768 // This means that we are not closing the current GuiWorkArea;
771 // Switch to the next GuiWorkArea in the found TabWorkArea.
772 d.current_work_area_ = twa->currentWorkArea();
776 if (d.splitter_->count() == 0)
777 // No more work area, switch to the background widget.
782 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
788 void GuiView::updateLayoutList()
791 d.layout_->updateContents(false);
795 void GuiView::updateToolbars()
797 if (d.current_work_area_) {
799 d.current_work_area_->bufferView().cursor().inMathed();
801 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
803 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
804 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
805 bool const mathmacrotemplate =
806 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
808 d.toolbars_->update(math, table, review, mathmacrotemplate);
810 d.toolbars_->update(false, false, false, false);
812 // update read-only status of open dialogs.
817 Buffer * GuiView::buffer()
819 if (d.current_work_area_)
820 return &d.current_work_area_->bufferView().buffer();
825 Buffer const * GuiView::buffer() const
827 if (d.current_work_area_)
828 return &d.current_work_area_->bufferView().buffer();
833 void GuiView::setBuffer(Buffer * newBuffer)
835 BOOST_ASSERT(newBuffer);
838 GuiWorkArea * wa = workArea(*newBuffer);
840 updateLabels(*newBuffer->masterBuffer());
841 wa = addWorkArea(*newBuffer);
843 //Disconnect the old buffer...there's no new one.
846 connectBuffer(*newBuffer);
847 connectBufferView(wa->bufferView());
848 setCurrentWorkArea(wa);
854 void GuiView::connectBuffer(Buffer & buf)
856 buf.setGuiDelegate(this);
860 void GuiView::disconnectBuffer()
862 if (d.current_work_area_)
863 d.current_work_area_->bufferView().setGuiDelegate(0);
867 void GuiView::connectBufferView(BufferView & bv)
869 bv.setGuiDelegate(this);
873 void GuiView::disconnectBufferView()
875 if (d.current_work_area_)
876 d.current_work_area_->bufferView().setGuiDelegate(0);
880 void GuiView::errors(string const & error_type)
882 ErrorList & el = buffer()->errorList(error_type);
884 showDialog("errorlist", error_type);
888 void GuiView::updateDialog(string const & name, string const & data)
890 if (!isDialogVisible(name))
893 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
894 if (it == d.dialogs_.end())
897 Dialog * const dialog = it->second.get();
898 if (dialog->isVisibleView())
899 dialog->updateData(data);
903 BufferView * GuiView::view()
905 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
909 void GuiView::updateToc()
911 updateDialog("toc", "");
915 void GuiView::updateEmbeddedFiles()
917 updateDialog("embedding", "");
921 void GuiView::autoSave()
923 LYXERR(Debug::INFO, "Running autoSave()");
926 view()->buffer().autoSave();
930 void GuiView::resetAutosaveTimers()
933 d.autosave_timeout_.restart();
937 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
941 Buffer * buf = buffer();
943 /* In LyX/Mac, when a dialog is open, the menus of the
944 application can still be accessed without giving focus to
945 the main window. In this case, we want to disable the menu
946 entries that are buffer-related.
948 Note that this code is not perfect, as bug 1941 attests:
949 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
951 if (cmd.origin == FuncRequest::MENU && !hasFocus())
955 case LFUN_BUFFER_WRITE:
956 enable = buf && (buf->isUnnamed() || !buf->isClean());
959 case LFUN_BUFFER_WRITE_AS:
963 case LFUN_TOOLBAR_TOGGLE:
964 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
967 case LFUN_DIALOG_TOGGLE:
968 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
969 // fall through to set "enable"
970 case LFUN_DIALOG_SHOW: {
971 string const name = cmd.getArg(0);
973 enable = name == "aboutlyx"
974 || name == "file" //FIXME: should be removed.
976 || name == "texinfo";
977 else if (name == "print")
978 enable = buf->isExportable("dvi")
979 && lyxrc.print_command != "none";
980 else if (name == "character") {
984 InsetCode ic = view()->cursor().inset().lyxCode();
985 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
988 else if (name == "symbols") {
989 if (!view() || view()->cursor().inMathed())
992 InsetCode ic = view()->cursor().inset().lyxCode();
993 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
996 else if (name == "latexlog")
997 enable = FileName(buf->logName()).isReadableFile();
998 else if (name == "spellchecker")
999 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1000 enable = !buf->isReadonly();
1004 else if (name == "vclog")
1005 enable = buf->lyxvc().inUse();
1009 case LFUN_DIALOG_UPDATE: {
1010 string const name = cmd.getArg(0);
1012 enable = name == "prefs";
1016 case LFUN_INSET_APPLY: {
1021 string const name = cmd.getArg(0);
1022 Inset * inset = getOpenInset(name);
1024 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1026 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1027 // Every inset is supposed to handle this
1028 BOOST_ASSERT(false);
1032 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1033 flag |= getStatus(fr);
1035 enable = flag.enabled();
1047 flag.enabled(false);
1053 static FileName selectTemplateFile()
1055 FileDialog dlg(_("Select template file"));
1056 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1057 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1059 FileDialog::Result result =
1060 dlg.open(from_utf8(lyxrc.template_path),
1061 FileFilterList(_("LyX Documents (*.lyx)")),
1064 if (result.first == FileDialog::Later)
1066 if (result.second.empty())
1068 return FileName(to_utf8(result.second));
1072 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1076 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1079 message(_("Document not loaded."));
1084 setBuffer(newBuffer);
1086 // scroll to the position when the file was last closed
1087 if (lyxrc.use_lastfilepos) {
1088 LastFilePosSection::FilePos filepos =
1089 LyX::ref().session().lastFilePos().load(filename);
1090 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1094 LyX::ref().session().lastFiles().add(filename);
1101 void GuiView::openDocument(string const & fname)
1103 string initpath = lyxrc.document_path;
1106 string const trypath = buffer()->filePath();
1107 // If directory is writeable, use this as default.
1108 if (FileName(trypath).isDirWritable())
1114 if (fname.empty()) {
1115 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1116 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1117 dlg.setButton2(_("Examples|#E#e"),
1118 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1120 FileDialog::Result result =
1121 dlg.open(from_utf8(initpath),
1122 FileFilterList(_("LyX Documents (*.lyx)")),
1125 if (result.first == FileDialog::Later)
1128 filename = to_utf8(result.second);
1130 // check selected filename
1131 if (filename.empty()) {
1132 message(_("Canceled."));
1138 // get absolute path of file and add ".lyx" to the filename if
1140 FileName const fullname =
1141 fileSearch(string(), filename, "lyx", support::may_not_exist);
1142 if (!fullname.empty())
1143 filename = fullname.absFilename();
1145 // if the file doesn't exist, let the user create one
1146 if (!fullname.exists()) {
1147 // the user specifically chose this name. Believe him.
1148 Buffer * const b = newFile(filename, string(), true);
1154 docstring const disp_fn = makeDisplayPath(filename);
1155 message(bformat(_("Opening document %1$s..."), disp_fn));
1158 Buffer * buf = loadDocument(fullname);
1162 buf->errors("Parse");
1163 str2 = bformat(_("Document %1$s opened."), disp_fn);
1165 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1170 // FIXME: clean that
1171 static bool import(GuiView * lv, FileName const & filename,
1172 string const & format, ErrorList & errorList)
1174 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1176 string loader_format;
1177 vector<string> loaders = theConverters().loaders();
1178 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1179 for (vector<string>::const_iterator it = loaders.begin();
1180 it != loaders.end(); ++it) {
1181 if (!theConverters().isReachable(format, *it))
1184 string const tofile =
1185 changeExtension(filename.absFilename(),
1186 formats.extension(*it));
1187 if (!theConverters().convert(0, filename, FileName(tofile),
1188 filename, format, *it, errorList))
1190 loader_format = *it;
1193 if (loader_format.empty()) {
1194 frontend::Alert::error(_("Couldn't import file"),
1195 bformat(_("No information for importing the format %1$s."),
1196 formats.prettyName(format)));
1200 loader_format = format;
1202 if (loader_format == "lyx") {
1203 Buffer * buf = lv->loadDocument(lyxfile);
1208 buf->errors("Parse");
1210 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1214 bool as_paragraphs = loader_format == "textparagraph";
1215 string filename2 = (loader_format == format) ? filename.absFilename()
1216 : changeExtension(filename.absFilename(),
1217 formats.extension(loader_format));
1218 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1219 theLyXFunc().setLyXView(lv);
1220 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1227 void GuiView::importDocument(string const & argument)
1230 string filename = split(argument, format, ' ');
1232 LYXERR(Debug::INFO, format << " file: " << filename);
1234 // need user interaction
1235 if (filename.empty()) {
1236 string initpath = lyxrc.document_path;
1238 Buffer const * buf = buffer();
1240 string const trypath = buf->filePath();
1241 // If directory is writeable, use this as default.
1242 if (FileName(trypath).isDirWritable())
1246 docstring const text = bformat(_("Select %1$s file to import"),
1247 formats.prettyName(format));
1249 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1250 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1251 dlg.setButton2(_("Examples|#E#e"),
1252 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1254 docstring filter = formats.prettyName(format);
1257 filter += from_utf8(formats.extension(format));
1260 FileDialog::Result result =
1261 dlg.open(from_utf8(initpath),
1262 FileFilterList(filter),
1265 if (result.first == FileDialog::Later)
1268 filename = to_utf8(result.second);
1270 // check selected filename
1271 if (filename.empty())
1272 message(_("Canceled."));
1275 if (filename.empty())
1278 // get absolute path of file
1279 FileName const fullname(makeAbsPath(filename));
1281 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1283 // Check if the document already is open
1284 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1287 if (!closeBuffer()) {
1288 message(_("Canceled."));
1293 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1295 // if the file exists already, and we didn't do
1296 // -i lyx thefile.lyx, warn
1297 if (lyxfile.exists() && fullname != lyxfile) {
1299 docstring text = bformat(_("The document %1$s already exists.\n\n"
1300 "Do you want to overwrite that document?"), displaypath);
1301 int const ret = Alert::prompt(_("Overwrite document?"),
1302 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1305 message(_("Canceled."));
1310 message(bformat(_("Importing %1$s..."), displaypath));
1311 ErrorList errorList;
1312 if (import(this, fullname, format, errorList))
1313 message(_("imported."));
1315 message(_("file not imported!"));
1317 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1321 void GuiView::newDocument(string const & filename, bool from_template)
1323 FileName initpath(lyxrc.document_path);
1324 Buffer * buf = buffer();
1326 FileName const trypath(buf->filePath());
1327 // If directory is writeable, use this as default.
1328 if (trypath.isDirWritable())
1332 string templatefile = from_template ?
1333 selectTemplateFile().absFilename() : string();
1335 if (filename.empty())
1336 b = newUnnamedFile(templatefile, initpath);
1338 b = newFile(filename, templatefile, true);
1342 // Ensure the cursor is correctly positionned on screen.
1343 view()->showCursor();
1347 void GuiView::insertLyXFile(docstring const & fname)
1349 BufferView * bv = view();
1354 FileName filename(to_utf8(fname));
1356 if (!filename.empty()) {
1357 bv->insertLyXFile(filename);
1361 // Launch a file browser
1363 string initpath = lyxrc.document_path;
1364 string const trypath = bv->buffer().filePath();
1365 // If directory is writeable, use this as default.
1366 if (FileName(trypath).isDirWritable())
1370 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1371 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1372 dlg.setButton2(_("Examples|#E#e"),
1373 from_utf8(addPath(package().system_support().absFilename(),
1376 FileDialog::Result result =
1377 dlg.open(from_utf8(initpath),
1378 FileFilterList(_("LyX Documents (*.lyx)")),
1381 if (result.first == FileDialog::Later)
1385 filename.set(to_utf8(result.second));
1387 // check selected filename
1388 if (filename.empty()) {
1389 // emit message signal.
1390 message(_("Canceled."));
1394 bv->insertLyXFile(filename);
1398 void GuiView::insertPlaintextFile(docstring const & fname,
1401 BufferView * bv = view();
1406 FileName filename(to_utf8(fname));
1408 if (!filename.empty()) {
1409 bv->insertPlaintextFile(filename, asParagraph);
1413 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1414 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1416 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1417 FileFilterList(), docstring());
1419 if (result.first == FileDialog::Later)
1423 filename.set(to_utf8(result.second));
1425 // check selected filename
1426 if (filename.empty()) {
1427 // emit message signal.
1428 message(_("Canceled."));
1432 bv->insertPlaintextFile(filename, asParagraph);
1436 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1438 FileName fname = b.fileName();
1439 FileName const oldname = fname;
1441 if (!newname.empty()) {
1443 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1445 // Switch to this Buffer.
1448 /// No argument? Ask user through dialog.
1450 FileDialog dlg(_("Choose a filename to save document as"),
1451 LFUN_BUFFER_WRITE_AS);
1452 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1453 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1455 if (!isLyXFilename(fname.absFilename()))
1456 fname.changeExtension(".lyx");
1458 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1460 FileDialog::Result result =
1461 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1463 from_utf8(fname.onlyFileName()));
1465 if (result.first == FileDialog::Later)
1468 fname.set(to_utf8(result.second));
1473 if (!isLyXFilename(fname.absFilename()))
1474 fname.changeExtension(".lyx");
1477 if (FileName(fname).exists()) {
1478 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1479 docstring text = bformat(_("The document %1$s already "
1480 "exists.\n\nDo you want to "
1481 "overwrite that document?"),
1483 int const ret = Alert::prompt(_("Overwrite document?"),
1484 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1487 case 1: return renameBuffer(b, docstring());
1488 case 2: return false;
1492 // Ok, change the name of the buffer
1493 b.setFileName(fname.absFilename());
1495 bool unnamed = b.isUnnamed();
1496 b.setUnnamed(false);
1497 b.saveCheckSum(fname);
1499 if (!saveBuffer(b)) {
1500 b.setFileName(oldname.absFilename());
1501 b.setUnnamed(unnamed);
1502 b.saveCheckSum(oldname);
1510 bool GuiView::saveBuffer(Buffer & b)
1513 return renameBuffer(b, docstring());
1516 LyX::ref().session().lastFiles().add(b.fileName());
1520 // Switch to this Buffer.
1523 // FIXME: we don't tell the user *WHY* the save failed !!
1524 docstring const file = makeDisplayPath(b.absFileName(), 30);
1525 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1526 "Do you want to rename the document and "
1527 "try again?"), file);
1528 int const ret = Alert::prompt(_("Rename and save?"),
1529 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1532 if (!renameBuffer(b, docstring()))
1541 return saveBuffer(b);
1545 bool GuiView::closeBuffer()
1547 Buffer * buf = buffer();
1548 return buf && closeBuffer(*buf);
1552 bool GuiView::closeBuffer(Buffer & buf)
1554 if (buf.isClean() || buf.paragraphs().empty()) {
1555 theBufferList().release(&buf);
1558 // Switch to this Buffer.
1563 if (buf.isUnnamed())
1564 file = from_utf8(buf.fileName().onlyFileName());
1566 file = buf.fileName().displayName(30);
1568 docstring const text = bformat(_("The document %1$s has unsaved changes."
1569 "\n\nDo you want to save the document or discard the changes?"), file);
1570 int const ret = Alert::prompt(_("Save changed document?"),
1571 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1575 if (!saveBuffer(buf))
1579 // if we crash after this we could
1580 // have no autosave file but I guess
1581 // this is really improbable (Jug)
1582 removeAutosaveFile(buf.absFileName());
1588 // save file names to .lyx/session
1589 // if master/slave are both open, do not save slave since it
1590 // will be automatically loaded when the master is loaded
1591 if (buf.masterBuffer() == &buf)
1592 LyX::ref().session().lastOpened().add(buf.fileName());
1594 theBufferList().release(&buf);
1599 bool GuiView::quitWriteAll()
1601 while (!theBufferList().empty()) {
1602 Buffer * b = theBufferList().first();
1603 if (!closeBuffer(*b))
1610 bool GuiView::dispatch(FuncRequest const & cmd)
1612 BufferView * bv = view();
1613 // By default we won't need any update.
1615 bv->cursor().updateFlags(Update::None);
1617 switch(cmd.action) {
1618 case LFUN_FILE_OPEN:
1619 openDocument(to_utf8(cmd.argument()));
1622 case LFUN_BUFFER_IMPORT:
1623 importDocument(to_utf8(cmd.argument()));
1626 case LFUN_BUFFER_SWITCH:
1627 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1630 case LFUN_BUFFER_NEXT:
1631 setBuffer(theBufferList().next(buffer()));
1634 case LFUN_BUFFER_PREVIOUS:
1635 setBuffer(theBufferList().previous(buffer()));
1638 case LFUN_COMMAND_EXECUTE: {
1639 bool const show_it = cmd.argument() != "off";
1640 d.toolbars_->showCommandBuffer(show_it);
1643 case LFUN_DROP_LAYOUTS_CHOICE:
1645 d.layout_->showPopup();
1648 case LFUN_MENU_OPEN:
1649 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1650 menu->exec(QCursor::pos());
1653 case LFUN_FILE_INSERT:
1654 insertLyXFile(cmd.argument());
1656 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1657 insertPlaintextFile(cmd.argument(), true);
1660 case LFUN_FILE_INSERT_PLAINTEXT:
1661 insertPlaintextFile(cmd.argument(), false);
1664 case LFUN_BUFFER_WRITE:
1666 saveBuffer(bv->buffer());
1669 case LFUN_BUFFER_WRITE_AS:
1671 renameBuffer(bv->buffer(), cmd.argument());
1674 case LFUN_BUFFER_WRITE_ALL: {
1675 Buffer * first = theBufferList().first();
1678 message(_("Saving all documents..."));
1679 // We cannot use a for loop as the buffer list cycles.
1685 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1686 b = theBufferList().next(b);
1687 } while (b != first);
1688 message(_("All documents saved."));
1692 case LFUN_TOOLBAR_TOGGLE: {
1693 string const name = cmd.getArg(0);
1694 bool const allowauto = cmd.getArg(1) == "allowauto";
1695 // it is possible to get current toolbar status like this,...
1696 // but I decide to obey the order of ToolbarBackend::flags
1697 // and disregard real toolbar status.
1698 // toolbars_->saveToolbarInfo();
1700 // toggle state on/off/auto
1701 d.toolbars_->toggleToolbarState(name, allowauto);
1705 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1707 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1711 if (tbi->flags & ToolbarInfo::ON)
1713 else if (tbi->flags & ToolbarInfo::OFF)
1715 else if (tbi->flags & ToolbarInfo::AUTO)
1718 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1719 _(tbi->gui_name), state));
1723 case LFUN_DIALOG_UPDATE: {
1724 string const name = to_utf8(cmd.argument());
1725 // Can only update a dialog connected to an existing inset
1726 Inset * inset = getOpenInset(name);
1728 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1729 inset->dispatch(view()->cursor(), fr);
1730 } else if (name == "paragraph") {
1731 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1732 } else if (name == "prefs") {
1733 updateDialog(name, string());
1738 case LFUN_DIALOG_TOGGLE: {
1739 if (isDialogVisible(cmd.getArg(0)))
1740 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1742 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1746 case LFUN_DIALOG_DISCONNECT_INSET:
1747 disconnectDialog(to_utf8(cmd.argument()));
1750 case LFUN_DIALOG_HIDE: {
1753 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1757 case LFUN_DIALOG_SHOW: {
1758 string const name = cmd.getArg(0);
1759 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1761 if (name == "character") {
1762 data = freefont2string();
1764 showDialog("character", data);
1765 } else if (name == "latexlog") {
1766 Buffer::LogType type;
1767 string const logfile = buffer()->logName(&type);
1769 case Buffer::latexlog:
1772 case Buffer::buildlog:
1776 data += Lexer::quoteString(logfile);
1777 showDialog("log", data);
1778 } else if (name == "vclog") {
1779 string const data = "vc " +
1780 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1781 showDialog("log", data);
1782 } else if (name == "symbols") {
1783 data = bv->cursor().getEncoding()->name();
1785 showDialog("symbols", data);
1787 showDialog(name, data);
1791 case LFUN_INSET_APPLY: {
1792 string const name = cmd.getArg(0);
1793 Inset * inset = getOpenInset(name);
1795 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1796 inset->dispatch(view()->cursor(), fr);
1798 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1804 case LFUN_UI_TOGGLE:
1816 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1818 string const arg = cmd.getArg(0);
1819 if (arg == "scrollbar") {
1820 // hide() is of no help
1821 if (d.current_work_area_->verticalScrollBarPolicy() ==
1822 Qt::ScrollBarAlwaysOff)
1824 d.current_work_area_->setVerticalScrollBarPolicy(
1825 Qt::ScrollBarAsNeeded);
1827 d.current_work_area_->setVerticalScrollBarPolicy(
1828 Qt::ScrollBarAlwaysOff);
1831 if (arg == "statusbar") {
1832 statusBar()->setVisible(!statusBar()->isVisible());
1835 if (arg == "menubar") {
1836 menuBar()->setVisible(!menuBar()->isVisible());
1839 #if QT_VERSION >= 0x040300
1840 if (arg == "frame") {
1842 getContentsMargins(&l, &t, &r, &b);
1843 //are the frames in default state?
1845 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1846 setContentsMargins(-2, -2, -2, -2);
1848 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1849 setContentsMargins(0, 0, 0, 0);
1854 if (arg != "fullscreen") {
1855 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1859 if (isFullScreen()) {
1861 #if QT_VERSION >= 0x040300
1862 setContentsMargins(0, 0, 0, 0);
1864 for (int i = 0; i != d.splitter_->count(); ++i)
1865 d.tabWorkArea(i)->setFullScreen(false);
1867 statusBar()->show();
1869 statusBar()->hide();
1871 for (int i = 0; i != d.splitter_->count(); ++i)
1872 d.tabWorkArea(i)->setFullScreen(true);
1873 #if QT_VERSION >= 0x040300
1874 setContentsMargins(-2, -2, -2, -2);
1881 Buffer const * GuiView::updateInset(Inset const * inset)
1883 if (!d.current_work_area_)
1887 d.current_work_area_->scheduleRedraw();
1889 return &d.current_work_area_->bufferView().buffer();
1893 void GuiView::restartCursor()
1895 /* When we move around, or type, it's nice to be able to see
1896 * the cursor immediately after the keypress.
1898 if (d.current_work_area_)
1899 d.current_work_area_->startBlinkingCursor();
1901 // Take this occasion to update the toobars and layout list.
1908 // This list should be kept in sync with the list of insets in
1909 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1910 // dialog should have the same name as the inset.
1912 char const * const dialognames[] = {
1913 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1914 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1915 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1916 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1917 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1919 #ifdef HAVE_LIBAIKSAURUS
1923 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1925 char const * const * const end_dialognames =
1926 dialognames + (sizeof(dialognames) / sizeof(char *));
1930 cmpCStr(char const * name) : name_(name) {}
1931 bool operator()(char const * other) {
1932 return strcmp(other, name_) == 0;
1939 bool isValidName(string const & name)
1941 return find_if(dialognames, end_dialognames,
1942 cmpCStr(name.c_str())) != end_dialognames;
1948 void GuiView::resetDialogs()
1950 // Make sure that no LFUN uses any LyXView.
1951 theLyXFunc().setLyXView(0);
1952 // FIXME: the "math panels" toolbar takes an awful lot of time to
1953 // initialise so we don't do that for the time being.
1954 //d.toolbars_->init();
1955 guiApp->menus().fillMenuBar(this);
1957 d.layout_->updateContents(true);
1958 // Now update controls with current buffer.
1959 theLyXFunc().setLyXView(this);
1964 Dialog * GuiView::find_or_build(string const & name)
1966 if (!isValidName(name))
1969 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1971 if (it != d.dialogs_.end())
1972 return it->second.get();
1974 Dialog * dialog = build(name);
1975 d.dialogs_[name].reset(dialog);
1976 if (lyxrc.allow_geometry_session)
1977 dialog->restoreSession();
1982 void GuiView::showDialog(string const & name, string const & data,
1989 Dialog * dialog = find_or_build(name);
1991 dialog->showData(data);
1993 d.open_insets_[name] = inset;
1999 bool GuiView::isDialogVisible(string const & name) const
2001 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2002 if (it == d.dialogs_.end())
2004 return it->second.get()->isVisibleView();
2008 void GuiView::hideDialog(string const & name, Inset * inset)
2010 // Don't send the signal if we are quitting, because on MSVC it is
2011 // destructed before the cut stack in CutAndPaste.cpp, and this method
2012 // is called from some inset destructor if the cut stack is not empty
2017 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2018 if (it == d.dialogs_.end())
2021 if (inset && inset != getOpenInset(name))
2024 Dialog * const dialog = it->second.get();
2025 if (dialog->isVisibleView())
2027 d.open_insets_[name] = 0;
2031 void GuiView::disconnectDialog(string const & name)
2033 if (!isValidName(name))
2036 if (d.open_insets_.find(name) != d.open_insets_.end())
2037 d.open_insets_[name] = 0;
2041 Inset * GuiView::getOpenInset(string const & name) const
2043 if (!isValidName(name))
2046 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2047 return it == d.open_insets_.end() ? 0 : it->second;
2051 void GuiView::hideAll() const
2053 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2054 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2056 for(; it != end; ++it)
2057 it->second->hideView();
2061 void GuiView::hideBufferDependent() const
2063 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2064 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2066 for(; it != end; ++it) {
2067 Dialog * dialog = it->second.get();
2068 if (dialog->isBufferDependent())
2074 void GuiView::updateBufferDependent(bool switched) const
2076 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2077 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2079 for(; it != end; ++it) {
2080 Dialog * dialog = it->second.get();
2081 if (!dialog->isVisibleView())
2083 if (switched && dialog->isBufferDependent()) {
2084 if (dialog->initialiseParams(""))
2085 dialog->updateView();
2089 // A bit clunky, but the dialog will request
2090 // that the kernel provides it with the necessary
2092 dialog->updateDialog();
2098 void GuiView::checkStatus()
2100 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2101 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2103 for(; it != end; ++it) {
2104 Dialog * const dialog = it->second.get();
2105 if (dialog && dialog->isVisibleView())
2106 dialog->checkStatus();
2112 // will be replaced by a proper factory...
2113 Dialog * createGuiAbout(GuiView & lv);
2114 Dialog * createGuiBibitem(GuiView & lv);
2115 Dialog * createGuiBibtex(GuiView & lv);
2116 Dialog * createGuiBox(GuiView & lv);
2117 Dialog * createGuiBranch(GuiView & lv);
2118 Dialog * createGuiChanges(GuiView & lv);
2119 Dialog * createGuiCharacter(GuiView & lv);
2120 Dialog * createGuiCitation(GuiView & lv);
2121 Dialog * createGuiDelimiter(GuiView & lv);
2122 Dialog * createGuiDocument(GuiView & lv);
2123 Dialog * createGuiErrorList(GuiView & lv);
2124 Dialog * createGuiERT(GuiView & lv);
2125 Dialog * createGuiExternal(GuiView & lv);
2126 Dialog * createGuiFloat(GuiView & lv);
2127 Dialog * createGuiGraphics(GuiView & lv);
2128 Dialog * createGuiInclude(GuiView & lv);
2129 Dialog * createGuiIndex(GuiView & lv);
2130 Dialog * createGuiLabel(GuiView & lv);
2131 Dialog * createGuiListings(GuiView & lv);
2132 Dialog * createGuiLog(GuiView & lv);
2133 Dialog * createGuiMathMatrix(GuiView & lv);
2134 Dialog * createGuiNomenclature(GuiView & lv);
2135 Dialog * createGuiNote(GuiView & lv);
2136 Dialog * createGuiParagraph(GuiView & lv);
2137 Dialog * createGuiPreferences(GuiView & lv);
2138 Dialog * createGuiPrint(GuiView & lv);
2139 Dialog * createGuiRef(GuiView & lv);
2140 Dialog * createGuiSearch(GuiView & lv);
2141 Dialog * createGuiSendTo(GuiView & lv);
2142 Dialog * createGuiShowFile(GuiView & lv);
2143 Dialog * createGuiSpellchecker(GuiView & lv);
2144 Dialog * createGuiSymbols(GuiView & lv);
2145 Dialog * createGuiTabularCreate(GuiView & lv);
2146 Dialog * createGuiTabular(GuiView & lv);
2147 Dialog * createGuiTexInfo(GuiView & lv);
2148 Dialog * createGuiToc(GuiView & lv);
2149 Dialog * createGuiThesaurus(GuiView & lv);
2150 Dialog * createGuiHyperlink(GuiView & lv);
2151 Dialog * createGuiVSpace(GuiView & lv);
2152 Dialog * createGuiViewSource(GuiView & lv);
2153 Dialog * createGuiWrap(GuiView & lv);
2156 Dialog * GuiView::build(string const & name)
2158 BOOST_ASSERT(isValidName(name));
2160 if (name == "aboutlyx")
2161 return createGuiAbout(*this);
2162 if (name == "bibitem")
2163 return createGuiBibitem(*this);
2164 if (name == "bibtex")
2165 return createGuiBibtex(*this);
2167 return createGuiBox(*this);
2168 if (name == "branch")
2169 return createGuiBranch(*this);
2170 if (name == "changes")
2171 return createGuiChanges(*this);
2172 if (name == "character")
2173 return createGuiCharacter(*this);
2174 if (name == "citation")
2175 return createGuiCitation(*this);
2176 if (name == "document")
2177 return createGuiDocument(*this);
2178 if (name == "errorlist")
2179 return createGuiErrorList(*this);
2181 return createGuiERT(*this);
2182 if (name == "external")
2183 return createGuiExternal(*this);
2185 return createGuiShowFile(*this);
2186 if (name == "findreplace")
2187 return createGuiSearch(*this);
2188 if (name == "float")
2189 return createGuiFloat(*this);
2190 if (name == "graphics")
2191 return createGuiGraphics(*this);
2192 if (name == "include")
2193 return createGuiInclude(*this);
2194 if (name == "index")
2195 return createGuiIndex(*this);
2196 if (name == "nomenclature")
2197 return createGuiNomenclature(*this);
2198 if (name == "label")
2199 return createGuiLabel(*this);
2201 return createGuiLog(*this);
2202 if (name == "view-source")
2203 return createGuiViewSource(*this);
2204 if (name == "mathdelimiter")
2205 return createGuiDelimiter(*this);
2206 if (name == "mathmatrix")
2207 return createGuiMathMatrix(*this);
2209 return createGuiNote(*this);
2210 if (name == "paragraph")
2211 return createGuiParagraph(*this);
2212 if (name == "prefs")
2213 return createGuiPreferences(*this);
2214 if (name == "print")
2215 return createGuiPrint(*this);
2217 return createGuiRef(*this);
2218 if (name == "sendto")
2219 return createGuiSendTo(*this);
2220 if (name == "spellchecker")
2221 return createGuiSpellchecker(*this);
2222 if (name == "symbols")
2223 return createGuiSymbols(*this);
2224 if (name == "tabular")
2225 return createGuiTabular(*this);
2226 if (name == "tabularcreate")
2227 return createGuiTabularCreate(*this);
2228 if (name == "texinfo")
2229 return createGuiTexInfo(*this);
2230 #ifdef HAVE_LIBAIKSAURUS
2231 if (name == "thesaurus")
2232 return createGuiThesaurus(*this);
2235 return createGuiToc(*this);
2237 return createGuiHyperlink(*this);
2238 if (name == "vspace")
2239 return createGuiVSpace(*this);
2241 return createGuiWrap(*this);
2242 if (name == "listings")
2243 return createGuiListings(*this);
2249 } // namespace frontend
2252 #include "GuiView_moc.cpp"