#include "GuiApplication.h"
#include "GuiCommandBuffer.h"
#include "GuiCompleter.h"
-#include "GuiWorkArea.h"
#include "GuiKeySymbol.h"
#include "GuiToc.h"
#include "GuiToolbar.h"
+#include "GuiWorkArea.h"
#include "LayoutBox.h"
#include "Menus.h"
#include "TocModel.h"
#include "Intl.h"
#include "Layout.h"
#include "Lexer.h"
+#include "LyXAction.h"
#include "LyXFunc.h"
#include "LyX.h"
#include "LyXRC.h"
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/gettext.h"
+#include "support/filetools.h"
#include "support/ForkedCalls.h"
#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/os.h"
#include "support/Package.h"
+#include "support/Path.h"
+#include "support/Systemcall.h"
#include "support/Timeout.h"
+#include "support/ProgressInterface.h"
+#include "GuiProgress.h"
#include <QAction>
#include <QApplication>
#include <QSplitter>
#include <QStackedWidget>
#include <QStatusBar>
+#include <QTime>
#include <QTimer>
#include <QToolBar>
#include <QUrl>
#include <QScrollBar>
+#define EXPORT_in_THREAD 1
+
+
+// QtConcurrent was introduced in Qt 4.4
+#if (QT_VERSION >= 0x040400)
+#include <QFuture>
+#include <QFutureWatcher>
+#include <QtConcurrentRun>
+#endif
+
#include <boost/bind.hpp>
+#include <sstream>
+
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
/// Toolbar store providing access to individual toolbars by name.
-typedef std::map<std::string, GuiToolbar *> ToolbarMap;
+typedef map<string, GuiToolbar *> ToolbarMap;
typedef boost::shared_ptr<Dialog> DialogPtr;
struct GuiView::GuiViewPrivate
{
- GuiViewPrivate()
- : current_work_area_(0), current_main_work_area_(0),
+ GuiViewPrivate(GuiView * gv)
+ : gv_(gv), current_work_area_(0), current_main_work_area_(0),
layout_(0), autosave_timeout_(5000),
in_show_(false)
{
stack_widget_->addWidget(bg_widget_);
stack_widget_->addWidget(splitter_);
setBackground();
+ progress_ = new GuiProgress(gv);
}
~GuiViewPrivate()
delete splitter_;
delete bg_widget_;
delete stack_widget_;
+ delete progress_;
}
QMenu * toolBarPopup(GuiView * parent)
return tabWorkArea(0);
}
+#if (QT_VERSION >= 0x040400)
+ void setPreviewFuture(QFuture<docstring> const & f)
+ {
+ if (preview_watcher_.isRunning()) {
+ // we prefer to cancel this preview in order to keep a snappy
+ // interface.
+ return;
+ }
+ preview_watcher_.setFuture(f);
+ }
+#endif
+
public:
+ GuiView * gv_;
GuiWorkArea * current_work_area_;
GuiWorkArea * current_main_work_area_;
QSplitter * splitter_;
BackgroundWidget * bg_widget_;
/// view's toolbars
ToolbarMap toolbars_;
+ ProgressInterface* progress_;
/// The main layout box.
/**
* \warning Don't Delete! The layout box is actually owned by
*/
LayoutBox * layout_;
- ///
- map<string, Inset *> open_insets_;
-
///
map<string, DialogPtr> dialogs_;
///
TocModels toc_models_;
+
+#if (QT_VERSION >= 0x040400)
+ ///
+ QFutureWatcher<docstring> autosave_watcher_;
+ QFutureWatcher<docstring> preview_watcher_;
+#else
+ struct DummyWatcher { bool isRunning(){return false;} };
+ DummyWatcher preview_watcher_;
+#endif
};
GuiView::GuiView(int id)
- : d(*new GuiViewPrivate), id_(id), closing_(false)
+ : d(*new GuiViewPrivate(this)), id_(id), closing_(false)
{
// GuiToolbars *must* be initialised before the menu bar.
normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
constructToolbars();
- d.layout_ = new LayoutBox(*this);
- d.stack_widget_->addWidget(d.layout_);
// set ourself as the current view. This is needed for the menu bar
// filling, at least for the static special menu item on Mac. Otherwise
// they are greyed out.
- theLyXFunc().setLyXView(this);
+ guiApp->setCurrentView(this);
// Fill up the menu bar.
guiApp->menus().fillMenuBar(menuBar(), this, true);
setAcceptDrops(true);
statusBar()->setSizeGripEnabled(true);
+ updateStatusBar();
+
+#if (QT_VERSION >= 0x040400)
+ connect(&d.autosave_watcher_, SIGNAL(finished()), this,
+ SLOT(threadFinished()));
+ connect(&d.preview_watcher_, SIGNAL(finished()), this,
+ SLOT(threadFinished()));
+#endif
+
+ connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)),
+ SLOT(doShowDialog(QString const &, QString const &, Inset *)));
// Forbid too small unresizable window because it can happen
// with some window manager under X11.
}
+void GuiView::threadFinished()
+{
+#if (QT_VERSION >= 0x040400)
+ QFutureWatcher<docstring> const * watcher =
+ static_cast<QFutureWatcher<docstring> const *>(sender());
+ message(watcher->result());
+#endif
+}
+
+
void GuiView::saveLayout() const
{
QSettings settings;
dialog->prepareView();
if ((dialog = findOrBuild("view-source", true)))
dialog->prepareView();
+ if ((dialog = findOrBuild("progress", true)))
+ dialog->prepareView();
if (!restoreState(settings.value("layout").toByteArray(), 0))
initToolbars();
delete it->second;
d.toolbars_.clear();
+ // I don't like doing this here, but the standard toolbar
+ // destroys this object when it's destroyed itself (vfr)
+ d.layout_ = new LayoutBox(*this);
+ d.stack_widget_->addWidget(d.layout_);
+ d.layout_->move(0,0);
+
// extracts the toolbars from the backend
Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
Toolbars::Infos::iterator end = guiApp->toolbars().end();
LYXERR(Debug::DEBUG, "GuiView::setFocus()" << this);
// Make sure LyXFunc points to the correct view.
guiApp->setCurrentView(this);
- theLyXFunc().setLyXView(this);
QMainWindow::setFocus();
if (d.current_work_area_)
d.current_work_area_->setFocus();
LYXERR(Debug::DEBUG, "GuiView::closeEvent()");
closing_ = true;
+ writeSession();
+
// it can happen that this event arrives without selecting the view,
// e.g. when clicking the close button on a background window.
setFocus();
- if (!closeBufferAll(true)) {
+ if (!closeWorkAreaAll()) {
closing_ = false;
close_event->ignore();
return;
}
- // Make sure that nothing will use this close to be closed View.
+ // Make sure that nothing will use this to be closed View.
guiApp->unregisterView(this);
if (isFullScreen()) {
}
-bool GuiView::closeBufferAll(bool tolastopened)
-{
- GuiWorkArea * active_wa = currentMainWorkArea();
- setCurrentWorkArea(active_wa);
-
- // We might be in a situation that there is still a tabWorkArea, but
- // there are no tabs anymore. This can happen when we get here after a
- // TabWorkArea::lastWorkAreaRemoved() signal. Therefore we count how
- // many TabWorkArea's have no documents anymore.
- int empty_twa = 0;
-
- // We have to call count() each time, because it can happen that
- // more than one splitter will disappear in one iteration (bug 5998).
- for (; d.splitter_->count() > empty_twa; ) {
- TabWorkArea * twa = d.tabWorkArea(empty_twa);
-
- int twa_count = twa->count();
- if (twa->count() == 0)
- ++empty_twa;
-
- for (; twa_count; --twa_count) {
- twa->setCurrentIndex(twa_count-1);
-
- GuiWorkArea * wa = twa->currentWorkArea();
- bool const is_active_wa = active_wa == wa;
- Buffer * b = &wa->bufferView().buffer();
- if (b->parent()) {
- // This is a child document, just close the tab
- // after saving but keep the file loaded.
- if (!closeBuffer(*b, false, tolastopened, is_active_wa))
- return false;
- continue;
- }
-
- vector<Buffer *> clist = b->getChildren();
- for (vector<Buffer *>::const_iterator it = clist.begin();
- it != clist.end(); ++it) {
- if ((*it)->isClean())
- continue;
- Buffer * c = *it;
- // If a child is dirty, do not close
- // without user intervention
- //FIXME: should buffers be closed or not?
- if (!closeBuffer(*c, false, false))
- return false;
- }
-
- QList<int> const ids = guiApp->viewIds();
- for (int i = 0; i != ids.size(); ++i) {
- if (id_ == ids[i])
- continue;
- if (guiApp->view(ids[i]).workArea(*b)) {
- // FIXME 1: should we put an alert box here
- // that the buffer is viewed elsewhere?
- // FIXME 2: should we try to save this buffer in any case?
- //saveBuffer(b);
-
- // This buffer is also opened in another view, so
- // close the associated work area...
- removeWorkArea(wa);
- // ... but don't close the buffer.
- b = 0;
- break;
- }
- }
- // closeBuffer() needs buffer workArea still alive and
- // set as currrent one, and destroys it
- if (b && !closeBuffer(*b, true, tolastopened, is_active_wa))
- return false;
- }
- }
- return true;
-}
-
-
void GuiView::dragEnterEvent(QDragEnterEvent * event)
{
if (event->mimeData()->hasUrls())
for (int i = 0; i != files.size(); ++i) {
string const file = os::internal_path(fromqstr(
files.at(i).toLocalFile()));
- if (!file.empty()) {
- // Asynchronously post the event. DropEvent usually come
- // from the BufferView. But reloading a file might close
- // the BufferView from within its own event handler.
- guiApp->dispatchDelayed(FuncRequest(LFUN_FILE_OPEN, file));
- event->accept();
+ if (file.empty())
+ continue;
+
+ string const ext = support::getExtension(file);
+ vector<const Format *> found_formats;
+
+ // Find all formats that have the correct extension.
+ vector<const Format *> const & import_formats
+ = theConverters().importableFormats();
+ vector<const Format *>::const_iterator it = import_formats.begin();
+ for (; it != import_formats.end(); ++it)
+ if ((*it)->extension() == ext)
+ found_formats.push_back(*it);
+
+ FuncRequest cmd;
+ if (found_formats.size() >= 1) {
+ if (found_formats.size() > 1) {
+ //FIXME: show a dialog to choose the correct importable format
+ LYXERR(Debug::FILES,
+ "Multiple importable formats found, selecting first");
+ }
+ string const arg = found_formats[0]->name() + " " + file;
+ cmd = FuncRequest(LFUN_BUFFER_IMPORT, arg);
+ }
+ else {
+ //FIXME: do we have to explicitly check whether it's a lyx file?
+ LYXERR(Debug::FILES,
+ "No formats found, trying to open it as a lyx file");
+ cmd = FuncRequest(LFUN_FILE_OPEN, file);
}
+
+ // Asynchronously post the event. DropEvent usually comes
+ // from the BufferView. But reloading a file might close
+ // the BufferView from within its own event handler.
+ guiApp->dispatchDelayed(cmd);
+ event->accept();
}
}
{
if (ForkedProcess::iAmAChild())
return;
+
+ // call is moved to GUI-thread by GuiProgress
+ d.progress_->appendMessage(toqstr(str));
+}
- statusBar()->showMessage(toqstr(str));
+
+void GuiView::updateMessage(QString const & str)
+{
+ statusBar()->showMessage(str);
d.statusbar_timer_.stop();
d.statusbar_timer_.start(3000);
}
void GuiView::clearMessage()
{
- if (!hasFocus())
- return;
- theLyXFunc().setLyXView(this);
- statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+ // FIXME: This code was introduced in r19643 to fix bug #4123. However,
+ // the hasFocus function mostly returns false, even if the focus is on
+ // a workarea in this view.
+ //if (!hasFocus())
+ // return;
+ showMessage();
d.statusbar_timer_.stop();
}
void GuiView::updateWindowTitle(GuiWorkArea * wa)
{
- if (wa != d.current_work_area_)
+ if (wa != d.current_work_area_
+ || wa->bufferView().buffer().isInternal())
return;
setWindowTitle(qt_("LyX: ") + wa->windowTitle());
setWindowIconText(wa->windowIconText());
updateDialogs();
resetWindowTitleAndIconText();
+ updateStatusBar();
if (lyxrc.open_buffers_in_tabs)
// Nothing more to do, the window should stay open.
if (d.statusbar_timer_.isActive())
return;
- theLyXFunc().setLyXView(this);
- statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+ showMessage();
}
-bool GuiView::hasFocus() const
+void GuiView::showMessage()
{
- return qApp->activeWindow() == this;
+ QString msg = toqstr(theGuiApp()->viewStatusMessage());
+ if (msg.isEmpty()) {
+ BufferView const * bv = currentBufferView();
+ if (bv)
+ msg = toqstr(bv->cursor().currentState());
+ else
+ msg = qt_("Welcome to LyX!");
+ }
+ statusBar()->showMessage(msg);
}
// break;
case QEvent::WindowActivate: {
- if (this == guiApp->currentView()) {
+ GuiView * old_view = guiApp->currentView();
+ if (this == old_view) {
setFocus();
return QMainWindow::event(e);
}
+ if (old_view && old_view->currentBufferView()) {
+ // save current selection to the selection buffer to allow
+ // middle-button paste in this window.
+ cap::saveSelection(old_view->currentBufferView()->cursor());
+ }
guiApp->setCurrentView(this);
- theLyXFunc().setLyXView(this);
if (d.current_work_area_) {
BufferView & bv = d.current_work_area_->bufferView();
connectBufferView(bv);
// Allow processing of shortcuts that are allowed even when no Buffer
// is viewed.
- theLyXFunc().setLyXView(this);
KeySymbol sym;
setKeySymbol(&sym, ke);
- theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
+ guiApp->processKeySym(sym, q_key_state(ke->modifiers()));
e->accept();
return true;
}
if (old_gwa == wa)
return;
- if (view())
- cap::saveSelection(view()->cursor());
+ if (currentBufferView())
+ cap::saveSelection(currentBufferView()->cursor());
theGuiApp()->setCurrentView(this);
d.current_work_area_ = wa;
}
-Buffer * GuiView::buffer()
-{
- if (d.current_work_area_)
- return &d.current_work_area_->bufferView().buffer();
- return 0;
-}
-
-
-Buffer const * GuiView::buffer() const
-{
- if (d.current_work_area_)
- return &d.current_work_area_->bufferView().buffer();
- return 0;
-}
-
-
void GuiView::setBuffer(Buffer * newBuffer)
{
- LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << std::endl);
+ LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << endl);
LASSERT(newBuffer, return);
setBusy(true);
void GuiView::disconnectBuffer()
{
if (d.current_work_area_)
- d.current_work_area_->bufferView().setGuiDelegate(0);
+ d.current_work_area_->bufferView().buffer().setGuiDelegate(0);
}
void GuiView::errors(string const & error_type, bool from_master)
{
ErrorList & el = from_master ?
- buffer()->masterBuffer()->errorList(error_type)
- : buffer()->errorList(error_type);
+ documentBufferView()->buffer().masterBuffer()->errorList(error_type)
+ : documentBufferView()->buffer().errorList(error_type);
string data = error_type;
if (from_master)
data = "from_master|" + error_type;
}
-void GuiView::updateTocItem(std::string const & type, DocIterator const & dit)
+void GuiView::updateTocItem(string const & type, DocIterator const & dit)
{
d.toc_models_.updateItem(toqstr(type), dit);
}
void GuiView::structureChanged()
{
- d.toc_models_.reset(view());
+ d.toc_models_.reset(documentBufferView());
// Navigator needs more than a simple update in this case. It needs to be
// rebuilt.
updateDialog("toc", "");
}
-BufferView * GuiView::view()
+BufferView * GuiView::documentBufferView()
+{
+ return currentMainWorkArea()
+ ? ¤tMainWorkArea()->bufferView()
+ : 0;
+}
+
+
+BufferView const * GuiView::documentBufferView() const
+{
+ return currentMainWorkArea()
+ ? ¤tMainWorkArea()->bufferView()
+ : 0;
+}
+
+
+BufferView * GuiView::currentBufferView()
{
return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
}
+BufferView const * GuiView::currentBufferView() const
+{
+ return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
+}
+
+
+#if (QT_VERSION >= 0x040400)
+static docstring saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
+{
+ bool failed = true;
+ FileName const tmp_ret = FileName::tempName("lyxauto");
+ if (!tmp_ret.empty()) {
+ if (buffer->writeFile(tmp_ret))
+ failed = !tmp_ret.moveTo(fname);
+ }
+ if (failed) {
+ // failed to write/rename tmp_ret so try writing direct
+ failed = buffer->writeFile(fname);
+ }
+ delete buffer;
+ return failed
+ ? _("Automatic save failed!")
+ : _("Automatic save done.");
+}
+#endif
+
+
void GuiView::autoSave()
{
LYXERR(Debug::INFO, "Running autoSave()");
- if (buffer())
- view()->buffer().autoSave();
+ Buffer * buffer = documentBufferView()
+ ? &documentBufferView()->buffer() : 0;
+ if (!buffer)
+ return;
+
+#if (QT_VERSION >= 0x040400)
+ QFuture<docstring> f = QtConcurrent::run(saveAndDestroyBuffer, buffer->clone(),
+ buffer->getAutosaveFilename());
+ d.autosave_watcher_.setFuture(f);
+#else
+ buffer->autoSave();
+#endif
}
bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
{
bool enable = true;
- Buffer * buf = buffer();
+ Buffer * buf = currentBufferView()
+ ? ¤tBufferView()->buffer() : 0;
+ Buffer * doc_buffer = documentBufferView()
+ ? &(documentBufferView()->buffer()) : 0;
+
+ // Check whether we need a buffer
+ if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
+ // no, exit directly
+ flag.message(from_utf8(N_("Command not allowed with"
+ "out any document open")));
+ flag.setEnabled(false);
+ return true;
+ }
if (cmd.origin == FuncRequest::TOC) {
GuiToc * toc = static_cast<GuiToc*>(findOrBuild("toc", false));
FuncStatus fs;
- if (toc->getStatus(view()->cursor(), cmd, fs))
+ if (toc->getStatus(documentBufferView()->cursor(), cmd, fs))
flag |= fs;
else
flag.setEnabled(false);
}
switch(cmd.action) {
- case LFUN_BUFFER_WRITE:
- enable = buf && (buf->isUnnamed() || !buf->isClean());
+ case LFUN_BUFFER_IMPORT:
break;
- case LFUN_BUFFER_WRITE_AS:
- enable = buf;
+ case LFUN_MASTER_BUFFER_UPDATE:
+ case LFUN_MASTER_BUFFER_VIEW:
+ enable = doc_buffer && doc_buffer->parent() != 0
+ && !d.preview_watcher_.isRunning();
+ break;
+
+ case LFUN_BUFFER_UPDATE:
+ case LFUN_BUFFER_VIEW: {
+ if (!doc_buffer || d.preview_watcher_.isRunning()) {
+ enable = false;
+ break;
+ }
+ string format = to_utf8(cmd.argument());
+ if (cmd.argument().empty())
+ format = doc_buffer->getDefaultOutputFormat();
+ enable = doc_buffer->isExportableFormat(format);
+ break;
+ }
+
+ case LFUN_BUFFER_RELOAD:
+ enable = doc_buffer && !doc_buffer->isUnnamed()
+ && doc_buffer->fileName().exists()
+ && (!doc_buffer->isClean()
+ || doc_buffer->isExternallyModified(Buffer::timestamp_method));
+ break;
+
+ case LFUN_BUFFER_CHILD_OPEN:
+ enable = doc_buffer;
+ break;
+
+ case LFUN_BUFFER_WRITE:
+ enable = doc_buffer && (doc_buffer->isUnnamed() || !doc_buffer->isClean());
break;
- case LFUN_BUFFER_CLOSE_ALL: {
+ //FIXME: This LFUN should be moved to GuiApplication.
+ case LFUN_BUFFER_WRITE_ALL: {
+ // We enable the command only if there are some modified buffers
+ Buffer * first = theBufferList().first();
enable = false;
- BufferList::iterator it = theBufferList().begin();
- BufferList::iterator end = theBufferList().end();
- int visible_buffers = 0;
- for (; it != end; ++it) {
- if (workArea(**it))
- ++visible_buffers;
- if (visible_buffers > 1) {
+ if (!first)
+ break;
+ Buffer * b = first;
+ // We cannot use a for loop as the buffer list is a cycle.
+ do {
+ if (!b->isClean()) {
enable = true;
break;
}
- }
+ b = theBufferList().next(b);
+ } while (b != first);
break;
}
+ case LFUN_BUFFER_WRITE_AS:
+ enable = doc_buffer;
+ break;
+
+ case LFUN_BUFFER_CLOSE:
+ enable = doc_buffer;
+ break;
+
+ case LFUN_BUFFER_CLOSE_ALL:
+ enable = theBufferList().last() != theBufferList().first();
+ break;
+
case LFUN_SPLIT_VIEW:
if (cmd.getArg(0) == "vertical")
- enable = buf && (d.splitter_->count() == 1 ||
+ enable = doc_buffer && (d.splitter_->count() == 1 ||
d.splitter_->orientation() == Qt::Vertical);
else
- enable = buf && (d.splitter_->count() == 1 ||
+ enable = doc_buffer && (d.splitter_->count() == 1 ||
d.splitter_->orientation() == Qt::Horizontal);
break;
flag.setOnOff(t->isVisible());
break;
+ case LFUN_DROP_LAYOUTS_CHOICE:
+ enable = buf;
+ break;
+
case LFUN_UI_TOGGLE:
flag.setOnOff(isFullScreen());
break;
+ case LFUN_DIALOG_DISCONNECT_INSET:
+ break;
+
+ case LFUN_DIALOG_HIDE:
+ // FIXME: should we check if the dialog is shown?
+ break;
+
case LFUN_DIALOG_TOGGLE:
flag.setOnOff(isDialogVisible(cmd.getArg(0)));
// fall through to set "enable"
case LFUN_DIALOG_SHOW: {
string const name = cmd.getArg(0);
- if (!buf)
+ if (!doc_buffer)
enable = name == "aboutlyx"
|| name == "file" //FIXME: should be removed.
|| name == "prefs"
- || name == "texinfo";
+ || name == "texinfo"
+ || name == "progress"
+ || name == "compare";
else if (name == "print")
- enable = buf->isExportable("dvi")
+ enable = doc_buffer->isExportable("dvi")
&& lyxrc.print_command != "none";
else if (name == "character" || name == "symbols") {
- if (buf->isReadonly() || !view() || !view()->cursor().inTexted())
+ if (!buf || buf->isReadonly()
+ || !currentBufferView()->cursor().inTexted())
enable = false;
else {
// FIXME we should consider passthru
// paragraphs too.
- Inset const & in = view()->cursor().inset();
+ Inset const & in = currentBufferView()->cursor().inset();
enable = !in.getLayout().isPassThru();
}
}
else if (name == "latexlog")
- enable = FileName(buf->logName()).isReadableFile();
+ enable = FileName(doc_buffer->logName()).isReadableFile();
else if (name == "spellchecker")
- enable = theSpellChecker() && !buf->isReadonly();
+ enable = theSpellChecker() && !doc_buffer->isReadonly();
else if (name == "vclog")
- enable = buf->lyxvc().inUse();
+ enable = doc_buffer->lyxvc().inUse();
break;
}
break;
}
- case LFUN_INSET_APPLY: {
- string const name = cmd.getArg(0);
- Inset * inset = getOpenInset(name);
- if (inset) {
- FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
- FuncStatus fs;
- if (!inset->getStatus(view()->cursor(), fr, fs)) {
- // Every inset is supposed to handle this
- LASSERT(false, break);
- }
- flag |= fs;
- } else {
- FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
- flag |= lyx::getStatus(fr);
- }
- enable = flag.enabled();
+ case LFUN_COMMAND_EXECUTE:
+ case LFUN_MESSAGE:
+ case LFUN_MENU_OPEN:
+ // Nothing to check.
break;
- }
case LFUN_COMPLETION_INLINE:
if (!d.current_work_area_
- || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
+ || !d.current_work_area_->completer().inlinePossible(
+ currentBufferView()->cursor()))
enable = false;
break;
case LFUN_COMPLETION_POPUP:
if (!d.current_work_area_
- || !d.current_work_area_->completer().popupPossible(view()->cursor()))
+ || !d.current_work_area_->completer().popupPossible(
+ currentBufferView()->cursor()))
enable = false;
break;
case LFUN_COMPLETION_COMPLETE:
if (!d.current_work_area_
- || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
+ || !d.current_work_area_->completer().inlinePossible(
+ currentBufferView()->cursor()))
enable = false;
break;
break;
case LFUN_BUFFER_ZOOM_OUT:
- enable = buf && lyxrc.zoom > 10;
+ enable = doc_buffer && lyxrc.zoom > 10;
break;
case LFUN_BUFFER_ZOOM_IN:
- enable = buf;
+ enable = doc_buffer;
+ break;
+
+ case LFUN_BUFFER_NEXT:
+ case LFUN_BUFFER_PREVIOUS:
+ // FIXME: should we check is there is an previous or next buffer?
+ break;
+ case LFUN_BUFFER_SWITCH:
+ // toggle on the current buffer, but do not toggle off
+ // the other ones (is that a good idea?)
+ if (doc_buffer
+ && to_utf8(cmd.argument()) == doc_buffer->absFileName())
+ flag.setOnOff(true);
+ break;
+
+ case LFUN_VC_REGISTER:
+ enable = doc_buffer && !doc_buffer->lyxvc().inUse();
+ break;
+ case LFUN_VC_CHECK_IN:
+ enable = doc_buffer && doc_buffer->lyxvc().checkInEnabled();
+ break;
+ case LFUN_VC_CHECK_OUT:
+ enable = doc_buffer && doc_buffer->lyxvc().checkOutEnabled();
+ break;
+ case LFUN_VC_LOCKING_TOGGLE:
+ enable = doc_buffer && !doc_buffer->isReadonly()
+ && doc_buffer->lyxvc().lockingToggleEnabled();
+ flag.setOnOff(enable && !doc_buffer->lyxvc().locker().empty());
+ break;
+ case LFUN_VC_REVERT:
+ enable = doc_buffer && doc_buffer->lyxvc().inUse();
+ break;
+ case LFUN_VC_UNDO_LAST:
+ enable = doc_buffer && doc_buffer->lyxvc().undoLastEnabled();
+ break;
+ case LFUN_VC_REPO_UPDATE:
+ enable = doc_buffer && doc_buffer->lyxvc().inUse();
+ break;
+ case LFUN_VC_COMMAND: {
+ if (cmd.argument().empty())
+ enable = false;
+ if (!doc_buffer && contains(cmd.getArg(0), 'D'))
+ enable = false;
+ break;
+ }
+
+ case LFUN_SERVER_GOTO_FILE_ROW:
break;
default:
if (lyxrc.use_lastfilepos) {
LastFilePosSection::FilePos filepos =
theSession().lastFilePos().load(filename);
- view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
+ documentBufferView()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
}
if (tolastfiles)
{
string initpath = lyxrc.document_path;
- if (buffer()) {
- string const trypath = buffer()->filePath();
+ if (documentBufferView()) {
+ string const trypath = documentBufferView()->buffer().filePath();
// If directory is writeable, use this as default.
if (FileName(trypath).isDirWritable())
initpath = trypath;
string filename2 = (loader_format == format) ? filename.absFilename()
: support::changeExtension(filename.absFilename(),
formats.extension(loader_format));
- lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
- theLyXFunc().setLyXView(lv);
+ lv->currentBufferView()->insertPlaintextFile(FileName(filename2),
+ as_paragraphs);
+ guiApp->setCurrentView(lv);
lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
}
// need user interaction
if (filename.empty()) {
string initpath = lyxrc.document_path;
-
- Buffer const * buf = buffer();
- if (buf) {
- string const trypath = buf->filePath();
+ if (documentBufferView()) {
+ string const trypath = documentBufferView()->buffer().filePath();
// If directory is writeable, use this as default.
if (FileName(trypath).isDirWritable())
initpath = trypath;
void GuiView::newDocument(string const & filename, bool from_template)
{
FileName initpath(lyxrc.document_path);
- Buffer * buf = buffer();
- if (buf) {
- FileName const trypath(buf->filePath());
+ if (documentBufferView()) {
+ FileName const trypath(documentBufferView()->buffer().filePath());
// If directory is writeable, use this as default.
if (trypath.isDirWritable())
initpath = trypath;
Buffer * b;
if (filename.empty())
- b = newUnnamedFile(templatefile, initpath);
+ b = newUnnamedFile(initpath, to_utf8(_("newfile")), templatefile);
else
b = newFile(filename, templatefile, true);
// If no new document could be created, it is unsure
// whether there is a valid BufferView.
- if (view())
+ if (currentBufferView())
// Ensure the cursor is correctly positioned on screen.
- view()->showCursor();
+ currentBufferView()->showCursor();
}
void GuiView::insertLyXFile(docstring const & fname)
{
- BufferView * bv = view();
+ BufferView * bv = documentBufferView();
if (!bv)
return;
void GuiView::insertPlaintextFile(docstring const & fname,
bool asParagraph)
{
- BufferView * bv = view();
+ BufferView * bv = documentBufferView();
if (!bv)
return;
bool GuiView::hideWorkArea(GuiWorkArea * wa)
+{
+ return closeWorkArea(wa, false);
+}
+
+
+bool GuiView::closeWorkArea(GuiWorkArea * wa)
{
Buffer & buf = wa->bufferView().buffer();
- return closeBuffer(buf, false);
+ return closeWorkArea(wa, !buf.parent());
}
bool GuiView::closeBuffer()
{
- Buffer * buf = buffer();
- return buf && closeBuffer(*buf, !buf->parent());
+ GuiWorkArea * wa = currentMainWorkArea();
+ setCurrentWorkArea(wa);
+ Buffer & buf = wa->bufferView().buffer();
+ return wa && closeWorkArea(wa, !buf.parent());
+}
+
+
+void GuiView::writeSession() const {
+ GuiWorkArea const * active_wa = currentMainWorkArea();
+ for (int i = 0; i < d.splitter_->count(); ++i) {
+ TabWorkArea * twa = d.tabWorkArea(i);
+ for (int j = 0; j < twa->count(); ++j) {
+ GuiWorkArea * wa = static_cast<GuiWorkArea *>(twa->widget(j));
+ Buffer & buf = wa->bufferView().buffer();
+ theSession().lastOpened().add(buf.fileName(), wa == active_wa);
+ }
+ }
+}
+
+
+bool GuiView::closeBufferAll()
+{
+ // Close the workareas in all other views
+ QList<int> const ids = guiApp->viewIds();
+ for (int i = 0; i != ids.size(); ++i) {
+ if (id_ != ids[i] && !guiApp->view(ids[i]).closeWorkAreaAll())
+ return false;
+ }
+
+ // Close our own workareas
+ if (!closeWorkAreaAll())
+ return false;
+
+ // Now close the hidden buffers. We prevent hidden buffers from being
+ // dirty, so we can just close them.
+ theBufferList().closeAll();
+ return true;
+}
+
+
+bool GuiView::closeWorkAreaAll()
+{
+ setCurrentWorkArea(currentMainWorkArea());
+
+ // We might be in a situation that there is still a tabWorkArea, but
+ // there are no tabs anymore. This can happen when we get here after a
+ // TabWorkArea::lastWorkAreaRemoved() signal. Therefore we count how
+ // many TabWorkArea's have no documents anymore.
+ int empty_twa = 0;
+
+ // We have to call count() each time, because it can happen that
+ // more than one splitter will disappear in one iteration (bug 5998).
+ for (; d.splitter_->count() > empty_twa; ) {
+ TabWorkArea * twa = d.tabWorkArea(empty_twa);
+
+ if (twa->count() == 0)
+ ++empty_twa;
+ else {
+ setCurrentWorkArea(twa->currentWorkArea());
+ if (!closeTabWorkArea(twa))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer)
+{
+ if (!wa)
+ return false;
+
+ Buffer & buf = wa->bufferView().buffer();
+
+ if (close_buffer)
+ return closeBuffer(buf);
+ else {
+ if (!inMultiTabs(wa))
+ if (!saveBufferIfNeeded(buf, true))
+ return false;
+ removeWorkArea(wa);
+ return true;
+ }
}
-bool GuiView::closeBuffer(Buffer & buf, bool close_buffer,
- bool tolastopened, bool mark_active)
+bool GuiView::closeBuffer(Buffer & buf)
{
+ // If we are in a close_event all children will be closed in some time,
+ // so no need to do it here. This will ensure that the children end up
+ // in the session file in the correct order. If we close the master
+ // buffer, we can close or release the child buffers here too.
+ if (!closing_) {
+ vector<Buffer *> clist = buf.getChildren(false);
+ for (vector<Buffer *>::const_iterator it = clist.begin();
+ it != clist.end(); ++it) {
+ // If a child is dirty, do not close
+ // without user intervention
+ //FIXME: should we look in other tabworkareas?
+ Buffer * child_buf = *it;
+ GuiWorkArea * child_wa = workArea(*child_buf);
+ if (child_wa) {
+ if (!closeWorkArea(child_wa, true))
+ return false;
+ } else
+ theBufferList().releaseChild(&buf, child_buf);
+ }
+ }
// goto bookmark to update bookmark pit.
//FIXME: we should update only the bookmarks related to this buffer!
LYXERR(Debug::DEBUG, "GuiView::closeBuffer()");
for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
theLyXFunc().gotoBookmark(i+1, false, false);
- if (saveBufferIfNeeded(buf, !close_buffer)) {
- // save in sessions if requested
- // do not save childs if their master
- // is opened as well
- if (tolastopened)
- theSession().lastOpened().add(buf.fileName(), mark_active);
- if (!close_buffer)
- removeWorkArea(currentMainWorkArea());
- else
- theBufferList().release(&buf);
+ if (saveBufferIfNeeded(buf, false)) {
+ theBufferList().release(&buf);
return true;
}
return false;
}
+bool GuiView::closeTabWorkArea(TabWorkArea * twa)
+{
+ while (twa == d.currentTabWorkArea()) {
+ twa->setCurrentIndex(twa->count()-1);
+
+ GuiWorkArea * wa = twa->currentWorkArea();
+ Buffer & b = wa->bufferView().buffer();
+
+ // We only want to close the buffer if the same buffer is not visible
+ // in another view, and if this is not a child and if we are closing
+ // a view (not a tabgroup).
+ bool const close_buffer =
+ !inMultiViews(wa) && !b.parent() && closing_;
+
+ if (!closeWorkArea(wa, close_buffer))
+ return false;
+ }
+ return true;
+}
+
+
bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
{
if (buf.isClean() || buf.paragraphs().empty())
// have no autosave file but I guess
// this is really improbable (Jug)
buf.removeAutosaveFile();
- if (hiding) {
+ if (hiding)
// revert all changes
- buf.loadLyXFile(buf.fileName());
- buf.markClean();
- }
+ buf.reload();
+ buf.markClean();
break;
case 2:
return false;
}
+bool GuiView::inMultiTabs(GuiWorkArea * wa)
+{
+ Buffer & buf = wa->bufferView().buffer();
+
+ for (int i = 0; i != d.splitter_->count(); ++i) {
+ GuiWorkArea * wa_ = d.tabWorkArea(i)->workArea(buf);
+ if (wa_ && wa_ != wa)
+ return true;
+ }
+ return inMultiViews(wa);
+}
+
+
+bool GuiView::inMultiViews(GuiWorkArea * wa)
+{
+ QList<int> const ids = guiApp->viewIds();
+ Buffer & buf = wa->bufferView().buffer();
+
+ int found_twa = 0;
+ for (int i = 0; i != ids.size() && found_twa <= 1; ++i) {
+ if (id_ == ids[i])
+ continue;
+
+ if (guiApp->view(ids[i]).workArea(buf))
+ return true;
+ }
+ return false;
+}
+
+
void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np)
{
- Buffer * const curbuf = buffer();
+ Buffer * const curbuf = documentBufferView()
+ ? &documentBufferView()->buffer() : 0;
Buffer * nextbuf = curbuf;
while (true) {
if (np == NEXTBUFFER)
}
+/// make sure the document is saved
+static bool ensureBufferClean(Buffer * buffer)
+{
+ LASSERT(buffer, return false);
+ if (buffer->isClean() && !buffer->isUnnamed())
+ return true;
+
+ docstring const file = buffer->fileName().displayName(30);
+ docstring title;
+ docstring text;
+ if (!buffer->isUnnamed()) {
+ text = bformat(_("The document %1$s has unsaved "
+ "changes.\n\nDo you want to save "
+ "the document?"), file);
+ title = _("Save changed document?");
+
+ } else {
+ text = bformat(_("The document %1$s has not been "
+ "saved yet.\n\nDo you want to save "
+ "the document?"), file);
+ title = _("Save new document?");
+ }
+ int const ret = Alert::prompt(title, text, 0, 1, _("&Save"), _("&Cancel"));
+
+ if (ret == 0)
+ dispatch(FuncRequest(LFUN_BUFFER_WRITE));
+
+ return buffer->isClean() && !buffer->isUnnamed();
+}
+
+
+void GuiView::reloadBuffer()
+{
+ Buffer * buf = &documentBufferView()->buffer();
+ buf->reload();
+}
+
+
+void GuiView::checkExternallyModifiedBuffers()
+{
+ BufferList::iterator bit = theBufferList().begin();
+ BufferList::iterator const bend = theBufferList().end();
+ for (; bit != bend; ++bit) {
+ if ((*bit)->fileName().exists()
+ && (*bit)->isExternallyModified(Buffer::checksum_method)) {
+ docstring text = bformat(_("Document \n%1$s\n has been externally modified."
+ " Reload now? Any local changes will be lost."),
+ from_utf8((*bit)->absFileName()));
+ int const ret = Alert::prompt(_("Reload externally changed document?"),
+ text, 0, 1, _("&Reload"), _("&Cancel"));
+ if (!ret)
+ (*bit)->reload();
+ }
+ }
+}
+
+
+void GuiView::dispatchVC(FuncRequest const & cmd)
+{
+ // message for statusbar
+ string msg;
+ Buffer * buffer = documentBufferView()
+ ? &(documentBufferView()->buffer()) : 0;
+
+ switch (cmd.action) {
+ case LFUN_VC_REGISTER:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (!buffer->lyxvc().inUse()) {
+ if (buffer->lyxvc().registrer())
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_CHECK_IN:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+ msg = buffer->lyxvc().checkIn();
+ if (!msg.empty())
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_CHECK_OUT:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (buffer->lyxvc().inUse()) {
+ msg = buffer->lyxvc().checkOut();
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_LOCKING_TOGGLE:
+ LASSERT(buffer, return);
+ if (!ensureBufferClean(buffer) || buffer->isReadonly())
+ break;
+ if (buffer->lyxvc().inUse()) {
+ string res = buffer->lyxvc().lockingToggle();
+ if (res.empty()) {
+ frontend::Alert::error(_("Revision control error."),
+ _("Error when setting the locking property."));
+ } else {
+ msg = res;
+ reloadBuffer();
+ }
+ }
+ break;
+
+ case LFUN_VC_REVERT:
+ LASSERT(buffer, return);
+ buffer->lyxvc().revert();
+ reloadBuffer();
+ break;
+
+ case LFUN_VC_UNDO_LAST:
+ LASSERT(buffer, return);
+ buffer->lyxvc().undoLast();
+ reloadBuffer();
+ break;
+
+ case LFUN_VC_REPO_UPDATE:
+ LASSERT(buffer, return);
+ if (ensureBufferClean(buffer)) {
+ msg = buffer->lyxvc().repoUpdate();
+ checkExternallyModifiedBuffers();
+ }
+ break;
+
+ case LFUN_VC_COMMAND: {
+ string flag = cmd.getArg(0);
+ if (buffer && contains(flag, 'R') && !ensureBufferClean(buffer))
+ break;
+ docstring message;
+ if (contains(flag, 'M')) {
+ if (!Alert::askForText(message, _("LyX VC: Log Message")))
+ break;
+ }
+ string path = cmd.getArg(1);
+ if (contains(path, "$$p") && buffer)
+ path = subst(path, "$$p", buffer->filePath());
+ LYXERR(Debug::LYXVC, "Directory: " << path);
+ FileName pp(path);
+ if (!pp.isReadableDirectory()) {
+ lyxerr << _("Directory is not accessible.") << endl;
+ break;
+ }
+ support::PathChanger p(pp);
+
+ string command = cmd.getArg(2);
+ if (command.empty())
+ break;
+ if (buffer) {
+ command = subst(command, "$$i", buffer->absFileName());
+ command = subst(command, "$$p", buffer->filePath());
+ }
+ command = subst(command, "$$m", to_utf8(message));
+ LYXERR(Debug::LYXVC, "Command: " << command);
+ Systemcall one;
+ one.startscript(Systemcall::Wait, command);
+
+ if (!buffer)
+ break;
+ if (contains(flag, 'I'))
+ buffer->markDirty();
+ if (contains(flag, 'R'))
+ reloadBuffer();
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!msg.empty())
+ message(from_utf8(msg));
+}
+
+
+void GuiView::openChildDocument(string const & fname)
+{
+ LASSERT(documentBufferView(), return);
+ Buffer & buffer = documentBufferView()->buffer();
+ FileName const filename = support::makeAbsPath(fname, buffer.filePath());
+ documentBufferView()->saveBookmark(false);
+ Buffer * child = 0;
+ bool parsed = false;
+ if (theBufferList().exists(filename)) {
+ child = theBufferList().getBuffer(filename);
+ } else {
+ message(bformat(_("Opening child document %1$s..."),
+ makeDisplayPath(filename.absFilename())));
+ child = loadDocument(filename, false);
+ parsed = true;
+ }
+ if (!child)
+ return;
+
+ // Set the parent name of the child document.
+ // This makes insertion of citations and references in the child work,
+ // when the target is in the parent or another child document.
+ child->setParent(&buffer);
+ child->masterBuffer()->updateLabels();
+ setBuffer(child);
+ if (parsed)
+ child->errors("Parse");
+}
+
+
+bool GuiView::goToFileRow(string const & argument)
+{
+ string file_name;
+ int row;
+ size_t i = argument.find_last_of(' ');
+ if (i != string::npos) {
+ file_name = os::internal_path(trim(argument.substr(0, i)));
+ istringstream is(argument.substr(i + 1));
+ is >> row;
+ if (is.fail())
+ i = string::npos;
+ }
+ if (i == string::npos) {
+ LYXERR0("Wrong argument: " << argument);
+ return false;
+ }
+ Buffer * buf = 0;
+ string const abstmp = package().temp_dir().absFilename();
+ string const realtmp = package().temp_dir().realPath();
+ // We have to use os::path_prefix_is() here, instead of
+ // simply prefixIs(), because the file name comes from
+ // an external application and may need case adjustment.
+ if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
+ || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
+ // Needed by inverse dvi search. If it is a file
+ // in tmpdir, call the apropriated function.
+ // If tmpdir is a symlink, we may have the real
+ // path passed back, so we correct for that.
+ if (!prefixIs(file_name, abstmp))
+ file_name = subst(file_name, realtmp, abstmp);
+ buf = theBufferList().getBufferFromTmp(file_name);
+ } else {
+ // Must replace extension of the file to be .lyx
+ // and get full path
+ FileName const s = fileSearch(string(),
+ support::changeExtension(file_name, ".lyx"), "lyx");
+ // Either change buffer or load the file
+ if (theBufferList().exists(s))
+ buf = theBufferList().getBuffer(s);
+ else if (s.exists()) {
+ buf = loadDocument(s);
+ buf->updateLabels();
+ buf->errors("Parse");
+ } else {
+ message(bformat(
+ _("File does not exist: %1$s"),
+ makeDisplayPath(file_name)));
+ return false;
+ }
+ }
+ setBuffer(buf);
+ documentBufferView()->setCursorFromRow(row);
+ return true;
+}
+
+
+#if (QT_VERSION >= 0x040400)
+static docstring exportAndDestroy(Buffer * buffer, string const & format)
+{
+ bool const success = buffer->doExport(format, true);
+ delete buffer;
+ return success
+ ? bformat(_("Successful export to format: %1$s"), from_utf8(format))
+ : bformat(_("Error exporting to format: %1$s"), from_utf8(format));
+}
+
+
+static docstring previewAndDestroy(Buffer * buffer, string const & format)
+{
+ bool const success = buffer->preview(format);
+ delete buffer;
+ return success
+ ? bformat(_("Successful preview of format: %1$s"), from_utf8(format))
+ : bformat(_("Error previewing format: %1$s"), from_utf8(format));
+}
+#endif
+
+
bool GuiView::dispatch(FuncRequest const & cmd)
{
- BufferView * bv = view();
+ BufferView * bv = currentBufferView();
// By default we won't need any update.
if (bv)
bv->cursor().updateFlags(Update::None);
+
+ Buffer * doc_buffer = documentBufferView()
+ ? &(documentBufferView()->buffer()) : 0;
+
bool dispatched = true;
if (cmd.origin == FuncRequest::TOC) {
return true;
}
+ string const argument = to_utf8(cmd.argument());
+
switch(cmd.action) {
+ case LFUN_BUFFER_CHILD_OPEN:
+ openChildDocument(to_utf8(cmd.argument()));
+ break;
+
case LFUN_BUFFER_IMPORT:
importDocument(to_utf8(cmd.argument()));
break;
+ case LFUN_BUFFER_EXPORT: {
+ if (!doc_buffer)
+ break;
+ if (cmd.argument() == "custom") {
+ lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
+ break;
+ }
+ if (doc_buffer->doExport(argument, false)) {
+ message(bformat(_("Error exporting to format: %1$s."),
+ cmd.argument()));
+ }
+ break;
+ }
+
+ case LFUN_BUFFER_UPDATE: {
+ if (!doc_buffer)
+ break;
+ string format = argument;
+ if (argument.empty())
+ format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+ d.progress_->clearMessages();
+ message(_("Exporting ..."));
+ QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+ doc_buffer->clone(), format);
+ d.setPreviewFuture(f);
+#else
+ doc_buffer->doExport(format, true);
+#endif
+ break;
+ }
+ case LFUN_BUFFER_VIEW: {
+ if (!doc_buffer)
+ break;
+ string format = argument;
+ if (argument.empty())
+ format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+ d.progress_->clearMessages();
+ message(_("Previewing ..."));
+ QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+ doc_buffer->clone(), format);
+ d.setPreviewFuture(f);
+#else
+ doc_buffer->preview(format);
+#endif
+ break;
+ }
+ case LFUN_MASTER_BUFFER_UPDATE: {
+ if (!doc_buffer)
+ break;
+ string format = argument;
+ Buffer const * master = doc_buffer->masterBuffer();
+ if (argument.empty())
+ format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+ QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+ master->clone(), format);
+ d.setPreviewFuture(f);
+#else
+ master->doExport(format, true);
+#endif
+ break;
+ }
+ case LFUN_MASTER_BUFFER_VIEW: {
+ string format = argument;
+ Buffer const * master = doc_buffer->masterBuffer();
+ if (argument.empty())
+ format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+ QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+ master->clone(), format);
+ d.setPreviewFuture(f);
+#else
+ master->preview(format);
+#endif
+ break;
+ }
case LFUN_BUFFER_SWITCH:
if (FileName::isAbsolute(to_utf8(cmd.argument()))) {
Buffer * buffer =
if (buffer)
setBuffer(buffer);
else
- bv->cursor().message(_("Document not loaded"));
+ message(_("Document not loaded"));
}
break;
insertPlaintextFile(cmd.argument(), false);
break;
+ case LFUN_BUFFER_RELOAD: {
+ LASSERT(doc_buffer, break);
+ docstring const file = makeDisplayPath(doc_buffer->absFileName(), 20);
+ docstring text = bformat(_("Any changes will be lost. Are you sure "
+ "you want to revert to the saved version of the document %1$s?"), file);
+ int const ret = Alert::prompt(_("Revert to saved document?"),
+ text, 1, 1, _("&Revert"), _("&Cancel"));
+
+ if (ret == 0) {
+ doc_buffer->markClean();
+ reloadBuffer();
+ }
+ break;
+ }
+
case LFUN_BUFFER_WRITE:
- if (bv)
- saveBuffer(bv->buffer());
+ LASSERT(doc_buffer, break);
+ saveBuffer(*doc_buffer);
break;
case LFUN_BUFFER_WRITE_AS:
- if (bv)
- renameBuffer(bv->buffer(), cmd.argument());
+ LASSERT(doc_buffer, break);
+ renameBuffer(*doc_buffer, cmd.argument());
break;
case LFUN_BUFFER_WRITE_ALL: {
break;
}
+ case LFUN_BUFFER_CLOSE:
+ closeBuffer();
+ break;
+
+ case LFUN_BUFFER_CLOSE_ALL:
+ closeBufferAll();
+ break;
+
case LFUN_TOOLBAR_TOGGLE: {
string const name = cmd.getArg(0);
if (GuiToolbar * t = toolbar(name))
case LFUN_DIALOG_UPDATE: {
string const name = to_utf8(cmd.argument());
- // Can only update a dialog connected to an existing inset
- Inset * inset = getOpenInset(name);
- if (inset) {
+ if (currentBufferView()) {
+ Inset * inset = currentBufferView()->editedInset(name);
+ // Can only update a dialog connected to an existing inset
+ if (!inset)
+ break;
+ // FIXME: get rid of this indirection; GuiView ask the inset
+ // if he is kind enough to update itself...
FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
- inset->dispatch(view()->cursor(), fr);
+ inset->dispatch(currentBufferView()->cursor(), fr);
} else if (name == "paragraph") {
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
} else if (name == "prefs" || name == "document") {
showDialog("character", data);
} else if (name == "latexlog") {
Buffer::LogType type;
- string const logfile = buffer()->logName(&type);
+ string const logfile = doc_buffer->logName(&type);
switch (type) {
case Buffer::latexlog:
data = "latex ";
showDialog("log", data);
} else if (name == "vclog") {
string const data = "vc " +
- Lexer::quoteString(buffer()->lyxvc().getLogFile());
+ Lexer::quoteString(doc_buffer->lyxvc().getLogFile());
showDialog("log", data);
} else if (name == "symbols") {
data = bv->cursor().getEncoding()->name();
break;
}
- case LFUN_INSET_APPLY: {
- string const name = cmd.getArg(0);
- Inset * inset = getOpenInset(name);
- if (inset) {
- // put cursor in front of inset.
- if (!view()->setCursorFromInset(inset)) {
- LASSERT(false, break);
- }
-
- // useful if we are called from a dialog.
- view()->cursor().beginUndoGroup();
- view()->cursor().recordUndo();
- FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
- inset->dispatch(view()->cursor(), fr);
- view()->cursor().endUndoGroup();
- } else {
- FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
- lyx::dispatch(fr);
- }
+ case LFUN_MESSAGE:
+ message(cmd.argument());
break;
- }
case LFUN_UI_TOGGLE:
lfunUiToggle(cmd);
setFocus();
break;
- case LFUN_SPLIT_VIEW:
- if (Buffer * buf = buffer()) {
- string const orientation = cmd.getArg(0);
- d.splitter_->setOrientation(orientation == "vertical"
- ? Qt::Vertical : Qt::Horizontal);
- TabWorkArea * twa = addTabWorkArea();
- GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
- setCurrentWorkArea(wa);
- }
+ case LFUN_SPLIT_VIEW: {
+ LASSERT(doc_buffer, break);
+ string const orientation = cmd.getArg(0);
+ d.splitter_->setOrientation(orientation == "vertical"
+ ? Qt::Vertical : Qt::Horizontal);
+ TabWorkArea * twa = addTabWorkArea();
+ GuiWorkArea * wa = twa->addWorkArea(*doc_buffer, *this);
+ setCurrentWorkArea(wa);
break;
-
+ }
case LFUN_CLOSE_TAB_GROUP:
if (TabWorkArea * twa = d.currentTabWorkArea()) {
- delete twa;
+ closeTabWorkArea(twa);
+ d.current_work_area_ = 0;
twa = d.currentTabWorkArea();
// Switch to the next GuiWorkArea in the found TabWorkArea.
if (twa) {
lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
break;
+ case LFUN_VC_REGISTER:
+ case LFUN_VC_CHECK_IN:
+ case LFUN_VC_CHECK_OUT:
+ case LFUN_VC_REPO_UPDATE:
+ case LFUN_VC_LOCKING_TOGGLE:
+ case LFUN_VC_REVERT:
+ case LFUN_VC_UNDO_LAST:
+ case LFUN_VC_COMMAND:
+ dispatchVC(cmd);
+ break;
+
+ case LFUN_SERVER_GOTO_FILE_ROW:
+ goToFileRow(to_utf8(cmd.argument()));
+ break;
+
default:
dispatched = false;
break;
char const * const dialognames[] = {
"aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
-"citation", "document", "errorlist", "ert", "external", "file", "findreplace",
-"findreplaceadv", "float", "graphics", "href", "include", "index",
-"index_print", "info", "listings", "label", "log", "mathdelimiter",
+"citation", "compare", "document", "errorlist", "ert", "external", "file",
+"findreplace", "findreplaceadv", "float", "graphics", "href", "include",
+"index", "index_print", "info", "listings", "label", "log", "mathdelimiter",
"mathmatrix", "mathspace", "nomenclature", "nomencl_print", "note",
"paragraph", "phantom", "prefs", "print", "ref", "sendto", "space",
"spellchecker", "symbols", "tabular", "tabularcreate", "thesaurus", "texinfo",
-"toc", "view-source", "vspace", "wrap" };
+"toc", "view-source", "vspace", "wrap", "progress"};
char const * const * const end_dialognames =
dialognames + (sizeof(dialognames) / sizeof(char *));
void GuiView::resetDialogs()
{
// Make sure that no LFUN uses any LyXView.
- theLyXFunc().setLyXView(0);
+ guiApp->setCurrentView(0);
saveLayout();
menuBar()->clear();
constructToolbars();
guiApp->menus().fillMenuBar(menuBar(), this, false);
d.layout_->updateContents(true);
// Now update controls with current buffer.
- theLyXFunc().setLyXView(this);
+ guiApp->setCurrentView(this);
restoreLayout();
restartCursor();
}
void GuiView::showDialog(string const & name, string const & data,
Inset * inset)
+{
+ triggerShowDialog(toqstr(name), toqstr(data), inset);
+}
+
+
+void GuiView::doShowDialog(QString const & qname, QString const & qdata,
+ Inset * inset)
{
if (d.in_show_)
return;
+ const string name = fromqstr(qname);
+ const string data = fromqstr(qdata);
+
d.in_show_ = true;
try {
Dialog * dialog = findOrBuild(name, false);
if (dialog) {
dialog->showData(data);
- if (inset)
- d.open_insets_[name] = inset;
+ if (inset && currentBufferView())
+ currentBufferView()->editInset(name, inset);
}
}
catch (ExceptionMessage const & ex) {
if (it == d.dialogs_.end())
return;
- if (inset && inset != getOpenInset(name))
+ if (inset && currentBufferView()
+ && inset != currentBufferView()->editedInset(name))
return;
Dialog * const dialog = it->second.get();
if (dialog->isVisibleView())
dialog->hideView();
- d.open_insets_[name] = 0;
+ if (currentBufferView())
+ currentBufferView()->editInset(name, 0);
}
{
if (!isValidName(name))
return;
-
- if (d.open_insets_.find(name) != d.open_insets_.end())
- d.open_insets_[name] = 0;
-}
-
-
-Inset * GuiView::getOpenInset(string const & name) const
-{
- if (!isValidName(name))
- return 0;
-
- map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
- return it == d.open_insets_.end() ? 0 : it->second;
+ if (currentBufferView())
+ currentBufferView()->editInset(name, 0);
}
Dialog * createGuiChanges(GuiView & lv);
Dialog * createGuiCharacter(GuiView & lv);
Dialog * createGuiCitation(GuiView & lv);
+Dialog * createGuiCompare(GuiView & lv);
Dialog * createGuiDelimiter(GuiView & lv);
Dialog * createGuiDocument(GuiView & lv);
Dialog * createGuiErrorList(GuiView & lv);
Dialog * createGuiVSpace(GuiView & lv);
Dialog * createGuiViewSource(GuiView & lv);
Dialog * createGuiWrap(GuiView & lv);
+Dialog * createGuiProgressView(GuiView & lv);
+
Dialog * GuiView::build(string const & name)
return createGuiCharacter(*this);
if (name == "citation")
return createGuiCitation(*this);
+ if (name == "compare")
+ return createGuiCompare(*this);
if (name == "document")
return createGuiDocument(*this);
if (name == "errorlist")
return createGuiVSpace(*this);
if (name == "wrap")
return createGuiWrap(*this);
+ if (name == "progress")
+ return createGuiProgressView(*this);
return 0;
}