3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * \author Abdelrazak Younes
11 * Full author contact details are available in file CREDITS.
19 #include "FileDialog.h"
20 #include "GuiApplication.h"
21 #include "GuiWorkArea.h"
22 #include "GuiKeySymbol.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
27 #include "qt_helpers.h"
29 #include "frontends/alert.h"
31 #include "buffer_funcs.h"
33 #include "BufferList.h"
34 #include "BufferParams.h"
35 #include "BufferView.h"
36 #include "Converter.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "support/gettext.h"
49 #include "Paragraph.h"
50 #include "TextClass.h"
52 #include "ToolbarBackend.h"
55 #include "support/debug.h"
56 #include "support/FileFilterList.h"
57 #include "support/FileName.h"
58 #include "support/filetools.h"
59 #include "support/ForkedCalls.h"
60 #include "support/lstrings.h"
61 #include "support/os.h"
62 #include "support/Package.h"
63 #include "support/Timeout.h"
66 #include <QApplication>
67 #include <QCloseEvent>
69 #include <QDesktopWidget>
70 #include <QDragEnterEvent>
78 #include <QPushButton>
82 #include <QStackedWidget>
89 #include <boost/assert.hpp>
90 #include <boost/bind.hpp>
92 #ifdef HAVE_SYS_TIME_H
93 # include <sys/time.h>
100 using namespace lyx::support;
104 extern bool quitting;
110 class BackgroundWidget : public QWidget
115 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
116 /// The text to be written on top of the pixmap
117 QString const text = lyx_version ? lyx_version : qt_("unknown version");
118 splash_ = QPixmap(":/images/banner.png");
120 QPainter pain(&splash_);
121 pain.setPen(QColor(255, 255, 0));
123 // The font used to display the version info
124 font.setStyleHint(QFont::SansSerif);
125 font.setWeight(QFont::Bold);
126 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
128 pain.drawText(260, 270, text);
131 void paintEvent(QPaintEvent *)
133 int x = (width() - splash_.width()) / 2;
134 int y = (height() - splash_.height()) / 2;
136 pain.drawPixmap(x, y, splash_);
146 typedef boost::shared_ptr<Dialog> DialogPtr;
148 struct GuiView::GuiViewPrivate
151 : current_work_area_(0), layout_(0),
152 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
154 // hardcode here the platform specific icon size
155 smallIconSize = 14; // scaling problems
156 normalIconSize = 20; // ok, default
157 bigIconSize = 26; // better for some math icons
159 splitter_ = new QSplitter;
160 bg_widget_ = new BackgroundWidget;
161 stack_widget_ = new QStackedWidget;
162 stack_widget_->addWidget(bg_widget_);
163 stack_widget_->addWidget(splitter_);
171 delete stack_widget_;
175 QMenu * toolBarPopup(GuiView * parent)
177 // FIXME: translation
178 QMenu * menu = new QMenu(parent);
179 QActionGroup * iconSizeGroup = new QActionGroup(parent);
181 QAction * smallIcons = new QAction(iconSizeGroup);
182 smallIcons->setText(qt_("Small-sized icons"));
183 smallIcons->setCheckable(true);
184 QObject::connect(smallIcons, SIGNAL(triggered()),
185 parent, SLOT(smallSizedIcons()));
186 menu->addAction(smallIcons);
188 QAction * normalIcons = new QAction(iconSizeGroup);
189 normalIcons->setText(qt_("Normal-sized icons"));
190 normalIcons->setCheckable(true);
191 QObject::connect(normalIcons, SIGNAL(triggered()),
192 parent, SLOT(normalSizedIcons()));
193 menu->addAction(normalIcons);
195 QAction * bigIcons = new QAction(iconSizeGroup);
196 bigIcons->setText(qt_("Big-sized icons"));
197 bigIcons->setCheckable(true);
198 QObject::connect(bigIcons, SIGNAL(triggered()),
199 parent, SLOT(bigSizedIcons()));
200 menu->addAction(bigIcons);
202 unsigned int cur = parent->iconSize().width();
203 if ( cur == parent->d.smallIconSize)
204 smallIcons->setChecked(true);
205 else if (cur == parent->d.normalIconSize)
206 normalIcons->setChecked(true);
207 else if (cur == parent->d.bigIconSize)
208 bigIcons->setChecked(true);
215 stack_widget_->setCurrentWidget(bg_widget_);
216 bg_widget_->setUpdatesEnabled(true);
219 TabWorkArea * tabWorkArea(int i)
221 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
224 TabWorkArea * currentTabWorkArea()
226 if (splitter_->count() == 1)
227 // The first TabWorkArea is always the first one, if any.
228 return tabWorkArea(0);
230 TabWorkArea * tab_widget = 0;
231 for (int i = 0; i != splitter_->count(); ++i) {
232 QWidget * w = splitter_->widget(i);
235 tab_widget = dynamic_cast<TabWorkArea *>(w);
244 GuiWorkArea * current_work_area_;
245 QSplitter * splitter_;
246 QStackedWidget * stack_widget_;
247 BackgroundWidget * bg_widget_;
249 GuiToolbars * toolbars_;
250 /// The main layout box.
252 * \warning Don't Delete! The layout box is actually owned by
253 * whichever toolbar contains it. All the GuiView class needs is a
254 * means of accessing it.
256 * FIXME: replace that with a proper model so that we are not limited
257 * to only one dialog.
259 GuiLayoutBox * layout_;
262 map<string, Inset *> open_insets_;
265 map<string, DialogPtr> dialogs_;
267 unsigned int smallIconSize;
268 unsigned int normalIconSize;
269 unsigned int bigIconSize;
271 QTimer statusbar_timer_;
272 /// are we quitting by the menu?
273 bool quitting_by_menu_;
274 /// auto-saving of buffers
275 Timeout autosave_timeout_;
276 /// flag against a race condition due to multiclicks, see bug #1119
281 GuiView::GuiView(int id)
282 : d(*new GuiViewPrivate), id_(id)
284 // GuiToolbars *must* be initialised before the menu bar.
285 d.toolbars_ = new GuiToolbars(*this);
287 // Fill up the menu bar.
288 guiApp->menus().fillMenuBar(this);
290 setCentralWidget(d.stack_widget_);
292 // Start autosave timer
293 if (lyxrc.autosave) {
294 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
295 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
296 d.autosave_timeout_.start();
298 connect(&d.statusbar_timer_, SIGNAL(timeout()),
299 this, SLOT(clearMessage()));
301 // Qt bug? signal lastWindowClosed does not work
302 setAttribute(Qt::WA_QuitOnClose, false);
303 setAttribute(Qt::WA_DeleteOnClose, true);
305 // assign an icon to main form. We do not do it under Qt/Mac,
306 // since the icon is provided in the application bundle.
307 setWindowIcon(QPixmap(":/images/lyx.png"));
311 setAcceptDrops(true);
313 statusBar()->setSizeGripEnabled(true);
315 // Forbid too small unresizable window because it can happen
316 // with some window manager under X11.
317 setMinimumSize(300, 200);
319 if (!lyxrc.allow_geometry_session)
320 // No session handling, default to a sane size.
321 setGeometry(50, 50, 690, 510);
323 // Now take care of session management.
325 QString const key = "view-" + QString::number(id_);
327 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
328 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
332 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
333 setGeometry(50, 50, 690, 510);
335 setIconSize(settings.value(key + "/icon_size").toSize());
345 void GuiView::close()
347 d.quitting_by_menu_ = true;
348 d.current_work_area_ = 0;
349 for (int i = 0; i != d.splitter_->count(); ++i) {
350 TabWorkArea * twa = d.tabWorkArea(i);
354 QMainWindow::close();
355 d.quitting_by_menu_ = false;
359 void GuiView::setFocus()
361 if (d.current_work_area_)
362 d.current_work_area_->setFocus();
368 QMenu * GuiView::createPopupMenu()
370 return d.toolBarPopup(this);
374 void GuiView::showEvent(QShowEvent * e)
376 LYXERR(Debug::GUI, "Passed Geometry "
377 << size().height() << "x" << size().width()
378 << "+" << pos().x() << "+" << pos().y());
380 if (d.splitter_->count() == 0)
381 // No work area, switch to the background widget.
384 QMainWindow::showEvent(e);
388 void GuiView::closeEvent(QCloseEvent * close_event)
390 // we may have been called through the close window button
391 // which bypasses the LFUN machinery.
392 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
393 if (!quitWriteAll()) {
394 close_event->ignore();
399 // Make sure that no LFUN use this close to be closed View.
400 theLyXFunc().setLyXView(0);
401 // Make sure the timer time out will not trigger a statusbar update.
402 d.statusbar_timer_.stop();
404 if (lyxrc.allow_geometry_session) {
406 QString const key = "view-" + QString::number(id_);
408 settings.setValue(key + "/pos", pos());
409 settings.setValue(key + "/size", size());
411 settings.setValue(key + "/geometry", saveGeometry());
413 settings.setValue(key + "/icon_size", iconSize());
414 d.toolbars_->saveToolbarInfo();
415 // Now take care of all other dialogs:
416 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
417 for (; it!= d.dialogs_.end(); ++it)
418 it->second->saveSession();
421 guiApp->unregisterView(id_);
422 if (guiApp->viewCount() > 0) {
423 // Just close the window and do nothing else if this is not the
425 close_event->accept();
431 // this is the place where we leave the frontend.
432 // it is the only point at which we start quitting.
433 close_event->accept();
434 // quit the event loop
439 void GuiView::dragEnterEvent(QDragEnterEvent * event)
441 if (event->mimeData()->hasUrls())
443 /// \todo Ask lyx-devel is this is enough:
444 /// if (event->mimeData()->hasFormat("text/plain"))
445 /// event->acceptProposedAction();
449 void GuiView::dropEvent(QDropEvent* event)
451 QList<QUrl> files = event->mimeData()->urls();
455 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
456 for (int i = 0; i != files.size(); ++i) {
457 string const file = os::internal_path(fromqstr(
458 files.at(i).toLocalFile()));
460 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
465 void GuiView::message(docstring const & str)
467 if (ForkedProcess::iAmAChild())
470 statusBar()->showMessage(toqstr(str));
471 d.statusbar_timer_.stop();
472 d.statusbar_timer_.start(3000);
476 void GuiView::smallSizedIcons()
478 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
482 void GuiView::normalSizedIcons()
484 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
488 void GuiView::bigSizedIcons()
490 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
494 void GuiView::clearMessage()
498 theLyXFunc().setLyXView(this);
499 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
500 d.statusbar_timer_.stop();
504 void GuiView::updateWindowTitle(GuiWorkArea * wa)
506 if (wa != d.current_work_area_)
508 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
509 setWindowIconText(wa->windowIconText());
513 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
516 disconnectBufferView();
517 connectBufferView(wa->bufferView());
518 connectBuffer(wa->bufferView().buffer());
519 d.current_work_area_ = wa;
520 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
521 this, SLOT(updateWindowTitle(GuiWorkArea *)));
522 updateWindowTitle(wa);
525 // Buffer-dependent dialogs should be updated or
526 // hidden. This should go here because some dialogs (eg ToC)
527 // require bv_->text.
528 updateBufferDependent(true);
535 void GuiView::updateStatusBar()
537 // let the user see the explicit message
538 if (d.statusbar_timer_.isActive())
541 theLyXFunc().setLyXView(this);
542 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
546 bool GuiView::hasFocus() const
548 return qApp->activeWindow() == this;
552 bool GuiView::event(QEvent * e)
556 // Useful debug code:
557 //case QEvent::ActivationChange:
558 //case QEvent::WindowDeactivate:
559 //case QEvent::Paint:
560 //case QEvent::Enter:
561 //case QEvent::Leave:
562 //case QEvent::HoverEnter:
563 //case QEvent::HoverLeave:
564 //case QEvent::HoverMove:
565 //case QEvent::StatusTip:
566 //case QEvent::DragEnter:
567 //case QEvent::DragLeave:
571 case QEvent::WindowActivate: {
572 guiApp->setCurrentView(*this);
573 if (d.current_work_area_) {
574 BufferView & bv = d.current_work_area_->bufferView();
575 connectBufferView(bv);
576 connectBuffer(bv.buffer());
577 // The document structure, name and dialogs might have
578 // changed in another view.
579 updateBufferDependent(true);
584 setWindowTitle(qt_("LyX"));
585 setWindowIconText(qt_("LyX"));
588 return QMainWindow::event(e);
591 case QEvent::ShortcutOverride: {
592 if (d.current_work_area_)
593 // Nothing special to do.
594 return QMainWindow::event(e);
596 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
598 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
600 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
601 || ke->key() == Qt::Key_Backtab)
602 return QMainWindow::event(e);
604 // Allow processing of shortcuts that are allowed even when no Buffer
606 theLyXFunc().setLyXView(this);
608 setKeySymbol(&sym, ke);
609 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
615 return QMainWindow::event(e);
620 bool GuiView::focusNextPrevChild(bool /*next*/)
627 void GuiView::setBusy(bool busy)
629 if (d.current_work_area_) {
630 d.current_work_area_->setUpdatesEnabled(!busy);
632 d.current_work_area_->stopBlinkingCursor();
634 d.current_work_area_->startBlinkingCursor();
638 QApplication::setOverrideCursor(Qt::WaitCursor);
640 QApplication::restoreOverrideCursor();
644 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
646 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
648 if (tbinfo.flags & ToolbarInfo::TOP) {
650 addToolBarBreak(Qt::TopToolBarArea);
651 addToolBar(Qt::TopToolBarArea, toolBar);
654 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
655 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
656 #if (QT_VERSION >= 0x040202)
658 addToolBarBreak(Qt::BottomToolBarArea);
660 addToolBar(Qt::BottomToolBarArea, toolBar);
663 if (tbinfo.flags & ToolbarInfo::LEFT) {
664 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
665 #if (QT_VERSION >= 0x040202)
667 addToolBarBreak(Qt::LeftToolBarArea);
669 addToolBar(Qt::LeftToolBarArea, toolBar);
672 if (tbinfo.flags & ToolbarInfo::RIGHT) {
673 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
674 #if (QT_VERSION >= 0x040202)
676 addToolBarBreak(Qt::RightToolBarArea);
678 addToolBar(Qt::RightToolBarArea, toolBar);
681 // The following does not work so I cannot restore to exact toolbar location
683 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
684 toolBar->move(tbinfo.posx, tbinfo.posy);
691 GuiWorkArea * GuiView::workArea(Buffer & buffer)
693 for (int i = 0; i != d.splitter_->count(); ++i) {
694 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
702 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
705 // Automatically create a TabWorkArea if there are none yet.
706 if (!d.splitter_->count())
709 TabWorkArea * tab_widget = d.currentTabWorkArea();
710 return tab_widget->addWorkArea(buffer, *this);
714 void GuiView::addTabWorkArea()
716 TabWorkArea * twa = new TabWorkArea;
717 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
718 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
719 d.splitter_->addWidget(twa);
720 d.stack_widget_->setCurrentWidget(d.splitter_);
724 GuiWorkArea const * GuiView::currentWorkArea() const
726 return d.current_work_area_;
730 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
734 // Changing work area can result from opening a file so
735 // update the toc in any case.
738 d.current_work_area_ = wa;
739 for (int i = 0; i != d.splitter_->count(); ++i) {
740 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
746 void GuiView::removeWorkArea(GuiWorkArea * wa)
749 if (wa == d.current_work_area_) {
751 disconnectBufferView();
752 hideBufferDependent();
753 d.current_work_area_ = 0;
756 for (int i = 0; i != d.splitter_->count(); ++i) {
757 TabWorkArea * twa = d.tabWorkArea(i);
758 if (!twa->removeWorkArea(wa))
759 // Not found in this tab group.
762 // We found and removed the GuiWorkArea.
764 // No more WorkAreas in this tab group, so delete it.
769 if (d.current_work_area_)
770 // This means that we are not closing the current GuiWorkArea;
773 // Switch to the next GuiWorkArea in the found TabWorkArea.
774 d.current_work_area_ = twa->currentWorkArea();
778 if (d.splitter_->count() == 0)
779 // No more work area, switch to the background widget.
784 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
790 void GuiView::updateLayoutList()
793 d.layout_->updateContents(false);
797 void GuiView::updateToolbars()
799 if (d.current_work_area_) {
801 d.current_work_area_->bufferView().cursor().inMathed();
803 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
805 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
806 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
807 bool const mathmacrotemplate =
808 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
810 d.toolbars_->update(math, table, review, mathmacrotemplate);
812 d.toolbars_->update(false, false, false, false);
814 // update read-only status of open dialogs.
819 Buffer * GuiView::buffer()
821 if (d.current_work_area_)
822 return &d.current_work_area_->bufferView().buffer();
827 Buffer const * GuiView::buffer() const
829 if (d.current_work_area_)
830 return &d.current_work_area_->bufferView().buffer();
835 void GuiView::setBuffer(Buffer * newBuffer)
837 BOOST_ASSERT(newBuffer);
840 GuiWorkArea * wa = workArea(*newBuffer);
842 updateLabels(*newBuffer->masterBuffer());
843 wa = addWorkArea(*newBuffer);
845 //Disconnect the old buffer...there's no new one.
848 connectBuffer(*newBuffer);
849 connectBufferView(wa->bufferView());
850 setCurrentWorkArea(wa);
856 void GuiView::connectBuffer(Buffer & buf)
858 buf.setGuiDelegate(this);
862 void GuiView::disconnectBuffer()
864 if (d.current_work_area_)
865 d.current_work_area_->bufferView().setGuiDelegate(0);
869 void GuiView::connectBufferView(BufferView & bv)
871 bv.setGuiDelegate(this);
875 void GuiView::disconnectBufferView()
877 if (d.current_work_area_)
878 d.current_work_area_->bufferView().setGuiDelegate(0);
882 void GuiView::errors(string const & error_type)
884 ErrorList & el = buffer()->errorList(error_type);
886 showDialog("errorlist", error_type);
890 void GuiView::updateDialog(string const & name, string const & data)
892 if (!isDialogVisible(name))
895 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
896 if (it == d.dialogs_.end())
899 Dialog * const dialog = it->second.get();
900 if (dialog->isVisibleView())
901 dialog->updateData(data);
905 BufferView * GuiView::view()
907 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
911 void GuiView::updateToc()
913 updateDialog("toc", "");
917 void GuiView::updateEmbeddedFiles()
919 updateDialog("embedding", "");
923 void GuiView::autoSave()
925 LYXERR(Debug::INFO, "Running autoSave()");
928 view()->buffer().autoSave();
932 void GuiView::resetAutosaveTimers()
935 d.autosave_timeout_.restart();
939 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
943 Buffer * buf = buffer();
945 /* In LyX/Mac, when a dialog is open, the menus of the
946 application can still be accessed without giving focus to
947 the main window. In this case, we want to disable the menu
948 entries that are buffer-related.
950 Note that this code is not perfect, as bug 1941 attests:
951 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
953 if (cmd.origin == FuncRequest::MENU && !hasFocus())
957 case LFUN_BUFFER_WRITE:
958 enable = buf && (buf->isUnnamed() || !buf->isClean());
961 case LFUN_BUFFER_WRITE_AS:
965 case LFUN_TOOLBAR_TOGGLE:
966 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
969 case LFUN_DIALOG_TOGGLE:
970 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
971 // fall through to set "enable"
972 case LFUN_DIALOG_SHOW: {
973 string const name = cmd.getArg(0);
975 enable = name == "aboutlyx"
976 || name == "file" //FIXME: should be removed.
978 || name == "texinfo";
979 else if (name == "print")
980 enable = buf->isExportable("dvi")
981 && lyxrc.print_command != "none";
982 else if (name == "character") {
986 InsetCode ic = view()->cursor().inset().lyxCode();
987 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
990 else if (name == "symbols") {
991 if (!view() || view()->cursor().inMathed())
994 InsetCode ic = view()->cursor().inset().lyxCode();
995 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
998 else if (name == "latexlog")
999 enable = FileName(buf->logName()).isReadableFile();
1000 else if (name == "spellchecker")
1001 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1002 enable = !buf->isReadonly();
1006 else if (name == "vclog")
1007 enable = buf->lyxvc().inUse();
1011 case LFUN_DIALOG_UPDATE: {
1012 string const name = cmd.getArg(0);
1014 enable = name == "prefs";
1018 case LFUN_INSET_APPLY: {
1023 string const name = cmd.getArg(0);
1024 Inset * inset = getOpenInset(name);
1026 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1028 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1029 // Every inset is supposed to handle this
1030 BOOST_ASSERT(false);
1034 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1035 flag |= getStatus(fr);
1037 enable = flag.enabled();
1049 flag.enabled(false);
1055 static FileName selectTemplateFile()
1057 FileDialog dlg(_("Select template file"));
1058 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1059 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1061 FileDialog::Result result =
1062 dlg.open(from_utf8(lyxrc.template_path),
1063 FileFilterList(_("LyX Documents (*.lyx)")),
1066 if (result.first == FileDialog::Later)
1068 if (result.second.empty())
1070 return FileName(to_utf8(result.second));
1074 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1078 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1081 message(_("Document not loaded."));
1086 setBuffer(newBuffer);
1088 // scroll to the position when the file was last closed
1089 if (lyxrc.use_lastfilepos) {
1090 LastFilePosSection::FilePos filepos =
1091 LyX::ref().session().lastFilePos().load(filename);
1092 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1096 LyX::ref().session().lastFiles().add(filename);
1103 void GuiView::openDocument(string const & fname)
1105 string initpath = lyxrc.document_path;
1108 string const trypath = buffer()->filePath();
1109 // If directory is writeable, use this as default.
1110 if (FileName(trypath).isDirWritable())
1116 if (fname.empty()) {
1117 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1118 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1119 dlg.setButton2(_("Examples|#E#e"),
1120 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1122 FileDialog::Result result =
1123 dlg.open(from_utf8(initpath),
1124 FileFilterList(_("LyX Documents (*.lyx)")),
1127 if (result.first == FileDialog::Later)
1130 filename = to_utf8(result.second);
1132 // check selected filename
1133 if (filename.empty()) {
1134 message(_("Canceled."));
1140 // get absolute path of file and add ".lyx" to the filename if
1142 FileName const fullname =
1143 fileSearch(string(), filename, "lyx", support::may_not_exist);
1144 if (!fullname.empty())
1145 filename = fullname.absFilename();
1147 // if the file doesn't exist, let the user create one
1148 if (!fullname.exists()) {
1149 // the user specifically chose this name. Believe him.
1150 Buffer * const b = newFile(filename, string(), true);
1156 docstring const disp_fn = makeDisplayPath(filename);
1157 message(bformat(_("Opening document %1$s..."), disp_fn));
1160 Buffer * buf = loadDocument(fullname);
1164 buf->errors("Parse");
1165 str2 = bformat(_("Document %1$s opened."), disp_fn);
1167 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1172 // FIXME: clean that
1173 static bool import(GuiView * lv, FileName const & filename,
1174 string const & format, ErrorList & errorList)
1176 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1178 string loader_format;
1179 vector<string> loaders = theConverters().loaders();
1180 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1181 for (vector<string>::const_iterator it = loaders.begin();
1182 it != loaders.end(); ++it) {
1183 if (!theConverters().isReachable(format, *it))
1186 string const tofile =
1187 changeExtension(filename.absFilename(),
1188 formats.extension(*it));
1189 if (!theConverters().convert(0, filename, FileName(tofile),
1190 filename, format, *it, errorList))
1192 loader_format = *it;
1195 if (loader_format.empty()) {
1196 frontend::Alert::error(_("Couldn't import file"),
1197 bformat(_("No information for importing the format %1$s."),
1198 formats.prettyName(format)));
1202 loader_format = format;
1204 if (loader_format == "lyx") {
1205 Buffer * buf = lv->loadDocument(lyxfile);
1210 buf->errors("Parse");
1212 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1216 bool as_paragraphs = loader_format == "textparagraph";
1217 string filename2 = (loader_format == format) ? filename.absFilename()
1218 : changeExtension(filename.absFilename(),
1219 formats.extension(loader_format));
1220 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1221 theLyXFunc().setLyXView(lv);
1222 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1229 void GuiView::importDocument(string const & argument)
1232 string filename = split(argument, format, ' ');
1234 LYXERR(Debug::INFO, format << " file: " << filename);
1236 // need user interaction
1237 if (filename.empty()) {
1238 string initpath = lyxrc.document_path;
1240 Buffer const * buf = buffer();
1242 string const trypath = buf->filePath();
1243 // If directory is writeable, use this as default.
1244 if (FileName(trypath).isDirWritable())
1248 docstring const text = bformat(_("Select %1$s file to import"),
1249 formats.prettyName(format));
1251 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1252 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1253 dlg.setButton2(_("Examples|#E#e"),
1254 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1256 docstring filter = formats.prettyName(format);
1259 filter += from_utf8(formats.extension(format));
1262 FileDialog::Result result =
1263 dlg.open(from_utf8(initpath),
1264 FileFilterList(filter),
1267 if (result.first == FileDialog::Later)
1270 filename = to_utf8(result.second);
1272 // check selected filename
1273 if (filename.empty())
1274 message(_("Canceled."));
1277 if (filename.empty())
1280 // get absolute path of file
1281 FileName const fullname(makeAbsPath(filename));
1283 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1285 // Check if the document already is open
1286 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1289 if (!closeBuffer()) {
1290 message(_("Canceled."));
1295 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1297 // if the file exists already, and we didn't do
1298 // -i lyx thefile.lyx, warn
1299 if (lyxfile.exists() && fullname != lyxfile) {
1301 docstring text = bformat(_("The document %1$s already exists.\n\n"
1302 "Do you want to overwrite that document?"), displaypath);
1303 int const ret = Alert::prompt(_("Overwrite document?"),
1304 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1307 message(_("Canceled."));
1312 message(bformat(_("Importing %1$s..."), displaypath));
1313 ErrorList errorList;
1314 if (import(this, fullname, format, errorList))
1315 message(_("imported."));
1317 message(_("file not imported!"));
1319 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1323 void GuiView::newDocument(string const & filename, bool from_template)
1325 FileName initpath(lyxrc.document_path);
1326 Buffer * buf = buffer();
1328 FileName const trypath(buf->filePath());
1329 // If directory is writeable, use this as default.
1330 if (trypath.isDirWritable())
1334 string templatefile = from_template ?
1335 selectTemplateFile().absFilename() : string();
1337 if (filename.empty())
1338 b = newUnnamedFile(templatefile, initpath);
1340 b = newFile(filename, templatefile, true);
1344 // Ensure the cursor is correctly positionned on screen.
1345 view()->showCursor();
1349 void GuiView::insertLyXFile(docstring const & fname)
1351 BufferView * bv = view();
1356 FileName filename(to_utf8(fname));
1358 if (!filename.empty()) {
1359 bv->insertLyXFile(filename);
1363 // Launch a file browser
1365 string initpath = lyxrc.document_path;
1366 string const trypath = bv->buffer().filePath();
1367 // If directory is writeable, use this as default.
1368 if (FileName(trypath).isDirWritable())
1372 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1373 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1374 dlg.setButton2(_("Examples|#E#e"),
1375 from_utf8(addPath(package().system_support().absFilename(),
1378 FileDialog::Result result =
1379 dlg.open(from_utf8(initpath),
1380 FileFilterList(_("LyX Documents (*.lyx)")),
1383 if (result.first == FileDialog::Later)
1387 filename.set(to_utf8(result.second));
1389 // check selected filename
1390 if (filename.empty()) {
1391 // emit message signal.
1392 message(_("Canceled."));
1396 bv->insertLyXFile(filename);
1400 void GuiView::insertPlaintextFile(docstring const & fname,
1403 BufferView * bv = view();
1408 FileName filename(to_utf8(fname));
1410 if (!filename.empty()) {
1411 bv->insertPlaintextFile(filename, asParagraph);
1415 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1416 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1418 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1419 FileFilterList(), docstring());
1421 if (result.first == FileDialog::Later)
1425 filename.set(to_utf8(result.second));
1427 // check selected filename
1428 if (filename.empty()) {
1429 // emit message signal.
1430 message(_("Canceled."));
1434 bv->insertPlaintextFile(filename, asParagraph);
1438 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1440 FileName fname = b.fileName();
1441 FileName const oldname = fname;
1443 if (!newname.empty()) {
1445 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1447 // Switch to this Buffer.
1450 /// No argument? Ask user through dialog.
1452 FileDialog dlg(_("Choose a filename to save document as"),
1453 LFUN_BUFFER_WRITE_AS);
1454 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1455 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1457 if (!isLyXFilename(fname.absFilename()))
1458 fname.changeExtension(".lyx");
1460 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1462 FileDialog::Result result =
1463 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1465 from_utf8(fname.onlyFileName()));
1467 if (result.first == FileDialog::Later)
1470 fname.set(to_utf8(result.second));
1475 if (!isLyXFilename(fname.absFilename()))
1476 fname.changeExtension(".lyx");
1479 if (FileName(fname).exists()) {
1480 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1481 docstring text = bformat(_("The document %1$s already "
1482 "exists.\n\nDo you want to "
1483 "overwrite that document?"),
1485 int const ret = Alert::prompt(_("Overwrite document?"),
1486 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1489 case 1: return renameBuffer(b, docstring());
1490 case 2: return false;
1494 // Ok, change the name of the buffer
1495 b.setFileName(fname.absFilename());
1497 bool unnamed = b.isUnnamed();
1498 b.setUnnamed(false);
1499 b.saveCheckSum(fname);
1501 if (!saveBuffer(b)) {
1502 b.setFileName(oldname.absFilename());
1503 b.setUnnamed(unnamed);
1504 b.saveCheckSum(oldname);
1512 bool GuiView::saveBuffer(Buffer & b)
1515 return renameBuffer(b, docstring());
1518 LyX::ref().session().lastFiles().add(b.fileName());
1522 // Switch to this Buffer.
1525 // FIXME: we don't tell the user *WHY* the save failed !!
1526 docstring const file = makeDisplayPath(b.absFileName(), 30);
1527 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1528 "Do you want to rename the document and "
1529 "try again?"), file);
1530 int const ret = Alert::prompt(_("Rename and save?"),
1531 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1534 if (!renameBuffer(b, docstring()))
1543 return saveBuffer(b);
1547 bool GuiView::closeBuffer()
1549 Buffer * buf = buffer();
1550 return buf && closeBuffer(*buf);
1554 bool GuiView::closeBuffer(Buffer & buf)
1556 if (buf.isClean() || buf.paragraphs().empty()) {
1557 theBufferList().release(&buf);
1560 // Switch to this Buffer.
1565 if (buf.isUnnamed())
1566 file = from_utf8(buf.fileName().onlyFileName());
1568 file = buf.fileName().displayName(30);
1570 docstring const text = bformat(_("The document %1$s has unsaved changes."
1571 "\n\nDo you want to save the document or discard the changes?"), file);
1572 int const ret = Alert::prompt(_("Save changed document?"),
1573 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1577 if (!saveBuffer(buf))
1581 // if we crash after this we could
1582 // have no autosave file but I guess
1583 // this is really improbable (Jug)
1584 removeAutosaveFile(buf.absFileName());
1590 // save file names to .lyx/session
1591 // if master/slave are both open, do not save slave since it
1592 // will be automatically loaded when the master is loaded
1593 if (buf.masterBuffer() == &buf)
1594 LyX::ref().session().lastOpened().add(buf.fileName());
1596 theBufferList().release(&buf);
1601 bool GuiView::quitWriteAll()
1603 while (!theBufferList().empty()) {
1604 Buffer * b = theBufferList().first();
1605 if (!closeBuffer(*b))
1612 bool GuiView::dispatch(FuncRequest const & cmd)
1614 BufferView * bv = view();
1615 // By default we won't need any update.
1617 bv->cursor().updateFlags(Update::None);
1619 switch(cmd.action) {
1620 case LFUN_FILE_OPEN:
1621 openDocument(to_utf8(cmd.argument()));
1624 case LFUN_BUFFER_IMPORT:
1625 importDocument(to_utf8(cmd.argument()));
1628 case LFUN_BUFFER_SWITCH:
1629 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1632 case LFUN_BUFFER_NEXT:
1633 setBuffer(theBufferList().next(buffer()));
1636 case LFUN_BUFFER_PREVIOUS:
1637 setBuffer(theBufferList().previous(buffer()));
1640 case LFUN_COMMAND_EXECUTE: {
1641 bool const show_it = cmd.argument() != "off";
1642 d.toolbars_->showCommandBuffer(show_it);
1645 case LFUN_DROP_LAYOUTS_CHOICE:
1647 d.layout_->showPopup();
1650 case LFUN_MENU_OPEN:
1651 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1652 menu->exec(QCursor::pos());
1655 case LFUN_FILE_INSERT:
1656 insertLyXFile(cmd.argument());
1658 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1659 insertPlaintextFile(cmd.argument(), true);
1662 case LFUN_FILE_INSERT_PLAINTEXT:
1663 insertPlaintextFile(cmd.argument(), false);
1666 case LFUN_BUFFER_WRITE:
1668 saveBuffer(bv->buffer());
1671 case LFUN_BUFFER_WRITE_AS:
1673 renameBuffer(bv->buffer(), cmd.argument());
1676 case LFUN_BUFFER_WRITE_ALL: {
1677 Buffer * first = theBufferList().first();
1680 message(_("Saving all documents..."));
1681 // We cannot use a for loop as the buffer list cycles.
1687 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1688 b = theBufferList().next(b);
1689 } while (b != first);
1690 message(_("All documents saved."));
1694 case LFUN_TOOLBAR_TOGGLE: {
1695 string const name = cmd.getArg(0);
1696 bool const allowauto = cmd.getArg(1) == "allowauto";
1697 // it is possible to get current toolbar status like this,...
1698 // but I decide to obey the order of ToolbarBackend::flags
1699 // and disregard real toolbar status.
1700 // toolbars_->saveToolbarInfo();
1702 // toggle state on/off/auto
1703 d.toolbars_->toggleToolbarState(name, allowauto);
1707 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1709 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1713 if (tbi->flags & ToolbarInfo::ON)
1715 else if (tbi->flags & ToolbarInfo::OFF)
1717 else if (tbi->flags & ToolbarInfo::AUTO)
1720 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1721 _(tbi->gui_name), state));
1725 case LFUN_DIALOG_UPDATE: {
1726 string const name = to_utf8(cmd.argument());
1727 // Can only update a dialog connected to an existing inset
1728 Inset * inset = getOpenInset(name);
1730 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1731 inset->dispatch(view()->cursor(), fr);
1732 } else if (name == "paragraph") {
1733 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1734 } else if (name == "prefs") {
1735 updateDialog(name, string());
1740 case LFUN_DIALOG_TOGGLE: {
1741 if (isDialogVisible(cmd.getArg(0)))
1742 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1744 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1748 case LFUN_DIALOG_DISCONNECT_INSET:
1749 disconnectDialog(to_utf8(cmd.argument()));
1752 case LFUN_DIALOG_HIDE: {
1755 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1759 case LFUN_DIALOG_SHOW: {
1760 string const name = cmd.getArg(0);
1761 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1763 if (name == "character") {
1764 data = freefont2string();
1766 showDialog("character", data);
1767 } else if (name == "latexlog") {
1768 Buffer::LogType type;
1769 string const logfile = buffer()->logName(&type);
1771 case Buffer::latexlog:
1774 case Buffer::buildlog:
1778 data += Lexer::quoteString(logfile);
1779 showDialog("log", data);
1780 } else if (name == "vclog") {
1781 string const data = "vc " +
1782 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1783 showDialog("log", data);
1784 } else if (name == "symbols") {
1785 data = bv->cursor().getEncoding()->name();
1787 showDialog("symbols", data);
1789 showDialog(name, data);
1793 case LFUN_INSET_APPLY: {
1794 string const name = cmd.getArg(0);
1795 Inset * inset = getOpenInset(name);
1797 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1798 inset->dispatch(view()->cursor(), fr);
1800 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1806 case LFUN_UI_TOGGLE:
1818 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1820 string const arg = cmd.getArg(0);
1821 if (arg == "scrollbar") {
1822 // hide() is of no help
1823 if (d.current_work_area_->verticalScrollBarPolicy() ==
1824 Qt::ScrollBarAlwaysOff)
1826 d.current_work_area_->setVerticalScrollBarPolicy(
1827 Qt::ScrollBarAsNeeded);
1829 d.current_work_area_->setVerticalScrollBarPolicy(
1830 Qt::ScrollBarAlwaysOff);
1833 if (arg == "statusbar") {
1834 statusBar()->setVisible(!statusBar()->isVisible());
1837 if (arg == "menubar") {
1838 menuBar()->setVisible(!menuBar()->isVisible());
1841 #if QT_VERSION >= 0x040300
1842 if (arg == "frame") {
1844 getContentsMargins(&l, &t, &r, &b);
1845 //are the frames in default state?
1847 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1848 setContentsMargins(-2, -2, -2, -2);
1850 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1851 setContentsMargins(0, 0, 0, 0);
1856 if (arg != "fullscreen") {
1857 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1861 if (isFullScreen()) {
1863 #if QT_VERSION >= 0x040300
1864 setContentsMargins(0, 0, 0, 0);
1866 for (int i = 0; i != d.splitter_->count(); ++i)
1867 d.tabWorkArea(i)->setFullScreen(false);
1869 statusBar()->show();
1871 statusBar()->hide();
1873 for (int i = 0; i != d.splitter_->count(); ++i)
1874 d.tabWorkArea(i)->setFullScreen(true);
1875 #if QT_VERSION >= 0x040300
1876 setContentsMargins(-2, -2, -2, -2);
1883 Buffer const * GuiView::updateInset(Inset const * inset)
1885 if (!d.current_work_area_)
1889 d.current_work_area_->scheduleRedraw();
1891 return &d.current_work_area_->bufferView().buffer();
1895 void GuiView::restartCursor()
1897 /* When we move around, or type, it's nice to be able to see
1898 * the cursor immediately after the keypress.
1900 if (d.current_work_area_)
1901 d.current_work_area_->startBlinkingCursor();
1903 // Take this occasion to update the toobars and layout list.
1910 // This list should be kept in sync with the list of insets in
1911 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1912 // dialog should have the same name as the inset.
1914 char const * const dialognames[] = {
1915 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1916 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1917 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1918 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1919 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1921 #ifdef HAVE_LIBAIKSAURUS
1925 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1927 char const * const * const end_dialognames =
1928 dialognames + (sizeof(dialognames) / sizeof(char *));
1932 cmpCStr(char const * name) : name_(name) {}
1933 bool operator()(char const * other) {
1934 return strcmp(other, name_) == 0;
1941 bool isValidName(string const & name)
1943 return find_if(dialognames, end_dialognames,
1944 cmpCStr(name.c_str())) != end_dialognames;
1950 void GuiView::resetDialogs()
1952 // Make sure that no LFUN uses any LyXView.
1953 theLyXFunc().setLyXView(0);
1954 // FIXME: the "math panels" toolbar takes an awful lot of time to
1955 // initialise so we don't do that for the time being.
1956 //d.toolbars_->init();
1957 guiApp->menus().fillMenuBar(this);
1959 d.layout_->updateContents(true);
1960 // Now update controls with current buffer.
1961 theLyXFunc().setLyXView(this);
1966 Dialog * GuiView::find_or_build(string const & name)
1968 if (!isValidName(name))
1971 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1973 if (it != d.dialogs_.end())
1974 return it->second.get();
1976 Dialog * dialog = build(name);
1977 d.dialogs_[name].reset(dialog);
1978 if (lyxrc.allow_geometry_session)
1979 dialog->restoreSession();
1984 void GuiView::showDialog(string const & name, string const & data,
1991 Dialog * dialog = find_or_build(name);
1993 dialog->showData(data);
1995 d.open_insets_[name] = inset;
2001 bool GuiView::isDialogVisible(string const & name) const
2003 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2004 if (it == d.dialogs_.end())
2006 return it->second.get()->isVisibleView();
2010 void GuiView::hideDialog(string const & name, Inset * inset)
2012 // Don't send the signal if we are quitting, because on MSVC it is
2013 // destructed before the cut stack in CutAndPaste.cpp, and this method
2014 // is called from some inset destructor if the cut stack is not empty
2019 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2020 if (it == d.dialogs_.end())
2023 if (inset && inset != getOpenInset(name))
2026 Dialog * const dialog = it->second.get();
2027 if (dialog->isVisibleView())
2029 d.open_insets_[name] = 0;
2033 void GuiView::disconnectDialog(string const & name)
2035 if (!isValidName(name))
2038 if (d.open_insets_.find(name) != d.open_insets_.end())
2039 d.open_insets_[name] = 0;
2043 Inset * GuiView::getOpenInset(string const & name) const
2045 if (!isValidName(name))
2048 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2049 return it == d.open_insets_.end() ? 0 : it->second;
2053 void GuiView::hideAll() const
2055 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2056 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2058 for(; it != end; ++it)
2059 it->second->hideView();
2063 void GuiView::hideBufferDependent() const
2065 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2066 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2068 for(; it != end; ++it) {
2069 Dialog * dialog = it->second.get();
2070 if (dialog->isBufferDependent())
2076 void GuiView::updateBufferDependent(bool switched) const
2078 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2079 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2081 for(; it != end; ++it) {
2082 Dialog * dialog = it->second.get();
2083 if (!dialog->isVisibleView())
2085 if (switched && dialog->isBufferDependent()) {
2086 if (dialog->initialiseParams(""))
2087 dialog->updateView();
2091 // A bit clunky, but the dialog will request
2092 // that the kernel provides it with the necessary
2094 dialog->updateDialog();
2100 void GuiView::checkStatus()
2102 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2103 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2105 for(; it != end; ++it) {
2106 Dialog * const dialog = it->second.get();
2107 if (dialog && dialog->isVisibleView())
2108 dialog->checkStatus();
2114 // will be replaced by a proper factory...
2115 Dialog * createGuiAbout(GuiView & lv);
2116 Dialog * createGuiBibitem(GuiView & lv);
2117 Dialog * createGuiBibtex(GuiView & lv);
2118 Dialog * createGuiBox(GuiView & lv);
2119 Dialog * createGuiBranch(GuiView & lv);
2120 Dialog * createGuiChanges(GuiView & lv);
2121 Dialog * createGuiCharacter(GuiView & lv);
2122 Dialog * createGuiCitation(GuiView & lv);
2123 Dialog * createGuiDelimiter(GuiView & lv);
2124 Dialog * createGuiDocument(GuiView & lv);
2125 Dialog * createGuiErrorList(GuiView & lv);
2126 Dialog * createGuiERT(GuiView & lv);
2127 Dialog * createGuiExternal(GuiView & lv);
2128 Dialog * createGuiFloat(GuiView & lv);
2129 Dialog * createGuiGraphics(GuiView & lv);
2130 Dialog * createGuiInclude(GuiView & lv);
2131 Dialog * createGuiIndex(GuiView & lv);
2132 Dialog * createGuiLabel(GuiView & lv);
2133 Dialog * createGuiListings(GuiView & lv);
2134 Dialog * createGuiLog(GuiView & lv);
2135 Dialog * createGuiMathMatrix(GuiView & lv);
2136 Dialog * createGuiNomenclature(GuiView & lv);
2137 Dialog * createGuiNote(GuiView & lv);
2138 Dialog * createGuiParagraph(GuiView & lv);
2139 Dialog * createGuiPreferences(GuiView & lv);
2140 Dialog * createGuiPrint(GuiView & lv);
2141 Dialog * createGuiRef(GuiView & lv);
2142 Dialog * createGuiSearch(GuiView & lv);
2143 Dialog * createGuiSendTo(GuiView & lv);
2144 Dialog * createGuiShowFile(GuiView & lv);
2145 Dialog * createGuiSpellchecker(GuiView & lv);
2146 Dialog * createGuiSymbols(GuiView & lv);
2147 Dialog * createGuiTabularCreate(GuiView & lv);
2148 Dialog * createGuiTabular(GuiView & lv);
2149 Dialog * createGuiTexInfo(GuiView & lv);
2150 Dialog * createGuiToc(GuiView & lv);
2151 Dialog * createGuiThesaurus(GuiView & lv);
2152 Dialog * createGuiHyperlink(GuiView & lv);
2153 Dialog * createGuiVSpace(GuiView & lv);
2154 Dialog * createGuiViewSource(GuiView & lv);
2155 Dialog * createGuiWrap(GuiView & lv);
2158 Dialog * GuiView::build(string const & name)
2160 BOOST_ASSERT(isValidName(name));
2162 if (name == "aboutlyx")
2163 return createGuiAbout(*this);
2164 if (name == "bibitem")
2165 return createGuiBibitem(*this);
2166 if (name == "bibtex")
2167 return createGuiBibtex(*this);
2169 return createGuiBox(*this);
2170 if (name == "branch")
2171 return createGuiBranch(*this);
2172 if (name == "changes")
2173 return createGuiChanges(*this);
2174 if (name == "character")
2175 return createGuiCharacter(*this);
2176 if (name == "citation")
2177 return createGuiCitation(*this);
2178 if (name == "document")
2179 return createGuiDocument(*this);
2180 if (name == "errorlist")
2181 return createGuiErrorList(*this);
2183 return createGuiERT(*this);
2184 if (name == "external")
2185 return createGuiExternal(*this);
2187 return createGuiShowFile(*this);
2188 if (name == "findreplace")
2189 return createGuiSearch(*this);
2190 if (name == "float")
2191 return createGuiFloat(*this);
2192 if (name == "graphics")
2193 return createGuiGraphics(*this);
2194 if (name == "include")
2195 return createGuiInclude(*this);
2196 if (name == "index")
2197 return createGuiIndex(*this);
2198 if (name == "nomenclature")
2199 return createGuiNomenclature(*this);
2200 if (name == "label")
2201 return createGuiLabel(*this);
2203 return createGuiLog(*this);
2204 if (name == "view-source")
2205 return createGuiViewSource(*this);
2206 if (name == "mathdelimiter")
2207 return createGuiDelimiter(*this);
2208 if (name == "mathmatrix")
2209 return createGuiMathMatrix(*this);
2211 return createGuiNote(*this);
2212 if (name == "paragraph")
2213 return createGuiParagraph(*this);
2214 if (name == "prefs")
2215 return createGuiPreferences(*this);
2216 if (name == "print")
2217 return createGuiPrint(*this);
2219 return createGuiRef(*this);
2220 if (name == "sendto")
2221 return createGuiSendTo(*this);
2222 if (name == "spellchecker")
2223 return createGuiSpellchecker(*this);
2224 if (name == "symbols")
2225 return createGuiSymbols(*this);
2226 if (name == "tabular")
2227 return createGuiTabular(*this);
2228 if (name == "tabularcreate")
2229 return createGuiTabularCreate(*this);
2230 if (name == "texinfo")
2231 return createGuiTexInfo(*this);
2232 #ifdef HAVE_LIBAIKSAURUS
2233 if (name == "thesaurus")
2234 return createGuiThesaurus(*this);
2237 return createGuiToc(*this);
2239 return createGuiHyperlink(*this);
2240 if (name == "vspace")
2241 return createGuiVSpace(*this);
2243 return createGuiWrap(*this);
2244 if (name == "listings")
2245 return createGuiListings(*this);
2251 } // namespace frontend
2254 #include "GuiView_moc.cpp"