]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/InGuiThread.h
On Linux show in crash message box the backtrace
[lyx.git] / src / frontends / qt4 / InGuiThread.h
1 // -*- C++ -*-
2 /**
3  * \file InGuiThread.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Peter Kümmel
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef INGUITHREAD_H
13 #define INGUITHREAD_H
14
15 #include <QMutex>
16 #include <QObject>
17 #include <QWaitCondition>
18
19 #include "support/bind.h"
20 #include "support/functional.h"
21
22 namespace lyx {
23 namespace frontend {
24
25
26 class IntoGuiThreadMover : public QObject
27 {
28         Q_OBJECT
29
30 protected:
31
32         IntoGuiThreadMover();
33
34         void callInGuiThread();
35
36 Q_SIGNALS:
37         void triggerFunctionCall();
38
39 private Q_SLOTS:
40         void doFunctionCall();
41
42 private:
43         virtual void synchronousFunctionCall() = 0;
44
45         QWaitCondition condition_;
46         QMutex sync_mutex_;
47 };
48
49
50 template<class R>
51 class InGuiThread : private IntoGuiThreadMover
52 {
53 public:
54
55         InGuiThread() {}
56
57         template<class F>
58         R call(F f)
59         {
60                 func_ = f;
61                 callInGuiThread();
62                 return return_value_;
63         }
64
65         template<class F, class P1>
66         R call(F f, P1& p1)
67         {
68                 return call(lyx::bind(f, lyx::ref(p1)));
69         }
70
71         template<class F, class P1, class P2>
72         R call(F f, P1& p1, P2& p2)
73         {
74                 return call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2)));
75         }
76
77         template<class F, class P1, class P2, class P3>
78         R call(F f, P1& p1, P2& p2, P3& p3)
79         {
80                 return call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3)));
81         }
82
83         template<class F, class P1, class P2, class P3, class P4>
84         R call(F f, P1& p1, P2& p2, P3& p3, P4& p4)
85         {
86                 return call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3), lyx::ref(p4)));
87         }
88
89         /*
90           ...
91         */
92
93         template<class F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
94         R call(F f, P1& p1, P2& p2, P3& p3, P4& p4, P5& p5, P6& p6, P7& p7, P8& p8)
95         {
96                 return call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3), lyx::ref(p4), 
97                         lyx::ref(p5), lyx::ref(p6), lyx::ref(p7), lyx::ref(p8)));
98         }
99
100 private:
101
102         void synchronousFunctionCall()
103         {
104                 return_value_ = func_();
105         }
106
107 private:
108         R return_value_;
109         function<R()> func_;
110 };
111
112
113 // void specialisation
114 template<>
115 class InGuiThread<void> : private IntoGuiThreadMover
116 {
117 public:
118
119         InGuiThread() {}
120
121         template<class F>
122         void call(F f)
123         {
124                 func_ = f;
125                 callInGuiThread();
126         }
127
128         template<class F, class P1>
129         void call(F f, P1& p1)
130         {
131                 call(lyx::bind(f, lyx::ref(p1)));
132         }
133
134         template<class F, class P1, class P2>
135         void call(F f, P1& p1, P2& p2)
136         {
137                 call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2)));
138         }
139
140         template<class F, class P1, class P2, class P3>
141         void call(F f, P1& p1, P2& p2, P3& p3)
142         {
143                 call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3)));
144         }
145
146         template<class F, class P1, class P2, class P3, class P4>
147         void call(F f, P1& p1, P2& p2, P3& p3, P4& p4)
148         {
149                 call(lyx::bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3), lyx::ref(p4)));
150         }
151
152         /*
153           ...
154         */
155
156         template<class F, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
157         void call(F f, P1& p1, P2& p2, P3& p3, P4& p4, P5& p5, P6& p6, P7& p7, P8& p8)
158         {
159                 call(bind(f, lyx::ref(p1), lyx::ref(p2), lyx::ref(p3), lyx::ref(p4), lyx::ref(p5),
160                         lyx::ref(p6), lyx::ref(p7), lyx::ref(p8)));
161         }
162
163 private:
164
165         void synchronousFunctionCall()
166         {
167                 func_();
168         }
169
170 private:
171         function<void()> func_;
172 };
173
174
175 } // namespace frontend
176 } // namespace lyx
177
178 #endif // INGUITHREAD_H