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 TabWorkArea * tab_widget = 0;
228 for (int i = 0; i != splitter_->count(); ++i) {
229 QWidget * w = splitter_->widget(i);
232 tab_widget = dynamic_cast<TabWorkArea *>(w);
241 GuiWorkArea * current_work_area_;
242 QSplitter * splitter_;
243 QStackedWidget * stack_widget_;
244 BackgroundWidget * bg_widget_;
246 GuiToolbars * toolbars_;
247 /// The main layout box.
249 * \warning Don't Delete! The layout box is actually owned by
250 * whichever toolbar contains it. All the GuiView class needs is a
251 * means of accessing it.
253 * FIXME: replace that with a proper model so that we are not limited
254 * to only one dialog.
256 GuiLayoutBox * layout_;
259 map<string, Inset *> open_insets_;
262 map<string, DialogPtr> dialogs_;
264 unsigned int smallIconSize;
265 unsigned int normalIconSize;
266 unsigned int bigIconSize;
268 QTimer statusbar_timer_;
269 /// are we quitting by the menu?
270 bool quitting_by_menu_;
271 /// auto-saving of buffers
272 Timeout autosave_timeout_;
273 /// flag against a race condition due to multiclicks, see bug #1119
278 GuiView::GuiView(int id)
279 : d(*new GuiViewPrivate), id_(id)
281 // GuiToolbars *must* be initialised before the menu bar.
282 d.toolbars_ = new GuiToolbars(*this);
284 // Fill up the menu bar.
285 guiApp->menus().fillMenuBar(this);
287 setCentralWidget(d.stack_widget_);
289 // Start autosave timer
290 if (lyxrc.autosave) {
291 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
292 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
293 d.autosave_timeout_.start();
295 connect(&d.statusbar_timer_, SIGNAL(timeout()),
296 this, SLOT(clearMessage()));
298 // Qt bug? signal lastWindowClosed does not work
299 setAttribute(Qt::WA_QuitOnClose, false);
300 setAttribute(Qt::WA_DeleteOnClose, true);
302 // assign an icon to main form. We do not do it under Qt/Mac,
303 // since the icon is provided in the application bundle.
304 setWindowIcon(QPixmap(":/images/lyx.png"));
308 setAcceptDrops(true);
310 statusBar()->setSizeGripEnabled(true);
312 // Forbid too small unresizable window because it can happen
313 // with some window manager under X11.
314 setMinimumSize(300, 200);
316 if (!lyxrc.allow_geometry_session)
317 // No session handling, default to a sane size.
318 setGeometry(50, 50, 690, 510);
320 // Now take care of session management.
322 QString const key = "view-" + QString::number(id_);
324 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
325 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
329 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
330 setGeometry(50, 50, 690, 510);
332 setIconSize(settings.value(key + "/icon_size").toSize());
342 void GuiView::close()
344 d.quitting_by_menu_ = true;
345 d.current_work_area_ = 0;
346 for (int i = 0; i != d.splitter_->count(); ++i) {
347 TabWorkArea * twa = d.tabWorkArea(i);
351 QMainWindow::close();
352 d.quitting_by_menu_ = false;
356 void GuiView::setFocus()
358 if (d.current_work_area_)
359 d.current_work_area_->setFocus();
365 QMenu * GuiView::createPopupMenu()
367 return d.toolBarPopup(this);
371 void GuiView::showEvent(QShowEvent * e)
373 LYXERR(Debug::GUI, "Passed Geometry "
374 << size().height() << "x" << size().width()
375 << "+" << pos().x() << "+" << pos().y());
377 if (d.splitter_->count() == 0)
378 // No work area, switch to the background widget.
381 QMainWindow::showEvent(e);
385 void GuiView::closeEvent(QCloseEvent * close_event)
387 // we may have been called through the close window button
388 // which bypasses the LFUN machinery.
389 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
390 if (!quitWriteAll()) {
391 close_event->ignore();
396 // Make sure that no LFUN use this close to be closed View.
397 theLyXFunc().setLyXView(0);
399 // Save toolbars configuration
400 if (isFullScreen()) {
401 d.toolbars_->toggleFullScreen(!isFullScreen());
405 // Make sure the timer time out will not trigger a statusbar update.
406 d.statusbar_timer_.stop();
408 // Saving fullscreen requires additional tweaks in the toolbar code.
409 // It wouldn't also work under linux natively.
410 if (lyxrc.allow_geometry_session && !isFullScreen()) {
412 QString const key = "view-" + QString::number(id_);
414 settings.setValue(key + "/pos", pos());
415 settings.setValue(key + "/size", size());
417 settings.setValue(key + "/geometry", saveGeometry());
419 settings.setValue(key + "/icon_size", iconSize());
420 d.toolbars_->saveToolbarInfo();
421 // Now take care of all other dialogs:
422 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
423 for (; it!= d.dialogs_.end(); ++it)
424 it->second->saveSession();
427 guiApp->unregisterView(id_);
428 if (guiApp->viewCount() > 0) {
429 // Just close the window and do nothing else if this is not the
431 close_event->accept();
437 // this is the place where we leave the frontend.
438 // it is the only point at which we start quitting.
439 close_event->accept();
440 // quit the event loop
445 void GuiView::dragEnterEvent(QDragEnterEvent * event)
447 if (event->mimeData()->hasUrls())
449 /// \todo Ask lyx-devel is this is enough:
450 /// if (event->mimeData()->hasFormat("text/plain"))
451 /// event->acceptProposedAction();
455 void GuiView::dropEvent(QDropEvent* event)
457 QList<QUrl> files = event->mimeData()->urls();
461 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
462 for (int i = 0; i != files.size(); ++i) {
463 string const file = os::internal_path(fromqstr(
464 files.at(i).toLocalFile()));
466 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
471 void GuiView::message(docstring const & str)
473 if (ForkedProcess::iAmAChild())
476 statusBar()->showMessage(toqstr(str));
477 d.statusbar_timer_.stop();
478 d.statusbar_timer_.start(3000);
482 void GuiView::smallSizedIcons()
484 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
488 void GuiView::normalSizedIcons()
490 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
494 void GuiView::bigSizedIcons()
496 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
500 void GuiView::clearMessage()
504 theLyXFunc().setLyXView(this);
505 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
506 d.statusbar_timer_.stop();
510 void GuiView::updateWindowTitle(GuiWorkArea * wa)
512 if (wa != d.current_work_area_)
514 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
515 setWindowIconText(wa->windowIconText());
519 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
522 disconnectBufferView();
523 connectBufferView(wa->bufferView());
524 connectBuffer(wa->bufferView().buffer());
525 d.current_work_area_ = wa;
526 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
527 this, SLOT(updateWindowTitle(GuiWorkArea *)));
528 updateWindowTitle(wa);
531 // Buffer-dependent dialogs should be updated or
532 // hidden. This should go here because some dialogs (eg ToC)
533 // require bv_->text.
534 updateBufferDependent(true);
541 void GuiView::updateStatusBar()
543 // let the user see the explicit message
544 if (d.statusbar_timer_.isActive())
547 theLyXFunc().setLyXView(this);
548 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
552 bool GuiView::hasFocus() const
554 return qApp->activeWindow() == this;
558 bool GuiView::event(QEvent * e)
562 // Useful debug code:
563 //case QEvent::ActivationChange:
564 //case QEvent::WindowDeactivate:
565 //case QEvent::Paint:
566 //case QEvent::Enter:
567 //case QEvent::Leave:
568 //case QEvent::HoverEnter:
569 //case QEvent::HoverLeave:
570 //case QEvent::HoverMove:
571 //case QEvent::StatusTip:
572 //case QEvent::DragEnter:
573 //case QEvent::DragLeave:
577 case QEvent::WindowActivate: {
578 guiApp->setCurrentView(*this);
579 if (d.current_work_area_) {
580 BufferView & bv = d.current_work_area_->bufferView();
581 connectBufferView(bv);
582 connectBuffer(bv.buffer());
583 // The document structure, name and dialogs might have
584 // changed in another view.
585 updateBufferDependent(true);
590 setWindowTitle(qt_("LyX"));
591 setWindowIconText(qt_("LyX"));
594 return QMainWindow::event(e);
597 case QEvent::ShortcutOverride: {
598 if (d.current_work_area_)
599 // Nothing special to do.
600 return QMainWindow::event(e);
602 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
604 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
606 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
607 || ke->key() == Qt::Key_Backtab)
608 return QMainWindow::event(e);
610 // Allow processing of shortcuts that are allowed even when no Buffer
612 theLyXFunc().setLyXView(this);
614 setKeySymbol(&sym, ke);
615 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
621 return QMainWindow::event(e);
626 bool GuiView::focusNextPrevChild(bool /*next*/)
633 void GuiView::setBusy(bool busy)
635 if (d.current_work_area_) {
636 d.current_work_area_->setUpdatesEnabled(!busy);
638 d.current_work_area_->stopBlinkingCursor();
640 d.current_work_area_->startBlinkingCursor();
644 QApplication::setOverrideCursor(Qt::WaitCursor);
646 QApplication::restoreOverrideCursor();
650 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
652 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
654 if (tbinfo.flags & ToolbarInfo::TOP) {
656 addToolBarBreak(Qt::TopToolBarArea);
657 addToolBar(Qt::TopToolBarArea, toolBar);
660 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
661 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
662 #if (QT_VERSION >= 0x040202)
664 addToolBarBreak(Qt::BottomToolBarArea);
666 addToolBar(Qt::BottomToolBarArea, toolBar);
669 if (tbinfo.flags & ToolbarInfo::LEFT) {
670 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
671 #if (QT_VERSION >= 0x040202)
673 addToolBarBreak(Qt::LeftToolBarArea);
675 addToolBar(Qt::LeftToolBarArea, toolBar);
678 if (tbinfo.flags & ToolbarInfo::RIGHT) {
679 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
680 #if (QT_VERSION >= 0x040202)
682 addToolBarBreak(Qt::RightToolBarArea);
684 addToolBar(Qt::RightToolBarArea, toolBar);
687 // The following does not work so I cannot restore to exact toolbar location
689 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
690 toolBar->move(tbinfo.posx, tbinfo.posy);
697 GuiWorkArea * GuiView::workArea(Buffer & buffer)
699 for (int i = 0; i != d.splitter_->count(); ++i) {
700 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
708 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
711 // Automatically create a TabWorkArea if there are none yet.
712 if (!d.splitter_->count())
715 TabWorkArea * tab_widget = d.currentTabWorkArea();
716 return tab_widget->addWorkArea(buffer, *this);
720 void GuiView::addTabWorkArea()
722 TabWorkArea * twa = new TabWorkArea;
723 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
724 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
725 d.splitter_->addWidget(twa);
726 d.stack_widget_->setCurrentWidget(d.splitter_);
730 GuiWorkArea const * GuiView::currentWorkArea() const
732 return d.current_work_area_;
736 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
740 // Changing work area can result from opening a file so
741 // update the toc in any case.
744 d.current_work_area_ = wa;
745 for (int i = 0; i != d.splitter_->count(); ++i) {
746 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
752 void GuiView::removeWorkArea(GuiWorkArea * wa)
755 if (wa == d.current_work_area_) {
757 disconnectBufferView();
758 hideBufferDependent();
759 d.current_work_area_ = 0;
762 for (int i = 0; i != d.splitter_->count(); ++i) {
763 TabWorkArea * twa = d.tabWorkArea(i);
764 if (!twa->removeWorkArea(wa))
765 // Not found in this tab group.
768 // We found and removed the GuiWorkArea.
770 // No more WorkAreas in this tab group, so delete it.
775 if (d.current_work_area_)
776 // This means that we are not closing the current GuiWorkArea;
779 // Switch to the next GuiWorkArea in the found TabWorkArea.
780 d.current_work_area_ = twa->currentWorkArea();
784 if (d.splitter_->count() == 0)
785 // No more work area, switch to the background widget.
790 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
796 void GuiView::updateLayoutList()
799 d.layout_->updateContents(false);
803 void GuiView::updateToolbars()
805 if (d.current_work_area_) {
807 d.current_work_area_->bufferView().cursor().inMathed();
809 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
811 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
812 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
813 bool const mathmacrotemplate =
814 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
816 d.toolbars_->update(math, table, review, mathmacrotemplate);
818 d.toolbars_->update(false, false, false, false);
820 // update read-only status of open dialogs.
825 Buffer * GuiView::buffer()
827 if (d.current_work_area_)
828 return &d.current_work_area_->bufferView().buffer();
833 Buffer const * GuiView::buffer() const
835 if (d.current_work_area_)
836 return &d.current_work_area_->bufferView().buffer();
841 void GuiView::setBuffer(Buffer * newBuffer)
843 BOOST_ASSERT(newBuffer);
846 GuiWorkArea * wa = workArea(*newBuffer);
848 updateLabels(*newBuffer->masterBuffer());
849 wa = addWorkArea(*newBuffer);
851 //Disconnect the old buffer...there's no new one.
854 connectBuffer(*newBuffer);
855 connectBufferView(wa->bufferView());
856 setCurrentWorkArea(wa);
862 void GuiView::connectBuffer(Buffer & buf)
864 buf.setGuiDelegate(this);
868 void GuiView::disconnectBuffer()
870 if (d.current_work_area_)
871 d.current_work_area_->bufferView().setGuiDelegate(0);
875 void GuiView::connectBufferView(BufferView & bv)
877 bv.setGuiDelegate(this);
881 void GuiView::disconnectBufferView()
883 if (d.current_work_area_)
884 d.current_work_area_->bufferView().setGuiDelegate(0);
888 void GuiView::errors(string const & error_type)
890 ErrorList & el = buffer()->errorList(error_type);
892 showDialog("errorlist", error_type);
896 void GuiView::updateDialog(string const & name, string const & data)
898 if (!isDialogVisible(name))
901 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
902 if (it == d.dialogs_.end())
905 Dialog * const dialog = it->second.get();
906 if (dialog->isVisibleView())
907 dialog->updateData(data);
911 BufferView * GuiView::view()
913 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
917 void GuiView::updateToc()
919 updateDialog("toc", "");
923 void GuiView::updateEmbeddedFiles()
925 updateDialog("embedding", "");
929 void GuiView::autoSave()
931 LYXERR(Debug::INFO, "Running autoSave()");
934 view()->buffer().autoSave();
938 void GuiView::resetAutosaveTimers()
941 d.autosave_timeout_.restart();
945 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
949 Buffer * buf = buffer();
951 /* In LyX/Mac, when a dialog is open, the menus of the
952 application can still be accessed without giving focus to
953 the main window. In this case, we want to disable the menu
954 entries that are buffer-related.
956 Note that this code is not perfect, as bug 1941 attests:
957 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
959 if (cmd.origin == FuncRequest::MENU && !hasFocus())
963 case LFUN_BUFFER_WRITE:
964 enable = buf && (buf->isUnnamed() || !buf->isClean());
967 case LFUN_BUFFER_WRITE_AS:
971 case LFUN_TOOLBAR_TOGGLE:
972 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
975 case LFUN_DIALOG_TOGGLE:
976 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
977 // fall through to set "enable"
978 case LFUN_DIALOG_SHOW: {
979 string const name = cmd.getArg(0);
981 enable = name == "aboutlyx"
982 || name == "file" //FIXME: should be removed.
984 || name == "texinfo";
985 else if (name == "print")
986 enable = buf->isExportable("dvi")
987 && lyxrc.print_command != "none";
988 else if (name == "character") {
992 InsetCode ic = view()->cursor().inset().lyxCode();
993 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
996 else if (name == "symbols") {
997 if (!view() || view()->cursor().inMathed())
1000 InsetCode ic = view()->cursor().inset().lyxCode();
1001 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1004 else if (name == "latexlog")
1005 enable = FileName(buf->logName()).isReadableFile();
1006 else if (name == "spellchecker")
1007 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1008 enable = !buf->isReadonly();
1012 else if (name == "vclog")
1013 enable = buf->lyxvc().inUse();
1017 case LFUN_DIALOG_UPDATE: {
1018 string const name = cmd.getArg(0);
1020 enable = name == "prefs";
1024 case LFUN_INSET_APPLY: {
1029 string const name = cmd.getArg(0);
1030 Inset * inset = getOpenInset(name);
1032 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1034 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1035 // Every inset is supposed to handle this
1036 BOOST_ASSERT(false);
1040 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1041 flag |= getStatus(fr);
1043 enable = flag.enabled();
1055 flag.enabled(false);
1061 static FileName selectTemplateFile()
1063 FileDialog dlg(_("Select template file"));
1064 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1065 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1067 FileDialog::Result result =
1068 dlg.open(from_utf8(lyxrc.template_path),
1069 FileFilterList(_("LyX Documents (*.lyx)")),
1072 if (result.first == FileDialog::Later)
1074 if (result.second.empty())
1076 return FileName(to_utf8(result.second));
1080 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1084 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1087 message(_("Document not loaded."));
1092 setBuffer(newBuffer);
1094 // scroll to the position when the file was last closed
1095 if (lyxrc.use_lastfilepos) {
1096 LastFilePosSection::FilePos filepos =
1097 LyX::ref().session().lastFilePos().load(filename);
1098 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1102 LyX::ref().session().lastFiles().add(filename);
1109 void GuiView::openDocument(string const & fname)
1111 string initpath = lyxrc.document_path;
1114 string const trypath = buffer()->filePath();
1115 // If directory is writeable, use this as default.
1116 if (FileName(trypath).isDirWritable())
1122 if (fname.empty()) {
1123 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1124 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1125 dlg.setButton2(_("Examples|#E#e"),
1126 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1128 FileDialog::Result result =
1129 dlg.open(from_utf8(initpath),
1130 FileFilterList(_("LyX Documents (*.lyx)")),
1133 if (result.first == FileDialog::Later)
1136 filename = to_utf8(result.second);
1138 // check selected filename
1139 if (filename.empty()) {
1140 message(_("Canceled."));
1146 // get absolute path of file and add ".lyx" to the filename if
1148 FileName const fullname =
1149 fileSearch(string(), filename, "lyx", support::may_not_exist);
1150 if (!fullname.empty())
1151 filename = fullname.absFilename();
1153 // if the file doesn't exist, let the user create one
1154 if (!fullname.exists()) {
1155 // the user specifically chose this name. Believe him.
1156 Buffer * const b = newFile(filename, string(), true);
1162 docstring const disp_fn = makeDisplayPath(filename);
1163 message(bformat(_("Opening document %1$s..."), disp_fn));
1166 Buffer * buf = loadDocument(fullname);
1170 buf->errors("Parse");
1171 str2 = bformat(_("Document %1$s opened."), disp_fn);
1173 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1178 // FIXME: clean that
1179 static bool import(GuiView * lv, FileName const & filename,
1180 string const & format, ErrorList & errorList)
1182 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1184 string loader_format;
1185 vector<string> loaders = theConverters().loaders();
1186 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1187 for (vector<string>::const_iterator it = loaders.begin();
1188 it != loaders.end(); ++it) {
1189 if (!theConverters().isReachable(format, *it))
1192 string const tofile =
1193 changeExtension(filename.absFilename(),
1194 formats.extension(*it));
1195 if (!theConverters().convert(0, filename, FileName(tofile),
1196 filename, format, *it, errorList))
1198 loader_format = *it;
1201 if (loader_format.empty()) {
1202 frontend::Alert::error(_("Couldn't import file"),
1203 bformat(_("No information for importing the format %1$s."),
1204 formats.prettyName(format)));
1208 loader_format = format;
1210 if (loader_format == "lyx") {
1211 Buffer * buf = lv->loadDocument(lyxfile);
1216 buf->errors("Parse");
1218 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1222 bool as_paragraphs = loader_format == "textparagraph";
1223 string filename2 = (loader_format == format) ? filename.absFilename()
1224 : changeExtension(filename.absFilename(),
1225 formats.extension(loader_format));
1226 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1227 theLyXFunc().setLyXView(lv);
1228 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1235 void GuiView::importDocument(string const & argument)
1238 string filename = split(argument, format, ' ');
1240 LYXERR(Debug::INFO, format << " file: " << filename);
1242 // need user interaction
1243 if (filename.empty()) {
1244 string initpath = lyxrc.document_path;
1246 Buffer const * buf = buffer();
1248 string const trypath = buf->filePath();
1249 // If directory is writeable, use this as default.
1250 if (FileName(trypath).isDirWritable())
1254 docstring const text = bformat(_("Select %1$s file to import"),
1255 formats.prettyName(format));
1257 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1258 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1259 dlg.setButton2(_("Examples|#E#e"),
1260 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1262 docstring filter = formats.prettyName(format);
1265 filter += from_utf8(formats.extension(format));
1268 FileDialog::Result result =
1269 dlg.open(from_utf8(initpath),
1270 FileFilterList(filter),
1273 if (result.first == FileDialog::Later)
1276 filename = to_utf8(result.second);
1278 // check selected filename
1279 if (filename.empty())
1280 message(_("Canceled."));
1283 if (filename.empty())
1286 // get absolute path of file
1287 FileName const fullname(makeAbsPath(filename));
1289 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1291 // Check if the document already is open
1292 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1295 if (!closeBuffer()) {
1296 message(_("Canceled."));
1301 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1303 // if the file exists already, and we didn't do
1304 // -i lyx thefile.lyx, warn
1305 if (lyxfile.exists() && fullname != lyxfile) {
1307 docstring text = bformat(_("The document %1$s already exists.\n\n"
1308 "Do you want to overwrite that document?"), displaypath);
1309 int const ret = Alert::prompt(_("Overwrite document?"),
1310 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1313 message(_("Canceled."));
1318 message(bformat(_("Importing %1$s..."), displaypath));
1319 ErrorList errorList;
1320 if (import(this, fullname, format, errorList))
1321 message(_("imported."));
1323 message(_("file not imported!"));
1325 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1329 void GuiView::newDocument(string const & filename, bool from_template)
1331 FileName initpath(lyxrc.document_path);
1332 Buffer * buf = buffer();
1334 FileName const trypath(buf->filePath());
1335 // If directory is writeable, use this as default.
1336 if (trypath.isDirWritable())
1340 string templatefile = from_template ?
1341 selectTemplateFile().absFilename() : string();
1343 if (filename.empty())
1344 b = newUnnamedFile(templatefile, initpath);
1346 b = newFile(filename, templatefile, true);
1350 // Ensure the cursor is correctly positionned on screen.
1351 view()->showCursor();
1355 void GuiView::insertLyXFile(docstring const & fname)
1357 BufferView * bv = view();
1362 FileName filename(to_utf8(fname));
1364 if (!filename.empty()) {
1365 bv->insertLyXFile(filename);
1369 // Launch a file browser
1371 string initpath = lyxrc.document_path;
1372 string const trypath = bv->buffer().filePath();
1373 // If directory is writeable, use this as default.
1374 if (FileName(trypath).isDirWritable())
1378 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1379 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1380 dlg.setButton2(_("Examples|#E#e"),
1381 from_utf8(addPath(package().system_support().absFilename(),
1384 FileDialog::Result result =
1385 dlg.open(from_utf8(initpath),
1386 FileFilterList(_("LyX Documents (*.lyx)")),
1389 if (result.first == FileDialog::Later)
1393 filename.set(to_utf8(result.second));
1395 // check selected filename
1396 if (filename.empty()) {
1397 // emit message signal.
1398 message(_("Canceled."));
1402 bv->insertLyXFile(filename);
1406 void GuiView::insertPlaintextFile(docstring const & fname,
1409 BufferView * bv = view();
1414 FileName filename(to_utf8(fname));
1416 if (!filename.empty()) {
1417 bv->insertPlaintextFile(filename, asParagraph);
1421 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1422 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1424 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1425 FileFilterList(), docstring());
1427 if (result.first == FileDialog::Later)
1431 filename.set(to_utf8(result.second));
1433 // check selected filename
1434 if (filename.empty()) {
1435 // emit message signal.
1436 message(_("Canceled."));
1440 bv->insertPlaintextFile(filename, asParagraph);
1444 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1446 FileName fname = b.fileName();
1447 FileName const oldname = fname;
1449 if (!newname.empty()) {
1451 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1453 // Switch to this Buffer.
1456 /// No argument? Ask user through dialog.
1458 FileDialog dlg(_("Choose a filename to save document as"),
1459 LFUN_BUFFER_WRITE_AS);
1460 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1461 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1463 if (!isLyXFilename(fname.absFilename()))
1464 fname.changeExtension(".lyx");
1466 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1468 FileDialog::Result result =
1469 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1471 from_utf8(fname.onlyFileName()));
1473 if (result.first == FileDialog::Later)
1476 fname.set(to_utf8(result.second));
1481 if (!isLyXFilename(fname.absFilename()))
1482 fname.changeExtension(".lyx");
1485 if (FileName(fname).exists()) {
1486 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1487 docstring text = bformat(_("The document %1$s already "
1488 "exists.\n\nDo you want to "
1489 "overwrite that document?"),
1491 int const ret = Alert::prompt(_("Overwrite document?"),
1492 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1495 case 1: return renameBuffer(b, docstring());
1496 case 2: return false;
1500 // Ok, change the name of the buffer
1501 b.setFileName(fname.absFilename());
1503 bool unnamed = b.isUnnamed();
1504 b.setUnnamed(false);
1505 b.saveCheckSum(fname);
1507 if (!saveBuffer(b)) {
1508 b.setFileName(oldname.absFilename());
1509 b.setUnnamed(unnamed);
1510 b.saveCheckSum(oldname);
1518 bool GuiView::saveBuffer(Buffer & b)
1521 return renameBuffer(b, docstring());
1524 LyX::ref().session().lastFiles().add(b.fileName());
1528 // Switch to this Buffer.
1531 // FIXME: we don't tell the user *WHY* the save failed !!
1532 docstring const file = makeDisplayPath(b.absFileName(), 30);
1533 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1534 "Do you want to rename the document and "
1535 "try again?"), file);
1536 int const ret = Alert::prompt(_("Rename and save?"),
1537 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1540 if (!renameBuffer(b, docstring()))
1549 return saveBuffer(b);
1553 bool GuiView::closeBuffer()
1555 Buffer * buf = buffer();
1556 return buf && closeBuffer(*buf);
1560 bool GuiView::closeBuffer(Buffer & buf)
1562 if (buf.isClean() || buf.paragraphs().empty()) {
1563 theBufferList().release(&buf);
1566 // Switch to this Buffer.
1571 if (buf.isUnnamed())
1572 file = from_utf8(buf.fileName().onlyFileName());
1574 file = buf.fileName().displayName(30);
1576 docstring const text = bformat(_("The document %1$s has unsaved changes."
1577 "\n\nDo you want to save the document or discard the changes?"), file);
1578 int const ret = Alert::prompt(_("Save changed document?"),
1579 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1583 if (!saveBuffer(buf))
1587 // if we crash after this we could
1588 // have no autosave file but I guess
1589 // this is really improbable (Jug)
1590 removeAutosaveFile(buf.absFileName());
1596 // save file names to .lyx/session
1597 // if master/slave are both open, do not save slave since it
1598 // will be automatically loaded when the master is loaded
1599 if (buf.masterBuffer() == &buf)
1600 LyX::ref().session().lastOpened().add(buf.fileName());
1602 theBufferList().release(&buf);
1607 bool GuiView::quitWriteAll()
1609 while (!theBufferList().empty()) {
1610 Buffer * b = theBufferList().first();
1611 if (!closeBuffer(*b))
1618 bool GuiView::dispatch(FuncRequest const & cmd)
1620 BufferView * bv = view();
1621 // By default we won't need any update.
1623 bv->cursor().updateFlags(Update::None);
1625 switch(cmd.action) {
1626 case LFUN_FILE_OPEN:
1627 openDocument(to_utf8(cmd.argument()));
1630 case LFUN_BUFFER_IMPORT:
1631 importDocument(to_utf8(cmd.argument()));
1634 case LFUN_BUFFER_SWITCH:
1635 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1638 case LFUN_BUFFER_NEXT:
1639 setBuffer(theBufferList().next(buffer()));
1642 case LFUN_BUFFER_PREVIOUS:
1643 setBuffer(theBufferList().previous(buffer()));
1646 case LFUN_COMMAND_EXECUTE: {
1647 bool const show_it = cmd.argument() != "off";
1648 d.toolbars_->showCommandBuffer(show_it);
1651 case LFUN_DROP_LAYOUTS_CHOICE:
1653 d.layout_->showPopup();
1656 case LFUN_MENU_OPEN:
1657 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1658 menu->exec(QCursor::pos());
1661 case LFUN_FILE_INSERT:
1662 insertLyXFile(cmd.argument());
1664 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1665 insertPlaintextFile(cmd.argument(), true);
1668 case LFUN_FILE_INSERT_PLAINTEXT:
1669 insertPlaintextFile(cmd.argument(), false);
1672 case LFUN_BUFFER_WRITE:
1674 saveBuffer(bv->buffer());
1677 case LFUN_BUFFER_WRITE_AS:
1679 renameBuffer(bv->buffer(), cmd.argument());
1682 case LFUN_BUFFER_WRITE_ALL: {
1683 Buffer * first = theBufferList().first();
1686 message(_("Saving all documents..."));
1687 // We cannot use a for loop as the buffer list cycles.
1693 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1694 b = theBufferList().next(b);
1695 } while (b != first);
1696 message(_("All documents saved."));
1700 case LFUN_TOOLBAR_TOGGLE: {
1701 string const name = cmd.getArg(0);
1702 bool const allowauto = cmd.getArg(1) == "allowauto";
1703 // it is possible to get current toolbar status like this,...
1704 // but I decide to obey the order of ToolbarBackend::flags
1705 // and disregard real toolbar status.
1706 // toolbars_->saveToolbarInfo();
1708 // toggle state on/off/auto
1709 d.toolbars_->toggleToolbarState(name, allowauto);
1713 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1715 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1719 if (tbi->flags & ToolbarInfo::ON)
1721 else if (tbi->flags & ToolbarInfo::OFF)
1723 else if (tbi->flags & ToolbarInfo::AUTO)
1726 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1727 _(tbi->gui_name), state));
1731 case LFUN_DIALOG_UPDATE: {
1732 string const name = to_utf8(cmd.argument());
1733 // Can only update a dialog connected to an existing inset
1734 Inset * inset = getOpenInset(name);
1736 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1737 inset->dispatch(view()->cursor(), fr);
1738 } else if (name == "paragraph") {
1739 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1740 } else if (name == "prefs") {
1741 updateDialog(name, string());
1746 case LFUN_DIALOG_TOGGLE: {
1747 if (isDialogVisible(cmd.getArg(0)))
1748 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1750 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1754 case LFUN_DIALOG_DISCONNECT_INSET:
1755 disconnectDialog(to_utf8(cmd.argument()));
1758 case LFUN_DIALOG_HIDE: {
1761 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1765 case LFUN_DIALOG_SHOW: {
1766 string const name = cmd.getArg(0);
1767 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1769 if (name == "character") {
1770 data = freefont2string();
1772 showDialog("character", data);
1773 } else if (name == "latexlog") {
1774 Buffer::LogType type;
1775 string const logfile = buffer()->logName(&type);
1777 case Buffer::latexlog:
1780 case Buffer::buildlog:
1784 data += Lexer::quoteString(logfile);
1785 showDialog("log", data);
1786 } else if (name == "vclog") {
1787 string const data = "vc " +
1788 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1789 showDialog("log", data);
1790 } else if (name == "symbols") {
1791 data = bv->cursor().getEncoding()->name();
1793 showDialog("symbols", data);
1795 showDialog(name, data);
1799 case LFUN_INSET_APPLY: {
1800 string const name = cmd.getArg(0);
1801 Inset * inset = getOpenInset(name);
1803 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1804 inset->dispatch(view()->cursor(), fr);
1806 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1812 case LFUN_UI_TOGGLE:
1814 // Make sure the keyboard focus stays in the work area.
1826 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1828 string const arg = cmd.getArg(0);
1829 if (arg == "scrollbar") {
1830 // hide() is of no help
1831 if (d.current_work_area_->verticalScrollBarPolicy() ==
1832 Qt::ScrollBarAlwaysOff)
1834 d.current_work_area_->setVerticalScrollBarPolicy(
1835 Qt::ScrollBarAsNeeded);
1837 d.current_work_area_->setVerticalScrollBarPolicy(
1838 Qt::ScrollBarAlwaysOff);
1841 if (arg == "statusbar") {
1842 statusBar()->setVisible(!statusBar()->isVisible());
1845 if (arg == "menubar") {
1846 menuBar()->setVisible(!menuBar()->isVisible());
1849 #if QT_VERSION >= 0x040300
1850 if (arg == "frame") {
1852 getContentsMargins(&l, &t, &r, &b);
1853 //are the frames in default state?
1855 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1856 setContentsMargins(-2, -2, -2, -2);
1858 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1859 setContentsMargins(0, 0, 0, 0);
1864 if (arg != "fullscreen") {
1865 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1869 if (lyxrc.full_screen_toolbars)
1870 d.toolbars_->toggleFullScreen(!isFullScreen());
1872 if (isFullScreen()) {
1873 for (int i = 0; i != d.splitter_->count(); ++i)
1874 d.tabWorkArea(i)->setFullScreen(false);
1875 #if QT_VERSION >= 0x040300
1876 setContentsMargins(0, 0, 0, 0);
1880 statusBar()->show();
1882 for (int i = 0; i != d.splitter_->count(); ++i)
1883 d.tabWorkArea(i)->setFullScreen(true);
1884 #if QT_VERSION >= 0x040300
1885 setContentsMargins(-2, -2, -2, -2);
1888 statusBar()->hide();
1890 if (d.current_work_area_) {
1891 // It seems there is a bug somewhere preventing the scrollbar to
1892 // show up with updated parameters. This work-around seems to work.
1893 d.current_work_area_->verticalScrollBar()->show();
1899 Buffer const * GuiView::updateInset(Inset const * inset)
1901 if (!d.current_work_area_)
1905 d.current_work_area_->scheduleRedraw();
1907 return &d.current_work_area_->bufferView().buffer();
1911 void GuiView::restartCursor()
1913 /* When we move around, or type, it's nice to be able to see
1914 * the cursor immediately after the keypress.
1916 if (d.current_work_area_)
1917 d.current_work_area_->startBlinkingCursor();
1919 // Take this occasion to update the toobars and layout list.
1926 // This list should be kept in sync with the list of insets in
1927 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1928 // dialog should have the same name as the inset.
1930 char const * const dialognames[] = {
1931 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1932 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1933 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1934 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1935 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1937 #ifdef HAVE_LIBAIKSAURUS
1941 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1943 char const * const * const end_dialognames =
1944 dialognames + (sizeof(dialognames) / sizeof(char *));
1948 cmpCStr(char const * name) : name_(name) {}
1949 bool operator()(char const * other) {
1950 return strcmp(other, name_) == 0;
1957 bool isValidName(string const & name)
1959 return find_if(dialognames, end_dialognames,
1960 cmpCStr(name.c_str())) != end_dialognames;
1966 void GuiView::resetDialogs()
1968 // Make sure that no LFUN uses any LyXView.
1969 theLyXFunc().setLyXView(0);
1970 // FIXME: the "math panels" toolbar takes an awful lot of time to
1971 // initialise so we don't do that for the time being.
1972 //d.toolbars_->init();
1973 guiApp->menus().fillMenuBar(this);
1975 d.layout_->updateContents(true);
1976 // Now update controls with current buffer.
1977 theLyXFunc().setLyXView(this);
1982 Dialog * GuiView::find_or_build(string const & name)
1984 if (!isValidName(name))
1987 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1989 if (it != d.dialogs_.end())
1990 return it->second.get();
1992 Dialog * dialog = build(name);
1993 d.dialogs_[name].reset(dialog);
1994 if (lyxrc.allow_geometry_session)
1995 dialog->restoreSession();
2000 void GuiView::showDialog(string const & name, string const & data,
2007 Dialog * dialog = find_or_build(name);
2009 dialog->showData(data);
2011 d.open_insets_[name] = inset;
2017 bool GuiView::isDialogVisible(string const & name) const
2019 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2020 if (it == d.dialogs_.end())
2022 return it->second.get()->isVisibleView();
2026 void GuiView::hideDialog(string const & name, Inset * inset)
2028 // Don't send the signal if we are quitting, because on MSVC it is
2029 // destructed before the cut stack in CutAndPaste.cpp, and this method
2030 // is called from some inset destructor if the cut stack is not empty
2035 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2036 if (it == d.dialogs_.end())
2039 if (inset && inset != getOpenInset(name))
2042 Dialog * const dialog = it->second.get();
2043 if (dialog->isVisibleView())
2045 d.open_insets_[name] = 0;
2049 void GuiView::disconnectDialog(string const & name)
2051 if (!isValidName(name))
2054 if (d.open_insets_.find(name) != d.open_insets_.end())
2055 d.open_insets_[name] = 0;
2059 Inset * GuiView::getOpenInset(string const & name) const
2061 if (!isValidName(name))
2064 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2065 return it == d.open_insets_.end() ? 0 : it->second;
2069 void GuiView::hideAll() const
2071 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2072 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2074 for(; it != end; ++it)
2075 it->second->hideView();
2079 void GuiView::hideBufferDependent() const
2081 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2082 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2084 for(; it != end; ++it) {
2085 Dialog * dialog = it->second.get();
2086 if (dialog->isBufferDependent())
2092 void GuiView::updateBufferDependent(bool switched) const
2094 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2095 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2097 for(; it != end; ++it) {
2098 Dialog * dialog = it->second.get();
2099 if (!dialog->isVisibleView())
2101 if (switched && dialog->isBufferDependent()) {
2102 if (dialog->initialiseParams(""))
2103 dialog->updateView();
2107 // A bit clunky, but the dialog will request
2108 // that the kernel provides it with the necessary
2110 dialog->updateDialog();
2116 void GuiView::checkStatus()
2118 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2119 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2121 for(; it != end; ++it) {
2122 Dialog * const dialog = it->second.get();
2123 if (dialog && dialog->isVisibleView())
2124 dialog->checkStatus();
2130 // will be replaced by a proper factory...
2131 Dialog * createGuiAbout(GuiView & lv);
2132 Dialog * createGuiBibitem(GuiView & lv);
2133 Dialog * createGuiBibtex(GuiView & lv);
2134 Dialog * createGuiBox(GuiView & lv);
2135 Dialog * createGuiBranch(GuiView & lv);
2136 Dialog * createGuiChanges(GuiView & lv);
2137 Dialog * createGuiCharacter(GuiView & lv);
2138 Dialog * createGuiCitation(GuiView & lv);
2139 Dialog * createGuiDelimiter(GuiView & lv);
2140 Dialog * createGuiDocument(GuiView & lv);
2141 Dialog * createGuiErrorList(GuiView & lv);
2142 Dialog * createGuiERT(GuiView & lv);
2143 Dialog * createGuiExternal(GuiView & lv);
2144 Dialog * createGuiFloat(GuiView & lv);
2145 Dialog * createGuiGraphics(GuiView & lv);
2146 Dialog * createGuiInclude(GuiView & lv);
2147 Dialog * createGuiLabel(GuiView & lv);
2148 Dialog * createGuiListings(GuiView & lv);
2149 Dialog * createGuiLog(GuiView & lv);
2150 Dialog * createGuiMathMatrix(GuiView & lv);
2151 Dialog * createGuiNomenclature(GuiView & lv);
2152 Dialog * createGuiNote(GuiView & lv);
2153 Dialog * createGuiParagraph(GuiView & lv);
2154 Dialog * createGuiPreferences(GuiView & lv);
2155 Dialog * createGuiPrint(GuiView & lv);
2156 Dialog * createGuiRef(GuiView & lv);
2157 Dialog * createGuiSearch(GuiView & lv);
2158 Dialog * createGuiSendTo(GuiView & lv);
2159 Dialog * createGuiShowFile(GuiView & lv);
2160 Dialog * createGuiSpellchecker(GuiView & lv);
2161 Dialog * createGuiSymbols(GuiView & lv);
2162 Dialog * createGuiTabularCreate(GuiView & lv);
2163 Dialog * createGuiTabular(GuiView & lv);
2164 Dialog * createGuiTexInfo(GuiView & lv);
2165 Dialog * createGuiToc(GuiView & lv);
2166 Dialog * createGuiThesaurus(GuiView & lv);
2167 Dialog * createGuiHyperlink(GuiView & lv);
2168 Dialog * createGuiVSpace(GuiView & lv);
2169 Dialog * createGuiViewSource(GuiView & lv);
2170 Dialog * createGuiWrap(GuiView & lv);
2173 Dialog * GuiView::build(string const & name)
2175 BOOST_ASSERT(isValidName(name));
2177 if (name == "aboutlyx")
2178 return createGuiAbout(*this);
2179 if (name == "bibitem")
2180 return createGuiBibitem(*this);
2181 if (name == "bibtex")
2182 return createGuiBibtex(*this);
2184 return createGuiBox(*this);
2185 if (name == "branch")
2186 return createGuiBranch(*this);
2187 if (name == "changes")
2188 return createGuiChanges(*this);
2189 if (name == "character")
2190 return createGuiCharacter(*this);
2191 if (name == "citation")
2192 return createGuiCitation(*this);
2193 if (name == "document")
2194 return createGuiDocument(*this);
2195 if (name == "errorlist")
2196 return createGuiErrorList(*this);
2198 return createGuiERT(*this);
2199 if (name == "external")
2200 return createGuiExternal(*this);
2202 return createGuiShowFile(*this);
2203 if (name == "findreplace")
2204 return createGuiSearch(*this);
2205 if (name == "float")
2206 return createGuiFloat(*this);
2207 if (name == "graphics")
2208 return createGuiGraphics(*this);
2209 if (name == "include")
2210 return createGuiInclude(*this);
2211 if (name == "nomenclature")
2212 return createGuiNomenclature(*this);
2213 if (name == "label")
2214 return createGuiLabel(*this);
2216 return createGuiLog(*this);
2217 if (name == "view-source")
2218 return createGuiViewSource(*this);
2219 if (name == "mathdelimiter")
2220 return createGuiDelimiter(*this);
2221 if (name == "mathmatrix")
2222 return createGuiMathMatrix(*this);
2224 return createGuiNote(*this);
2225 if (name == "paragraph")
2226 return createGuiParagraph(*this);
2227 if (name == "prefs")
2228 return createGuiPreferences(*this);
2229 if (name == "print")
2230 return createGuiPrint(*this);
2232 return createGuiRef(*this);
2233 if (name == "sendto")
2234 return createGuiSendTo(*this);
2235 if (name == "spellchecker")
2236 return createGuiSpellchecker(*this);
2237 if (name == "symbols")
2238 return createGuiSymbols(*this);
2239 if (name == "tabular")
2240 return createGuiTabular(*this);
2241 if (name == "tabularcreate")
2242 return createGuiTabularCreate(*this);
2243 if (name == "texinfo")
2244 return createGuiTexInfo(*this);
2245 #ifdef HAVE_LIBAIKSAURUS
2246 if (name == "thesaurus")
2247 return createGuiThesaurus(*this);
2250 return createGuiToc(*this);
2252 return createGuiHyperlink(*this);
2253 if (name == "vspace")
2254 return createGuiVSpace(*this);
2256 return createGuiWrap(*this);
2257 if (name == "listings")
2258 return createGuiListings(*this);
2264 } // namespace frontend
2267 #include "GuiView_moc.cpp"