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 <boost/assert.hpp>
25 #include "GuiApplication.h"
26 #include "GuiWorkArea.h"
27 #include "GuiKeySymbol.h"
28 #include "GuiMenubar.h"
29 #include "GuiToolbar.h"
30 #include "GuiToolbars.h"
32 #include "qt_helpers.h"
34 #include "support/filetools.h"
35 #include "support/convert.h"
36 #include "support/lstrings.h"
37 #include "support/os.h"
39 #include "buffer_funcs.h"
41 #include "BufferList.h"
42 #include "BufferParams.h"
43 #include "BufferView.h"
46 #include "ErrorList.h"
47 #include "FuncRequest.h"
54 #include "MenuBackend.h"
55 #include "Paragraph.h"
56 #include "TextClass.h"
58 #include "ToolbarBackend.h"
61 #include "support/lstrings.h"
62 #include "support/filetools.h" // OnlyFilename()
63 #include "support/Timeout.h"
66 #include <QApplication>
67 #include <QCloseEvent>
68 #include <QDesktopWidget>
69 #include <QDragEnterEvent>
76 #include <QPushButton>
80 #include <QStackedWidget>
85 #include <boost/bind.hpp>
86 #include <boost/current_function.hpp>
88 #ifdef HAVE_SYS_TIME_H
89 # include <sys/time.h>
101 extern bool quitting;
105 using support::bformat;
106 using support::FileName;
107 using support::makeDisplayPath;
108 using support::onlyFilename;
112 int const statusbar_timer_value = 3000;
114 class BackgroundWidget : public QWidget
117 BackgroundWidget(QString const & file, QString const & text)
119 splash_ = new QPixmap(file);
121 lyxerr << "could not load splash screen: '" << fromqstr(file) << "'" << endl;
125 QPainter pain(splash_);
126 pain.setPen(QColor(255, 255, 0));
128 // The font used to display the version info
129 font.setStyleHint(QFont::SansSerif);
130 font.setWeight(QFont::Bold);
131 font.setPointSize(convert<int>(lyxrc.font_sizes[FONT_SIZE_LARGE]));
133 pain.drawText(260, 270, text);
136 void paintEvent(QPaintEvent *)
141 int x = (width() - splash_->width()) / 2;
142 int y = (height() - splash_->height()) / 2;
144 pain.drawPixmap(x, y, *splash_);
154 typedef boost::shared_ptr<Dialog> DialogPtr;
156 struct GuiView::GuiViewPrivate
159 : current_work_area_(0), posx_offset(0), posy_offset(0),
160 autosave_timeout_(new Timeout(5000)), quitting_by_menu_(false),
163 // hardcode here the platform specific icon size
164 smallIconSize = 14; // scaling problems
165 normalIconSize = 20; // ok, default
166 bigIconSize = 26; // better for some math icons
168 splitter_ = new QSplitter;
170 stack_widget_ = new QStackedWidget;
171 stack_widget_->addWidget(bg_widget_);
172 stack_widget_->addWidget(splitter_);
180 delete stack_widget_;
183 delete autosave_timeout_;
186 QMenu * toolBarPopup(GuiView * parent)
188 // FIXME: translation
189 QMenu * menu = new QMenu(parent);
190 QActionGroup * iconSizeGroup = new QActionGroup(parent);
192 QAction * smallIcons = new QAction(iconSizeGroup);
193 smallIcons->setText(qt_("Small-sized icons"));
194 smallIcons->setCheckable(true);
195 QObject::connect(smallIcons, SIGNAL(triggered()),
196 parent, SLOT(smallSizedIcons()));
197 menu->addAction(smallIcons);
199 QAction * normalIcons = new QAction(iconSizeGroup);
200 normalIcons->setText(qt_("Normal-sized icons"));
201 normalIcons->setCheckable(true);
202 QObject::connect(normalIcons, SIGNAL(triggered()),
203 parent, SLOT(normalSizedIcons()));
204 menu->addAction(normalIcons);
206 QAction * bigIcons = new QAction(iconSizeGroup);
207 bigIcons->setText(qt_("Big-sized icons"));
208 bigIcons->setCheckable(true);
209 QObject::connect(bigIcons, SIGNAL(triggered()),
210 parent, SLOT(bigSizedIcons()));
211 menu->addAction(bigIcons);
213 unsigned int cur = parent->iconSize().width();
214 if ( cur == parent->d.smallIconSize)
215 smallIcons->setChecked(true);
216 else if (cur == parent->d.normalIconSize)
217 normalIcons->setChecked(true);
218 else if (cur == parent->d.bigIconSize)
219 bigIcons->setChecked(true);
224 void initBackground()
226 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
227 /// The text to be written on top of the pixmap
228 QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
229 bg_widget_ = new BackgroundWidget(":/images/banner.png", text);
234 stack_widget_->setCurrentWidget(bg_widget_);
235 bg_widget_->setUpdatesEnabled(true);
238 TabWorkArea * tabWorkArea(int i)
240 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
243 TabWorkArea * currentTabWorkArea()
245 if (splitter_->count() == 1)
246 // The first TabWorkArea is always the first one, if any.
247 return tabWorkArea(0);
249 TabWorkArea * tab_widget = 0;
250 for (int i = 0; i != splitter_->count(); ++i) {
251 QWidget * w = splitter_->widget(i);
254 tab_widget = dynamic_cast<TabWorkArea *>(w);
266 GuiWorkArea * current_work_area_;
270 QSplitter * splitter_;
271 QStackedWidget * stack_widget_;
272 BackgroundWidget * bg_widget_;
274 GuiMenubar * menubar_;
276 GuiToolbars * toolbars_;
278 docstring current_layout;
281 std::map<std::string, Inset *> open_insets_;
284 std::map<std::string, DialogPtr> dialogs_;
286 unsigned int smallIconSize;
287 unsigned int normalIconSize;
288 unsigned int bigIconSize;
290 QTimer statusbar_timer_;
291 /// are we quitting by the menu?
292 bool quitting_by_menu_;
293 /// auto-saving of buffers
294 Timeout * const autosave_timeout_;
296 /// flag against a race condition due to multiclicks in Qt frontend,
302 GuiView::GuiView(int id)
303 : d(*new GuiViewPrivate), id_(id)
305 // GuiToolbars *must* be initialised before GuiMenubar.
306 d.toolbars_ = new GuiToolbars(*this);
307 d.menubar_ = new GuiMenubar(this, menubackend);
309 setCentralWidget(d.stack_widget_);
311 // Start autosave timer
312 if (lyxrc.autosave) {
313 d.autosave_timeout_->timeout.connect(boost::bind(&GuiView::autoSave, this));
314 d.autosave_timeout_->setTimeout(lyxrc.autosave * 1000);
315 d.autosave_timeout_->start();
317 QObject::connect(&d.statusbar_timer_, SIGNAL(timeout()),
318 this, SLOT(clearMessage()));
320 // Qt bug? signal lastWindowClosed does not work
321 setAttribute(Qt::WA_QuitOnClose, false);
322 setAttribute(Qt::WA_DeleteOnClose, true);
324 // assign an icon to main form. We do not do it under Qt/Mac,
325 // since the icon is provided in the application bundle.
326 setWindowIcon(QPixmap(":/images/lyx.png"));
330 setAcceptDrops(true);
332 statusBar()->setSizeGripEnabled(true);
334 // Forbid too small unresizable window because it can happen
335 // with some window manager under X11.
336 setMinimumSize(300, 200);
338 if (!lyxrc.allow_geometry_session)
339 // No session handling, default to a sane size.
340 setGeometry(50, 50, 690, 510);
342 // Now take care of session management.
344 QString const key = "view-" + QString::number(id_);
346 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
347 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
351 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
352 setGeometry(50, 50, 690, 510);
354 setIconSize(settings.value(key + "/icon_size").toSize());
364 void GuiView::close()
366 d.quitting_by_menu_ = true;
367 d.current_work_area_ = 0;
368 for (int i = 0; i != d.splitter_->count(); ++i) {
369 TabWorkArea * twa = d.tabWorkArea(i);
373 QMainWindow::close();
374 d.quitting_by_menu_ = false;
378 void GuiView::setFocus()
380 if (d.current_work_area_)
381 d.current_work_area_->setFocus();
387 QMenu* GuiView::createPopupMenu()
389 return d.toolBarPopup(this);
393 void GuiView::showEvent(QShowEvent * e)
395 LYXERR(Debug::GUI, "Passed Geometry "
396 << size().height() << "x" << size().width()
397 << "+" << pos().x() << "+" << pos().y());
399 if (d.splitter_->count() == 0)
400 // No work area, switch to the background widget.
403 QMainWindow::showEvent(e);
407 void GuiView::closeEvent(QCloseEvent * close_event)
409 // we may have been called through the close window button
410 // which bypasses the LFUN machinery.
411 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
412 if (!theBufferList().quitWriteAll()) {
413 close_event->ignore();
418 // Make sure that no LFUN use this close to be closed View.
419 theLyXFunc().setLyXView(0);
420 // Make sure the timer time out will not trigger a statusbar update.
421 d.statusbar_timer_.stop();
423 if (lyxrc.allow_geometry_session) {
425 QString const key = "view-" + QString::number(id_);
427 settings.setValue(key + "/pos", pos());
428 settings.setValue(key + "/size", size());
430 settings.setValue(key + "/geometry", saveGeometry());
432 settings.setValue(key + "/icon_size", iconSize());
433 d.toolbars_->saveToolbarInfo();
436 guiApp->unregisterView(id_);
437 if (guiApp->viewCount() > 0) {
438 // Just close the window and do nothing else if this is not the
440 close_event->accept();
446 // this is the place where we leave the frontend.
447 // it is the only point at which we start quitting.
448 close_event->accept();
449 // quit the event loop
454 void GuiView::dragEnterEvent(QDragEnterEvent * event)
456 if (event->mimeData()->hasUrls())
458 /// \todo Ask lyx-devel is this is enough:
459 /// if (event->mimeData()->hasFormat("text/plain"))
460 /// event->acceptProposedAction();
464 void GuiView::dropEvent(QDropEvent* event)
466 QList<QUrl> files = event->mimeData()->urls();
470 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
471 for (int i = 0; i != files.size(); ++i) {
472 string const file = support::os::internal_path(fromqstr(
473 files.at(i).toLocalFile()));
475 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
480 void GuiView::message(docstring const & str)
482 statusBar()->showMessage(toqstr(str));
483 d.statusbar_timer_.stop();
484 d.statusbar_timer_.start(statusbar_timer_value);
488 void GuiView::smallSizedIcons()
490 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
494 void GuiView::normalSizedIcons()
496 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
500 void GuiView::bigSizedIcons()
502 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
506 void GuiView::clearMessage()
510 theLyXFunc().setLyXView(this);
511 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
512 d.statusbar_timer_.stop();
516 void GuiView::updateWindowTitle(GuiWorkArea * wa)
518 if (wa != d.current_work_area_)
520 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
521 setWindowIconText(wa->windowIconText());
525 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
528 disconnectBufferView();
529 connectBufferView(wa->bufferView());
530 connectBuffer(wa->bufferView().buffer());
531 d.current_work_area_ = wa;
532 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
533 this, SLOT(updateWindowTitle(GuiWorkArea *)));
534 updateWindowTitle(wa);
537 // Buffer-dependent dialogs should be updated or
538 // hidden. This should go here because some dialogs (eg ToC)
539 // require bv_->text.
540 updateBufferDependent(true);
542 updateLayoutChoice(false);
547 void GuiView::updateStatusBar()
549 // let the user see the explicit message
550 if (d.statusbar_timer_.isActive())
553 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
557 bool GuiView::hasFocus() const
559 return qApp->activeWindow() == this;
563 bool GuiView::event(QEvent * e)
567 // Useful debug code:
568 //case QEvent::ActivationChange:
569 //case QEvent::WindowDeactivate:
570 //case QEvent::Paint:
571 //case QEvent::Enter:
572 //case QEvent::Leave:
573 //case QEvent::HoverEnter:
574 //case QEvent::HoverLeave:
575 //case QEvent::HoverMove:
576 //case QEvent::StatusTip:
577 //case QEvent::DragEnter:
578 //case QEvent::DragLeave:
582 case QEvent::WindowActivate: {
583 guiApp->setCurrentView(*this);
584 if (d.current_work_area_) {
585 BufferView & bv = d.current_work_area_->bufferView();
586 connectBufferView(bv);
587 connectBuffer(bv.buffer());
588 // The document structure, name and dialogs might have
589 // changed in another view.
590 updateBufferDependent(true);
592 setWindowTitle(qt_("LyX"));
593 setWindowIconText(qt_("LyX"));
595 return QMainWindow::event(e);
597 case QEvent::ShortcutOverride: {
598 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
599 if (!d.current_work_area_) {
600 theLyXFunc().setLyXView(this);
602 setKeySymbol(&sym, ke);
603 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
607 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
609 setKeySymbol(&sym, ke);
610 d.current_work_area_->processKeySym(sym, NoModifier);
616 return QMainWindow::event(e);
621 bool GuiView::focusNextPrevChild(bool /*next*/)
628 void GuiView::setBusy(bool yes)
630 if (d.current_work_area_) {
631 d.current_work_area_->setUpdatesEnabled(!yes);
633 d.current_work_area_->stopBlinkingCursor();
635 d.current_work_area_->startBlinkingCursor();
639 QApplication::setOverrideCursor(Qt::WaitCursor);
641 QApplication::restoreOverrideCursor();
645 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
647 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
649 if (tbinfo.flags & ToolbarInfo::TOP) {
651 addToolBarBreak(Qt::TopToolBarArea);
652 addToolBar(Qt::TopToolBarArea, toolBar);
655 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
656 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
657 #if (QT_VERSION >= 0x040202)
659 addToolBarBreak(Qt::BottomToolBarArea);
661 addToolBar(Qt::BottomToolBarArea, toolBar);
664 if (tbinfo.flags & ToolbarInfo::LEFT) {
665 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
666 #if (QT_VERSION >= 0x040202)
668 addToolBarBreak(Qt::LeftToolBarArea);
670 addToolBar(Qt::LeftToolBarArea, toolBar);
673 if (tbinfo.flags & ToolbarInfo::RIGHT) {
674 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
675 #if (QT_VERSION >= 0x040202)
677 addToolBarBreak(Qt::RightToolBarArea);
679 addToolBar(Qt::RightToolBarArea, toolBar);
682 // The following does not work so I cannot restore to exact toolbar location
684 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
685 toolBar->move(tbinfo.posx, tbinfo.posy);
692 GuiWorkArea * GuiView::workArea(Buffer & buffer)
694 for (int i = 0; i != d.splitter_->count(); ++i) {
695 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
703 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
705 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
706 wa->setUpdatesEnabled(false);
708 // Automatically create a TabWorkArea if there are none yet.
709 if (!d.splitter_->count())
712 TabWorkArea * tab_widget = d.currentTabWorkArea();
713 tab_widget->addTab(wa, wa->windowTitle());
714 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
715 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
717 wa->bufferView().updateMetrics();
719 // Hide tabbar if there's only one tab.
720 tab_widget->showBar(tab_widget->count() > 1);
725 void GuiView::addTabWorkArea()
727 TabWorkArea * twa = new TabWorkArea;
728 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
729 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
730 d.splitter_->addWidget(twa);
731 d.stack_widget_->setCurrentWidget(d.splitter_);
735 GuiWorkArea const * GuiView::currentWorkArea() const
737 return d.current_work_area_;
741 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
743 BOOST_ASSERT(work_area);
745 // Changing work area can result from opening a file so
746 // update the toc in any case.
749 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
750 d.current_work_area_ = wa;
751 for (int i = 0; i != d.splitter_->count(); ++i) {
752 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
758 void GuiView::removeWorkArea(GuiWorkArea * work_area)
760 BOOST_ASSERT(work_area);
761 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
762 if (gwa == d.current_work_area_) {
764 disconnectBufferView();
765 hideBufferDependent();
766 d.current_work_area_ = 0;
769 // removing a work area often results from closing a file so
770 // update the toc in any case.
773 for (int i = 0; i != d.splitter_->count(); ++i) {
774 TabWorkArea * twa = d.tabWorkArea(i);
775 if (!twa->removeWorkArea(gwa))
776 // Not found in this tab group.
779 // We found and removed the GuiWorkArea.
781 // No more WorkAreas in this tab group, so delete it.
786 if (d.current_work_area_)
787 // This means that we are not closing the current GuiWorkArea;
790 // Switch to the next GuiWorkArea in the found TabWorkArea.
791 d.current_work_area_ = twa->currentWorkArea();
795 if (d.splitter_->count() == 0)
796 // No more work area, switch to the background widget.
801 void GuiView::updateLayoutChoice(bool force)
803 // Don't show any layouts without a buffer
805 d.toolbars_->clearLayoutList();
809 // Update the layout display
810 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
811 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
814 docstring const & layout = d.current_work_area_->bufferView().cursor().
815 innerParagraph().layout()->name();
817 if (layout != d.current_layout) {
818 d.toolbars_->setLayout(layout);
819 d.current_layout = layout;
824 bool GuiView::isToolbarVisible(std::string const & id)
826 return d.toolbars_->visible(id);
829 void GuiView::updateToolbars()
831 if (d.current_work_area_) {
833 d.current_work_area_->bufferView().cursor().inMathed();
835 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
837 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
838 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
840 d.toolbars_->update(math, table, review);
842 d.toolbars_->update(false, false, false);
844 // update read-only status of open dialogs.
849 Buffer * GuiView::buffer()
851 if (d.current_work_area_)
852 return &d.current_work_area_->bufferView().buffer();
857 Buffer const * GuiView::buffer() const
859 if (d.current_work_area_)
860 return &d.current_work_area_->bufferView().buffer();
865 void GuiView::setBuffer(Buffer * newBuffer)
867 BOOST_ASSERT(newBuffer);
870 GuiWorkArea * wa = workArea(*newBuffer);
872 updateLabels(*newBuffer->masterBuffer());
873 wa = addWorkArea(*newBuffer);
875 //Disconnect the old buffer...there's no new one.
878 connectBuffer(*newBuffer);
879 connectBufferView(wa->bufferView());
880 setCurrentWorkArea(wa);
886 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
890 Buffer * newBuffer = checkAndLoadLyXFile(filename);
893 message(_("Document not loaded."));
899 GuiWorkArea * wa = workArea(*newBuffer);
901 wa = addWorkArea(*newBuffer);
903 // scroll to the position when the file was last closed
904 if (lyxrc.use_lastfilepos) {
905 LastFilePosSection::FilePos filepos =
906 LyX::ref().session().lastFilePos().load(filename);
907 // if successfully move to pit (returned par_id is not zero),
908 // update metrics and reset font
909 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
913 LyX::ref().session().lastFiles().add(filename);
920 void GuiView::connectBuffer(Buffer & buf)
922 buf.setGuiDelegate(this);
926 void GuiView::disconnectBuffer()
928 if (d.current_work_area_)
929 d.current_work_area_->bufferView().setGuiDelegate(0);
933 void GuiView::connectBufferView(BufferView & bv)
935 bv.setGuiDelegate(this);
939 void GuiView::disconnectBufferView()
941 if (d.current_work_area_)
942 d.current_work_area_->bufferView().setGuiDelegate(0);
946 void GuiView::errors(string const & error_type)
948 ErrorList & el = buffer()->errorList(error_type);
950 showDialog("errorlist", error_type);
954 void GuiView::updateDialog(string const & name, string const & data)
956 if (!isDialogVisible(name))
959 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
960 if (it == d.dialogs_.end())
963 Dialog * const dialog = it->second.get();
964 if (dialog->isVisibleView())
965 dialog->updateData(data);
969 BufferView * GuiView::view()
971 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
975 void GuiView::updateToc()
977 updateDialog("toc", "");
981 void GuiView::updateEmbeddedFiles()
983 updateDialog("embedding", "");
987 void GuiView::autoSave()
989 LYXERR(Debug::INFO, "Running autoSave()");
992 view()->buffer().autoSave();
996 void GuiView::resetAutosaveTimers()
999 d.autosave_timeout_->restart();
1003 void GuiView::dispatch(FuncRequest const & cmd)
1005 switch(cmd.action) {
1006 case LFUN_BUFFER_SWITCH:
1007 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1010 case LFUN_COMMAND_EXECUTE: {
1011 bool const show_it = cmd.argument() != "off";
1012 d.toolbars_->showCommandBuffer(show_it);
1015 case LFUN_DROP_LAYOUTS_CHOICE:
1016 d.toolbars_->openLayoutList();
1019 case LFUN_MENU_OPEN:
1020 d.menubar_->openByName(toqstr(cmd.argument()));
1023 case LFUN_TOOLBAR_TOGGLE: {
1024 string const name = cmd.getArg(0);
1025 bool const allowauto = cmd.getArg(1) == "allowauto";
1026 // it is possible to get current toolbar status like this,...
1027 // but I decide to obey the order of ToolbarBackend::flags
1028 // and disregard real toolbar status.
1029 // toolbars_->saveToolbarInfo();
1031 // toggle state on/off/auto
1032 d.toolbars_->toggleToolbarState(name, allowauto);
1036 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1038 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1042 if (tbi->flags & ToolbarInfo::ON)
1044 else if (tbi->flags & ToolbarInfo::OFF)
1046 else if (tbi->flags & ToolbarInfo::AUTO)
1049 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1050 _(tbi->gui_name), state));
1055 theLyXFunc().setLyXView(this);
1061 Buffer const * GuiView::updateInset(Inset const * inset)
1063 if (!d.current_work_area_)
1067 d.current_work_area_->scheduleRedraw();
1069 return &d.current_work_area_->bufferView().buffer();
1073 void GuiView::restartCursor()
1075 /* When we move around, or type, it's nice to be able to see
1076 * the cursor immediately after the keypress.
1078 if (d.current_work_area_)
1079 d.current_work_area_->startBlinkingCursor();
1083 Dialog * GuiView::find_or_build(string const & name)
1085 if (!isValidName(name))
1088 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1090 if (it != d.dialogs_.end())
1091 return it->second.get();
1093 d.dialogs_[name].reset(build(name));
1094 return d.dialogs_[name].get();
1098 void GuiView::showDialog(string const & name, string const & data,
1105 Dialog * dialog = find_or_build(name);
1107 dialog->showData(data);
1109 d.open_insets_[name] = inset;
1115 bool GuiView::isDialogVisible(string const & name) const
1117 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1118 if (it == d.dialogs_.end())
1120 return it->second.get()->isVisibleView();
1124 void GuiView::hideDialog(string const & name, Inset * inset)
1126 // Don't send the signal if we are quitting, because on MSVC it is
1127 // destructed before the cut stack in CutAndPaste.cpp, and this method
1128 // is called from some inset destructor if the cut stack is not empty
1133 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1134 if (it == d.dialogs_.end())
1137 if (inset && inset != getOpenInset(name))
1140 Dialog * const dialog = it->second.get();
1141 if (dialog->isVisibleView())
1143 d.open_insets_[name] = 0;
1147 void GuiView::disconnectDialog(string const & name)
1149 if (!isValidName(name))
1152 if (d.open_insets_.find(name) != d.open_insets_.end())
1153 d.open_insets_[name] = 0;
1157 Inset * GuiView::getOpenInset(string const & name) const
1159 if (!isValidName(name))
1162 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1163 return it == d.open_insets_.end() ? 0 : it->second;
1167 void GuiView::hideAll() const
1169 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1170 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1172 for(; it != end; ++it)
1177 void GuiView::hideBufferDependent() const
1179 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1180 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1182 for(; it != end; ++it) {
1183 Dialog * dialog = it->second.get();
1184 if (dialog->isBufferDependent())
1190 void GuiView::updateBufferDependent(bool switched) const
1192 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1193 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1195 for(; it != end; ++it) {
1196 Dialog * dialog = it->second.get();
1197 if (switched && dialog->isBufferDependent()) {
1198 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1199 dialog->updateView();
1203 // A bit clunky, but the dialog will request
1204 // that the kernel provides it with the necessary
1206 dialog->slotRestore();
1212 void GuiView::redrawDialog() const
1214 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1215 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1217 for(; it != end; ++it)
1218 it->second->redraw();
1222 void GuiView::checkStatus()
1224 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1225 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1227 for(; it != end; ++it) {
1228 Dialog * const dialog = it->second.get();
1229 if (dialog && dialog->isVisibleView())
1230 dialog->checkStatus();
1237 // This list should be kept in sync with the list of insets in
1238 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1239 // dialog should have the same name as the inset.
1241 char const * const dialognames[] = {
1242 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1243 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1244 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1245 "mathdelimiter", "mathmatrix", "note", "paragraph",
1246 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1248 #ifdef HAVE_LIBAIKSAURUS
1252 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1254 char const * const * const end_dialognames =
1255 dialognames + (sizeof(dialognames) / sizeof(char *));
1259 cmpCStr(char const * name) : name_(name) {}
1260 bool operator()(char const * other) {
1261 return strcmp(other, name_) == 0;
1270 // will be replaced by a proper factory...
1271 Dialog * createGuiAbout(LyXView & lv);
1272 Dialog * createGuiBibitem(LyXView & lv);
1273 Dialog * createGuiBibtex(LyXView & lv);
1274 Dialog * createGuiBox(LyXView & lv);
1275 Dialog * createGuiBranch(LyXView & lv);
1276 Dialog * createGuiChanges(LyXView & lv);
1277 Dialog * createGuiCharacter(LyXView & lv);
1278 Dialog * createGuiCitation(LyXView & lv);
1279 Dialog * createGuiDelimiter(LyXView & lv);
1280 Dialog * createGuiDocument(LyXView & lv);
1281 Dialog * createGuiErrorList(LyXView & lv);
1282 Dialog * createGuiERT(LyXView & lv);
1283 Dialog * createGuiExternal(LyXView & lv);
1284 Dialog * createGuiFloat(LyXView & lv);
1285 Dialog * createGuiGraphics(LyXView & lv);
1286 Dialog * createGuiInclude(LyXView & lv);
1287 Dialog * createGuiIndex(LyXView & lv);
1288 Dialog * createGuiLabel(LyXView & lv);
1289 Dialog * createGuiListings(LyXView & lv);
1290 Dialog * createGuiLog(LyXView & lv);
1291 Dialog * createGuiMathMatrix(LyXView & lv);
1292 Dialog * createGuiNomenclature(LyXView & lv);
1293 Dialog * createGuiNote(LyXView & lv);
1294 Dialog * createGuiParagraph(LyXView & lv);
1295 Dialog * createGuiPreferences(LyXView & lv);
1296 Dialog * createGuiPrint(LyXView & lv);
1297 Dialog * createGuiRef(LyXView & lv);
1298 Dialog * createGuiSearch(LyXView & lv);
1299 Dialog * createGuiSendTo(LyXView & lv);
1300 Dialog * createGuiShowFile(LyXView & lv);
1301 Dialog * createGuiSpellchecker(LyXView & lv);
1302 Dialog * createGuiTabularCreate(LyXView & lv);
1303 Dialog * createGuiTabular(LyXView & lv);
1304 Dialog * createGuiTexInfo(LyXView & lv);
1305 Dialog * createGuiToc(LyXView & lv);
1306 Dialog * createGuiThesaurus(LyXView & lv);
1307 Dialog * createGuiHyperlink(LyXView & lv);
1308 Dialog * createGuiVSpace(LyXView & lv);
1309 Dialog * createGuiViewSource(LyXView & lv);
1310 Dialog * createGuiWrap(LyXView & lv);
1313 bool GuiView::isValidName(string const & name) const
1315 return std::find_if(dialognames, end_dialognames,
1316 cmpCStr(name.c_str())) != end_dialognames;
1320 Dialog * GuiView::build(string const & name)
1322 BOOST_ASSERT(isValidName(name));
1324 if (name == "aboutlyx")
1325 return createGuiAbout(*this);
1326 if (name == "bibitem")
1327 return createGuiBibitem(*this);
1328 if (name == "bibtex")
1329 return createGuiBibtex(*this);
1331 return createGuiBox(*this);
1332 if (name == "branch")
1333 return createGuiBranch(*this);
1334 if (name == "changes")
1335 return createGuiChanges(*this);
1336 if (name == "character")
1337 return createGuiCharacter(*this);
1338 if (name == "citation")
1339 return createGuiCitation(*this);
1340 if (name == "document")
1341 return createGuiDocument(*this);
1342 if (name == "errorlist")
1343 return createGuiErrorList(*this);
1345 return createGuiERT(*this);
1346 if (name == "external")
1347 return createGuiExternal(*this);
1349 return createGuiShowFile(*this);
1350 if (name == "findreplace")
1351 return createGuiSearch(*this);
1352 if (name == "float")
1353 return createGuiFloat(*this);
1354 if (name == "graphics")
1355 return createGuiGraphics(*this);
1356 if (name == "include")
1357 return createGuiInclude(*this);
1358 if (name == "index")
1359 return createGuiIndex(*this);
1360 if (name == "nomenclature")
1361 return createGuiNomenclature(*this);
1362 if (name == "label")
1363 return createGuiLabel(*this);
1365 return createGuiLog(*this);
1366 if (name == "view-source")
1367 return createGuiViewSource(*this);
1368 if (name == "mathdelimiter")
1369 return createGuiDelimiter(*this);
1370 if (name == "mathmatrix")
1371 return createGuiMathMatrix(*this);
1373 return createGuiNote(*this);
1374 if (name == "paragraph")
1375 return createGuiParagraph(*this);
1376 if (name == "prefs")
1377 return createGuiPreferences(*this);
1378 if (name == "print")
1379 return createGuiPrint(*this);
1381 return createGuiRef(*this);
1382 if (name == "sendto")
1383 return createGuiSendTo(*this);
1384 if (name == "spellchecker")
1385 return createGuiSpellchecker(*this);
1386 if (name == "tabular")
1387 return createGuiTabular(*this);
1388 if (name == "tabularcreate")
1389 return createGuiTabularCreate(*this);
1390 if (name == "texinfo")
1391 return createGuiTexInfo(*this);
1392 #ifdef HAVE_LIBAIKSAURUS
1393 if (name == "thesaurus")
1394 return createGuiThesaurus(*this);
1397 return createGuiToc(*this);
1399 return createGuiHyperlink(*this);
1400 if (name == "vspace")
1401 return createGuiVSpace(*this);
1403 return createGuiWrap(*this);
1404 if (name == "listings")
1405 return createGuiListings(*this);
1411 } // namespace frontend
1414 #include "GuiView_moc.cpp"