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);
327 setMinimumSize(300, 200);
328 // GuiToolbars *must* be initialised before GuiMenubar.
329 d.toolbars_ = new GuiToolbars(*this);
331 d.menubar_ = new GuiMenubar(this, menubackend);
333 statusBar()->setSizeGripEnabled(true);
335 QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
336 this, SLOT(clearMessage()));
340 if (!lyxrc.allow_geometry_session)
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());
361 delete autosave_timeout_;
366 void GuiView::close()
368 quitting_by_menu_ = true;
369 d.current_work_area_ = 0;
370 for (int i = 0; i != d.splitter_->count(); ++i) {
371 TabWorkArea * twa = d.tabWorkArea(i);
375 QMainWindow::close();
376 quitting_by_menu_ = false;
380 void GuiView::setFocus()
382 if (d.current_work_area_)
383 d.current_work_area_->setFocus();
389 QMenu* GuiView::createPopupMenu()
391 return d.toolBarPopup(this);
395 void GuiView::showEvent(QShowEvent * e)
397 LYXERR(Debug::GUI, "Passed Geometry "
398 << size().height() << "x" << size().width()
399 << "+" << pos().x() << "+" << pos().y());
401 if (d.splitter_->count() == 0)
402 // No work area, switch to the background widget.
405 QMainWindow::showEvent(e);
409 void GuiView::closeEvent(QCloseEvent * close_event)
411 // we may have been called through the close window button
412 // which bypasses the LFUN machinery.
413 if (!quitting_by_menu_ && guiApp->viewCount() == 1) {
414 if (!theBufferList().quitWriteAll()) {
415 close_event->ignore();
420 // Make sure that no LFUN use this close to be closed View.
421 theLyXFunc().setLyXView(0);
422 // Make sure the timer time out will not trigger a statusbar update.
423 statusbar_timer_.stop();
425 if (lyxrc.allow_geometry_session) {
427 QString const key = "view-" + QString::number(id());
429 settings.setValue(key + "/pos", pos());
430 settings.setValue(key + "/size", size());
432 settings.setValue(key + "/geometry", saveGeometry());
434 settings.setValue(key + "/icon_size", iconSize());
435 d.toolbars_->saveToolbarInfo();
438 guiApp->unregisterView(id());
439 if (guiApp->viewCount() > 0) {
440 // Just close the window and do nothing else if this is not the
442 close_event->accept();
448 // this is the place where we leave the frontend.
449 // it is the only point at which we start quitting.
450 close_event->accept();
451 // quit the event loop
456 void GuiView::dragEnterEvent(QDragEnterEvent * event)
458 if (event->mimeData()->hasUrls())
460 /// \todo Ask lyx-devel is this is enough:
461 /// if (event->mimeData()->hasFormat("text/plain"))
462 /// event->acceptProposedAction();
466 void GuiView::dropEvent(QDropEvent* event)
468 QList<QUrl> files = event->mimeData()->urls();
472 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
473 for (int i = 0; i != files.size(); ++i) {
474 string const file = support::os::internal_path(fromqstr(
475 files.at(i).toLocalFile()));
477 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
482 void GuiView::message(docstring const & str)
484 statusBar()->showMessage(toqstr(str));
485 statusbar_timer_.stop();
486 statusbar_timer_.start(statusbar_timer_value);
490 void GuiView::smallSizedIcons()
492 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
496 void GuiView::normalSizedIcons()
498 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
502 void GuiView::bigSizedIcons()
504 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
508 void GuiView::clearMessage()
512 theLyXFunc().setLyXView(this);
513 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
514 statusbar_timer_.stop();
518 void GuiView::updateWindowTitle(GuiWorkArea * wa)
520 if (wa != d.current_work_area_)
522 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
523 setWindowIconText(wa->windowIconText());
527 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
530 disconnectBufferView();
531 connectBufferView(wa->bufferView());
532 connectBuffer(wa->bufferView().buffer());
533 d.current_work_area_ = wa;
534 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
535 this, SLOT(updateWindowTitle(GuiWorkArea *)));
536 updateWindowTitle(wa);
539 // Buffer-dependent dialogs should be updated or
540 // hidden. This should go here because some dialogs (eg ToC)
541 // require bv_->text.
542 updateBufferDependent(true);
544 updateLayoutChoice(false);
549 void GuiView::updateStatusBar()
551 // let the user see the explicit message
552 if (statusbar_timer_.isActive())
555 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
559 bool GuiView::hasFocus() const
561 return qApp->activeWindow() == this;
565 bool GuiView::event(QEvent * e)
569 // Useful debug code:
570 //case QEvent::ActivationChange:
571 //case QEvent::WindowDeactivate:
572 //case QEvent::Paint:
573 //case QEvent::Enter:
574 //case QEvent::Leave:
575 //case QEvent::HoverEnter:
576 //case QEvent::HoverLeave:
577 //case QEvent::HoverMove:
578 //case QEvent::StatusTip:
579 //case QEvent::DragEnter:
580 //case QEvent::DragLeave:
584 case QEvent::WindowActivate: {
585 guiApp->setCurrentView(*this);
586 if (d.current_work_area_) {
587 BufferView & bv = d.current_work_area_->bufferView();
588 connectBufferView(bv);
589 connectBuffer(bv.buffer());
590 // The document structure, name and dialogs might have
591 // changed in another view.
592 updateBufferDependent(true);
594 setWindowTitle(qt_("LyX"));
595 setWindowIconText(qt_("LyX"));
597 return QMainWindow::event(e);
599 case QEvent::ShortcutOverride: {
600 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
601 if (!d.current_work_area_) {
602 theLyXFunc().setLyXView(this);
604 setKeySymbol(&sym, ke);
605 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
609 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
611 setKeySymbol(&sym, ke);
612 d.current_work_area_->processKeySym(sym, NoModifier);
618 return QMainWindow::event(e);
623 bool GuiView::focusNextPrevChild(bool /*next*/)
630 void GuiView::setBusy(bool yes)
632 if (d.current_work_area_) {
633 d.current_work_area_->setUpdatesEnabled(!yes);
635 d.current_work_area_->stopBlinkingCursor();
637 d.current_work_area_->startBlinkingCursor();
641 QApplication::setOverrideCursor(Qt::WaitCursor);
643 QApplication::restoreOverrideCursor();
647 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
649 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
651 if (tbinfo.flags & ToolbarInfo::TOP) {
653 addToolBarBreak(Qt::TopToolBarArea);
654 addToolBar(Qt::TopToolBarArea, toolBar);
657 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
658 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
659 #if (QT_VERSION >= 0x040202)
661 addToolBarBreak(Qt::BottomToolBarArea);
663 addToolBar(Qt::BottomToolBarArea, toolBar);
666 if (tbinfo.flags & ToolbarInfo::LEFT) {
667 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
668 #if (QT_VERSION >= 0x040202)
670 addToolBarBreak(Qt::LeftToolBarArea);
672 addToolBar(Qt::LeftToolBarArea, toolBar);
675 if (tbinfo.flags & ToolbarInfo::RIGHT) {
676 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
677 #if (QT_VERSION >= 0x040202)
679 addToolBarBreak(Qt::RightToolBarArea);
681 addToolBar(Qt::RightToolBarArea, toolBar);
684 // The following does not work so I cannot restore to exact toolbar location
686 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
687 toolBar->move(tbinfo.posx, tbinfo.posy);
694 GuiWorkArea * GuiView::workArea(Buffer & buffer)
696 for (int i = 0; i != d.splitter_->count(); ++i) {
697 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
705 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
707 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
708 wa->setUpdatesEnabled(false);
710 // Automatically create a TabWorkArea if there are none yet.
711 if (!d.splitter_->count())
714 TabWorkArea * tab_widget = d.currentTabWorkArea();
715 tab_widget->addTab(wa, wa->windowTitle());
716 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
717 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
719 wa->bufferView().updateMetrics();
721 // Hide tabbar if there's only one tab.
722 tab_widget->showBar(tab_widget->count() > 1);
727 void GuiView::addTabWorkArea()
729 TabWorkArea * twa = new TabWorkArea;
730 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
731 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
732 d.splitter_->addWidget(twa);
733 d.stack_widget_->setCurrentWidget(d.splitter_);
737 GuiWorkArea const * GuiView::currentWorkArea() const
739 return d.current_work_area_;
743 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
745 BOOST_ASSERT(work_area);
747 // Changing work area can result from opening a file so
748 // update the toc in any case.
751 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
752 d.current_work_area_ = wa;
753 for (int i = 0; i != d.splitter_->count(); ++i) {
754 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
760 void GuiView::removeWorkArea(GuiWorkArea * work_area)
762 BOOST_ASSERT(work_area);
763 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
764 if (gwa == d.current_work_area_) {
766 disconnectBufferView();
767 hideBufferDependent();
768 d.current_work_area_ = 0;
771 // removing a work area often results from closing a file so
772 // update the toc in any case.
775 for (int i = 0; i != d.splitter_->count(); ++i) {
776 TabWorkArea * twa = d.tabWorkArea(i);
777 if (!twa->removeWorkArea(gwa))
778 // Not found in this tab group.
781 // We found and removed the GuiWorkArea.
783 // No more WorkAreas in this tab group, so delete it.
788 if (d.current_work_area_)
789 // This means that we are not closing the current GuiWorkArea;
792 // Switch to the next GuiWorkArea in the found TabWorkArea.
793 d.current_work_area_ = twa->currentWorkArea();
797 if (d.splitter_->count() == 0)
798 // No more work area, switch to the background widget.
803 void GuiView::updateLayoutChoice(bool force)
805 // Don't show any layouts without a buffer
807 d.toolbars_->clearLayoutList();
811 // Update the layout display
812 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
813 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
816 docstring const & layout = d.current_work_area_->bufferView().cursor().
817 innerParagraph().layout()->name();
819 if (layout != d.current_layout) {
820 d.toolbars_->setLayout(layout);
821 d.current_layout = layout;
826 bool GuiView::isToolbarVisible(std::string const & id)
828 return d.toolbars_->visible(id);
831 void GuiView::updateToolbars()
833 if (d.current_work_area_) {
835 d.current_work_area_->bufferView().cursor().inMathed();
837 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
839 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
840 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
842 d.toolbars_->update(math, table, review);
844 d.toolbars_->update(false, false, false);
846 // update read-only status of open dialogs.
851 Buffer * GuiView::buffer()
853 if (d.current_work_area_)
854 return &d.current_work_area_->bufferView().buffer();
859 Buffer const * GuiView::buffer() const
861 if (d.current_work_area_)
862 return &d.current_work_area_->bufferView().buffer();
867 void GuiView::setBuffer(Buffer * newBuffer)
869 BOOST_ASSERT(newBuffer);
872 GuiWorkArea * wa = workArea(*newBuffer);
874 updateLabels(*newBuffer->masterBuffer());
875 wa = addWorkArea(*newBuffer);
877 //Disconnect the old buffer...there's no new one.
880 connectBuffer(*newBuffer);
881 connectBufferView(wa->bufferView());
882 setCurrentWorkArea(wa);
888 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
892 Buffer * newBuffer = checkAndLoadLyXFile(filename);
895 message(_("Document not loaded."));
901 GuiWorkArea * wa = workArea(*newBuffer);
903 wa = addWorkArea(*newBuffer);
905 // scroll to the position when the file was last closed
906 if (lyxrc.use_lastfilepos) {
907 LastFilePosSection::FilePos filepos =
908 LyX::ref().session().lastFilePos().load(filename);
909 // if successfully move to pit (returned par_id is not zero),
910 // update metrics and reset font
911 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
915 LyX::ref().session().lastFiles().add(filename);
922 void GuiView::connectBuffer(Buffer & buf)
924 buf.setGuiDelegate(this);
928 void GuiView::disconnectBuffer()
930 if (d.current_work_area_)
931 d.current_work_area_->bufferView().setGuiDelegate(0);
935 void GuiView::connectBufferView(BufferView & bv)
937 bv.setGuiDelegate(this);
941 void GuiView::disconnectBufferView()
943 if (d.current_work_area_)
944 d.current_work_area_->bufferView().setGuiDelegate(0);
948 void GuiView::errors(string const & error_type)
950 ErrorList & el = buffer()->errorList(error_type);
952 showDialog("errorlist", error_type);
956 void GuiView::updateDialog(string const & name, string const & data)
958 if (!isDialogVisible(name))
961 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
962 if (it == d.dialogs_.end())
965 Dialog * const dialog = it->second.get();
966 if (dialog->isVisibleView())
967 dialog->updateData(data);
971 BufferView * GuiView::view()
973 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
977 void GuiView::updateToc()
979 updateDialog("toc", "");
983 void GuiView::updateEmbeddedFiles()
985 updateDialog("embedding", "");
989 void GuiView::autoSave()
991 LYXERR(Debug::INFO, "Running autoSave()");
994 view()->buffer().autoSave();
998 void GuiView::resetAutosaveTimers()
1001 autosave_timeout_->restart();
1005 void GuiView::dispatch(FuncRequest const & cmd)
1007 switch(cmd.action) {
1008 case LFUN_BUFFER_SWITCH:
1009 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1012 case LFUN_COMMAND_EXECUTE: {
1013 bool const show_it = cmd.argument() != "off";
1014 d.toolbars_->showCommandBuffer(show_it);
1017 case LFUN_DROP_LAYOUTS_CHOICE:
1018 d.toolbars_->openLayoutList();
1021 case LFUN_MENU_OPEN:
1022 d.menubar_->openByName(toqstr(cmd.argument()));
1025 case LFUN_TOOLBAR_TOGGLE: {
1026 string const name = cmd.getArg(0);
1027 bool const allowauto = cmd.getArg(1) == "allowauto";
1028 // it is possible to get current toolbar status like this,...
1029 // but I decide to obey the order of ToolbarBackend::flags
1030 // and disregard real toolbar status.
1031 // toolbars_->saveToolbarInfo();
1033 // toggle state on/off/auto
1034 d.toolbars_->toggleToolbarState(name, allowauto);
1038 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1040 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1044 if (tbi->flags & ToolbarInfo::ON)
1046 else if (tbi->flags & ToolbarInfo::OFF)
1048 else if (tbi->flags & ToolbarInfo::AUTO)
1051 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1052 _(tbi->gui_name), state));
1057 theLyXFunc().setLyXView(this);
1063 Buffer const * GuiView::updateInset(Inset const * inset)
1065 if (!d.current_work_area_)
1069 d.current_work_area_->scheduleRedraw();
1071 return &d.current_work_area_->bufferView().buffer();
1075 void GuiView::restartCursor()
1077 /* When we move around, or type, it's nice to be able to see
1078 * the cursor immediately after the keypress.
1080 if (d.current_work_area_)
1081 d.current_work_area_->startBlinkingCursor();
1085 Dialog * GuiView::find_or_build(string const & name)
1087 if (!isValidName(name))
1090 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1092 if (it != d.dialogs_.end())
1093 return it->second.get();
1095 d.dialogs_[name].reset(build(name));
1096 return d.dialogs_[name].get();
1100 void GuiView::showDialog(string const & name, string const & data,
1107 Dialog * dialog = find_or_build(name);
1109 dialog->showData(data);
1111 d.open_insets_[name] = inset;
1117 bool GuiView::isDialogVisible(string const & name) const
1119 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1120 if (it == d.dialogs_.end())
1122 return it->second.get()->isVisibleView();
1126 void GuiView::hideDialog(string const & name, Inset * inset)
1128 // Don't send the signal if we are quitting, because on MSVC it is
1129 // destructed before the cut stack in CutAndPaste.cpp, and this method
1130 // is called from some inset destructor if the cut stack is not empty
1135 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1136 if (it == d.dialogs_.end())
1139 if (inset && inset != getOpenInset(name))
1142 Dialog * const dialog = it->second.get();
1143 if (dialog->isVisibleView())
1145 d.open_insets_[name] = 0;
1149 void GuiView::disconnectDialog(string const & name)
1151 if (!isValidName(name))
1154 if (d.open_insets_.find(name) != d.open_insets_.end())
1155 d.open_insets_[name] = 0;
1159 Inset * GuiView::getOpenInset(string const & name) const
1161 if (!isValidName(name))
1164 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1165 return it == d.open_insets_.end() ? 0 : it->second;
1169 void GuiView::hideAll() const
1171 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1172 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1174 for(; it != end; ++it)
1179 void GuiView::hideBufferDependent() const
1181 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1182 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1184 for(; it != end; ++it) {
1185 Dialog * dialog = it->second.get();
1186 if (dialog->isBufferDependent())
1192 void GuiView::updateBufferDependent(bool switched) const
1194 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1195 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1197 for(; it != end; ++it) {
1198 Dialog * dialog = it->second.get();
1199 if (switched && dialog->isBufferDependent()) {
1200 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1201 dialog->updateView();
1205 // A bit clunky, but the dialog will request
1206 // that the kernel provides it with the necessary
1208 dialog->slotRestore();
1214 void GuiView::redrawDialog() const
1216 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1217 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1219 for(; it != end; ++it)
1220 it->second->redraw();
1224 void GuiView::checkStatus()
1226 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1227 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1229 for(; it != end; ++it) {
1230 Dialog * const dialog = it->second.get();
1231 if (dialog && dialog->isVisibleView())
1232 dialog->checkStatus();
1239 // This list should be kept in sync with the list of insets in
1240 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1241 // dialog should have the same name as the inset.
1243 char const * const dialognames[] = {
1244 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1245 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1246 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1247 "mathdelimiter", "mathmatrix", "note", "paragraph",
1248 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1250 #ifdef HAVE_LIBAIKSAURUS
1254 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1256 char const * const * const end_dialognames =
1257 dialognames + (sizeof(dialognames) / sizeof(char *));
1261 cmpCStr(char const * name) : name_(name) {}
1262 bool operator()(char const * other) {
1263 return strcmp(other, name_) == 0;
1272 // will be replaced by a proper factory...
1273 Dialog * createGuiAbout(LyXView & lv);
1274 Dialog * createGuiBibitem(LyXView & lv);
1275 Dialog * createGuiBibtex(LyXView & lv);
1276 Dialog * createGuiBox(LyXView & lv);
1277 Dialog * createGuiBranch(LyXView & lv);
1278 Dialog * createGuiChanges(LyXView & lv);
1279 Dialog * createGuiCharacter(LyXView & lv);
1280 Dialog * createGuiCitation(LyXView & lv);
1281 Dialog * createGuiDelimiter(LyXView & lv);
1282 Dialog * createGuiDocument(LyXView & lv);
1283 Dialog * createGuiErrorList(LyXView & lv);
1284 Dialog * createGuiERT(LyXView & lv);
1285 Dialog * createGuiExternal(LyXView & lv);
1286 Dialog * createGuiFloat(LyXView & lv);
1287 Dialog * createGuiGraphics(LyXView & lv);
1288 Dialog * createGuiInclude(LyXView & lv);
1289 Dialog * createGuiIndex(LyXView & lv);
1290 Dialog * createGuiLabel(LyXView & lv);
1291 Dialog * createGuiListings(LyXView & lv);
1292 Dialog * createGuiLog(LyXView & lv);
1293 Dialog * createGuiMathMatrix(LyXView & lv);
1294 Dialog * createGuiNomenclature(LyXView & lv);
1295 Dialog * createGuiNote(LyXView & lv);
1296 Dialog * createGuiParagraph(LyXView & lv);
1297 Dialog * createGuiPreferences(LyXView & lv);
1298 Dialog * createGuiPrint(LyXView & lv);
1299 Dialog * createGuiRef(LyXView & lv);
1300 Dialog * createGuiSearch(LyXView & lv);
1301 Dialog * createGuiSendTo(LyXView & lv);
1302 Dialog * createGuiShowFile(LyXView & lv);
1303 Dialog * createGuiSpellchecker(LyXView & lv);
1304 Dialog * createGuiTabularCreate(LyXView & lv);
1305 Dialog * createGuiTabular(LyXView & lv);
1306 Dialog * createGuiTexInfo(LyXView & lv);
1307 Dialog * createGuiToc(LyXView & lv);
1308 Dialog * createGuiThesaurus(LyXView & lv);
1309 Dialog * createGuiHyperlink(LyXView & lv);
1310 Dialog * createGuiVSpace(LyXView & lv);
1311 Dialog * createGuiViewSource(LyXView & lv);
1312 Dialog * createGuiWrap(LyXView & lv);
1315 bool GuiView::isValidName(string const & name) const
1317 return std::find_if(dialognames, end_dialognames,
1318 cmpCStr(name.c_str())) != end_dialognames;
1322 Dialog * GuiView::build(string const & name)
1324 BOOST_ASSERT(isValidName(name));
1326 if (name == "aboutlyx")
1327 return createGuiAbout(*this);
1328 if (name == "bibitem")
1329 return createGuiBibitem(*this);
1330 if (name == "bibtex")
1331 return createGuiBibtex(*this);
1333 return createGuiBox(*this);
1334 if (name == "branch")
1335 return createGuiBranch(*this);
1336 if (name == "changes")
1337 return createGuiChanges(*this);
1338 if (name == "character")
1339 return createGuiCharacter(*this);
1340 if (name == "citation")
1341 return createGuiCitation(*this);
1342 if (name == "document")
1343 return createGuiDocument(*this);
1344 if (name == "errorlist")
1345 return createGuiErrorList(*this);
1347 return createGuiERT(*this);
1348 if (name == "external")
1349 return createGuiExternal(*this);
1351 return createGuiShowFile(*this);
1352 if (name == "findreplace")
1353 return createGuiSearch(*this);
1354 if (name == "float")
1355 return createGuiFloat(*this);
1356 if (name == "graphics")
1357 return createGuiGraphics(*this);
1358 if (name == "include")
1359 return createGuiInclude(*this);
1360 if (name == "index")
1361 return createGuiIndex(*this);
1362 if (name == "nomenclature")
1363 return createGuiNomenclature(*this);
1364 if (name == "label")
1365 return createGuiLabel(*this);
1367 return createGuiLog(*this);
1368 if (name == "view-source")
1369 return createGuiViewSource(*this);
1370 if (name == "mathdelimiter")
1371 return createGuiDelimiter(*this);
1372 if (name == "mathmatrix")
1373 return createGuiMathMatrix(*this);
1375 return createGuiNote(*this);
1376 if (name == "paragraph")
1377 return createGuiParagraph(*this);
1378 if (name == "prefs")
1379 return createGuiPreferences(*this);
1380 if (name == "print")
1381 return createGuiPrint(*this);
1383 return createGuiRef(*this);
1384 if (name == "sendto")
1385 return createGuiSendTo(*this);
1386 if (name == "spellchecker")
1387 return createGuiSpellchecker(*this);
1388 if (name == "tabular")
1389 return createGuiTabular(*this);
1390 if (name == "tabularcreate")
1391 return createGuiTabularCreate(*this);
1392 if (name == "texinfo")
1393 return createGuiTexInfo(*this);
1394 #ifdef HAVE_LIBAIKSAURUS
1395 if (name == "thesaurus")
1396 return createGuiThesaurus(*this);
1399 return createGuiToc(*this);
1401 return createGuiHyperlink(*this);
1402 if (name == "vspace")
1403 return createGuiVSpace(*this);
1405 return createGuiWrap(*this);
1406 if (name == "listings")
1407 return createGuiListings(*this);
1413 } // namespace frontend
1416 #include "GuiView_moc.cpp"