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)
707 // Automatically create a TabWorkArea if there are none yet.
708 if (!d.splitter_->count())
711 TabWorkArea * tab_widget = d.currentTabWorkArea();
712 return tab_widget->addWorkArea(buffer, *this);
716 void GuiView::addTabWorkArea()
718 TabWorkArea * twa = new TabWorkArea;
719 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
720 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
721 d.splitter_->addWidget(twa);
722 d.stack_widget_->setCurrentWidget(d.splitter_);
726 GuiWorkArea const * GuiView::currentWorkArea() const
728 return d.current_work_area_;
732 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
734 BOOST_ASSERT(work_area);
736 // Changing work area can result from opening a file so
737 // update the toc in any case.
740 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
741 d.current_work_area_ = wa;
742 for (int i = 0; i != d.splitter_->count(); ++i) {
743 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
749 void GuiView::removeWorkArea(GuiWorkArea * work_area)
751 BOOST_ASSERT(work_area);
752 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
753 if (gwa == d.current_work_area_) {
755 disconnectBufferView();
756 hideBufferDependent();
757 d.current_work_area_ = 0;
760 // removing a work area often results from closing a file so
761 // update the toc in any case.
764 for (int i = 0; i != d.splitter_->count(); ++i) {
765 TabWorkArea * twa = d.tabWorkArea(i);
766 if (!twa->removeWorkArea(gwa))
767 // Not found in this tab group.
770 // We found and removed the GuiWorkArea.
772 // No more WorkAreas in this tab group, so delete it.
777 if (d.current_work_area_)
778 // This means that we are not closing the current GuiWorkArea;
781 // Switch to the next GuiWorkArea in the found TabWorkArea.
782 d.current_work_area_ = twa->currentWorkArea();
786 if (d.splitter_->count() == 0)
787 // No more work area, switch to the background widget.
792 void GuiView::updateLayoutChoice(bool force)
794 // Don't show any layouts without a buffer
796 d.toolbars_->clearLayoutList();
800 // Update the layout display
801 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
802 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
805 docstring const & layout = d.current_work_area_->bufferView().cursor().
806 innerParagraph().layout()->name();
808 if (layout != d.current_layout) {
809 d.toolbars_->setLayout(layout);
810 d.current_layout = layout;
815 bool GuiView::isToolbarVisible(std::string const & id)
817 return d.toolbars_->visible(id);
820 void GuiView::updateToolbars()
822 if (d.current_work_area_) {
824 d.current_work_area_->bufferView().cursor().inMathed();
826 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
828 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
829 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
831 d.toolbars_->update(math, table, review);
833 d.toolbars_->update(false, false, false);
835 // update read-only status of open dialogs.
840 Buffer * GuiView::buffer()
842 if (d.current_work_area_)
843 return &d.current_work_area_->bufferView().buffer();
848 Buffer const * GuiView::buffer() const
850 if (d.current_work_area_)
851 return &d.current_work_area_->bufferView().buffer();
856 void GuiView::setBuffer(Buffer * newBuffer)
858 BOOST_ASSERT(newBuffer);
861 GuiWorkArea * wa = workArea(*newBuffer);
863 updateLabels(*newBuffer->masterBuffer());
864 wa = addWorkArea(*newBuffer);
866 //Disconnect the old buffer...there's no new one.
869 connectBuffer(*newBuffer);
870 connectBufferView(wa->bufferView());
871 setCurrentWorkArea(wa);
877 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
881 Buffer * newBuffer = checkAndLoadLyXFile(filename);
884 message(_("Document not loaded."));
890 GuiWorkArea * wa = workArea(*newBuffer);
892 wa = addWorkArea(*newBuffer);
894 // scroll to the position when the file was last closed
895 if (lyxrc.use_lastfilepos) {
896 LastFilePosSection::FilePos filepos =
897 LyX::ref().session().lastFilePos().load(filename);
898 // if successfully move to pit (returned par_id is not zero),
899 // update metrics and reset font
900 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
904 LyX::ref().session().lastFiles().add(filename);
911 void GuiView::connectBuffer(Buffer & buf)
913 buf.setGuiDelegate(this);
917 void GuiView::disconnectBuffer()
919 if (d.current_work_area_)
920 d.current_work_area_->bufferView().setGuiDelegate(0);
924 void GuiView::connectBufferView(BufferView & bv)
926 bv.setGuiDelegate(this);
930 void GuiView::disconnectBufferView()
932 if (d.current_work_area_)
933 d.current_work_area_->bufferView().setGuiDelegate(0);
937 void GuiView::errors(string const & error_type)
939 ErrorList & el = buffer()->errorList(error_type);
941 showDialog("errorlist", error_type);
945 void GuiView::updateDialog(string const & name, string const & data)
947 if (!isDialogVisible(name))
950 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
951 if (it == d.dialogs_.end())
954 Dialog * const dialog = it->second.get();
955 if (dialog->isVisibleView())
956 dialog->updateData(data);
960 BufferView * GuiView::view()
962 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
966 void GuiView::updateToc()
968 updateDialog("toc", "");
972 void GuiView::updateEmbeddedFiles()
974 updateDialog("embedding", "");
978 void GuiView::autoSave()
980 LYXERR(Debug::INFO, "Running autoSave()");
983 view()->buffer().autoSave();
987 void GuiView::resetAutosaveTimers()
990 d.autosave_timeout_->restart();
994 void GuiView::dispatch(FuncRequest const & cmd)
997 case LFUN_BUFFER_SWITCH:
998 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1001 case LFUN_COMMAND_EXECUTE: {
1002 bool const show_it = cmd.argument() != "off";
1003 d.toolbars_->showCommandBuffer(show_it);
1006 case LFUN_DROP_LAYOUTS_CHOICE:
1007 d.toolbars_->openLayoutList();
1010 case LFUN_MENU_OPEN:
1011 d.menubar_->openByName(toqstr(cmd.argument()));
1014 case LFUN_TOOLBAR_TOGGLE: {
1015 string const name = cmd.getArg(0);
1016 bool const allowauto = cmd.getArg(1) == "allowauto";
1017 // it is possible to get current toolbar status like this,...
1018 // but I decide to obey the order of ToolbarBackend::flags
1019 // and disregard real toolbar status.
1020 // toolbars_->saveToolbarInfo();
1022 // toggle state on/off/auto
1023 d.toolbars_->toggleToolbarState(name, allowauto);
1027 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1029 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1033 if (tbi->flags & ToolbarInfo::ON)
1035 else if (tbi->flags & ToolbarInfo::OFF)
1037 else if (tbi->flags & ToolbarInfo::AUTO)
1040 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1041 _(tbi->gui_name), state));
1046 theLyXFunc().setLyXView(this);
1052 Buffer const * GuiView::updateInset(Inset const * inset)
1054 if (!d.current_work_area_)
1058 d.current_work_area_->scheduleRedraw();
1060 return &d.current_work_area_->bufferView().buffer();
1064 void GuiView::restartCursor()
1066 /* When we move around, or type, it's nice to be able to see
1067 * the cursor immediately after the keypress.
1069 if (d.current_work_area_)
1070 d.current_work_area_->startBlinkingCursor();
1075 // This list should be kept in sync with the list of insets in
1076 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1077 // dialog should have the same name as the inset.
1079 char const * const dialognames[] = {
1080 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1081 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1082 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1083 "mathdelimiter", "mathmatrix", "note", "paragraph",
1084 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1086 #ifdef HAVE_LIBAIKSAURUS
1090 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1092 char const * const * const end_dialognames =
1093 dialognames + (sizeof(dialognames) / sizeof(char *));
1097 cmpCStr(char const * name) : name_(name) {}
1098 bool operator()(char const * other) {
1099 return strcmp(other, name_) == 0;
1106 bool isValidName(string const & name)
1108 return std::find_if(dialognames, end_dialognames,
1109 cmpCStr(name.c_str())) != end_dialognames;
1115 Dialog * GuiView::find_or_build(string const & name)
1117 if (!isValidName(name))
1120 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1122 if (it != d.dialogs_.end())
1123 return it->second.get();
1125 d.dialogs_[name].reset(build(name));
1126 return d.dialogs_[name].get();
1130 void GuiView::showDialog(string const & name, string const & data,
1137 Dialog * dialog = find_or_build(name);
1139 dialog->showData(data);
1141 d.open_insets_[name] = inset;
1147 bool GuiView::isDialogVisible(string const & name) const
1149 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1150 if (it == d.dialogs_.end())
1152 return it->second.get()->isVisibleView();
1156 void GuiView::hideDialog(string const & name, Inset * inset)
1158 // Don't send the signal if we are quitting, because on MSVC it is
1159 // destructed before the cut stack in CutAndPaste.cpp, and this method
1160 // is called from some inset destructor if the cut stack is not empty
1165 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1166 if (it == d.dialogs_.end())
1169 if (inset && inset != getOpenInset(name))
1172 Dialog * const dialog = it->second.get();
1173 if (dialog->isVisibleView())
1175 d.open_insets_[name] = 0;
1179 void GuiView::disconnectDialog(string const & name)
1181 if (!isValidName(name))
1184 if (d.open_insets_.find(name) != d.open_insets_.end())
1185 d.open_insets_[name] = 0;
1189 Inset * GuiView::getOpenInset(string const & name) const
1191 if (!isValidName(name))
1194 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1195 return it == d.open_insets_.end() ? 0 : it->second;
1199 void GuiView::hideAll() 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)
1209 void GuiView::hideBufferDependent() 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) {
1215 Dialog * dialog = it->second.get();
1216 if (dialog->isBufferDependent())
1222 void GuiView::updateBufferDependent(bool switched) const
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 * dialog = it->second.get();
1229 if (switched && dialog->isBufferDependent()) {
1230 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1231 dialog->updateView();
1235 // A bit clunky, but the dialog will request
1236 // that the kernel provides it with the necessary
1238 dialog->slotRestore();
1244 void GuiView::checkStatus()
1246 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1247 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1249 for(; it != end; ++it) {
1250 Dialog * const dialog = it->second.get();
1251 if (dialog && dialog->isVisibleView())
1252 dialog->checkStatus();
1258 // will be replaced by a proper factory...
1259 Dialog * createGuiAbout(LyXView & lv);
1260 Dialog * createGuiBibitem(LyXView & lv);
1261 Dialog * createGuiBibtex(LyXView & lv);
1262 Dialog * createGuiBox(LyXView & lv);
1263 Dialog * createGuiBranch(LyXView & lv);
1264 Dialog * createGuiChanges(LyXView & lv);
1265 Dialog * createGuiCharacter(LyXView & lv);
1266 Dialog * createGuiCitation(LyXView & lv);
1267 Dialog * createGuiDelimiter(LyXView & lv);
1268 Dialog * createGuiDocument(LyXView & lv);
1269 Dialog * createGuiErrorList(LyXView & lv);
1270 Dialog * createGuiERT(LyXView & lv);
1271 Dialog * createGuiExternal(LyXView & lv);
1272 Dialog * createGuiFloat(LyXView & lv);
1273 Dialog * createGuiGraphics(LyXView & lv);
1274 Dialog * createGuiInclude(LyXView & lv);
1275 Dialog * createGuiIndex(LyXView & lv);
1276 Dialog * createGuiLabel(LyXView & lv);
1277 Dialog * createGuiListings(LyXView & lv);
1278 Dialog * createGuiLog(LyXView & lv);
1279 Dialog * createGuiMathMatrix(LyXView & lv);
1280 Dialog * createGuiNomenclature(LyXView & lv);
1281 Dialog * createGuiNote(LyXView & lv);
1282 Dialog * createGuiParagraph(LyXView & lv);
1283 Dialog * createGuiPreferences(LyXView & lv);
1284 Dialog * createGuiPrint(LyXView & lv);
1285 Dialog * createGuiRef(LyXView & lv);
1286 Dialog * createGuiSearch(LyXView & lv);
1287 Dialog * createGuiSendTo(LyXView & lv);
1288 Dialog * createGuiShowFile(LyXView & lv);
1289 Dialog * createGuiSpellchecker(LyXView & lv);
1290 Dialog * createGuiTabularCreate(LyXView & lv);
1291 Dialog * createGuiTabular(LyXView & lv);
1292 Dialog * createGuiTexInfo(LyXView & lv);
1293 Dialog * createGuiToc(LyXView & lv);
1294 Dialog * createGuiThesaurus(LyXView & lv);
1295 Dialog * createGuiHyperlink(LyXView & lv);
1296 Dialog * createGuiVSpace(LyXView & lv);
1297 Dialog * createGuiViewSource(LyXView & lv);
1298 Dialog * createGuiWrap(LyXView & lv);
1301 Dialog * GuiView::build(string const & name)
1303 BOOST_ASSERT(isValidName(name));
1305 if (name == "aboutlyx")
1306 return createGuiAbout(*this);
1307 if (name == "bibitem")
1308 return createGuiBibitem(*this);
1309 if (name == "bibtex")
1310 return createGuiBibtex(*this);
1312 return createGuiBox(*this);
1313 if (name == "branch")
1314 return createGuiBranch(*this);
1315 if (name == "changes")
1316 return createGuiChanges(*this);
1317 if (name == "character")
1318 return createGuiCharacter(*this);
1319 if (name == "citation")
1320 return createGuiCitation(*this);
1321 if (name == "document")
1322 return createGuiDocument(*this);
1323 if (name == "errorlist")
1324 return createGuiErrorList(*this);
1326 return createGuiERT(*this);
1327 if (name == "external")
1328 return createGuiExternal(*this);
1330 return createGuiShowFile(*this);
1331 if (name == "findreplace")
1332 return createGuiSearch(*this);
1333 if (name == "float")
1334 return createGuiFloat(*this);
1335 if (name == "graphics")
1336 return createGuiGraphics(*this);
1337 if (name == "include")
1338 return createGuiInclude(*this);
1339 if (name == "index")
1340 return createGuiIndex(*this);
1341 if (name == "nomenclature")
1342 return createGuiNomenclature(*this);
1343 if (name == "label")
1344 return createGuiLabel(*this);
1346 return createGuiLog(*this);
1347 if (name == "view-source")
1348 return createGuiViewSource(*this);
1349 if (name == "mathdelimiter")
1350 return createGuiDelimiter(*this);
1351 if (name == "mathmatrix")
1352 return createGuiMathMatrix(*this);
1354 return createGuiNote(*this);
1355 if (name == "paragraph")
1356 return createGuiParagraph(*this);
1357 if (name == "prefs")
1358 return createGuiPreferences(*this);
1359 if (name == "print")
1360 return createGuiPrint(*this);
1362 return createGuiRef(*this);
1363 if (name == "sendto")
1364 return createGuiSendTo(*this);
1365 if (name == "spellchecker")
1366 return createGuiSpellchecker(*this);
1367 if (name == "tabular")
1368 return createGuiTabular(*this);
1369 if (name == "tabularcreate")
1370 return createGuiTabularCreate(*this);
1371 if (name == "texinfo")
1372 return createGuiTexInfo(*this);
1373 #ifdef HAVE_LIBAIKSAURUS
1374 if (name == "thesaurus")
1375 return createGuiThesaurus(*this);
1378 return createGuiToc(*this);
1380 return createGuiHyperlink(*this);
1381 if (name == "vspace")
1382 return createGuiVSpace(*this);
1384 return createGuiWrap(*this);
1385 if (name == "listings")
1386 return createGuiListings(*this);
1392 } // namespace frontend
1395 #include "GuiView_moc.cpp"