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 "GuiWorkArea.h"
22 #include "GuiKeySymbol.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
27 #include "qt_helpers.h"
29 #include "frontends/alert.h"
31 #include "buffer_funcs.h"
33 #include "BufferList.h"
34 #include "BufferParams.h"
35 #include "BufferView.h"
36 #include "Converter.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "support/gettext.h"
49 #include "Paragraph.h"
50 #include "TextClass.h"
52 #include "ToolbarBackend.h"
55 #include "support/debug.h"
56 #include "support/FileFilterList.h"
57 #include "support/FileName.h"
58 #include "support/filetools.h"
59 #include "support/ForkedCalls.h"
60 #include "support/lstrings.h"
61 #include "support/os.h"
62 #include "support/Package.h"
63 #include "support/Timeout.h"
66 #include <QApplication>
67 #include <QCloseEvent>
69 #include <QDesktopWidget>
70 #include <QDragEnterEvent>
78 #include <QPushButton>
82 #include <QStackedWidget>
89 #include <boost/assert.hpp>
90 #include <boost/bind.hpp>
92 #ifdef HAVE_SYS_TIME_H
93 # include <sys/time.h>
100 using namespace lyx::support;
107 class BackgroundWidget : public QWidget
112 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
113 /// The text to be written on top of the pixmap
114 QString const text = lyx_version ? lyx_version : qt_("unknown version");
115 splash_ = QPixmap(":/images/banner.png");
117 QPainter pain(&splash_);
118 pain.setPen(QColor(255, 255, 0));
120 // The font used to display the version info
121 font.setStyleHint(QFont::SansSerif);
122 font.setWeight(QFont::Bold);
123 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
125 pain.drawText(260, 270, text);
128 void paintEvent(QPaintEvent *)
130 int x = (width() - splash_.width()) / 2;
131 int y = (height() - splash_.height()) / 2;
133 pain.drawPixmap(x, y, splash_);
143 typedef boost::shared_ptr<Dialog> DialogPtr;
145 struct GuiView::GuiViewPrivate
148 : current_work_area_(0), layout_(0),
149 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
151 // hardcode here the platform specific icon size
152 smallIconSize = 14; // scaling problems
153 normalIconSize = 20; // ok, default
154 bigIconSize = 26; // better for some math icons
156 splitter_ = new QSplitter;
157 bg_widget_ = new BackgroundWidget;
158 stack_widget_ = new QStackedWidget;
159 stack_widget_->addWidget(bg_widget_);
160 stack_widget_->addWidget(splitter_);
168 delete stack_widget_;
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);
212 stack_widget_->setCurrentWidget(bg_widget_);
213 bg_widget_->setUpdatesEnabled(true);
216 TabWorkArea * tabWorkArea(int i)
218 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
221 TabWorkArea * currentTabWorkArea()
223 if (splitter_->count() == 1)
224 // The first TabWorkArea is always the first one, if any.
225 return tabWorkArea(0);
227 for (int i = 0; i != splitter_->count(); ++i) {
228 TabWorkArea * twa = tabWorkArea(i);
229 if (current_work_area_ == twa->currentWorkArea())
233 // None has the focus so we just take the first one.
234 return tabWorkArea(0);
238 GuiWorkArea * current_work_area_;
239 QSplitter * splitter_;
240 QStackedWidget * stack_widget_;
241 BackgroundWidget * bg_widget_;
243 GuiToolbars * toolbars_;
244 /// The main layout box.
246 * \warning Don't Delete! The layout box is actually owned by
247 * whichever toolbar contains it. All the GuiView class needs is a
248 * means of accessing it.
250 * FIXME: replace that with a proper model so that we are not limited
251 * to only one dialog.
253 GuiLayoutBox * layout_;
256 map<string, Inset *> open_insets_;
259 map<string, DialogPtr> dialogs_;
261 unsigned int smallIconSize;
262 unsigned int normalIconSize;
263 unsigned int bigIconSize;
265 QTimer statusbar_timer_;
266 /// are we quitting by the menu?
267 bool quitting_by_menu_;
268 /// auto-saving of buffers
269 Timeout autosave_timeout_;
270 /// flag against a race condition due to multiclicks, see bug #1119
275 GuiView::GuiView(int id)
276 : d(*new GuiViewPrivate), id_(id)
278 // GuiToolbars *must* be initialised before the menu bar.
279 d.toolbars_ = new GuiToolbars(*this);
281 // Fill up the menu bar.
282 guiApp->menus().fillMenuBar(this);
284 setCentralWidget(d.stack_widget_);
286 // Start autosave timer
287 if (lyxrc.autosave) {
288 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
289 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
290 d.autosave_timeout_.start();
292 connect(&d.statusbar_timer_, SIGNAL(timeout()),
293 this, SLOT(clearMessage()));
295 // Qt bug? signal lastWindowClosed does not work
296 setAttribute(Qt::WA_QuitOnClose, false);
297 setAttribute(Qt::WA_DeleteOnClose, true);
299 // assign an icon to main form. We do not do it under Qt/Mac,
300 // since the icon is provided in the application bundle.
301 setWindowIcon(QPixmap(":/images/lyx.png"));
305 setAcceptDrops(true);
307 statusBar()->setSizeGripEnabled(true);
309 // Forbid too small unresizable window because it can happen
310 // with some window manager under X11.
311 setMinimumSize(300, 200);
313 if (!lyxrc.allow_geometry_session)
314 // No session handling, default to a sane size.
315 setGeometry(50, 50, 690, 510);
317 // Now take care of session management.
319 QString const key = "view-" + QString::number(id_);
321 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
322 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
326 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
327 setGeometry(50, 50, 690, 510);
329 setIconSize(settings.value(key + "/icon_size").toSize());
339 void GuiView::close()
341 d.quitting_by_menu_ = true;
342 d.current_work_area_ = 0;
343 for (int i = 0; i != d.splitter_->count(); ++i) {
344 TabWorkArea * twa = d.tabWorkArea(i);
348 QMainWindow::close();
349 d.quitting_by_menu_ = false;
353 void GuiView::setFocus()
355 if (d.current_work_area_)
356 d.current_work_area_->setFocus();
362 QMenu * GuiView::createPopupMenu()
364 return d.toolBarPopup(this);
368 void GuiView::showEvent(QShowEvent * e)
370 LYXERR(Debug::GUI, "Passed Geometry "
371 << size().height() << "x" << size().width()
372 << "+" << pos().x() << "+" << pos().y());
374 if (d.splitter_->count() == 0)
375 // No work area, switch to the background widget.
378 QMainWindow::showEvent(e);
382 void GuiView::closeEvent(QCloseEvent * close_event)
384 // we may have been called through the close window button
385 // which bypasses the LFUN machinery.
386 if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
387 if (!quitWriteAll()) {
388 close_event->ignore();
393 while (Buffer * b = buffer()) {
395 // This is a child document, just close the tab after saving
396 // but keep the file loaded.
397 if (!saveBuffer(*b)) {
398 close_event->ignore();
401 removeWorkArea(d.current_work_area_);
405 std::vector<int> const & ids = guiApp->viewIds();
406 for (int i = 0; i != ids.size(); ++i) {
409 if (GuiWorkArea * wa = guiApp->view(ids[i]).workArea(*b)) {
410 // FIXME 1: should we put an alert box here that the buffer
411 // is viewed elsewhere?
412 // FIXME 2: should we try to save this buffer in any case?
415 // This buffer is also opened in another view, so
416 // but close the associated work area nevertheless.
417 removeWorkArea(d.current_work_area_);
418 // but don't close it.
423 if (b && !closeBuffer(*b)) {
424 close_event->ignore();
429 // Make sure that no LFUN use this close to be closed View.
430 theLyXFunc().setLyXView(0);
432 // Save toolbars configuration
433 if (isFullScreen()) {
434 d.toolbars_->toggleFullScreen(!isFullScreen());
438 // Make sure the timer time out will not trigger a statusbar update.
439 d.statusbar_timer_.stop();
441 // Saving fullscreen requires additional tweaks in the toolbar code.
442 // It wouldn't also work under linux natively.
443 if (lyxrc.allow_geometry_session && !isFullScreen()) {
445 QString const key = "view-" + QString::number(id_);
447 settings.setValue(key + "/pos", pos());
448 settings.setValue(key + "/size", size());
450 settings.setValue(key + "/geometry", saveGeometry());
452 settings.setValue(key + "/icon_size", iconSize());
453 d.toolbars_->saveToolbarInfo();
454 // Now take care of all other dialogs:
455 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
456 for (; it!= d.dialogs_.end(); ++it)
457 it->second->saveSession();
460 guiApp->unregisterView(id_);
461 if (guiApp->viewCount() > 0) {
462 // Just close the window and do nothing else if this is not the
464 close_event->accept();
470 // this is the place where we leave the frontend.
471 // it is the only point at which we start quitting.
472 close_event->accept();
473 // quit the event loop
478 void GuiView::dragEnterEvent(QDragEnterEvent * event)
480 if (event->mimeData()->hasUrls())
482 /// \todo Ask lyx-devel is this is enough:
483 /// if (event->mimeData()->hasFormat("text/plain"))
484 /// event->acceptProposedAction();
488 void GuiView::dropEvent(QDropEvent* event)
490 QList<QUrl> files = event->mimeData()->urls();
494 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
495 for (int i = 0; i != files.size(); ++i) {
496 string const file = os::internal_path(fromqstr(
497 files.at(i).toLocalFile()));
499 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
504 void GuiView::message(docstring const & str)
506 if (ForkedProcess::iAmAChild())
509 statusBar()->showMessage(toqstr(str));
510 d.statusbar_timer_.stop();
511 d.statusbar_timer_.start(3000);
515 void GuiView::smallSizedIcons()
517 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
521 void GuiView::normalSizedIcons()
523 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
527 void GuiView::bigSizedIcons()
529 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
533 void GuiView::clearMessage()
537 theLyXFunc().setLyXView(this);
538 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
539 d.statusbar_timer_.stop();
543 void GuiView::updateWindowTitle(GuiWorkArea * wa)
545 if (wa != d.current_work_area_)
547 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
548 setWindowIconText(wa->windowIconText());
552 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
555 disconnectBufferView();
556 connectBufferView(wa->bufferView());
557 connectBuffer(wa->bufferView().buffer());
558 d.current_work_area_ = wa;
559 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
560 this, SLOT(updateWindowTitle(GuiWorkArea *)));
561 updateWindowTitle(wa);
564 // Buffer-dependent dialogs should be updated or
565 // hidden. This should go here because some dialogs (eg ToC)
566 // require bv_->text.
567 updateBufferDependent(true);
574 void GuiView::updateStatusBar()
576 // let the user see the explicit message
577 if (d.statusbar_timer_.isActive())
580 theLyXFunc().setLyXView(this);
581 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
585 bool GuiView::hasFocus() const
587 return qApp->activeWindow() == this;
591 bool GuiView::event(QEvent * e)
595 // Useful debug code:
596 //case QEvent::ActivationChange:
597 //case QEvent::WindowDeactivate:
598 //case QEvent::Paint:
599 //case QEvent::Enter:
600 //case QEvent::Leave:
601 //case QEvent::HoverEnter:
602 //case QEvent::HoverLeave:
603 //case QEvent::HoverMove:
604 //case QEvent::StatusTip:
605 //case QEvent::DragEnter:
606 //case QEvent::DragLeave:
610 case QEvent::WindowActivate: {
611 guiApp->setCurrentView(*this);
612 if (d.current_work_area_) {
613 BufferView & bv = d.current_work_area_->bufferView();
614 connectBufferView(bv);
615 connectBuffer(bv.buffer());
616 // The document structure, name and dialogs might have
617 // changed in another view.
618 updateBufferDependent(true);
623 setWindowTitle(qt_("LyX"));
624 setWindowIconText(qt_("LyX"));
627 return QMainWindow::event(e);
630 case QEvent::ShortcutOverride: {
631 if (d.current_work_area_)
632 // Nothing special to do.
633 return QMainWindow::event(e);
635 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
637 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
639 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
640 || ke->key() == Qt::Key_Backtab)
641 return QMainWindow::event(e);
643 // Allow processing of shortcuts that are allowed even when no Buffer
645 theLyXFunc().setLyXView(this);
647 setKeySymbol(&sym, ke);
648 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
654 return QMainWindow::event(e);
659 bool GuiView::focusNextPrevChild(bool /*next*/)
666 void GuiView::setBusy(bool busy)
668 if (d.current_work_area_) {
669 d.current_work_area_->setUpdatesEnabled(!busy);
671 d.current_work_area_->stopBlinkingCursor();
673 d.current_work_area_->startBlinkingCursor();
677 QApplication::setOverrideCursor(Qt::WaitCursor);
679 QApplication::restoreOverrideCursor();
683 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
685 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
687 if (tbinfo.flags & ToolbarInfo::TOP) {
689 addToolBarBreak(Qt::TopToolBarArea);
690 addToolBar(Qt::TopToolBarArea, toolBar);
693 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
694 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
695 #if (QT_VERSION >= 0x040202)
697 addToolBarBreak(Qt::BottomToolBarArea);
699 addToolBar(Qt::BottomToolBarArea, toolBar);
702 if (tbinfo.flags & ToolbarInfo::LEFT) {
703 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
704 #if (QT_VERSION >= 0x040202)
706 addToolBarBreak(Qt::LeftToolBarArea);
708 addToolBar(Qt::LeftToolBarArea, toolBar);
711 if (tbinfo.flags & ToolbarInfo::RIGHT) {
712 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
713 #if (QT_VERSION >= 0x040202)
715 addToolBarBreak(Qt::RightToolBarArea);
717 addToolBar(Qt::RightToolBarArea, toolBar);
720 // The following does not work so I cannot restore to exact toolbar location
722 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
723 toolBar->move(tbinfo.posx, tbinfo.posy);
730 GuiWorkArea * GuiView::workArea(Buffer & buffer)
732 if (TabWorkArea * twa = d.currentTabWorkArea())
733 return twa->workArea(buffer);
738 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
740 // Automatically create a TabWorkArea if there are none yet.
741 TabWorkArea * tab_widget = d.splitter_->count()
742 ? d.currentTabWorkArea() : addTabWorkArea();
743 return tab_widget->addWorkArea(buffer, *this);
747 TabWorkArea * GuiView::addTabWorkArea()
749 TabWorkArea * twa = new TabWorkArea;
750 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
751 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
752 d.splitter_->addWidget(twa);
753 d.stack_widget_->setCurrentWidget(d.splitter_);
758 GuiWorkArea const * GuiView::currentWorkArea() const
760 return d.current_work_area_;
764 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
768 // Changing work area can result from opening a file so
769 // update the toc in any case.
772 d.current_work_area_ = wa;
773 for (int i = 0; i != d.splitter_->count(); ++i) {
774 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
780 void GuiView::removeWorkArea(GuiWorkArea * wa)
783 if (wa == d.current_work_area_) {
785 disconnectBufferView();
786 hideBufferDependent();
787 d.current_work_area_ = 0;
790 for (int i = 0; i != d.splitter_->count(); ++i) {
791 TabWorkArea * twa = d.tabWorkArea(i);
792 if (!twa->removeWorkArea(wa))
793 // Not found in this tab group.
796 // We found and removed the GuiWorkArea.
798 // No more WorkAreas in this tab group, so delete it.
803 if (d.current_work_area_)
804 // This means that we are not closing the current GuiWorkArea;
807 // Switch to the next GuiWorkArea in the found TabWorkArea.
808 d.current_work_area_ = twa->currentWorkArea();
812 if (d.splitter_->count() == 0)
813 // No more work area, switch to the background widget.
818 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
824 void GuiView::updateLayoutList()
827 d.layout_->updateContents(false);
831 void GuiView::updateToolbars()
833 if (d.current_work_area_) {
835 d.current_work_area_->bufferView().cursor().inMathed();
837 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
839 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
840 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
841 bool const mathmacrotemplate =
842 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
844 d.toolbars_->update(math, table, review, mathmacrotemplate);
846 d.toolbars_->update(false, false, false, false);
848 // update read-only status of open dialogs.
853 Buffer * GuiView::buffer()
855 if (d.current_work_area_)
856 return &d.current_work_area_->bufferView().buffer();
861 Buffer const * GuiView::buffer() const
863 if (d.current_work_area_)
864 return &d.current_work_area_->bufferView().buffer();
869 void GuiView::setBuffer(Buffer * newBuffer)
871 BOOST_ASSERT(newBuffer);
874 GuiWorkArea * wa = workArea(*newBuffer);
876 updateLabels(*newBuffer->masterBuffer());
877 wa = addWorkArea(*newBuffer);
879 //Disconnect the old buffer...there's no new one.
882 connectBuffer(*newBuffer);
883 connectBufferView(wa->bufferView());
884 setCurrentWorkArea(wa);
890 void GuiView::connectBuffer(Buffer & buf)
892 buf.setGuiDelegate(this);
896 void GuiView::disconnectBuffer()
898 if (d.current_work_area_)
899 d.current_work_area_->bufferView().setGuiDelegate(0);
903 void GuiView::connectBufferView(BufferView & bv)
905 bv.setGuiDelegate(this);
909 void GuiView::disconnectBufferView()
911 if (d.current_work_area_)
912 d.current_work_area_->bufferView().setGuiDelegate(0);
916 void GuiView::errors(string const & error_type)
918 ErrorList & el = buffer()->errorList(error_type);
920 showDialog("errorlist", error_type);
924 void GuiView::updateDialog(string const & name, string const & data)
926 if (!isDialogVisible(name))
929 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
930 if (it == d.dialogs_.end())
933 Dialog * const dialog = it->second.get();
934 if (dialog->isVisibleView())
935 dialog->updateData(data);
939 BufferView * GuiView::view()
941 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
945 void GuiView::updateToc()
947 updateDialog("toc", "");
951 void GuiView::updateEmbeddedFiles()
953 updateDialog("embedding", "");
957 void GuiView::autoSave()
959 LYXERR(Debug::INFO, "Running autoSave()");
962 view()->buffer().autoSave();
966 void GuiView::resetAutosaveTimers()
969 d.autosave_timeout_.restart();
973 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
977 Buffer * buf = buffer();
979 /* In LyX/Mac, when a dialog is open, the menus of the
980 application can still be accessed without giving focus to
981 the main window. In this case, we want to disable the menu
982 entries that are buffer-related.
984 Note that this code is not perfect, as bug 1941 attests:
985 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
987 if (cmd.origin == FuncRequest::MENU && !hasFocus())
991 case LFUN_BUFFER_WRITE:
992 enable = buf && (buf->isUnnamed() || !buf->isClean());
995 case LFUN_BUFFER_WRITE_AS:
999 case LFUN_SPLIT_VIEW:
1003 case LFUN_CLOSE_TAB_GROUP:
1004 enable = d.currentTabWorkArea();
1007 case LFUN_TOOLBAR_TOGGLE:
1008 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
1011 case LFUN_DIALOG_TOGGLE:
1012 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
1013 // fall through to set "enable"
1014 case LFUN_DIALOG_SHOW: {
1015 string const name = cmd.getArg(0);
1017 enable = name == "aboutlyx"
1018 || name == "file" //FIXME: should be removed.
1020 || name == "texinfo";
1021 else if (name == "print")
1022 enable = buf->isExportable("dvi")
1023 && lyxrc.print_command != "none";
1024 else if (name == "character") {
1028 InsetCode ic = view()->cursor().inset().lyxCode();
1029 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1032 else if (name == "symbols") {
1033 if (!view() || view()->cursor().inMathed())
1036 InsetCode ic = view()->cursor().inset().lyxCode();
1037 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1040 else if (name == "latexlog")
1041 enable = FileName(buf->logName()).isReadableFile();
1042 else if (name == "spellchecker")
1043 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1044 enable = !buf->isReadonly();
1048 else if (name == "vclog")
1049 enable = buf->lyxvc().inUse();
1053 case LFUN_DIALOG_UPDATE: {
1054 string const name = cmd.getArg(0);
1056 enable = name == "prefs";
1060 case LFUN_INSET_APPLY: {
1065 string const name = cmd.getArg(0);
1066 Inset * inset = getOpenInset(name);
1068 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1070 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1071 // Every inset is supposed to handle this
1072 BOOST_ASSERT(false);
1076 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1077 flag |= getStatus(fr);
1079 enable = flag.enabled();
1083 case LFUN_COMPLETION_INLINE:
1084 if (!d.current_work_area_
1085 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1089 case LFUN_COMPLETION_POPUP:
1090 if (!d.current_work_area_
1091 || !d.current_work_area_->completer().popupPossible(view()->cursor()))
1095 case LFUN_COMPLETION_COMPLETE:
1096 if (!d.current_work_area_
1097 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1109 flag.enabled(false);
1115 static FileName selectTemplateFile()
1117 FileDialog dlg(_("Select template file"));
1118 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1119 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1121 FileDialog::Result result =
1122 dlg.open(from_utf8(lyxrc.template_path),
1123 FileFilterList(_("LyX Documents (*.lyx)")),
1126 if (result.first == FileDialog::Later)
1128 if (result.second.empty())
1130 return FileName(to_utf8(result.second));
1134 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1138 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1141 message(_("Document not loaded."));
1146 setBuffer(newBuffer);
1148 // scroll to the position when the file was last closed
1149 if (lyxrc.use_lastfilepos) {
1150 LastFilePosSection::FilePos filepos =
1151 LyX::ref().session().lastFilePos().load(filename);
1152 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1156 LyX::ref().session().lastFiles().add(filename);
1163 void GuiView::openDocument(string const & fname)
1165 string initpath = lyxrc.document_path;
1168 string const trypath = buffer()->filePath();
1169 // If directory is writeable, use this as default.
1170 if (FileName(trypath).isDirWritable())
1176 if (fname.empty()) {
1177 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
1178 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1179 dlg.setButton2(_("Examples|#E#e"),
1180 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1182 FileDialog::Result result =
1183 dlg.open(from_utf8(initpath),
1184 FileFilterList(_("LyX Documents (*.lyx)")),
1187 if (result.first == FileDialog::Later)
1190 filename = to_utf8(result.second);
1192 // check selected filename
1193 if (filename.empty()) {
1194 message(_("Canceled."));
1200 // get absolute path of file and add ".lyx" to the filename if
1202 FileName const fullname =
1203 fileSearch(string(), filename, "lyx", support::may_not_exist);
1204 if (!fullname.empty())
1205 filename = fullname.absFilename();
1207 // if the file doesn't exist, let the user create one
1208 if (!fullname.exists()) {
1209 // the user specifically chose this name. Believe him.
1210 Buffer * const b = newFile(filename, string(), true);
1216 docstring const disp_fn = makeDisplayPath(filename);
1217 message(bformat(_("Opening document %1$s..."), disp_fn));
1220 Buffer * buf = loadDocument(fullname);
1224 buf->errors("Parse");
1225 str2 = bformat(_("Document %1$s opened."), disp_fn);
1227 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1232 // FIXME: clean that
1233 static bool import(GuiView * lv, FileName const & filename,
1234 string const & format, ErrorList & errorList)
1236 FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
1238 string loader_format;
1239 vector<string> loaders = theConverters().loaders();
1240 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1241 for (vector<string>::const_iterator it = loaders.begin();
1242 it != loaders.end(); ++it) {
1243 if (!theConverters().isReachable(format, *it))
1246 string const tofile =
1247 changeExtension(filename.absFilename(),
1248 formats.extension(*it));
1249 if (!theConverters().convert(0, filename, FileName(tofile),
1250 filename, format, *it, errorList))
1252 loader_format = *it;
1255 if (loader_format.empty()) {
1256 frontend::Alert::error(_("Couldn't import file"),
1257 bformat(_("No information for importing the format %1$s."),
1258 formats.prettyName(format)));
1262 loader_format = format;
1264 if (loader_format == "lyx") {
1265 Buffer * buf = lv->loadDocument(lyxfile);
1270 buf->errors("Parse");
1272 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1276 bool as_paragraphs = loader_format == "textparagraph";
1277 string filename2 = (loader_format == format) ? filename.absFilename()
1278 : changeExtension(filename.absFilename(),
1279 formats.extension(loader_format));
1280 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1281 theLyXFunc().setLyXView(lv);
1282 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1289 void GuiView::importDocument(string const & argument)
1292 string filename = split(argument, format, ' ');
1294 LYXERR(Debug::INFO, format << " file: " << filename);
1296 // need user interaction
1297 if (filename.empty()) {
1298 string initpath = lyxrc.document_path;
1300 Buffer const * buf = buffer();
1302 string const trypath = buf->filePath();
1303 // If directory is writeable, use this as default.
1304 if (FileName(trypath).isDirWritable())
1308 docstring const text = bformat(_("Select %1$s file to import"),
1309 formats.prettyName(format));
1311 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
1312 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1313 dlg.setButton2(_("Examples|#E#e"),
1314 from_utf8(addPath(package().system_support().absFilename(), "examples")));
1316 docstring filter = formats.prettyName(format);
1319 filter += from_utf8(formats.extension(format));
1322 FileDialog::Result result =
1323 dlg.open(from_utf8(initpath),
1324 FileFilterList(filter),
1327 if (result.first == FileDialog::Later)
1330 filename = to_utf8(result.second);
1332 // check selected filename
1333 if (filename.empty())
1334 message(_("Canceled."));
1337 if (filename.empty())
1340 // get absolute path of file
1341 FileName const fullname(makeAbsPath(filename));
1343 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
1345 // Check if the document already is open
1346 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1349 if (!closeBuffer()) {
1350 message(_("Canceled."));
1355 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1357 // if the file exists already, and we didn't do
1358 // -i lyx thefile.lyx, warn
1359 if (lyxfile.exists() && fullname != lyxfile) {
1361 docstring text = bformat(_("The document %1$s already exists.\n\n"
1362 "Do you want to overwrite that document?"), displaypath);
1363 int const ret = Alert::prompt(_("Overwrite document?"),
1364 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1367 message(_("Canceled."));
1372 message(bformat(_("Importing %1$s..."), displaypath));
1373 ErrorList errorList;
1374 if (import(this, fullname, format, errorList))
1375 message(_("imported."));
1377 message(_("file not imported!"));
1379 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1383 void GuiView::newDocument(string const & filename, bool from_template)
1385 FileName initpath(lyxrc.document_path);
1386 Buffer * buf = buffer();
1388 FileName const trypath(buf->filePath());
1389 // If directory is writeable, use this as default.
1390 if (trypath.isDirWritable())
1394 string templatefile = from_template ?
1395 selectTemplateFile().absFilename() : string();
1397 if (filename.empty())
1398 b = newUnnamedFile(templatefile, initpath);
1400 b = newFile(filename, templatefile, true);
1404 // Ensure the cursor is correctly positionned on screen.
1405 view()->showCursor();
1409 void GuiView::insertLyXFile(docstring const & fname)
1411 BufferView * bv = view();
1416 FileName filename(to_utf8(fname));
1418 if (!filename.empty()) {
1419 bv->insertLyXFile(filename);
1423 // Launch a file browser
1425 string initpath = lyxrc.document_path;
1426 string const trypath = bv->buffer().filePath();
1427 // If directory is writeable, use this as default.
1428 if (FileName(trypath).isDirWritable())
1432 FileDialog dlg(_("Select LyX document to insert"), LFUN_FILE_INSERT);
1433 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1434 dlg.setButton2(_("Examples|#E#e"),
1435 from_utf8(addPath(package().system_support().absFilename(),
1438 FileDialog::Result result =
1439 dlg.open(from_utf8(initpath),
1440 FileFilterList(_("LyX Documents (*.lyx)")),
1443 if (result.first == FileDialog::Later)
1447 filename.set(to_utf8(result.second));
1449 // check selected filename
1450 if (filename.empty()) {
1451 // emit message signal.
1452 message(_("Canceled."));
1456 bv->insertLyXFile(filename);
1460 void GuiView::insertPlaintextFile(docstring const & fname,
1463 BufferView * bv = view();
1468 FileName filename(to_utf8(fname));
1470 if (!filename.empty()) {
1471 bv->insertPlaintextFile(filename, asParagraph);
1475 FileDialog dlg(_("Select file to insert"), (asParagraph ?
1476 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1478 FileDialog::Result result = dlg.open(from_utf8(bv->buffer().filePath()),
1479 FileFilterList(), docstring());
1481 if (result.first == FileDialog::Later)
1485 filename.set(to_utf8(result.second));
1487 // check selected filename
1488 if (filename.empty()) {
1489 // emit message signal.
1490 message(_("Canceled."));
1494 bv->insertPlaintextFile(filename, asParagraph);
1498 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1500 FileName fname = b.fileName();
1501 FileName const oldname = fname;
1503 if (!newname.empty()) {
1505 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1507 // Switch to this Buffer.
1510 /// No argument? Ask user through dialog.
1512 FileDialog dlg(_("Choose a filename to save document as"),
1513 LFUN_BUFFER_WRITE_AS);
1514 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
1515 dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
1517 if (!isLyXFilename(fname.absFilename()))
1518 fname.changeExtension(".lyx");
1520 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1522 FileDialog::Result result =
1523 dlg.save(from_utf8(fname.onlyPath().absFilename()),
1525 from_utf8(fname.onlyFileName()));
1527 if (result.first == FileDialog::Later)
1530 fname.set(to_utf8(result.second));
1535 if (!isLyXFilename(fname.absFilename()))
1536 fname.changeExtension(".lyx");
1539 if (FileName(fname).exists()) {
1540 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1541 docstring text = bformat(_("The document %1$s already "
1542 "exists.\n\nDo you want to "
1543 "overwrite that document?"),
1545 int const ret = Alert::prompt(_("Overwrite document?"),
1546 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1549 case 1: return renameBuffer(b, docstring());
1550 case 2: return false;
1554 // Ok, change the name of the buffer
1555 b.setFileName(fname.absFilename());
1557 bool unnamed = b.isUnnamed();
1558 b.setUnnamed(false);
1559 b.saveCheckSum(fname);
1561 if (!saveBuffer(b)) {
1562 b.setFileName(oldname.absFilename());
1563 b.setUnnamed(unnamed);
1564 b.saveCheckSum(oldname);
1572 bool GuiView::saveBuffer(Buffer & b)
1575 return renameBuffer(b, docstring());
1578 LyX::ref().session().lastFiles().add(b.fileName());
1582 // Switch to this Buffer.
1585 // FIXME: we don't tell the user *WHY* the save failed !!
1586 docstring const file = makeDisplayPath(b.absFileName(), 30);
1587 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1588 "Do you want to rename the document and "
1589 "try again?"), file);
1590 int const ret = Alert::prompt(_("Rename and save?"),
1591 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1594 if (!renameBuffer(b, docstring()))
1603 return saveBuffer(b);
1607 bool GuiView::closeBuffer()
1609 Buffer * buf = buffer();
1610 return buf && closeBuffer(*buf);
1614 bool GuiView::closeBuffer(Buffer & buf)
1616 if (buf.isClean() || buf.paragraphs().empty()) {
1617 theBufferList().release(&buf);
1620 // Switch to this Buffer.
1625 if (buf.isUnnamed())
1626 file = from_utf8(buf.fileName().onlyFileName());
1628 file = buf.fileName().displayName(30);
1630 docstring const text = bformat(_("The document %1$s has unsaved changes."
1631 "\n\nDo you want to save the document or discard the changes?"), file);
1632 int const ret = Alert::prompt(_("Save changed document?"),
1633 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1637 if (!saveBuffer(buf))
1641 // if we crash after this we could
1642 // have no autosave file but I guess
1643 // this is really improbable (Jug)
1644 removeAutosaveFile(buf.absFileName());
1650 // save file names to .lyx/session
1651 // if master/slave are both open, do not save slave since it
1652 // will be automatically loaded when the master is loaded
1653 if (buf.masterBuffer() == &buf)
1654 LyX::ref().session().lastOpened().add(buf.fileName());
1656 theBufferList().release(&buf);
1661 bool GuiView::quitWriteAll()
1663 while (!theBufferList().empty()) {
1664 Buffer * b = theBufferList().first();
1665 if (!closeBuffer(*b))
1672 bool GuiView::dispatch(FuncRequest const & cmd)
1674 BufferView * bv = view();
1675 // By default we won't need any update.
1677 bv->cursor().updateFlags(Update::None);
1679 switch(cmd.action) {
1680 case LFUN_FILE_OPEN:
1681 openDocument(to_utf8(cmd.argument()));
1684 case LFUN_BUFFER_IMPORT:
1685 importDocument(to_utf8(cmd.argument()));
1688 case LFUN_BUFFER_SWITCH:
1689 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1692 case LFUN_BUFFER_NEXT:
1693 setBuffer(theBufferList().next(buffer()));
1696 case LFUN_BUFFER_PREVIOUS:
1697 setBuffer(theBufferList().previous(buffer()));
1700 case LFUN_COMMAND_EXECUTE: {
1701 bool const show_it = cmd.argument() != "off";
1702 d.toolbars_->showCommandBuffer(show_it);
1705 case LFUN_DROP_LAYOUTS_CHOICE:
1707 d.layout_->showPopup();
1710 case LFUN_MENU_OPEN:
1711 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument())))
1712 menu->exec(QCursor::pos());
1715 case LFUN_FILE_INSERT:
1716 insertLyXFile(cmd.argument());
1718 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1719 insertPlaintextFile(cmd.argument(), true);
1722 case LFUN_FILE_INSERT_PLAINTEXT:
1723 insertPlaintextFile(cmd.argument(), false);
1726 case LFUN_BUFFER_WRITE:
1728 saveBuffer(bv->buffer());
1731 case LFUN_BUFFER_WRITE_AS:
1733 renameBuffer(bv->buffer(), cmd.argument());
1736 case LFUN_BUFFER_WRITE_ALL: {
1737 Buffer * first = theBufferList().first();
1740 message(_("Saving all documents..."));
1741 // We cannot use a for loop as the buffer list cycles.
1747 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1748 b = theBufferList().next(b);
1749 } while (b != first);
1750 message(_("All documents saved."));
1754 case LFUN_TOOLBAR_TOGGLE: {
1755 string const name = cmd.getArg(0);
1756 bool const allowauto = cmd.getArg(1) == "allowauto";
1757 // it is possible to get current toolbar status like this,...
1758 // but I decide to obey the order of ToolbarBackend::flags
1759 // and disregard real toolbar status.
1760 // toolbars_->saveToolbarInfo();
1762 // toggle state on/off/auto
1763 d.toolbars_->toggleToolbarState(name, allowauto);
1767 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1769 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1773 if (tbi->flags & ToolbarInfo::ON)
1775 else if (tbi->flags & ToolbarInfo::OFF)
1777 else if (tbi->flags & ToolbarInfo::AUTO)
1780 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1781 _(tbi->gui_name), state));
1785 case LFUN_DIALOG_UPDATE: {
1786 string const name = to_utf8(cmd.argument());
1787 // Can only update a dialog connected to an existing inset
1788 Inset * inset = getOpenInset(name);
1790 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1791 inset->dispatch(view()->cursor(), fr);
1792 } else if (name == "paragraph") {
1793 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1794 } else if (name == "prefs") {
1795 updateDialog(name, string());
1800 case LFUN_DIALOG_TOGGLE: {
1801 if (isDialogVisible(cmd.getArg(0)))
1802 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1804 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1808 case LFUN_DIALOG_DISCONNECT_INSET:
1809 disconnectDialog(to_utf8(cmd.argument()));
1812 case LFUN_DIALOG_HIDE: {
1815 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1819 case LFUN_DIALOG_SHOW: {
1820 string const name = cmd.getArg(0);
1821 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1823 if (name == "character") {
1824 data = freefont2string();
1826 showDialog("character", data);
1827 } else if (name == "latexlog") {
1828 Buffer::LogType type;
1829 string const logfile = buffer()->logName(&type);
1831 case Buffer::latexlog:
1834 case Buffer::buildlog:
1838 data += Lexer::quoteString(logfile);
1839 showDialog("log", data);
1840 } else if (name == "vclog") {
1841 string const data = "vc " +
1842 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1843 showDialog("log", data);
1844 } else if (name == "symbols") {
1845 data = bv->cursor().getEncoding()->name();
1847 showDialog("symbols", data);
1849 showDialog(name, data);
1853 case LFUN_INSET_APPLY: {
1854 string const name = cmd.getArg(0);
1855 Inset * inset = getOpenInset(name);
1857 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1858 inset->dispatch(view()->cursor(), fr);
1860 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1866 case LFUN_UI_TOGGLE:
1868 // Make sure the keyboard focus stays in the work area.
1872 case LFUN_COMPLETION_INLINE:
1873 if (d.current_work_area_)
1874 d.current_work_area_->completer().showInline();
1877 case LFUN_SPLIT_VIEW:
1878 if (Buffer * buf = buffer()) {
1879 string const orientation = cmd.getArg(0);
1880 d.splitter_->setOrientation(orientation == "vertical"
1881 ? Qt::Vertical : Qt::Horizontal);
1882 TabWorkArea * twa = addTabWorkArea();
1883 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1884 setCurrentWorkArea(wa);
1888 case LFUN_CLOSE_TAB_GROUP:
1889 if (TabWorkArea * twa = d.currentTabWorkArea()) {
1891 twa = d.currentTabWorkArea();
1892 // Switch to the next GuiWorkArea in the found TabWorkArea.
1893 d.current_work_area_ = twa? twa->currentWorkArea() : 0;
1894 if (d.splitter_->count() == 0)
1895 // No more work area, switch to the background widget.
1900 case LFUN_COMPLETION_POPUP:
1901 if (d.current_work_area_)
1902 d.current_work_area_->completer().showPopup();
1906 case LFUN_COMPLETION_COMPLETE:
1907 if (d.current_work_area_)
1908 d.current_work_area_->completer().tab();
1919 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1921 string const arg = cmd.getArg(0);
1922 if (arg == "scrollbar") {
1923 // hide() is of no help
1924 if (d.current_work_area_->verticalScrollBarPolicy() ==
1925 Qt::ScrollBarAlwaysOff)
1927 d.current_work_area_->setVerticalScrollBarPolicy(
1928 Qt::ScrollBarAsNeeded);
1930 d.current_work_area_->setVerticalScrollBarPolicy(
1931 Qt::ScrollBarAlwaysOff);
1934 if (arg == "statusbar") {
1935 statusBar()->setVisible(!statusBar()->isVisible());
1938 if (arg == "menubar") {
1939 menuBar()->setVisible(!menuBar()->isVisible());
1942 #if QT_VERSION >= 0x040300
1943 if (arg == "frame") {
1945 getContentsMargins(&l, &t, &r, &b);
1946 //are the frames in default state?
1948 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1949 setContentsMargins(-2, -2, -2, -2);
1951 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1952 setContentsMargins(0, 0, 0, 0);
1957 if (arg != "fullscreen") {
1958 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1962 if (lyxrc.full_screen_toolbars)
1963 d.toolbars_->toggleFullScreen(!isFullScreen());
1965 if (isFullScreen()) {
1966 for (int i = 0; i != d.splitter_->count(); ++i)
1967 d.tabWorkArea(i)->setFullScreen(false);
1968 #if QT_VERSION >= 0x040300
1969 setContentsMargins(0, 0, 0, 0);
1973 statusBar()->show();
1975 for (int i = 0; i != d.splitter_->count(); ++i)
1976 d.tabWorkArea(i)->setFullScreen(true);
1977 #if QT_VERSION >= 0x040300
1978 setContentsMargins(-2, -2, -2, -2);
1981 statusBar()->hide();
1987 Buffer const * GuiView::updateInset(Inset const * inset)
1989 if (!d.current_work_area_)
1993 d.current_work_area_->scheduleRedraw();
1995 return &d.current_work_area_->bufferView().buffer();
1999 void GuiView::restartCursor()
2001 /* When we move around, or type, it's nice to be able to see
2002 * the cursor immediately after the keypress.
2004 if (d.current_work_area_)
2005 d.current_work_area_->startBlinkingCursor();
2007 // Take this occasion to update the toobars and layout list.
2013 void GuiView::updateCompletion(bool start, bool keep)
2015 if (d.current_work_area_)
2016 d.current_work_area_->completer().updateVisibility(start, keep);
2021 // This list should be kept in sync with the list of insets in
2022 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
2023 // dialog should have the same name as the inset.
2025 char const * const dialognames[] = {
2026 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
2027 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
2028 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
2029 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
2030 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
2032 #ifdef HAVE_LIBAIKSAURUS
2036 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
2038 char const * const * const end_dialognames =
2039 dialognames + (sizeof(dialognames) / sizeof(char *));
2043 cmpCStr(char const * name) : name_(name) {}
2044 bool operator()(char const * other) {
2045 return strcmp(other, name_) == 0;
2052 bool isValidName(string const & name)
2054 return find_if(dialognames, end_dialognames,
2055 cmpCStr(name.c_str())) != end_dialognames;
2061 void GuiView::resetDialogs()
2063 // Make sure that no LFUN uses any LyXView.
2064 theLyXFunc().setLyXView(0);
2065 // FIXME: the "math panels" toolbar takes an awful lot of time to
2066 // initialise so we don't do that for the time being.
2067 //d.toolbars_->init();
2068 guiApp->menus().fillMenuBar(this);
2070 d.layout_->updateContents(true);
2071 // Now update controls with current buffer.
2072 theLyXFunc().setLyXView(this);
2077 Dialog * GuiView::find_or_build(string const & name)
2079 if (!isValidName(name))
2082 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2084 if (it != d.dialogs_.end())
2085 return it->second.get();
2087 Dialog * dialog = build(name);
2088 d.dialogs_[name].reset(dialog);
2089 if (lyxrc.allow_geometry_session)
2090 dialog->restoreSession();
2095 void GuiView::showDialog(string const & name, string const & data,
2102 Dialog * dialog = find_or_build(name);
2104 dialog->showData(data);
2106 d.open_insets_[name] = inset;
2112 bool GuiView::isDialogVisible(string const & name) const
2114 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2115 if (it == d.dialogs_.end())
2117 return it->second.get()->isVisibleView();
2121 void GuiView::hideDialog(string const & name, Inset * inset)
2123 // Don't send the signal if we are quitting, because on MSVC it is
2124 // destructed before the cut stack in CutAndPaste.cpp, and this method
2125 // is called from some inset destructor if the cut stack is not empty
2130 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2131 if (it == d.dialogs_.end())
2134 if (inset && inset != getOpenInset(name))
2137 Dialog * const dialog = it->second.get();
2138 if (dialog->isVisibleView())
2140 d.open_insets_[name] = 0;
2144 void GuiView::disconnectDialog(string const & name)
2146 if (!isValidName(name))
2149 if (d.open_insets_.find(name) != d.open_insets_.end())
2150 d.open_insets_[name] = 0;
2154 Inset * GuiView::getOpenInset(string const & name) const
2156 if (!isValidName(name))
2159 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2160 return it == d.open_insets_.end() ? 0 : it->second;
2164 void GuiView::hideAll() const
2166 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2167 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2169 for(; it != end; ++it)
2170 it->second->hideView();
2174 void GuiView::hideBufferDependent() const
2176 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2177 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2179 for(; it != end; ++it) {
2180 Dialog * dialog = it->second.get();
2181 if (dialog->isBufferDependent())
2187 void GuiView::updateBufferDependent(bool switched) const
2189 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2190 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2192 for(; it != end; ++it) {
2193 Dialog * dialog = it->second.get();
2194 if (!dialog->isVisibleView())
2196 if (switched && dialog->isBufferDependent()) {
2197 if (dialog->initialiseParams(""))
2198 dialog->updateView();
2202 // A bit clunky, but the dialog will request
2203 // that the kernel provides it with the necessary
2205 dialog->updateDialog();
2211 void GuiView::checkStatus()
2213 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2214 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2216 for(; it != end; ++it) {
2217 Dialog * const dialog = it->second.get();
2218 if (dialog && dialog->isVisibleView())
2219 dialog->checkStatus();
2225 // will be replaced by a proper factory...
2226 Dialog * createGuiAbout(GuiView & lv);
2227 Dialog * createGuiBibitem(GuiView & lv);
2228 Dialog * createGuiBibtex(GuiView & lv);
2229 Dialog * createGuiBox(GuiView & lv);
2230 Dialog * createGuiBranch(GuiView & lv);
2231 Dialog * createGuiChanges(GuiView & lv);
2232 Dialog * createGuiCharacter(GuiView & lv);
2233 Dialog * createGuiCitation(GuiView & lv);
2234 Dialog * createGuiDelimiter(GuiView & lv);
2235 Dialog * createGuiDocument(GuiView & lv);
2236 Dialog * createGuiErrorList(GuiView & lv);
2237 Dialog * createGuiERT(GuiView & lv);
2238 Dialog * createGuiExternal(GuiView & lv);
2239 Dialog * createGuiFloat(GuiView & lv);
2240 Dialog * createGuiGraphics(GuiView & lv);
2241 Dialog * createGuiInclude(GuiView & lv);
2242 Dialog * createGuiLabel(GuiView & lv);
2243 Dialog * createGuiListings(GuiView & lv);
2244 Dialog * createGuiLog(GuiView & lv);
2245 Dialog * createGuiMathMatrix(GuiView & lv);
2246 Dialog * createGuiNomenclature(GuiView & lv);
2247 Dialog * createGuiNote(GuiView & lv);
2248 Dialog * createGuiParagraph(GuiView & lv);
2249 Dialog * createGuiPreferences(GuiView & lv);
2250 Dialog * createGuiPrint(GuiView & lv);
2251 Dialog * createGuiRef(GuiView & lv);
2252 Dialog * createGuiSearch(GuiView & lv);
2253 Dialog * createGuiSendTo(GuiView & lv);
2254 Dialog * createGuiShowFile(GuiView & lv);
2255 Dialog * createGuiSpellchecker(GuiView & lv);
2256 Dialog * createGuiSymbols(GuiView & lv);
2257 Dialog * createGuiTabularCreate(GuiView & lv);
2258 Dialog * createGuiTabular(GuiView & lv);
2259 Dialog * createGuiTexInfo(GuiView & lv);
2260 Dialog * createGuiToc(GuiView & lv);
2261 Dialog * createGuiThesaurus(GuiView & lv);
2262 Dialog * createGuiHyperlink(GuiView & lv);
2263 Dialog * createGuiVSpace(GuiView & lv);
2264 Dialog * createGuiViewSource(GuiView & lv);
2265 Dialog * createGuiWrap(GuiView & lv);
2268 Dialog * GuiView::build(string const & name)
2270 BOOST_ASSERT(isValidName(name));
2272 if (name == "aboutlyx")
2273 return createGuiAbout(*this);
2274 if (name == "bibitem")
2275 return createGuiBibitem(*this);
2276 if (name == "bibtex")
2277 return createGuiBibtex(*this);
2279 return createGuiBox(*this);
2280 if (name == "branch")
2281 return createGuiBranch(*this);
2282 if (name == "changes")
2283 return createGuiChanges(*this);
2284 if (name == "character")
2285 return createGuiCharacter(*this);
2286 if (name == "citation")
2287 return createGuiCitation(*this);
2288 if (name == "document")
2289 return createGuiDocument(*this);
2290 if (name == "errorlist")
2291 return createGuiErrorList(*this);
2293 return createGuiERT(*this);
2294 if (name == "external")
2295 return createGuiExternal(*this);
2297 return createGuiShowFile(*this);
2298 if (name == "findreplace")
2299 return createGuiSearch(*this);
2300 if (name == "float")
2301 return createGuiFloat(*this);
2302 if (name == "graphics")
2303 return createGuiGraphics(*this);
2304 if (name == "include")
2305 return createGuiInclude(*this);
2306 if (name == "nomenclature")
2307 return createGuiNomenclature(*this);
2308 if (name == "label")
2309 return createGuiLabel(*this);
2311 return createGuiLog(*this);
2312 if (name == "view-source")
2313 return createGuiViewSource(*this);
2314 if (name == "mathdelimiter")
2315 return createGuiDelimiter(*this);
2316 if (name == "mathmatrix")
2317 return createGuiMathMatrix(*this);
2319 return createGuiNote(*this);
2320 if (name == "paragraph")
2321 return createGuiParagraph(*this);
2322 if (name == "prefs")
2323 return createGuiPreferences(*this);
2324 if (name == "print")
2325 return createGuiPrint(*this);
2327 return createGuiRef(*this);
2328 if (name == "sendto")
2329 return createGuiSendTo(*this);
2330 if (name == "spellchecker")
2331 return createGuiSpellchecker(*this);
2332 if (name == "symbols")
2333 return createGuiSymbols(*this);
2334 if (name == "tabular")
2335 return createGuiTabular(*this);
2336 if (name == "tabularcreate")
2337 return createGuiTabularCreate(*this);
2338 if (name == "texinfo")
2339 return createGuiTexInfo(*this);
2340 #ifdef HAVE_LIBAIKSAURUS
2341 if (name == "thesaurus")
2342 return createGuiThesaurus(*this);
2345 return createGuiToc(*this);
2347 return createGuiHyperlink(*this);
2348 if (name == "vspace")
2349 return createGuiVSpace(*this);
2351 return createGuiWrap(*this);
2352 if (name == "listings")
2353 return createGuiListings(*this);
2359 } // namespace frontend
2362 #include "GuiView_moc.cpp"