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;
107 class BackgroundWidget : public QWidget
112 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
113 /// The text to be written on top of the pixmap
114 QString const text = lyx_version ? lyx_version : qt_("unknown version");
115 splash_ = QPixmap(":/images/banner.png");
117 QPainter pain(&splash_);
118 pain.setPen(QColor(255, 255, 0));
120 // The font used to display the version info
121 font.setStyleHint(QFont::SansSerif);
122 font.setWeight(QFont::Bold);
123 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
125 pain.drawText(260, 270, text);
128 void paintEvent(QPaintEvent *)
130 int x = (width() - splash_.width()) / 2;
131 int y = (height() - splash_.height()) / 2;
133 pain.drawPixmap(x, y, splash_);
143 typedef boost::shared_ptr<Dialog> DialogPtr;
145 struct GuiView::GuiViewPrivate
148 : current_work_area_(0), layout_(0),
149 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
151 // hardcode here the platform specific icon size
152 smallIconSize = 14; // scaling problems
153 normalIconSize = 20; // ok, default
154 bigIconSize = 26; // better for some math icons
156 splitter_ = new QSplitter;
157 bg_widget_ = new BackgroundWidget;
158 stack_widget_ = new QStackedWidget;
159 stack_widget_->addWidget(bg_widget_);
160 stack_widget_->addWidget(splitter_);
168 delete stack_widget_;
172 QMenu * toolBarPopup(GuiView * parent)
174 // FIXME: translation
175 QMenu * menu = new QMenu(parent);
176 QActionGroup * iconSizeGroup = new QActionGroup(parent);
178 QAction * smallIcons = new QAction(iconSizeGroup);
179 smallIcons->setText(qt_("Small-sized icons"));
180 smallIcons->setCheckable(true);
181 QObject::connect(smallIcons, SIGNAL(triggered()),
182 parent, SLOT(smallSizedIcons()));
183 menu->addAction(smallIcons);
185 QAction * normalIcons = new QAction(iconSizeGroup);
186 normalIcons->setText(qt_("Normal-sized icons"));
187 normalIcons->setCheckable(true);
188 QObject::connect(normalIcons, SIGNAL(triggered()),
189 parent, SLOT(normalSizedIcons()));
190 menu->addAction(normalIcons);
192 QAction * bigIcons = new QAction(iconSizeGroup);
193 bigIcons->setText(qt_("Big-sized icons"));
194 bigIcons->setCheckable(true);
195 QObject::connect(bigIcons, SIGNAL(triggered()),
196 parent, SLOT(bigSizedIcons()));
197 menu->addAction(bigIcons);
199 unsigned int cur = parent->iconSize().width();
200 if ( cur == parent->d.smallIconSize)
201 smallIcons->setChecked(true);
202 else if (cur == parent->d.normalIconSize)
203 normalIcons->setChecked(true);
204 else if (cur == parent->d.bigIconSize)
205 bigIcons->setChecked(true);
212 stack_widget_->setCurrentWidget(bg_widget_);
213 bg_widget_->setUpdatesEnabled(true);
216 TabWorkArea * tabWorkArea(int i)
218 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
221 TabWorkArea * currentTabWorkArea()
223 if (splitter_->count() == 1)
224 // The first TabWorkArea is always the first one, if any.
225 return tabWorkArea(0);
227 for (int i = 0; i != splitter_->count(); ++i) {
228 TabWorkArea * twa = tabWorkArea(i);
229 if (current_work_area_ == twa->currentWorkArea())
233 // None has the focus so we just take the first one.
234 return tabWorkArea(0);
238 GuiWorkArea * current_work_area_;
239 QSplitter * splitter_;
240 QStackedWidget * stack_widget_;
241 BackgroundWidget * bg_widget_;
243 GuiToolbars * toolbars_;
244 /// The main layout box.
246 * \warning Don't Delete! The layout box is actually owned by
247 * whichever toolbar contains it. All the GuiView class needs is a
248 * means of accessing it.
250 * FIXME: replace that with a proper model so that we are not limited
251 * to only one dialog.
253 GuiLayoutBox * layout_;
256 map<string, Inset *> open_insets_;
259 map<string, DialogPtr> dialogs_;
261 unsigned int smallIconSize;
262 unsigned int normalIconSize;
263 unsigned int bigIconSize;
265 QTimer statusbar_timer_;
266 /// are we quitting by the menu?
267 bool quitting_by_menu_;
268 /// auto-saving of buffers
269 Timeout autosave_timeout_;
270 /// flag against a race condition due to multiclicks, see bug #1119
275 GuiView::GuiView(int id)
276 : d(*new GuiViewPrivate), id_(id)
278 // GuiToolbars *must* be initialised before the menu bar.
279 d.toolbars_ = new GuiToolbars(*this);
281 // Fill up the menu bar.
282 guiApp->menus().fillMenuBar(this);
284 setCentralWidget(d.stack_widget_);
286 // Start autosave timer
287 if (lyxrc.autosave) {
288 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
289 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
290 d.autosave_timeout_.start();
292 connect(&d.statusbar_timer_, SIGNAL(timeout()),
293 this, SLOT(clearMessage()));
295 // Qt bug? signal lastWindowClosed does not work
296 setAttribute(Qt::WA_QuitOnClose, false);
297 setAttribute(Qt::WA_DeleteOnClose, true);
299 // assign an icon to main form. We do not do it under Qt/Mac,
300 // since the icon is provided in the application bundle.
301 setWindowIcon(QPixmap(":/images/lyx.png"));
305 setAcceptDrops(true);
307 statusBar()->setSizeGripEnabled(true);
309 // Forbid too small unresizable window because it can happen
310 // with some window manager under X11.
311 setMinimumSize(300, 200);
313 if (!lyxrc.allow_geometry_session)
314 // No session handling, default to a sane size.
315 setGeometry(50, 50, 690, 510);
317 // Now take care of session management.
319 QString const key = "view-" + QString::number(id_);
321 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
322 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
326 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
327 setGeometry(50, 50, 690, 510);
329 setIconSize(settings.value(key + "/icon_size").toSize());
339 void GuiView::close()
341 d.quitting_by_menu_ = true;
342 d.current_work_area_ = 0;
343 for (int i = 0; i != d.splitter_->count(); ++i) {
344 TabWorkArea * twa = d.tabWorkArea(i);
348 QMainWindow::close();
349 d.quitting_by_menu_ = false;
353 void GuiView::setFocus()
355 if (d.current_work_area_)
356 d.current_work_area_->setFocus();
362 QMenu * GuiView::createPopupMenu()
364 return d.toolBarPopup(this);
368 void GuiView::showEvent(QShowEvent * e)
370 LYXERR(Debug::GUI, "Passed Geometry "
371 << size().height() << "x" << size().width()
372 << "+" << pos().x() << "+" << pos().y());
374 if (d.splitter_->count() == 0)
375 // No work area, switch to the background widget.
378 QMainWindow::showEvent(e);
382 void GuiView::closeEvent(QCloseEvent * close_event)
384 // we may have been called through the close window button
385 // which bypasses the LFUN machinery.
386 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
387 if (!quitWriteAll()) {
388 close_event->ignore();
393 // Make sure that no LFUN use this close to be closed View.
394 theLyXFunc().setLyXView(0);
396 // Save toolbars configuration
397 if (isFullScreen()) {
398 d.toolbars_->toggleFullScreen(!isFullScreen());
402 // Make sure the timer time out will not trigger a statusbar update.
403 d.statusbar_timer_.stop();
405 // Saving fullscreen requires additional tweaks in the toolbar code.
406 // It wouldn't also work under linux natively.
407 if (lyxrc.allow_geometry_session && !isFullScreen()) {
409 QString const key = "view-" + QString::number(id_);
411 settings.setValue(key + "/pos", pos());
412 settings.setValue(key + "/size", size());
414 settings.setValue(key + "/geometry", saveGeometry());
416 settings.setValue(key + "/icon_size", iconSize());
417 d.toolbars_->saveToolbarInfo();
418 // Now take care of all other dialogs:
419 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
420 for (; it!= d.dialogs_.end(); ++it)
421 it->second->saveSession();
424 guiApp->unregisterView(id_);
425 if (guiApp->viewCount() > 0) {
426 // Just close the window and do nothing else if this is not the
428 close_event->accept();
434 // this is the place where we leave the frontend.
435 // it is the only point at which we start quitting.
436 close_event->accept();
437 // quit the event loop
442 void GuiView::dragEnterEvent(QDragEnterEvent * event)
444 if (event->mimeData()->hasUrls())
446 /// \todo Ask lyx-devel is this is enough:
447 /// if (event->mimeData()->hasFormat("text/plain"))
448 /// event->acceptProposedAction();
452 void GuiView::dropEvent(QDropEvent* event)
454 QList<QUrl> files = event->mimeData()->urls();
458 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
459 for (int i = 0; i != files.size(); ++i) {
460 string const file = os::internal_path(fromqstr(
461 files.at(i).toLocalFile()));
463 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
468 void GuiView::message(docstring const & str)
470 if (ForkedProcess::iAmAChild())
473 statusBar()->showMessage(toqstr(str));
474 d.statusbar_timer_.stop();
475 d.statusbar_timer_.start(3000);
479 void GuiView::smallSizedIcons()
481 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
485 void GuiView::normalSizedIcons()
487 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
491 void GuiView::bigSizedIcons()
493 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
497 void GuiView::clearMessage()
501 theLyXFunc().setLyXView(this);
502 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
503 d.statusbar_timer_.stop();
507 void GuiView::updateWindowTitle(GuiWorkArea * wa)
509 if (wa != d.current_work_area_)
511 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
512 setWindowIconText(wa->windowIconText());
516 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
519 disconnectBufferView();
520 connectBufferView(wa->bufferView());
521 connectBuffer(wa->bufferView().buffer());
522 d.current_work_area_ = wa;
523 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
524 this, SLOT(updateWindowTitle(GuiWorkArea *)));
525 updateWindowTitle(wa);
528 // Buffer-dependent dialogs should be updated or
529 // hidden. This should go here because some dialogs (eg ToC)
530 // require bv_->text.
531 updateBufferDependent(true);
538 void GuiView::updateStatusBar()
540 // let the user see the explicit message
541 if (d.statusbar_timer_.isActive())
544 theLyXFunc().setLyXView(this);
545 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
549 bool GuiView::hasFocus() const
551 return qApp->activeWindow() == this;
555 bool GuiView::event(QEvent * e)
559 // Useful debug code:
560 //case QEvent::ActivationChange:
561 //case QEvent::WindowDeactivate:
562 //case QEvent::Paint:
563 //case QEvent::Enter:
564 //case QEvent::Leave:
565 //case QEvent::HoverEnter:
566 //case QEvent::HoverLeave:
567 //case QEvent::HoverMove:
568 //case QEvent::StatusTip:
569 //case QEvent::DragEnter:
570 //case QEvent::DragLeave:
574 case QEvent::WindowActivate: {
575 guiApp->setCurrentView(*this);
576 if (d.current_work_area_) {
577 BufferView & bv = d.current_work_area_->bufferView();
578 connectBufferView(bv);
579 connectBuffer(bv.buffer());
580 // The document structure, name and dialogs might have
581 // changed in another view.
582 updateBufferDependent(true);
587 setWindowTitle(qt_("LyX"));
588 setWindowIconText(qt_("LyX"));
591 return QMainWindow::event(e);
594 case QEvent::ShortcutOverride: {
595 if (d.current_work_area_)
596 // Nothing special to do.
597 return QMainWindow::event(e);
599 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
601 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
603 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
604 || ke->key() == Qt::Key_Backtab)
605 return QMainWindow::event(e);
607 // Allow processing of shortcuts that are allowed even when no Buffer
609 theLyXFunc().setLyXView(this);
611 setKeySymbol(&sym, ke);
612 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
618 return QMainWindow::event(e);
623 bool GuiView::focusNextPrevChild(bool /*next*/)
630 void GuiView::setBusy(bool busy)
632 if (d.current_work_area_) {
633 d.current_work_area_->setUpdatesEnabled(!busy);
635 d.current_work_area_->stopBlinkingCursor();
637 d.current_work_area_->startBlinkingCursor();
641 QApplication::setOverrideCursor(Qt::WaitCursor);
643 QApplication::restoreOverrideCursor();
647 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
649 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
651 if (tbinfo.flags & ToolbarInfo::TOP) {
653 addToolBarBreak(Qt::TopToolBarArea);
654 addToolBar(Qt::TopToolBarArea, toolBar);
657 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
658 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
659 #if (QT_VERSION >= 0x040202)
661 addToolBarBreak(Qt::BottomToolBarArea);
663 addToolBar(Qt::BottomToolBarArea, toolBar);
666 if (tbinfo.flags & ToolbarInfo::LEFT) {
667 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
668 #if (QT_VERSION >= 0x040202)
670 addToolBarBreak(Qt::LeftToolBarArea);
672 addToolBar(Qt::LeftToolBarArea, toolBar);
675 if (tbinfo.flags & ToolbarInfo::RIGHT) {
676 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
677 #if (QT_VERSION >= 0x040202)
679 addToolBarBreak(Qt::RightToolBarArea);
681 addToolBar(Qt::RightToolBarArea, toolBar);
684 // The following does not work so I cannot restore to exact toolbar location
686 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
687 toolBar->move(tbinfo.posx, tbinfo.posy);
694 GuiWorkArea * GuiView::workArea(Buffer & buffer)
696 if (TabWorkArea * twa = d.currentTabWorkArea())
697 return twa->workArea(buffer);
702 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
704 // Automatically create a TabWorkArea if there are none yet.
705 TabWorkArea * tab_widget = d.splitter_->count()
706 ? d.currentTabWorkArea() : addTabWorkArea();
707 return tab_widget->addWorkArea(buffer, *this);
711 TabWorkArea * GuiView::addTabWorkArea()
713 TabWorkArea * twa = new TabWorkArea;
714 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
715 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
716 d.splitter_->addWidget(twa);
717 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_SPLIT_VIEW:
967 case LFUN_TOOLBAR_TOGGLE:
968 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
971 case LFUN_DIALOG_TOGGLE:
972 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
973 // fall through to set "enable"
974 case LFUN_DIALOG_SHOW: {
975 string const name = cmd.getArg(0);
977 enable = name == "aboutlyx"
978 || name == "file" //FIXME: should be removed.
980 || name == "texinfo";
981 else if (name == "print")
982 enable = buf->isExportable("dvi")
983 && lyxrc.print_command != "none";
984 else if (name == "character") {
988 InsetCode ic = view()->cursor().inset().lyxCode();
989 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
992 else if (name == "symbols") {
993 if (!view() || view()->cursor().inMathed())
996 InsetCode ic = view()->cursor().inset().lyxCode();
997 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1000 else if (name == "latexlog")
1001 enable = FileName(buf->logName()).isReadableFile();
1002 else if (name == "spellchecker")
1003 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1004 enable = !buf->isReadonly();
1008 else if (name == "vclog")
1009 enable = buf->lyxvc().inUse();
1013 case LFUN_DIALOG_UPDATE: {
1014 string const name = cmd.getArg(0);
1016 enable = name == "prefs";
1020 case LFUN_INSET_APPLY: {
1025 string const name = cmd.getArg(0);
1026 Inset * inset = getOpenInset(name);
1028 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1030 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1031 // Every inset is supposed to handle this
1032 BOOST_ASSERT(false);
1036 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1037 flag |= getStatus(fr);
1039 enable = flag.enabled();
1051 flag.enabled(false);
1057 static FileName selectTemplateFile()
1059 FileDialog dlg(_("Select template file"));
1060 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1061 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1063 FileDialog::Result result =
1064 dlg.open(from_utf8(lyxrc.template_path),
1065 FileFilterList(_("LyX Documents (*.lyx)")),
1068 if (result.first == FileDialog::Later)
1070 if (result.second.empty())
1072 return FileName(to_utf8(result.second));
1076 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1080 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1083 message(_("Document not loaded."));
1088 setBuffer(newBuffer);
1090 // scroll to the position when the file was last closed
1091 if (lyxrc.use_lastfilepos) {
1092 LastFilePosSection::FilePos filepos =
1093 LyX::ref().session().lastFilePos().load(filename);
1094 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1098 LyX::ref().session().lastFiles().add(filename);
1105 void GuiView::openDocument(string const & fname)
1107 string initpath = lyxrc.document_path;
1110 string const trypath = buffer()->filePath();
1111 // If directory is writeable, use this as default.
1112 if (FileName(trypath).isDirWritable())
1118 if (fname.empty()) {
1119 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1120 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1121 dlg.setButton2(_("Examples|#E#e"),
1122 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1124 FileDialog::Result result =
1125 dlg.open(from_utf8(initpath),
1126 FileFilterList(_("LyX Documents (*.lyx)")),
1129 if (result.first == FileDialog::Later)
1132 filename = to_utf8(result.second);
1134 // check selected filename
1135 if (filename.empty()) {
1136 message(_("Canceled."));
1142 // get absolute path of file and add ".lyx" to the filename if
1144 FileName const fullname =
1145 fileSearch(string(), filename, "lyx", support::may_not_exist);
1146 if (!fullname.empty())
1147 filename = fullname.absFilename();
1149 // if the file doesn't exist, let the user create one
1150 if (!fullname.exists()) {
1151 // the user specifically chose this name. Believe him.
1152 Buffer * const b = newFile(filename, string(), true);
1158 docstring const disp_fn = makeDisplayPath(filename);
1159 message(bformat(_("Opening document %1$s..."), disp_fn));
1162 Buffer * buf = loadDocument(fullname);
1166 buf->errors("Parse");
1167 str2 = bformat(_("Document %1$s opened."), disp_fn);
1169 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1174 // FIXME: clean that
1175 static bool import(GuiView * lv, FileName const & filename,
1176 string const & format, ErrorList & errorList)
1178 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1180 string loader_format;
1181 vector<string> loaders = theConverters().loaders();
1182 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1183 for (vector<string>::const_iterator it = loaders.begin();
1184 it != loaders.end(); ++it) {
1185 if (!theConverters().isReachable(format, *it))
1188 string const tofile =
1189 changeExtension(filename.absFilename(),
1190 formats.extension(*it));
1191 if (!theConverters().convert(0, filename, FileName(tofile),
1192 filename, format, *it, errorList))
1194 loader_format = *it;
1197 if (loader_format.empty()) {
1198 frontend::Alert::error(_("Couldn't import file"),
1199 bformat(_("No information for importing the format %1$s."),
1200 formats.prettyName(format)));
1204 loader_format = format;
1206 if (loader_format == "lyx") {
1207 Buffer * buf = lv->loadDocument(lyxfile);
1212 buf->errors("Parse");
1214 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1218 bool as_paragraphs = loader_format == "textparagraph";
1219 string filename2 = (loader_format == format) ? filename.absFilename()
1220 : changeExtension(filename.absFilename(),
1221 formats.extension(loader_format));
1222 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1223 theLyXFunc().setLyXView(lv);
1224 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1231 void GuiView::importDocument(string const & argument)
1234 string filename = split(argument, format, ' ');
1236 LYXERR(Debug::INFO, format << " file: " << filename);
1238 // need user interaction
1239 if (filename.empty()) {
1240 string initpath = lyxrc.document_path;
1242 Buffer const * buf = buffer();
1244 string const trypath = buf->filePath();
1245 // If directory is writeable, use this as default.
1246 if (FileName(trypath).isDirWritable())
1250 docstring const text = bformat(_("Select %1$s file to import"),
1251 formats.prettyName(format));
1253 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1254 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1255 dlg.setButton2(_("Examples|#E#e"),
1256 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1258 docstring filter = formats.prettyName(format);
1261 filter += from_utf8(formats.extension(format));
1264 FileDialog::Result result =
1265 dlg.open(from_utf8(initpath),
1266 FileFilterList(filter),
1269 if (result.first == FileDialog::Later)
1272 filename = to_utf8(result.second);
1274 // check selected filename
1275 if (filename.empty())
1276 message(_("Canceled."));
1279 if (filename.empty())
1282 // get absolute path of file
1283 FileName const fullname(makeAbsPath(filename));
1285 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1287 // Check if the document already is open
1288 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1291 if (!closeBuffer()) {
1292 message(_("Canceled."));
1297 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1299 // if the file exists already, and we didn't do
1300 // -i lyx thefile.lyx, warn
1301 if (lyxfile.exists() && fullname != lyxfile) {
1303 docstring text = bformat(_("The document %1$s already exists.\n\n"
1304 "Do you want to overwrite that document?"), displaypath);
1305 int const ret = Alert::prompt(_("Overwrite document?"),
1306 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1309 message(_("Canceled."));
1314 message(bformat(_("Importing %1$s..."), displaypath));
1315 ErrorList errorList;
1316 if (import(this, fullname, format, errorList))
1317 message(_("imported."));
1319 message(_("file not imported!"));
1321 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1325 void GuiView::newDocument(string const & filename, bool from_template)
1327 FileName initpath(lyxrc.document_path);
1328 Buffer * buf = buffer();
1330 FileName const trypath(buf->filePath());
1331 // If directory is writeable, use this as default.
1332 if (trypath.isDirWritable())
1336 string templatefile = from_template ?
1337 selectTemplateFile().absFilename() : string();
1339 if (filename.empty())
1340 b = newUnnamedFile(templatefile, initpath);
1342 b = newFile(filename, templatefile, true);
1346 // Ensure the cursor is correctly positionned on screen.
1347 view()->showCursor();
1351 void GuiView::insertLyXFile(docstring const & fname)
1353 BufferView * bv = view();
1358 FileName filename(to_utf8(fname));
1360 if (!filename.empty()) {
1361 bv->insertLyXFile(filename);
1365 // Launch a file browser
1367 string initpath = lyxrc.document_path;
1368 string const trypath = bv->buffer().filePath();
1369 // If directory is writeable, use this as default.
1370 if (FileName(trypath).isDirWritable())
1374 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1375 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1376 dlg.setButton2(_("Examples|#E#e"),
1377 from_utf8(addPath(package().system_support().absFilename(),
1380 FileDialog::Result result =
1381 dlg.open(from_utf8(initpath),
1382 FileFilterList(_("LyX Documents (*.lyx)")),
1385 if (result.first == FileDialog::Later)
1389 filename.set(to_utf8(result.second));
1391 // check selected filename
1392 if (filename.empty()) {
1393 // emit message signal.
1394 message(_("Canceled."));
1398 bv->insertLyXFile(filename);
1402 void GuiView::insertPlaintextFile(docstring const & fname,
1405 BufferView * bv = view();
1410 FileName filename(to_utf8(fname));
1412 if (!filename.empty()) {
1413 bv->insertPlaintextFile(filename, asParagraph);
1417 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1418 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1420 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1421 FileFilterList(), docstring());
1423 if (result.first == FileDialog::Later)
1427 filename.set(to_utf8(result.second));
1429 // check selected filename
1430 if (filename.empty()) {
1431 // emit message signal.
1432 message(_("Canceled."));
1436 bv->insertPlaintextFile(filename, asParagraph);
1440 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1442 FileName fname = b.fileName();
1443 FileName const oldname = fname;
1445 if (!newname.empty()) {
1447 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1449 // Switch to this Buffer.
1452 /// No argument? Ask user through dialog.
1454 FileDialog dlg(_("Choose a filename to save document as"),
1455 LFUN_BUFFER_WRITE_AS);
1456 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1457 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1459 if (!isLyXFilename(fname.absFilename()))
1460 fname.changeExtension(".lyx");
1462 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1464 FileDialog::Result result =
1465 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1467 from_utf8(fname.onlyFileName()));
1469 if (result.first == FileDialog::Later)
1472 fname.set(to_utf8(result.second));
1477 if (!isLyXFilename(fname.absFilename()))
1478 fname.changeExtension(".lyx");
1481 if (FileName(fname).exists()) {
1482 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1483 docstring text = bformat(_("The document %1$s already "
1484 "exists.\n\nDo you want to "
1485 "overwrite that document?"),
1487 int const ret = Alert::prompt(_("Overwrite document?"),
1488 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1491 case 1: return renameBuffer(b, docstring());
1492 case 2: return false;
1496 // Ok, change the name of the buffer
1497 b.setFileName(fname.absFilename());
1499 bool unnamed = b.isUnnamed();
1500 b.setUnnamed(false);
1501 b.saveCheckSum(fname);
1503 if (!saveBuffer(b)) {
1504 b.setFileName(oldname.absFilename());
1505 b.setUnnamed(unnamed);
1506 b.saveCheckSum(oldname);
1514 bool GuiView::saveBuffer(Buffer & b)
1517 return renameBuffer(b, docstring());
1520 LyX::ref().session().lastFiles().add(b.fileName());
1524 // Switch to this Buffer.
1527 // FIXME: we don't tell the user *WHY* the save failed !!
1528 docstring const file = makeDisplayPath(b.absFileName(), 30);
1529 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1530 "Do you want to rename the document and "
1531 "try again?"), file);
1532 int const ret = Alert::prompt(_("Rename and save?"),
1533 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1536 if (!renameBuffer(b, docstring()))
1545 return saveBuffer(b);
1549 bool GuiView::closeBuffer()
1551 Buffer * buf = buffer();
1552 return buf && closeBuffer(*buf);
1556 bool GuiView::closeBuffer(Buffer & buf)
1558 if (buf.isClean() || buf.paragraphs().empty()) {
1559 theBufferList().release(&buf);
1562 // Switch to this Buffer.
1567 if (buf.isUnnamed())
1568 file = from_utf8(buf.fileName().onlyFileName());
1570 file = buf.fileName().displayName(30);
1572 docstring const text = bformat(_("The document %1$s has unsaved changes."
1573 "\n\nDo you want to save the document or discard the changes?"), file);
1574 int const ret = Alert::prompt(_("Save changed document?"),
1575 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1579 if (!saveBuffer(buf))
1583 // if we crash after this we could
1584 // have no autosave file but I guess
1585 // this is really improbable (Jug)
1586 removeAutosaveFile(buf.absFileName());
1592 // save file names to .lyx/session
1593 // if master/slave are both open, do not save slave since it
1594 // will be automatically loaded when the master is loaded
1595 if (buf.masterBuffer() == &buf)
1596 LyX::ref().session().lastOpened().add(buf.fileName());
1598 theBufferList().release(&buf);
1603 bool GuiView::quitWriteAll()
1605 while (!theBufferList().empty()) {
1606 Buffer * b = theBufferList().first();
1607 if (!closeBuffer(*b))
1614 bool GuiView::dispatch(FuncRequest const & cmd)
1616 BufferView * bv = view();
1617 // By default we won't need any update.
1619 bv->cursor().updateFlags(Update::None);
1621 switch(cmd.action) {
1622 case LFUN_FILE_OPEN:
1623 openDocument(to_utf8(cmd.argument()));
1626 case LFUN_BUFFER_IMPORT:
1627 importDocument(to_utf8(cmd.argument()));
1630 case LFUN_BUFFER_SWITCH:
1631 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1634 case LFUN_BUFFER_NEXT:
1635 setBuffer(theBufferList().next(buffer()));
1638 case LFUN_BUFFER_PREVIOUS:
1639 setBuffer(theBufferList().previous(buffer()));
1642 case LFUN_COMMAND_EXECUTE: {
1643 bool const show_it = cmd.argument() != "off";
1644 d.toolbars_->showCommandBuffer(show_it);
1647 case LFUN_DROP_LAYOUTS_CHOICE:
1649 d.layout_->showPopup();
1652 case LFUN_MENU_OPEN:
1653 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1654 menu->exec(QCursor::pos());
1657 case LFUN_FILE_INSERT:
1658 insertLyXFile(cmd.argument());
1660 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1661 insertPlaintextFile(cmd.argument(), true);
1664 case LFUN_FILE_INSERT_PLAINTEXT:
1665 insertPlaintextFile(cmd.argument(), false);
1668 case LFUN_BUFFER_WRITE:
1670 saveBuffer(bv->buffer());
1673 case LFUN_BUFFER_WRITE_AS:
1675 renameBuffer(bv->buffer(), cmd.argument());
1678 case LFUN_BUFFER_WRITE_ALL: {
1679 Buffer * first = theBufferList().first();
1682 message(_("Saving all documents..."));
1683 // We cannot use a for loop as the buffer list cycles.
1689 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1690 b = theBufferList().next(b);
1691 } while (b != first);
1692 message(_("All documents saved."));
1696 case LFUN_TOOLBAR_TOGGLE: {
1697 string const name = cmd.getArg(0);
1698 bool const allowauto = cmd.getArg(1) == "allowauto";
1699 // it is possible to get current toolbar status like this,...
1700 // but I decide to obey the order of ToolbarBackend::flags
1701 // and disregard real toolbar status.
1702 // toolbars_->saveToolbarInfo();
1704 // toggle state on/off/auto
1705 d.toolbars_->toggleToolbarState(name, allowauto);
1709 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1711 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1715 if (tbi->flags & ToolbarInfo::ON)
1717 else if (tbi->flags & ToolbarInfo::OFF)
1719 else if (tbi->flags & ToolbarInfo::AUTO)
1722 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1723 _(tbi->gui_name), state));
1727 case LFUN_DIALOG_UPDATE: {
1728 string const name = to_utf8(cmd.argument());
1729 // Can only update a dialog connected to an existing inset
1730 Inset * inset = getOpenInset(name);
1732 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1733 inset->dispatch(view()->cursor(), fr);
1734 } else if (name == "paragraph") {
1735 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1736 } else if (name == "prefs") {
1737 updateDialog(name, string());
1742 case LFUN_DIALOG_TOGGLE: {
1743 if (isDialogVisible(cmd.getArg(0)))
1744 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1746 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1750 case LFUN_DIALOG_DISCONNECT_INSET:
1751 disconnectDialog(to_utf8(cmd.argument()));
1754 case LFUN_DIALOG_HIDE: {
1757 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1761 case LFUN_DIALOG_SHOW: {
1762 string const name = cmd.getArg(0);
1763 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1765 if (name == "character") {
1766 data = freefont2string();
1768 showDialog("character", data);
1769 } else if (name == "latexlog") {
1770 Buffer::LogType type;
1771 string const logfile = buffer()->logName(&type);
1773 case Buffer::latexlog:
1776 case Buffer::buildlog:
1780 data += Lexer::quoteString(logfile);
1781 showDialog("log", data);
1782 } else if (name == "vclog") {
1783 string const data = "vc " +
1784 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1785 showDialog("log", data);
1786 } else if (name == "symbols") {
1787 data = bv->cursor().getEncoding()->name();
1789 showDialog("symbols", data);
1791 showDialog(name, data);
1795 case LFUN_INSET_APPLY: {
1796 string const name = cmd.getArg(0);
1797 Inset * inset = getOpenInset(name);
1799 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1800 inset->dispatch(view()->cursor(), fr);
1802 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1808 case LFUN_UI_TOGGLE:
1810 // Make sure the keyboard focus stays in the work area.
1814 case LFUN_SPLIT_VIEW:
1815 if (Buffer * buf = buffer()) {
1816 TabWorkArea * twa = addTabWorkArea();
1817 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1818 setCurrentWorkArea(wa);
1830 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1832 string const arg = cmd.getArg(0);
1833 if (arg == "scrollbar") {
1834 // hide() is of no help
1835 if (d.current_work_area_->verticalScrollBarPolicy() ==
1836 Qt::ScrollBarAlwaysOff)
1838 d.current_work_area_->setVerticalScrollBarPolicy(
1839 Qt::ScrollBarAsNeeded);
1841 d.current_work_area_->setVerticalScrollBarPolicy(
1842 Qt::ScrollBarAlwaysOff);
1845 if (arg == "statusbar") {
1846 statusBar()->setVisible(!statusBar()->isVisible());
1849 if (arg == "menubar") {
1850 menuBar()->setVisible(!menuBar()->isVisible());
1853 #if QT_VERSION >= 0x040300
1854 if (arg == "frame") {
1856 getContentsMargins(&l, &t, &r, &b);
1857 //are the frames in default state?
1859 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1860 setContentsMargins(-2, -2, -2, -2);
1862 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1863 setContentsMargins(0, 0, 0, 0);
1868 if (arg != "fullscreen") {
1869 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1873 if (lyxrc.full_screen_toolbars)
1874 d.toolbars_->toggleFullScreen(!isFullScreen());
1876 if (isFullScreen()) {
1877 for (int i = 0; i != d.splitter_->count(); ++i)
1878 d.tabWorkArea(i)->setFullScreen(false);
1879 #if QT_VERSION >= 0x040300
1880 setContentsMargins(0, 0, 0, 0);
1884 statusBar()->show();
1886 for (int i = 0; i != d.splitter_->count(); ++i)
1887 d.tabWorkArea(i)->setFullScreen(true);
1888 #if QT_VERSION >= 0x040300
1889 setContentsMargins(-2, -2, -2, -2);
1892 statusBar()->hide();
1898 Buffer const * GuiView::updateInset(Inset const * inset)
1900 if (!d.current_work_area_)
1904 d.current_work_area_->scheduleRedraw();
1906 return &d.current_work_area_->bufferView().buffer();
1910 void GuiView::restartCursor()
1912 /* When we move around, or type, it's nice to be able to see
1913 * the cursor immediately after the keypress.
1915 if (d.current_work_area_)
1916 d.current_work_area_->startBlinkingCursor();
1918 // Take this occasion to update the toobars and layout list.
1925 // This list should be kept in sync with the list of insets in
1926 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1927 // dialog should have the same name as the inset.
1929 char const * const dialognames[] = {
1930 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1931 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1932 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1933 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1934 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1936 #ifdef HAVE_LIBAIKSAURUS
1940 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1942 char const * const * const end_dialognames =
1943 dialognames + (sizeof(dialognames) / sizeof(char *));
1947 cmpCStr(char const * name) : name_(name) {}
1948 bool operator()(char const * other) {
1949 return strcmp(other, name_) == 0;
1956 bool isValidName(string const & name)
1958 return find_if(dialognames, end_dialognames,
1959 cmpCStr(name.c_str())) != end_dialognames;
1965 void GuiView::resetDialogs()
1967 // Make sure that no LFUN uses any LyXView.
1968 theLyXFunc().setLyXView(0);
1969 // FIXME: the "math panels" toolbar takes an awful lot of time to
1970 // initialise so we don't do that for the time being.
1971 //d.toolbars_->init();
1972 guiApp->menus().fillMenuBar(this);
1974 d.layout_->updateContents(true);
1975 // Now update controls with current buffer.
1976 theLyXFunc().setLyXView(this);
1981 Dialog * GuiView::find_or_build(string const & name)
1983 if (!isValidName(name))
1986 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1988 if (it != d.dialogs_.end())
1989 return it->second.get();
1991 Dialog * dialog = build(name);
1992 d.dialogs_[name].reset(dialog);
1993 if (lyxrc.allow_geometry_session)
1994 dialog->restoreSession();
1999 void GuiView::showDialog(string const & name, string const & data,
2006 Dialog * dialog = find_or_build(name);
2008 dialog->showData(data);
2010 d.open_insets_[name] = inset;
2016 bool GuiView::isDialogVisible(string const & name) const
2018 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2019 if (it == d.dialogs_.end())
2021 return it->second.get()->isVisibleView();
2025 void GuiView::hideDialog(string const & name, Inset * inset)
2027 // Don't send the signal if we are quitting, because on MSVC it is
2028 // destructed before the cut stack in CutAndPaste.cpp, and this method
2029 // is called from some inset destructor if the cut stack is not empty
2034 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2035 if (it == d.dialogs_.end())
2038 if (inset && inset != getOpenInset(name))
2041 Dialog * const dialog = it->second.get();
2042 if (dialog->isVisibleView())
2044 d.open_insets_[name] = 0;
2048 void GuiView::disconnectDialog(string const & name)
2050 if (!isValidName(name))
2053 if (d.open_insets_.find(name) != d.open_insets_.end())
2054 d.open_insets_[name] = 0;
2058 Inset * GuiView::getOpenInset(string const & name) const
2060 if (!isValidName(name))
2063 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2064 return it == d.open_insets_.end() ? 0 : it->second;
2068 void GuiView::hideAll() const
2070 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2071 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2073 for(; it != end; ++it)
2074 it->second->hideView();
2078 void GuiView::hideBufferDependent() const
2080 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2081 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2083 for(; it != end; ++it) {
2084 Dialog * dialog = it->second.get();
2085 if (dialog->isBufferDependent())
2091 void GuiView::updateBufferDependent(bool switched) const
2093 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2094 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2096 for(; it != end; ++it) {
2097 Dialog * dialog = it->second.get();
2098 if (!dialog->isVisibleView())
2100 if (switched && dialog->isBufferDependent()) {
2101 if (dialog->initialiseParams(""))
2102 dialog->updateView();
2106 // A bit clunky, but the dialog will request
2107 // that the kernel provides it with the necessary
2109 dialog->updateDialog();
2115 void GuiView::checkStatus()
2117 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2118 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2120 for(; it != end; ++it) {
2121 Dialog * const dialog = it->second.get();
2122 if (dialog && dialog->isVisibleView())
2123 dialog->checkStatus();
2129 // will be replaced by a proper factory...
2130 Dialog * createGuiAbout(GuiView & lv);
2131 Dialog * createGuiBibitem(GuiView & lv);
2132 Dialog * createGuiBibtex(GuiView & lv);
2133 Dialog * createGuiBox(GuiView & lv);
2134 Dialog * createGuiBranch(GuiView & lv);
2135 Dialog * createGuiChanges(GuiView & lv);
2136 Dialog * createGuiCharacter(GuiView & lv);
2137 Dialog * createGuiCitation(GuiView & lv);
2138 Dialog * createGuiDelimiter(GuiView & lv);
2139 Dialog * createGuiDocument(GuiView & lv);
2140 Dialog * createGuiErrorList(GuiView & lv);
2141 Dialog * createGuiERT(GuiView & lv);
2142 Dialog * createGuiExternal(GuiView & lv);
2143 Dialog * createGuiFloat(GuiView & lv);
2144 Dialog * createGuiGraphics(GuiView & lv);
2145 Dialog * createGuiInclude(GuiView & lv);
2146 Dialog * createGuiLabel(GuiView & lv);
2147 Dialog * createGuiListings(GuiView & lv);
2148 Dialog * createGuiLog(GuiView & lv);
2149 Dialog * createGuiMathMatrix(GuiView & lv);
2150 Dialog * createGuiNomenclature(GuiView & lv);
2151 Dialog * createGuiNote(GuiView & lv);
2152 Dialog * createGuiParagraph(GuiView & lv);
2153 Dialog * createGuiPreferences(GuiView & lv);
2154 Dialog * createGuiPrint(GuiView & lv);
2155 Dialog * createGuiRef(GuiView & lv);
2156 Dialog * createGuiSearch(GuiView & lv);
2157 Dialog * createGuiSendTo(GuiView & lv);
2158 Dialog * createGuiShowFile(GuiView & lv);
2159 Dialog * createGuiSpellchecker(GuiView & lv);
2160 Dialog * createGuiSymbols(GuiView & lv);
2161 Dialog * createGuiTabularCreate(GuiView & lv);
2162 Dialog * createGuiTabular(GuiView & lv);
2163 Dialog * createGuiTexInfo(GuiView & lv);
2164 Dialog * createGuiToc(GuiView & lv);
2165 Dialog * createGuiThesaurus(GuiView & lv);
2166 Dialog * createGuiHyperlink(GuiView & lv);
2167 Dialog * createGuiVSpace(GuiView & lv);
2168 Dialog * createGuiViewSource(GuiView & lv);
2169 Dialog * createGuiWrap(GuiView & lv);
2172 Dialog * GuiView::build(string const & name)
2174 BOOST_ASSERT(isValidName(name));
2176 if (name == "aboutlyx")
2177 return createGuiAbout(*this);
2178 if (name == "bibitem")
2179 return createGuiBibitem(*this);
2180 if (name == "bibtex")
2181 return createGuiBibtex(*this);
2183 return createGuiBox(*this);
2184 if (name == "branch")
2185 return createGuiBranch(*this);
2186 if (name == "changes")
2187 return createGuiChanges(*this);
2188 if (name == "character")
2189 return createGuiCharacter(*this);
2190 if (name == "citation")
2191 return createGuiCitation(*this);
2192 if (name == "document")
2193 return createGuiDocument(*this);
2194 if (name == "errorlist")
2195 return createGuiErrorList(*this);
2197 return createGuiERT(*this);
2198 if (name == "external")
2199 return createGuiExternal(*this);
2201 return createGuiShowFile(*this);
2202 if (name == "findreplace")
2203 return createGuiSearch(*this);
2204 if (name == "float")
2205 return createGuiFloat(*this);
2206 if (name == "graphics")
2207 return createGuiGraphics(*this);
2208 if (name == "include")
2209 return createGuiInclude(*this);
2210 if (name == "nomenclature")
2211 return createGuiNomenclature(*this);
2212 if (name == "label")
2213 return createGuiLabel(*this);
2215 return createGuiLog(*this);
2216 if (name == "view-source")
2217 return createGuiViewSource(*this);
2218 if (name == "mathdelimiter")
2219 return createGuiDelimiter(*this);
2220 if (name == "mathmatrix")
2221 return createGuiMathMatrix(*this);
2223 return createGuiNote(*this);
2224 if (name == "paragraph")
2225 return createGuiParagraph(*this);
2226 if (name == "prefs")
2227 return createGuiPreferences(*this);
2228 if (name == "print")
2229 return createGuiPrint(*this);
2231 return createGuiRef(*this);
2232 if (name == "sendto")
2233 return createGuiSendTo(*this);
2234 if (name == "spellchecker")
2235 return createGuiSpellchecker(*this);
2236 if (name == "symbols")
2237 return createGuiSymbols(*this);
2238 if (name == "tabular")
2239 return createGuiTabular(*this);
2240 if (name == "tabularcreate")
2241 return createGuiTabularCreate(*this);
2242 if (name == "texinfo")
2243 return createGuiTexInfo(*this);
2244 #ifdef HAVE_LIBAIKSAURUS
2245 if (name == "thesaurus")
2246 return createGuiThesaurus(*this);
2249 return createGuiToc(*this);
2251 return createGuiHyperlink(*this);
2252 if (name == "vspace")
2253 return createGuiVSpace(*this);
2255 return createGuiWrap(*this);
2256 if (name == "listings")
2257 return createGuiListings(*this);
2263 } // namespace frontend
2266 #include "GuiView_moc.cpp"