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 "FuncStatus.h"
41 #include "FuncRequest.h"
42 #include "support/gettext.h"
50 #include "Paragraph.h"
51 #include "TextClass.h"
53 #include "ToolbarBackend.h"
56 #include "support/debug.h"
57 #include "support/FileFilterList.h"
58 #include "support/FileName.h"
59 #include "support/filetools.h"
60 #include "support/ForkedCalls.h"
61 #include "support/lstrings.h"
62 #include "support/os.h"
63 #include "support/Package.h"
64 #include "support/Timeout.h"
67 #include <QApplication>
68 #include <QCloseEvent>
70 #include <QDesktopWidget>
71 #include <QDragEnterEvent>
79 #include <QPushButton>
83 #include <QStackedWidget>
90 #include <boost/assert.hpp>
91 #include <boost/bind.hpp>
93 #ifdef HAVE_SYS_TIME_H
94 # include <sys/time.h>
101 using namespace lyx::support;
108 class BackgroundWidget : public QWidget
113 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
114 /// The text to be written on top of the pixmap
115 QString const text = lyx_version ? lyx_version : qt_("unknown version");
116 splash_ = QPixmap(":/images/banner.png");
118 QPainter pain(&splash_);
119 pain.setPen(QColor(255, 255, 0));
121 // The font used to display the version info
122 font.setStyleHint(QFont::SansSerif);
123 font.setWeight(QFont::Bold);
124 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
126 pain.drawText(260, 270, text);
129 void paintEvent(QPaintEvent *)
131 int x = (width() - splash_.width()) / 2;
132 int y = (height() - splash_.height()) / 2;
134 pain.drawPixmap(x, y, splash_);
144 typedef boost::shared_ptr<Dialog> DialogPtr;
146 struct GuiView::GuiViewPrivate
149 : current_work_area_(0), layout_(0), autosave_timeout_(5000),
152 // hardcode here the platform specific icon size
153 smallIconSize = 14; // scaling problems
154 normalIconSize = 20; // ok, default
155 bigIconSize = 26; // better for some math icons
157 splitter_ = new QSplitter;
158 bg_widget_ = new BackgroundWidget;
159 stack_widget_ = new QStackedWidget;
160 stack_widget_->addWidget(bg_widget_);
161 stack_widget_->addWidget(splitter_);
169 delete stack_widget_;
173 QMenu * toolBarPopup(GuiView * parent)
175 // FIXME: translation
176 QMenu * menu = new QMenu(parent);
177 QActionGroup * iconSizeGroup = new QActionGroup(parent);
179 QAction * smallIcons = new QAction(iconSizeGroup);
180 smallIcons->setText(qt_("Small-sized icons"));
181 smallIcons->setCheckable(true);
182 QObject::connect(smallIcons, SIGNAL(triggered()),
183 parent, SLOT(smallSizedIcons()));
184 menu->addAction(smallIcons);
186 QAction * normalIcons = new QAction(iconSizeGroup);
187 normalIcons->setText(qt_("Normal-sized icons"));
188 normalIcons->setCheckable(true);
189 QObject::connect(normalIcons, SIGNAL(triggered()),
190 parent, SLOT(normalSizedIcons()));
191 menu->addAction(normalIcons);
193 QAction * bigIcons = new QAction(iconSizeGroup);
194 bigIcons->setText(qt_("Big-sized icons"));
195 bigIcons->setCheckable(true);
196 QObject::connect(bigIcons, SIGNAL(triggered()),
197 parent, SLOT(bigSizedIcons()));
198 menu->addAction(bigIcons);
200 unsigned int cur = parent->iconSize().width();
201 if ( cur == parent->d.smallIconSize)
202 smallIcons->setChecked(true);
203 else if (cur == parent->d.normalIconSize)
204 normalIcons->setChecked(true);
205 else if (cur == parent->d.bigIconSize)
206 bigIcons->setChecked(true);
213 stack_widget_->setCurrentWidget(bg_widget_);
214 bg_widget_->setUpdatesEnabled(true);
217 TabWorkArea * tabWorkArea(int i)
219 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
222 TabWorkArea * currentTabWorkArea()
224 if (splitter_->count() == 1)
225 // The first TabWorkArea is always the first one, if any.
226 return tabWorkArea(0);
228 for (int i = 0; i != splitter_->count(); ++i) {
229 TabWorkArea * twa = tabWorkArea(i);
230 if (current_work_area_ == twa->currentWorkArea())
234 // None has the focus so we just take the first one.
235 return tabWorkArea(0);
239 GuiWorkArea * current_work_area_;
240 QSplitter * splitter_;
241 QStackedWidget * stack_widget_;
242 BackgroundWidget * bg_widget_;
244 GuiToolbars * toolbars_;
245 /// The main layout box.
247 * \warning Don't Delete! The layout box is actually owned by
248 * whichever toolbar contains it. All the GuiView class needs is a
249 * means of accessing it.
251 * FIXME: replace that with a proper model so that we are not limited
252 * to only one dialog.
254 GuiLayoutBox * layout_;
257 map<string, Inset *> open_insets_;
260 map<string, DialogPtr> dialogs_;
262 unsigned int smallIconSize;
263 unsigned int normalIconSize;
264 unsigned int bigIconSize;
266 QTimer statusbar_timer_;
267 /// auto-saving of buffers
268 Timeout autosave_timeout_;
269 /// flag against a race condition due to multiclicks, see bug #1119
274 GuiView::GuiView(int id)
275 : d(*new GuiViewPrivate), id_(id)
277 // GuiToolbars *must* be initialised before the menu bar.
278 d.toolbars_ = new GuiToolbars(*this);
280 // Fill up the menu bar.
281 guiApp->menus().fillMenuBar(menuBar(), this);
283 setCentralWidget(d.stack_widget_);
285 // Start autosave timer
286 if (lyxrc.autosave) {
287 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
288 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
289 d.autosave_timeout_.start();
291 connect(&d.statusbar_timer_, SIGNAL(timeout()),
292 this, SLOT(clearMessage()));
294 // We don't want to keep the window in memory if it is closed.
295 setAttribute(Qt::WA_DeleteOnClose, true);
298 // assign an icon to main form. We do not do it under Qt/Mac,
299 // since the icon is provided in the application bundle.
300 setWindowIcon(QPixmap(":/images/lyx.png"));
304 setAcceptDrops(true);
306 statusBar()->setSizeGripEnabled(true);
308 // Forbid too small unresizable window because it can happen
309 // with some window manager under X11.
310 setMinimumSize(300, 200);
312 if (!lyxrc.allow_geometry_session)
313 // No session handling, default to a sane size.
314 setGeometry(50, 50, 690, 510);
316 // Now take care of session management.
318 QString const key = "view-" + QString::number(id_);
320 QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
321 QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
325 if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
326 setGeometry(50, 50, 690, 510);
328 setIconSize(settings.value(key + "/icon_size").toSize());
338 void GuiView::setFocus()
340 if (d.current_work_area_)
341 d.current_work_area_->setFocus();
347 QMenu * GuiView::createPopupMenu()
349 return d.toolBarPopup(this);
353 void GuiView::showEvent(QShowEvent * e)
355 LYXERR(Debug::GUI, "Passed Geometry "
356 << size().height() << "x" << size().width()
357 << "+" << pos().x() << "+" << pos().y());
359 if (d.splitter_->count() == 0)
360 // No work area, switch to the background widget.
363 QMainWindow::showEvent(e);
367 void GuiView::closeEvent(QCloseEvent * close_event)
369 // it can happen that this event arrives without selecting the view,
370 // e.g. when clicking the close button on a background window.
371 theLyXFunc().setLyXView(this);
373 while (Buffer * b = buffer()) {
375 // This is a child document, just close the tab after saving
376 // but keep the file loaded.
377 if (!saveBuffer(*b)) {
378 close_event->ignore();
381 removeWorkArea(d.current_work_area_);
385 std::vector<int> const & ids = guiApp->viewIds();
386 for (size_type i = 0; i != ids.size(); ++i) {
389 if (guiApp->view(ids[i]).workArea(*b)) {
390 // FIXME 1: should we put an alert box here that the buffer
391 // is viewed elsewhere?
392 // FIXME 2: should we try to save this buffer in any case?
395 // This buffer is also opened in another view, so
396 // but close the associated work area nevertheless.
397 removeWorkArea(d.current_work_area_);
398 // but don't close it.
403 if (b && !closeBuffer(*b)) {
404 close_event->ignore();
409 // Make sure that no LFUN use this close to be closed View.
410 theLyXFunc().setLyXView(0);
412 // Save toolbars configuration
413 if (isFullScreen()) {
414 d.toolbars_->toggleFullScreen(!isFullScreen());
418 // Make sure the timer time out will not trigger a statusbar update.
419 d.statusbar_timer_.stop();
421 // Saving fullscreen requires additional tweaks in the toolbar code.
422 // It wouldn't also work under linux natively.
423 if (lyxrc.allow_geometry_session && !isFullScreen()) {
425 QString const key = "view-" + QString::number(id_);
427 settings.setValue(key + "/pos", pos());
428 settings.setValue(key + "/size", size());
430 settings.setValue(key + "/geometry", saveGeometry());
432 settings.setValue(key + "/icon_size", iconSize());
433 d.toolbars_->saveToolbarInfo();
434 // Now take care of all other dialogs:
435 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
436 for (; it!= d.dialogs_.end(); ++it)
437 it->second->saveSession();
440 guiApp->unregisterView(id_);
441 close_event->accept();
445 void GuiView::dragEnterEvent(QDragEnterEvent * event)
447 if (event->mimeData()->hasUrls())
449 /// \todo Ask lyx-devel is this is enough:
450 /// if (event->mimeData()->hasFormat("text/plain"))
451 /// event->acceptProposedAction();
455 void GuiView::dropEvent(QDropEvent* event)
457 QList<QUrl> files = event->mimeData()->urls();
461 LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
462 for (int i = 0; i != files.size(); ++i) {
463 string const file = os::internal_path(fromqstr(
464 files.at(i).toLocalFile()));
466 lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
471 void GuiView::message(docstring const & str)
473 if (ForkedProcess::iAmAChild())
476 statusBar()->showMessage(toqstr(str));
477 d.statusbar_timer_.stop();
478 d.statusbar_timer_.start(3000);
482 void GuiView::smallSizedIcons()
484 setIconSize(QSize(d.smallIconSize, d.smallIconSize));
488 void GuiView::normalSizedIcons()
490 setIconSize(QSize(d.normalIconSize, d.normalIconSize));
494 void GuiView::bigSizedIcons()
496 setIconSize(QSize(d.bigIconSize, d.bigIconSize));
500 void GuiView::clearMessage()
504 theLyXFunc().setLyXView(this);
505 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
506 d.statusbar_timer_.stop();
510 void GuiView::updateWindowTitle(GuiWorkArea * wa)
512 if (wa != d.current_work_area_)
514 setWindowTitle(qt_("LyX: ") + wa->windowTitle());
515 setWindowIconText(wa->windowIconText());
519 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
522 disconnectBufferView();
523 connectBufferView(wa->bufferView());
524 connectBuffer(wa->bufferView().buffer());
525 d.current_work_area_ = wa;
526 QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
527 this, SLOT(updateWindowTitle(GuiWorkArea *)));
528 updateWindowTitle(wa);
531 // Buffer-dependent dialogs should be updated or
532 // hidden. This should go here because some dialogs (eg ToC)
533 // require bv_->text.
534 updateBufferDependent(true);
541 void GuiView::on_lastWorkAreaRemoved()
544 // On Mac close the view if there is no Tab open anymore,
545 // but only if no splitter is visible
546 if (!lyxrc.single_window && d.splitter_->count() == 1) {
547 TabWorkArea * twa = qobject_cast<TabWorkArea *>(d.splitter_->widget(0));
548 if (twa && twa->count() == 0) {
549 // close the view, as no tab is open anymore
550 QTimer::singleShot(0, this, SLOT(close()));
557 void GuiView::updateStatusBar()
559 // let the user see the explicit message
560 if (d.statusbar_timer_.isActive())
563 theLyXFunc().setLyXView(this);
564 statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
568 bool GuiView::hasFocus() const
570 return qApp->activeWindow() == this;
574 bool GuiView::event(QEvent * e)
578 // Useful debug code:
579 //case QEvent::ActivationChange:
580 //case QEvent::WindowDeactivate:
581 //case QEvent::Paint:
582 //case QEvent::Enter:
583 //case QEvent::Leave:
584 //case QEvent::HoverEnter:
585 //case QEvent::HoverLeave:
586 //case QEvent::HoverMove:
587 //case QEvent::StatusTip:
588 //case QEvent::DragEnter:
589 //case QEvent::DragLeave:
593 case QEvent::WindowActivate: {
594 if (this == guiApp->currentView()) {
596 return QMainWindow::event(e);
598 guiApp->setCurrentView(*this);
599 if (d.current_work_area_) {
600 BufferView & bv = d.current_work_area_->bufferView();
601 connectBufferView(bv);
602 connectBuffer(bv.buffer());
603 // The document structure, name and dialogs might have
604 // changed in another view.
605 updateBufferDependent(true);
610 setWindowTitle(qt_("LyX"));
611 setWindowIconText(qt_("LyX"));
614 return QMainWindow::event(e);
617 case QEvent::ShortcutOverride: {
618 if (d.current_work_area_)
619 // Nothing special to do.
620 return QMainWindow::event(e);
622 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
624 // Let Qt handle menu access and the Tab keys to navigate keys to navigate
626 if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab
627 || ke->key() == Qt::Key_Backtab)
628 return QMainWindow::event(e);
630 // Allow processing of shortcuts that are allowed even when no Buffer
632 theLyXFunc().setLyXView(this);
634 setKeySymbol(&sym, ke);
635 theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
641 return QMainWindow::event(e);
646 bool GuiView::focusNextPrevChild(bool /*next*/)
653 void GuiView::setBusy(bool busy)
655 if (d.current_work_area_) {
656 d.current_work_area_->setUpdatesEnabled(!busy);
658 d.current_work_area_->stopBlinkingCursor();
660 d.current_work_area_->startBlinkingCursor();
664 QApplication::setOverrideCursor(Qt::WaitCursor);
666 QApplication::restoreOverrideCursor();
670 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
672 GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
674 if (tbinfo.flags & ToolbarInfo::TOP) {
676 addToolBarBreak(Qt::TopToolBarArea);
677 addToolBar(Qt::TopToolBarArea, toolBar);
680 if (tbinfo.flags & ToolbarInfo::BOTTOM) {
681 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
682 #if (QT_VERSION >= 0x040202)
684 addToolBarBreak(Qt::BottomToolBarArea);
686 addToolBar(Qt::BottomToolBarArea, toolBar);
689 if (tbinfo.flags & ToolbarInfo::LEFT) {
690 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
691 #if (QT_VERSION >= 0x040202)
693 addToolBarBreak(Qt::LeftToolBarArea);
695 addToolBar(Qt::LeftToolBarArea, toolBar);
698 if (tbinfo.flags & ToolbarInfo::RIGHT) {
699 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
700 #if (QT_VERSION >= 0x040202)
702 addToolBarBreak(Qt::RightToolBarArea);
704 addToolBar(Qt::RightToolBarArea, toolBar);
707 // The following does not work so I cannot restore to exact toolbar location
709 ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
710 toolBar->move(tbinfo.posx, tbinfo.posy);
717 GuiWorkArea * GuiView::workArea(Buffer & buffer)
719 if (TabWorkArea * twa = d.currentTabWorkArea())
720 return twa->workArea(buffer);
725 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
727 // Automatically create a TabWorkArea if there are none yet.
728 TabWorkArea * tab_widget = d.splitter_->count()
729 ? d.currentTabWorkArea() : addTabWorkArea();
730 return tab_widget->addWorkArea(buffer, *this);
734 TabWorkArea * GuiView::addTabWorkArea()
736 TabWorkArea * twa = new TabWorkArea;
737 QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
738 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
739 QObject::connect(twa, SIGNAL(lastWorkAreaRemoved()),
740 this, SLOT(on_lastWorkAreaRemoved()));
742 d.splitter_->addWidget(twa);
743 d.stack_widget_->setCurrentWidget(d.splitter_);
748 GuiWorkArea const * GuiView::currentWorkArea() const
750 return d.current_work_area_;
754 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
758 // Changing work area can result from opening a file so
759 // update the toc in any case.
762 d.current_work_area_ = wa;
763 for (int i = 0; i != d.splitter_->count(); ++i) {
764 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
770 void GuiView::removeWorkArea(GuiWorkArea * wa)
773 if (wa == d.current_work_area_) {
775 disconnectBufferView();
776 hideBufferDependent();
777 d.current_work_area_ = 0;
780 for (int i = 0; i != d.splitter_->count(); ++i) {
781 TabWorkArea * twa = d.tabWorkArea(i);
782 if (!twa->removeWorkArea(wa))
783 // Not found in this tab group.
786 // We found and removed the GuiWorkArea.
788 // No more WorkAreas in this tab group, so delete it.
793 if (d.current_work_area_)
794 // This means that we are not closing the current GuiWorkArea;
797 // Switch to the next GuiWorkArea in the found TabWorkArea.
798 d.current_work_area_ = twa->currentWorkArea();
802 if (d.splitter_->count() == 0)
803 // No more work area, switch to the background widget.
808 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
814 void GuiView::updateLayoutList()
817 d.layout_->updateContents(false);
821 void GuiView::updateToolbars()
823 if (d.current_work_area_) {
825 d.current_work_area_->bufferView().cursor().inMathed();
827 lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
829 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
830 lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
831 bool const mathmacrotemplate =
832 lyx::getStatus(FuncRequest(LFUN_IN_MATHMACROTEMPLATE)).enabled();
834 d.toolbars_->update(math, table, review, mathmacrotemplate);
836 d.toolbars_->update(false, false, false, false);
838 // update read-only status of open dialogs.
843 Buffer * GuiView::buffer()
845 if (d.current_work_area_)
846 return &d.current_work_area_->bufferView().buffer();
851 Buffer const * GuiView::buffer() const
853 if (d.current_work_area_)
854 return &d.current_work_area_->bufferView().buffer();
859 void GuiView::setBuffer(Buffer * newBuffer)
861 BOOST_ASSERT(newBuffer);
864 GuiWorkArea * wa = workArea(*newBuffer);
866 updateLabels(*newBuffer->masterBuffer());
867 wa = addWorkArea(*newBuffer);
869 //Disconnect the old buffer...there's no new one.
872 connectBuffer(*newBuffer);
873 connectBufferView(wa->bufferView());
874 setCurrentWorkArea(wa);
880 void GuiView::connectBuffer(Buffer & buf)
882 buf.setGuiDelegate(this);
886 void GuiView::disconnectBuffer()
888 if (d.current_work_area_)
889 d.current_work_area_->bufferView().setGuiDelegate(0);
893 void GuiView::connectBufferView(BufferView & bv)
895 bv.setGuiDelegate(this);
899 void GuiView::disconnectBufferView()
901 if (d.current_work_area_)
902 d.current_work_area_->bufferView().setGuiDelegate(0);
906 void GuiView::errors(string const & error_type)
908 ErrorList & el = buffer()->errorList(error_type);
910 showDialog("errorlist", error_type);
914 void GuiView::updateDialog(string const & name, string const & data)
916 if (!isDialogVisible(name))
919 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
920 if (it == d.dialogs_.end())
923 Dialog * const dialog = it->second.get();
924 if (dialog->isVisibleView())
925 dialog->updateData(data);
929 BufferView * GuiView::view()
931 return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
935 void GuiView::updateToc()
937 updateDialog("toc", "");
941 void GuiView::updateEmbeddedFiles()
943 updateDialog("embedding", "");
947 void GuiView::autoSave()
949 LYXERR(Debug::INFO, "Running autoSave()");
952 view()->buffer().autoSave();
956 void GuiView::resetAutosaveTimers()
959 d.autosave_timeout_.restart();
963 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
967 Buffer * buf = buffer();
969 /* In LyX/Mac, when a dialog is open, the menus of the
970 application can still be accessed without giving focus to
971 the main window. In this case, we want to disable the menu
972 entries that are buffer-related.
974 Note that this code is not perfect, as bug 1941 attests:
975 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
977 if (cmd.origin == FuncRequest::MENU && !hasFocus())
981 case LFUN_BUFFER_WRITE:
982 enable = buf && (buf->isUnnamed() || !buf->isClean());
985 case LFUN_BUFFER_WRITE_AS:
989 case LFUN_SPLIT_VIEW:
993 case LFUN_CLOSE_TAB_GROUP:
994 enable = d.currentTabWorkArea();
997 case LFUN_TOOLBAR_TOGGLE:
998 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
1001 case LFUN_DIALOG_TOGGLE:
1002 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
1003 // fall through to set "enable"
1004 case LFUN_DIALOG_SHOW: {
1005 string const name = cmd.getArg(0);
1007 enable = name == "aboutlyx"
1008 || name == "file" //FIXME: should be removed.
1010 || name == "texinfo";
1011 else if (name == "print")
1012 enable = buf->isExportable("dvi")
1013 && lyxrc.print_command != "none";
1014 else if (name == "character") {
1018 InsetCode ic = view()->cursor().inset().lyxCode();
1019 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1022 else if (name == "symbols") {
1023 if (!view() || view()->cursor().inMathed())
1026 InsetCode ic = view()->cursor().inset().lyxCode();
1027 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
1030 else if (name == "latexlog")
1031 enable = FileName(buf->logName()).isReadableFile();
1032 else if (name == "spellchecker")
1033 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
1034 enable = !buf->isReadonly();
1038 else if (name == "vclog")
1039 enable = buf->lyxvc().inUse();
1043 case LFUN_DIALOG_UPDATE: {
1044 string const name = cmd.getArg(0);
1046 enable = name == "prefs";
1050 case LFUN_INSET_APPLY: {
1055 string const name = cmd.getArg(0);
1056 Inset * inset = getOpenInset(name);
1058 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1060 if (!inset->getStatus(view()->cursor(), fr, fs)) {
1061 // Every inset is supposed to handle this
1062 BOOST_ASSERT(false);
1066 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1067 flag |= getStatus(fr);
1069 enable = flag.enabled();
1073 case LFUN_COMPLETION_INLINE:
1074 if (!d.current_work_area_
1075 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1079 case LFUN_COMPLETION_POPUP:
1080 if (!d.current_work_area_
1081 || !d.current_work_area_->completer().popupPossible(view()->cursor()))
1085 case LFUN_COMPLETION_COMPLETE:
1086 if (!d.current_work_area_
1087 || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
1099 flag.enabled(false);
1105 static FileName selectTemplateFile()
1107 FileDialog dlg(qt_("Select template file"));
1108 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1109 dlg.setButton1(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1111 FileDialog::Result result =
1112 dlg.open(toqstr(lyxrc.template_path),
1113 FileFilterList(_("LyX Documents (*.lyx)")));
1115 if (result.first == FileDialog::Later)
1117 if (result.second.isEmpty())
1119 return FileName(fromqstr(result.second));
1123 Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
1127 Buffer * newBuffer = checkAndLoadLyXFile(filename);
1130 message(_("Document not loaded."));
1135 setBuffer(newBuffer);
1137 // scroll to the position when the file was last closed
1138 if (lyxrc.use_lastfilepos) {
1139 LastFilePosSection::FilePos filepos =
1140 LyX::ref().session().lastFilePos().load(filename);
1141 view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
1145 LyX::ref().session().lastFiles().add(filename);
1152 void GuiView::openDocument(string const & fname)
1154 string initpath = lyxrc.document_path;
1157 string const trypath = buffer()->filePath();
1158 // If directory is writeable, use this as default.
1159 if (FileName(trypath).isDirWritable())
1165 if (fname.empty()) {
1166 FileDialog dlg(qt_("Select document to open"), LFUN_FILE_OPEN);
1167 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1168 dlg.setButton2(qt_("Examples|#E#e"),
1169 toqstr(addPath(package().system_support().absFilename(), "examples")));
1171 FileDialog::Result result =
1172 dlg.open(toqstr(initpath), FileFilterList(_("LyX Documents (*.lyx)")));
1174 if (result.first == FileDialog::Later)
1177 filename = fromqstr(result.second);
1179 // check selected filename
1180 if (filename.empty()) {
1181 message(_("Canceled."));
1187 // get absolute path of file and add ".lyx" to the filename if
1189 FileName const fullname =
1190 fileSearch(string(), filename, "lyx", support::may_not_exist);
1191 if (!fullname.empty())
1192 filename = fullname.absFilename();
1194 // if the file doesn't exist, let the user create one
1195 if (!fullname.exists()) {
1196 // the user specifically chose this name. Believe him.
1197 Buffer * const b = newFile(filename, string(), true);
1203 docstring const disp_fn = makeDisplayPath(filename);
1204 message(bformat(_("Opening document %1$s..."), disp_fn));
1207 Buffer * buf = loadDocument(fullname);
1212 buf->errors("Parse");
1213 str2 = bformat(_("Document %1$s opened."), disp_fn);
1215 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1220 // FIXME: clean that
1221 static bool import(GuiView * lv, FileName const & filename,
1222 string const & format, ErrorList & errorList)
1224 FileName const lyxfile(support::changeExtension(filename.absFilename(), ".lyx"));
1226 string loader_format;
1227 vector<string> loaders = theConverters().loaders();
1228 if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
1229 for (vector<string>::const_iterator it = loaders.begin();
1230 it != loaders.end(); ++it) {
1231 if (!theConverters().isReachable(format, *it))
1234 string const tofile =
1235 support::changeExtension(filename.absFilename(),
1236 formats.extension(*it));
1237 if (!theConverters().convert(0, filename, FileName(tofile),
1238 filename, format, *it, errorList))
1240 loader_format = *it;
1243 if (loader_format.empty()) {
1244 frontend::Alert::error(_("Couldn't import file"),
1245 bformat(_("No information for importing the format %1$s."),
1246 formats.prettyName(format)));
1250 loader_format = format;
1252 if (loader_format == "lyx") {
1253 Buffer * buf = lv->loadDocument(lyxfile);
1258 buf->errors("Parse");
1260 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
1264 bool as_paragraphs = loader_format == "textparagraph";
1265 string filename2 = (loader_format == format) ? filename.absFilename()
1266 : support::changeExtension(filename.absFilename(),
1267 formats.extension(loader_format));
1268 lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
1269 theLyXFunc().setLyXView(lv);
1270 lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
1277 void GuiView::importDocument(string const & argument)
1280 string filename = split(argument, format, ' ');
1282 LYXERR(Debug::INFO, format << " file: " << filename);
1284 // need user interaction
1285 if (filename.empty()) {
1286 string initpath = lyxrc.document_path;
1288 Buffer const * buf = buffer();
1290 string const trypath = buf->filePath();
1291 // If directory is writeable, use this as default.
1292 if (FileName(trypath).isDirWritable())
1296 docstring const text = bformat(_("Select %1$s file to import"),
1297 formats.prettyName(format));
1299 FileDialog dlg(toqstr(text), LFUN_BUFFER_IMPORT);
1300 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1301 dlg.setButton2(qt_("Examples|#E#e"),
1302 toqstr(addPath(package().system_support().absFilename(), "examples")));
1304 docstring filter = formats.prettyName(format);
1307 filter += from_utf8(formats.extension(format));
1310 FileDialog::Result result =
1311 dlg.open(toqstr(initpath), FileFilterList(filter));
1313 if (result.first == FileDialog::Later)
1316 filename = fromqstr(result.second);
1318 // check selected filename
1319 if (filename.empty())
1320 message(_("Canceled."));
1323 if (filename.empty())
1326 // get absolute path of file
1327 FileName const fullname(makeAbsPath(filename));
1329 FileName const lyxfile(support::changeExtension(fullname.absFilename(), ".lyx"));
1331 // Check if the document already is open
1332 Buffer * buf = theBufferList().getBuffer(lyxfile.absFilename());
1335 if (!closeBuffer()) {
1336 message(_("Canceled."));
1341 docstring const displaypath = makeDisplayPath(lyxfile.absFilename(), 30);
1343 // if the file exists already, and we didn't do
1344 // -i lyx thefile.lyx, warn
1345 if (lyxfile.exists() && fullname != lyxfile) {
1347 docstring text = bformat(_("The document %1$s already exists.\n\n"
1348 "Do you want to overwrite that document?"), displaypath);
1349 int const ret = Alert::prompt(_("Overwrite document?"),
1350 text, 0, 1, _("&Overwrite"), _("&Cancel"));
1353 message(_("Canceled."));
1358 message(bformat(_("Importing %1$s..."), displaypath));
1359 ErrorList errorList;
1360 if (import(this, fullname, format, errorList))
1361 message(_("imported."));
1363 message(_("file not imported!"));
1365 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
1369 void GuiView::newDocument(string const & filename, bool from_template)
1371 FileName initpath(lyxrc.document_path);
1372 Buffer * buf = buffer();
1374 FileName const trypath(buf->filePath());
1375 // If directory is writeable, use this as default.
1376 if (trypath.isDirWritable())
1380 string templatefile = from_template ?
1381 selectTemplateFile().absFilename() : string();
1383 if (filename.empty())
1384 b = newUnnamedFile(templatefile, initpath);
1386 b = newFile(filename, templatefile, true);
1390 // Ensure the cursor is correctly positionned on screen.
1391 view()->showCursor();
1395 void GuiView::insertLyXFile(docstring const & fname)
1397 BufferView * bv = view();
1402 FileName filename(to_utf8(fname));
1404 if (!filename.empty()) {
1405 bv->insertLyXFile(filename);
1409 // Launch a file browser
1411 string initpath = lyxrc.document_path;
1412 string const trypath = bv->buffer().filePath();
1413 // If directory is writeable, use this as default.
1414 if (FileName(trypath).isDirWritable())
1418 FileDialog dlg(qt_("Select LyX document to insert"), LFUN_FILE_INSERT);
1419 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1420 dlg.setButton2(qt_("Examples|#E#e"),
1421 toqstr(addPath(package().system_support().absFilename(),
1424 FileDialog::Result result =
1425 dlg.open(toqstr(initpath),
1426 FileFilterList(_("LyX Documents (*.lyx)")));
1428 if (result.first == FileDialog::Later)
1432 filename.set(fromqstr(result.second));
1434 // check selected filename
1435 if (filename.empty()) {
1436 // emit message signal.
1437 message(_("Canceled."));
1441 bv->insertLyXFile(filename);
1445 void GuiView::insertPlaintextFile(docstring const & fname,
1448 BufferView * bv = view();
1453 FileName filename(to_utf8(fname));
1455 if (!filename.empty()) {
1456 bv->insertPlaintextFile(filename, asParagraph);
1460 FileDialog dlg(qt_("Select file to insert"), (asParagraph ?
1461 LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
1463 FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
1466 if (result.first == FileDialog::Later)
1470 filename.set(fromqstr(result.second));
1472 // check selected filename
1473 if (filename.empty()) {
1474 // emit message signal.
1475 message(_("Canceled."));
1479 bv->insertPlaintextFile(filename, asParagraph);
1483 bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
1485 FileName fname = b.fileName();
1486 FileName const oldname = fname;
1488 if (!newname.empty()) {
1490 fname = makeAbsPath(to_utf8(newname), oldname.onlyPath().absFilename());
1492 // Switch to this Buffer.
1495 /// No argument? Ask user through dialog.
1497 FileDialog dlg(qt_("Choose a filename to save document as"),
1498 LFUN_BUFFER_WRITE_AS);
1499 dlg.setButton1(qt_("Documents|#o#O"), toqstr(lyxrc.document_path));
1500 dlg.setButton2(qt_("Templates|#T#t"), toqstr(lyxrc.template_path));
1502 if (!isLyXFilename(fname.absFilename()))
1503 fname.changeExtension(".lyx");
1505 FileFilterList const filter(_("LyX Documents (*.lyx)"));
1507 FileDialog::Result result =
1508 dlg.save(toqstr(fname.onlyPath().absFilename()),
1510 toqstr(fname.onlyFileName()));
1512 if (result.first == FileDialog::Later)
1515 fname.set(fromqstr(result.second));
1520 if (!isLyXFilename(fname.absFilename()))
1521 fname.changeExtension(".lyx");
1524 if (FileName(fname).exists()) {
1525 docstring const file = makeDisplayPath(fname.absFilename(), 30);
1526 docstring text = bformat(_("The document %1$s already "
1527 "exists.\n\nDo you want to "
1528 "overwrite that document?"),
1530 int const ret = Alert::prompt(_("Overwrite document?"),
1531 text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel"));
1534 case 1: return renameBuffer(b, docstring());
1535 case 2: return false;
1539 // Ok, change the name of the buffer
1540 b.setFileName(fname.absFilename());
1542 bool unnamed = b.isUnnamed();
1543 b.setUnnamed(false);
1544 b.saveCheckSum(fname);
1546 if (!saveBuffer(b)) {
1547 b.setFileName(oldname.absFilename());
1548 b.setUnnamed(unnamed);
1549 b.saveCheckSum(oldname);
1557 bool GuiView::saveBuffer(Buffer & b)
1560 return renameBuffer(b, docstring());
1563 LyX::ref().session().lastFiles().add(b.fileName());
1567 // Switch to this Buffer.
1570 // FIXME: we don't tell the user *WHY* the save failed !!
1571 docstring const file = makeDisplayPath(b.absFileName(), 30);
1572 docstring text = bformat(_("The document %1$s could not be saved.\n\n"
1573 "Do you want to rename the document and "
1574 "try again?"), file);
1575 int const ret = Alert::prompt(_("Rename and save?"),
1576 text, 0, 2, _("&Rename"), _("&Retry"), _("&Cancel"));
1579 if (!renameBuffer(b, docstring()))
1588 return saveBuffer(b);
1592 bool GuiView::closeBuffer()
1594 Buffer * buf = buffer();
1595 return buf && closeBuffer(*buf);
1599 bool GuiView::closeBuffer(Buffer & buf)
1601 // goto bookmark to update bookmark pit.
1602 //FIXME: we should update only the bookmarks related to this buffer!
1603 for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
1604 theLyXFunc().gotoBookmark(i+1, false, false);
1606 if (buf.isClean() || buf.paragraphs().empty()) {
1607 if (buf.masterBuffer() == &buf)
1608 LyX::ref().session().lastOpened().add(buf.fileName());
1609 theBufferList().release(&buf);
1612 // Switch to this Buffer.
1617 if (buf.isUnnamed())
1618 file = from_utf8(buf.fileName().onlyFileName());
1620 file = buf.fileName().displayName(30);
1622 // Bring this window to top before asking questions.
1626 docstring const text = bformat(_("The document %1$s has unsaved changes."
1627 "\n\nDo you want to save the document or discard the changes?"), file);
1628 int const ret = Alert::prompt(_("Save changed document?"),
1629 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
1633 if (!saveBuffer(buf))
1637 // if we crash after this we could
1638 // have no autosave file but I guess
1639 // this is really improbable (Jug)
1640 removeAutosaveFile(buf.absFileName());
1646 // save file names to .lyx/session
1647 // if master/slave are both open, do not save slave since it
1648 // will be automatically loaded when the master is loaded
1649 if (buf.masterBuffer() == &buf)
1650 LyX::ref().session().lastOpened().add(buf.fileName());
1652 theBufferList().release(&buf);
1657 bool GuiView::dispatch(FuncRequest const & cmd)
1659 BufferView * bv = view();
1660 // By default we won't need any update.
1662 bv->cursor().updateFlags(Update::None);
1664 switch(cmd.action) {
1665 case LFUN_BUFFER_IMPORT:
1666 importDocument(to_utf8(cmd.argument()));
1669 case LFUN_BUFFER_SWITCH:
1670 setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1673 case LFUN_BUFFER_NEXT:
1674 setBuffer(theBufferList().next(buffer()));
1677 case LFUN_BUFFER_PREVIOUS:
1678 setBuffer(theBufferList().previous(buffer()));
1681 case LFUN_COMMAND_EXECUTE: {
1682 bool const show_it = cmd.argument() != "off";
1683 d.toolbars_->showCommandBuffer(show_it);
1686 case LFUN_DROP_LAYOUTS_CHOICE:
1688 d.layout_->showPopup();
1691 case LFUN_MENU_OPEN:
1692 if (QMenu * menu = guiApp->menus().menu(toqstr(cmd.argument()), *this))
1693 menu->exec(QCursor::pos());
1696 case LFUN_FILE_INSERT:
1697 insertLyXFile(cmd.argument());
1699 case LFUN_FILE_INSERT_PLAINTEXT_PARA:
1700 insertPlaintextFile(cmd.argument(), true);
1703 case LFUN_FILE_INSERT_PLAINTEXT:
1704 insertPlaintextFile(cmd.argument(), false);
1707 case LFUN_BUFFER_WRITE:
1709 saveBuffer(bv->buffer());
1712 case LFUN_BUFFER_WRITE_AS:
1714 renameBuffer(bv->buffer(), cmd.argument());
1717 case LFUN_BUFFER_WRITE_ALL: {
1718 Buffer * first = theBufferList().first();
1721 message(_("Saving all documents..."));
1722 // We cannot use a for loop as the buffer list cycles.
1728 LYXERR(Debug::ACTION, "Saved " << b->absFileName());
1729 b = theBufferList().next(b);
1730 } while (b != first);
1731 message(_("All documents saved."));
1735 case LFUN_TOOLBAR_TOGGLE: {
1736 string const name = cmd.getArg(0);
1737 bool const allowauto = cmd.getArg(1) == "allowauto";
1738 // it is possible to get current toolbar status like this,...
1739 // but I decide to obey the order of ToolbarBackend::flags
1740 // and disregard real toolbar status.
1741 // toolbars_->saveToolbarInfo();
1743 // toggle state on/off/auto
1744 d.toolbars_->toggleToolbarState(name, allowauto);
1748 ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1750 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1754 if (tbi->flags & ToolbarInfo::ON)
1756 else if (tbi->flags & ToolbarInfo::OFF)
1758 else if (tbi->flags & ToolbarInfo::AUTO)
1761 message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1762 _(tbi->gui_name), state));
1766 case LFUN_DIALOG_UPDATE: {
1767 string const name = to_utf8(cmd.argument());
1768 // Can only update a dialog connected to an existing inset
1769 Inset * inset = getOpenInset(name);
1771 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1772 inset->dispatch(view()->cursor(), fr);
1773 } else if (name == "paragraph") {
1774 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1775 } else if (name == "prefs") {
1776 updateDialog(name, string());
1781 case LFUN_DIALOG_TOGGLE: {
1782 if (isDialogVisible(cmd.getArg(0)))
1783 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1785 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1789 case LFUN_DIALOG_DISCONNECT_INSET:
1790 disconnectDialog(to_utf8(cmd.argument()));
1793 case LFUN_DIALOG_HIDE: {
1794 guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1798 case LFUN_DIALOG_SHOW: {
1799 string const name = cmd.getArg(0);
1800 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1802 if (name == "character") {
1803 data = freefont2string();
1805 showDialog("character", data);
1806 } else if (name == "latexlog") {
1807 Buffer::LogType type;
1808 string const logfile = buffer()->logName(&type);
1810 case Buffer::latexlog:
1813 case Buffer::buildlog:
1817 data += Lexer::quoteString(logfile);
1818 showDialog("log", data);
1819 } else if (name == "vclog") {
1820 string const data = "vc " +
1821 Lexer::quoteString(buffer()->lyxvc().getLogFile());
1822 showDialog("log", data);
1823 } else if (name == "symbols") {
1824 data = bv->cursor().getEncoding()->name();
1826 showDialog("symbols", data);
1828 showDialog(name, data);
1832 case LFUN_INSET_APPLY: {
1833 string const name = cmd.getArg(0);
1834 Inset * inset = getOpenInset(name);
1836 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1837 inset->dispatch(view()->cursor(), fr);
1839 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1845 case LFUN_UI_TOGGLE:
1847 // Make sure the keyboard focus stays in the work area.
1851 case LFUN_COMPLETION_INLINE:
1852 if (d.current_work_area_)
1853 d.current_work_area_->completer().showInline();
1856 case LFUN_SPLIT_VIEW:
1857 if (Buffer * buf = buffer()) {
1858 string const orientation = cmd.getArg(0);
1859 d.splitter_->setOrientation(orientation == "vertical"
1860 ? Qt::Vertical : Qt::Horizontal);
1861 TabWorkArea * twa = addTabWorkArea();
1862 GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
1863 setCurrentWorkArea(wa);
1867 case LFUN_CLOSE_TAB_GROUP:
1868 if (TabWorkArea * twa = d.currentTabWorkArea()) {
1870 twa = d.currentTabWorkArea();
1871 // Switch to the next GuiWorkArea in the found TabWorkArea.
1872 d.current_work_area_ = twa? twa->currentWorkArea() : 0;
1873 if (d.splitter_->count() == 0)
1874 // No more work area, switch to the background widget.
1879 case LFUN_COMPLETION_POPUP:
1880 if (d.current_work_area_)
1881 d.current_work_area_->completer().showPopup();
1885 case LFUN_COMPLETION_COMPLETE:
1886 if (d.current_work_area_)
1887 d.current_work_area_->completer().tab();
1898 void GuiView::lfunUiToggle(FuncRequest const & cmd)
1900 string const arg = cmd.getArg(0);
1901 if (arg == "scrollbar") {
1902 // hide() is of no help
1903 if (d.current_work_area_->verticalScrollBarPolicy() ==
1904 Qt::ScrollBarAlwaysOff)
1906 d.current_work_area_->setVerticalScrollBarPolicy(
1907 Qt::ScrollBarAsNeeded);
1909 d.current_work_area_->setVerticalScrollBarPolicy(
1910 Qt::ScrollBarAlwaysOff);
1913 if (arg == "statusbar") {
1914 statusBar()->setVisible(!statusBar()->isVisible());
1917 if (arg == "menubar") {
1918 menuBar()->setVisible(!menuBar()->isVisible());
1921 #if QT_VERSION >= 0x040300
1922 if (arg == "frame") {
1924 getContentsMargins(&l, &t, &r, &b);
1925 //are the frames in default state?
1926 d.current_work_area_->setFrameStyle(QFrame::NoFrame);
1928 setContentsMargins(-2, -2, -2, -2);
1930 setContentsMargins(0, 0, 0, 0);
1935 if (arg != "fullscreen") {
1936 message(bformat(_("LFUN_UI_TOGGLE %1$s unknown command!"), from_utf8(arg)));
1940 if (lyxrc.full_screen_toolbars)
1941 d.toolbars_->toggleFullScreen(!isFullScreen());
1943 if (isFullScreen()) {
1944 for (int i = 0; i != d.splitter_->count(); ++i)
1945 d.tabWorkArea(i)->setFullScreen(false);
1946 #if QT_VERSION >= 0x040300
1947 setContentsMargins(0, 0, 0, 0);
1951 statusBar()->show();
1953 for (int i = 0; i != d.splitter_->count(); ++i)
1954 d.tabWorkArea(i)->setFullScreen(true);
1955 #if QT_VERSION >= 0x040300
1956 setContentsMargins(-2, -2, -2, -2);
1959 statusBar()->hide();
1965 Buffer const * GuiView::updateInset(Inset const * inset)
1967 if (!d.current_work_area_)
1971 d.current_work_area_->scheduleRedraw();
1973 return &d.current_work_area_->bufferView().buffer();
1977 void GuiView::restartCursor()
1979 /* When we move around, or type, it's nice to be able to see
1980 * the cursor immediately after the keypress.
1982 if (d.current_work_area_)
1983 d.current_work_area_->startBlinkingCursor();
1985 // Take this occasion to update the other GUI elements.
1992 void GuiView::updateCompletion(Cursor & cur, bool start, bool keep)
1994 if (d.current_work_area_)
1995 d.current_work_area_->completer().updateVisibility(cur, start, keep);
2000 // This list should be kept in sync with the list of insets in
2001 // src/insets/Inset.cpp. I.e., if a dialog goes with an inset, the
2002 // dialog should have the same name as the inset.
2004 char const * const dialognames[] = {
2005 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
2006 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
2007 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
2008 "mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
2009 "ref", "sendto", "spellchecker", "symbols", "tabular", "tabularcreate",
2011 #ifdef HAVE_LIBAIKSAURUS
2015 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
2017 char const * const * const end_dialognames =
2018 dialognames + (sizeof(dialognames) / sizeof(char *));
2022 cmpCStr(char const * name) : name_(name) {}
2023 bool operator()(char const * other) {
2024 return strcmp(other, name_) == 0;
2031 bool isValidName(string const & name)
2033 return find_if(dialognames, end_dialognames,
2034 cmpCStr(name.c_str())) != end_dialognames;
2040 void GuiView::resetDialogs()
2042 // Make sure that no LFUN uses any LyXView.
2043 theLyXFunc().setLyXView(0);
2044 // FIXME: the "math panels" toolbar takes an awful lot of time to
2045 // initialise so we don't do that for the time being.
2046 //d.toolbars_->init();
2047 guiApp->menus().fillMenuBar(menuBar(), this);
2049 d.layout_->updateContents(true);
2050 // Now update controls with current buffer.
2051 theLyXFunc().setLyXView(this);
2056 Dialog * GuiView::find_or_build(string const & name)
2058 if (!isValidName(name))
2061 map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
2063 if (it != d.dialogs_.end())
2064 return it->second.get();
2066 Dialog * dialog = build(name);
2067 d.dialogs_[name].reset(dialog);
2068 if (lyxrc.allow_geometry_session)
2069 dialog->restoreSession();
2074 void GuiView::showDialog(string const & name, string const & data,
2081 Dialog * dialog = find_or_build(name);
2083 dialog->showData(data);
2085 d.open_insets_[name] = inset;
2091 bool GuiView::isDialogVisible(string const & name) const
2093 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2094 if (it == d.dialogs_.end())
2096 return it->second.get()->isVisibleView();
2100 void GuiView::hideDialog(string const & name, Inset * inset)
2102 map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
2103 if (it == d.dialogs_.end())
2106 if (inset && inset != getOpenInset(name))
2109 Dialog * const dialog = it->second.get();
2110 if (dialog->isVisibleView())
2112 d.open_insets_[name] = 0;
2116 void GuiView::disconnectDialog(string const & name)
2118 if (!isValidName(name))
2121 if (d.open_insets_.find(name) != d.open_insets_.end())
2122 d.open_insets_[name] = 0;
2126 Inset * GuiView::getOpenInset(string const & name) const
2128 if (!isValidName(name))
2131 map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
2132 return it == d.open_insets_.end() ? 0 : it->second;
2136 void GuiView::hideAll() const
2138 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2139 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2141 for(; it != end; ++it)
2142 it->second->hideView();
2146 void GuiView::hideBufferDependent() const
2148 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2149 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2151 for(; it != end; ++it) {
2152 Dialog * dialog = it->second.get();
2153 if (dialog->isBufferDependent())
2159 void GuiView::updateBufferDependent(bool switched) const
2161 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2162 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2164 for(; it != end; ++it) {
2165 Dialog * dialog = it->second.get();
2166 if (!dialog->isVisibleView())
2168 if (switched && dialog->isBufferDependent()) {
2169 if (dialog->initialiseParams(""))
2170 dialog->updateView();
2174 // A bit clunky, but the dialog will request
2175 // that the kernel provides it with the necessary
2177 dialog->updateDialog();
2183 void GuiView::checkStatus()
2185 map<string, DialogPtr>::const_iterator it = d.dialogs_.begin();
2186 map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
2188 for(; it != end; ++it) {
2189 Dialog * const dialog = it->second.get();
2190 if (dialog && dialog->isVisibleView())
2191 dialog->checkStatus();
2197 // will be replaced by a proper factory...
2198 Dialog * createGuiAbout(GuiView & lv);
2199 Dialog * createGuiBibitem(GuiView & lv);
2200 Dialog * createGuiBibtex(GuiView & lv);
2201 Dialog * createGuiBox(GuiView & lv);
2202 Dialog * createGuiBranch(GuiView & lv);
2203 Dialog * createGuiChanges(GuiView & lv);
2204 Dialog * createGuiCharacter(GuiView & lv);
2205 Dialog * createGuiCitation(GuiView & lv);
2206 Dialog * createGuiDelimiter(GuiView & lv);
2207 Dialog * createGuiDocument(GuiView & lv);
2208 Dialog * createGuiErrorList(GuiView & lv);
2209 Dialog * createGuiERT(GuiView & lv);
2210 Dialog * createGuiExternal(GuiView & lv);
2211 Dialog * createGuiFloat(GuiView & lv);
2212 Dialog * createGuiGraphics(GuiView & lv);
2213 Dialog * createGuiInclude(GuiView & lv);
2214 Dialog * createGuiLabel(GuiView & lv);
2215 Dialog * createGuiListings(GuiView & lv);
2216 Dialog * createGuiLog(GuiView & lv);
2217 Dialog * createGuiMathMatrix(GuiView & lv);
2218 Dialog * createGuiNomenclature(GuiView & lv);
2219 Dialog * createGuiNote(GuiView & lv);
2220 Dialog * createGuiParagraph(GuiView & lv);
2221 Dialog * createGuiPreferences(GuiView & lv);
2222 Dialog * createGuiPrint(GuiView & lv);
2223 Dialog * createGuiRef(GuiView & lv);
2224 Dialog * createGuiSearch(GuiView & lv);
2225 Dialog * createGuiSendTo(GuiView & lv);
2226 Dialog * createGuiShowFile(GuiView & lv);
2227 Dialog * createGuiSpellchecker(GuiView & lv);
2228 Dialog * createGuiSymbols(GuiView & lv);
2229 Dialog * createGuiTabularCreate(GuiView & lv);
2230 Dialog * createGuiTabular(GuiView & lv);
2231 Dialog * createGuiTexInfo(GuiView & lv);
2232 Dialog * createGuiToc(GuiView & lv);
2233 Dialog * createGuiThesaurus(GuiView & lv);
2234 Dialog * createGuiHyperlink(GuiView & lv);
2235 Dialog * createGuiVSpace(GuiView & lv);
2236 Dialog * createGuiViewSource(GuiView & lv);
2237 Dialog * createGuiWrap(GuiView & lv);
2240 Dialog * GuiView::build(string const & name)
2242 BOOST_ASSERT(isValidName(name));
2244 if (name == "aboutlyx")
2245 return createGuiAbout(*this);
2246 if (name == "bibitem")
2247 return createGuiBibitem(*this);
2248 if (name == "bibtex")
2249 return createGuiBibtex(*this);
2251 return createGuiBox(*this);
2252 if (name == "branch")
2253 return createGuiBranch(*this);
2254 if (name == "changes")
2255 return createGuiChanges(*this);
2256 if (name == "character")
2257 return createGuiCharacter(*this);
2258 if (name == "citation")
2259 return createGuiCitation(*this);
2260 if (name == "document")
2261 return createGuiDocument(*this);
2262 if (name == "errorlist")
2263 return createGuiErrorList(*this);
2265 return createGuiERT(*this);
2266 if (name == "external")
2267 return createGuiExternal(*this);
2269 return createGuiShowFile(*this);
2270 if (name == "findreplace")
2271 return createGuiSearch(*this);
2272 if (name == "float")
2273 return createGuiFloat(*this);
2274 if (name == "graphics")
2275 return createGuiGraphics(*this);
2276 if (name == "include")
2277 return createGuiInclude(*this);
2278 if (name == "nomenclature")
2279 return createGuiNomenclature(*this);
2280 if (name == "label")
2281 return createGuiLabel(*this);
2283 return createGuiLog(*this);
2284 if (name == "view-source")
2285 return createGuiViewSource(*this);
2286 if (name == "mathdelimiter")
2287 return createGuiDelimiter(*this);
2288 if (name == "mathmatrix")
2289 return createGuiMathMatrix(*this);
2291 return createGuiNote(*this);
2292 if (name == "paragraph")
2293 return createGuiParagraph(*this);
2294 if (name == "prefs")
2295 return createGuiPreferences(*this);
2296 if (name == "print")
2297 return createGuiPrint(*this);
2299 return createGuiRef(*this);
2300 if (name == "sendto")
2301 return createGuiSendTo(*this);
2302 if (name == "spellchecker")
2303 return createGuiSpellchecker(*this);
2304 if (name == "symbols")
2305 return createGuiSymbols(*this);
2306 if (name == "tabular")
2307 return createGuiTabular(*this);
2308 if (name == "tabularcreate")
2309 return createGuiTabularCreate(*this);
2310 if (name == "texinfo")
2311 return createGuiTexInfo(*this);
2312 #ifdef HAVE_LIBAIKSAURUS
2313 if (name == "thesaurus")
2314 return createGuiThesaurus(*this);
2317 return createGuiToc(*this);
2319 return createGuiHyperlink(*this);
2320 if (name == "vspace")
2321 return createGuiVSpace(*this);
2323 return createGuiWrap(*this);
2324 if (name == "listings")
2325 return createGuiListings(*this);
2331 } // namespace frontend
2334 #include "GuiView_moc.cpp"