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.
18 #include "GuiImplementation.h"
19 #include "GuiWorkArea.h"
20 #include "GuiKeySymbol.h"
21 #include "GuiMenubar.h"
22 #include "GuiToolbar.h"
23 #include "GuiToolbars.h"
27 #include "qt_helpers.h"
29 #include "frontends/Application.h"
30 #include "frontends/Dialogs.h"
31 #include "frontends/Gui.h"
33 #include "support/filetools.h"
34 #include "support/convert.h"
35 #include "support/lstrings.h"
36 #include "support/os.h"
38 #include "buffer_funcs.h"
40 #include "BufferList.h"
41 #include "BufferParams.h"
42 #include "BufferView.h"
45 #include "ErrorList.h"
46 #include "FuncRequest.h"
53 #include "MenuBackend.h"
54 #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>
75 #include <QPushButton>
77 #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;
103 using support::FileName;
104 using support::makeDisplayPath;
105 using support::onlyFilename;
109 int const statusbar_timer_value = 3000;
111 class BackgroundWidget : public QWidget
114 BackgroundWidget(QString const & file, QString const & text)
116 splash_ = new QPixmap(file);
118 lyxerr << "could not load splash screen: '" << fromqstr(file) << "'" << endl;
122 QPainter pain(splash_);
123 pain.setPen(QColor(255, 255, 0));
125 // The font used to display the version info
126 font.setStyleHint(QFont::SansSerif);
127 font.setWeight(QFont::Bold);
128 font.setPointSize(convert<int>(lyxrc.font_sizes[FONT_SIZE_LARGE]));
130 pain.drawText(260, 270, text);
133 void paintEvent(QPaintEvent *)
138 int x = (width() - splash_->width()) / 2;
139 int y = (height() - splash_->height()) / 2;
141 pain.drawPixmap(x, y, *splash_);
151 struct GuiView::GuiViewPrivate
154 : current_work_area_(0), posx_offset(0), posy_offset(0)
161 delete stack_widget_;
166 unsigned int smallIconSize;
167 unsigned int normalIconSize;
168 unsigned int bigIconSize;
169 // static needed by "New Window"
170 static unsigned int lastIconSize;
172 QMenu * toolBarPopup(GuiView * parent)
174 // FIXME: translation
175 QMenu * menu = new QMenu(parent);
176 QActionGroup * iconSizeGroup = new QActionGroup(parent);
178 QAction * smallIcons = new QAction(iconSizeGroup);
179 smallIcons->setText(qt_("Small-sized icons"));
180 smallIcons->setCheckable(true);
181 QObject::connect(smallIcons, SIGNAL(triggered()),
182 parent, SLOT(smallSizedIcons()));
183 menu->addAction(smallIcons);
185 QAction * normalIcons = new QAction(iconSizeGroup);
186 normalIcons->setText(qt_("Normal-sized icons"));
187 normalIcons->setCheckable(true);
188 QObject::connect(normalIcons, SIGNAL(triggered()),
189 parent, SLOT(normalSizedIcons()));
190 menu->addAction(normalIcons);
192 QAction * bigIcons = new QAction(iconSizeGroup);
193 bigIcons->setText(qt_("Big-sized icons"));
194 bigIcons->setCheckable(true);
195 QObject::connect(bigIcons, SIGNAL(triggered()),
196 parent, SLOT(bigSizedIcons()));
197 menu->addAction(bigIcons);
199 unsigned int cur = parent->iconSize().width();
200 if ( cur == parent->d.smallIconSize)
201 smallIcons->setChecked(true);
202 else if (cur == parent->d.normalIconSize)
203 normalIcons->setChecked(true);
204 else if (cur == parent->d.bigIconSize)
205 bigIcons->setChecked(true);
210 void initBackground()
212 LYXERR(Debug::GUI) << "show banner: " << lyxrc.show_banner << endl;
213 /// The text to be written on top of the pixmap
214 QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
215 bg_widget_ = new BackgroundWidget(":/images/banner.png", text);
220 stack_widget_->setCurrentWidget(bg_widget_);
221 bg_widget_->setUpdatesEnabled(true);
224 TabWorkArea * tabWorkArea(int i)
226 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
229 TabWorkArea * currentTabWorkArea()
231 if (splitter_->count() == 1)
232 // The first TabWorkArea is always the first one, if any.
233 return tabWorkArea(0);
235 TabWorkArea * tab_widget = 0;
236 for (int i = 0; i != splitter_->count(); ++i) {
237 QWidget * w = splitter_->widget(i);
240 tab_widget = dynamic_cast<TabWorkArea *>(w);
252 GuiWorkArea * current_work_area_;
256 QSplitter * splitter_;
257 QStackedWidget * stack_widget_;
258 BackgroundWidget * bg_widget_;
260 GuiMenubar * menubar_;
262 GuiToolbars * toolbars_;
264 docstring current_layout;
268 unsigned int GuiView::GuiViewPrivate::lastIconSize = 0;
271 GuiView::GuiView(int id)
272 : QMainWindow(), LyXView(id),
273 d(*new GuiViewPrivate),
274 quitting_by_menu_(false),
275 autosave_timeout_(new Timeout(5000)),
276 dialogs_(new Dialogs(*this))
278 // Start autosave timer
279 if (lyxrc.autosave) {
280 autosave_timeout_->timeout.connect(boost::bind(&GuiView::autoSave, this));
281 autosave_timeout_->setTimeout(lyxrc.autosave * 1000);
282 autosave_timeout_->start();
285 // Qt bug? signal lastWindowClosed does not work
286 setAttribute(Qt::WA_QuitOnClose, false);
287 setAttribute(Qt::WA_DeleteOnClose, true);
289 // hardcode here the platform specific icon size
290 d.smallIconSize = 14; // scaling problems
291 d.normalIconSize = 20; // ok, default
292 d.bigIconSize = 26; // better for some math icons
295 // assign an icon to main form. We do not do it under Qt/Mac,
296 // since the icon is provided in the application bundle.
297 setWindowIcon(QPixmap(":/images/lyx.png"));
301 d.splitter_ = new QSplitter;
304 LYXERR(Debug::GUI) << "stack widget!" << endl;
305 d.stack_widget_ = new QStackedWidget;
306 d.stack_widget_->addWidget(d.bg_widget_);
307 d.stack_widget_->addWidget(d.splitter_);
308 setCentralWidget(d.stack_widget_);
311 setAcceptDrops(true);
318 delete autosave_timeout_;
323 void GuiView::close()
325 quitting_by_menu_ = true;
326 d.current_work_area_ = 0;
327 for (int i = 0; i != d.splitter_->count(); ++i) {
328 TabWorkArea * twa = d.tabWorkArea(i);
332 QMainWindow::close();
333 quitting_by_menu_ = false;
337 void GuiView::setFocus()
339 if (d.current_work_area_)
340 d.current_work_area_->setFocus();
346 QMenu* GuiView::createPopupMenu()
348 return d.toolBarPopup(this);
354 // GuiToolbars *must* be initialised before GuiMenubar.
355 d.toolbars_ = new GuiToolbars(*this);
356 // FIXME: GuiToolbars::init() cannot be integrated in the ctor
357 // because LyXFunc::getStatus() needs a properly initialized
358 // GuiToolbars object (for LFUN_TOOLBAR_TOGGLE).
360 d.menubar_ = new GuiMenubar(this, menubackend);
362 statusBar()->setSizeGripEnabled(true);
364 QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
365 this, SLOT(clearMessage()));
371 void GuiView::closeEvent(QCloseEvent * close_event)
373 // we may have been called through the close window button
374 // which bypasses the LFUN machinery.
375 if (!quitting_by_menu_ && theApp()->gui().viewIds().size() == 1) {
376 if (!theBufferList().quitWriteAll()) {
377 close_event->ignore();
382 // Make sure that no LFUN use this close to be closed View.
383 theLyXFunc().setLyXView(0);
384 // Make sure the timer time out will not trigger a statusbar update.
385 statusbar_timer_.stop();
387 theApp()->gui().unregisterView(id());
388 if (!theApp()->gui().viewIds().empty()) {
389 // Just close the window and do nothing else if this is not the
391 close_event->accept();
397 // this is the place where we leave the frontend.
398 // it is the only point at which we start quitting.
400 close_event->accept();
401 // quit the event loop
406 void GuiView::dragEnterEvent(QDragEnterEvent * event)
408 if (event->mimeData()->hasUrls())
410 /// \todo Ask lyx-devel is this is enough:
411 /// if (event->mimeData()->hasFormat("text/plain"))
412 /// event->acceptProposedAction();
416 void GuiView::dropEvent(QDropEvent* event)
418 QList<QUrl> files = event->mimeData()->urls();
422 LYXERR(Debug::GUI) << BOOST_CURRENT_FUNCTION
423 << " got URLs!" << endl;
424 for (int i = 0; i != files.size(); ++i) {
425 string const file = support::os::internal_path(fromqstr(
426 files.at(i).toLocalFile()));
428 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
433 void GuiView::saveGeometry()
435 static bool done = false;
442 // change the ifdef to 'geometry = normalGeometry();' only
443 // when Trolltech has fixed the broken normalGeometry on X11:
444 // http://www.trolltech.com/developer/task-tracker/index_html?id=119684+&method=entry
445 // Then also the moveEvent, resizeEvent, and the
446 // code for floatingGeometry_ can be removed;
447 // adjust GuiView::setGeometry()
449 QRect normal_geometry;
452 normal_geometry = normalGeometry();
454 maximized = CompletelyMaximized;
456 maximized = NotMaximized;
459 normal_geometry = updateFloatingGeometry();
461 QDesktopWidget& dw = *qApp->desktop();
462 QRect desk = dw.availableGeometry(dw.primaryScreen());
463 // Qt bug on Linux: load completely maximized, vert max. save-> frameGeometry().height() is wrong
464 if (isMaximized() && desk.width() <= frameGeometry().width() && desk.height() <= frameGeometry().height()) {
465 maximized = CompletelyMaximized;
466 // maximizing does not work when the window is allready hor. or vert. maximized
467 // Tested only on KDE
468 int dh = frameGeometry().height() - height();
469 if (desk.height() <= normal_geometry.height() + dh)
470 normal_geometry.setHeight(normal_geometry.height() - 1);
471 int dw = frameGeometry().width() - width();
472 if (desk.width() <= normal_geometry.width() + dw)
473 normal_geometry.setWidth(normal_geometry.width() - 1);
474 } else if (desk.height() <= frameGeometry().height()) {
475 maximized = VerticallyMaximized;
476 } else if (desk.width() <= frameGeometry().width()) {
477 maximized = HorizontallyMaximized;
479 maximized = NotMaximized;
483 // save windows size and position
484 SessionInfoSection & info = LyX::ref().session().sessionInfo();
485 info.save("WindowWidth", convert<string>(normal_geometry.width()));
486 info.save("WindowHeight", convert<string>(normal_geometry.height()));
487 info.save("WindowMaximized", convert<string>(int(maximized)));
488 info.save("IconSizeXY", convert<string>(iconSize().width()));
489 if (lyxrc.geometry_xysaved) {
490 info.save("WindowPosX", convert<string>(normal_geometry.x() + d.posx_offset));
491 info.save("WindowPosY", convert<string>(normal_geometry.y() + d.posy_offset));
493 d.toolbars_->saveToolbarInfo();
497 void GuiView::setGeometry(unsigned int width,
500 LyXView::Maximized maximized,
501 unsigned int iconSizeXY,
502 const string & geometryArg)
504 // use last value (not at startup)
505 if (d.lastIconSize != 0)
506 setIconSize(d.lastIconSize);
507 else if (iconSizeXY != 0)
508 setIconSize(iconSizeXY);
510 setIconSize(d.normalIconSize);
512 // only true when the -geometry option was NOT used
513 if (width != 0 && height != 0) {
514 if (posx != -1 && posy != -1) {
515 // if there are startup positioning problems:
516 // http://doc.trolltech.com/4.2/qdesktopwidget.html
517 QDesktopWidget& dw = *qApp->desktop();
518 if (dw.isVirtualDesktop()) {
519 if(!dw.geometry().contains(posx, posy)) {
524 // Which system doesn't use a virtual desktop?
525 // TODO save also last screen number and check if it is still availabe.
528 // FIXME: use setGeometry only when Trolltech has fixed the qt4/X11 bug
529 QWidget::setGeometry(posx, posy, width, height);
531 resize(width, height);
535 resize(width, height);
538 // remember original size
539 floatingGeometry_ = QRect(posx, posy, width, height);
541 if (maximized != NotMaximized) {
542 if (maximized == CompletelyMaximized) {
543 setWindowState(Qt::WindowMaximized);
546 // TODO How to set by the window manager?
547 // setWindowState(Qt::WindowVerticallyMaximized);
549 QDesktopWidget& dw = *qApp->desktop();
550 QRect desk = dw.availableGeometry(dw.primaryScreen());
551 if (maximized == VerticallyMaximized)
552 resize(width, desk.height());
553 if (maximized == HorizontallyMaximized)
554 resize(desk.width(), height);
561 // FIXME: move this code into parse_geometry() (LyX.cpp)
565 QRegExp re( "[=]*(?:([0-9]+)[xX]([0-9]+)){0,1}[ ]*(?:([+-][0-9]*)([+-][0-9]*)){0,1}" );
566 re.indexIn(toqstr(geometryArg.c_str()));
567 w = re.cap(1).toInt();
568 h = re.cap(2).toInt();
569 x = re.cap(3).toInt();
570 y = re.cap(4).toInt();
571 QWidget::setGeometry( x, y, w, h );
582 // after show geometry() has changed (Qt bug?)
583 // we compensate the drift when storing the position
586 if (width != 0 && height != 0)
587 if (posx != -1 && posy != -1) {
589 d.posx_offset = posx - normalGeometry().x();
590 d.posy_offset = posy - normalGeometry().y();
593 if (maximized == NotMaximized) {
594 d.posx_offset = posx - geometry().x();
595 d.posy_offset = posy - geometry().y();
603 void GuiView::message(docstring const & str)
605 statusBar()->showMessage(toqstr(str));
606 statusbar_timer_.stop();
607 statusbar_timer_.start(statusbar_timer_value);
611 void GuiView::setIconSize(unsigned int size)
613 d.lastIconSize = size;
614 QMainWindow::setIconSize(QSize(size, size));
618 void GuiView::smallSizedIcons()
620 setIconSize(d.smallIconSize);
624 void GuiView::normalSizedIcons()
626 setIconSize(d.normalIconSize);
630 void GuiView::bigSizedIcons()
632 setIconSize(d.bigIconSize);
636 void GuiView::clearMessage()
640 theLyXFunc().setLyXView(this);
641 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
642 statusbar_timer_.stop();
646 void GuiView::updateWindowTitle(GuiWorkArea * wa)
648 if (wa != d.current_work_area_)
650 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
651 setWindowIconText(wa->windowIconText());
655 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
658 disconnectBufferView();
659 connectBufferView(wa->bufferView());
660 connectBuffer(wa->bufferView().buffer());
661 d.current_work_area_ = wa;
662 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
663 this, SLOT(updateWindowTitle(GuiWorkArea *)));
664 updateWindowTitle(wa);
667 // Buffer-dependent dialogs should be updated or
668 // hidden. This should go here because some dialogs (eg ToC)
669 // require bv_->text.
670 dialogs_->updateBufferDependent(true);
672 updateLayoutChoice(false);
677 void GuiView::updateStatusBar()
679 // let the user see the explicit message
680 if (statusbar_timer_.isActive())
683 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
687 bool GuiView::hasFocus() const
689 return qApp->activeWindow() == this;
693 QRect GuiView::updateFloatingGeometry()
695 QDesktopWidget& dw = *qApp->desktop();
696 QRect desk = dw.availableGeometry(dw.primaryScreen());
697 // remember only non-maximized sizes
698 if (!isMaximized() && desk.width() > frameGeometry().width() && desk.height() > frameGeometry().height()) {
699 floatingGeometry_ = QRect(x(), y(), width(), height());
701 return floatingGeometry_;
705 void GuiView::resizeEvent(QResizeEvent *)
707 updateFloatingGeometry();
711 void GuiView::moveEvent(QMoveEvent *)
713 updateFloatingGeometry();
717 bool GuiView::event(QEvent * e)
721 // Useful debug code:
722 //case QEvent::ActivationChange:
723 //case QEvent::WindowDeactivate:
724 //case QEvent::Paint:
725 //case QEvent::Enter:
726 //case QEvent::Leave:
727 //case QEvent::HoverEnter:
728 //case QEvent::HoverLeave:
729 //case QEvent::HoverMove:
730 //case QEvent::StatusTip:
731 //case QEvent::DragEnter:
732 //case QEvent::DragLeave:
736 case QEvent::WindowActivate: {
737 theApp()->setCurrentView(*this);
738 if (d.current_work_area_) {
739 BufferView & bv = d.current_work_area_->bufferView();
740 connectBufferView(bv);
741 connectBuffer(bv.buffer());
742 // The document structure, name and dialogs might have
743 // changed in another view.
744 dialogs_->updateBufferDependent(true);
746 setWindowTitle(qt_("LyX"));
747 setWindowIconText(qt_("LyX"));
749 return QMainWindow::event(e);
751 case QEvent::ShortcutOverride: {
752 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
753 if (!d.current_work_area_) {
754 theLyXFunc().setLyXView(this);
756 setKeySymbol(&sym, ke);
757 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
761 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
763 setKeySymbol(&sym, ke);
764 d.current_work_area_->processKeySym(sym, NoModifier);
770 return QMainWindow::event(e);
775 bool GuiView::focusNextPrevChild(bool /*next*/)
782 void GuiView::setBusy(bool yes)
784 if (d.current_work_area_) {
785 d.current_work_area_->setUpdatesEnabled(!yes);
787 d.current_work_area_->stopBlinkingCursor();
789 d.current_work_area_->startBlinkingCursor();
793 QApplication::setOverrideCursor(Qt::WaitCursor);
795 QApplication::restoreOverrideCursor();
799 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
801 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
803 if (tbinfo.flags & ToolbarInfo::TOP) {
805 addToolBarBreak(Qt::TopToolBarArea);
806 addToolBar(Qt::TopToolBarArea, toolBar);
809 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
810 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
811 #if (QT_VERSION >= 0x040202)
813 addToolBarBreak(Qt::BottomToolBarArea);
815 addToolBar(Qt::BottomToolBarArea, toolBar);
818 if (tbinfo.flags & ToolbarInfo::LEFT) {
819 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
820 #if (QT_VERSION >= 0x040202)
822 addToolBarBreak(Qt::LeftToolBarArea);
824 addToolBar(Qt::LeftToolBarArea, toolBar);
827 if (tbinfo.flags & ToolbarInfo::RIGHT) {
828 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
829 #if (QT_VERSION >= 0x040202)
831 addToolBarBreak(Qt::RightToolBarArea);
833 addToolBar(Qt::RightToolBarArea, toolBar);
836 // The following does not work so I cannot restore to exact toolbar location
838 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
839 toolBar->move(tbinfo.posx, tbinfo.posy);
846 GuiWorkArea * GuiView::workArea(Buffer & buffer)
848 for (int i = 0; i != d.splitter_->count(); ++i) {
849 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
857 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
859 GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
860 wa->setUpdatesEnabled(false);
862 // Automatically create a TabWorkArea if there are none yet.
863 if (!d.splitter_->count())
866 TabWorkArea * tab_widget = d.currentTabWorkArea();
867 tab_widget->addTab(wa, wa->windowTitle());
868 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
869 tab_widget, SLOT(updateTabText(GuiWorkArea *)));
871 wa->bufferView().updateMetrics();
873 // Hide tabbar if there's only one tab.
874 tab_widget->showBar(tab_widget->count() > 1);
879 void GuiView::addTabWorkArea()
881 TabWorkArea * twa = new TabWorkArea;
882 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
883 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
884 d.splitter_->addWidget(twa);
885 d.stack_widget_->setCurrentWidget(d.splitter_);
889 GuiWorkArea const * GuiView::currentWorkArea() const
891 return d.current_work_area_;
895 void GuiView::setCurrentWorkArea(GuiWorkArea * work_area)
897 BOOST_ASSERT(work_area);
899 // Changing work area can result from opening a file so
900 // update the toc in any case.
903 GuiWorkArea * wa = static_cast<GuiWorkArea *>(work_area);
904 d.current_work_area_ = wa;
905 for (int i = 0; i != d.splitter_->count(); ++i) {
906 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
912 void GuiView::removeWorkArea(GuiWorkArea * work_area)
914 BOOST_ASSERT(work_area);
915 GuiWorkArea * gwa = static_cast<GuiWorkArea *>(work_area);
916 if (gwa == d.current_work_area_) {
918 disconnectBufferView();
919 dialogs_->hideBufferDependent();
920 d.current_work_area_ = 0;
923 // removing a work area often results from closing a file so
924 // update the toc in any case.
927 for (int i = 0; i != d.splitter_->count(); ++i) {
928 TabWorkArea * twa = d.tabWorkArea(i);
929 if (!twa->removeWorkArea(gwa))
930 // Not found in this tab group.
933 // We found and removed the GuiWorkArea.
935 // No more WorkAreas in this tab group, so delete it.
940 if (d.current_work_area_)
941 // This means that we are not closing the current GuiWorkArea;
944 // Switch to the next GuiWorkArea in the found TabWorkArea.
945 d.current_work_area_ = twa->currentWorkArea();
949 if (d.splitter_->count() == 0)
950 // No more work area, switch to the background widget.
955 void GuiView::showMiniBuffer(bool visible)
957 d.toolbars_->showCommandBuffer(visible);
961 void GuiView::updateLayoutChoice(bool force)
963 // Don't show any layouts without a buffer
965 d.toolbars_->clearLayoutList();
969 // Update the layout display
970 if (d.toolbars_->updateLayoutList(buffer()->params().getTextClassPtr(), force)) {
971 d.current_layout = buffer()->params().getTextClass().defaultLayoutName();
974 docstring const & layout = d.current_work_area_->bufferView().cursor().
975 innerParagraph().layout()->name();
977 if (layout != d.current_layout) {
978 d.toolbars_->setLayout(layout);
979 d.current_layout = layout;
984 bool GuiView::isToolbarVisible(std::string const & id)
986 return d.toolbars_->visible(id);
989 void GuiView::updateToolbars()
991 if (d.current_work_area_) {
993 d.current_work_area_->bufferView().cursor().inMathed();
995 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
997 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
998 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
1000 d.toolbars_->update(math, table, review);
1002 d.toolbars_->update(false, false, false);
1004 // update read-only status of open dialogs.
1005 dialogs_->checkStatus();
1009 Buffer * GuiView::buffer()
1011 if (d.current_work_area_)
1012 return &d.current_work_area_->bufferView().buffer();
1017 Buffer const * GuiView::buffer() const
1019 if (d.current_work_area_)
1020 return &d.current_work_area_->bufferView().buffer();
1025 void GuiView::setBuffer(Buffer * newBuffer)
1027 BOOST_ASSERT(newBuffer);
1030 GuiWorkArea * wa = workArea(*newBuffer);
1032 updateLabels(*newBuffer->masterBuffer());
1033 wa = addWorkArea(*newBuffer);
1035 //Disconnect the old buffer...there's no new one.
1038 connectBuffer(*newBuffer);
1039 connectBufferView(wa->bufferView());
1040 setCurrentWorkArea(wa);
1046 Buffer * GuiView::loadLyXFile(FileName const & filename, bool tolastfiles)
1050 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1053 message(_("Document not loaded."));
1059 GuiWorkArea * wa = workArea(*newBuffer);
1061 wa = addWorkArea(*newBuffer);
1063 // scroll to the position when the file was last closed
1064 if (lyxrc.use_lastfilepos) {
1065 LastFilePosSection::FilePos filepos =
1066 LyX::ref().session().lastFilePos().load(filename);
1067 // if successfully move to pit (returned par_id is not zero),
1068 // update metrics and reset font
1069 wa->bufferView().moveToPosition(filepos.pit, filepos.pos, 0, 0);
1073 LyX::ref().session().lastFiles().add(filename);
1080 void GuiView::connectBuffer(Buffer & buf)
1082 buf.setGuiDelegate(this);
1086 void GuiView::disconnectBuffer()
1088 if (d.current_work_area_)
1089 d.current_work_area_->bufferView().setGuiDelegate(0);
1093 void GuiView::connectBufferView(BufferView & bv)
1095 bv.setGuiDelegate(this);
1099 void GuiView::disconnectBufferView()
1101 if (d.current_work_area_)
1102 d.current_work_area_->bufferView().setGuiDelegate(0);
1106 void GuiView::errors(string const & error_type)
1108 ErrorList & el = buffer()->errorList(error_type);
1110 dialogs_->show("errorlist", error_type);
1114 void GuiView::showDialog(string const & name)
1116 dialogs_->show(name);
1120 void GuiView::showDialogWithData(string const & name, string const & data)
1122 dialogs_->show(name, data);
1126 void GuiView::showInsetDialog(string const & name, string const & data,
1129 dialogs_->show(name, data, inset);
1133 void GuiView::updateDialog(string const & name, string const & data)
1135 if (dialogs_->visible(name))
1136 dialogs_->update(name, data);
1140 BufferView * GuiView::view()
1142 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
1146 void GuiView::updateToc()
1148 updateDialog("toc", "");
1152 void GuiView::updateEmbeddedFiles()
1154 updateDialog("embedding", "");
1158 void GuiView::autoSave()
1160 LYXERR(Debug::INFO) << "Running autoSave()" << endl;
1163 view()->buffer().autoSave();
1167 void GuiView::resetAutosaveTimers()
1170 autosave_timeout_->restart();
1174 void GuiView::dispatch(FuncRequest const & cmd)
1176 switch(cmd.action) {
1177 case LFUN_BUFFER_SWITCH:
1178 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1181 case LFUN_COMMAND_EXECUTE:
1182 d.toolbars_->showCommandBuffer(true);
1185 case LFUN_DROP_LAYOUTS_CHOICE:
1186 d.toolbars_->openLayoutList();
1189 case LFUN_MENU_OPEN:
1190 d.menubar_->openByName(toqstr(cmd.argument()));
1193 case LFUN_TOOLBAR_TOGGLE: {
1194 string const name = cmd.getArg(0);
1195 bool const allowauto = cmd.getArg(1) == "allowauto";
1196 // it is possible to get current toolbar status like this,...
1197 // but I decide to obey the order of ToolbarBackend::flags
1198 // and disregard real toolbar status.
1199 // toolbars_->saveToolbarInfo();
1201 // toggle state on/off/auto
1202 d.toolbars_->toggleToolbarState(name, allowauto);
1206 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1208 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1212 if (tbi->flags & ToolbarInfo::ON)
1214 else if (tbi->flags & ToolbarInfo::OFF)
1216 else if (tbi->flags & ToolbarInfo::AUTO)
1219 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1220 _(tbi->gui_name), state));
1225 theLyXFunc().setLyXView(this);
1231 Buffer const * GuiView::updateInset(Inset const * inset)
1233 if (!d.current_work_area_)
1237 d.current_work_area_->scheduleRedraw();
1239 return &d.current_work_area_->bufferView().buffer();
1243 void GuiView::restartCursor()
1245 /* When we move around, or type, it's nice to be able to see
1246 * the cursor immediately after the keypress.
1248 if (d.current_work_area_)
1249 d.current_work_area_->startBlinkingCursor();
1252 } // namespace frontend
1255 #include "GuiView_moc.cpp"