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>
86 #include <boost/bind.hpp>
87 #include <boost/current_function.hpp>
89 #ifdef HAVE_SYS_TIME_H
90 # include <sys/time.h>
102 extern bool quitting;
106 using support::bformat;
107 using support::FileName;
108 using support::makeDisplayPath;
109 using support::onlyFilename;
113 int const statusbar_timer_value = 3000;
115 class BackgroundWidget : public QWidget
118 BackgroundWidget(QString const & file, QString const & text)
120 splash_ = new QPixmap(file);
122 lyxerr << "could not load splash screen: '" << fromqstr(file) << "'" << endl;
126 QPainter pain(splash_);
127 pain.setPen(QColor(255, 255, 0));
129 // The font used to display the version info
130 font.setStyleHint(QFont::SansSerif);
131 font.setWeight(QFont::Bold);
132 font.setPointSize(convert<int>(lyxrc.font_sizes[FONT_SIZE_LARGE]));
134 pain.drawText(260, 270, text);
137 void paintEvent(QPaintEvent *)
142 int x = (width() - splash_->width()) / 2;
143 int y = (height() - splash_->height()) / 2;
145 pain.drawPixmap(x, y, *splash_);
155 typedef boost::shared_ptr<Dialog> DialogPtr;
157 struct GuiView::GuiViewPrivate
160 : current_work_area_(0), posx_offset(0), posy_offset(0),
161 autosave_timeout_(new Timeout(5000)), quitting_by_menu_(false),
164 // hardcode here the platform specific icon size
165 smallIconSize = 14; // scaling problems
166 normalIconSize = 20; // ok, default
167 bigIconSize = 26; // better for some math icons
169 splitter_ = new QSplitter;
171 stack_widget_ = new QStackedWidget;
172 stack_widget_->addWidget(bg_widget_);
173 stack_widget_->addWidget(splitter_);
181 delete stack_widget_;
184 delete autosave_timeout_;
187 QMenu * toolBarPopup(GuiView * parent)
189 // FIXME: translation
190 QMenu * menu = new QMenu(parent);
191 QActionGroup * iconSizeGroup = new QActionGroup(parent);
193 QAction * smallIcons = new QAction(iconSizeGroup);
194 smallIcons->setText(qt_("Small-sized icons"));
195 smallIcons->setCheckable(true);
196 QObject::connect(smallIcons, SIGNAL(triggered()),
197 parent, SLOT(smallSizedIcons()));
198 menu->addAction(smallIcons);
200 QAction * normalIcons = new QAction(iconSizeGroup);
201 normalIcons->setText(qt_("Normal-sized icons"));
202 normalIcons->setCheckable(true);
203 QObject::connect(normalIcons, SIGNAL(triggered()),
204 parent, SLOT(normalSizedIcons()));
205 menu->addAction(normalIcons);
207 QAction * bigIcons = new QAction(iconSizeGroup);
208 bigIcons->setText(qt_("Big-sized icons"));
209 bigIcons->setCheckable(true);
210 QObject::connect(bigIcons, SIGNAL(triggered()),
211 parent, SLOT(bigSizedIcons()));
212 menu->addAction(bigIcons);
214 unsigned int cur = parent->iconSize().width();
215 if ( cur == parent->d.smallIconSize)
216 smallIcons->setChecked(true);
217 else if (cur == parent->d.normalIconSize)
218 normalIcons->setChecked(true);
219 else if (cur == parent->d.bigIconSize)
220 bigIcons->setChecked(true);
225 void initBackground()
227 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
228 /// The text to be written on top of the pixmap
229 QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
230 bg_widget_ = new BackgroundWidget(":/images/banner.png", text);
235 stack_widget_->setCurrentWidget(bg_widget_);
236 bg_widget_->setUpdatesEnabled(true);
239 TabWorkArea * tabWorkArea(int i)
241 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
244 TabWorkArea * currentTabWorkArea()
246 if (splitter_->count() == 1)
247 // The first TabWorkArea is always the first one, if any.
248 return tabWorkArea(0);
250 TabWorkArea * tab_widget = 0;
251 for (int i = 0; i != splitter_->count(); ++i) {
252 QWidget * w = splitter_->widget(i);
255 tab_widget = dynamic_cast<TabWorkArea *>(w);
267 GuiWorkArea * current_work_area_;
271 QSplitter * splitter_;
272 QStackedWidget * stack_widget_;
273 BackgroundWidget * bg_widget_;
275 GuiMenubar * menubar_;
277 GuiToolbars * toolbars_;
279 docstring current_layout;
282 std::map<std::string, Inset *> open_insets_;
285 std::map<std::string, DialogPtr> dialogs_;
287 unsigned int smallIconSize;
288 unsigned int normalIconSize;
289 unsigned int bigIconSize;
291 QTimer statusbar_timer_;
292 /// are we quitting by the menu?
293 bool quitting_by_menu_;
294 /// auto-saving of buffers
295 Timeout * const autosave_timeout_;
297 /// flag against a race condition due to multiclicks in Qt frontend,
303 GuiView::GuiView(int id)
304 : d(*new GuiViewPrivate), id_(id)
306 // GuiToolbars *must* be initialised before GuiMenubar.
307 d.toolbars_ = new GuiToolbars(*this);
308 d.menubar_ = new GuiMenubar(this, menubackend);
310 setCentralWidget(d.stack_widget_);
312 // Start autosave timer
313 if (lyxrc.autosave) {
314 d.autosave_timeout_->timeout.connect(boost::bind(&GuiView::autoSave, this));
315 d.autosave_timeout_->setTimeout(lyxrc.autosave * 1000);
316 d.autosave_timeout_->start();
318 QObject::connect(&d.statusbar_timer_, SIGNAL(timeout()),
319 this, SLOT(clearMessage()));
321 // Qt bug? signal lastWindowClosed does not work
322 setAttribute(Qt::WA_QuitOnClose, false);
323 setAttribute(Qt::WA_DeleteOnClose, true);
325 // assign an icon to main form. We do not do it under Qt/Mac,
326 // since the icon is provided in the application bundle.
327 setWindowIcon(QPixmap(":/images/lyx.png"));
331 setAcceptDrops(true);
333 statusBar()->setSizeGripEnabled(true);
335 // Forbid too small unresizable window because it can happen
336 // with some window manager under X11.
337 setMinimumSize(300, 200);
339 if (!lyxrc.allow_geometry_session)
340 // No session handling, default to a sane size.
341 setGeometry(50, 50, 690, 510);
343 // Now take care of session management.
345 QString const key = "view-" + QString::number(id_);
347 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
348 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
352 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
353 setGeometry(50, 50, 690, 510);
355 setIconSize(settings.value(key + "/icon_size").toSize());
365 void GuiView::close()
367 d.quitting_by_menu_ = true;
368 d.current_work_area_ = 0;
369 for (int i = 0; i != d.splitter_->count(); ++i) {
370 TabWorkArea * twa = d.tabWorkArea(i);
374 QMainWindow::close();
375 d.quitting_by_menu_ = false;
379 void GuiView::setFocus()
381 if (d.current_work_area_)
382 d.current_work_area_->setFocus();
388 QMenu* GuiView::createPopupMenu()
390 return d.toolBarPopup(this);
394 void GuiView::showEvent(QShowEvent * e)
396 LYXERR(Debug::GUI, "Passed Geometry "
397 << size().height() << "x" << size().width()
398 << "+" << pos().x() << "+" << pos().y());
400 if (d.splitter_->count() == 0)
401 // No work area, switch to the background widget.
404 QMainWindow::showEvent(e);
408 void GuiView::closeEvent(QCloseEvent * close_event)
410 // we may have been called through the close window button
411 // which bypasses the LFUN machinery.
412 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
413 if (!theBufferList().quitWriteAll()) {
414 close_event->ignore();
419 // Make sure that no LFUN use this close to be closed View.
420 theLyXFunc().setLyXView(0);
421 // Make sure the timer time out will not trigger a statusbar update.
422 d.statusbar_timer_.stop();
424 if (lyxrc.allow_geometry_session) {
426 QString const key = "view-" + QString::number(id_);
428 settings.setValue(key + "/pos", pos());
429 settings.setValue(key + "/size", size());
431 settings.setValue(key + "/geometry", saveGeometry());
433 settings.setValue(key + "/icon_size", iconSize());
434 d.toolbars_->saveToolbarInfo();
437 guiApp->unregisterView(id_);
438 if (guiApp->viewCount() > 0) {
439 // Just close the window and do nothing else if this is not the
441 close_event->accept();
447 // this is the place where we leave the frontend.
448 // it is the only point at which we start quitting.
449 close_event->accept();
450 // quit the event loop
455 void GuiView::dragEnterEvent(QDragEnterEvent * event)
457 if (event->mimeData()->hasUrls())
459 /// \todo Ask lyx-devel is this is enough:
460 /// if (event->mimeData()->hasFormat("text/plain"))
461 /// event->acceptProposedAction();
465 void GuiView::dropEvent(QDropEvent* event)
467 QList<QUrl> files = event->mimeData()->urls();
471 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
472 for (int i = 0; i != files.size(); ++i) {
473 string const file = support::os::internal_path(fromqstr(
474 files.at(i).toLocalFile()));
476 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
481 void GuiView::message(docstring const & str)
483 statusBar()->showMessage(toqstr(str));
484 d.statusbar_timer_.stop();
485 d.statusbar_timer_.start(statusbar_timer_value);
489 void GuiView::smallSizedIcons()
491 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
495 void GuiView::normalSizedIcons()
497 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
501 void GuiView::bigSizedIcons()
503 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
507 void GuiView::clearMessage()
511 theLyXFunc().setLyXView(this);
512 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
513 d.statusbar_timer_.stop();
517 void GuiView::updateWindowTitle(GuiWorkArea * wa)
519 if (wa != d.current_work_area_)
521 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
522 setWindowIconText(wa->windowIconText());
526 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
529 disconnectBufferView();
530 connectBufferView(wa->bufferView());
531 connectBuffer(wa->bufferView().buffer());
532 d.current_work_area_ = wa;
533 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
534 this, SLOT(updateWindowTitle(GuiWorkArea *)));
535 updateWindowTitle(wa);
538 // Buffer-dependent dialogs should be updated or
539 // hidden. This should go here because some dialogs (eg ToC)
540 // require bv_->text.
541 updateBufferDependent(true);
543 updateLayoutChoice(false);
548 void GuiView::updateStatusBar()
550 // let the user see the explicit message
551 if (d.statusbar_timer_.isActive())
554 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
558 bool GuiView::hasFocus() const
560 return qApp->activeWindow() == this;
564 bool GuiView::event(QEvent * e)
568 // Useful debug code:
569 //case QEvent::ActivationChange:
570 //case QEvent::WindowDeactivate:
571 //case QEvent::Paint:
572 //case QEvent::Enter:
573 //case QEvent::Leave:
574 //case QEvent::HoverEnter:
575 //case QEvent::HoverLeave:
576 //case QEvent::HoverMove:
577 //case QEvent::StatusTip:
578 //case QEvent::DragEnter:
579 //case QEvent::DragLeave:
583 case QEvent::WindowActivate: {
584 guiApp->setCurrentView(*this);
585 if (d.current_work_area_) {
586 BufferView & bv = d.current_work_area_->bufferView();
587 connectBufferView(bv);
588 connectBuffer(bv.buffer());
589 // The document structure, name and dialogs might have
590 // changed in another view.
591 updateBufferDependent(true);
593 setWindowTitle(qt_("LyX"));
594 setWindowIconText(qt_("LyX"));
596 return QMainWindow::event(e);
598 case QEvent::ShortcutOverride: {
599 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
600 if (!d.current_work_area_) {
601 theLyXFunc().setLyXView(this);
603 setKeySymbol(&sym, ke);
604 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
608 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
610 setKeySymbol(&sym, ke);
611 d.current_work_area_->processKeySym(sym, NoModifier);
617 return QMainWindow::event(e);
622 bool GuiView::focusNextPrevChild(bool /*next*/)
629 void GuiView::setBusy(bool yes)
631 if (d.current_work_area_) {
632 d.current_work_area_->setUpdatesEnabled(!yes);
634 d.current_work_area_->stopBlinkingCursor();
636 d.current_work_area_->startBlinkingCursor();
640 QApplication::setOverrideCursor(Qt::WaitCursor);
642 QApplication::restoreOverrideCursor();
646 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
648 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
650 if (tbinfo.flags & ToolbarInfo::TOP) {
652 addToolBarBreak(Qt::TopToolBarArea);
653 addToolBar(Qt::TopToolBarArea, toolBar);
656 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
657 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
658 #if (QT_VERSION >= 0x040202)
660 addToolBarBreak(Qt::BottomToolBarArea);
662 addToolBar(Qt::BottomToolBarArea, toolBar);
665 if (tbinfo.flags & ToolbarInfo::LEFT) {
666 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
667 #if (QT_VERSION >= 0x040202)
669 addToolBarBreak(Qt::LeftToolBarArea);
671 addToolBar(Qt::LeftToolBarArea, toolBar);
674 if (tbinfo.flags & ToolbarInfo::RIGHT) {
675 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
676 #if (QT_VERSION >= 0x040202)
678 addToolBarBreak(Qt::RightToolBarArea);
680 addToolBar(Qt::RightToolBarArea, toolBar);
683 // The following does not work so I cannot restore to exact toolbar location
685 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
686 toolBar->move(tbinfo.posx, tbinfo.posy);
693 GuiWorkArea * GuiView::workArea(Buffer & buffer)
695 for (int i = 0; i != d.splitter_->count(); ++i) {
696 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
704 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
706 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
707 wa->setUpdatesEnabled(false);
709 // Automatically create a TabWorkArea if there are none yet.
710 if (!d.splitter_->count())
713 TabWorkArea * tab_widget = d.currentTabWorkArea();
714 tab_widget->addTab(wa, wa->windowTitle());
715 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
716 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
718 wa->bufferView().updateMetrics();
720 // Hide tabbar if there's only one tab.
721 tab_widget->showBar(tab_widget->count() > 1);
726 void GuiView::addTabWorkArea()
728 TabWorkArea * twa = new TabWorkArea;
729 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
730 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
731 d.splitter_->addWidget(twa);
732 d.stack_widget_->setCurrentWidget(d.splitter_);
736 GuiWorkArea const * GuiView::currentWorkArea() const
738 return d.current_work_area_;
742 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
744 BOOST_ASSERT(work_area);
746 // Changing work area can result from opening a file so
747 // update the toc in any case.
750 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
751 d.current_work_area_ = wa;
752 for (int i = 0; i != d.splitter_->count(); ++i) {
753 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
759 void GuiView::removeWorkArea(GuiWorkArea * work_area)
761 BOOST_ASSERT(work_area);
762 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
763 if (gwa == d.current_work_area_) {
765 disconnectBufferView();
766 hideBufferDependent();
767 d.current_work_area_ = 0;
770 // removing a work area often results from closing a file so
771 // update the toc in any case.
774 for (int i = 0; i != d.splitter_->count(); ++i) {
775 TabWorkArea * twa = d.tabWorkArea(i);
776 if (!twa->removeWorkArea(gwa))
777 // Not found in this tab group.
780 // We found and removed the GuiWorkArea.
782 // No more WorkAreas in this tab group, so delete it.
787 if (d.current_work_area_)
788 // This means that we are not closing the current GuiWorkArea;
791 // Switch to the next GuiWorkArea in the found TabWorkArea.
792 d.current_work_area_ = twa->currentWorkArea();
796 if (d.splitter_->count() == 0)
797 // No more work area, switch to the background widget.
802 void GuiView::updateLayoutChoice(bool force)
804 // Don't show any layouts without a buffer
806 d.toolbars_->clearLayoutList();
810 // Update the layout display
811 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
812 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
815 docstring const & layout = d.current_work_area_->bufferView().cursor().
816 innerParagraph().layout()->name();
818 if (layout != d.current_layout) {
819 d.toolbars_->setLayout(layout);
820 d.current_layout = layout;
825 bool GuiView::isToolbarVisible(std::string const & id)
827 return d.toolbars_->visible(id);
830 void GuiView::updateToolbars()
832 if (d.current_work_area_) {
834 d.current_work_area_->bufferView().cursor().inMathed();
836 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
838 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
839 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
841 d.toolbars_->update(math, table, review);
843 d.toolbars_->update(false, false, false);
845 // update read-only status of open dialogs.
850 Buffer * GuiView::buffer()
852 if (d.current_work_area_)
853 return &d.current_work_area_->bufferView().buffer();
858 Buffer const * GuiView::buffer() const
860 if (d.current_work_area_)
861 return &d.current_work_area_->bufferView().buffer();
866 void GuiView::setBuffer(Buffer * newBuffer)
868 BOOST_ASSERT(newBuffer);
871 GuiWorkArea * wa = workArea(*newBuffer);
873 updateLabels(*newBuffer->masterBuffer());
874 wa = addWorkArea(*newBuffer);
876 //Disconnect the old buffer...there's no new one.
879 connectBuffer(*newBuffer);
880 connectBufferView(wa->bufferView());
881 setCurrentWorkArea(wa);
887 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
891 Buffer * newBuffer = checkAndLoadLyXFile(filename);
894 message(_("Document not loaded."));
900 GuiWorkArea * wa = workArea(*newBuffer);
902 wa = addWorkArea(*newBuffer);
904 // scroll to the position when the file was last closed
905 if (lyxrc.use_lastfilepos) {
906 LastFilePosSection::FilePos filepos =
907 LyX::ref().session().lastFilePos().load(filename);
908 // if successfully move to pit (returned par_id is not zero),
909 // update metrics and reset font
910 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
914 LyX::ref().session().lastFiles().add(filename);
921 void GuiView::connectBuffer(Buffer & buf)
923 buf.setGuiDelegate(this);
927 void GuiView::disconnectBuffer()
929 if (d.current_work_area_)
930 d.current_work_area_->bufferView().setGuiDelegate(0);
934 void GuiView::connectBufferView(BufferView & bv)
936 bv.setGuiDelegate(this);
940 void GuiView::disconnectBufferView()
942 if (d.current_work_area_)
943 d.current_work_area_->bufferView().setGuiDelegate(0);
947 void GuiView::errors(string const & error_type)
949 ErrorList & el = buffer()->errorList(error_type);
951 showDialog("errorlist", error_type);
955 void GuiView::updateDialog(string const & name, string const & data)
957 if (!isDialogVisible(name))
960 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
961 if (it == d.dialogs_.end())
964 Dialog * const dialog = it->second.get();
965 if (dialog->isVisibleView())
966 dialog->updateData(data);
970 BufferView * GuiView::view()
972 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
976 void GuiView::updateToc()
978 updateDialog("toc", "");
982 void GuiView::updateEmbeddedFiles()
984 updateDialog("embedding", "");
988 void GuiView::autoSave()
990 LYXERR(Debug::INFO, "Running autoSave()");
993 view()->buffer().autoSave();
997 void GuiView::resetAutosaveTimers()
1000 d.autosave_timeout_->restart();
1004 void GuiView::dispatch(FuncRequest const & cmd)
1006 switch(cmd.action) {
1007 case LFUN_BUFFER_SWITCH:
1008 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1011 case LFUN_COMMAND_EXECUTE: {
1012 bool const show_it = cmd.argument() != "off";
1013 d.toolbars_->showCommandBuffer(show_it);
1016 case LFUN_DROP_LAYOUTS_CHOICE:
1017 d.toolbars_->openLayoutList();
1020 case LFUN_MENU_OPEN:
1021 d.menubar_->openByName(toqstr(cmd.argument()));
1024 case LFUN_TOOLBAR_TOGGLE: {
1025 string const name = cmd.getArg(0);
1026 bool const allowauto = cmd.getArg(1) == "allowauto";
1027 // it is possible to get current toolbar status like this,...
1028 // but I decide to obey the order of ToolbarBackend::flags
1029 // and disregard real toolbar status.
1030 // toolbars_->saveToolbarInfo();
1032 // toggle state on/off/auto
1033 d.toolbars_->toggleToolbarState(name, allowauto);
1037 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1039 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1043 if (tbi->flags & ToolbarInfo::ON)
1045 else if (tbi->flags & ToolbarInfo::OFF)
1047 else if (tbi->flags & ToolbarInfo::AUTO)
1050 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1051 _(tbi->gui_name), state));
1056 theLyXFunc().setLyXView(this);
1062 Buffer const * GuiView::updateInset(Inset const * inset)
1064 if (!d.current_work_area_)
1068 d.current_work_area_->scheduleRedraw();
1070 return &d.current_work_area_->bufferView().buffer();
1074 void GuiView::restartCursor()
1076 /* When we move around, or type, it's nice to be able to see
1077 * the cursor immediately after the keypress.
1079 if (d.current_work_area_)
1080 d.current_work_area_->startBlinkingCursor();
1085 // This list should be kept in sync with the list of insets in
1086 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1087 // dialog should have the same name as the inset.
1089 char const * const dialognames[] = {
1090 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1091 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1092 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1093 "mathdelimiter", "mathmatrix", "note", "paragraph",
1094 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1096 #ifdef HAVE_LIBAIKSAURUS
1100 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1102 char const * const * const end_dialognames =
1103 dialognames + (sizeof(dialognames) / sizeof(char *));
1107 cmpCStr(char const * name) : name_(name) {}
1108 bool operator()(char const * other) {
1109 return strcmp(other, name_) == 0;
1116 bool isValidName(string const & name)
1118 return std::find_if(dialognames, end_dialognames,
1119 cmpCStr(name.c_str())) != end_dialognames;
1125 Dialog * GuiView::find_or_build(string const & name)
1127 if (!isValidName(name))
1130 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1132 if (it != d.dialogs_.end())
1133 return it->second.get();
1135 d.dialogs_[name].reset(build(name));
1136 return d.dialogs_[name].get();
1140 void GuiView::showDialog(string const & name, string const & data,
1147 Dialog * dialog = find_or_build(name);
1149 dialog->showData(data);
1151 d.open_insets_[name] = inset;
1157 bool GuiView::isDialogVisible(string const & name) const
1159 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1160 if (it == d.dialogs_.end())
1162 return it->second.get()->isVisibleView();
1166 void GuiView::hideDialog(string const & name, Inset * inset)
1168 // Don't send the signal if we are quitting, because on MSVC it is
1169 // destructed before the cut stack in CutAndPaste.cpp, and this method
1170 // is called from some inset destructor if the cut stack is not empty
1175 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1176 if (it == d.dialogs_.end())
1179 if (inset && inset != getOpenInset(name))
1182 Dialog * const dialog = it->second.get();
1183 if (dialog->isVisibleView())
1185 d.open_insets_[name] = 0;
1189 void GuiView::disconnectDialog(string const & name)
1191 if (!isValidName(name))
1194 if (d.open_insets_.find(name) != d.open_insets_.end())
1195 d.open_insets_[name] = 0;
1199 Inset * GuiView::getOpenInset(string const & name) const
1201 if (!isValidName(name))
1204 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1205 return it == d.open_insets_.end() ? 0 : it->second;
1209 void GuiView::hideAll() const
1211 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1212 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1214 for(; it != end; ++it)
1219 void GuiView::hideBufferDependent() const
1221 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1222 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1224 for(; it != end; ++it) {
1225 Dialog * dialog = it->second.get();
1226 if (dialog->isBufferDependent())
1232 void GuiView::updateBufferDependent(bool switched) const
1234 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1235 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1237 for(; it != end; ++it) {
1238 Dialog * dialog = it->second.get();
1239 if (switched && dialog->isBufferDependent()) {
1240 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1241 dialog->updateView();
1245 // A bit clunky, but the dialog will request
1246 // that the kernel provides it with the necessary
1248 dialog->slotRestore();
1254 void GuiView::checkStatus()
1256 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1257 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1259 for(; it != end; ++it) {
1260 Dialog * const dialog = it->second.get();
1261 if (dialog && dialog->isVisibleView())
1262 dialog->checkStatus();
1268 // will be replaced by a proper factory...
1269 Dialog * createGuiAbout(LyXView & lv);
1270 Dialog * createGuiBibitem(LyXView & lv);
1271 Dialog * createGuiBibtex(LyXView & lv);
1272 Dialog * createGuiBox(LyXView & lv);
1273 Dialog * createGuiBranch(LyXView & lv);
1274 Dialog * createGuiChanges(LyXView & lv);
1275 Dialog * createGuiCharacter(LyXView & lv);
1276 Dialog * createGuiCitation(LyXView & lv);
1277 Dialog * createGuiDelimiter(LyXView & lv);
1278 Dialog * createGuiDocument(LyXView & lv);
1279 Dialog * createGuiErrorList(LyXView & lv);
1280 Dialog * createGuiERT(LyXView & lv);
1281 Dialog * createGuiExternal(LyXView & lv);
1282 Dialog * createGuiFloat(LyXView & lv);
1283 Dialog * createGuiGraphics(LyXView & lv);
1284 Dialog * createGuiInclude(LyXView & lv);
1285 Dialog * createGuiIndex(LyXView & lv);
1286 Dialog * createGuiLabel(LyXView & lv);
1287 Dialog * createGuiListings(LyXView & lv);
1288 Dialog * createGuiLog(LyXView & lv);
1289 Dialog * createGuiMathMatrix(LyXView & lv);
1290 Dialog * createGuiNomenclature(LyXView & lv);
1291 Dialog * createGuiNote(LyXView & lv);
1292 Dialog * createGuiParagraph(LyXView & lv);
1293 Dialog * createGuiPreferences(LyXView & lv);
1294 Dialog * createGuiPrint(LyXView & lv);
1295 Dialog * createGuiRef(LyXView & lv);
1296 Dialog * createGuiSearch(LyXView & lv);
1297 Dialog * createGuiSendTo(LyXView & lv);
1298 Dialog * createGuiShowFile(LyXView & lv);
1299 Dialog * createGuiSpellchecker(LyXView & lv);
1300 Dialog * createGuiTabularCreate(LyXView & lv);
1301 Dialog * createGuiTabular(LyXView & lv);
1302 Dialog * createGuiTexInfo(LyXView & lv);
1303 Dialog * createGuiToc(LyXView & lv);
1304 Dialog * createGuiThesaurus(LyXView & lv);
1305 Dialog * createGuiHyperlink(LyXView & lv);
1306 Dialog * createGuiVSpace(LyXView & lv);
1307 Dialog * createGuiViewSource(LyXView & lv);
1308 Dialog * createGuiWrap(LyXView & lv);
1311 Dialog * GuiView::build(string const & name)
1313 BOOST_ASSERT(isValidName(name));
1315 if (name == "aboutlyx")
1316 return createGuiAbout(*this);
1317 if (name == "bibitem")
1318 return createGuiBibitem(*this);
1319 if (name == "bibtex")
1320 return createGuiBibtex(*this);
1322 return createGuiBox(*this);
1323 if (name == "branch")
1324 return createGuiBranch(*this);
1325 if (name == "changes")
1326 return createGuiChanges(*this);
1327 if (name == "character")
1328 return createGuiCharacter(*this);
1329 if (name == "citation")
1330 return createGuiCitation(*this);
1331 if (name == "document")
1332 return createGuiDocument(*this);
1333 if (name == "errorlist")
1334 return createGuiErrorList(*this);
1336 return createGuiERT(*this);
1337 if (name == "external")
1338 return createGuiExternal(*this);
1340 return createGuiShowFile(*this);
1341 if (name == "findreplace")
1342 return createGuiSearch(*this);
1343 if (name == "float")
1344 return createGuiFloat(*this);
1345 if (name == "graphics")
1346 return createGuiGraphics(*this);
1347 if (name == "include")
1348 return createGuiInclude(*this);
1349 if (name == "index")
1350 return createGuiIndex(*this);
1351 if (name == "nomenclature")
1352 return createGuiNomenclature(*this);
1353 if (name == "label")
1354 return createGuiLabel(*this);
1356 return createGuiLog(*this);
1357 if (name == "view-source")
1358 return createGuiViewSource(*this);
1359 if (name == "mathdelimiter")
1360 return createGuiDelimiter(*this);
1361 if (name == "mathmatrix")
1362 return createGuiMathMatrix(*this);
1364 return createGuiNote(*this);
1365 if (name == "paragraph")
1366 return createGuiParagraph(*this);
1367 if (name == "prefs")
1368 return createGuiPreferences(*this);
1369 if (name == "print")
1370 return createGuiPrint(*this);
1372 return createGuiRef(*this);
1373 if (name == "sendto")
1374 return createGuiSendTo(*this);
1375 if (name == "spellchecker")
1376 return createGuiSpellchecker(*this);
1377 if (name == "tabular")
1378 return createGuiTabular(*this);
1379 if (name == "tabularcreate")
1380 return createGuiTabularCreate(*this);
1381 if (name == "texinfo")
1382 return createGuiTexInfo(*this);
1383 #ifdef HAVE_LIBAIKSAURUS
1384 if (name == "thesaurus")
1385 return createGuiThesaurus(*this);
1388 return createGuiToc(*this);
1390 return createGuiHyperlink(*this);
1391 if (name == "vspace")
1392 return createGuiVSpace(*this);
1394 return createGuiWrap(*this);
1395 if (name == "listings")
1396 return createGuiListings(*this);
1402 } // namespace frontend
1405 #include "GuiView_moc.cpp"