3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * \author Abdelrazak Younes
11 * Full author contact details are available in file CREDITS.
19 #include "FileDialog.h"
20 #include "GuiApplication.h"
21 #include "GuiWorkArea.h"
22 #include "GuiKeySymbol.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
27 #include "qt_helpers.h"
29 #include "frontends/alert.h"
31 #include "buffer_funcs.h"
33 #include "BufferList.h"
34 #include "BufferParams.h"
35 #include "BufferView.h"
36 #include "Converter.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "support/gettext.h"
49 #include "Paragraph.h"
50 #include "TextClass.h"
52 #include "ToolbarBackend.h"
55 #include "support/debug.h"
56 #include "support/FileFilterList.h"
57 #include "support/FileName.h"
58 #include "support/filetools.h"
59 #include "support/ForkedCalls.h"
60 #include "support/lstrings.h"
61 #include "support/os.h"
62 #include "support/Package.h"
63 #include "support/Timeout.h"
66 #include <QApplication>
67 #include <QCloseEvent>
69 #include <QDesktopWidget>
70 #include <QDragEnterEvent>
78 #include <QPushButton>
82 #include <QStackedWidget>
89 #include <boost/assert.hpp>
90 #include <boost/bind.hpp>
92 #ifdef HAVE_SYS_TIME_H
93 # include <sys/time.h>
100 using namespace lyx::support;
107 class BackgroundWidget : public QWidget
112 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
113 /// The text to be written on top of the pixmap
114 QString const text = lyx_version ? lyx_version : qt_("unknown version");
115 splash_ = QPixmap(":/images/banner.png");
117 QPainter pain(&splash_);
118 pain.setPen(QColor(255, 255, 0));
120 // The font used to display the version info
121 font.setStyleHint(QFont::SansSerif);
122 font.setWeight(QFont::Bold);
123 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
125 pain.drawText(260, 270, text);
128 void paintEvent(QPaintEvent *)
130 int x = (width() - splash_.width()) / 2;
131 int y = (height() - splash_.height()) / 2;
133 pain.drawPixmap(x, y, splash_);
143 typedef boost::shared_ptr<Dialog> DialogPtr;
145 struct GuiView::GuiViewPrivate
148 : current_work_area_(0), layout_(0),
149 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
151 // hardcode here the platform specific icon size
152 smallIconSize = 14; // scaling problems
153 normalIconSize = 20; // ok, default
154 bigIconSize = 26; // better for some math icons
156 splitter_ = new QSplitter;
157 bg_widget_ = new BackgroundWidget;
158 stack_widget_ = new QStackedWidget;
159 stack_widget_->addWidget(bg_widget_);
160 stack_widget_->addWidget(splitter_);
168 delete stack_widget_;
172 QMenu * toolBarPopup(GuiView * parent)
174 // FIXME: translation
175 QMenu * menu = new QMenu(parent);
176 QActionGroup * iconSizeGroup = new QActionGroup(parent);
178 QAction * smallIcons = new QAction(iconSizeGroup);
179 smallIcons->setText(qt_("Small-sized icons"));
180 smallIcons->setCheckable(true);
181 QObject::connect(smallIcons, SIGNAL(triggered()),
182 parent, SLOT(smallSizedIcons()));
183 menu->addAction(smallIcons);
185 QAction * normalIcons = new QAction(iconSizeGroup);
186 normalIcons->setText(qt_("Normal-sized icons"));
187 normalIcons->setCheckable(true);
188 QObject::connect(normalIcons, SIGNAL(triggered()),
189 parent, SLOT(normalSizedIcons()));
190 menu->addAction(normalIcons);
192 QAction * bigIcons = new QAction(iconSizeGroup);
193 bigIcons->setText(qt_("Big-sized icons"));
194 bigIcons->setCheckable(true);
195 QObject::connect(bigIcons, SIGNAL(triggered()),
196 parent, SLOT(bigSizedIcons()));
197 menu->addAction(bigIcons);
199 unsigned int cur = parent->iconSize().width();
200 if ( cur == parent->d.smallIconSize)
201 smallIcons->setChecked(true);
202 else if (cur == parent->d.normalIconSize)
203 normalIcons->setChecked(true);
204 else if (cur == parent->d.bigIconSize)
205 bigIcons->setChecked(true);
212 stack_widget_->setCurrentWidget(bg_widget_);
213 bg_widget_->setUpdatesEnabled(true);
216 TabWorkArea * tabWorkArea(int i)
218 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
221 TabWorkArea * currentTabWorkArea()
223 if (splitter_->count() == 1)
224 // The first TabWorkArea is always the first one, if any.
225 return tabWorkArea(0);
227 for (int i = 0; i != splitter_->count(); ++i) {
228 TabWorkArea * twa = tabWorkArea(i);
229 if (current_work_area_ == twa->currentWorkArea())
233 // None has the focus so we just take the first one.
234 return tabWorkArea(0);
238 GuiWorkArea * current_work_area_;
239 QSplitter * splitter_;
240 QStackedWidget * stack_widget_;
241 BackgroundWidget * bg_widget_;
243 GuiToolbars * toolbars_;
244 /// The main layout box.
246 * \warning Don't Delete! The layout box is actually owned by
247 * whichever toolbar contains it. All the GuiView class needs is a
248 * means of accessing it.
250 * FIXME: replace that with a proper model so that we are not limited
251 * to only one dialog.
253 GuiLayoutBox * layout_;
256 map<string, Inset *> open_insets_;
259 map<string, DialogPtr> dialogs_;
261 unsigned int smallIconSize;
262 unsigned int normalIconSize;
263 unsigned int bigIconSize;
265 QTimer statusbar_timer_;
266 /// are we quitting by the menu?
267 bool quitting_by_menu_;
268 /// auto-saving of buffers
269 Timeout autosave_timeout_;
270 /// flag against a race condition due to multiclicks, see bug #1119
275 GuiView::GuiView(int id)
276 : d(*new GuiViewPrivate), id_(id)
278 // GuiToolbars *must* be initialised before the menu bar.
279 d.toolbars_ = new GuiToolbars(*this);
281 // Fill up the menu bar.
282 guiApp->menus().fillMenuBar(this);
284 setCentralWidget(d.stack_widget_);
286 // Start autosave timer
287 if (lyxrc.autosave) {
288 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
289 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
290 d.autosave_timeout_.start();
292 connect(&d.statusbar_timer_, SIGNAL(timeout()),
293 this, SLOT(clearMessage()));
295 // Qt bug? signal lastWindowClosed does not work
296 setAttribute(Qt::WA_QuitOnClose, false);
297 setAttribute(Qt::WA_DeleteOnClose, true);
299 // assign an icon to main form. We do not do it under Qt/Mac,
300 // since the icon is provided in the application bundle.
301 setWindowIcon(QPixmap(":/images/lyx.png"));
305 setAcceptDrops(true);
307 statusBar()->setSizeGripEnabled(true);
309 // Forbid too small unresizable window because it can happen
310 // with some window manager under X11.
311 setMinimumSize(300, 200);
313 if (!lyxrc.allow_geometry_session)
314 // No session handling, default to a sane size.
315 setGeometry(50, 50, 690, 510);
317 // Now take care of session management.
319 QString const key = "view-" + QString::number(id_);
321 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
322 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
326 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
327 setGeometry(50, 50, 690, 510);
329 setIconSize(settings.value(key + "/icon_size").toSize());
339 void GuiView::close()
341 d.quitting_by_menu_ = true;
342 d.current_work_area_ = 0;
343 for (int i = 0; i != d.splitter_->count(); ++i) {
344 TabWorkArea * twa = d.tabWorkArea(i);
348 QMainWindow::close();
349 d.quitting_by_menu_ = false;
353 void GuiView::setFocus()
355 if (d.current_work_area_)
356 d.current_work_area_->setFocus();
362 QMenu * GuiView::createPopupMenu()
364 return d.toolBarPopup(this);
368 void GuiView::showEvent(QShowEvent * e)
370 LYXERR(Debug::GUI, "Passed Geometry "
371 << size().height() << "x" << size().width()
372 << "+" << pos().x() << "+" << pos().y());
374 if (d.splitter_->count() == 0)
375 // No work area, switch to the background widget.
378 QMainWindow::showEvent(e);
382 void GuiView::closeEvent(QCloseEvent * close_event)
384 // we may have been called through the close window button
385 // which bypasses the LFUN machinery.
386 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
387 if (!quitWriteAll()) {
388 close_event->ignore();
393 // Make sure that no LFUN use this close to be closed View.
394 theLyXFunc().setLyXView(0);
396 // Save toolbars configuration
397 if (isFullScreen()) {
398 d.toolbars_->toggleFullScreen(!isFullScreen());
402 // Make sure the timer time out will not trigger a statusbar update.
403 d.statusbar_timer_.stop();
405 // Saving fullscreen requires additional tweaks in the toolbar code.
406 // It wouldn't also work under linux natively.
407 if (lyxrc.allow_geometry_session && !isFullScreen()) {
409 QString const key = "view-" + QString::number(id_);
411 settings.setValue(key + "/pos", pos());
412 settings.setValue(key + "/size", size());
414 settings.setValue(key + "/geometry", saveGeometry());
416 settings.setValue(key + "/icon_size", iconSize());
417 d.toolbars_->saveToolbarInfo();
418 // Now take care of all other dialogs:
419 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
420 for (; it!= d.dialogs_.end(); ++it)
421 it->second->saveSession();
424 guiApp->unregisterView(id_);
425 if (guiApp->viewCount() > 0) {
426 // Just close the window and do nothing else if this is not the
428 close_event->accept();
434 // this is the place where we leave the frontend.
435 // it is the only point at which we start quitting.
436 close_event->accept();
437 // quit the event loop
442 void GuiView::dragEnterEvent(QDragEnterEvent * event)
444 if (event->mimeData()->hasUrls())
446 /// \todo Ask lyx-devel is this is enough:
447 /// if (event->mimeData()->hasFormat("text/plain"))
448 /// event->acceptProposedAction();
452 void GuiView::dropEvent(QDropEvent* event)
454 QList<QUrl> files = event->mimeData()->urls();
458 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
459 for (int i = 0; i != files.size(); ++i) {
460 string const file = os::internal_path(fromqstr(
461 files.at(i).toLocalFile()));
463 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
468 void GuiView::message(docstring const & str)
470 if (ForkedProcess::iAmAChild())
473 statusBar()->showMessage(toqstr(str));
474 d.statusbar_timer_.stop();
475 d.statusbar_timer_.start(3000);
479 void GuiView::smallSizedIcons()
481 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
485 void GuiView::normalSizedIcons()
487 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
491 void GuiView::bigSizedIcons()
493 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
497 void GuiView::clearMessage()
501 theLyXFunc().setLyXView(this);
502 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
503 d.statusbar_timer_.stop();
507 void GuiView::updateWindowTitle(GuiWorkArea * wa)
509 if (wa != d.current_work_area_)
511 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
512 setWindowIconText(wa->windowIconText());
516 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
519 disconnectBufferView();
520 connectBufferView(wa->bufferView());
521 connectBuffer(wa->bufferView().buffer());
522 d.current_work_area_ = wa;
523 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
524 this, SLOT(updateWindowTitle(GuiWorkArea *)));
525 updateWindowTitle(wa);
528 // Buffer-dependent dialogs should be updated or
529 // hidden. This should go here because some dialogs (eg ToC)
530 // require bv_->text.
531 updateBufferDependent(true);
538 void GuiView::updateStatusBar()
540 // let the user see the explicit message
541 if (d.statusbar_timer_.isActive())
544 theLyXFunc().setLyXView(this);
545 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
549 bool GuiView::hasFocus() const
551 return qApp->activeWindow() == this;
555 bool GuiView::event(QEvent * e)
559 // Useful debug code:
560 //case QEvent::ActivationChange:
561 //case QEvent::WindowDeactivate:
562 //case QEvent::Paint:
563 //case QEvent::Enter:
564 //case QEvent::Leave:
565 //case QEvent::HoverEnter:
566 //case QEvent::HoverLeave:
567 //case QEvent::HoverMove:
568 //case QEvent::StatusTip:
569 //case QEvent::DragEnter:
570 //case QEvent::DragLeave:
574 case QEvent::WindowActivate: {
575 guiApp->setCurrentView(*this);
576 if (d.current_work_area_) {
577 BufferView & bv = d.current_work_area_->bufferView();
578 connectBufferView(bv);
579 connectBuffer(bv.buffer());
580 // The document structure, name and dialogs might have
581 // changed in another view.
582 updateBufferDependent(true);
587 setWindowTitle(qt_("LyX"));
588 setWindowIconText(qt_("LyX"));
591 return QMainWindow::event(e);
594 case QEvent::ShortcutOverride: {
595 if (d.current_work_area_)
596 // Nothing special to do.
597 return QMainWindow::event(e);
599 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
601 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
603 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
604 || ke->key() == Qt::Key_Backtab)
605 return QMainWindow::event(e);
607 // Allow processing of shortcuts that are allowed even when no Buffer
609 theLyXFunc().setLyXView(this);
611 setKeySymbol(&sym, ke);
612 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
618 return QMainWindow::event(e);
623 bool GuiView::focusNextPrevChild(bool /*next*/)
630 void GuiView::setBusy(bool busy)
632 if (d.current_work_area_) {
633 d.current_work_area_->setUpdatesEnabled(!busy);
635 d.current_work_area_->stopBlinkingCursor();
637 d.current_work_area_->startBlinkingCursor();
641 QApplication::setOverrideCursor(Qt::WaitCursor);
643 QApplication::restoreOverrideCursor();
647 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
649 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
651 if (tbinfo.flags & ToolbarInfo::TOP) {
653 addToolBarBreak(Qt::TopToolBarArea);
654 addToolBar(Qt::TopToolBarArea, toolBar);
657 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
658 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
659 #if (QT_VERSION >= 0x040202)
661 addToolBarBreak(Qt::BottomToolBarArea);
663 addToolBar(Qt::BottomToolBarArea, toolBar);
666 if (tbinfo.flags & ToolbarInfo::LEFT) {
667 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
668 #if (QT_VERSION >= 0x040202)
670 addToolBarBreak(Qt::LeftToolBarArea);
672 addToolBar(Qt::LeftToolBarArea, toolBar);
675 if (tbinfo.flags & ToolbarInfo::RIGHT) {
676 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
677 #if (QT_VERSION >= 0x040202)
679 addToolBarBreak(Qt::RightToolBarArea);
681 addToolBar(Qt::RightToolBarArea, toolBar);
684 // The following does not work so I cannot restore to exact toolbar location
686 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
687 toolBar->move(tbinfo.posx, tbinfo.posy);
694 GuiWorkArea * GuiView::workArea(Buffer & buffer)
696 if (TabWorkArea * twa = d.currentTabWorkArea())
697 return twa->workArea(buffer);
702 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
704 // Automatically create a TabWorkArea if there are none yet.
705 TabWorkArea * tab_widget = d.splitter_->count()
706 ? d.currentTabWorkArea() : addTabWorkArea();
707 return tab_widget->addWorkArea(buffer, *this);
711 TabWorkArea * GuiView::addTabWorkArea()
713 TabWorkArea * twa = new TabWorkArea;
714 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
715 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
716 d.splitter_->addWidget(twa);
717 d.stack_widget_->setCurrentWidget(d.splitter_);
722 GuiWorkArea const * GuiView::currentWorkArea() const
724 return d.current_work_area_;
728 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
732 // Changing work area can result from opening a file so
733 // update the toc in any case.
736 d.current_work_area_ = wa;
737 for (int i = 0; i != d.splitter_->count(); ++i) {
738 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
744 void GuiView::removeWorkArea(GuiWorkArea * wa)
747 if (wa == d.current_work_area_) {
749 disconnectBufferView();
750 hideBufferDependent();
751 d.current_work_area_ = 0;
754 for (int i = 0; i != d.splitter_->count(); ++i) {
755 TabWorkArea * twa = d.tabWorkArea(i);
756 if (!twa->removeWorkArea(wa))
757 // Not found in this tab group.
760 // We found and removed the GuiWorkArea.
762 // No more WorkAreas in this tab group, so delete it.
767 if (d.current_work_area_)
768 // This means that we are not closing the current GuiWorkArea;
771 // Switch to the next GuiWorkArea in the found TabWorkArea.
772 d.current_work_area_ = twa->currentWorkArea();
776 if (d.splitter_->count() == 0)
777 // No more work area, switch to the background widget.
782 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
788 void GuiView::updateLayoutList()
791 d.layout_->updateContents(false);
795 void GuiView::updateToolbars()
797 if (d.current_work_area_) {
799 d.current_work_area_->bufferView().cursor().inMathed();
801 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
803 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
804 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
805 bool const mathmacrotemplate =
806 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
808 d.toolbars_->update(math, table, review, mathmacrotemplate);
810 d.toolbars_->update(false, false, false, false);
812 // update read-only status of open dialogs.
817 Buffer * GuiView::buffer()
819 if (d.current_work_area_)
820 return &d.current_work_area_->bufferView().buffer();
825 Buffer const * GuiView::buffer() const
827 if (d.current_work_area_)
828 return &d.current_work_area_->bufferView().buffer();
833 void GuiView::setBuffer(Buffer * newBuffer)
835 BOOST_ASSERT(newBuffer);
838 GuiWorkArea * wa = workArea(*newBuffer);
840 updateLabels(*newBuffer->masterBuffer());
841 wa = addWorkArea(*newBuffer);
843 //Disconnect the old buffer...there's no new one.
846 connectBuffer(*newBuffer);
847 connectBufferView(wa->bufferView());
848 setCurrentWorkArea(wa);
854 void GuiView::connectBuffer(Buffer & buf)
856 buf.setGuiDelegate(this);
860 void GuiView::disconnectBuffer()
862 if (d.current_work_area_)
863 d.current_work_area_->bufferView().setGuiDelegate(0);
867 void GuiView::connectBufferView(BufferView & bv)
869 bv.setGuiDelegate(this);
873 void GuiView::disconnectBufferView()
875 if (d.current_work_area_)
876 d.current_work_area_->bufferView().setGuiDelegate(0);
880 void GuiView::errors(string const & error_type)
882 ErrorList & el = buffer()->errorList(error_type);
884 showDialog("errorlist", error_type);
888 void GuiView::updateDialog(string const & name, string const & data)
890 if (!isDialogVisible(name))
893 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
894 if (it == d.dialogs_.end())
897 Dialog * const dialog = it->second.get();
898 if (dialog->isVisibleView())
899 dialog->updateData(data);
903 BufferView * GuiView::view()
905 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
909 void GuiView::updateToc()
911 updateDialog("toc", "");
915 void GuiView::updateEmbeddedFiles()
917 updateDialog("embedding", "");
921 void GuiView::autoSave()
923 LYXERR(Debug::INFO, "Running autoSave()");
926 view()->buffer().autoSave();
930 void GuiView::resetAutosaveTimers()
933 d.autosave_timeout_.restart();
937 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
941 Buffer * buf = buffer();
943 /* In LyX/Mac, when a dialog is open, the menus of the
944 application can still be accessed without giving focus to
945 the main window. In this case, we want to disable the menu
946 entries that are buffer-related.
948 Note that this code is not perfect, as bug 1941 attests:
949 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
951 if (cmd.origin == FuncRequest::MENU && !hasFocus())
955 case LFUN_BUFFER_WRITE:
956 enable = buf && (buf->isUnnamed() || !buf->isClean());
959 case LFUN_BUFFER_WRITE_AS:
963 case LFUN_SPLIT_VIEW:
967 case LFUN_CLOSE_TAB_GROUP:
968 enable = d.currentTabWorkArea();
971 case LFUN_TOOLBAR_TOGGLE:
972 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
975 case LFUN_DIALOG_TOGGLE:
976 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
977 // fall through to set "enable"
978 case LFUN_DIALOG_SHOW: {
979 string const name = cmd.getArg(0);
981 enable = name == "aboutlyx"
982 || name == "file" //FIXME: should be removed.
984 || name == "texinfo";
985 else if (name == "print")
986 enable = buf->isExportable("dvi")
987 && lyxrc.print_command != "none";
988 else if (name == "character") {
992 InsetCode ic = view()->cursor().inset().lyxCode();
993 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
996 else if (name == "symbols") {
997 if (!view() || view()->cursor().inMathed())
1000 InsetCode ic = view()->cursor().inset().lyxCode();
1001 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1004 else if (name == "latexlog")
1005 enable = FileName(buf->logName()).isReadableFile();
1006 else if (name == "spellchecker")
1007 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1008 enable = !buf->isReadonly();
1012 else if (name == "vclog")
1013 enable = buf->lyxvc().inUse();
1017 case LFUN_DIALOG_UPDATE: {
1018 string const name = cmd.getArg(0);
1020 enable = name == "prefs";
1024 case LFUN_INSET_APPLY: {
1029 string const name = cmd.getArg(0);
1030 Inset * inset = getOpenInset(name);
1032 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1034 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1035 // Every inset is supposed to handle this
1036 BOOST_ASSERT(false);
1040 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1041 flag |= getStatus(fr);
1043 enable = flag.enabled();
1055 flag.enabled(false);
1061 static FileName selectTemplateFile()
1063 FileDialog dlg(_("Select template file"));
1064 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1065 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1067 FileDialog::Result result =
1068 dlg.open(from_utf8(lyxrc.template_path),
1069 FileFilterList(_("LyX Documents (*.lyx)")),
1072 if (result.first == FileDialog::Later)
1074 if (result.second.empty())
1076 return FileName(to_utf8(result.second));
1080 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1084 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1087 message(_("Document not loaded."));
1092 setBuffer(newBuffer);
1094 // scroll to the position when the file was last closed
1095 if (lyxrc.use_lastfilepos) {
1096 LastFilePosSection::FilePos filepos =
1097 LyX::ref().session().lastFilePos().load(filename);
1098 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1102 LyX::ref().session().lastFiles().add(filename);
1109 void GuiView::openDocument(string const & fname)
1111 string initpath = lyxrc.document_path;
1114 string const trypath = buffer()->filePath();
1115 // If directory is writeable, use this as default.
1116 if (FileName(trypath).isDirWritable())
1122 if (fname.empty()) {
1123 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1124 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1125 dlg.setButton2(_("Examples|#E#e"),
1126 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1128 FileDialog::Result result =
1129 dlg.open(from_utf8(initpath),
1130 FileFilterList(_("LyX Documents (*.lyx)")),
1133 if (result.first == FileDialog::Later)
1136 filename = to_utf8(result.second);
1138 // check selected filename
1139 if (filename.empty()) {
1140 message(_("Canceled."));
1146 // get absolute path of file and add ".lyx" to the filename if
1148 FileName const fullname =
1149 fileSearch(string(), filename, "lyx", support::may_not_exist);
1150 if (!fullname.empty())
1151 filename = fullname.absFilename();
1153 // if the file doesn't exist, let the user create one
1154 if (!fullname.exists()) {
1155 // the user specifically chose this name. Believe him.
1156 Buffer * const b = newFile(filename, string(), true);
1162 docstring const disp_fn = makeDisplayPath(filename);
1163 message(bformat(_("Opening document %1$s..."), disp_fn));
1166 Buffer * buf = loadDocument(fullname);
1170 buf->errors("Parse");
1171 str2 = bformat(_("Document %1$s opened."), disp_fn);
1173 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1178 // FIXME: clean that
1179 static bool import(GuiView * lv, FileName const & filename,
1180 string const & format, ErrorList & errorList)
1182 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1184 string loader_format;
1185 vector<string> loaders = theConverters().loaders();
1186 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1187 for (vector<string>::const_iterator it = loaders.begin();
1188 it != loaders.end(); ++it) {
1189 if (!theConverters().isReachable(format, *it))
1192 string const tofile =
1193 changeExtension(filename.absFilename(),
1194 formats.extension(*it));
1195 if (!theConverters().convert(0, filename, FileName(tofile),
1196 filename, format, *it, errorList))
1198 loader_format = *it;
1201 if (loader_format.empty()) {
1202 frontend::Alert::error(_("Couldn't import file"),
1203 bformat(_("No information for importing the format %1$s."),
1204 formats.prettyName(format)));
1208 loader_format = format;
1210 if (loader_format == "lyx") {
1211 Buffer * buf = lv->loadDocument(lyxfile);
1216 buf->errors("Parse");
1218 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1222 bool as_paragraphs = loader_format == "textparagraph";
1223 string filename2 = (loader_format == format) ? filename.absFilename()
1224 : changeExtension(filename.absFilename(),
1225 formats.extension(loader_format));
1226 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1227 theLyXFunc().setLyXView(lv);
1228 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1235 void GuiView::importDocument(string const & argument)
1238 string filename = split(argument, format, ' ');
1240 LYXERR(Debug::INFO, format << " file: " << filename);
1242 // need user interaction
1243 if (filename.empty()) {
1244 string initpath = lyxrc.document_path;
1246 Buffer const * buf = buffer();
1248 string const trypath = buf->filePath();
1249 // If directory is writeable, use this as default.
1250 if (FileName(trypath).isDirWritable())
1254 docstring const text = bformat(_("Select %1$s file to import"),
1255 formats.prettyName(format));
1257 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1258 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1259 dlg.setButton2(_("Examples|#E#e"),
1260 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1262 docstring filter = formats.prettyName(format);
1265 filter += from_utf8(formats.extension(format));
1268 FileDialog::Result result =
1269 dlg.open(from_utf8(initpath),
1270 FileFilterList(filter),
1273 if (result.first == FileDialog::Later)
1276 filename = to_utf8(result.second);
1278 // check selected filename
1279 if (filename.empty())
1280 message(_("Canceled."));
1283 if (filename.empty())
1286 // get absolute path of file
1287 FileName const fullname(makeAbsPath(filename));
1289 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1291 // Check if the document already is open
1292 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1295 if (!closeBuffer()) {
1296 message(_("Canceled."));
1301 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1303 // if the file exists already, and we didn't do
1304 // -i lyx thefile.lyx, warn
1305 if (lyxfile.exists() && fullname != lyxfile) {
1307 docstring text = bformat(_("The document %1$s already exists.\n\n"
1308 "Do you want to overwrite that document?"), displaypath);
1309 int const ret = Alert::prompt(_("Overwrite document?"),
1310 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1313 message(_("Canceled."));
1318 message(bformat(_("Importing %1$s..."), displaypath));
1319 ErrorList errorList;
1320 if (import(this, fullname, format, errorList))
1321 message(_("imported."));
1323 message(_("file not imported!"));
1325 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1329 void GuiView::newDocument(string const & filename, bool from_template)
1331 FileName initpath(lyxrc.document_path);
1332 Buffer * buf = buffer();
1334 FileName const trypath(buf->filePath());
1335 // If directory is writeable, use this as default.
1336 if (trypath.isDirWritable())
1340 string templatefile = from_template ?
1341 selectTemplateFile().absFilename() : string();
1343 if (filename.empty())
1344 b = newUnnamedFile(templatefile, initpath);
1346 b = newFile(filename, templatefile, true);
1350 // Ensure the cursor is correctly positionned on screen.
1351 view()->showCursor();
1355 void GuiView::insertLyXFile(docstring const & fname)
1357 BufferView * bv = view();
1362 FileName filename(to_utf8(fname));
1364 if (!filename.empty()) {
1365 bv->insertLyXFile(filename);
1369 // Launch a file browser
1371 string initpath = lyxrc.document_path;
1372 string const trypath = bv->buffer().filePath();
1373 // If directory is writeable, use this as default.
1374 if (FileName(trypath).isDirWritable())
1378 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1379 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1380 dlg.setButton2(_("Examples|#E#e"),
1381 from_utf8(addPath(package().system_support().absFilename(),
1384 FileDialog::Result result =
1385 dlg.open(from_utf8(initpath),
1386 FileFilterList(_("LyX Documents (*.lyx)")),
1389 if (result.first == FileDialog::Later)
1393 filename.set(to_utf8(result.second));
1395 // check selected filename
1396 if (filename.empty()) {
1397 // emit message signal.
1398 message(_("Canceled."));
1402 bv->insertLyXFile(filename);
1406 void GuiView::insertPlaintextFile(docstring const & fname,
1409 BufferView * bv = view();
1414 FileName filename(to_utf8(fname));
1416 if (!filename.empty()) {
1417 bv->insertPlaintextFile(filename, asParagraph);
1421 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1422 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1424 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1425 FileFilterList(), docstring());
1427 if (result.first == FileDialog::Later)
1431 filename.set(to_utf8(result.second));
1433 // check selected filename
1434 if (filename.empty()) {
1435 // emit message signal.
1436 message(_("Canceled."));
1440 bv->insertPlaintextFile(filename, asParagraph);
1444 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1446 FileName fname = b.fileName();
1447 FileName const oldname = fname;
1449 if (!newname.empty()) {
1451 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1453 // Switch to this Buffer.
1456 /// No argument? Ask user through dialog.
1458 FileDialog dlg(_("Choose a filename to save document as"),
1459 LFUN_BUFFER_WRITE_AS);
1460 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1461 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1463 if (!isLyXFilename(fname.absFilename()))
1464 fname.changeExtension(".lyx");
1466 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1468 FileDialog::Result result =
1469 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1471 from_utf8(fname.onlyFileName()));
1473 if (result.first == FileDialog::Later)
1476 fname.set(to_utf8(result.second));
1481 if (!isLyXFilename(fname.absFilename()))
1482 fname.changeExtension(".lyx");
1485 if (FileName(fname).exists()) {
1486 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1487 docstring text = bformat(_("The document %1$s already "
1488 "exists.\n\nDo you want to "
1489 "overwrite that document?"),
1491 int const ret = Alert::prompt(_("Overwrite document?"),
1492 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1495 case 1: return renameBuffer(b, docstring());
1496 case 2: return false;
1500 // Ok, change the name of the buffer
1501 b.setFileName(fname.absFilename());
1503 bool unnamed = b.isUnnamed();
1504 b.setUnnamed(false);
1505 b.saveCheckSum(fname);
1507 if (!saveBuffer(b)) {
1508 b.setFileName(oldname.absFilename());
1509 b.setUnnamed(unnamed);
1510 b.saveCheckSum(oldname);
1518 bool GuiView::saveBuffer(Buffer & b)
1521 return renameBuffer(b, docstring());
1524 LyX::ref().session().lastFiles().add(b.fileName());
1528 // Switch to this Buffer.
1531 // FIXME: we don't tell the user *WHY* the save failed !!
1532 docstring const file = makeDisplayPath(b.absFileName(), 30);
1533 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1534 "Do you want to rename the document and "
1535 "try again?"), file);
1536 int const ret = Alert::prompt(_("Rename and save?"),
1537 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1540 if (!renameBuffer(b, docstring()))
1549 return saveBuffer(b);
1553 bool GuiView::closeBuffer()
1555 Buffer * buf = buffer();
1556 return buf && closeBuffer(*buf);
1560 bool GuiView::closeBuffer(Buffer & buf)
1562 if (buf.isClean() || buf.paragraphs().empty()) {
1563 theBufferList().release(&buf);
1566 // Switch to this Buffer.
1571 if (buf.isUnnamed())
1572 file = from_utf8(buf.fileName().onlyFileName());
1574 file = buf.fileName().displayName(30);
1576 docstring const text = bformat(_("The document %1$s has unsaved changes."
1577 "\n\nDo you want to save the document or discard the changes?"), file);
1578 int const ret = Alert::prompt(_("Save changed document?"),
1579 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1583 if (!saveBuffer(buf))
1587 // if we crash after this we could
1588 // have no autosave file but I guess
1589 // this is really improbable (Jug)
1590 removeAutosaveFile(buf.absFileName());
1596 // save file names to .lyx/session
1597 // if master/slave are both open, do not save slave since it
1598 // will be automatically loaded when the master is loaded
1599 if (buf.masterBuffer() == &buf)
1600 LyX::ref().session().lastOpened().add(buf.fileName());
1602 theBufferList().release(&buf);
1607 bool GuiView::quitWriteAll()
1609 while (!theBufferList().empty()) {
1610 Buffer * b = theBufferList().first();
1611 if (!closeBuffer(*b))
1618 bool GuiView::dispatch(FuncRequest const & cmd)
1620 BufferView * bv = view();
1621 // By default we won't need any update.
1623 bv->cursor().updateFlags(Update::None);
1625 switch(cmd.action) {
1626 case LFUN_FILE_OPEN:
1627 openDocument(to_utf8(cmd.argument()));
1630 case LFUN_BUFFER_IMPORT:
1631 importDocument(to_utf8(cmd.argument()));
1634 case LFUN_BUFFER_SWITCH:
1635 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1638 case LFUN_BUFFER_NEXT:
1639 setBuffer(theBufferList().next(buffer()));
1642 case LFUN_BUFFER_PREVIOUS:
1643 setBuffer(theBufferList().previous(buffer()));
1646 case LFUN_COMMAND_EXECUTE: {
1647 bool const show_it = cmd.argument() != "off";
1648 d.toolbars_->showCommandBuffer(show_it);
1651 case LFUN_DROP_LAYOUTS_CHOICE:
1653 d.layout_->showPopup();
1656 case LFUN_MENU_OPEN:
1657 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1658 menu->exec(QCursor::pos());
1661 case LFUN_FILE_INSERT:
1662 insertLyXFile(cmd.argument());
1664 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1665 insertPlaintextFile(cmd.argument(), true);
1668 case LFUN_FILE_INSERT_PLAINTEXT:
1669 insertPlaintextFile(cmd.argument(), false);
1672 case LFUN_BUFFER_WRITE:
1674 saveBuffer(bv->buffer());
1677 case LFUN_BUFFER_WRITE_AS:
1679 renameBuffer(bv->buffer(), cmd.argument());
1682 case LFUN_BUFFER_WRITE_ALL: {
1683 Buffer * first = theBufferList().first();
1686 message(_("Saving all documents..."));
1687 // We cannot use a for loop as the buffer list cycles.
1693 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1694 b = theBufferList().next(b);
1695 } while (b != first);
1696 message(_("All documents saved."));
1700 case LFUN_TOOLBAR_TOGGLE: {
1701 string const name = cmd.getArg(0);
1702 bool const allowauto = cmd.getArg(1) == "allowauto";
1703 // it is possible to get current toolbar status like this,...
1704 // but I decide to obey the order of ToolbarBackend::flags
1705 // and disregard real toolbar status.
1706 // toolbars_->saveToolbarInfo();
1708 // toggle state on/off/auto
1709 d.toolbars_->toggleToolbarState(name, allowauto);
1713 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1715 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1719 if (tbi->flags & ToolbarInfo::ON)
1721 else if (tbi->flags & ToolbarInfo::OFF)
1723 else if (tbi->flags & ToolbarInfo::AUTO)
1726 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1727 _(tbi->gui_name), state));
1731 case LFUN_DIALOG_UPDATE: {
1732 string const name = to_utf8(cmd.argument());
1733 // Can only update a dialog connected to an existing inset
1734 Inset * inset = getOpenInset(name);
1736 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1737 inset->dispatch(view()->cursor(), fr);
1738 } else if (name == "paragraph") {
1739 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1740 } else if (name == "prefs") {
1741 updateDialog(name, string());
1746 case LFUN_DIALOG_TOGGLE: {
1747 if (isDialogVisible(cmd.getArg(0)))
1748 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1750 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1754 case LFUN_DIALOG_DISCONNECT_INSET:
1755 disconnectDialog(to_utf8(cmd.argument()));
1758 case LFUN_DIALOG_HIDE: {
1761 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1765 case LFUN_DIALOG_SHOW: {
1766 string const name = cmd.getArg(0);
1767 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1769 if (name == "character") {
1770 data = freefont2string();
1772 showDialog("character", data);
1773 } else if (name == "latexlog") {
1774 Buffer::LogType type;
1775 string const logfile = buffer()->logName(&type);
1777 case Buffer::latexlog:
1780 case Buffer::buildlog:
1784 data += Lexer::quoteString(logfile);
1785 showDialog("log", data);
1786 } else if (name == "vclog") {
1787 string const data = "vc " +
1788 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1789 showDialog("log", data);
1790 } else if (name == "symbols") {
1791 data = bv->cursor().getEncoding()->name();
1793 showDialog("symbols", data);
1795 showDialog(name, data);
1799 case LFUN_INSET_APPLY: {
1800 string const name = cmd.getArg(0);
1801 Inset * inset = getOpenInset(name);
1803 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1804 inset->dispatch(view()->cursor(), fr);
1806 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1812 case LFUN_UI_TOGGLE:
1814 // Make sure the keyboard focus stays in the work area.
1818 case LFUN_SPLIT_VIEW:
1819 if (Buffer * buf = buffer()) {
1820 string const orientation = cmd.getArg(0);
1821 d.splitter_->setOrientation(orientation == "vertical"
1822 ? Qt::Vertical : Qt::Horizontal);
1823 TabWorkArea * twa = addTabWorkArea();
1824 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1825 setCurrentWorkArea(wa);
1829 case LFUN_CLOSE_TAB_GROUP:
1830 if (TabWorkArea * twa = d.currentTabWorkArea())
1842 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1844 string const arg = cmd.getArg(0);
1845 if (arg == "scrollbar") {
1846 // hide() is of no help
1847 if (d.current_work_area_->verticalScrollBarPolicy() ==
1848 Qt::ScrollBarAlwaysOff)
1850 d.current_work_area_->setVerticalScrollBarPolicy(
1851 Qt::ScrollBarAsNeeded);
1853 d.current_work_area_->setVerticalScrollBarPolicy(
1854 Qt::ScrollBarAlwaysOff);
1857 if (arg == "statusbar") {
1858 statusBar()->setVisible(!statusBar()->isVisible());
1861 if (arg == "menubar") {
1862 menuBar()->setVisible(!menuBar()->isVisible());
1865 #if QT_VERSION >= 0x040300
1866 if (arg == "frame") {
1868 getContentsMargins(&l, &t, &r, &b);
1869 //are the frames in default state?
1871 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1872 setContentsMargins(-2, -2, -2, -2);
1874 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1875 setContentsMargins(0, 0, 0, 0);
1880 if (arg != "fullscreen") {
1881 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1885 if (lyxrc.full_screen_toolbars)
1886 d.toolbars_->toggleFullScreen(!isFullScreen());
1888 if (isFullScreen()) {
1889 for (int i = 0; i != d.splitter_->count(); ++i)
1890 d.tabWorkArea(i)->setFullScreen(false);
1891 #if QT_VERSION >= 0x040300
1892 setContentsMargins(0, 0, 0, 0);
1896 statusBar()->show();
1898 for (int i = 0; i != d.splitter_->count(); ++i)
1899 d.tabWorkArea(i)->setFullScreen(true);
1900 #if QT_VERSION >= 0x040300
1901 setContentsMargins(-2, -2, -2, -2);
1904 statusBar()->hide();
1910 Buffer const * GuiView::updateInset(Inset const * inset)
1912 if (!d.current_work_area_)
1916 d.current_work_area_->scheduleRedraw();
1918 return &d.current_work_area_->bufferView().buffer();
1922 void GuiView::restartCursor()
1924 /* When we move around, or type, it's nice to be able to see
1925 * the cursor immediately after the keypress.
1927 if (d.current_work_area_)
1928 d.current_work_area_->startBlinkingCursor();
1930 // Take this occasion to update the toobars and layout list.
1937 // This list should be kept in sync with the list of insets in
1938 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1939 // dialog should have the same name as the inset.
1941 char const * const dialognames[] = {
1942 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1943 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1944 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1945 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1946 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1948 #ifdef HAVE_LIBAIKSAURUS
1952 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1954 char const * const * const end_dialognames =
1955 dialognames + (sizeof(dialognames) / sizeof(char *));
1959 cmpCStr(char const * name) : name_(name) {}
1960 bool operator()(char const * other) {
1961 return strcmp(other, name_) == 0;
1968 bool isValidName(string const & name)
1970 return find_if(dialognames, end_dialognames,
1971 cmpCStr(name.c_str())) != end_dialognames;
1977 void GuiView::resetDialogs()
1979 // Make sure that no LFUN uses any LyXView.
1980 theLyXFunc().setLyXView(0);
1981 // FIXME: the "math panels" toolbar takes an awful lot of time to
1982 // initialise so we don't do that for the time being.
1983 //d.toolbars_->init();
1984 guiApp->menus().fillMenuBar(this);
1986 d.layout_->updateContents(true);
1987 // Now update controls with current buffer.
1988 theLyXFunc().setLyXView(this);
1993 Dialog * GuiView::find_or_build(string const & name)
1995 if (!isValidName(name))
1998 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2000 if (it != d.dialogs_.end())
2001 return it->second.get();
2003 Dialog * dialog = build(name);
2004 d.dialogs_[name].reset(dialog);
2005 if (lyxrc.allow_geometry_session)
2006 dialog->restoreSession();
2011 void GuiView::showDialog(string const & name, string const & data,
2018 Dialog * dialog = find_or_build(name);
2020 dialog->showData(data);
2022 d.open_insets_[name] = inset;
2028 bool GuiView::isDialogVisible(string const & name) const
2030 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2031 if (it == d.dialogs_.end())
2033 return it->second.get()->isVisibleView();
2037 void GuiView::hideDialog(string const & name, Inset * inset)
2039 // Don't send the signal if we are quitting, because on MSVC it is
2040 // destructed before the cut stack in CutAndPaste.cpp, and this method
2041 // is called from some inset destructor if the cut stack is not empty
2046 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2047 if (it == d.dialogs_.end())
2050 if (inset && inset != getOpenInset(name))
2053 Dialog * const dialog = it->second.get();
2054 if (dialog->isVisibleView())
2056 d.open_insets_[name] = 0;
2060 void GuiView::disconnectDialog(string const & name)
2062 if (!isValidName(name))
2065 if (d.open_insets_.find(name) != d.open_insets_.end())
2066 d.open_insets_[name] = 0;
2070 Inset * GuiView::getOpenInset(string const & name) const
2072 if (!isValidName(name))
2075 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2076 return it == d.open_insets_.end() ? 0 : it->second;
2080 void GuiView::hideAll() const
2082 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2083 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2085 for(; it != end; ++it)
2086 it->second->hideView();
2090 void GuiView::hideBufferDependent() const
2092 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2093 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2095 for(; it != end; ++it) {
2096 Dialog * dialog = it->second.get();
2097 if (dialog->isBufferDependent())
2103 void GuiView::updateBufferDependent(bool switched) const
2105 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2106 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2108 for(; it != end; ++it) {
2109 Dialog * dialog = it->second.get();
2110 if (!dialog->isVisibleView())
2112 if (switched && dialog->isBufferDependent()) {
2113 if (dialog->initialiseParams(""))
2114 dialog->updateView();
2118 // A bit clunky, but the dialog will request
2119 // that the kernel provides it with the necessary
2121 dialog->updateDialog();
2127 void GuiView::checkStatus()
2129 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2130 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2132 for(; it != end; ++it) {
2133 Dialog * const dialog = it->second.get();
2134 if (dialog && dialog->isVisibleView())
2135 dialog->checkStatus();
2141 // will be replaced by a proper factory...
2142 Dialog * createGuiAbout(GuiView & lv);
2143 Dialog * createGuiBibitem(GuiView & lv);
2144 Dialog * createGuiBibtex(GuiView & lv);
2145 Dialog * createGuiBox(GuiView & lv);
2146 Dialog * createGuiBranch(GuiView & lv);
2147 Dialog * createGuiChanges(GuiView & lv);
2148 Dialog * createGuiCharacter(GuiView & lv);
2149 Dialog * createGuiCitation(GuiView & lv);
2150 Dialog * createGuiDelimiter(GuiView & lv);
2151 Dialog * createGuiDocument(GuiView & lv);
2152 Dialog * createGuiErrorList(GuiView & lv);
2153 Dialog * createGuiERT(GuiView & lv);
2154 Dialog * createGuiExternal(GuiView & lv);
2155 Dialog * createGuiFloat(GuiView & lv);
2156 Dialog * createGuiGraphics(GuiView & lv);
2157 Dialog * createGuiInclude(GuiView & lv);
2158 Dialog * createGuiLabel(GuiView & lv);
2159 Dialog * createGuiListings(GuiView & lv);
2160 Dialog * createGuiLog(GuiView & lv);
2161 Dialog * createGuiMathMatrix(GuiView & lv);
2162 Dialog * createGuiNomenclature(GuiView & lv);
2163 Dialog * createGuiNote(GuiView & lv);
2164 Dialog * createGuiParagraph(GuiView & lv);
2165 Dialog * createGuiPreferences(GuiView & lv);
2166 Dialog * createGuiPrint(GuiView & lv);
2167 Dialog * createGuiRef(GuiView & lv);
2168 Dialog * createGuiSearch(GuiView & lv);
2169 Dialog * createGuiSendTo(GuiView & lv);
2170 Dialog * createGuiShowFile(GuiView & lv);
2171 Dialog * createGuiSpellchecker(GuiView & lv);
2172 Dialog * createGuiSymbols(GuiView & lv);
2173 Dialog * createGuiTabularCreate(GuiView & lv);
2174 Dialog * createGuiTabular(GuiView & lv);
2175 Dialog * createGuiTexInfo(GuiView & lv);
2176 Dialog * createGuiToc(GuiView & lv);
2177 Dialog * createGuiThesaurus(GuiView & lv);
2178 Dialog * createGuiHyperlink(GuiView & lv);
2179 Dialog * createGuiVSpace(GuiView & lv);
2180 Dialog * createGuiViewSource(GuiView & lv);
2181 Dialog * createGuiWrap(GuiView & lv);
2184 Dialog * GuiView::build(string const & name)
2186 BOOST_ASSERT(isValidName(name));
2188 if (name == "aboutlyx")
2189 return createGuiAbout(*this);
2190 if (name == "bibitem")
2191 return createGuiBibitem(*this);
2192 if (name == "bibtex")
2193 return createGuiBibtex(*this);
2195 return createGuiBox(*this);
2196 if (name == "branch")
2197 return createGuiBranch(*this);
2198 if (name == "changes")
2199 return createGuiChanges(*this);
2200 if (name == "character")
2201 return createGuiCharacter(*this);
2202 if (name == "citation")
2203 return createGuiCitation(*this);
2204 if (name == "document")
2205 return createGuiDocument(*this);
2206 if (name == "errorlist")
2207 return createGuiErrorList(*this);
2209 return createGuiERT(*this);
2210 if (name == "external")
2211 return createGuiExternal(*this);
2213 return createGuiShowFile(*this);
2214 if (name == "findreplace")
2215 return createGuiSearch(*this);
2216 if (name == "float")
2217 return createGuiFloat(*this);
2218 if (name == "graphics")
2219 return createGuiGraphics(*this);
2220 if (name == "include")
2221 return createGuiInclude(*this);
2222 if (name == "nomenclature")
2223 return createGuiNomenclature(*this);
2224 if (name == "label")
2225 return createGuiLabel(*this);
2227 return createGuiLog(*this);
2228 if (name == "view-source")
2229 return createGuiViewSource(*this);
2230 if (name == "mathdelimiter")
2231 return createGuiDelimiter(*this);
2232 if (name == "mathmatrix")
2233 return createGuiMathMatrix(*this);
2235 return createGuiNote(*this);
2236 if (name == "paragraph")
2237 return createGuiParagraph(*this);
2238 if (name == "prefs")
2239 return createGuiPreferences(*this);
2240 if (name == "print")
2241 return createGuiPrint(*this);
2243 return createGuiRef(*this);
2244 if (name == "sendto")
2245 return createGuiSendTo(*this);
2246 if (name == "spellchecker")
2247 return createGuiSpellchecker(*this);
2248 if (name == "symbols")
2249 return createGuiSymbols(*this);
2250 if (name == "tabular")
2251 return createGuiTabular(*this);
2252 if (name == "tabularcreate")
2253 return createGuiTabularCreate(*this);
2254 if (name == "texinfo")
2255 return createGuiTexInfo(*this);
2256 #ifdef HAVE_LIBAIKSAURUS
2257 if (name == "thesaurus")
2258 return createGuiThesaurus(*this);
2261 return createGuiToc(*this);
2263 return createGuiHyperlink(*this);
2264 if (name == "vspace")
2265 return createGuiVSpace(*this);
2267 return createGuiWrap(*this);
2268 if (name == "listings")
2269 return createGuiListings(*this);
2275 } // namespace frontend
2278 #include "GuiView_moc.cpp"