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), autosave_timeout_(5000),
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 /// auto-saving of buffers
267 Timeout autosave_timeout_;
268 /// flag against a race condition due to multiclicks, see bug #1119
273 GuiView::GuiView(int id)
274 : d(*new GuiViewPrivate), id_(id)
276 // GuiToolbars *must* be initialised before the menu bar.
277 d.toolbars_ = new GuiToolbars(*this);
279 // Fill up the menu bar.
280 guiApp->menus().fillMenuBar(this);
282 setCentralWidget(d.stack_widget_);
284 // Start autosave timer
285 if (lyxrc.autosave) {
286 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
287 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
288 d.autosave_timeout_.start();
290 connect(&d.statusbar_timer_, SIGNAL(timeout()),
291 this, SLOT(clearMessage()));
293 // We don't want to keep the window in memory if it is closed.
294 setAttribute(Qt::WA_DeleteOnClose, true);
297 // assign an icon to main form. We do not do it under Qt/Mac,
298 // since the icon is provided in the application bundle.
299 setWindowIcon(QPixmap(":/images/lyx.png"));
303 setAcceptDrops(true);
305 statusBar()->setSizeGripEnabled(true);
307 // Forbid too small unresizable window because it can happen
308 // with some window manager under X11.
309 setMinimumSize(300, 200);
311 if (!lyxrc.allow_geometry_session)
312 // No session handling, default to a sane size.
313 setGeometry(50, 50, 690, 510);
315 // Now take care of session management.
317 QString const key = "view-" + QString::number(id_);
319 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
320 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
324 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
325 setGeometry(50, 50, 690, 510);
327 setIconSize(settings.value(key + "/icon_size").toSize());
337 void GuiView::setFocus()
339 if (d.current_work_area_)
340 d.current_work_area_->setFocus();
346 QMenu * GuiView::createPopupMenu()
348 return d.toolBarPopup(this);
352 void GuiView::showEvent(QShowEvent * e)
354 LYXERR(Debug::GUI, "Passed Geometry "
355 << size().height() << "x" << size().width()
356 << "+" << pos().x() << "+" << pos().y());
358 if (d.splitter_->count() == 0)
359 // No work area, switch to the background widget.
362 QMainWindow::showEvent(e);
366 void GuiView::closeEvent(QCloseEvent * close_event)
368 while (Buffer * b = buffer()) {
370 // This is a child document, just close the tab after saving
371 // but keep the file loaded.
372 if (!saveBuffer(*b)) {
373 close_event->ignore();
376 removeWorkArea(d.current_work_area_);
380 std::vector<int> const & ids = guiApp->viewIds();
381 for (size_type i = 0; i != ids.size(); ++i) {
384 if (guiApp->view(ids[i]).workArea(*b)) {
385 // FIXME 1: should we put an alert box here that the buffer
386 // is viewed elsewhere?
387 // FIXME 2: should we try to save this buffer in any case?
390 // This buffer is also opened in another view, so
391 // but close the associated work area nevertheless.
392 removeWorkArea(d.current_work_area_);
393 // but don't close it.
398 if (b && !closeBuffer(*b)) {
399 close_event->ignore();
404 // Make sure that no LFUN use this close to be closed View.
405 theLyXFunc().setLyXView(0);
407 // Save toolbars configuration
408 if (isFullScreen()) {
409 d.toolbars_->toggleFullScreen(!isFullScreen());
413 // Make sure the timer time out will not trigger a statusbar update.
414 d.statusbar_timer_.stop();
416 // Saving fullscreen requires additional tweaks in the toolbar code.
417 // It wouldn't also work under linux natively.
418 if (lyxrc.allow_geometry_session && !isFullScreen()) {
420 QString const key = "view-" + QString::number(id_);
422 settings.setValue(key + "/pos", pos());
423 settings.setValue(key + "/size", size());
425 settings.setValue(key + "/geometry", saveGeometry());
427 settings.setValue(key + "/icon_size", iconSize());
428 d.toolbars_->saveToolbarInfo();
429 // Now take care of all other dialogs:
430 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
431 for (; it!= d.dialogs_.end(); ++it)
432 it->second->saveSession();
435 guiApp->unregisterView(id_);
436 close_event->accept();
440 void GuiView::dragEnterEvent(QDragEnterEvent * event)
442 if (event->mimeData()->hasUrls())
444 /// \todo Ask lyx-devel is this is enough:
445 /// if (event->mimeData()->hasFormat("text/plain"))
446 /// event->acceptProposedAction();
450 void GuiView::dropEvent(QDropEvent* event)
452 QList<QUrl> files = event->mimeData()->urls();
456 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
457 for (int i = 0; i != files.size(); ++i) {
458 string const file = os::internal_path(fromqstr(
459 files.at(i).toLocalFile()));
461 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
466 void GuiView::message(docstring const & str)
468 if (ForkedProcess::iAmAChild())
471 statusBar()->showMessage(toqstr(str));
472 d.statusbar_timer_.stop();
473 d.statusbar_timer_.start(3000);
477 void GuiView::smallSizedIcons()
479 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
483 void GuiView::normalSizedIcons()
485 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
489 void GuiView::bigSizedIcons()
491 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
495 void GuiView::clearMessage()
499 theLyXFunc().setLyXView(this);
500 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
501 d.statusbar_timer_.stop();
505 void GuiView::updateWindowTitle(GuiWorkArea * wa)
507 if (wa != d.current_work_area_)
509 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
510 setWindowIconText(wa->windowIconText());
514 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
517 disconnectBufferView();
518 connectBufferView(wa->bufferView());
519 connectBuffer(wa->bufferView().buffer());
520 d.current_work_area_ = wa;
521 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
522 this, SLOT(updateWindowTitle(GuiWorkArea *)));
523 updateWindowTitle(wa);
526 // Buffer-dependent dialogs should be updated or
527 // hidden. This should go here because some dialogs (eg ToC)
528 // require bv_->text.
529 updateBufferDependent(true);
536 void GuiView::updateStatusBar()
538 // let the user see the explicit message
539 if (d.statusbar_timer_.isActive())
542 theLyXFunc().setLyXView(this);
543 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
547 bool GuiView::hasFocus() const
549 return qApp->activeWindow() == this;
553 bool GuiView::event(QEvent * e)
557 // Useful debug code:
558 //case QEvent::ActivationChange:
559 //case QEvent::WindowDeactivate:
560 //case QEvent::Paint:
561 //case QEvent::Enter:
562 //case QEvent::Leave:
563 //case QEvent::HoverEnter:
564 //case QEvent::HoverLeave:
565 //case QEvent::HoverMove:
566 //case QEvent::StatusTip:
567 //case QEvent::DragEnter:
568 //case QEvent::DragLeave:
572 case QEvent::WindowActivate: {
573 if (this == guiApp->currentView()) {
575 return QMainWindow::event(e);
577 guiApp->setCurrentView(*this);
578 if (d.current_work_area_) {
579 BufferView & bv = d.current_work_area_->bufferView();
580 connectBufferView(bv);
581 connectBuffer(bv.buffer());
582 // The document structure, name and dialogs might have
583 // changed in another view.
584 updateBufferDependent(true);
589 setWindowTitle(qt_("LyX"));
590 setWindowIconText(qt_("LyX"));
593 return QMainWindow::event(e);
596 case QEvent::ShortcutOverride: {
597 if (d.current_work_area_)
598 // Nothing special to do.
599 return QMainWindow::event(e);
601 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
603 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
605 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
606 || ke->key() == Qt::Key_Backtab)
607 return QMainWindow::event(e);
609 // Allow processing of shortcuts that are allowed even when no Buffer
611 theLyXFunc().setLyXView(this);
613 setKeySymbol(&sym, ke);
614 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
620 return QMainWindow::event(e);
625 bool GuiView::focusNextPrevChild(bool /*next*/)
632 void GuiView::setBusy(bool busy)
634 if (d.current_work_area_) {
635 d.current_work_area_->setUpdatesEnabled(!busy);
637 d.current_work_area_->stopBlinkingCursor();
639 d.current_work_area_->startBlinkingCursor();
643 QApplication::setOverrideCursor(Qt::WaitCursor);
645 QApplication::restoreOverrideCursor();
649 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
651 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
653 if (tbinfo.flags & ToolbarInfo::TOP) {
655 addToolBarBreak(Qt::TopToolBarArea);
656 addToolBar(Qt::TopToolBarArea, toolBar);
659 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
660 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
661 #if (QT_VERSION >= 0x040202)
663 addToolBarBreak(Qt::BottomToolBarArea);
665 addToolBar(Qt::BottomToolBarArea, toolBar);
668 if (tbinfo.flags & ToolbarInfo::LEFT) {
669 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
670 #if (QT_VERSION >= 0x040202)
672 addToolBarBreak(Qt::LeftToolBarArea);
674 addToolBar(Qt::LeftToolBarArea, toolBar);
677 if (tbinfo.flags & ToolbarInfo::RIGHT) {
678 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
679 #if (QT_VERSION >= 0x040202)
681 addToolBarBreak(Qt::RightToolBarArea);
683 addToolBar(Qt::RightToolBarArea, toolBar);
686 // The following does not work so I cannot restore to exact toolbar location
688 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
689 toolBar->move(tbinfo.posx, tbinfo.posy);
696 GuiWorkArea * GuiView::workArea(Buffer & buffer)
698 if (TabWorkArea * twa = d.currentTabWorkArea())
699 return twa->workArea(buffer);
704 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
706 // Automatically create a TabWorkArea if there are none yet.
707 TabWorkArea * tab_widget = d.splitter_->count()
708 ? d.currentTabWorkArea() : addTabWorkArea();
709 return tab_widget->addWorkArea(buffer, *this);
713 TabWorkArea * 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_);
724 GuiWorkArea const * GuiView::currentWorkArea() const
726 return d.current_work_area_;
730 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
734 // Changing work area can result from opening a file so
735 // update the toc in any case.
738 d.current_work_area_ = wa;
739 for (int i = 0; i != d.splitter_->count(); ++i) {
740 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
746 void GuiView::removeWorkArea(GuiWorkArea * wa)
749 if (wa == d.current_work_area_) {
751 disconnectBufferView();
752 hideBufferDependent();
753 d.current_work_area_ = 0;
756 for (int i = 0; i != d.splitter_->count(); ++i) {
757 TabWorkArea * twa = d.tabWorkArea(i);
758 if (!twa->removeWorkArea(wa))
759 // Not found in this tab group.
762 // We found and removed the GuiWorkArea.
764 // No more WorkAreas in this tab group, so delete it.
769 if (d.current_work_area_)
770 // This means that we are not closing the current GuiWorkArea;
773 // Switch to the next GuiWorkArea in the found TabWorkArea.
774 d.current_work_area_ = twa->currentWorkArea();
778 if (d.splitter_->count() == 0)
779 // No more work area, switch to the background widget.
784 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
790 void GuiView::updateLayoutList()
793 d.layout_->updateContents(false);
797 void GuiView::updateToolbars()
799 if (d.current_work_area_) {
801 d.current_work_area_->bufferView().cursor().inMathed();
803 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
805 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
806 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
807 bool const mathmacrotemplate =
808 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
810 d.toolbars_->update(math, table, review, mathmacrotemplate);
812 d.toolbars_->update(false, false, false, false);
814 // update read-only status of open dialogs.
819 Buffer * GuiView::buffer()
821 if (d.current_work_area_)
822 return &d.current_work_area_->bufferView().buffer();
827 Buffer const * GuiView::buffer() const
829 if (d.current_work_area_)
830 return &d.current_work_area_->bufferView().buffer();
835 void GuiView::setBuffer(Buffer * newBuffer)
837 BOOST_ASSERT(newBuffer);
840 GuiWorkArea * wa = workArea(*newBuffer);
842 updateLabels(*newBuffer->masterBuffer());
843 wa = addWorkArea(*newBuffer);
845 //Disconnect the old buffer...there's no new one.
848 connectBuffer(*newBuffer);
849 connectBufferView(wa->bufferView());
850 setCurrentWorkArea(wa);
856 void GuiView::connectBuffer(Buffer & buf)
858 buf.setGuiDelegate(this);
862 void GuiView::disconnectBuffer()
864 if (d.current_work_area_)
865 d.current_work_area_->bufferView().setGuiDelegate(0);
869 void GuiView::connectBufferView(BufferView & bv)
871 bv.setGuiDelegate(this);
875 void GuiView::disconnectBufferView()
877 if (d.current_work_area_)
878 d.current_work_area_->bufferView().setGuiDelegate(0);
882 void GuiView::errors(string const & error_type)
884 ErrorList & el = buffer()->errorList(error_type);
886 showDialog("errorlist", error_type);
890 void GuiView::updateDialog(string const & name, string const & data)
892 if (!isDialogVisible(name))
895 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
896 if (it == d.dialogs_.end())
899 Dialog * const dialog = it->second.get();
900 if (dialog->isVisibleView())
901 dialog->updateData(data);
905 BufferView * GuiView::view()
907 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
911 void GuiView::updateToc()
913 updateDialog("toc", "");
917 void GuiView::updateEmbeddedFiles()
919 updateDialog("embedding", "");
923 void GuiView::autoSave()
925 LYXERR(Debug::INFO, "Running autoSave()");
928 view()->buffer().autoSave();
932 void GuiView::resetAutosaveTimers()
935 d.autosave_timeout_.restart();
939 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
943 Buffer * buf = buffer();
945 /* In LyX/Mac, when a dialog is open, the menus of the
946 application can still be accessed without giving focus to
947 the main window. In this case, we want to disable the menu
948 entries that are buffer-related.
950 Note that this code is not perfect, as bug 1941 attests:
951 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
953 if (cmd.origin == FuncRequest::MENU && !hasFocus())
957 case LFUN_BUFFER_WRITE:
958 enable = buf && (buf->isUnnamed() || !buf->isClean());
961 case LFUN_BUFFER_WRITE_AS:
965 case LFUN_SPLIT_VIEW:
969 case LFUN_CLOSE_TAB_GROUP:
970 enable = d.currentTabWorkArea();
973 case LFUN_TOOLBAR_TOGGLE:
974 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
977 case LFUN_DIALOG_TOGGLE:
978 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
979 // fall through to set "enable"
980 case LFUN_DIALOG_SHOW: {
981 string const name = cmd.getArg(0);
983 enable = name == "aboutlyx"
984 || name == "file" //FIXME: should be removed.
986 || name == "texinfo";
987 else if (name == "print")
988 enable = buf->isExportable("dvi")
989 && lyxrc.print_command != "none";
990 else if (name == "character") {
994 InsetCode ic = view()->cursor().inset().lyxCode();
995 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
998 else if (name == "symbols") {
999 if (!view() || view()->cursor().inMathed())
1002 InsetCode ic = view()->cursor().inset().lyxCode();
1003 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1006 else if (name == "latexlog")
1007 enable = FileName(buf->logName()).isReadableFile();
1008 else if (name == "spellchecker")
1009 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1010 enable = !buf->isReadonly();
1014 else if (name == "vclog")
1015 enable = buf->lyxvc().inUse();
1019 case LFUN_DIALOG_UPDATE: {
1020 string const name = cmd.getArg(0);
1022 enable = name == "prefs";
1026 case LFUN_INSET_APPLY: {
1031 string const name = cmd.getArg(0);
1032 Inset * inset = getOpenInset(name);
1034 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1036 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1037 // Every inset is supposed to handle this
1038 BOOST_ASSERT(false);
1042 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1043 flag |= getStatus(fr);
1045 enable = flag.enabled();
1049 case LFUN_COMPLETION_INLINE:
1050 if (!d.current_work_area_
1051 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1055 case LFUN_COMPLETION_POPUP:
1056 if (!d.current_work_area_
1057 || !d.current_work_area_->completer().popupPossible(view()->cursor()))
1061 case LFUN_COMPLETION_COMPLETE:
1062 if (!d.current_work_area_
1063 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1075 flag.enabled(false);
1081 static FileName selectTemplateFile()
1083 FileDialog dlg(_("Select template file"));
1084 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1085 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1087 FileDialog::Result result =
1088 dlg.open(from_utf8(lyxrc.template_path),
1089 FileFilterList(_("LyX Documents (*.lyx)")),
1092 if (result.first == FileDialog::Later)
1094 if (result.second.empty())
1096 return FileName(to_utf8(result.second));
1100 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1104 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1107 message(_("Document not loaded."));
1112 setBuffer(newBuffer);
1114 // scroll to the position when the file was last closed
1115 if (lyxrc.use_lastfilepos) {
1116 LastFilePosSection::FilePos filepos =
1117 LyX::ref().session().lastFilePos().load(filename);
1118 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1122 LyX::ref().session().lastFiles().add(filename);
1129 void GuiView::openDocument(string const & fname)
1131 string initpath = lyxrc.document_path;
1134 string const trypath = buffer()->filePath();
1135 // If directory is writeable, use this as default.
1136 if (FileName(trypath).isDirWritable())
1142 if (fname.empty()) {
1143 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1144 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1145 dlg.setButton2(_("Examples|#E#e"),
1146 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1148 FileDialog::Result result =
1149 dlg.open(from_utf8(initpath),
1150 FileFilterList(_("LyX Documents (*.lyx)")),
1153 if (result.first == FileDialog::Later)
1156 filename = to_utf8(result.second);
1158 // check selected filename
1159 if (filename.empty()) {
1160 message(_("Canceled."));
1166 // get absolute path of file and add ".lyx" to the filename if
1168 FileName const fullname =
1169 fileSearch(string(), filename, "lyx", support::may_not_exist);
1170 if (!fullname.empty())
1171 filename = fullname.absFilename();
1173 // if the file doesn't exist, let the user create one
1174 if (!fullname.exists()) {
1175 // the user specifically chose this name. Believe him.
1176 Buffer * const b = newFile(filename, string(), true);
1182 docstring const disp_fn = makeDisplayPath(filename);
1183 message(bformat(_("Opening document %1$s..."), disp_fn));
1186 Buffer * buf = loadDocument(fullname);
1190 buf->errors("Parse");
1191 str2 = bformat(_("Document %1$s opened."), disp_fn);
1193 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1198 // FIXME: clean that
1199 static bool import(GuiView * lv, FileName const & filename,
1200 string const & format, ErrorList & errorList)
1202 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1204 string loader_format;
1205 vector<string> loaders = theConverters().loaders();
1206 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1207 for (vector<string>::const_iterator it = loaders.begin();
1208 it != loaders.end(); ++it) {
1209 if (!theConverters().isReachable(format, *it))
1212 string const tofile =
1213 changeExtension(filename.absFilename(),
1214 formats.extension(*it));
1215 if (!theConverters().convert(0, filename, FileName(tofile),
1216 filename, format, *it, errorList))
1218 loader_format = *it;
1221 if (loader_format.empty()) {
1222 frontend::Alert::error(_("Couldn't import file"),
1223 bformat(_("No information for importing the format %1$s."),
1224 formats.prettyName(format)));
1228 loader_format = format;
1230 if (loader_format == "lyx") {
1231 Buffer * buf = lv->loadDocument(lyxfile);
1236 buf->errors("Parse");
1238 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1242 bool as_paragraphs = loader_format == "textparagraph";
1243 string filename2 = (loader_format == format) ? filename.absFilename()
1244 : changeExtension(filename.absFilename(),
1245 formats.extension(loader_format));
1246 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1247 theLyXFunc().setLyXView(lv);
1248 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1255 void GuiView::importDocument(string const & argument)
1258 string filename = split(argument, format, ' ');
1260 LYXERR(Debug::INFO, format << " file: " << filename);
1262 // need user interaction
1263 if (filename.empty()) {
1264 string initpath = lyxrc.document_path;
1266 Buffer const * buf = buffer();
1268 string const trypath = buf->filePath();
1269 // If directory is writeable, use this as default.
1270 if (FileName(trypath).isDirWritable())
1274 docstring const text = bformat(_("Select %1$s file to import"),
1275 formats.prettyName(format));
1277 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1278 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1279 dlg.setButton2(_("Examples|#E#e"),
1280 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1282 docstring filter = formats.prettyName(format);
1285 filter += from_utf8(formats.extension(format));
1288 FileDialog::Result result =
1289 dlg.open(from_utf8(initpath),
1290 FileFilterList(filter),
1293 if (result.first == FileDialog::Later)
1296 filename = to_utf8(result.second);
1298 // check selected filename
1299 if (filename.empty())
1300 message(_("Canceled."));
1303 if (filename.empty())
1306 // get absolute path of file
1307 FileName const fullname(makeAbsPath(filename));
1309 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1311 // Check if the document already is open
1312 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1315 if (!closeBuffer()) {
1316 message(_("Canceled."));
1321 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1323 // if the file exists already, and we didn't do
1324 // -i lyx thefile.lyx, warn
1325 if (lyxfile.exists() && fullname != lyxfile) {
1327 docstring text = bformat(_("The document %1$s already exists.\n\n"
1328 "Do you want to overwrite that document?"), displaypath);
1329 int const ret = Alert::prompt(_("Overwrite document?"),
1330 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1333 message(_("Canceled."));
1338 message(bformat(_("Importing %1$s..."), displaypath));
1339 ErrorList errorList;
1340 if (import(this, fullname, format, errorList))
1341 message(_("imported."));
1343 message(_("file not imported!"));
1345 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1349 void GuiView::newDocument(string const & filename, bool from_template)
1351 FileName initpath(lyxrc.document_path);
1352 Buffer * buf = buffer();
1354 FileName const trypath(buf->filePath());
1355 // If directory is writeable, use this as default.
1356 if (trypath.isDirWritable())
1360 string templatefile = from_template ?
1361 selectTemplateFile().absFilename() : string();
1363 if (filename.empty())
1364 b = newUnnamedFile(templatefile, initpath);
1366 b = newFile(filename, templatefile, true);
1370 // Ensure the cursor is correctly positionned on screen.
1371 view()->showCursor();
1375 void GuiView::insertLyXFile(docstring const & fname)
1377 BufferView * bv = view();
1382 FileName filename(to_utf8(fname));
1384 if (!filename.empty()) {
1385 bv->insertLyXFile(filename);
1389 // Launch a file browser
1391 string initpath = lyxrc.document_path;
1392 string const trypath = bv->buffer().filePath();
1393 // If directory is writeable, use this as default.
1394 if (FileName(trypath).isDirWritable())
1398 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1399 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1400 dlg.setButton2(_("Examples|#E#e"),
1401 from_utf8(addPath(package().system_support().absFilename(),
1404 FileDialog::Result result =
1405 dlg.open(from_utf8(initpath),
1406 FileFilterList(_("LyX Documents (*.lyx)")),
1409 if (result.first == FileDialog::Later)
1413 filename.set(to_utf8(result.second));
1415 // check selected filename
1416 if (filename.empty()) {
1417 // emit message signal.
1418 message(_("Canceled."));
1422 bv->insertLyXFile(filename);
1426 void GuiView::insertPlaintextFile(docstring const & fname,
1429 BufferView * bv = view();
1434 FileName filename(to_utf8(fname));
1436 if (!filename.empty()) {
1437 bv->insertPlaintextFile(filename, asParagraph);
1441 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1442 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1444 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1445 FileFilterList(), docstring());
1447 if (result.first == FileDialog::Later)
1451 filename.set(to_utf8(result.second));
1453 // check selected filename
1454 if (filename.empty()) {
1455 // emit message signal.
1456 message(_("Canceled."));
1460 bv->insertPlaintextFile(filename, asParagraph);
1464 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1466 FileName fname = b.fileName();
1467 FileName const oldname = fname;
1469 if (!newname.empty()) {
1471 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1473 // Switch to this Buffer.
1476 /// No argument? Ask user through dialog.
1478 FileDialog dlg(_("Choose a filename to save document as"),
1479 LFUN_BUFFER_WRITE_AS);
1480 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1481 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1483 if (!isLyXFilename(fname.absFilename()))
1484 fname.changeExtension(".lyx");
1486 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1488 FileDialog::Result result =
1489 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1491 from_utf8(fname.onlyFileName()));
1493 if (result.first == FileDialog::Later)
1496 fname.set(to_utf8(result.second));
1501 if (!isLyXFilename(fname.absFilename()))
1502 fname.changeExtension(".lyx");
1505 if (FileName(fname).exists()) {
1506 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1507 docstring text = bformat(_("The document %1$s already "
1508 "exists.\n\nDo you want to "
1509 "overwrite that document?"),
1511 int const ret = Alert::prompt(_("Overwrite document?"),
1512 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1515 case 1: return renameBuffer(b, docstring());
1516 case 2: return false;
1520 // Ok, change the name of the buffer
1521 b.setFileName(fname.absFilename());
1523 bool unnamed = b.isUnnamed();
1524 b.setUnnamed(false);
1525 b.saveCheckSum(fname);
1527 if (!saveBuffer(b)) {
1528 b.setFileName(oldname.absFilename());
1529 b.setUnnamed(unnamed);
1530 b.saveCheckSum(oldname);
1538 bool GuiView::saveBuffer(Buffer & b)
1541 return renameBuffer(b, docstring());
1544 LyX::ref().session().lastFiles().add(b.fileName());
1548 // Switch to this Buffer.
1551 // FIXME: we don't tell the user *WHY* the save failed !!
1552 docstring const file = makeDisplayPath(b.absFileName(), 30);
1553 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1554 "Do you want to rename the document and "
1555 "try again?"), file);
1556 int const ret = Alert::prompt(_("Rename and save?"),
1557 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1560 if (!renameBuffer(b, docstring()))
1569 return saveBuffer(b);
1573 bool GuiView::closeBuffer()
1575 Buffer * buf = buffer();
1576 return buf && closeBuffer(*buf);
1580 bool GuiView::closeBuffer(Buffer & buf)
1582 // goto bookmark to update bookmark pit.
1583 //FIXME: we should update only the bookmarks related to this buffer!
1584 for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
1585 theLyXFunc().gotoBookmark(i+1, false, false);
1587 if (buf.isClean() || buf.paragraphs().empty()) {
1588 theBufferList().release(&buf);
1591 // Switch to this Buffer.
1596 if (buf.isUnnamed())
1597 file = from_utf8(buf.fileName().onlyFileName());
1599 file = buf.fileName().displayName(30);
1601 // Bring this window to top before asking questions.
1605 docstring const text = bformat(_("The document %1$s has unsaved changes."
1606 "\n\nDo you want to save the document or discard the changes?"), file);
1607 int const ret = Alert::prompt(_("Save changed document?"),
1608 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1612 if (!saveBuffer(buf))
1616 // if we crash after this we could
1617 // have no autosave file but I guess
1618 // this is really improbable (Jug)
1619 removeAutosaveFile(buf.absFileName());
1625 // save file names to .lyx/session
1626 // if master/slave are both open, do not save slave since it
1627 // will be automatically loaded when the master is loaded
1628 if (buf.masterBuffer() == &buf)
1629 LyX::ref().session().lastOpened().add(buf.fileName());
1631 theBufferList().release(&buf);
1636 bool GuiView::dispatch(FuncRequest const & cmd)
1638 BufferView * bv = view();
1639 // By default we won't need any update.
1641 bv->cursor().updateFlags(Update::None);
1643 switch(cmd.action) {
1644 case LFUN_FILE_OPEN:
1645 openDocument(to_utf8(cmd.argument()));
1648 case LFUN_BUFFER_IMPORT:
1649 importDocument(to_utf8(cmd.argument()));
1652 case LFUN_BUFFER_SWITCH:
1653 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1656 case LFUN_BUFFER_NEXT:
1657 setBuffer(theBufferList().next(buffer()));
1660 case LFUN_BUFFER_PREVIOUS:
1661 setBuffer(theBufferList().previous(buffer()));
1664 case LFUN_COMMAND_EXECUTE: {
1665 bool const show_it = cmd.argument() != "off";
1666 d.toolbars_->showCommandBuffer(show_it);
1669 case LFUN_DROP_LAYOUTS_CHOICE:
1671 d.layout_->showPopup();
1674 case LFUN_MENU_OPEN:
1675 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1676 menu->exec(QCursor::pos());
1679 case LFUN_FILE_INSERT:
1680 insertLyXFile(cmd.argument());
1682 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1683 insertPlaintextFile(cmd.argument(), true);
1686 case LFUN_FILE_INSERT_PLAINTEXT:
1687 insertPlaintextFile(cmd.argument(), false);
1690 case LFUN_BUFFER_WRITE:
1692 saveBuffer(bv->buffer());
1695 case LFUN_BUFFER_WRITE_AS:
1697 renameBuffer(bv->buffer(), cmd.argument());
1700 case LFUN_BUFFER_WRITE_ALL: {
1701 Buffer * first = theBufferList().first();
1704 message(_("Saving all documents..."));
1705 // We cannot use a for loop as the buffer list cycles.
1711 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1712 b = theBufferList().next(b);
1713 } while (b != first);
1714 message(_("All documents saved."));
1718 case LFUN_TOOLBAR_TOGGLE: {
1719 string const name = cmd.getArg(0);
1720 bool const allowauto = cmd.getArg(1) == "allowauto";
1721 // it is possible to get current toolbar status like this,...
1722 // but I decide to obey the order of ToolbarBackend::flags
1723 // and disregard real toolbar status.
1724 // toolbars_->saveToolbarInfo();
1726 // toggle state on/off/auto
1727 d.toolbars_->toggleToolbarState(name, allowauto);
1731 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1733 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1737 if (tbi->flags & ToolbarInfo::ON)
1739 else if (tbi->flags & ToolbarInfo::OFF)
1741 else if (tbi->flags & ToolbarInfo::AUTO)
1744 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1745 _(tbi->gui_name), state));
1749 case LFUN_DIALOG_UPDATE: {
1750 string const name = to_utf8(cmd.argument());
1751 // Can only update a dialog connected to an existing inset
1752 Inset * inset = getOpenInset(name);
1754 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1755 inset->dispatch(view()->cursor(), fr);
1756 } else if (name == "paragraph") {
1757 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1758 } else if (name == "prefs") {
1759 updateDialog(name, string());
1764 case LFUN_DIALOG_TOGGLE: {
1765 if (isDialogVisible(cmd.getArg(0)))
1766 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1768 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1772 case LFUN_DIALOG_DISCONNECT_INSET:
1773 disconnectDialog(to_utf8(cmd.argument()));
1776 case LFUN_DIALOG_HIDE: {
1777 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1781 case LFUN_DIALOG_SHOW: {
1782 string const name = cmd.getArg(0);
1783 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1785 if (name == "character") {
1786 data = freefont2string();
1788 showDialog("character", data);
1789 } else if (name == "latexlog") {
1790 Buffer::LogType type;
1791 string const logfile = buffer()->logName(&type);
1793 case Buffer::latexlog:
1796 case Buffer::buildlog:
1800 data += Lexer::quoteString(logfile);
1801 showDialog("log", data);
1802 } else if (name == "vclog") {
1803 string const data = "vc " +
1804 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1805 showDialog("log", data);
1806 } else if (name == "symbols") {
1807 data = bv->cursor().getEncoding()->name();
1809 showDialog("symbols", data);
1811 showDialog(name, data);
1815 case LFUN_INSET_APPLY: {
1816 string const name = cmd.getArg(0);
1817 Inset * inset = getOpenInset(name);
1819 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1820 inset->dispatch(view()->cursor(), fr);
1822 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1828 case LFUN_UI_TOGGLE:
1830 // Make sure the keyboard focus stays in the work area.
1834 case LFUN_COMPLETION_INLINE:
1835 if (d.current_work_area_)
1836 d.current_work_area_->completer().showInline();
1839 case LFUN_SPLIT_VIEW:
1840 if (Buffer * buf = buffer()) {
1841 string const orientation = cmd.getArg(0);
1842 d.splitter_->setOrientation(orientation == "vertical"
1843 ? Qt::Vertical : Qt::Horizontal);
1844 TabWorkArea * twa = addTabWorkArea();
1845 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1846 setCurrentWorkArea(wa);
1850 case LFUN_CLOSE_TAB_GROUP:
1851 if (TabWorkArea * twa = d.currentTabWorkArea()) {
1853 twa = d.currentTabWorkArea();
1854 // Switch to the next GuiWorkArea in the found TabWorkArea.
1855 d.current_work_area_ = twa? twa->currentWorkArea() : 0;
1856 if (d.splitter_->count() == 0)
1857 // No more work area, switch to the background widget.
1862 case LFUN_COMPLETION_POPUP:
1863 if (d.current_work_area_)
1864 d.current_work_area_->completer().showPopup();
1868 case LFUN_COMPLETION_COMPLETE:
1869 if (d.current_work_area_)
1870 d.current_work_area_->completer().tab();
1881 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1883 string const arg = cmd.getArg(0);
1884 if (arg == "scrollbar") {
1885 // hide() is of no help
1886 if (d.current_work_area_->verticalScrollBarPolicy() ==
1887 Qt::ScrollBarAlwaysOff)
1889 d.current_work_area_->setVerticalScrollBarPolicy(
1890 Qt::ScrollBarAsNeeded);
1892 d.current_work_area_->setVerticalScrollBarPolicy(
1893 Qt::ScrollBarAlwaysOff);
1896 if (arg == "statusbar") {
1897 statusBar()->setVisible(!statusBar()->isVisible());
1900 if (arg == "menubar") {
1901 menuBar()->setVisible(!menuBar()->isVisible());
1904 #if QT_VERSION >= 0x040300
1905 if (arg == "frame") {
1907 getContentsMargins(&l, &t, &r, &b);
1908 //are the frames in default state?
1910 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1911 setContentsMargins(-2, -2, -2, -2);
1913 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1914 setContentsMargins(0, 0, 0, 0);
1919 if (arg != "fullscreen") {
1920 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1924 if (lyxrc.full_screen_toolbars)
1925 d.toolbars_->toggleFullScreen(!isFullScreen());
1927 if (isFullScreen()) {
1928 for (int i = 0; i != d.splitter_->count(); ++i)
1929 d.tabWorkArea(i)->setFullScreen(false);
1930 #if QT_VERSION >= 0x040300
1931 setContentsMargins(0, 0, 0, 0);
1935 statusBar()->show();
1937 for (int i = 0; i != d.splitter_->count(); ++i)
1938 d.tabWorkArea(i)->setFullScreen(true);
1939 #if QT_VERSION >= 0x040300
1940 setContentsMargins(-2, -2, -2, -2);
1943 statusBar()->hide();
1949 Buffer const * GuiView::updateInset(Inset const * inset)
1951 if (!d.current_work_area_)
1955 d.current_work_area_->scheduleRedraw();
1957 return &d.current_work_area_->bufferView().buffer();
1961 void GuiView::restartCursor()
1963 /* When we move around, or type, it's nice to be able to see
1964 * the cursor immediately after the keypress.
1966 if (d.current_work_area_)
1967 d.current_work_area_->startBlinkingCursor();
1969 // Take this occasion to update the other GUI elements.
1976 void GuiView::updateCompletion(Cursor & cur, bool start, bool keep)
1978 if (d.current_work_area_)
1979 d.current_work_area_->completer().updateVisibility(cur, start, keep);
1984 // This list should be kept in sync with the list of insets in
1985 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1986 // dialog should have the same name as the inset.
1988 char const * const dialognames[] = {
1989 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1990 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1991 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1992 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
1993 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
1995 #ifdef HAVE_LIBAIKSAURUS
1999 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
2001 char const * const * const end_dialognames =
2002 dialognames + (sizeof(dialognames) / sizeof(char *));
2006 cmpCStr(char const * name) : name_(name) {}
2007 bool operator()(char const * other) {
2008 return strcmp(other, name_) == 0;
2015 bool isValidName(string const & name)
2017 return find_if(dialognames, end_dialognames,
2018 cmpCStr(name.c_str())) != end_dialognames;
2024 void GuiView::resetDialogs()
2026 // Make sure that no LFUN uses any LyXView.
2027 theLyXFunc().setLyXView(0);
2028 // FIXME: the "math panels" toolbar takes an awful lot of time to
2029 // initialise so we don't do that for the time being.
2030 //d.toolbars_->init();
2031 guiApp->menus().fillMenuBar(this);
2033 d.layout_->updateContents(true);
2034 // Now update controls with current buffer.
2035 theLyXFunc().setLyXView(this);
2040 Dialog * GuiView::find_or_build(string const & name)
2042 if (!isValidName(name))
2045 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2047 if (it != d.dialogs_.end())
2048 return it->second.get();
2050 Dialog * dialog = build(name);
2051 d.dialogs_[name].reset(dialog);
2052 if (lyxrc.allow_geometry_session)
2053 dialog->restoreSession();
2058 void GuiView::showDialog(string const & name, string const & data,
2065 Dialog * dialog = find_or_build(name);
2067 dialog->showData(data);
2069 d.open_insets_[name] = inset;
2075 bool GuiView::isDialogVisible(string const & name) const
2077 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2078 if (it == d.dialogs_.end())
2080 return it->second.get()->isVisibleView();
2084 void GuiView::hideDialog(string const & name, Inset * inset)
2086 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2087 if (it == d.dialogs_.end())
2090 if (inset && inset != getOpenInset(name))
2093 Dialog * const dialog = it->second.get();
2094 if (dialog->isVisibleView())
2096 d.open_insets_[name] = 0;
2100 void GuiView::disconnectDialog(string const & name)
2102 if (!isValidName(name))
2105 if (d.open_insets_.find(name) != d.open_insets_.end())
2106 d.open_insets_[name] = 0;
2110 Inset * GuiView::getOpenInset(string const & name) const
2112 if (!isValidName(name))
2115 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2116 return it == d.open_insets_.end() ? 0 : it->second;
2120 void GuiView::hideAll() const
2122 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2123 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2125 for(; it != end; ++it)
2126 it->second->hideView();
2130 void GuiView::hideBufferDependent() const
2132 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2133 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2135 for(; it != end; ++it) {
2136 Dialog * dialog = it->second.get();
2137 if (dialog->isBufferDependent())
2143 void GuiView::updateBufferDependent(bool switched) const
2145 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2146 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2148 for(; it != end; ++it) {
2149 Dialog * dialog = it->second.get();
2150 if (!dialog->isVisibleView())
2152 if (switched && dialog->isBufferDependent()) {
2153 if (dialog->initialiseParams(""))
2154 dialog->updateView();
2158 // A bit clunky, but the dialog will request
2159 // that the kernel provides it with the necessary
2161 dialog->updateDialog();
2167 void GuiView::checkStatus()
2169 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2170 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2172 for(; it != end; ++it) {
2173 Dialog * const dialog = it->second.get();
2174 if (dialog && dialog->isVisibleView())
2175 dialog->checkStatus();
2181 // will be replaced by a proper factory...
2182 Dialog * createGuiAbout(GuiView & lv);
2183 Dialog * createGuiBibitem(GuiView & lv);
2184 Dialog * createGuiBibtex(GuiView & lv);
2185 Dialog * createGuiBox(GuiView & lv);
2186 Dialog * createGuiBranch(GuiView & lv);
2187 Dialog * createGuiChanges(GuiView & lv);
2188 Dialog * createGuiCharacter(GuiView & lv);
2189 Dialog * createGuiCitation(GuiView & lv);
2190 Dialog * createGuiDelimiter(GuiView & lv);
2191 Dialog * createGuiDocument(GuiView & lv);
2192 Dialog * createGuiErrorList(GuiView & lv);
2193 Dialog * createGuiERT(GuiView & lv);
2194 Dialog * createGuiExternal(GuiView & lv);
2195 Dialog * createGuiFloat(GuiView & lv);
2196 Dialog * createGuiGraphics(GuiView & lv);
2197 Dialog * createGuiInclude(GuiView & lv);
2198 Dialog * createGuiLabel(GuiView & lv);
2199 Dialog * createGuiListings(GuiView & lv);
2200 Dialog * createGuiLog(GuiView & lv);
2201 Dialog * createGuiMathMatrix(GuiView & lv);
2202 Dialog * createGuiNomenclature(GuiView & lv);
2203 Dialog * createGuiNote(GuiView & lv);
2204 Dialog * createGuiParagraph(GuiView & lv);
2205 Dialog * createGuiPreferences(GuiView & lv);
2206 Dialog * createGuiPrint(GuiView & lv);
2207 Dialog * createGuiRef(GuiView & lv);
2208 Dialog * createGuiSearch(GuiView & lv);
2209 Dialog * createGuiSendTo(GuiView & lv);
2210 Dialog * createGuiShowFile(GuiView & lv);
2211 Dialog * createGuiSpellchecker(GuiView & lv);
2212 Dialog * createGuiSymbols(GuiView & lv);
2213 Dialog * createGuiTabularCreate(GuiView & lv);
2214 Dialog * createGuiTabular(GuiView & lv);
2215 Dialog * createGuiTexInfo(GuiView & lv);
2216 Dialog * createGuiToc(GuiView & lv);
2217 Dialog * createGuiThesaurus(GuiView & lv);
2218 Dialog * createGuiHyperlink(GuiView & lv);
2219 Dialog * createGuiVSpace(GuiView & lv);
2220 Dialog * createGuiViewSource(GuiView & lv);
2221 Dialog * createGuiWrap(GuiView & lv);
2224 Dialog * GuiView::build(string const & name)
2226 BOOST_ASSERT(isValidName(name));
2228 if (name == "aboutlyx")
2229 return createGuiAbout(*this);
2230 if (name == "bibitem")
2231 return createGuiBibitem(*this);
2232 if (name == "bibtex")
2233 return createGuiBibtex(*this);
2235 return createGuiBox(*this);
2236 if (name == "branch")
2237 return createGuiBranch(*this);
2238 if (name == "changes")
2239 return createGuiChanges(*this);
2240 if (name == "character")
2241 return createGuiCharacter(*this);
2242 if (name == "citation")
2243 return createGuiCitation(*this);
2244 if (name == "document")
2245 return createGuiDocument(*this);
2246 if (name == "errorlist")
2247 return createGuiErrorList(*this);
2249 return createGuiERT(*this);
2250 if (name == "external")
2251 return createGuiExternal(*this);
2253 return createGuiShowFile(*this);
2254 if (name == "findreplace")
2255 return createGuiSearch(*this);
2256 if (name == "float")
2257 return createGuiFloat(*this);
2258 if (name == "graphics")
2259 return createGuiGraphics(*this);
2260 if (name == "include")
2261 return createGuiInclude(*this);
2262 if (name == "nomenclature")
2263 return createGuiNomenclature(*this);
2264 if (name == "label")
2265 return createGuiLabel(*this);
2267 return createGuiLog(*this);
2268 if (name == "view-source")
2269 return createGuiViewSource(*this);
2270 if (name == "mathdelimiter")
2271 return createGuiDelimiter(*this);
2272 if (name == "mathmatrix")
2273 return createGuiMathMatrix(*this);
2275 return createGuiNote(*this);
2276 if (name == "paragraph")
2277 return createGuiParagraph(*this);
2278 if (name == "prefs")
2279 return createGuiPreferences(*this);
2280 if (name == "print")
2281 return createGuiPrint(*this);
2283 return createGuiRef(*this);
2284 if (name == "sendto")
2285 return createGuiSendTo(*this);
2286 if (name == "spellchecker")
2287 return createGuiSpellchecker(*this);
2288 if (name == "symbols")
2289 return createGuiSymbols(*this);
2290 if (name == "tabular")
2291 return createGuiTabular(*this);
2292 if (name == "tabularcreate")
2293 return createGuiTabularCreate(*this);
2294 if (name == "texinfo")
2295 return createGuiTexInfo(*this);
2296 #ifdef HAVE_LIBAIKSAURUS
2297 if (name == "thesaurus")
2298 return createGuiThesaurus(*this);
2301 return createGuiToc(*this);
2303 return createGuiHyperlink(*this);
2304 if (name == "vspace")
2305 return createGuiVSpace(*this);
2307 return createGuiWrap(*this);
2308 if (name == "listings")
2309 return createGuiListings(*this);
2315 } // namespace frontend
2318 #include "GuiView_moc.cpp"