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);
333 delete autosave_timeout_;
338 void GuiView::close()
340 quitting_by_menu_ = true;
341 d.current_work_area_ = 0;
342 for (int i = 0; i != d.splitter_->count(); ++i) {
343 TabWorkArea * twa = d.tabWorkArea(i);
347 QMainWindow::close();
348 quitting_by_menu_ = false;
352 void GuiView::setFocus()
354 if (d.current_work_area_)
355 d.current_work_area_->setFocus();
361 QMenu* GuiView::createPopupMenu()
363 return d.toolBarPopup(this);
369 setMinimumSize(300, 200);
370 // GuiToolbars *must* be initialised before GuiMenubar.
371 d.toolbars_ = new GuiToolbars(*this);
372 // FIXME: GuiToolbars::init() cannot be integrated in the ctor
373 // because LyXFunc::getStatus() needs a properly initialized
374 // GuiToolbars object (for LFUN_TOOLBAR_TOGGLE).
376 d.menubar_ = new GuiMenubar(this, menubackend);
378 statusBar()->setSizeGripEnabled(true);
380 QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
381 this, SLOT(clearMessage()));
385 if (!lyxrc.allow_geometry_session)
386 setGeometry(50, 50, 690, 510);
388 // Now take care of session management.
390 QString const key = "view-" + QString::number(id());
392 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
393 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
397 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
398 setGeometry(50, 50, 690, 510);
400 setIconSize(settings.value(key + "/icon_size").toSize());
404 void GuiView::showEvent(QShowEvent * e)
406 LYXERR(Debug::GUI, "Passed Geometry "
407 << size().height() << "x" << size().width()
408 << "+" << pos().x() << "+" << pos().y());
410 if (d.splitter_->count() == 0)
411 // No work area, switch to the background widget.
414 QMainWindow::showEvent(e);
418 void GuiView::closeEvent(QCloseEvent * close_event)
420 // we may have been called through the close window button
421 // which bypasses the LFUN machinery.
422 if (!quitting_by_menu_ && guiApp->viewCount() == 1) {
423 if (!theBufferList().quitWriteAll()) {
424 close_event->ignore();
429 // Make sure that no LFUN use this close to be closed View.
430 theLyXFunc().setLyXView(0);
431 // Make sure the timer time out will not trigger a statusbar update.
432 statusbar_timer_.stop();
434 if (lyxrc.allow_geometry_session) {
436 QString const key = "view-" + QString::number(id());
438 settings.setValue(key + "/pos", pos());
439 settings.setValue(key + "/size", size());
441 settings.setValue(key + "/geometry", saveGeometry());
443 settings.setValue(key + "/icon_size", iconSize());
444 d.toolbars_->saveToolbarInfo();
447 guiApp->unregisterView(id());
448 if (guiApp->viewCount() > 0) {
449 // Just close the window and do nothing else if this is not the
451 close_event->accept();
457 // this is the place where we leave the frontend.
458 // it is the only point at which we start quitting.
459 close_event->accept();
460 // quit the event loop
465 void GuiView::dragEnterEvent(QDragEnterEvent * event)
467 if (event->mimeData()->hasUrls())
469 /// \todo Ask lyx-devel is this is enough:
470 /// if (event->mimeData()->hasFormat("text/plain"))
471 /// event->acceptProposedAction();
475 void GuiView::dropEvent(QDropEvent* event)
477 QList<QUrl> files = event->mimeData()->urls();
481 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
482 for (int i = 0; i != files.size(); ++i) {
483 string const file = support::os::internal_path(fromqstr(
484 files.at(i).toLocalFile()));
486 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
491 void GuiView::message(docstring const & str)
493 statusBar()->showMessage(toqstr(str));
494 statusbar_timer_.stop();
495 statusbar_timer_.start(statusbar_timer_value);
499 void GuiView::smallSizedIcons()
501 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
505 void GuiView::normalSizedIcons()
507 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
511 void GuiView::bigSizedIcons()
513 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
517 void GuiView::clearMessage()
521 theLyXFunc().setLyXView(this);
522 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
523 statusbar_timer_.stop();
527 void GuiView::updateWindowTitle(GuiWorkArea * wa)
529 if (wa != d.current_work_area_)
531 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
532 setWindowIconText(wa->windowIconText());
536 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
539 disconnectBufferView();
540 connectBufferView(wa->bufferView());
541 connectBuffer(wa->bufferView().buffer());
542 d.current_work_area_ = wa;
543 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
544 this, SLOT(updateWindowTitle(GuiWorkArea *)));
545 updateWindowTitle(wa);
548 // Buffer-dependent dialogs should be updated or
549 // hidden. This should go here because some dialogs (eg ToC)
550 // require bv_->text.
551 updateBufferDependent(true);
553 updateLayoutChoice(false);
558 void GuiView::updateStatusBar()
560 // let the user see the explicit message
561 if (statusbar_timer_.isActive())
564 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
568 bool GuiView::hasFocus() const
570 return qApp->activeWindow() == this;
574 bool GuiView::event(QEvent * e)
578 // Useful debug code:
579 //case QEvent::ActivationChange:
580 //case QEvent::WindowDeactivate:
581 //case QEvent::Paint:
582 //case QEvent::Enter:
583 //case QEvent::Leave:
584 //case QEvent::HoverEnter:
585 //case QEvent::HoverLeave:
586 //case QEvent::HoverMove:
587 //case QEvent::StatusTip:
588 //case QEvent::DragEnter:
589 //case QEvent::DragLeave:
593 case QEvent::WindowActivate: {
594 guiApp->setCurrentView(*this);
595 if (d.current_work_area_) {
596 BufferView & bv = d.current_work_area_->bufferView();
597 connectBufferView(bv);
598 connectBuffer(bv.buffer());
599 // The document structure, name and dialogs might have
600 // changed in another view.
601 updateBufferDependent(true);
603 setWindowTitle(qt_("LyX"));
604 setWindowIconText(qt_("LyX"));
606 return QMainWindow::event(e);
608 case QEvent::ShortcutOverride: {
609 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
610 if (!d.current_work_area_) {
611 theLyXFunc().setLyXView(this);
613 setKeySymbol(&sym, ke);
614 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
618 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
620 setKeySymbol(&sym, ke);
621 d.current_work_area_->processKeySym(sym, NoModifier);
627 return QMainWindow::event(e);
632 bool GuiView::focusNextPrevChild(bool /*next*/)
639 void GuiView::setBusy(bool yes)
641 if (d.current_work_area_) {
642 d.current_work_area_->setUpdatesEnabled(!yes);
644 d.current_work_area_->stopBlinkingCursor();
646 d.current_work_area_->startBlinkingCursor();
650 QApplication::setOverrideCursor(Qt::WaitCursor);
652 QApplication::restoreOverrideCursor();
656 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
658 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
660 if (tbinfo.flags & ToolbarInfo::TOP) {
662 addToolBarBreak(Qt::TopToolBarArea);
663 addToolBar(Qt::TopToolBarArea, toolBar);
666 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
667 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
668 #if (QT_VERSION >= 0x040202)
670 addToolBarBreak(Qt::BottomToolBarArea);
672 addToolBar(Qt::BottomToolBarArea, toolBar);
675 if (tbinfo.flags & ToolbarInfo::LEFT) {
676 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
677 #if (QT_VERSION >= 0x040202)
679 addToolBarBreak(Qt::LeftToolBarArea);
681 addToolBar(Qt::LeftToolBarArea, toolBar);
684 if (tbinfo.flags & ToolbarInfo::RIGHT) {
685 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
686 #if (QT_VERSION >= 0x040202)
688 addToolBarBreak(Qt::RightToolBarArea);
690 addToolBar(Qt::RightToolBarArea, toolBar);
693 // The following does not work so I cannot restore to exact toolbar location
695 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
696 toolBar->move(tbinfo.posx, tbinfo.posy);
703 GuiWorkArea * GuiView::workArea(Buffer & buffer)
705 for (int i = 0; i != d.splitter_->count(); ++i) {
706 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
714 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
716 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
717 wa->setUpdatesEnabled(false);
719 // Automatically create a TabWorkArea if there are none yet.
720 if (!d.splitter_->count())
723 TabWorkArea * tab_widget = d.currentTabWorkArea();
724 tab_widget->addTab(wa, wa->windowTitle());
725 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
726 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
728 wa->bufferView().updateMetrics();
730 // Hide tabbar if there's only one tab.
731 tab_widget->showBar(tab_widget->count() > 1);
736 void GuiView::addTabWorkArea()
738 TabWorkArea * twa = new TabWorkArea;
739 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
740 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
741 d.splitter_->addWidget(twa);
742 d.stack_widget_->setCurrentWidget(d.splitter_);
746 GuiWorkArea const * GuiView::currentWorkArea() const
748 return d.current_work_area_;
752 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
754 BOOST_ASSERT(work_area);
756 // Changing work area can result from opening a file so
757 // update the toc in any case.
760 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
761 d.current_work_area_ = wa;
762 for (int i = 0; i != d.splitter_->count(); ++i) {
763 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
769 void GuiView::removeWorkArea(GuiWorkArea * work_area)
771 BOOST_ASSERT(work_area);
772 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
773 if (gwa == d.current_work_area_) {
775 disconnectBufferView();
776 hideBufferDependent();
777 d.current_work_area_ = 0;
780 // removing a work area often results from closing a file so
781 // update the toc in any case.
784 for (int i = 0; i != d.splitter_->count(); ++i) {
785 TabWorkArea * twa = d.tabWorkArea(i);
786 if (!twa->removeWorkArea(gwa))
787 // Not found in this tab group.
790 // We found and removed the GuiWorkArea.
792 // No more WorkAreas in this tab group, so delete it.
797 if (d.current_work_area_)
798 // This means that we are not closing the current GuiWorkArea;
801 // Switch to the next GuiWorkArea in the found TabWorkArea.
802 d.current_work_area_ = twa->currentWorkArea();
806 if (d.splitter_->count() == 0)
807 // No more work area, switch to the background widget.
812 void GuiView::updateLayoutChoice(bool force)
814 // Don't show any layouts without a buffer
816 d.toolbars_->clearLayoutList();
820 // Update the layout display
821 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
822 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
825 docstring const & layout = d.current_work_area_->bufferView().cursor().
826 innerParagraph().layout()->name();
828 if (layout != d.current_layout) {
829 d.toolbars_->setLayout(layout);
830 d.current_layout = layout;
835 bool GuiView::isToolbarVisible(std::string const & id)
837 return d.toolbars_->visible(id);
840 void GuiView::updateToolbars()
842 if (d.current_work_area_) {
844 d.current_work_area_->bufferView().cursor().inMathed();
846 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
848 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
849 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
851 d.toolbars_->update(math, table, review);
853 d.toolbars_->update(false, false, false);
855 // update read-only status of open dialogs.
860 Buffer * GuiView::buffer()
862 if (d.current_work_area_)
863 return &d.current_work_area_->bufferView().buffer();
868 Buffer const * GuiView::buffer() const
870 if (d.current_work_area_)
871 return &d.current_work_area_->bufferView().buffer();
876 void GuiView::setBuffer(Buffer * newBuffer)
878 BOOST_ASSERT(newBuffer);
881 GuiWorkArea * wa = workArea(*newBuffer);
883 updateLabels(*newBuffer->masterBuffer());
884 wa = addWorkArea(*newBuffer);
886 //Disconnect the old buffer...there's no new one.
889 connectBuffer(*newBuffer);
890 connectBufferView(wa->bufferView());
891 setCurrentWorkArea(wa);
897 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
901 Buffer * newBuffer = checkAndLoadLyXFile(filename);
904 message(_("Document not loaded."));
910 GuiWorkArea * wa = workArea(*newBuffer);
912 wa = addWorkArea(*newBuffer);
914 // scroll to the position when the file was last closed
915 if (lyxrc.use_lastfilepos) {
916 LastFilePosSection::FilePos filepos =
917 LyX::ref().session().lastFilePos().load(filename);
918 // if successfully move to pit (returned par_id is not zero),
919 // update metrics and reset font
920 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
924 LyX::ref().session().lastFiles().add(filename);
931 void GuiView::connectBuffer(Buffer & buf)
933 buf.setGuiDelegate(this);
937 void GuiView::disconnectBuffer()
939 if (d.current_work_area_)
940 d.current_work_area_->bufferView().setGuiDelegate(0);
944 void GuiView::connectBufferView(BufferView & bv)
946 bv.setGuiDelegate(this);
950 void GuiView::disconnectBufferView()
952 if (d.current_work_area_)
953 d.current_work_area_->bufferView().setGuiDelegate(0);
957 void GuiView::errors(string const & error_type)
959 ErrorList & el = buffer()->errorList(error_type);
961 showDialog("errorlist", error_type);
965 void GuiView::updateDialog(string const & name, string const & data)
967 if (!isDialogVisible(name))
970 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
971 if (it == d.dialogs_.end())
974 Dialog * const dialog = it->second.get();
975 if (dialog->isVisibleView())
976 dialog->updateData(data);
980 BufferView * GuiView::view()
982 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
986 void GuiView::updateToc()
988 updateDialog("toc", "");
992 void GuiView::updateEmbeddedFiles()
994 updateDialog("embedding", "");
998 void GuiView::autoSave()
1000 LYXERR(Debug::INFO, "Running autoSave()");
1003 view()->buffer().autoSave();
1007 void GuiView::resetAutosaveTimers()
1010 autosave_timeout_->restart();
1014 void GuiView::dispatch(FuncRequest const & cmd)
1016 switch(cmd.action) {
1017 case LFUN_BUFFER_SWITCH:
1018 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1021 case LFUN_COMMAND_EXECUTE: {
1022 bool const show_it = cmd.argument() != "off";
1023 d.toolbars_->showCommandBuffer(show_it);
1026 case LFUN_DROP_LAYOUTS_CHOICE:
1027 d.toolbars_->openLayoutList();
1030 case LFUN_MENU_OPEN:
1031 d.menubar_->openByName(toqstr(cmd.argument()));
1034 case LFUN_TOOLBAR_TOGGLE: {
1035 string const name = cmd.getArg(0);
1036 bool const allowauto = cmd.getArg(1) == "allowauto";
1037 // it is possible to get current toolbar status like this,...
1038 // but I decide to obey the order of ToolbarBackend::flags
1039 // and disregard real toolbar status.
1040 // toolbars_->saveToolbarInfo();
1042 // toggle state on/off/auto
1043 d.toolbars_->toggleToolbarState(name, allowauto);
1047 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1049 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1053 if (tbi->flags & ToolbarInfo::ON)
1055 else if (tbi->flags & ToolbarInfo::OFF)
1057 else if (tbi->flags & ToolbarInfo::AUTO)
1060 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1061 _(tbi->gui_name), state));
1066 theLyXFunc().setLyXView(this);
1072 Buffer const * GuiView::updateInset(Inset const * inset)
1074 if (!d.current_work_area_)
1078 d.current_work_area_->scheduleRedraw();
1080 return &d.current_work_area_->bufferView().buffer();
1084 void GuiView::restartCursor()
1086 /* When we move around, or type, it's nice to be able to see
1087 * the cursor immediately after the keypress.
1089 if (d.current_work_area_)
1090 d.current_work_area_->startBlinkingCursor();
1094 Dialog * GuiView::find_or_build(string const & name)
1096 if (!isValidName(name))
1099 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1101 if (it != d.dialogs_.end())
1102 return it->second.get();
1104 d.dialogs_[name].reset(build(name));
1105 return d.dialogs_[name].get();
1109 void GuiView::showDialog(string const & name, string const & data,
1116 Dialog * dialog = find_or_build(name);
1118 dialog->showData(data);
1120 d.open_insets_[name] = inset;
1126 bool GuiView::isDialogVisible(string const & name) const
1128 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1129 if (it == d.dialogs_.end())
1131 return it->second.get()->isVisibleView();
1135 void GuiView::hideDialog(string const & name, Inset * inset)
1137 // Don't send the signal if we are quitting, because on MSVC it is
1138 // destructed before the cut stack in CutAndPaste.cpp, and this method
1139 // is called from some inset destructor if the cut stack is not empty
1144 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1145 if (it == d.dialogs_.end())
1148 if (inset && inset != getOpenInset(name))
1151 Dialog * const dialog = it->second.get();
1152 if (dialog->isVisibleView())
1154 d.open_insets_[name] = 0;
1158 void GuiView::disconnectDialog(string const & name)
1160 if (!isValidName(name))
1163 if (d.open_insets_.find(name) != d.open_insets_.end())
1164 d.open_insets_[name] = 0;
1168 Inset * GuiView::getOpenInset(string const & name) const
1170 if (!isValidName(name))
1173 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1174 return it == d.open_insets_.end() ? 0 : it->second;
1178 void GuiView::hideAll() const
1180 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1181 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1183 for(; it != end; ++it)
1188 void GuiView::hideBufferDependent() const
1190 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1191 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1193 for(; it != end; ++it) {
1194 Dialog * dialog = it->second.get();
1195 if (dialog->isBufferDependent())
1201 void GuiView::updateBufferDependent(bool switched) const
1203 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1204 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1206 for(; it != end; ++it) {
1207 Dialog * dialog = it->second.get();
1208 if (switched && dialog->isBufferDependent()) {
1209 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1210 dialog->updateView();
1214 // A bit clunky, but the dialog will request
1215 // that the kernel provides it with the necessary
1217 dialog->slotRestore();
1223 void GuiView::redrawDialog() const
1225 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1226 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1228 for(; it != end; ++it)
1229 it->second->redraw();
1233 void GuiView::checkStatus()
1235 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1236 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1238 for(; it != end; ++it) {
1239 Dialog * const dialog = it->second.get();
1240 if (dialog && dialog->isVisibleView())
1241 dialog->checkStatus();
1248 // This list should be kept in sync with the list of insets in
1249 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1250 // dialog should have the same name as the inset.
1252 char const * const dialognames[] = {
1253 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1254 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1255 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1256 "mathdelimiter", "mathmatrix", "note", "paragraph",
1257 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1259 #ifdef HAVE_LIBAIKSAURUS
1263 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1265 char const * const * const end_dialognames =
1266 dialognames + (sizeof(dialognames) / sizeof(char *));
1270 cmpCStr(char const * name) : name_(name) {}
1271 bool operator()(char const * other) {
1272 return strcmp(other, name_) == 0;
1281 // will be replaced by a proper factory...
1282 Dialog * createGuiAbout(LyXView & lv);
1283 Dialog * createGuiBibitem(LyXView & lv);
1284 Dialog * createGuiBibtex(LyXView & lv);
1285 Dialog * createGuiBox(LyXView & lv);
1286 Dialog * createGuiBranch(LyXView & lv);
1287 Dialog * createGuiChanges(LyXView & lv);
1288 Dialog * createGuiCharacter(LyXView & lv);
1289 Dialog * createGuiCitation(LyXView & lv);
1290 Dialog * createGuiDelimiter(LyXView & lv);
1291 Dialog * createGuiDocument(LyXView & lv);
1292 Dialog * createGuiErrorList(LyXView & lv);
1293 Dialog * createGuiERT(LyXView & lv);
1294 Dialog * createGuiExternal(LyXView & lv);
1295 Dialog * createGuiFloat(LyXView & lv);
1296 Dialog * createGuiGraphics(LyXView & lv);
1297 Dialog * createGuiInclude(LyXView & lv);
1298 Dialog * createGuiIndex(LyXView & lv);
1299 Dialog * createGuiLabel(LyXView & lv);
1300 Dialog * createGuiListings(LyXView & lv);
1301 Dialog * createGuiLog(LyXView & lv);
1302 Dialog * createGuiMathMatrix(LyXView & lv);
1303 Dialog * createGuiNomenclature(LyXView & lv);
1304 Dialog * createGuiNote(LyXView & lv);
1305 Dialog * createGuiParagraph(LyXView & lv);
1306 Dialog * createGuiPreferences(LyXView & lv);
1307 Dialog * createGuiPrint(LyXView & lv);
1308 Dialog * createGuiRef(LyXView & lv);
1309 Dialog * createGuiSearch(LyXView & lv);
1310 Dialog * createGuiSendTo(LyXView & lv);
1311 Dialog * createGuiShowFile(LyXView & lv);
1312 Dialog * createGuiSpellchecker(LyXView & lv);
1313 Dialog * createGuiTabularCreate(LyXView & lv);
1314 Dialog * createGuiTabular(LyXView & lv);
1315 Dialog * createGuiTexInfo(LyXView & lv);
1316 Dialog * createGuiToc(LyXView & lv);
1317 Dialog * createGuiThesaurus(LyXView & lv);
1318 Dialog * createGuiHyperlink(LyXView & lv);
1319 Dialog * createGuiVSpace(LyXView & lv);
1320 Dialog * createGuiViewSource(LyXView & lv);
1321 Dialog * createGuiWrap(LyXView & lv);
1324 bool GuiView::isValidName(string const & name) const
1326 return std::find_if(dialognames, end_dialognames,
1327 cmpCStr(name.c_str())) != end_dialognames;
1331 Dialog * GuiView::build(string const & name)
1333 BOOST_ASSERT(isValidName(name));
1335 if (name == "aboutlyx")
1336 return createGuiAbout(*this);
1337 if (name == "bibitem")
1338 return createGuiBibitem(*this);
1339 if (name == "bibtex")
1340 return createGuiBibtex(*this);
1342 return createGuiBox(*this);
1343 if (name == "branch")
1344 return createGuiBranch(*this);
1345 if (name == "changes")
1346 return createGuiChanges(*this);
1347 if (name == "character")
1348 return createGuiCharacter(*this);
1349 if (name == "citation")
1350 return createGuiCitation(*this);
1351 if (name == "document")
1352 return createGuiDocument(*this);
1353 if (name == "errorlist")
1354 return createGuiErrorList(*this);
1356 return createGuiERT(*this);
1357 if (name == "external")
1358 return createGuiExternal(*this);
1360 return createGuiShowFile(*this);
1361 if (name == "findreplace")
1362 return createGuiSearch(*this);
1363 if (name == "float")
1364 return createGuiFloat(*this);
1365 if (name == "graphics")
1366 return createGuiGraphics(*this);
1367 if (name == "include")
1368 return createGuiInclude(*this);
1369 if (name == "index")
1370 return createGuiIndex(*this);
1371 if (name == "nomenclature")
1372 return createGuiNomenclature(*this);
1373 if (name == "label")
1374 return createGuiLabel(*this);
1376 return createGuiLog(*this);
1377 if (name == "view-source")
1378 return createGuiViewSource(*this);
1379 if (name == "mathdelimiter")
1380 return createGuiDelimiter(*this);
1381 if (name == "mathmatrix")
1382 return createGuiMathMatrix(*this);
1384 return createGuiNote(*this);
1385 if (name == "paragraph")
1386 return createGuiParagraph(*this);
1387 if (name == "prefs")
1388 return createGuiPreferences(*this);
1389 if (name == "print")
1390 return createGuiPrint(*this);
1392 return createGuiRef(*this);
1393 if (name == "sendto")
1394 return createGuiSendTo(*this);
1395 if (name == "spellchecker")
1396 return createGuiSpellchecker(*this);
1397 if (name == "tabular")
1398 return createGuiTabular(*this);
1399 if (name == "tabularcreate")
1400 return createGuiTabularCreate(*this);
1401 if (name == "texinfo")
1402 return createGuiTexInfo(*this);
1403 #ifdef HAVE_LIBAIKSAURUS
1404 if (name == "thesaurus")
1405 return createGuiThesaurus(*this);
1408 return createGuiToc(*this);
1410 return createGuiHyperlink(*this);
1411 if (name == "vspace")
1412 return createGuiVSpace(*this);
1414 return createGuiWrap(*this);
1415 if (name == "listings")
1416 return createGuiListings(*this);
1422 } // namespace frontend
1425 #include "GuiView_moc.cpp"