#include "alert.h"
-
#include "frontends/Application.h"
#include "qt_helpers.h"
#include "support/docstring.h"
#include "support/lstrings.h"
#include "support/ProgressInterface.h"
+#include "support/InGuiThread.h"
#include <QApplication>
#include <QCheckBox>
#include <iomanip>
#include <iostream>
+
+// sync with GuiView.cpp
+#define EXPORT_in_THREAD 0
+
+
using namespace std;
using namespace lyx::support;
namespace Alert {
-int prompt(docstring const & title0, docstring const & question,
+
+int doPrompt(docstring const & title0, docstring const & question,
int default_button, int cancel_button,
docstring const & b1, docstring const & b2,
docstring const & b3, docstring const & b4)
return res;
}
+int prompt(docstring const & title0, docstring const & question,
+ int default_button, int cancel_button,
+ docstring const & b1, docstring const & b2,
+ docstring const & b3, docstring const & b4)
+{
+#ifdef EXPORT_in_THREAD
+ return InGuiThread<int>().call(&doPrompt,
+#else
+ return doPrompt(
+#endif
+ title0, question, default_button,
+ cancel_button, b1, b2, b3, b4);
+}
-void warning(docstring const & title0, docstring const & message,
+void doWarning(docstring const & title0, docstring const & message,
bool const & askshowagain)
{
lyxerr << "Warning: " << title0 << '\n'
qApp->restoreOverrideCursor();
}
+void warning(docstring const & title0, docstring const & message,
+ bool const & askshowagain)
+{
+#ifdef EXPORT_in_THREAD
+ InGuiThread<void>().call(&doWarning,
+#else
+ doWarning(
+#endif
+ title0, message, askshowagain);
+}
-void error(docstring const & title0, docstring const & message)
+void doError(docstring const & title0, docstring const & message)
{
lyxerr << "Error: " << title0 << '\n'
<< "----------------------------------------\n"
qApp->restoreOverrideCursor();
}
+void error(docstring const & title0, docstring const & message)
+{
+#ifdef EXPORT_in_THREAD
+ InGuiThread<void>().call(&doError,
+#else
+ doError(
+#endif
+ title0, message);
+}
-void information(docstring const & title0, docstring const & message)
+void doInformation(docstring const & title0, docstring const & message)
{
if (!use_gui || lyxerr.debugging())
lyxerr << title0 << '\n'
qApp->restoreOverrideCursor();
}
+void information(docstring const & title0, docstring const & message)
+{
+#ifdef EXPORT_in_THREAD
+ InGuiThread<void>().call(&doInformation,
+#else
+ doInformation(
+#endif
+ title0, message);
+}
-bool askForText(docstring & response, docstring const & msg,
+bool doAskForText(docstring & response, docstring const & msg,
docstring const & dflt)
{
if (!use_gui || lyxerr.debugging()) {
return false;
}
+bool askForText(docstring & response, docstring const & msg,
+ docstring const & dflt)
+{
+#ifdef EXPORT_in_THREAD
+ return InGuiThread<bool>().call(&doAskForText,
+#else
+ return doAskGForText(
+#endif
+ response, msg, dflt);
+}
} // namespace Alert
} // namespace frontend
--- /dev/null
+/**
+ * \file InGuiThread.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Peter Kümmel
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include "InGuiThread.h"
+
+#include <QThread>
+#include <QEventLoop>
+#include <QApplication>
+
+namespace lyx {
+namespace frontend {
+
+
+IntoGuiThreadMover::IntoGuiThreadMover()
+{
+ moveToThread(QApplication::instance()->thread());
+ connect(this, SIGNAL(triggerCall()), this, SLOT(doFunctionCall()),
+ Qt::QueuedConnection);
+}
+
+
+void IntoGuiThreadMover::callInGuiThread()
+{
+ if (QThread::currentThread() == QApplication::instance()->thread()) {
+ synchronousFunctionCall();
+ } else {
+ QEventLoop loop;
+ connect(this, SIGNAL(called()), &loop, SLOT(quit()));
+ Q_EMIT triggerCall();
+ loop.exec();
+ }
+}
+
+
+void IntoGuiThreadMover::doFunctionCall()
+{
+ synchronousFunctionCall();
+ Q_EMIT called();
+}
+
+
+} // namespace frontend
+} // namespace lyx
+
+
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file InGuiThread.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Peter Kümmel
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef INGUITHREAD_H
+#define INGUITHREAD_H
+
+#include <QObject>
+
+#include "support/bind.h"
+#include "support/functional.h"
+
+namespace lyx {
+namespace frontend {
+
+
+class IntoGuiThreadMover : public QObject
+{
+ Q_OBJECT
+
+protected:
+
+ IntoGuiThreadMover();
+
+ void callInGuiThread();
+
+Q_SIGNALS:
+ void triggerCall();
+ void called();
+
+private Q_SLOTS:
+ void doFunctionCall();
+
+private:
+ virtual void synchronousFunctionCall() = 0;
+};
+
+
+template<class R>
+class InGuiThread : private IntoGuiThreadMover
+{
+public:
+
+ InGuiThread() {}
+
+ template<class F>
+ R call(F f)
+ {
+ func_ = f;
+ callInGuiThread();
+ return return_value_;
+ }
+
+ template<class F, class P1>
+ R call(F f, P1 p1)
+ {
+ return call(bind(f, p1));
+ }
+
+ template<class F, class P1, class P2>
+ R call(F f, P1 p1, P2 p2)
+ {
+ return call(bind(f, p1, p2));
+ }
+
+ template<class F, class P1, class P2, class P3>
+ R call(F f, P1 p1, P2 p2, P3 p3)
+ {
+ return call(bind(f, p1, p2, p3));
+ }
+
+ template<class F, class P1, class P2, class P3, class P4>
+ R call(F f, P1 p1, P2 p2, P3 p3, P4 p4)
+ {
+ return call(bind(f, p1, p2, p3, p4));
+ }
+
+ /*
+ ...
+ */
+
+ template<class F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ R call(F f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
+ {
+ return call(bind(f, p1, p2, p3, p4, p5, p6, p7, p8));
+ }
+
+private:
+
+ void synchronousFunctionCall()
+ {
+ return_value_ = func_();
+ }
+
+private:
+ R return_value_;
+ function<R()> func_;
+};
+
+
+// void specialisation
+template<>
+class InGuiThread<void> : private IntoGuiThreadMover
+{
+public:
+
+ InGuiThread() {}
+
+ template<class F>
+ void call(F f)
+ {
+ func_ = f;
+ callInGuiThread();
+ }
+
+ template<class F, class P1>
+ void call(F f, P1 p1)
+ {
+ call(bind(f, p1));
+ }
+
+ template<class F, class P1, class P2>
+ void call(F f, P1 p1, P2 p2)
+ {
+ call(bind(f, p1, p2));
+ }
+
+ template<class F, class P1, class P2, class P3>
+ void call(F f, P1 p1, P2 p2, P3 p3)
+ {
+ call(bind(f, p1, p2, p3));
+ }
+
+ template<class F, class P1, class P2, class P3, class P4>
+ void call(F f, P1 p1, P2 p2, P3 p3, P4 p4)
+ {
+ call(bind(f, p1, p2, p3, p4));
+ }
+
+ /*
+ ...
+ */
+
+ template<class F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ void call(F f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
+ {
+ call(bind(f, p1, p2, p3, p4, p5, p6, p7, p8));
+ }
+
+private:
+
+ void synchronousFunctionCall()
+ {
+ func_();
+ }
+
+private:
+ function<void()> func_;
+};
+
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // GUIABOUT_H
foreach.h \
ForkedCalls.cpp \
ForkedCalls.h \
+ functional.h \
gettext.cpp \
gettext.h \
gzstream.cpp \
gzstream.h \
+ InGuiThread.h \
+ InGuiThread.cpp \
kill.cpp \
lassert.h \
lassert.cpp \
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file functional.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Peter Kümmel
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef LYX_FUNCTIONAL_H
+#define LYX_FUNCTIONAL_H
+
+#ifdef LYX_USE_TR1
+
+#include <functional>
+
+#ifdef __GNUC__
+#include <tr1/functional>
+#endif
+
+namespace lyx
+{
+ using std::tr1::function;
+}
+
+#else
+
+#include <boost/function.hpp>
+#include <boost/functional.hpp>
+
+namespace lyx
+{
+ using boost::function;
+}
+
+#endif
+
+
+#endif