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"));
587 return QMainWindow::event(e);
590 case QEvent::ShortcutOverride: {
591 if (d.current_work_area_)
592 // Nothing special to do.
593 return QMainWindow::event(e);
595 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
597 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
599 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
600 || ke->key() == Qt::Key_Backtab)
601 return QMainWindow::event(e);
603 // Allow processing of shortcuts that are allowed even when no Buffer
605 theLyXFunc().setLyXView(this);
607 setKeySymbol(&sym, ke);
608 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
614 return QMainWindow::event(e);
619 bool GuiView::focusNextPrevChild(bool /*next*/)
626 void GuiView::setBusy(bool busy)
628 if (d.current_work_area_) {
629 d.current_work_area_->setUpdatesEnabled(!busy);
631 d.current_work_area_->stopBlinkingCursor();
633 d.current_work_area_->startBlinkingCursor();
637 QApplication::setOverrideCursor(Qt::WaitCursor);
639 QApplication::restoreOverrideCursor();
643 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
645 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
647 if (tbinfo.flags & ToolbarInfo::TOP) {
649 addToolBarBreak(Qt::TopToolBarArea);
650 addToolBar(Qt::TopToolBarArea, toolBar);
653 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
654 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
655 #if (QT_VERSION >= 0x040202)
657 addToolBarBreak(Qt::BottomToolBarArea);
659 addToolBar(Qt::BottomToolBarArea, toolBar);
662 if (tbinfo.flags & ToolbarInfo::LEFT) {
663 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
664 #if (QT_VERSION >= 0x040202)
666 addToolBarBreak(Qt::LeftToolBarArea);
668 addToolBar(Qt::LeftToolBarArea, toolBar);
671 if (tbinfo.flags & ToolbarInfo::RIGHT) {
672 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
673 #if (QT_VERSION >= 0x040202)
675 addToolBarBreak(Qt::RightToolBarArea);
677 addToolBar(Qt::RightToolBarArea, toolBar);
680 // The following does not work so I cannot restore to exact toolbar location
682 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
683 toolBar->move(tbinfo.posx, tbinfo.posy);
690 GuiWorkArea * GuiView::workArea(Buffer & buffer)
692 for (int i = 0; i != d.splitter_->count(); ++i) {
693 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
701 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
704 // Automatically create a TabWorkArea if there are none yet.
705 if (!d.splitter_->count())
708 TabWorkArea * tab_widget = d.currentTabWorkArea();
709 return tab_widget->addWorkArea(buffer, *this);
713 void GuiView::addTabWorkArea()
715 TabWorkArea * twa = new TabWorkArea;
716 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
717 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
718 d.splitter_->addWidget(twa);
719 d.stack_widget_->setCurrentWidget(d.splitter_);
723 GuiWorkArea const * GuiView::currentWorkArea() const
725 return d.current_work_area_;
729 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
733 // Changing work area can result from opening a file so
734 // update the toc in any case.
737 d.current_work_area_ = wa;
738 for (int i = 0; i != d.splitter_->count(); ++i) {
739 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
745 void GuiView::removeWorkArea(GuiWorkArea * wa)
748 if (wa == d.current_work_area_) {
750 disconnectBufferView();
751 hideBufferDependent();
752 d.current_work_area_ = 0;
755 for (int i = 0; i != d.splitter_->count(); ++i) {
756 TabWorkArea * twa = d.tabWorkArea(i);
757 if (!twa->removeWorkArea(wa))
758 // Not found in this tab group.
761 // We found and removed the GuiWorkArea.
763 // No more WorkAreas in this tab group, so delete it.
768 if (d.current_work_area_)
769 // This means that we are not closing the current GuiWorkArea;
772 // Switch to the next GuiWorkArea in the found TabWorkArea.
773 d.current_work_area_ = twa->currentWorkArea();
777 if (d.splitter_->count() == 0)
778 // No more work area, switch to the background widget.
783 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
789 void GuiView::updateLayoutList()
792 d.layout_->updateContents(false);
796 void GuiView::updateToolbars()
798 if (d.current_work_area_) {
800 d.current_work_area_->bufferView().cursor().inMathed();
802 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
804 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
805 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
806 bool const mathmacrotemplate =
807 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
809 d.toolbars_->update(math, table, review, mathmacrotemplate);
811 d.toolbars_->update(false, false, false, false);
813 // update read-only status of open dialogs.
818 Buffer * GuiView::buffer()
820 if (d.current_work_area_)
821 return &d.current_work_area_->bufferView().buffer();
826 Buffer const * GuiView::buffer() const
828 if (d.current_work_area_)
829 return &d.current_work_area_->bufferView().buffer();
834 void GuiView::setBuffer(Buffer * newBuffer)
836 BOOST_ASSERT(newBuffer);
839 GuiWorkArea * wa = workArea(*newBuffer);
841 updateLabels(*newBuffer->masterBuffer());
842 wa = addWorkArea(*newBuffer);
844 //Disconnect the old buffer...there's no new one.
847 connectBuffer(*newBuffer);
848 connectBufferView(wa->bufferView());
849 setCurrentWorkArea(wa);
855 void GuiView::connectBuffer(Buffer & buf)
857 buf.setGuiDelegate(this);
861 void GuiView::disconnectBuffer()
863 if (d.current_work_area_)
864 d.current_work_area_->bufferView().setGuiDelegate(0);
868 void GuiView::connectBufferView(BufferView & bv)
870 bv.setGuiDelegate(this);
874 void GuiView::disconnectBufferView()
876 if (d.current_work_area_)
877 d.current_work_area_->bufferView().setGuiDelegate(0);
881 void GuiView::errors(string const & error_type)
883 ErrorList & el = buffer()->errorList(error_type);
885 showDialog("errorlist", error_type);
889 void GuiView::updateDialog(string const & name, string const & data)
891 if (!isDialogVisible(name))
894 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
895 if (it == d.dialogs_.end())
898 Dialog * const dialog = it->second.get();
899 if (dialog->isVisibleView())
900 dialog->updateData(data);
904 BufferView * GuiView::view()
906 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
910 void GuiView::updateToc()
912 updateDialog("toc", "");
916 void GuiView::updateEmbeddedFiles()
918 updateDialog("embedding", "");
922 void GuiView::autoSave()
924 LYXERR(Debug::INFO, "Running autoSave()");
927 view()->buffer().autoSave();
931 void GuiView::resetAutosaveTimers()
934 d.autosave_timeout_.restart();
938 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
942 Buffer * buf = buffer();
944 /* In LyX/Mac, when a dialog is open, the menus of the
945 application can still be accessed without giving focus to
946 the main window. In this case, we want to disable the menu
947 entries that are buffer-related.
949 Note that this code is not perfect, as bug 1941 attests:
950 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
952 if (cmd.origin == FuncRequest::MENU && !hasFocus())
956 case LFUN_BUFFER_WRITE:
957 enable = buf && (buf->isUnnamed() || !buf->isClean());
960 case LFUN_BUFFER_WRITE_AS:
964 case LFUN_TOOLBAR_TOGGLE:
965 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
968 case LFUN_DIALOG_TOGGLE:
969 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
970 // fall through to set "enable"
971 case LFUN_DIALOG_SHOW: {
972 string const name = cmd.getArg(0);
974 enable = name == "aboutlyx"
975 || name == "file" //FIXME: should be removed.
977 || name == "texinfo";
978 else if (name == "print")
979 enable = buf->isExportable("dvi")
980 && lyxrc.print_command != "none";
981 else if (name == "character") {
985 InsetCode ic = view()->cursor().inset().lyxCode();
986 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
989 else if (name == "symbols") {
990 if (!view() || view()->cursor().inMathed())
993 InsetCode ic = view()->cursor().inset().lyxCode();
994 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
997 else if (name == "latexlog")
998 enable = FileName(buf->logName()).isReadableFile();
999 else if (name == "spellchecker")
1000 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1001 enable = !buf->isReadonly();
1005 else if (name == "vclog")
1006 enable = buf->lyxvc().inUse();
1010 case LFUN_DIALOG_UPDATE: {
1011 string const name = cmd.getArg(0);
1013 enable = name == "prefs";
1017 case LFUN_INSET_APPLY: {
1022 string const name = cmd.getArg(0);
1023 Inset * inset = getOpenInset(name);
1025 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1027 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1028 // Every inset is supposed to handle this
1029 BOOST_ASSERT(false);
1033 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1034 flag |= getStatus(fr);
1036 enable = flag.enabled();
1048 flag.enabled(false);
1054 static FileName selectTemplateFile()
1056 FileDialog dlg(_("Select template file"));
1057 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1058 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1060 FileDialog::Result result =
1061 dlg.open(from_utf8(lyxrc.template_path),
1062 FileFilterList(_("LyX Documents (*.lyx)")),
1065 if (result.first == FileDialog::Later)
1067 if (result.second.empty())
1069 return FileName(to_utf8(result.second));
1073 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1077 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1080 message(_("Document not loaded."));
1085 setBuffer(newBuffer);
1087 // scroll to the position when the file was last closed
1088 if (lyxrc.use_lastfilepos) {
1089 LastFilePosSection::FilePos filepos =
1090 LyX::ref().session().lastFilePos().load(filename);
1091 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1095 LyX::ref().session().lastFiles().add(filename);
1102 void GuiView::openDocument(string const & fname)
1104 string initpath = lyxrc.document_path;
1107 string const trypath = buffer()->filePath();
1108 // If directory is writeable, use this as default.
1109 if (FileName(trypath).isDirWritable())
1115 if (fname.empty()) {
1116 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1117 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1118 dlg.setButton2(_("Examples|#E#e"),
1119 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1121 FileDialog::Result result =
1122 dlg.open(from_utf8(initpath),
1123 FileFilterList(_("LyX Documents (*.lyx)")),
1126 if (result.first == FileDialog::Later)
1129 filename = to_utf8(result.second);
1131 // check selected filename
1132 if (filename.empty()) {
1133 message(_("Canceled."));
1139 // get absolute path of file and add ".lyx" to the filename if
1141 FileName const fullname =
1142 fileSearch(string(), filename, "lyx", support::may_not_exist);
1143 if (!fullname.empty())
1144 filename = fullname.absFilename();
1146 // if the file doesn't exist, let the user create one
1147 if (!fullname.exists()) {
1148 // the user specifically chose this name. Believe him.
1149 Buffer * const b = newFile(filename, string(), true);
1155 docstring const disp_fn = makeDisplayPath(filename);
1156 message(bformat(_("Opening document %1$s..."), disp_fn));
1159 Buffer * buf = loadDocument(fullname);
1163 buf->errors("Parse");
1164 str2 = bformat(_("Document %1$s opened."), disp_fn);
1166 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1171 // FIXME: clean that
1172 static bool import(GuiView * lv, FileName const & filename,
1173 string const & format, ErrorList & errorList)
1175 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1177 string loader_format;
1178 vector<string> loaders = theConverters().loaders();
1179 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1180 for (vector<string>::const_iterator it = loaders.begin();
1181 it != loaders.end(); ++it) {
1182 if (!theConverters().isReachable(format, *it))
1185 string const tofile =
1186 changeExtension(filename.absFilename(),
1187 formats.extension(*it));
1188 if (!theConverters().convert(0, filename, FileName(tofile),
1189 filename, format, *it, errorList))
1191 loader_format = *it;
1194 if (loader_format.empty()) {
1195 frontend::Alert::error(_("Couldn't import file"),
1196 bformat(_("No information for importing the format %1$s."),
1197 formats.prettyName(format)));
1201 loader_format = format;
1203 if (loader_format == "lyx") {
1204 Buffer * buf = lv->loadDocument(lyxfile);
1209 buf->errors("Parse");
1211 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1215 bool as_paragraphs = loader_format == "textparagraph";
1216 string filename2 = (loader_format == format) ? filename.absFilename()
1217 : changeExtension(filename.absFilename(),
1218 formats.extension(loader_format));
1219 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1220 theLyXFunc().setLyXView(lv);
1221 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1228 void GuiView::importDocument(string const & argument)
1231 string filename = split(argument, format, ' ');
1233 LYXERR(Debug::INFO, format << " file: " << filename);
1235 // need user interaction
1236 if (filename.empty()) {
1237 string initpath = lyxrc.document_path;
1239 Buffer const * buf = buffer();
1241 string const trypath = buf->filePath();
1242 // If directory is writeable, use this as default.
1243 if (FileName(trypath).isDirWritable())
1247 docstring const text = bformat(_("Select %1$s file to import"),
1248 formats.prettyName(format));
1250 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1251 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1252 dlg.setButton2(_("Examples|#E#e"),
1253 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1255 docstring filter = formats.prettyName(format);
1258 filter += from_utf8(formats.extension(format));
1261 FileDialog::Result result =
1262 dlg.open(from_utf8(initpath),
1263 FileFilterList(filter),
1266 if (result.first == FileDialog::Later)
1269 filename = to_utf8(result.second);
1271 // check selected filename
1272 if (filename.empty())
1273 message(_("Canceled."));
1276 if (filename.empty())
1279 // get absolute path of file
1280 FileName const fullname(makeAbsPath(filename));
1282 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1284 // Check if the document already is open
1285 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1288 if (!closeBuffer()) {
1289 message(_("Canceled."));
1294 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1296 // if the file exists already, and we didn't do
1297 // -i lyx thefile.lyx, warn
1298 if (lyxfile.exists() && fullname != lyxfile) {
1300 docstring text = bformat(_("The document %1$s already exists.\n\n"
1301 "Do you want to overwrite that document?"), displaypath);
1302 int const ret = Alert::prompt(_("Overwrite document?"),
1303 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1306 message(_("Canceled."));
1311 message(bformat(_("Importing %1$s..."), displaypath));
1312 ErrorList errorList;
1313 if (import(this, fullname, format, errorList))
1314 message(_("imported."));
1316 message(_("file not imported!"));
1318 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1322 void GuiView::newDocument(string const & filename, bool from_template)
1324 FileName initpath(lyxrc.document_path);
1325 Buffer * buf = buffer();
1327 FileName const trypath(buf->filePath());
1328 // If directory is writeable, use this as default.
1329 if (trypath.isDirWritable())
1333 string templatefile = from_template ?
1334 selectTemplateFile().absFilename() : string();
1336 if (filename.empty())
1337 b = newUnnamedFile(templatefile, initpath);
1339 b = newFile(filename, templatefile, true);
1343 // Ensure the cursor is correctly positionned on screen.
1344 view()->showCursor();
1348 void GuiView::insertLyXFile(docstring const & fname)
1350 BufferView * bv = view();
1355 FileName filename(to_utf8(fname));
1357 if (!filename.empty()) {
1358 bv->insertLyXFile(filename);
1362 // Launch a file browser
1364 string initpath = lyxrc.document_path;
1365 string const trypath = bv->buffer().filePath();
1366 // If directory is writeable, use this as default.
1367 if (FileName(trypath).isDirWritable())
1371 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1372 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1373 dlg.setButton2(_("Examples|#E#e"),
1374 from_utf8(addPath(package().system_support().absFilename(),
1377 FileDialog::Result result =
1378 dlg.open(from_utf8(initpath),
1379 FileFilterList(_("LyX Documents (*.lyx)")),
1382 if (result.first == FileDialog::Later)
1386 filename.set(to_utf8(result.second));
1388 // check selected filename
1389 if (filename.empty()) {
1390 // emit message signal.
1391 message(_("Canceled."));
1395 bv->insertLyXFile(filename);
1399 void GuiView::insertPlaintextFile(docstring const & fname,
1402 BufferView * bv = view();
1407 FileName filename(to_utf8(fname));
1409 if (!filename.empty()) {
1410 bv->insertPlaintextFile(filename, asParagraph);
1414 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1415 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1417 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1418 FileFilterList(), docstring());
1420 if (result.first == FileDialog::Later)
1424 filename.set(to_utf8(result.second));
1426 // check selected filename
1427 if (filename.empty()) {
1428 // emit message signal.
1429 message(_("Canceled."));
1433 bv->insertPlaintextFile(filename, asParagraph);
1437 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1439 FileName fname = b.fileName();
1440 FileName const oldname = fname;
1442 if (!newname.empty()) {
1444 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1446 // Switch to this Buffer.
1449 /// No argument? Ask user through dialog.
1451 FileDialog dlg(_("Choose a filename to save document as"),
1452 LFUN_BUFFER_WRITE_AS);
1453 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1454 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1456 if (!isLyXFilename(fname.absFilename()))
1457 fname.changeExtension(".lyx");
1459 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1461 FileDialog::Result result =
1462 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1464 from_utf8(fname.onlyFileName()));
1466 if (result.first == FileDialog::Later)
1469 fname.set(to_utf8(result.second));
1474 if (!isLyXFilename(fname.absFilename()))
1475 fname.changeExtension(".lyx");
1478 if (FileName(fname).exists()) {
1479 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1480 docstring text = bformat(_("The document %1$s already "
1481 "exists.\n\nDo you want to "
1482 "overwrite that document?"),
1484 int const ret = Alert::prompt(_("Overwrite document?"),
1485 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1488 case 1: return renameBuffer(b, docstring());
1489 case 2: return false;
1493 // Ok, change the name of the buffer
1494 b.setFileName(fname.absFilename());
1496 bool unnamed = b.isUnnamed();
1497 b.setUnnamed(false);
1498 b.saveCheckSum(fname);
1500 if (!saveBuffer(b)) {
1501 b.setFileName(oldname.absFilename());
1502 b.setUnnamed(unnamed);
1503 b.saveCheckSum(oldname);
1511 bool GuiView::saveBuffer(Buffer & b)
1514 return renameBuffer(b, docstring());
1517 LyX::ref().session().lastFiles().add(b.fileName());
1521 // Switch to this Buffer.
1524 // FIXME: we don't tell the user *WHY* the save failed !!
1525 docstring const file = makeDisplayPath(b.absFileName(), 30);
1526 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1527 "Do you want to rename the document and "
1528 "try again?"), file);
1529 int const ret = Alert::prompt(_("Rename and save?"),
1530 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1533 if (!renameBuffer(b, docstring()))
1542 return saveBuffer(b);
1546 bool GuiView::closeBuffer()
1548 Buffer * buf = buffer();
1549 return buf && closeBuffer(*buf);
1553 bool GuiView::closeBuffer(Buffer & buf)
1555 if (buf.isClean() || buf.paragraphs().empty()) {
1556 theBufferList().release(&buf);
1559 // Switch to this Buffer.
1564 if (buf.isUnnamed())
1565 file = from_utf8(buf.fileName().onlyFileName());
1567 file = buf.fileName().displayName(30);
1569 docstring const text = bformat(_("The document %1$s has unsaved changes."
1570 "\n\nDo you want to save the document or discard the changes?"), file);
1571 int const ret = Alert::prompt(_("Save changed document?"),
1572 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1576 if (!saveBuffer(buf))
1580 // if we crash after this we could
1581 // have no autosave file but I guess
1582 // this is really improbable (Jug)
1583 removeAutosaveFile(buf.absFileName());
1589 // save file names to .lyx/session
1590 // if master/slave are both open, do not save slave since it
1591 // will be automatically loaded when the master is loaded
1592 if (buf.masterBuffer() == &buf)
1593 LyX::ref().session().lastOpened().add(buf.fileName());
1595 theBufferList().release(&buf);
1600 bool GuiView::quitWriteAll()
1602 while (!theBufferList().empty()) {
1603 Buffer * b = theBufferList().first();
1604 if (!closeBuffer(*b))
1611 bool GuiView::dispatch(FuncRequest const & cmd)
1613 BufferView * bv = view();
1614 // By default we won't need any update.
1616 bv->cursor().updateFlags(Update::None);
1618 switch(cmd.action) {
1619 case LFUN_FILE_OPEN:
1620 openDocument(to_utf8(cmd.argument()));
1623 case LFUN_BUFFER_IMPORT:
1624 importDocument(to_utf8(cmd.argument()));
1627 case LFUN_BUFFER_SWITCH:
1628 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1631 case LFUN_BUFFER_NEXT:
1632 setBuffer(theBufferList().next(buffer()));
1635 case LFUN_BUFFER_PREVIOUS:
1636 setBuffer(theBufferList().previous(buffer()));
1639 case LFUN_COMMAND_EXECUTE: {
1640 bool const show_it = cmd.argument() != "off";
1641 d.toolbars_->showCommandBuffer(show_it);
1644 case LFUN_DROP_LAYOUTS_CHOICE:
1646 d.layout_->showPopup();
1649 case LFUN_MENU_OPEN:
1650 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1651 menu->exec(QCursor::pos());
1654 case LFUN_FILE_INSERT:
1655 insertLyXFile(cmd.argument());
1657 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1658 insertPlaintextFile(cmd.argument(), true);
1661 case LFUN_FILE_INSERT_PLAINTEXT:
1662 insertPlaintextFile(cmd.argument(), false);
1665 case LFUN_BUFFER_WRITE:
1667 saveBuffer(bv->buffer());
1670 case LFUN_BUFFER_WRITE_AS:
1672 renameBuffer(bv->buffer(), cmd.argument());
1675 case LFUN_BUFFER_WRITE_ALL: {
1676 Buffer * first = theBufferList().first();
1679 message(_("Saving all documents..."));
1680 // We cannot use a for loop as the buffer list cycles.
1686 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1687 b = theBufferList().next(b);
1688 } while (b != first);
1689 message(_("All documents saved."));
1693 case LFUN_TOOLBAR_TOGGLE: {
1694 string const name = cmd.getArg(0);
1695 bool const allowauto = cmd.getArg(1) == "allowauto";
1696 // it is possible to get current toolbar status like this,...
1697 // but I decide to obey the order of ToolbarBackend::flags
1698 // and disregard real toolbar status.
1699 // toolbars_->saveToolbarInfo();
1701 // toggle state on/off/auto
1702 d.toolbars_->toggleToolbarState(name, allowauto);
1706 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1708 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1712 if (tbi->flags & ToolbarInfo::ON)
1714 else if (tbi->flags & ToolbarInfo::OFF)
1716 else if (tbi->flags & ToolbarInfo::AUTO)
1719 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1720 _(tbi->gui_name), state));
1724 case LFUN_DIALOG_UPDATE: {
1725 string const name = to_utf8(cmd.argument());
1726 // Can only update a dialog connected to an existing inset
1727 Inset * inset = getOpenInset(name);
1729 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1730 inset->dispatch(view()->cursor(), fr);
1731 } else if (name == "paragraph") {
1732 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1733 } else if (name == "prefs") {
1734 updateDialog(name, string());
1739 case LFUN_DIALOG_TOGGLE: {
1740 if (isDialogVisible(cmd.getArg(0)))
1741 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1743 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1747 case LFUN_DIALOG_DISCONNECT_INSET:
1748 disconnectDialog(to_utf8(cmd.argument()));
1751 case LFUN_DIALOG_HIDE: {
1754 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1758 case LFUN_DIALOG_SHOW: {
1759 string const name = cmd.getArg(0);
1760 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1762 if (name == "character") {
1763 data = freefont2string();
1765 showDialog("character", data);
1766 } else if (name == "latexlog") {
1767 Buffer::LogType type;
1768 string const logfile = buffer()->logName(&type);
1770 case Buffer::latexlog:
1773 case Buffer::buildlog:
1777 data += Lexer::quoteString(logfile);
1778 showDialog("log", data);
1779 } else if (name == "vclog") {
1780 string const data = "vc " +
1781 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1782 showDialog("log", data);
1783 } else if (name == "symbols") {
1784 data = bv->cursor().getEncoding()->name();
1786 showDialog("symbols", data);
1788 showDialog(name, data);
1792 case LFUN_INSET_APPLY: {
1793 string const name = cmd.getArg(0);
1794 Inset * inset = getOpenInset(name);
1796 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1797 inset->dispatch(view()->cursor(), fr);
1799 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1805 case LFUN_UI_TOGGLE:
1817 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1819 string const arg = cmd.getArg(0);
1820 if (arg == "scrollbar") {
1821 // hide() is of no help
1822 if (d.current_work_area_->verticalScrollBarPolicy() ==
1823 Qt::ScrollBarAlwaysOff)
1825 d.current_work_area_->setVerticalScrollBarPolicy(
1826 Qt::ScrollBarAsNeeded);
1828 d.current_work_area_->setVerticalScrollBarPolicy(
1829 Qt::ScrollBarAlwaysOff);
1832 if (arg == "statusbar") {
1833 statusBar()->setVisible(!statusBar()->isVisible());
1836 if (arg == "menubar") {
1837 menuBar()->setVisible(!menuBar()->isVisible());
1840 #if QT_VERSION >= 0x040300
1841 if (arg == "frame") {
1843 getContentsMargins(&l, &t, &r, &b);
1844 //are the frames in default state?
1846 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1847 setContentsMargins(-2, -2, -2, -2);
1849 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1850 setContentsMargins(0, 0, 0, 0);
1855 if (arg != "fullscreen") {
1856 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1860 if (isFullScreen()) {
1862 #if QT_VERSION >= 0x040300
1863 setContentsMargins(0, 0, 0, 0);
1865 for (int i = 0; i != d.splitter_->count(); ++i)
1866 d.tabWorkArea(i)->setFullScreen(false);
1868 statusBar()->show();
1870 statusBar()->hide();
1872 for (int i = 0; i != d.splitter_->count(); ++i)
1873 d.tabWorkArea(i)->setFullScreen(true);
1874 #if QT_VERSION >= 0x040300
1875 setContentsMargins(-2, -2, -2, -2);
1882 Buffer const * GuiView::updateInset(Inset const * inset)
1884 if (!d.current_work_area_)
1888 d.current_work_area_->scheduleRedraw();
1890 return &d.current_work_area_->bufferView().buffer();
1894 void GuiView::restartCursor()
1896 /* When we move around, or type, it's nice to be able to see
1897 * the cursor immediately after the keypress.
1899 if (d.current_work_area_)
1900 d.current_work_area_->startBlinkingCursor();
1902 // Take this occasion to update the toobars and layout list.
1909 // This list should be kept in sync with the list of insets in
1910 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1911 // dialog should have the same name as the inset.
1913 char const * const dialognames[] = {
1914 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1915 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1916 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1917 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1918 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1920 #ifdef HAVE_LIBAIKSAURUS
1924 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1926 char const * const * const end_dialognames =
1927 dialognames + (sizeof(dialognames) / sizeof(char *));
1931 cmpCStr(char const * name) : name_(name) {}
1932 bool operator()(char const * other) {
1933 return strcmp(other, name_) == 0;
1940 bool isValidName(string const & name)
1942 return find_if(dialognames, end_dialognames,
1943 cmpCStr(name.c_str())) != end_dialognames;
1949 void GuiView::resetDialogs()
1951 // Make sure that no LFUN uses any LyXView.
1952 theLyXFunc().setLyXView(0);
1953 // FIXME: the "math panels" toolbar takes an awful lot of time to
1954 // initialise so we don't do that for the time being.
1955 //d.toolbars_->init();
1956 guiApp->menus().fillMenuBar(this);
1958 d.layout_->updateContents(true);
1959 // Now update controls with current buffer.
1960 theLyXFunc().setLyXView(this);
1965 Dialog * GuiView::find_or_build(string const & name)
1967 if (!isValidName(name))
1970 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1972 if (it != d.dialogs_.end())
1973 return it->second.get();
1975 Dialog * dialog = build(name);
1976 d.dialogs_[name].reset(dialog);
1977 if (lyxrc.allow_geometry_session)
1978 dialog->restoreSession();
1983 void GuiView::showDialog(string const & name, string const & data,
1990 Dialog * dialog = find_or_build(name);
1992 dialog->showData(data);
1994 d.open_insets_[name] = inset;
2000 bool GuiView::isDialogVisible(string const & name) const
2002 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2003 if (it == d.dialogs_.end())
2005 return it->second.get()->isVisibleView();
2009 void GuiView::hideDialog(string const & name, Inset * inset)
2011 // Don't send the signal if we are quitting, because on MSVC it is
2012 // destructed before the cut stack in CutAndPaste.cpp, and this method
2013 // is called from some inset destructor if the cut stack is not empty
2018 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2019 if (it == d.dialogs_.end())
2022 if (inset && inset != getOpenInset(name))
2025 Dialog * const dialog = it->second.get();
2026 if (dialog->isVisibleView())
2028 d.open_insets_[name] = 0;
2032 void GuiView::disconnectDialog(string const & name)
2034 if (!isValidName(name))
2037 if (d.open_insets_.find(name) != d.open_insets_.end())
2038 d.open_insets_[name] = 0;
2042 Inset * GuiView::getOpenInset(string const & name) const
2044 if (!isValidName(name))
2047 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2048 return it == d.open_insets_.end() ? 0 : it->second;
2052 void GuiView::hideAll() const
2054 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2055 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2057 for(; it != end; ++it)
2058 it->second->hideView();
2062 void GuiView::hideBufferDependent() const
2064 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2065 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2067 for(; it != end; ++it) {
2068 Dialog * dialog = it->second.get();
2069 if (dialog->isBufferDependent())
2075 void GuiView::updateBufferDependent(bool switched) const
2077 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2078 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2080 for(; it != end; ++it) {
2081 Dialog * dialog = it->second.get();
2082 if (!dialog->isVisibleView())
2084 if (switched && dialog->isBufferDependent()) {
2085 if (dialog->initialiseParams(""))
2086 dialog->updateView();
2090 // A bit clunky, but the dialog will request
2091 // that the kernel provides it with the necessary
2093 dialog->updateDialog();
2099 void GuiView::checkStatus()
2101 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2102 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2104 for(; it != end; ++it) {
2105 Dialog * const dialog = it->second.get();
2106 if (dialog && dialog->isVisibleView())
2107 dialog->checkStatus();
2113 // will be replaced by a proper factory...
2114 Dialog * createGuiAbout(GuiView & lv);
2115 Dialog * createGuiBibitem(GuiView & lv);
2116 Dialog * createGuiBibtex(GuiView & lv);
2117 Dialog * createGuiBox(GuiView & lv);
2118 Dialog * createGuiBranch(GuiView & lv);
2119 Dialog * createGuiChanges(GuiView & lv);
2120 Dialog * createGuiCharacter(GuiView & lv);
2121 Dialog * createGuiCitation(GuiView & lv);
2122 Dialog * createGuiDelimiter(GuiView & lv);
2123 Dialog * createGuiDocument(GuiView & lv);
2124 Dialog * createGuiErrorList(GuiView & lv);
2125 Dialog * createGuiERT(GuiView & lv);
2126 Dialog * createGuiExternal(GuiView & lv);
2127 Dialog * createGuiFloat(GuiView & lv);
2128 Dialog * createGuiGraphics(GuiView & lv);
2129 Dialog * createGuiInclude(GuiView & lv);
2130 Dialog * createGuiIndex(GuiView & lv);
2131 Dialog * createGuiLabel(GuiView & lv);
2132 Dialog * createGuiListings(GuiView & lv);
2133 Dialog * createGuiLog(GuiView & lv);
2134 Dialog * createGuiMathMatrix(GuiView & lv);
2135 Dialog * createGuiNomenclature(GuiView & lv);
2136 Dialog * createGuiNote(GuiView & lv);
2137 Dialog * createGuiParagraph(GuiView & lv);
2138 Dialog * createGuiPreferences(GuiView & lv);
2139 Dialog * createGuiPrint(GuiView & lv);
2140 Dialog * createGuiRef(GuiView & lv);
2141 Dialog * createGuiSearch(GuiView & lv);
2142 Dialog * createGuiSendTo(GuiView & lv);
2143 Dialog * createGuiShowFile(GuiView & lv);
2144 Dialog * createGuiSpellchecker(GuiView & lv);
2145 Dialog * createGuiSymbols(GuiView & lv);
2146 Dialog * createGuiTabularCreate(GuiView & lv);
2147 Dialog * createGuiTabular(GuiView & lv);
2148 Dialog * createGuiTexInfo(GuiView & lv);
2149 Dialog * createGuiToc(GuiView & lv);
2150 Dialog * createGuiThesaurus(GuiView & lv);
2151 Dialog * createGuiHyperlink(GuiView & lv);
2152 Dialog * createGuiVSpace(GuiView & lv);
2153 Dialog * createGuiViewSource(GuiView & lv);
2154 Dialog * createGuiWrap(GuiView & lv);
2157 Dialog * GuiView::build(string const & name)
2159 BOOST_ASSERT(isValidName(name));
2161 if (name == "aboutlyx")
2162 return createGuiAbout(*this);
2163 if (name == "bibitem")
2164 return createGuiBibitem(*this);
2165 if (name == "bibtex")
2166 return createGuiBibtex(*this);
2168 return createGuiBox(*this);
2169 if (name == "branch")
2170 return createGuiBranch(*this);
2171 if (name == "changes")
2172 return createGuiChanges(*this);
2173 if (name == "character")
2174 return createGuiCharacter(*this);
2175 if (name == "citation")
2176 return createGuiCitation(*this);
2177 if (name == "document")
2178 return createGuiDocument(*this);
2179 if (name == "errorlist")
2180 return createGuiErrorList(*this);
2182 return createGuiERT(*this);
2183 if (name == "external")
2184 return createGuiExternal(*this);
2186 return createGuiShowFile(*this);
2187 if (name == "findreplace")
2188 return createGuiSearch(*this);
2189 if (name == "float")
2190 return createGuiFloat(*this);
2191 if (name == "graphics")
2192 return createGuiGraphics(*this);
2193 if (name == "include")
2194 return createGuiInclude(*this);
2195 if (name == "index")
2196 return createGuiIndex(*this);
2197 if (name == "nomenclature")
2198 return createGuiNomenclature(*this);
2199 if (name == "label")
2200 return createGuiLabel(*this);
2202 return createGuiLog(*this);
2203 if (name == "view-source")
2204 return createGuiViewSource(*this);
2205 if (name == "mathdelimiter")
2206 return createGuiDelimiter(*this);
2207 if (name == "mathmatrix")
2208 return createGuiMathMatrix(*this);
2210 return createGuiNote(*this);
2211 if (name == "paragraph")
2212 return createGuiParagraph(*this);
2213 if (name == "prefs")
2214 return createGuiPreferences(*this);
2215 if (name == "print")
2216 return createGuiPrint(*this);
2218 return createGuiRef(*this);
2219 if (name == "sendto")
2220 return createGuiSendTo(*this);
2221 if (name == "spellchecker")
2222 return createGuiSpellchecker(*this);
2223 if (name == "symbols")
2224 return createGuiSymbols(*this);
2225 if (name == "tabular")
2226 return createGuiTabular(*this);
2227 if (name == "tabularcreate")
2228 return createGuiTabularCreate(*this);
2229 if (name == "texinfo")
2230 return createGuiTexInfo(*this);
2231 #ifdef HAVE_LIBAIKSAURUS
2232 if (name == "thesaurus")
2233 return createGuiThesaurus(*this);
2236 return createGuiToc(*this);
2238 return createGuiHyperlink(*this);
2239 if (name == "vspace")
2240 return createGuiVSpace(*this);
2242 return createGuiWrap(*this);
2243 if (name == "listings")
2244 return createGuiListings(*this);
2250 } // namespace frontend
2253 #include "GuiView_moc.cpp"