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)
166 delete stack_widget_;
171 unsigned int smallIconSize;
172 unsigned int normalIconSize;
173 unsigned int bigIconSize;
174 // static needed by "New Window"
175 static unsigned int lastIconSize;
177 QMenu * toolBarPopup(GuiView * parent)
179 // FIXME: translation
180 QMenu * menu = new QMenu(parent);
181 QActionGroup * iconSizeGroup = new QActionGroup(parent);
183 QAction * smallIcons = new QAction(iconSizeGroup);
184 smallIcons->setText(qt_("Small-sized icons"));
185 smallIcons->setCheckable(true);
186 QObject::connect(smallIcons, SIGNAL(triggered()),
187 parent, SLOT(smallSizedIcons()));
188 menu->addAction(smallIcons);
190 QAction * normalIcons = new QAction(iconSizeGroup);
191 normalIcons->setText(qt_("Normal-sized icons"));
192 normalIcons->setCheckable(true);
193 QObject::connect(normalIcons, SIGNAL(triggered()),
194 parent, SLOT(normalSizedIcons()));
195 menu->addAction(normalIcons);
197 QAction * bigIcons = new QAction(iconSizeGroup);
198 bigIcons->setText(qt_("Big-sized icons"));
199 bigIcons->setCheckable(true);
200 QObject::connect(bigIcons, SIGNAL(triggered()),
201 parent, SLOT(bigSizedIcons()));
202 menu->addAction(bigIcons);
204 unsigned int cur = parent->iconSize().width();
205 if ( cur == parent->d.smallIconSize)
206 smallIcons->setChecked(true);
207 else if (cur == parent->d.normalIconSize)
208 normalIcons->setChecked(true);
209 else if (cur == parent->d.bigIconSize)
210 bigIcons->setChecked(true);
215 void initBackground()
217 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
218 /// The text to be written on top of the pixmap
219 QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
220 bg_widget_ = new BackgroundWidget(":/images/banner.png", text);
225 stack_widget_->setCurrentWidget(bg_widget_);
226 bg_widget_->setUpdatesEnabled(true);
229 TabWorkArea * tabWorkArea(int i)
231 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
234 TabWorkArea * currentTabWorkArea()
236 if (splitter_->count() == 1)
237 // The first TabWorkArea is always the first one, if any.
238 return tabWorkArea(0);
240 TabWorkArea * tab_widget = 0;
241 for (int i = 0; i != splitter_->count(); ++i) {
242 QWidget * w = splitter_->widget(i);
245 tab_widget = dynamic_cast<TabWorkArea *>(w);
257 GuiWorkArea * current_work_area_;
261 QSplitter * splitter_;
262 QStackedWidget * stack_widget_;
263 BackgroundWidget * bg_widget_;
265 GuiMenubar * menubar_;
267 GuiToolbars * toolbars_;
269 docstring current_layout;
272 std::map<std::string, Inset *> open_insets_;
275 std::map<std::string, DialogPtr> dialogs_;
277 /// flag against a race condition due to multiclicks
283 unsigned int GuiView::GuiViewPrivate::lastIconSize = 0;
286 GuiView::GuiView(int id)
287 : QMainWindow(), LyXView(id),
288 d(*new GuiViewPrivate),
289 quitting_by_menu_(false),
290 autosave_timeout_(new Timeout(5000)),
293 // Start autosave timer
294 if (lyxrc.autosave) {
295 autosave_timeout_->timeout.connect(boost::bind(&GuiView::autoSave, this));
296 autosave_timeout_->setTimeout(lyxrc.autosave * 1000);
297 autosave_timeout_->start();
300 // Qt bug? signal lastWindowClosed does not work
301 setAttribute(Qt::WA_QuitOnClose, false);
302 setAttribute(Qt::WA_DeleteOnClose, true);
304 // hardcode here the platform specific icon size
305 d.smallIconSize = 14; // scaling problems
306 d.normalIconSize = 20; // ok, default
307 d.bigIconSize = 26; // better for some math icons
310 // assign an icon to main form. We do not do it under Qt/Mac,
311 // since the icon is provided in the application bundle.
312 setWindowIcon(QPixmap(":/images/lyx.png"));
315 d.splitter_ = new QSplitter;
318 LYXERR(Debug::GUI, "stack widget!");
319 d.stack_widget_ = new QStackedWidget;
320 d.stack_widget_->addWidget(d.bg_widget_);
321 d.stack_widget_->addWidget(d.splitter_);
322 setCentralWidget(d.stack_widget_);
325 setAcceptDrops(true);
331 delete autosave_timeout_;
336 void GuiView::close()
338 quitting_by_menu_ = true;
339 d.current_work_area_ = 0;
340 for (int i = 0; i != d.splitter_->count(); ++i) {
341 TabWorkArea * twa = d.tabWorkArea(i);
345 QMainWindow::close();
346 quitting_by_menu_ = false;
350 void GuiView::setFocus()
352 if (d.current_work_area_)
353 d.current_work_area_->setFocus();
359 QMenu* GuiView::createPopupMenu()
361 return d.toolBarPopup(this);
367 setMinimumSize(300, 200);
368 // GuiToolbars *must* be initialised before GuiMenubar.
369 d.toolbars_ = new GuiToolbars(*this);
370 // FIXME: GuiToolbars::init() cannot be integrated in the ctor
371 // because LyXFunc::getStatus() needs a properly initialized
372 // GuiToolbars object (for LFUN_TOOLBAR_TOGGLE).
374 d.menubar_ = new GuiMenubar(this, menubackend);
376 statusBar()->setSizeGripEnabled(true);
378 QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
379 this, SLOT(clearMessage()));
383 if (!lyxrc.allow_geometry_session)
384 setGeometry(50, 50, 690, 510);
386 // Now take care of session management.
388 QString const key = "view-" + QString::number(id());
390 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
391 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
395 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
396 setGeometry(50, 50, 690, 510);
398 setIconSize(settings.value(key + "/icon_size").toSize());
402 void GuiView::showEvent(QShowEvent * e)
404 LYXERR(Debug::GUI, "Passed Geometry "
405 << size().height() << "x" << size().width()
406 << "+" << pos().x() << "+" << pos().y());
408 if (d.splitter_->count() == 0)
409 // No work area, switch to the background widget.
412 QMainWindow::showEvent(e);
416 void GuiView::closeEvent(QCloseEvent * close_event)
418 // we may have been called through the close window button
419 // which bypasses the LFUN machinery.
420 if (!quitting_by_menu_ && guiApp->viewCount() == 1) {
421 if (!theBufferList().quitWriteAll()) {
422 close_event->ignore();
427 // Make sure that no LFUN use this close to be closed View.
428 theLyXFunc().setLyXView(0);
429 // Make sure the timer time out will not trigger a statusbar update.
430 statusbar_timer_.stop();
432 if (lyxrc.allow_geometry_session) {
434 QString const key = "view-" + QString::number(id());
436 settings.setValue(key + "/pos", pos());
437 settings.setValue(key + "/size", size());
439 settings.setValue(key + "/geometry", saveGeometry());
441 settings.setValue(key + "/icon_size", iconSize());
442 d.toolbars_->saveToolbarInfo();
445 guiApp->unregisterView(id());
446 if (guiApp->viewCount() > 0) {
447 // Just close the window and do nothing else if this is not the
449 close_event->accept();
455 // this is the place where we leave the frontend.
456 // it is the only point at which we start quitting.
457 close_event->accept();
458 // quit the event loop
463 void GuiView::dragEnterEvent(QDragEnterEvent * event)
465 if (event->mimeData()->hasUrls())
467 /// \todo Ask lyx-devel is this is enough:
468 /// if (event->mimeData()->hasFormat("text/plain"))
469 /// event->acceptProposedAction();
473 void GuiView::dropEvent(QDropEvent* event)
475 QList<QUrl> files = event->mimeData()->urls();
479 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
480 for (int i = 0; i != files.size(); ++i) {
481 string const file = support::os::internal_path(fromqstr(
482 files.at(i).toLocalFile()));
484 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
489 void GuiView::message(docstring const & str)
491 statusBar()->showMessage(toqstr(str));
492 statusbar_timer_.stop();
493 statusbar_timer_.start(statusbar_timer_value);
497 void GuiView::smallSizedIcons()
499 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
503 void GuiView::normalSizedIcons()
505 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
509 void GuiView::bigSizedIcons()
511 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
515 void GuiView::clearMessage()
519 theLyXFunc().setLyXView(this);
520 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
521 statusbar_timer_.stop();
525 void GuiView::updateWindowTitle(GuiWorkArea * wa)
527 if (wa != d.current_work_area_)
529 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
530 setWindowIconText(wa->windowIconText());
534 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
537 disconnectBufferView();
538 connectBufferView(wa->bufferView());
539 connectBuffer(wa->bufferView().buffer());
540 d.current_work_area_ = wa;
541 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
542 this, SLOT(updateWindowTitle(GuiWorkArea *)));
543 updateWindowTitle(wa);
546 // Buffer-dependent dialogs should be updated or
547 // hidden. This should go here because some dialogs (eg ToC)
548 // require bv_->text.
549 updateBufferDependent(true);
551 updateLayoutChoice(false);
556 void GuiView::updateStatusBar()
558 // let the user see the explicit message
559 if (statusbar_timer_.isActive())
562 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
566 bool GuiView::hasFocus() const
568 return qApp->activeWindow() == this;
572 bool GuiView::event(QEvent * e)
576 // Useful debug code:
577 //case QEvent::ActivationChange:
578 //case QEvent::WindowDeactivate:
579 //case QEvent::Paint:
580 //case QEvent::Enter:
581 //case QEvent::Leave:
582 //case QEvent::HoverEnter:
583 //case QEvent::HoverLeave:
584 //case QEvent::HoverMove:
585 //case QEvent::StatusTip:
586 //case QEvent::DragEnter:
587 //case QEvent::DragLeave:
591 case QEvent::WindowActivate: {
592 guiApp->setCurrentView(*this);
593 if (d.current_work_area_) {
594 BufferView & bv = d.current_work_area_->bufferView();
595 connectBufferView(bv);
596 connectBuffer(bv.buffer());
597 // The document structure, name and dialogs might have
598 // changed in another view.
599 updateBufferDependent(true);
601 setWindowTitle(qt_("LyX"));
602 setWindowIconText(qt_("LyX"));
604 return QMainWindow::event(e);
606 case QEvent::ShortcutOverride: {
607 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
608 if (!d.current_work_area_) {
609 theLyXFunc().setLyXView(this);
611 setKeySymbol(&sym, ke);
612 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
616 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
618 setKeySymbol(&sym, ke);
619 d.current_work_area_->processKeySym(sym, NoModifier);
625 return QMainWindow::event(e);
630 bool GuiView::focusNextPrevChild(bool /*next*/)
637 void GuiView::setBusy(bool yes)
639 if (d.current_work_area_) {
640 d.current_work_area_->setUpdatesEnabled(!yes);
642 d.current_work_area_->stopBlinkingCursor();
644 d.current_work_area_->startBlinkingCursor();
648 QApplication::setOverrideCursor(Qt::WaitCursor);
650 QApplication::restoreOverrideCursor();
654 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
656 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
658 if (tbinfo.flags & ToolbarInfo::TOP) {
660 addToolBarBreak(Qt::TopToolBarArea);
661 addToolBar(Qt::TopToolBarArea, toolBar);
664 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
665 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
666 #if (QT_VERSION >= 0x040202)
668 addToolBarBreak(Qt::BottomToolBarArea);
670 addToolBar(Qt::BottomToolBarArea, toolBar);
673 if (tbinfo.flags & ToolbarInfo::LEFT) {
674 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
675 #if (QT_VERSION >= 0x040202)
677 addToolBarBreak(Qt::LeftToolBarArea);
679 addToolBar(Qt::LeftToolBarArea, toolBar);
682 if (tbinfo.flags & ToolbarInfo::RIGHT) {
683 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
684 #if (QT_VERSION >= 0x040202)
686 addToolBarBreak(Qt::RightToolBarArea);
688 addToolBar(Qt::RightToolBarArea, toolBar);
691 // The following does not work so I cannot restore to exact toolbar location
693 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
694 toolBar->move(tbinfo.posx, tbinfo.posy);
701 GuiWorkArea * GuiView::workArea(Buffer & buffer)
703 for (int i = 0; i != d.splitter_->count(); ++i) {
704 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
712 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
714 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
715 wa->setUpdatesEnabled(false);
717 // Automatically create a TabWorkArea if there are none yet.
718 if (!d.splitter_->count())
721 TabWorkArea * tab_widget = d.currentTabWorkArea();
722 tab_widget->addTab(wa, wa->windowTitle());
723 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
724 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
726 wa->bufferView().updateMetrics();
728 // Hide tabbar if there's only one tab.
729 tab_widget->showBar(tab_widget->count() > 1);
734 void GuiView::addTabWorkArea()
736 TabWorkArea * twa = new TabWorkArea;
737 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
738 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
739 d.splitter_->addWidget(twa);
740 d.stack_widget_->setCurrentWidget(d.splitter_);
744 GuiWorkArea const * GuiView::currentWorkArea() const
746 return d.current_work_area_;
750 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
752 BOOST_ASSERT(work_area);
754 // Changing work area can result from opening a file so
755 // update the toc in any case.
758 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
759 d.current_work_area_ = wa;
760 for (int i = 0; i != d.splitter_->count(); ++i) {
761 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
767 void GuiView::removeWorkArea(GuiWorkArea * work_area)
769 BOOST_ASSERT(work_area);
770 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
771 if (gwa == d.current_work_area_) {
773 disconnectBufferView();
774 hideBufferDependent();
775 d.current_work_area_ = 0;
778 // removing a work area often results from closing a file so
779 // update the toc in any case.
782 for (int i = 0; i != d.splitter_->count(); ++i) {
783 TabWorkArea * twa = d.tabWorkArea(i);
784 if (!twa->removeWorkArea(gwa))
785 // Not found in this tab group.
788 // We found and removed the GuiWorkArea.
790 // No more WorkAreas in this tab group, so delete it.
795 if (d.current_work_area_)
796 // This means that we are not closing the current GuiWorkArea;
799 // Switch to the next GuiWorkArea in the found TabWorkArea.
800 d.current_work_area_ = twa->currentWorkArea();
804 if (d.splitter_->count() == 0)
805 // No more work area, switch to the background widget.
810 void GuiView::updateLayoutChoice(bool force)
812 // Don't show any layouts without a buffer
814 d.toolbars_->clearLayoutList();
818 // Update the layout display
819 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
820 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
823 docstring const & layout = d.current_work_area_->bufferView().cursor().
824 innerParagraph().layout()->name();
826 if (layout != d.current_layout) {
827 d.toolbars_->setLayout(layout);
828 d.current_layout = layout;
833 bool GuiView::isToolbarVisible(std::string const & id)
835 return d.toolbars_->visible(id);
838 void GuiView::updateToolbars()
840 if (d.current_work_area_) {
842 d.current_work_area_->bufferView().cursor().inMathed();
844 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
846 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
847 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
849 d.toolbars_->update(math, table, review);
851 d.toolbars_->update(false, false, false);
853 // update read-only status of open dialogs.
858 Buffer * GuiView::buffer()
860 if (d.current_work_area_)
861 return &d.current_work_area_->bufferView().buffer();
866 Buffer const * GuiView::buffer() const
868 if (d.current_work_area_)
869 return &d.current_work_area_->bufferView().buffer();
874 void GuiView::setBuffer(Buffer * newBuffer)
876 BOOST_ASSERT(newBuffer);
879 GuiWorkArea * wa = workArea(*newBuffer);
881 updateLabels(*newBuffer->masterBuffer());
882 wa = addWorkArea(*newBuffer);
884 //Disconnect the old buffer...there's no new one.
887 connectBuffer(*newBuffer);
888 connectBufferView(wa->bufferView());
889 setCurrentWorkArea(wa);
895 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
899 Buffer * newBuffer = checkAndLoadLyXFile(filename);
902 message(_("Document not loaded."));
908 GuiWorkArea * wa = workArea(*newBuffer);
910 wa = addWorkArea(*newBuffer);
912 // scroll to the position when the file was last closed
913 if (lyxrc.use_lastfilepos) {
914 LastFilePosSection::FilePos filepos =
915 LyX::ref().session().lastFilePos().load(filename);
916 // if successfully move to pit (returned par_id is not zero),
917 // update metrics and reset font
918 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
922 LyX::ref().session().lastFiles().add(filename);
929 void GuiView::connectBuffer(Buffer & buf)
931 buf.setGuiDelegate(this);
935 void GuiView::disconnectBuffer()
937 if (d.current_work_area_)
938 d.current_work_area_->bufferView().setGuiDelegate(0);
942 void GuiView::connectBufferView(BufferView & bv)
944 bv.setGuiDelegate(this);
948 void GuiView::disconnectBufferView()
950 if (d.current_work_area_)
951 d.current_work_area_->bufferView().setGuiDelegate(0);
955 void GuiView::errors(string const & error_type)
957 ErrorList & el = buffer()->errorList(error_type);
959 showDialog("errorlist", error_type);
963 void GuiView::updateDialog(string const & name, string const & data)
965 if (!isDialogVisible(name))
968 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
969 if (it == d.dialogs_.end())
972 Dialog * const dialog = it->second.get();
973 if (dialog->isVisibleView())
974 dialog->updateData(data);
978 BufferView * GuiView::view()
980 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
984 void GuiView::updateToc()
986 updateDialog("toc", "");
990 void GuiView::updateEmbeddedFiles()
992 updateDialog("embedding", "");
996 void GuiView::autoSave()
998 LYXERR(Debug::INFO, "Running autoSave()");
1001 view()->buffer().autoSave();
1005 void GuiView::resetAutosaveTimers()
1008 autosave_timeout_->restart();
1012 void GuiView::dispatch(FuncRequest const & cmd)
1014 switch(cmd.action) {
1015 case LFUN_BUFFER_SWITCH:
1016 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1019 case LFUN_COMMAND_EXECUTE: {
1020 bool const show_it = cmd.argument() != "off";
1021 d.toolbars_->showCommandBuffer(show_it);
1024 case LFUN_DROP_LAYOUTS_CHOICE:
1025 d.toolbars_->openLayoutList();
1028 case LFUN_MENU_OPEN:
1029 d.menubar_->openByName(toqstr(cmd.argument()));
1032 case LFUN_TOOLBAR_TOGGLE: {
1033 string const name = cmd.getArg(0);
1034 bool const allowauto = cmd.getArg(1) == "allowauto";
1035 // it is possible to get current toolbar status like this,...
1036 // but I decide to obey the order of ToolbarBackend::flags
1037 // and disregard real toolbar status.
1038 // toolbars_->saveToolbarInfo();
1040 // toggle state on/off/auto
1041 d.toolbars_->toggleToolbarState(name, allowauto);
1045 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1047 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1051 if (tbi->flags & ToolbarInfo::ON)
1053 else if (tbi->flags & ToolbarInfo::OFF)
1055 else if (tbi->flags & ToolbarInfo::AUTO)
1058 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1059 _(tbi->gui_name), state));
1064 theLyXFunc().setLyXView(this);
1070 Buffer const * GuiView::updateInset(Inset const * inset)
1072 if (!d.current_work_area_)
1076 d.current_work_area_->scheduleRedraw();
1078 return &d.current_work_area_->bufferView().buffer();
1082 void GuiView::restartCursor()
1084 /* When we move around, or type, it's nice to be able to see
1085 * the cursor immediately after the keypress.
1087 if (d.current_work_area_)
1088 d.current_work_area_->startBlinkingCursor();
1092 Dialog * GuiView::find_or_build(string const & name)
1094 if (!isValidName(name))
1097 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1099 if (it != d.dialogs_.end())
1100 return it->second.get();
1102 d.dialogs_[name].reset(build(name));
1103 return d.dialogs_[name].get();
1107 void GuiView::showDialog(string const & name, string const & data,
1114 Dialog * dialog = find_or_build(name);
1116 dialog->showData(data);
1118 d.open_insets_[name] = inset;
1124 bool GuiView::isDialogVisible(string const & name) const
1126 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1127 if (it == d.dialogs_.end())
1129 return it->second.get()->isVisibleView();
1133 void GuiView::hideDialog(string const & name, Inset * inset)
1135 // Don't send the signal if we are quitting, because on MSVC it is
1136 // destructed before the cut stack in CutAndPaste.cpp, and this method
1137 // is called from some inset destructor if the cut stack is not empty
1142 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1143 if (it == d.dialogs_.end())
1146 if (inset && inset != getOpenInset(name))
1149 Dialog * const dialog = it->second.get();
1150 if (dialog->isVisibleView())
1152 d.open_insets_[name] = 0;
1156 void GuiView::disconnectDialog(string const & name)
1158 if (!isValidName(name))
1161 if (d.open_insets_.find(name) != d.open_insets_.end())
1162 d.open_insets_[name] = 0;
1166 Inset * GuiView::getOpenInset(string const & name) const
1168 if (!isValidName(name))
1171 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1172 return it == d.open_insets_.end() ? 0 : it->second;
1176 void GuiView::hideAll() const
1178 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1179 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1181 for(; it != end; ++it)
1186 void GuiView::hideBufferDependent() const
1188 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1189 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1191 for(; it != end; ++it) {
1192 Dialog * dialog = it->second.get();
1193 if (dialog->isBufferDependent())
1199 void GuiView::updateBufferDependent(bool switched) const
1201 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1202 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1204 for(; it != end; ++it) {
1205 Dialog * dialog = it->second.get();
1206 if (switched && dialog->isBufferDependent()) {
1207 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1208 dialog->updateView();
1212 // A bit clunky, but the dialog will request
1213 // that the kernel provides it with the necessary
1215 dialog->slotRestore();
1221 void GuiView::redrawDialog() const
1223 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1224 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1226 for(; it != end; ++it)
1227 it->second->redraw();
1231 void GuiView::checkStatus()
1233 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1234 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1236 for(; it != end; ++it) {
1237 Dialog * const dialog = it->second.get();
1238 if (dialog && dialog->isVisibleView())
1239 dialog->checkStatus();
1246 // This list should be kept in sync with the list of insets in
1247 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1248 // dialog should have the same name as the inset.
1250 char const * const dialognames[] = {
1251 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1252 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1253 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1254 "mathdelimiter", "mathmatrix", "note", "paragraph",
1255 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1257 #ifdef HAVE_LIBAIKSAURUS
1261 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1263 char const * const * const end_dialognames =
1264 dialognames + (sizeof(dialognames) / sizeof(char *));
1268 cmpCStr(char const * name) : name_(name) {}
1269 bool operator()(char const * other) {
1270 return strcmp(other, name_) == 0;
1279 // will be replaced by a proper factory...
1280 Dialog * createGuiAbout(LyXView & lv);
1281 Dialog * createGuiBibitem(LyXView & lv);
1282 Dialog * createGuiBibtex(LyXView & lv);
1283 Dialog * createGuiBox(LyXView & lv);
1284 Dialog * createGuiBranch(LyXView & lv);
1285 Dialog * createGuiChanges(LyXView & lv);
1286 Dialog * createGuiCharacter(LyXView & lv);
1287 Dialog * createGuiCitation(LyXView & lv);
1288 Dialog * createGuiDelimiter(LyXView & lv);
1289 Dialog * createGuiDocument(LyXView & lv);
1290 Dialog * createGuiErrorList(LyXView & lv);
1291 Dialog * createGuiERT(LyXView & lv);
1292 Dialog * createGuiExternal(LyXView & lv);
1293 Dialog * createGuiFloat(LyXView & lv);
1294 Dialog * createGuiGraphics(LyXView & lv);
1295 Dialog * createGuiInclude(LyXView & lv);
1296 Dialog * createGuiIndex(LyXView & lv);
1297 Dialog * createGuiLabel(LyXView & lv);
1298 Dialog * createGuiListings(LyXView & lv);
1299 Dialog * createGuiLog(LyXView & lv);
1300 Dialog * createGuiMathMatrix(LyXView & lv);
1301 Dialog * createGuiNomenclature(LyXView & lv);
1302 Dialog * createGuiNote(LyXView & lv);
1303 Dialog * createGuiParagraph(LyXView & lv);
1304 Dialog * createGuiPreferences(LyXView & lv);
1305 Dialog * createGuiPrint(LyXView & lv);
1306 Dialog * createGuiRef(LyXView & lv);
1307 Dialog * createGuiSearch(LyXView & lv);
1308 Dialog * createGuiSendTo(LyXView & lv);
1309 Dialog * createGuiShowFile(LyXView & lv);
1310 Dialog * createGuiSpellchecker(LyXView & lv);
1311 Dialog * createGuiTabularCreate(LyXView & lv);
1312 Dialog * createGuiTabular(LyXView & lv);
1313 Dialog * createGuiTexInfo(LyXView & lv);
1314 Dialog * createGuiToc(LyXView & lv);
1315 Dialog * createGuiThesaurus(LyXView & lv);
1316 Dialog * createGuiHyperlink(LyXView & lv);
1317 Dialog * createGuiVSpace(LyXView & lv);
1318 Dialog * createGuiViewSource(LyXView & lv);
1319 Dialog * createGuiWrap(LyXView & lv);
1322 bool GuiView::isValidName(string const & name) const
1324 return std::find_if(dialognames, end_dialognames,
1325 cmpCStr(name.c_str())) != end_dialognames;
1329 Dialog * GuiView::build(string const & name)
1331 BOOST_ASSERT(isValidName(name));
1333 if (name == "aboutlyx")
1334 return createGuiAbout(*this);
1335 if (name == "bibitem")
1336 return createGuiBibitem(*this);
1337 if (name == "bibtex")
1338 return createGuiBibtex(*this);
1340 return createGuiBox(*this);
1341 if (name == "branch")
1342 return createGuiBranch(*this);
1343 if (name == "changes")
1344 return createGuiChanges(*this);
1345 if (name == "character")
1346 return createGuiCharacter(*this);
1347 if (name == "citation")
1348 return createGuiCitation(*this);
1349 if (name == "document")
1350 return createGuiDocument(*this);
1351 if (name == "errorlist")
1352 return createGuiErrorList(*this);
1354 return createGuiERT(*this);
1355 if (name == "external")
1356 return createGuiExternal(*this);
1358 return createGuiShowFile(*this);
1359 if (name == "findreplace")
1360 return createGuiSearch(*this);
1361 if (name == "float")
1362 return createGuiFloat(*this);
1363 if (name == "graphics")
1364 return createGuiGraphics(*this);
1365 if (name == "include")
1366 return createGuiInclude(*this);
1367 if (name == "index")
1368 return createGuiIndex(*this);
1369 if (name == "nomenclature")
1370 return createGuiNomenclature(*this);
1371 if (name == "label")
1372 return createGuiLabel(*this);
1374 return createGuiLog(*this);
1375 if (name == "view-source")
1376 return createGuiViewSource(*this);
1377 if (name == "mathdelimiter")
1378 return createGuiDelimiter(*this);
1379 if (name == "mathmatrix")
1380 return createGuiMathMatrix(*this);
1382 return createGuiNote(*this);
1383 if (name == "paragraph")
1384 return createGuiParagraph(*this);
1385 if (name == "prefs")
1386 return createGuiPreferences(*this);
1387 if (name == "print")
1388 return createGuiPrint(*this);
1390 return createGuiRef(*this);
1391 if (name == "sendto")
1392 return createGuiSendTo(*this);
1393 if (name == "spellchecker")
1394 return createGuiSpellchecker(*this);
1395 if (name == "tabular")
1396 return createGuiTabular(*this);
1397 if (name == "tabularcreate")
1398 return createGuiTabularCreate(*this);
1399 if (name == "texinfo")
1400 return createGuiTexInfo(*this);
1401 #ifdef HAVE_LIBAIKSAURUS
1402 if (name == "thesaurus")
1403 return createGuiThesaurus(*this);
1406 return createGuiToc(*this);
1408 return createGuiHyperlink(*this);
1409 if (name == "vspace")
1410 return createGuiVSpace(*this);
1412 return createGuiWrap(*this);
1413 if (name == "listings")
1414 return createGuiListings(*this);
1420 /// Are the tooltips on or off?
1421 bool GuiView::tooltipsEnabled()
1426 } // namespace frontend
1429 #include "GuiView_moc.cpp"