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 "buffer_funcs.h"
36 #include "BufferList.h"
37 #include "BufferParams.h"
38 #include "BufferView.h"
41 #include "ErrorList.h"
42 #include "FuncRequest.h"
49 #include "MenuBackend.h"
50 #include "Paragraph.h"
51 #include "TextClass.h"
53 #include "ToolbarBackend.h"
56 #include "support/convert.h"
57 #include "support/lstrings.h"
58 #include "support/os.h"
59 #include "support/Timeout.h"
62 #include <QApplication>
63 #include <QCloseEvent>
64 #include <QDesktopWidget>
65 #include <QDragEnterEvent>
72 #include <QPushButton>
76 #include <QStackedWidget>
82 #include <boost/bind.hpp>
83 #include <boost/current_function.hpp>
85 #ifdef HAVE_SYS_TIME_H
86 # include <sys/time.h>
102 using support::bformat;
106 int const statusbar_timer_value = 3000;
108 class BackgroundWidget : public QWidget
111 BackgroundWidget(QString const & file, QString const & text)
113 splash_ = new QPixmap(file);
115 lyxerr << "could not load splash screen: '" << fromqstr(file) << "'" << endl;
119 QPainter pain(splash_);
120 pain.setPen(QColor(255, 255, 0));
122 // The font used to display the version info
123 font.setStyleHint(QFont::SansSerif);
124 font.setWeight(QFont::Bold);
125 font.setPointSize(convert<int>(lyxrc.font_sizes[FONT_SIZE_LARGE]));
127 pain.drawText(260, 270, text);
130 void paintEvent(QPaintEvent *)
135 int x = (width() - splash_->width()) / 2;
136 int y = (height() - splash_->height()) / 2;
138 pain.drawPixmap(x, y, *splash_);
148 typedef boost::shared_ptr<Dialog> DialogPtr;
150 struct GuiView::GuiViewPrivate
153 : current_work_area_(0), posx_offset(0), posy_offset(0),
154 autosave_timeout_(new Timeout(5000)), quitting_by_menu_(false),
157 // hardcode here the platform specific icon size
158 smallIconSize = 14; // scaling problems
159 normalIconSize = 20; // ok, default
160 bigIconSize = 26; // better for some math icons
162 splitter_ = new QSplitter;
164 stack_widget_ = new QStackedWidget;
165 stack_widget_->addWidget(bg_widget_);
166 stack_widget_->addWidget(splitter_);
174 delete stack_widget_;
177 delete autosave_timeout_;
180 QMenu * toolBarPopup(GuiView * parent)
182 // FIXME: translation
183 QMenu * menu = new QMenu(parent);
184 QActionGroup * iconSizeGroup = new QActionGroup(parent);
186 QAction * smallIcons = new QAction(iconSizeGroup);
187 smallIcons->setText(qt_("Small-sized icons"));
188 smallIcons->setCheckable(true);
189 QObject::connect(smallIcons, SIGNAL(triggered()),
190 parent, SLOT(smallSizedIcons()));
191 menu->addAction(smallIcons);
193 QAction * normalIcons = new QAction(iconSizeGroup);
194 normalIcons->setText(qt_("Normal-sized icons"));
195 normalIcons->setCheckable(true);
196 QObject::connect(normalIcons, SIGNAL(triggered()),
197 parent, SLOT(normalSizedIcons()));
198 menu->addAction(normalIcons);
200 QAction * bigIcons = new QAction(iconSizeGroup);
201 bigIcons->setText(qt_("Big-sized icons"));
202 bigIcons->setCheckable(true);
203 QObject::connect(bigIcons, SIGNAL(triggered()),
204 parent, SLOT(bigSizedIcons()));
205 menu->addAction(bigIcons);
207 unsigned int cur = parent->iconSize().width();
208 if ( cur == parent->d.smallIconSize)
209 smallIcons->setChecked(true);
210 else if (cur == parent->d.normalIconSize)
211 normalIcons->setChecked(true);
212 else if (cur == parent->d.bigIconSize)
213 bigIcons->setChecked(true);
218 void initBackground()
220 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
221 /// The text to be written on top of the pixmap
222 QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
223 bg_widget_ = new BackgroundWidget(":/images/banner.png", text);
228 stack_widget_->setCurrentWidget(bg_widget_);
229 bg_widget_->setUpdatesEnabled(true);
232 TabWorkArea * tabWorkArea(int i)
234 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
237 TabWorkArea * currentTabWorkArea()
239 if (splitter_->count() == 1)
240 // The first TabWorkArea is always the first one, if any.
241 return tabWorkArea(0);
243 TabWorkArea * tab_widget = 0;
244 for (int i = 0; i != splitter_->count(); ++i) {
245 QWidget * w = splitter_->widget(i);
248 tab_widget = dynamic_cast<TabWorkArea *>(w);
260 GuiWorkArea * current_work_area_;
264 QSplitter * splitter_;
265 QStackedWidget * stack_widget_;
266 BackgroundWidget * bg_widget_;
268 GuiMenubar * menubar_;
270 GuiToolbars * toolbars_;
272 docstring current_layout;
275 std::map<std::string, Inset *> open_insets_;
278 std::map<std::string, DialogPtr> dialogs_;
280 unsigned int smallIconSize;
281 unsigned int normalIconSize;
282 unsigned int bigIconSize;
284 QTimer statusbar_timer_;
285 /// are we quitting by the menu?
286 bool quitting_by_menu_;
287 /// auto-saving of buffers
288 Timeout * const autosave_timeout_;
290 /// flag against a race condition due to multiclicks in Qt frontend,
296 GuiView::GuiView(int id)
297 : d(*new GuiViewPrivate), id_(id)
299 // GuiToolbars *must* be initialised before GuiMenubar.
300 d.toolbars_ = new GuiToolbars(*this);
301 d.menubar_ = new GuiMenubar(this, menubackend);
303 setCentralWidget(d.stack_widget_);
305 // Start autosave timer
306 if (lyxrc.autosave) {
307 d.autosave_timeout_->timeout.connect(boost::bind(&GuiView::autoSave, this));
308 d.autosave_timeout_->setTimeout(lyxrc.autosave * 1000);
309 d.autosave_timeout_->start();
311 QObject::connect(&d.statusbar_timer_, SIGNAL(timeout()),
312 this, SLOT(clearMessage()));
314 // Qt bug? signal lastWindowClosed does not work
315 setAttribute(Qt::WA_QuitOnClose, false);
316 setAttribute(Qt::WA_DeleteOnClose, true);
318 // assign an icon to main form. We do not do it under Qt/Mac,
319 // since the icon is provided in the application bundle.
320 setWindowIcon(QPixmap(":/images/lyx.png"));
324 setAcceptDrops(true);
326 statusBar()->setSizeGripEnabled(true);
328 // Forbid too small unresizable window because it can happen
329 // with some window manager under X11.
330 setMinimumSize(300, 200);
332 if (!lyxrc.allow_geometry_session)
333 // No session handling, default to a sane size.
334 setGeometry(50, 50, 690, 510);
336 // Now take care of session management.
338 QString const key = "view-" + QString::number(id_);
340 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
341 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
345 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
346 setGeometry(50, 50, 690, 510);
348 setIconSize(settings.value(key + "/icon_size").toSize());
358 void GuiView::close()
360 d.quitting_by_menu_ = true;
361 d.current_work_area_ = 0;
362 for (int i = 0; i != d.splitter_->count(); ++i) {
363 TabWorkArea * twa = d.tabWorkArea(i);
367 QMainWindow::close();
368 d.quitting_by_menu_ = false;
372 void GuiView::setFocus()
374 if (d.current_work_area_)
375 d.current_work_area_->setFocus();
381 QMenu* GuiView::createPopupMenu()
383 return d.toolBarPopup(this);
387 void GuiView::showEvent(QShowEvent * e)
389 LYXERR(Debug::GUI, "Passed Geometry "
390 << size().height() << "x" << size().width()
391 << "+" << pos().x() << "+" << pos().y());
393 if (d.splitter_->count() == 0)
394 // No work area, switch to the background widget.
397 QMainWindow::showEvent(e);
401 void GuiView::closeEvent(QCloseEvent * close_event)
403 // we may have been called through the close window button
404 // which bypasses the LFUN machinery.
405 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
406 if (!theBufferList().quitWriteAll()) {
407 close_event->ignore();
412 // Make sure that no LFUN use this close to be closed View.
413 theLyXFunc().setLyXView(0);
414 // Make sure the timer time out will not trigger a statusbar update.
415 d.statusbar_timer_.stop();
417 if (lyxrc.allow_geometry_session) {
419 QString const key = "view-" + QString::number(id_);
421 settings.setValue(key + "/pos", pos());
422 settings.setValue(key + "/size", size());
424 settings.setValue(key + "/geometry", saveGeometry());
426 settings.setValue(key + "/icon_size", iconSize());
427 d.toolbars_->saveToolbarInfo();
430 guiApp->unregisterView(id_);
431 if (guiApp->viewCount() > 0) {
432 // Just close the window and do nothing else if this is not the
434 close_event->accept();
440 // this is the place where we leave the frontend.
441 // it is the only point at which we start quitting.
442 close_event->accept();
443 // quit the event loop
448 void GuiView::dragEnterEvent(QDragEnterEvent * event)
450 if (event->mimeData()->hasUrls())
452 /// \todo Ask lyx-devel is this is enough:
453 /// if (event->mimeData()->hasFormat("text/plain"))
454 /// event->acceptProposedAction();
458 void GuiView::dropEvent(QDropEvent* event)
460 QList<QUrl> files = event->mimeData()->urls();
464 LYXERR(Debug::GUI, BOOST_CURRENT_FUNCTION << " got URLs!");
465 for (int i = 0; i != files.size(); ++i) {
466 string const file = support::os::internal_path(fromqstr(
467 files.at(i).toLocalFile()));
469 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
474 void GuiView::message(docstring const & str)
476 statusBar()->showMessage(toqstr(str));
477 d.statusbar_timer_.stop();
478 d.statusbar_timer_.start(statusbar_timer_value);
482 void GuiView::smallSizedIcons()
484 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
488 void GuiView::normalSizedIcons()
490 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
494 void GuiView::bigSizedIcons()
496 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
500 void GuiView::clearMessage()
504 theLyXFunc().setLyXView(this);
505 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
506 d.statusbar_timer_.stop();
510 void GuiView::updateWindowTitle(GuiWorkArea * wa)
512 if (wa != d.current_work_area_)
514 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
515 setWindowIconText(wa->windowIconText());
519 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
522 disconnectBufferView();
523 connectBufferView(wa->bufferView());
524 connectBuffer(wa->bufferView().buffer());
525 d.current_work_area_ = wa;
526 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
527 this, SLOT(updateWindowTitle(GuiWorkArea *)));
528 updateWindowTitle(wa);
531 // Buffer-dependent dialogs should be updated or
532 // hidden. This should go here because some dialogs (eg ToC)
533 // require bv_->text.
534 updateBufferDependent(true);
536 updateLayoutChoice(false);
541 void GuiView::updateStatusBar()
543 // let the user see the explicit message
544 if (d.statusbar_timer_.isActive())
547 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
551 bool GuiView::hasFocus() const
553 return qApp->activeWindow() == this;
557 bool GuiView::event(QEvent * e)
561 // Useful debug code:
562 //case QEvent::ActivationChange:
563 //case QEvent::WindowDeactivate:
564 //case QEvent::Paint:
565 //case QEvent::Enter:
566 //case QEvent::Leave:
567 //case QEvent::HoverEnter:
568 //case QEvent::HoverLeave:
569 //case QEvent::HoverMove:
570 //case QEvent::StatusTip:
571 //case QEvent::DragEnter:
572 //case QEvent::DragLeave:
576 case QEvent::WindowActivate: {
577 guiApp->setCurrentView(*this);
578 if (d.current_work_area_) {
579 BufferView & bv = d.current_work_area_->bufferView();
580 connectBufferView(bv);
581 connectBuffer(bv.buffer());
582 // The document structure, name and dialogs might have
583 // changed in another view.
584 updateBufferDependent(true);
586 setWindowTitle(qt_("LyX"));
587 setWindowIconText(qt_("LyX"));
589 return QMainWindow::event(e);
591 case QEvent::ShortcutOverride: {
592 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
593 if (!d.current_work_area_) {
594 theLyXFunc().setLyXView(this);
596 setKeySymbol(&sym, ke);
597 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
601 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
603 setKeySymbol(&sym, ke);
604 d.current_work_area_->processKeySym(sym, NoModifier);
610 return QMainWindow::event(e);
615 bool GuiView::focusNextPrevChild(bool /*next*/)
622 void GuiView::setBusy(bool yes)
624 if (d.current_work_area_) {
625 d.current_work_area_->setUpdatesEnabled(!yes);
627 d.current_work_area_->stopBlinkingCursor();
629 d.current_work_area_->startBlinkingCursor();
633 QApplication::setOverrideCursor(Qt::WaitCursor);
635 QApplication::restoreOverrideCursor();
639 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
641 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
643 if (tbinfo.flags & ToolbarInfo::TOP) {
645 addToolBarBreak(Qt::TopToolBarArea);
646 addToolBar(Qt::TopToolBarArea, toolBar);
649 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
650 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
651 #if (QT_VERSION >= 0x040202)
653 addToolBarBreak(Qt::BottomToolBarArea);
655 addToolBar(Qt::BottomToolBarArea, toolBar);
658 if (tbinfo.flags & ToolbarInfo::LEFT) {
659 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
660 #if (QT_VERSION >= 0x040202)
662 addToolBarBreak(Qt::LeftToolBarArea);
664 addToolBar(Qt::LeftToolBarArea, toolBar);
667 if (tbinfo.flags & ToolbarInfo::RIGHT) {
668 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
669 #if (QT_VERSION >= 0x040202)
671 addToolBarBreak(Qt::RightToolBarArea);
673 addToolBar(Qt::RightToolBarArea, toolBar);
676 // The following does not work so I cannot restore to exact toolbar location
678 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
679 toolBar->move(tbinfo.posx, tbinfo.posy);
686 GuiWorkArea * GuiView::workArea(Buffer & buffer)
688 for (int i = 0; i != d.splitter_->count(); ++i) {
689 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
697 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
700 // Automatically create a TabWorkArea if there are none yet.
701 if (!d.splitter_->count())
704 TabWorkArea * tab_widget = d.currentTabWorkArea();
705 return tab_widget->addWorkArea(buffer, *this);
709 void GuiView::addTabWorkArea()
711 TabWorkArea * twa = new TabWorkArea;
712 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
713 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
714 d.splitter_->addWidget(twa);
715 d.stack_widget_->setCurrentWidget(d.splitter_);
719 GuiWorkArea const * GuiView::currentWorkArea() const
721 return d.current_work_area_;
725 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
727 BOOST_ASSERT(work_area);
729 // Changing work area can result from opening a file so
730 // update the toc in any case.
733 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
734 d.current_work_area_ = wa;
735 for (int i = 0; i != d.splitter_->count(); ++i) {
736 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
742 void GuiView::removeWorkArea(GuiWorkArea * work_area)
744 BOOST_ASSERT(work_area);
745 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
746 if (gwa == d.current_work_area_) {
748 disconnectBufferView();
749 hideBufferDependent();
750 d.current_work_area_ = 0;
753 // removing a work area often results from closing a file so
754 // update the toc in any case.
757 for (int i = 0; i != d.splitter_->count(); ++i) {
758 TabWorkArea * twa = d.tabWorkArea(i);
759 if (!twa->removeWorkArea(gwa))
760 // Not found in this tab group.
763 // We found and removed the GuiWorkArea.
765 // No more WorkAreas in this tab group, so delete it.
770 if (d.current_work_area_)
771 // This means that we are not closing the current GuiWorkArea;
774 // Switch to the next GuiWorkArea in the found TabWorkArea.
775 d.current_work_area_ = twa->currentWorkArea();
779 if (d.splitter_->count() == 0)
780 // No more work area, switch to the background widget.
785 void GuiView::updateLayoutChoice(bool force)
787 // Don't show any layouts without a buffer
789 d.toolbars_->clearLayoutList();
793 // Update the layout display
794 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
795 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
798 docstring const & layout = d.current_work_area_->bufferView().cursor().
799 innerParagraph().layout()->name();
801 if (layout != d.current_layout) {
802 d.toolbars_->setLayout(layout);
803 d.current_layout = layout;
808 bool GuiView::isToolbarVisible(std::string const & id)
810 return d.toolbars_->visible(id);
813 void GuiView::updateToolbars()
815 if (d.current_work_area_) {
817 d.current_work_area_->bufferView().cursor().inMathed();
819 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
821 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
822 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
824 d.toolbars_->update(math, table, review);
826 d.toolbars_->update(false, false, false);
828 // update read-only status of open dialogs.
833 Buffer * GuiView::buffer()
835 if (d.current_work_area_)
836 return &d.current_work_area_->bufferView().buffer();
841 Buffer const * GuiView::buffer() const
843 if (d.current_work_area_)
844 return &d.current_work_area_->bufferView().buffer();
849 void GuiView::setBuffer(Buffer * newBuffer)
851 BOOST_ASSERT(newBuffer);
854 GuiWorkArea * wa = workArea(*newBuffer);
856 updateLabels(*newBuffer->masterBuffer());
857 wa = addWorkArea(*newBuffer);
859 //Disconnect the old buffer...there's no new one.
862 connectBuffer(*newBuffer);
863 connectBufferView(wa->bufferView());
864 setCurrentWorkArea(wa);
870 void GuiView::connectBuffer(Buffer & buf)
872 buf.setGuiDelegate(this);
876 void GuiView::disconnectBuffer()
878 if (d.current_work_area_)
879 d.current_work_area_->bufferView().setGuiDelegate(0);
883 void GuiView::connectBufferView(BufferView & bv)
885 bv.setGuiDelegate(this);
889 void GuiView::disconnectBufferView()
891 if (d.current_work_area_)
892 d.current_work_area_->bufferView().setGuiDelegate(0);
896 void GuiView::errors(string const & error_type)
898 ErrorList & el = buffer()->errorList(error_type);
900 showDialog("errorlist", error_type);
904 void GuiView::updateDialog(string const & name, string const & data)
906 if (!isDialogVisible(name))
909 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
910 if (it == d.dialogs_.end())
913 Dialog * const dialog = it->second.get();
914 if (dialog->isVisibleView())
915 dialog->updateData(data);
919 BufferView * GuiView::view()
921 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
925 void GuiView::updateToc()
927 updateDialog("toc", "");
931 void GuiView::updateEmbeddedFiles()
933 updateDialog("embedding", "");
937 void GuiView::autoSave()
939 LYXERR(Debug::INFO, "Running autoSave()");
942 view()->buffer().autoSave();
946 void GuiView::resetAutosaveTimers()
949 d.autosave_timeout_->restart();
953 void GuiView::dispatch(FuncRequest const & cmd)
956 case LFUN_BUFFER_SWITCH:
957 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
960 case LFUN_COMMAND_EXECUTE: {
961 bool const show_it = cmd.argument() != "off";
962 d.toolbars_->showCommandBuffer(show_it);
965 case LFUN_DROP_LAYOUTS_CHOICE:
966 d.toolbars_->openLayoutList();
970 d.menubar_->openByName(toqstr(cmd.argument()));
973 case LFUN_TOOLBAR_TOGGLE: {
974 string const name = cmd.getArg(0);
975 bool const allowauto = cmd.getArg(1) == "allowauto";
976 // it is possible to get current toolbar status like this,...
977 // but I decide to obey the order of ToolbarBackend::flags
978 // and disregard real toolbar status.
979 // toolbars_->saveToolbarInfo();
981 // toggle state on/off/auto
982 d.toolbars_->toggleToolbarState(name, allowauto);
986 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
988 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
992 if (tbi->flags & ToolbarInfo::ON)
994 else if (tbi->flags & ToolbarInfo::OFF)
996 else if (tbi->flags & ToolbarInfo::AUTO)
999 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1000 _(tbi->gui_name), state));
1005 theLyXFunc().setLyXView(this);
1011 Buffer const * GuiView::updateInset(Inset const * inset)
1013 if (!d.current_work_area_)
1017 d.current_work_area_->scheduleRedraw();
1019 return &d.current_work_area_->bufferView().buffer();
1023 void GuiView::restartCursor()
1025 /* When we move around, or type, it's nice to be able to see
1026 * the cursor immediately after the keypress.
1028 if (d.current_work_area_)
1029 d.current_work_area_->startBlinkingCursor();
1034 // This list should be kept in sync with the list of insets in
1035 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
1036 // dialog should have the same name as the inset.
1038 char const * const dialognames[] = {
1039 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1040 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1041 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1042 "mathdelimiter", "mathmatrix", "note", "paragraph",
1043 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1045 #ifdef HAVE_LIBAIKSAURUS
1049 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1051 char const * const * const end_dialognames =
1052 dialognames + (sizeof(dialognames) / sizeof(char *));
1056 cmpCStr(char const * name) : name_(name) {}
1057 bool operator()(char const * other) {
1058 return strcmp(other, name_) == 0;
1065 bool isValidName(string const & name)
1067 return std::find_if(dialognames, end_dialognames,
1068 cmpCStr(name.c_str())) != end_dialognames;
1074 Dialog * GuiView::find_or_build(string const & name)
1076 if (!isValidName(name))
1079 std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1081 if (it != d.dialogs_.end())
1082 return it->second.get();
1084 d.dialogs_[name].reset(build(name));
1085 return d.dialogs_[name].get();
1089 void GuiView::showDialog(string const & name, string const & data,
1096 Dialog * dialog = find_or_build(name);
1098 dialog->showData(data);
1100 d.open_insets_[name] = inset;
1106 bool GuiView::isDialogVisible(string const & name) const
1108 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1109 if (it == d.dialogs_.end())
1111 return it->second.get()->isVisibleView();
1115 void GuiView::hideDialog(string const & name, Inset * inset)
1117 // Don't send the signal if we are quitting, because on MSVC it is
1118 // destructed before the cut stack in CutAndPaste.cpp, and this method
1119 // is called from some inset destructor if the cut stack is not empty
1124 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1125 if (it == d.dialogs_.end())
1128 if (inset && inset != getOpenInset(name))
1131 Dialog * const dialog = it->second.get();
1132 if (dialog->isVisibleView())
1134 d.open_insets_[name] = 0;
1138 void GuiView::disconnectDialog(string const & name)
1140 if (!isValidName(name))
1143 if (d.open_insets_.find(name) != d.open_insets_.end())
1144 d.open_insets_[name] = 0;
1148 Inset * GuiView::getOpenInset(string const & name) const
1150 if (!isValidName(name))
1153 std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1154 return it == d.open_insets_.end() ? 0 : it->second;
1158 void GuiView::hideAll() const
1160 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1161 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1163 for(; it != end; ++it)
1168 void GuiView::hideBufferDependent() const
1170 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1171 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1173 for(; it != end; ++it) {
1174 Dialog * dialog = it->second.get();
1175 if (dialog->isBufferDependent())
1181 void GuiView::updateBufferDependent(bool switched) const
1183 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1184 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1186 for(; it != end; ++it) {
1187 Dialog * dialog = it->second.get();
1188 if (switched && dialog->isBufferDependent()) {
1189 if (dialog->isVisibleView() && dialog->initialiseParams(""))
1190 dialog->updateView();
1194 // A bit clunky, but the dialog will request
1195 // that the kernel provides it with the necessary
1197 dialog->slotRestore();
1203 void GuiView::checkStatus()
1205 std::map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
1206 std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1208 for(; it != end; ++it) {
1209 Dialog * const dialog = it->second.get();
1210 if (dialog && dialog->isVisibleView())
1211 dialog->checkStatus();
1217 // will be replaced by a proper factory...
1218 Dialog * createGuiAbout(LyXView & lv);
1219 Dialog * createGuiBibitem(LyXView & lv);
1220 Dialog * createGuiBibtex(LyXView & lv);
1221 Dialog * createGuiBox(LyXView & lv);
1222 Dialog * createGuiBranch(LyXView & lv);
1223 Dialog * createGuiChanges(LyXView & lv);
1224 Dialog * createGuiCharacter(LyXView & lv);
1225 Dialog * createGuiCitation(LyXView & lv);
1226 Dialog * createGuiDelimiter(LyXView & lv);
1227 Dialog * createGuiDocument(LyXView & lv);
1228 Dialog * createGuiErrorList(LyXView & lv);
1229 Dialog * createGuiERT(LyXView & lv);
1230 Dialog * createGuiExternal(LyXView & lv);
1231 Dialog * createGuiFloat(LyXView & lv);
1232 Dialog * createGuiGraphics(LyXView & lv);
1233 Dialog * createGuiInclude(LyXView & lv);
1234 Dialog * createGuiIndex(LyXView & lv);
1235 Dialog * createGuiLabel(LyXView & lv);
1236 Dialog * createGuiListings(LyXView & lv);
1237 Dialog * createGuiLog(LyXView & lv);
1238 Dialog * createGuiMathMatrix(LyXView & lv);
1239 Dialog * createGuiNomenclature(LyXView & lv);
1240 Dialog * createGuiNote(LyXView & lv);
1241 Dialog * createGuiParagraph(LyXView & lv);
1242 Dialog * createGuiPreferences(LyXView & lv);
1243 Dialog * createGuiPrint(LyXView & lv);
1244 Dialog * createGuiRef(LyXView & lv);
1245 Dialog * createGuiSearch(LyXView & lv);
1246 Dialog * createGuiSendTo(LyXView & lv);
1247 Dialog * createGuiShowFile(LyXView & lv);
1248 Dialog * createGuiSpellchecker(LyXView & lv);
1249 Dialog * createGuiTabularCreate(LyXView & lv);
1250 Dialog * createGuiTabular(LyXView & lv);
1251 Dialog * createGuiTexInfo(LyXView & lv);
1252 Dialog * createGuiToc(LyXView & lv);
1253 Dialog * createGuiThesaurus(LyXView & lv);
1254 Dialog * createGuiHyperlink(LyXView & lv);
1255 Dialog * createGuiVSpace(LyXView & lv);
1256 Dialog * createGuiViewSource(LyXView & lv);
1257 Dialog * createGuiWrap(LyXView & lv);
1260 Dialog * GuiView::build(string const & name)
1262 BOOST_ASSERT(isValidName(name));
1264 if (name == "aboutlyx")
1265 return createGuiAbout(*this);
1266 if (name == "bibitem")
1267 return createGuiBibitem(*this);
1268 if (name == "bibtex")
1269 return createGuiBibtex(*this);
1271 return createGuiBox(*this);
1272 if (name == "branch")
1273 return createGuiBranch(*this);
1274 if (name == "changes")
1275 return createGuiChanges(*this);
1276 if (name == "character")
1277 return createGuiCharacter(*this);
1278 if (name == "citation")
1279 return createGuiCitation(*this);
1280 if (name == "document")
1281 return createGuiDocument(*this);
1282 if (name == "errorlist")
1283 return createGuiErrorList(*this);
1285 return createGuiERT(*this);
1286 if (name == "external")
1287 return createGuiExternal(*this);
1289 return createGuiShowFile(*this);
1290 if (name == "findreplace")
1291 return createGuiSearch(*this);
1292 if (name == "float")
1293 return createGuiFloat(*this);
1294 if (name == "graphics")
1295 return createGuiGraphics(*this);
1296 if (name == "include")
1297 return createGuiInclude(*this);
1298 if (name == "index")
1299 return createGuiIndex(*this);
1300 if (name == "nomenclature")
1301 return createGuiNomenclature(*this);
1302 if (name == "label")
1303 return createGuiLabel(*this);
1305 return createGuiLog(*this);
1306 if (name == "view-source")
1307 return createGuiViewSource(*this);
1308 if (name == "mathdelimiter")
1309 return createGuiDelimiter(*this);
1310 if (name == "mathmatrix")
1311 return createGuiMathMatrix(*this);
1313 return createGuiNote(*this);
1314 if (name == "paragraph")
1315 return createGuiParagraph(*this);
1316 if (name == "prefs")
1317 return createGuiPreferences(*this);
1318 if (name == "print")
1319 return createGuiPrint(*this);
1321 return createGuiRef(*this);
1322 if (name == "sendto")
1323 return createGuiSendTo(*this);
1324 if (name == "spellchecker")
1325 return createGuiSpellchecker(*this);
1326 if (name == "tabular")
1327 return createGuiTabular(*this);
1328 if (name == "tabularcreate")
1329 return createGuiTabularCreate(*this);
1330 if (name == "texinfo")
1331 return createGuiTexInfo(*this);
1332 #ifdef HAVE_LIBAIKSAURUS
1333 if (name == "thesaurus")
1334 return createGuiThesaurus(*this);
1337 return createGuiToc(*this);
1339 return createGuiHyperlink(*this);
1340 if (name == "vspace")
1341 return createGuiVSpace(*this);
1343 return createGuiWrap(*this);
1344 if (name == "listings")
1345 return createGuiListings(*this);
1351 } // namespace frontend
1354 #include "GuiView_moc.cpp"