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 "FileDialog.h"
20 #include "GuiApplication.h"
21 #include "GuiCompleter.h"
22 #include "GuiWorkArea.h"
23 #include "GuiKeySymbol.h"
24 #include "GuiToolbar.h"
25 #include "GuiToolbars.h"
29 #include "qt_helpers.h"
31 #include "frontends/alert.h"
33 #include "buffer_funcs.h"
35 #include "BufferList.h"
36 #include "BufferParams.h"
37 #include "BufferView.h"
38 #include "Converter.h"
41 #include "ErrorList.h"
43 #include "FuncStatus.h"
44 #include "FuncRequest.h"
52 #include "Paragraph.h"
53 #include "TextClass.h"
55 #include "ToolbarBackend.h"
58 #include "support/lassert.h"
59 #include "support/debug.h"
60 #include "support/FileName.h"
61 #include "support/filetools.h"
62 #include "support/gettext.h"
63 #include "support/ForkedCalls.h"
64 #include "support/lstrings.h"
65 #include "support/os.h"
66 #include "support/Package.h"
67 #include "support/Timeout.h"
70 #include <QApplication>
71 #include <QCloseEvent>
73 #include <QDesktopWidget>
74 #include <QDragEnterEvent>
82 #include <QPushButton>
86 #include <QStackedWidget>
93 #include <boost/bind.hpp>
95 #ifdef HAVE_SYS_TIME_H
96 # include <sys/time.h>
103 using namespace lyx::support;
110 class BackgroundWidget : public QWidget
115 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
116 /// The text to be written on top of the pixmap
117 QString const text = lyx_version ?
118 qt_("version ") + lyx_version : qt_("unknown version");
119 splash_ = QPixmap(":/images/banner.png");
121 QPainter pain(&splash_);
122 pain.setPen(QColor(0, 0, 0));
124 // The font used to display the version info
125 font.setStyleHint(QFont::SansSerif);
126 font.setWeight(QFont::Bold);
127 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
129 pain.drawText(190, 225, text);
132 void paintEvent(QPaintEvent *)
134 int x = (width() - splash_.width()) / 2;
135 int y = (height() - splash_.height()) / 2;
137 pain.drawPixmap(x, y, splash_);
147 typedef boost::shared_ptr<Dialog> DialogPtr;
149 struct GuiView::GuiViewPrivate
152 : current_work_area_(0), layout_(0), autosave_timeout_(5000),
155 // hardcode here the platform specific icon size
156 smallIconSize = 14; // scaling problems
157 normalIconSize = 20; // ok, default
158 bigIconSize = 26; // better for some math icons
160 splitter_ = new QSplitter;
161 bg_widget_ = new BackgroundWidget;
162 stack_widget_ = new QStackedWidget;
163 stack_widget_->addWidget(bg_widget_);
164 stack_widget_->addWidget(splitter_);
172 delete stack_widget_;
176 QMenu * toolBarPopup(GuiView * parent)
178 // FIXME: translation
179 QMenu * menu = new QMenu(parent);
180 QActionGroup * iconSizeGroup = new QActionGroup(parent);
182 QAction * smallIcons = new QAction(iconSizeGroup);
183 smallIcons->setText(qt_("Small-sized icons"));
184 smallIcons->setCheckable(true);
185 QObject::connect(smallIcons, SIGNAL(triggered()),
186 parent, SLOT(smallSizedIcons()));
187 menu->addAction(smallIcons);
189 QAction * normalIcons = new QAction(iconSizeGroup);
190 normalIcons->setText(qt_("Normal-sized icons"));
191 normalIcons->setCheckable(true);
192 QObject::connect(normalIcons, SIGNAL(triggered()),
193 parent, SLOT(normalSizedIcons()));
194 menu->addAction(normalIcons);
196 QAction * bigIcons = new QAction(iconSizeGroup);
197 bigIcons->setText(qt_("Big-sized icons"));
198 bigIcons->setCheckable(true);
199 QObject::connect(bigIcons, SIGNAL(triggered()),
200 parent, SLOT(bigSizedIcons()));
201 menu->addAction(bigIcons);
203 unsigned int cur = parent->iconSize().width();
204 if ( cur == parent->d.smallIconSize)
205 smallIcons->setChecked(true);
206 else if (cur == parent->d.normalIconSize)
207 normalIcons->setChecked(true);
208 else if (cur == parent->d.bigIconSize)
209 bigIcons->setChecked(true);
216 stack_widget_->setCurrentWidget(bg_widget_);
217 bg_widget_->setUpdatesEnabled(true);
220 TabWorkArea * tabWorkArea(int i)
222 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
225 TabWorkArea * currentTabWorkArea()
227 if (splitter_->count() == 1)
228 // The first TabWorkArea is always the first one, if any.
229 return tabWorkArea(0);
231 for (int i = 0; i != splitter_->count(); ++i) {
232 TabWorkArea * twa = tabWorkArea(i);
233 if (current_work_area_ == twa->currentWorkArea())
237 // None has the focus so we just take the first one.
238 return tabWorkArea(0);
242 GuiWorkArea * current_work_area_;
243 QSplitter * splitter_;
244 QStackedWidget * stack_widget_;
245 BackgroundWidget * bg_widget_;
247 GuiToolbars * toolbars_;
248 /// The main layout box.
250 * \warning Don't Delete! The layout box is actually owned by
251 * whichever toolbar contains it. All the GuiView class needs is a
252 * means of accessing it.
254 * FIXME: replace that with a proper model so that we are not limited
255 * to only one dialog.
257 GuiLayoutBox * layout_;
260 map<string, Inset *> open_insets_;
263 map<string, DialogPtr> dialogs_;
265 unsigned int smallIconSize;
266 unsigned int normalIconSize;
267 unsigned int bigIconSize;
269 QTimer statusbar_timer_;
270 /// auto-saving of buffers
271 Timeout autosave_timeout_;
272 /// flag against a race condition due to multiclicks, see bug #1119
276 TocModels toc_models_;
280 GuiView::GuiView(int id)
281 : d(*new GuiViewPrivate), id_(id)
283 // GuiToolbars *must* be initialised before the menu bar.
284 d.toolbars_ = new GuiToolbars(*this);
286 // set ourself as the current view. This is needed for the menu bar
287 // filling, at least for the static special menu item on Mac. Otherwise
288 // they are greyed out.
289 theLyXFunc().setLyXView(this);
291 // Fill up the menu bar.
292 guiApp->menus().fillMenuBar(menuBar(), this, true);
294 setCentralWidget(d.stack_widget_);
296 // Start autosave timer
297 if (lyxrc.autosave) {
298 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
299 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
300 d.autosave_timeout_.start();
302 connect(&d.statusbar_timer_, SIGNAL(timeout()),
303 this, SLOT(clearMessage()));
305 // We don't want to keep the window in memory if it is closed.
306 setAttribute(Qt::WA_DeleteOnClose, true);
308 #if (!defined(Q_WS_WIN) && !defined(Q_WS_MACX))
309 // assign an icon to main form. We do not do it under Qt/Win or Qt/Mac,
310 // since the icon is provided in the application bundle.
311 setWindowIcon(QPixmap(":/images/lyx.png"));
315 setAcceptDrops(true);
317 statusBar()->setSizeGripEnabled(true);
319 // Forbid too small unresizable window because it can happen
320 // with some window manager under X11.
321 setMinimumSize(300, 200);
323 if (!lyxrc.allow_geometry_session)
324 // No session handling, default to a sane size.
325 setGeometry(50, 50, 690, 510);
327 // Now take care of session management.
329 QString const key = "view-" + QString::number(id_);
331 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
332 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
336 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
337 setGeometry(50, 50, 690, 510);
339 setIconSize(settings.value(key + "/icon_size").toSize());
345 if (guiApp->currentView() == this)
346 guiApp->setCurrentView(0);
347 theLyXFunc().setLyXView(0);
353 TocModels & GuiView::tocModels()
355 return d.toc_models_;
359 void GuiView::setFocus()
361 if (d.current_work_area_)
362 d.current_work_area_->setFocus();
368 QMenu * GuiView::createPopupMenu()
370 return d.toolBarPopup(this);
374 void GuiView::showEvent(QShowEvent * e)
376 LYXERR(Debug::GUI, "Passed Geometry "
377 << size().height() << "x" << size().width()
378 << "+" << pos().x() << "+" << pos().y());
380 if (d.splitter_->count() == 0)
381 // No work area, switch to the background widget.
384 QMainWindow::showEvent(e);
388 void GuiView::closeEvent(QCloseEvent * close_event)
390 // it can happen that this event arrives without selecting the view,
391 // e.g. when clicking the close button on a background window.
392 theLyXFunc().setLyXView(this);
394 while (Buffer * b = buffer()) {
396 // This is a child document, just close the tab after saving
397 // but keep the file loaded.
398 if (!saveBuffer(*b)) {
399 close_event->ignore();
402 removeWorkArea(d.current_work_area_);
406 std::vector<int> const & ids = guiApp->viewIds();
407 for (size_type i = 0; i != ids.size(); ++i) {
410 if (guiApp->view(ids[i]).workArea(*b)) {
411 // FIXME 1: should we put an alert box here that the buffer
412 // is viewed elsewhere?
413 // FIXME 2: should we try to save this buffer in any case?
416 // This buffer is also opened in another view, so
417 // but close the associated work area nevertheless.
418 removeWorkArea(d.current_work_area_);
419 // but don't close it.
424 if (b && !closeBuffer(*b, true)) {
425 close_event->ignore();
430 // Make sure that no LFUN use this close to be closed View.
431 theLyXFunc().setLyXView(0);
433 // Save toolbars configuration
434 if (isFullScreen()) {
435 d.toolbars_->toggleFullScreen(!isFullScreen());
439 // Make sure the timer time out will not trigger a statusbar update.
440 d.statusbar_timer_.stop();
442 // Saving fullscreen requires additional tweaks in the toolbar code.
443 // It wouldn't also work under linux natively.
444 if (lyxrc.allow_geometry_session && !isFullScreen()) {
446 QString const key = "view-" + QString::number(id_);
448 settings.setValue(key + "/pos", pos());
449 settings.setValue(key + "/size", size());
451 settings.setValue(key + "/geometry", saveGeometry());
453 settings.setValue(key + "/icon_size", iconSize());
454 d.toolbars_->saveToolbarInfo();
455 // Now take care of all other dialogs:
456 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
457 for (; it!= d.dialogs_.end(); ++it)
458 it->second->saveSession();
461 guiApp->unregisterView(id_);
462 close_event->accept();
466 void GuiView::dragEnterEvent(QDragEnterEvent * event)
468 if (event->mimeData()->hasUrls())
470 /// \todo Ask lyx-devel is this is enough:
471 /// if (event->mimeData()->hasFormat("text/plain"))
472 /// event->acceptProposedAction();
476 void GuiView::dropEvent(QDropEvent* event)
478 QList<QUrl> files = event->mimeData()->urls();
482 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
483 for (int i = 0; i != files.size(); ++i) {
484 string const file = os::internal_path(fromqstr(
485 files.at(i).toLocalFile()));
487 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
492 void GuiView::message(docstring const & str)
494 if (ForkedProcess::iAmAChild())
497 statusBar()->showMessage(toqstr(str));
498 d.statusbar_timer_.stop();
499 d.statusbar_timer_.start(3000);
503 void GuiView::smallSizedIcons()
505 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
509 void GuiView::normalSizedIcons()
511 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
515 void GuiView::bigSizedIcons()
517 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
521 void GuiView::clearMessage()
525 theLyXFunc().setLyXView(this);
526 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
527 d.statusbar_timer_.stop();
531 void GuiView::updateWindowTitle(GuiWorkArea * wa)
533 if (wa != d.current_work_area_)
535 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
536 setWindowIconText(wa->windowIconText());
540 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
543 disconnectBufferView();
544 connectBufferView(wa->bufferView());
545 connectBuffer(wa->bufferView().buffer());
546 d.current_work_area_ = wa;
547 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
548 this, SLOT(updateWindowTitle(GuiWorkArea *)));
549 updateWindowTitle(wa);
553 // The document settings needs to be reinitialised.
554 updateDialog("document", "");
556 // Buffer-dependent dialogs must be updated. This is done here because
557 // some dialogs require buffer()->text.
562 void GuiView::on_lastWorkAreaRemoved()
565 // On Mac close the view if there is no Tab open anymore,
566 // but only if no splitter is visible
567 if (!lyxrc.open_buffers_in_tabs && d.splitter_->count() == 1) {
568 TabWorkArea * twa = qobject_cast<TabWorkArea *>(d.splitter_->widget(0));
569 if (twa && twa->count() == 0) {
570 // close the view, as no tab is open anymore
571 QTimer::singleShot(0, this, SLOT(close()));
576 // The document settings needs to be reinitialised.
577 updateDialog("document", "");
583 void GuiView::updateStatusBar()
585 // let the user see the explicit message
586 if (d.statusbar_timer_.isActive())
589 theLyXFunc().setLyXView(this);
590 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
594 bool GuiView::hasFocus() const
596 return qApp->activeWindow() == this;
600 bool GuiView::event(QEvent * e)
604 // Useful debug code:
605 //case QEvent::ActivationChange:
606 //case QEvent::WindowDeactivate:
607 //case QEvent::Paint:
608 //case QEvent::Enter:
609 //case QEvent::Leave:
610 //case QEvent::HoverEnter:
611 //case QEvent::HoverLeave:
612 //case QEvent::HoverMove:
613 //case QEvent::StatusTip:
614 //case QEvent::DragEnter:
615 //case QEvent::DragLeave:
619 case QEvent::WindowActivate: {
620 if (this == guiApp->currentView()) {
622 return QMainWindow::event(e);
624 guiApp->setCurrentView(this);
625 if (d.current_work_area_) {
626 BufferView & bv = d.current_work_area_->bufferView();
627 connectBufferView(bv);
628 connectBuffer(bv.buffer());
629 // The document structure, name and dialogs might have
630 // changed in another view.
632 // The document settings needs to be reinitialised.
633 updateDialog("document", "");
636 setWindowTitle(qt_("LyX"));
637 setWindowIconText(qt_("LyX"));
640 return QMainWindow::event(e);
643 case QEvent::ShortcutOverride: {
644 if (d.current_work_area_)
645 // Nothing special to do.
646 return QMainWindow::event(e);
648 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
650 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
652 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
653 || ke->key() == Qt::Key_Backtab)
654 return QMainWindow::event(e);
656 // Allow processing of shortcuts that are allowed even when no Buffer
658 theLyXFunc().setLyXView(this);
660 setKeySymbol(&sym, ke);
661 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
667 return QMainWindow::event(e);
672 bool GuiView::focusNextPrevChild(bool /*next*/)
679 void GuiView::setBusy(bool busy)
681 if (d.current_work_area_) {
682 d.current_work_area_->setUpdatesEnabled(!busy);
684 d.current_work_area_->stopBlinkingCursor();
686 d.current_work_area_->startBlinkingCursor();
690 QApplication::setOverrideCursor(Qt::WaitCursor);
692 QApplication::restoreOverrideCursor();
696 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
698 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
700 if (tbinfo.flags & ToolbarInfo::TOP) {
702 addToolBarBreak(Qt::TopToolBarArea);
703 addToolBar(Qt::TopToolBarArea, toolBar);
706 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
707 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
708 #if (QT_VERSION >= 0x040202)
710 addToolBarBreak(Qt::BottomToolBarArea);
712 addToolBar(Qt::BottomToolBarArea, toolBar);
715 if (tbinfo.flags & ToolbarInfo::LEFT) {
716 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
717 #if (QT_VERSION >= 0x040202)
719 addToolBarBreak(Qt::LeftToolBarArea);
721 addToolBar(Qt::LeftToolBarArea, toolBar);
724 if (tbinfo.flags & ToolbarInfo::RIGHT) {
725 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
726 #if (QT_VERSION >= 0x040202)
728 addToolBarBreak(Qt::RightToolBarArea);
730 addToolBar(Qt::RightToolBarArea, toolBar);
733 // The following does not work so I cannot restore to exact toolbar location
735 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
736 toolBar->move(tbinfo.posx, tbinfo.posy);
743 GuiWorkArea * GuiView::workArea(Buffer & buffer)
745 if (TabWorkArea * twa = d.currentTabWorkArea())
746 return twa->workArea(buffer);
751 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
753 // Automatically create a TabWorkArea if there are none yet.
754 TabWorkArea * tab_widget = d.splitter_->count()
755 ? d.currentTabWorkArea() : addTabWorkArea();
756 return tab_widget->addWorkArea(buffer, *this);
760 TabWorkArea * GuiView::addTabWorkArea()
762 TabWorkArea * twa = new TabWorkArea;
763 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
764 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
765 QObject::connect(twa, SIGNAL(lastWorkAreaRemoved()),
766 this, SLOT(on_lastWorkAreaRemoved()));
768 d.splitter_->addWidget(twa);
769 d.stack_widget_->setCurrentWidget(d.splitter_);
774 GuiWorkArea const * GuiView::currentWorkArea() const
776 return d.current_work_area_;
780 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
783 d.current_work_area_ = wa;
784 for (int i = 0; i != d.splitter_->count(); ++i) {
785 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
791 void GuiView::removeWorkArea(GuiWorkArea * wa)
794 if (wa == d.current_work_area_) {
796 disconnectBufferView();
797 d.current_work_area_ = 0;
800 for (int i = 0; i != d.splitter_->count(); ++i) {
801 TabWorkArea * twa = d.tabWorkArea(i);
802 if (!twa->removeWorkArea(wa))
803 // Not found in this tab group.
806 // We found and removed the GuiWorkArea.
808 // No more WorkAreas in this tab group, so delete it.
813 if (d.current_work_area_)
814 // This means that we are not closing the current GuiWorkArea;
817 // Switch to the next GuiWorkArea in the found TabWorkArea.
818 d.current_work_area_ = twa->currentWorkArea();
822 if (d.splitter_->count() == 0)
823 // No more work area, switch to the background widget.
828 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
834 void GuiView::updateLayoutList()
837 d.layout_->updateContents(false);
841 void GuiView::updateToolbars()
843 if (d.current_work_area_) {
845 d.current_work_area_->bufferView().cursor().inMathed();
847 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
849 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
850 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
851 bool const mathmacrotemplate =
852 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
854 d.toolbars_->update(math, table, review, mathmacrotemplate);
856 d.toolbars_->update(false, false, false, false);
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 LASSERT(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 void GuiView::connectBuffer(Buffer & buf)
899 buf.setGuiDelegate(this);
903 void GuiView::disconnectBuffer()
905 if (d.current_work_area_)
906 d.current_work_area_->bufferView().setGuiDelegate(0);
910 void GuiView::connectBufferView(BufferView & bv)
912 bv.setGuiDelegate(this);
916 void GuiView::disconnectBufferView()
918 if (d.current_work_area_)
919 d.current_work_area_->bufferView().setGuiDelegate(0);
923 void GuiView::errors(string const & error_type)
925 ErrorList & el = buffer()->errorList(error_type);
927 showDialog("errorlist", error_type);
931 void GuiView::structureChanged()
933 d.toc_models_.reset(view());
934 // Navigator needs more than a simple update in this case. It needs to be
936 updateDialog("toc", "");
940 void GuiView::updateDialog(string const & name, string const & data)
942 if (!isDialogVisible(name))
945 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
946 if (it == d.dialogs_.end())
949 Dialog * const dialog = it->second.get();
950 if (dialog->isVisibleView())
951 dialog->initialiseParams(data);
955 BufferView * GuiView::view()
957 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
961 void GuiView::autoSave()
963 LYXERR(Debug::INFO, "Running autoSave()");
966 view()->buffer().autoSave();
970 void GuiView::resetAutosaveTimers()
973 d.autosave_timeout_.restart();
977 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
981 Buffer * buf = buffer();
983 /* In LyX/Mac, when a dialog is open, the menus of the
984 application can still be accessed without giving focus to
985 the main window. In this case, we want to disable the menu
986 entries that are buffer-related.
988 Note that this code is not perfect, as bug 1941 attests:
989 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
991 if (cmd.origin == FuncRequest::MENU && !hasFocus())
995 case LFUN_BUFFER_WRITE:
996 enable = buf && (buf->isUnnamed() || !buf->isClean());
999 case LFUN_BUFFER_WRITE_AS:
1003 case LFUN_SPLIT_VIEW:
1007 case LFUN_CLOSE_TAB_GROUP:
1008 enable = d.currentTabWorkArea();
1011 case LFUN_TOOLBAR_TOGGLE:
1012 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
1015 case LFUN_UI_TOGGLE:
1016 flag.setOnOff(isFullScreen());
1019 case LFUN_DIALOG_TOGGLE:
1020 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
1021 // fall through to set "enable"
1022 case LFUN_DIALOG_SHOW: {
1023 string const name = cmd.getArg(0);
1025 enable = name == "aboutlyx"
1026 || name == "file" //FIXME: should be removed.
1028 || name == "texinfo";
1029 else if (name == "print")
1030 enable = buf->isExportable("dvi")
1031 && lyxrc.print_command != "none";
1032 else if (name == "character") {
1036 InsetCode ic = view()->cursor().inset().lyxCode();
1037 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1040 else if (name == "symbols") {
1041 if (!view() || view()->cursor().inMathed())
1044 InsetCode ic = view()->cursor().inset().lyxCode();
1045 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1048 else if (name == "latexlog")
1049 enable = FileName(buf->logName()).isReadableFile();
1050 else if (name == "spellchecker")
1051 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1052 enable = !buf->isReadonly();
1056 else if (name == "vclog")
1057 enable = buf->lyxvc().inUse();
1061 case LFUN_DIALOG_UPDATE: {
1062 string const name = cmd.getArg(0);
1064 enable = name == "prefs";
1068 case LFUN_INSET_APPLY: {
1073 string const name = cmd.getArg(0);
1074 Inset * inset = getOpenInset(name);
1076 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1078 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1079 // Every inset is supposed to handle this
1080 LASSERT(false, /**/);
1084 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1085 flag |= getStatus(fr);
1087 enable = flag.enabled();
1091 case LFUN_COMPLETION_INLINE:
1092 if (!d.current_work_area_
1093 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1097 case LFUN_COMPLETION_POPUP:
1098 if (!d.current_work_area_
1099 || !d.current_work_area_->completer().popupPossible(view()->cursor()))
1103 case LFUN_COMPLETION_COMPLETE:
1104 if (!d.current_work_area_
1105 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1117 flag.enabled(false);
1123 static FileName selectTemplateFile()
1125 FileDialog dlg(qt_("Select template file"));
1126 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1127 dlg.setButton1(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1129 FileDialog::Result result = dlg.open(toqstr(lyxrc.template_path),
1130 QStringList(qt_("LyX Documents (*.lyx)")));
1132 if (result.first == FileDialog::Later)
1134 if (result.second.isEmpty())
1136 return FileName(fromqstr(result.second));
1140 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1144 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1147 message(_("Document not loaded."));
1152 setBuffer(newBuffer);
1154 // scroll to the position when the file was last closed
1155 if (lyxrc.use_lastfilepos) {
1156 LastFilePosSection::FilePos filepos =
1157 LyX::ref().session().lastFilePos().load(filename);
1158 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1162 LyX::ref().session().lastFiles().add(filename);
1169 void GuiView::openDocument(string const & fname)
1171 string initpath = lyxrc.document_path;
1174 string const trypath = buffer()->filePath();
1175 // If directory is writeable, use this as default.
1176 if (FileName(trypath).isDirWritable())
1182 if (fname.empty()) {
1183 FileDialog dlg(qt_("Select document to open"), LFUN_FILE_OPEN);
1184 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1185 dlg.setButton2(qt_("Examples|#E#e"),
1186 toqstr(addPath(package().system_support().absFilename(), "examples")));
1188 FileDialog::Result result =
1189 dlg.open(toqstr(initpath), QStringList(qt_("LyX Documents (*.lyx)")));
1191 if (result.first == FileDialog::Later)
1194 filename = fromqstr(result.second);
1196 // check selected filename
1197 if (filename.empty()) {
1198 message(_("Canceled."));
1204 // get absolute path of file and add ".lyx" to the filename if
1206 FileName const fullname =
1207 fileSearch(string(), filename, "lyx", support::may_not_exist);
1208 if (!fullname.empty())
1209 filename = fullname.absFilename();
1211 // if the file doesn't exist, let the user create one
1212 if (!fullname.exists()) {
1213 // the user specifically chose this name. Believe him.
1214 Buffer * const b = newFile(filename, string(), true);
1220 docstring const disp_fn = makeDisplayPath(filename);
1221 message(bformat(_("Opening document %1$s..."), disp_fn));
1224 Buffer * buf = loadDocument(fullname);
1229 buf->errors("Parse");
1230 str2 = bformat(_("Document %1$s opened."), disp_fn);
1232 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1237 // FIXME: clean that
1238 static bool import(GuiView * lv, FileName const & filename,
1239 string const & format, ErrorList & errorList)
1241 FileName const lyxfile(support::changeExtension(filename.absFilename(), ".lyx"));
1243 string loader_format;
1244 vector<string> loaders = theConverters().loaders();
1245 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1246 for (vector<string>::const_iterator it = loaders.begin();
1247 it != loaders.end(); ++it) {
1248 if (!theConverters().isReachable(format, *it))
1251 string const tofile =
1252 support::changeExtension(filename.absFilename(),
1253 formats.extension(*it));
1254 if (!theConverters().convert(0, filename, FileName(tofile),
1255 filename, format, *it, errorList))
1257 loader_format = *it;
1260 if (loader_format.empty()) {
1261 frontend::Alert::error(_("Couldn't import file"),
1262 bformat(_("No information for importing the format %1$s."),
1263 formats.prettyName(format)));
1267 loader_format = format;
1269 if (loader_format == "lyx") {
1270 Buffer * buf = lv->loadDocument(lyxfile);
1275 buf->errors("Parse");
1277 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1281 bool as_paragraphs = loader_format == "textparagraph";
1282 string filename2 = (loader_format == format) ? filename.absFilename()
1283 : support::changeExtension(filename.absFilename(),
1284 formats.extension(loader_format));
1285 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1286 theLyXFunc().setLyXView(lv);
1287 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1294 void GuiView::importDocument(string const & argument)
1297 string filename = split(argument, format, ' ');
1299 LYXERR(Debug::INFO, format << " file: " << filename);
1301 // need user interaction
1302 if (filename.empty()) {
1303 string initpath = lyxrc.document_path;
1305 Buffer const * buf = buffer();
1307 string const trypath = buf->filePath();
1308 // If directory is writeable, use this as default.
1309 if (FileName(trypath).isDirWritable())
1313 docstring const text = bformat(_("Select %1$s file to import"),
1314 formats.prettyName(format));
1316 FileDialog dlg(toqstr(text), LFUN_BUFFER_IMPORT);
1317 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1318 dlg.setButton2(qt_("Examples|#E#e"),
1319 toqstr(addPath(package().system_support().absFilename(), "examples")));
1321 docstring filter = formats.prettyName(format);
1324 filter += from_utf8(formats.extension(format));
1327 FileDialog::Result result =
1328 dlg.open(toqstr(initpath), fileFilters(toqstr(filter)));
1330 if (result.first == FileDialog::Later)
1333 filename = fromqstr(result.second);
1335 // check selected filename
1336 if (filename.empty())
1337 message(_("Canceled."));
1340 if (filename.empty())
1343 // get absolute path of file
1344 FileName const fullname(support::makeAbsPath(filename));
1346 FileName const lyxfile(support::changeExtension(fullname.absFilename(), ".lyx"));
1348 // Check if the document already is open
1349 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1352 if (!closeBuffer()) {
1353 message(_("Canceled."));
1358 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1360 // if the file exists already, and we didn't do
1361 // -i lyx thefile.lyx, warn
1362 if (lyxfile.exists() && fullname != lyxfile) {
1364 docstring text = bformat(_("The document %1$s already exists.\n\n"
1365 "Do you want to overwrite that document?"), displaypath);
1366 int const ret = Alert::prompt(_("Overwrite document?"),
1367 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1370 message(_("Canceled."));
1375 message(bformat(_("Importing %1$s..."), displaypath));
1376 ErrorList errorList;
1377 if (import(this, fullname, format, errorList))
1378 message(_("imported."));
1380 message(_("file not imported!"));
1382 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1386 void GuiView::newDocument(string const & filename, bool from_template)
1388 FileName initpath(lyxrc.document_path);
1389 Buffer * buf = buffer();
1391 FileName const trypath(buf->filePath());
1392 // If directory is writeable, use this as default.
1393 if (trypath.isDirWritable())
1397 string templatefile = from_template ?
1398 selectTemplateFile().absFilename() : string();
1400 if (filename.empty())
1401 b = newUnnamedFile(templatefile, initpath);
1403 b = newFile(filename, templatefile, true);
1407 // Ensure the cursor is correctly positionned on screen.
1408 view()->showCursor();
1412 void GuiView::insertLyXFile(docstring const & fname)
1414 BufferView * bv = view();
1419 FileName filename(to_utf8(fname));
1421 if (!filename.empty()) {
1422 bv->insertLyXFile(filename);
1426 // Launch a file browser
1428 string initpath = lyxrc.document_path;
1429 string const trypath = bv->buffer().filePath();
1430 // If directory is writeable, use this as default.
1431 if (FileName(trypath).isDirWritable())
1435 FileDialog dlg(qt_("Select LyX document to insert"), LFUN_FILE_INSERT);
1436 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1437 dlg.setButton2(qt_("Examples|#E#e"),
1438 toqstr(addPath(package().system_support().absFilename(),
1441 FileDialog::Result result = dlg.open(toqstr(initpath),
1442 QStringList(qt_("LyX Documents (*.lyx)")));
1444 if (result.first == FileDialog::Later)
1448 filename.set(fromqstr(result.second));
1450 // check selected filename
1451 if (filename.empty()) {
1452 // emit message signal.
1453 message(_("Canceled."));
1457 bv->insertLyXFile(filename);
1461 void GuiView::insertPlaintextFile(docstring const & fname,
1464 BufferView * bv = view();
1469 FileName filename(to_utf8(fname));
1471 if (!filename.empty()) {
1472 bv->insertPlaintextFile(filename, asParagraph);
1476 FileDialog dlg(qt_("Select file to insert"), (asParagraph ?
1477 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1479 FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
1482 if (result.first == FileDialog::Later)
1486 filename.set(fromqstr(result.second));
1488 // check selected filename
1489 if (filename.empty()) {
1490 // emit message signal.
1491 message(_("Canceled."));
1495 bv->insertPlaintextFile(filename, asParagraph);
1499 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1501 FileName fname = b.fileName();
1502 FileName const oldname = fname;
1504 if (!newname.empty()) {
1506 fname = support::makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1508 // Switch to this Buffer.
1511 /// No argument? Ask user through dialog.
1513 FileDialog dlg(qt_("Choose a filename to save document as"),
1514 LFUN_BUFFER_WRITE_AS);
1515 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1516 dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1518 if (!isLyXFilename(fname.absFilename()))
1519 fname.changeExtension(".lyx");
1521 FileDialog::Result result =
1522 dlg.save(toqstr(fname.onlyPath().absFilename()),
1523 QStringList(qt_("LyX Documents (*.lyx)")),
1524 toqstr(fname.onlyFileName()));
1526 if (result.first == FileDialog::Later)
1529 fname.set(fromqstr(result.second));
1534 if (!isLyXFilename(fname.absFilename()))
1535 fname.changeExtension(".lyx");
1538 if (FileName(fname).exists()) {
1539 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1540 docstring text = bformat(_("The document %1$s already "
1541 "exists.\n\nDo you want to "
1542 "overwrite that document?"),
1544 int const ret = Alert::prompt(_("Overwrite document?"),
1545 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1548 case 1: return renameBuffer(b, docstring());
1549 case 2: return false;
1553 // Ok, change the name of the buffer
1554 b.setFileName(fname.absFilename());
1556 bool unnamed = b.isUnnamed();
1557 b.setUnnamed(false);
1558 b.saveCheckSum(fname);
1560 if (!saveBuffer(b)) {
1561 b.setFileName(oldname.absFilename());
1562 b.setUnnamed(unnamed);
1563 b.saveCheckSum(oldname);
1571 bool GuiView::saveBuffer(Buffer & b)
1574 return renameBuffer(b, docstring());
1577 LyX::ref().session().lastFiles().add(b.fileName());
1581 // Switch to this Buffer.
1584 // FIXME: we don't tell the user *WHY* the save failed !!
1585 docstring const file = makeDisplayPath(b.absFileName(), 30);
1586 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1587 "Do you want to rename the document and "
1588 "try again?"), file);
1589 int const ret = Alert::prompt(_("Rename and save?"),
1590 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1593 if (!renameBuffer(b, docstring()))
1602 return saveBuffer(b);
1606 bool GuiView::closeBuffer()
1608 Buffer * buf = buffer();
1609 return buf && closeBuffer(*buf);
1613 bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
1615 // goto bookmark to update bookmark pit.
1616 //FIXME: we should update only the bookmarks related to this buffer!
1617 for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
1618 theLyXFunc().gotoBookmark(i+1, false, false);
1620 if (buf.isClean() || buf.paragraphs().empty()) {
1621 if (buf.masterBuffer() == &buf && tolastopened)
1622 LyX::ref().session().lastOpened().add(buf.fileName());
1623 theBufferList().release(&buf);
1626 // Switch to this Buffer.
1631 if (buf.isUnnamed())
1632 file = from_utf8(buf.fileName().onlyFileName());
1634 file = buf.fileName().displayName(30);
1636 // Bring this window to top before asking questions.
1640 docstring const text = bformat(_("The document %1$s has unsaved changes."
1641 "\n\nDo you want to save the document or discard the changes?"), file);
1642 int const ret = Alert::prompt(_("Save changed document?"),
1643 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1647 if (!saveBuffer(buf))
1651 // if we crash after this we could
1652 // have no autosave file but I guess
1653 // this is really improbable (Jug)
1654 removeAutosaveFile(buf.absFileName());
1660 // save file names to .lyx/session
1661 // if master/slave are both open, do not save slave since it
1662 // will be automatically loaded when the master is loaded
1663 if (buf.masterBuffer() == &buf && tolastopened)
1664 LyX::ref().session().lastOpened().add(buf.fileName());
1666 theBufferList().release(&buf);
1671 bool GuiView::dispatch(FuncRequest const & cmd)
1673 BufferView * bv = view();
1674 // By default we won't need any update.
1676 bv->cursor().updateFlags(Update::None);
1678 switch(cmd.action) {
1679 case LFUN_BUFFER_IMPORT:
1680 importDocument(to_utf8(cmd.argument()));
1683 case LFUN_BUFFER_SWITCH:
1684 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1687 case LFUN_BUFFER_NEXT:
1688 setBuffer(theBufferList().next(buffer()));
1691 case LFUN_BUFFER_PREVIOUS:
1692 setBuffer(theBufferList().previous(buffer()));
1695 case LFUN_COMMAND_EXECUTE: {
1696 bool const show_it = cmd.argument() != "off";
1697 d.toolbars_->showCommandBuffer(show_it);
1700 case LFUN_DROP_LAYOUTS_CHOICE:
1702 d.layout_->showPopup();
1705 case LFUN_MENU_OPEN:
1706 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument()), *this))
1707 menu->exec(QCursor::pos());
1710 case LFUN_FILE_INSERT:
1711 insertLyXFile(cmd.argument());
1713 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1714 insertPlaintextFile(cmd.argument(), true);
1717 case LFUN_FILE_INSERT_PLAINTEXT:
1718 insertPlaintextFile(cmd.argument(), false);
1721 case LFUN_BUFFER_WRITE:
1723 saveBuffer(bv->buffer());
1726 case LFUN_BUFFER_WRITE_AS:
1728 renameBuffer(bv->buffer(), cmd.argument());
1731 case LFUN_BUFFER_WRITE_ALL: {
1732 Buffer * first = theBufferList().first();
1735 message(_("Saving all documents..."));
1736 // We cannot use a for loop as the buffer list cycles.
1739 if (!b->isClean()) {
1741 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1743 b = theBufferList().next(b);
1744 } while (b != first);
1745 message(_("All documents saved."));
1749 case LFUN_TOOLBAR_TOGGLE: {
1750 string const name = cmd.getArg(0);
1751 bool const allowauto = cmd.getArg(1) == "allowauto";
1752 // it is possible to get current toolbar status like this,...
1753 // but I decide to obey the order of ToolbarBackend::flags
1754 // and disregard real toolbar status.
1755 // toolbars_->saveToolbarInfo();
1757 // toggle state on/off/auto
1758 d.toolbars_->toggleToolbarState(name, allowauto);
1762 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1764 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1768 if (tbi->flags & ToolbarInfo::ON)
1770 else if (tbi->flags & ToolbarInfo::OFF)
1772 else if (tbi->flags & ToolbarInfo::AUTO)
1775 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1776 _(tbi->gui_name), state));
1780 case LFUN_DIALOG_UPDATE: {
1781 string const name = to_utf8(cmd.argument());
1782 // Can only update a dialog connected to an existing inset
1783 Inset * inset = getOpenInset(name);
1785 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1786 inset->dispatch(view()->cursor(), fr);
1787 } else if (name == "paragraph") {
1788 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1789 } else if (name == "prefs") {
1790 updateDialog(name, string());
1795 case LFUN_DIALOG_TOGGLE: {
1796 if (isDialogVisible(cmd.getArg(0)))
1797 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1799 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1803 case LFUN_DIALOG_DISCONNECT_INSET:
1804 disconnectDialog(to_utf8(cmd.argument()));
1807 case LFUN_DIALOG_HIDE: {
1808 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1812 case LFUN_DIALOG_SHOW: {
1813 string const name = cmd.getArg(0);
1814 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1816 if (name == "character") {
1817 data = freefont2string();
1819 showDialog("character", data);
1820 } else if (name == "latexlog") {
1821 Buffer::LogType type;
1822 string const logfile = buffer()->logName(&type);
1824 case Buffer::latexlog:
1827 case Buffer::buildlog:
1831 data += Lexer::quoteString(logfile);
1832 showDialog("log", data);
1833 } else if (name == "vclog") {
1834 string const data = "vc " +
1835 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1836 showDialog("log", data);
1837 } else if (name == "symbols") {
1838 data = bv->cursor().getEncoding()->name();
1840 showDialog("symbols", data);
1842 showDialog(name, data);
1846 case LFUN_INSET_APPLY: {
1847 string const name = cmd.getArg(0);
1848 Inset * inset = getOpenInset(name);
1850 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1851 inset->dispatch(view()->cursor(), fr);
1853 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1859 case LFUN_UI_TOGGLE:
1861 // Make sure the keyboard focus stays in the work area.
1865 case LFUN_COMPLETION_INLINE:
1866 if (d.current_work_area_)
1867 d.current_work_area_->completer().showInline();
1870 case LFUN_SPLIT_VIEW:
1871 if (Buffer * buf = buffer()) {
1872 string const orientation = cmd.getArg(0);
1873 d.splitter_->setOrientation(orientation == "vertical"
1874 ? Qt::Vertical : Qt::Horizontal);
1875 TabWorkArea * twa = addTabWorkArea();
1876 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1877 setCurrentWorkArea(wa);
1881 case LFUN_CLOSE_TAB_GROUP:
1882 if (TabWorkArea * twa = d.currentTabWorkArea()) {
1884 twa = d.currentTabWorkArea();
1885 // Switch to the next GuiWorkArea in the found TabWorkArea.
1886 d.current_work_area_ = twa? twa->currentWorkArea() : 0;
1887 if (d.splitter_->count() == 0)
1888 // No more work area, switch to the background widget.
1893 case LFUN_COMPLETION_POPUP:
1894 if (d.current_work_area_)
1895 d.current_work_area_->completer().showPopup();
1899 case LFUN_COMPLETION_COMPLETE:
1900 if (d.current_work_area_)
1901 d.current_work_area_->completer().tab();
1912 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1914 string const arg = cmd.getArg(0);
1915 if (arg == "scrollbar") {
1916 // hide() is of no help
1917 if (d.current_work_area_->verticalScrollBarPolicy() ==
1918 Qt::ScrollBarAlwaysOff)
1920 d.current_work_area_->setVerticalScrollBarPolicy(
1921 Qt::ScrollBarAsNeeded);
1923 d.current_work_area_->setVerticalScrollBarPolicy(
1924 Qt::ScrollBarAlwaysOff);
1927 if (arg == "statusbar") {
1928 statusBar()->setVisible(!statusBar()->isVisible());
1931 if (arg == "menubar") {
1932 menuBar()->setVisible(!menuBar()->isVisible());
1935 #if QT_VERSION >= 0x040300
1936 if (arg == "frame") {
1938 getContentsMargins(&l, &t, &r, &b);
1939 //are the frames in default state?
1940 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1942 setContentsMargins(-2, -2, -2, -2);
1944 setContentsMargins(0, 0, 0, 0);
1949 if (arg != "fullscreen") {
1950 message(bformat("LFUN_UI_TOGGLE " + _("%1$s unknown command!"), from_utf8(arg)));
1954 if (lyxrc.full_screen_toolbars)
1955 d.toolbars_->toggleFullScreen(!isFullScreen());
1957 if (isFullScreen()) {
1958 for (int i = 0; i != d.splitter_->count(); ++i)
1959 d.tabWorkArea(i)->setFullScreen(false);
1960 #if QT_VERSION >= 0x040300
1961 setContentsMargins(0, 0, 0, 0);
1963 setWindowState(windowState() ^ Qt::WindowFullScreen);
1965 statusBar()->show();
1967 for (int i = 0; i != d.splitter_->count(); ++i)
1968 d.tabWorkArea(i)->setFullScreen(true);
1969 #if QT_VERSION >= 0x040300
1970 setContentsMargins(-2, -2, -2, -2);
1972 setWindowState(windowState() ^ Qt::WindowFullScreen);
1973 statusBar()->hide();
1979 Buffer const * GuiView::updateInset(Inset const * inset)
1981 if (!d.current_work_area_)
1985 d.current_work_area_->scheduleRedraw();
1987 return &d.current_work_area_->bufferView().buffer();
1991 void GuiView::restartCursor()
1993 /* When we move around, or type, it's nice to be able to see
1994 * the cursor immediately after the keypress.
1996 if (d.current_work_area_)
1997 d.current_work_area_->startBlinkingCursor();
1999 // Take this occasion to update the other GUI elements.
2004 void GuiView::updateCompletion(Cursor & cur, bool start, bool keep)
2006 if (d.current_work_area_)
2007 d.current_work_area_->completer().updateVisibility(cur, start, keep);
2012 // This list should be kept in sync with the list of insets in
2013 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
2014 // dialog should have the same name as the inset.
2016 char const * const dialognames[] = {
2017 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
2018 "citation", "document", "errorlist", "ert", "external", "file",
2019 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
2020 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
2021 "ref", "sendto", "space", "spellchecker", "symbols", "tabular", "tabularcreate",
2023 #ifdef HAVE_LIBAIKSAURUS
2027 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
2029 char const * const * const end_dialognames =
2030 dialognames + (sizeof(dialognames) / sizeof(char *));
2034 cmpCStr(char const * name) : name_(name) {}
2035 bool operator()(char const * other) {
2036 return strcmp(other, name_) == 0;
2043 bool isValidName(string const & name)
2045 return find_if(dialognames, end_dialognames,
2046 cmpCStr(name.c_str())) != end_dialognames;
2052 void GuiView::resetDialogs()
2054 // Make sure that no LFUN uses any LyXView.
2055 theLyXFunc().setLyXView(0);
2056 // FIXME: the "math panels" toolbar takes an awful lot of time to
2057 // initialise so we don't do that for the time being.
2058 //d.toolbars_->init();
2059 guiApp->menus().fillMenuBar(menuBar(), this);
2061 d.layout_->updateContents(true);
2062 // Now update controls with current buffer.
2063 theLyXFunc().setLyXView(this);
2068 Dialog * GuiView::find_or_build(string const & name)
2070 if (!isValidName(name))
2073 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2075 if (it != d.dialogs_.end())
2076 return it->second.get();
2078 Dialog * dialog = build(name);
2079 d.dialogs_[name].reset(dialog);
2080 if (lyxrc.allow_geometry_session)
2081 dialog->restoreSession();
2086 void GuiView::showDialog(string const & name, string const & data,
2093 Dialog * dialog = find_or_build(name);
2095 dialog->showData(data);
2097 d.open_insets_[name] = inset;
2103 bool GuiView::isDialogVisible(string const & name) const
2105 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2106 if (it == d.dialogs_.end())
2108 return it->second.get()->isVisibleView();
2112 void GuiView::hideDialog(string const & name, Inset * inset)
2114 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2115 if (it == d.dialogs_.end())
2118 if (inset && inset != getOpenInset(name))
2121 Dialog * const dialog = it->second.get();
2122 if (dialog->isVisibleView())
2124 d.open_insets_[name] = 0;
2128 void GuiView::disconnectDialog(string const & name)
2130 if (!isValidName(name))
2133 if (d.open_insets_.find(name) != d.open_insets_.end())
2134 d.open_insets_[name] = 0;
2138 Inset * GuiView::getOpenInset(string const & name) const
2140 if (!isValidName(name))
2143 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2144 return it == d.open_insets_.end() ? 0 : it->second;
2148 void GuiView::hideAll() const
2150 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2151 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2153 for(; it != end; ++it)
2154 it->second->hideView();
2158 void GuiView::updateDialogs()
2160 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2161 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2163 for(; it != end; ++it) {
2164 Dialog * dialog = it->second.get();
2165 if (dialog && dialog->isVisibleView())
2166 dialog->checkStatus();
2174 // will be replaced by a proper factory...
2175 Dialog * createGuiAbout(GuiView & lv);
2176 Dialog * createGuiBibitem(GuiView & lv);
2177 Dialog * createGuiBibtex(GuiView & lv);
2178 Dialog * createGuiBox(GuiView & lv);
2179 Dialog * createGuiBranch(GuiView & lv);
2180 Dialog * createGuiChanges(GuiView & lv);
2181 Dialog * createGuiCharacter(GuiView & lv);
2182 Dialog * createGuiCitation(GuiView & lv);
2183 Dialog * createGuiDelimiter(GuiView & lv);
2184 Dialog * createGuiDocument(GuiView & lv);
2185 Dialog * createGuiErrorList(GuiView & lv);
2186 Dialog * createGuiERT(GuiView & lv);
2187 Dialog * createGuiExternal(GuiView & lv);
2188 Dialog * createGuiFloat(GuiView & lv);
2189 Dialog * createGuiGraphics(GuiView & lv);
2190 Dialog * createGuiHSpace(GuiView & lv);
2191 Dialog * createGuiInclude(GuiView & lv);
2192 Dialog * createGuiLabel(GuiView & lv);
2193 Dialog * createGuiListings(GuiView & lv);
2194 Dialog * createGuiLog(GuiView & lv);
2195 Dialog * createGuiMathMatrix(GuiView & lv);
2196 Dialog * createGuiNomenclature(GuiView & lv);
2197 Dialog * createGuiNote(GuiView & lv);
2198 Dialog * createGuiParagraph(GuiView & lv);
2199 Dialog * createGuiPreferences(GuiView & lv);
2200 Dialog * createGuiPrint(GuiView & lv);
2201 Dialog * createGuiRef(GuiView & lv);
2202 Dialog * createGuiSearch(GuiView & lv);
2203 Dialog * createGuiSendTo(GuiView & lv);
2204 Dialog * createGuiShowFile(GuiView & lv);
2205 Dialog * createGuiSpellchecker(GuiView & lv);
2206 Dialog * createGuiSymbols(GuiView & lv);
2207 Dialog * createGuiTabularCreate(GuiView & lv);
2208 Dialog * createGuiTabular(GuiView & lv);
2209 Dialog * createGuiTexInfo(GuiView & lv);
2210 Dialog * createGuiToc(GuiView & lv);
2211 Dialog * createGuiThesaurus(GuiView & lv);
2212 Dialog * createGuiHyperlink(GuiView & lv);
2213 Dialog * createGuiVSpace(GuiView & lv);
2214 Dialog * createGuiViewSource(GuiView & lv);
2215 Dialog * createGuiWrap(GuiView & lv);
2218 Dialog * GuiView::build(string const & name)
2220 LASSERT(isValidName(name), /**/);
2222 if (name == "aboutlyx")
2223 return createGuiAbout(*this);
2224 if (name == "bibitem")
2225 return createGuiBibitem(*this);
2226 if (name == "bibtex")
2227 return createGuiBibtex(*this);
2229 return createGuiBox(*this);
2230 if (name == "branch")
2231 return createGuiBranch(*this);
2232 if (name == "changes")
2233 return createGuiChanges(*this);
2234 if (name == "character")
2235 return createGuiCharacter(*this);
2236 if (name == "citation")
2237 return createGuiCitation(*this);
2238 if (name == "document")
2239 return createGuiDocument(*this);
2240 if (name == "errorlist")
2241 return createGuiErrorList(*this);
2243 return createGuiERT(*this);
2244 if (name == "external")
2245 return createGuiExternal(*this);
2247 return createGuiShowFile(*this);
2248 if (name == "findreplace")
2249 return createGuiSearch(*this);
2250 if (name == "float")
2251 return createGuiFloat(*this);
2252 if (name == "graphics")
2253 return createGuiGraphics(*this);
2254 if (name == "include")
2255 return createGuiInclude(*this);
2256 if (name == "nomenclature")
2257 return createGuiNomenclature(*this);
2258 if (name == "label")
2259 return createGuiLabel(*this);
2261 return createGuiLog(*this);
2262 if (name == "view-source")
2263 return createGuiViewSource(*this);
2264 if (name == "mathdelimiter")
2265 return createGuiDelimiter(*this);
2266 if (name == "mathmatrix")
2267 return createGuiMathMatrix(*this);
2269 return createGuiNote(*this);
2270 if (name == "paragraph")
2271 return createGuiParagraph(*this);
2272 if (name == "prefs")
2273 return createGuiPreferences(*this);
2274 if (name == "print")
2275 return createGuiPrint(*this);
2277 return createGuiRef(*this);
2278 if (name == "sendto")
2279 return createGuiSendTo(*this);
2280 if (name == "space")
2281 return createGuiHSpace(*this);
2282 if (name == "spellchecker")
2283 return createGuiSpellchecker(*this);
2284 if (name == "symbols")
2285 return createGuiSymbols(*this);
2286 if (name == "tabular")
2287 return createGuiTabular(*this);
2288 if (name == "tabularcreate")
2289 return createGuiTabularCreate(*this);
2290 if (name == "texinfo")
2291 return createGuiTexInfo(*this);
2292 #ifdef HAVE_LIBAIKSAURUS
2293 if (name == "thesaurus")
2294 return createGuiThesaurus(*this);
2297 return createGuiToc(*this);
2299 return createGuiHyperlink(*this);
2300 if (name == "vspace")
2301 return createGuiVSpace(*this);
2303 return createGuiWrap(*this);
2304 if (name == "listings")
2305 return createGuiListings(*this);
2311 } // namespace frontend
2314 #include "GuiView_moc.cpp"