]> git.lyx.org Git - features.git/commitdiff
add generic helper class for calling functions in gui thread
authorPeter Kümmel <syntheticpp@gmx.net>
Wed, 20 Oct 2010 23:50:49 +0000 (23:50 +0000)
committerPeter Kümmel <syntheticpp@gmx.net>
Wed, 20 Oct 2010 23:50:49 +0000 (23:50 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@35735 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/qt4/GuiAlert.cpp
src/support/InGuiThread.cpp [new file with mode: 0644]
src/support/InGuiThread.h [new file with mode: 0644]
src/support/Makefile.am
src/support/functional.h [new file with mode: 0644]

index 70bca4151e83df79e3eb8161710f0b1c6a990f26..e04b301e59968a0beae58f16a8cb3c49b8695e99 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "alert.h"
 
-
 #include "frontends/Application.h"
 
 #include "qt_helpers.h"
@@ -25,6 +24,7 @@
 #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;
 
@@ -124,7 +129,8 @@ void noAppDialog(QString const & title, QString const & msg, QMessageBox::Icon m
 
 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)
@@ -178,8 +184,21 @@ int prompt(docstring const & title0, docstring const & question,
        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'
@@ -213,8 +232,18 @@ void warning(docstring const & title0, docstring const & message,
        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"
@@ -240,8 +269,17 @@ void error(docstring const & title0, docstring const & message)
        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'
@@ -268,8 +306,17 @@ void information(docstring const & title0, docstring const & message)
        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()) {
@@ -300,6 +347,16 @@ bool askForText(docstring & response, docstring const & msg,
        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
diff --git a/src/support/InGuiThread.cpp b/src/support/InGuiThread.cpp
new file mode 100644 (file)
index 0000000..2ffbc7e
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * \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
+
+
diff --git a/src/support/InGuiThread.h b/src/support/InGuiThread.h
new file mode 100644 (file)
index 0000000..6d3b778
--- /dev/null
@@ -0,0 +1,172 @@
+// -*- 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
index 31993949fb50e54710b12a8fa59a91c94b45d42c..a60554dafd62dbc9906c7c3577bea4a46ef639d8 100644 (file)
@@ -56,10 +56,13 @@ liblyxsupport_a_SOURCES = \
        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 \
diff --git a/src/support/functional.h b/src/support/functional.h
new file mode 100644 (file)
index 0000000..47d9c45
--- /dev/null
@@ -0,0 +1,41 @@
+// -*- 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