PyApp.cxx
Go to the documentation of this file.
1 
14 #ifdef HAVE_CONFIG_H
15 // for have qt app
16 #include "config.h"
17 #endif
18 
19 #ifdef _MSC_VER
20 #include "msdevstudio/MSconfig.h"
21 #include <windows.h>
22 #endif
23 
24 // with Python 2.3, include before Qt headers to avoid conflict
25 // with symbol `slots'
26 // include first to avoid _POSIX_C_SOURCE warning.
27 #include <boost/python.hpp>
28 
29 #include "PyApp.h"
30 
31 #include "PyCanvas.h"
32 
33 #ifdef HAVE_QT_APP
34 #include "qt/CanvasWindow.h"
35 #include "qt/HdThread.h"
36 #include "qt/QtApp.h"
37 #include "qt/WindowController.h"
38 #include "qapplication.h"
39 #include "qwaitcondition.h"
40 #endif
41 
42 #ifndef _MSC_VER
43 #include <pthread.h>
44 #endif
45 using namespace boost::python;
46 
47 namespace hippodraw {
48 namespace Python {
49 
50 void
52 {
53  class_ < PyApp > ( "HDApp",
54  "The HippoDraw application class.\n" )
55 
56  .def ( init < int >
57  ( "HDApp () -> HDApp\n"
58  "HDApp ( value ) -> HDApp\n"
59  "\n"
60  "Using the constructor with no arguments creates\n"
61  "a HippoDraw application that runs in a separate\n"
62  "thread.\n"
63  "Using the constructor with one argument creates\n"
64  "a HippoDraw application in same thread. Use\n"
65  "app.exec_loop() to start it." ) )
66 
67  .def ( init < char * >
68  ("HDapp ( string ) -> HDapp" ) )
69 
70  .def ( "instance", &PyApp::instance,
71  return_value_policy < reference_existing_object > (),
72  "instance () -> HDApp\n"
73  "\n"
74  "Returns a singleton instance of the HippoDraw \n"
75  "application object" )
76 
77  .staticmethod ( "instance" )
78 
79  .def ( "canvas", &PyApp::currentCanvas,
80  return_value_policy < reference_existing_object > (),
81  "canvas () -> Canvas\n"
82  "\n"
83  "Returns the current canvas window." )
84 
85  .def ( "exec_loop", &PyApp::exec,
86  "exec_loop () -> value\n"
87  "\n"
88  "Starts the application object. Returns the value returned\n"
89  "by the application object upon exiting." )
90 
91  .def ( "quit", &PyApp::quit,
92  "quit () -> None\n"
93  "\n"
94  "Closes all Canvas windows and Terminates the application." )
95 
96  .def ( "quitOnLastWindowClose", &PyApp::quitOnLastWindowClose,
97  "quitOnLastWindowClose ( Boolean ) -> None\n"
98  "\n"
99  "If argument is True, allows application to quit when last\n"
100  "Canvas is closed." )
101 
102  .def ( "hasTerminated", &PyApp::hasTerminated,
103  "hasTerminated () -> Boolean\n"
104  "\n"
105  "Returns True if the application has terminated." )
106 
107  .def ( "openDocument", &PyApp::openDocument,
108  "openDocument ( string ) -> None\n"
109  "\n"
110  "Opens new canvas window from saved document file." )
111 
112  .def ( "lock", &PyApp::lock,
113  "lock () -> None\n"
114  "\n"
115  "Lock the Qt library Mutex. Will not return until no\n"
116  "other thread has the lock." )
117 
118  .def ( "unlock", &PyApp::unlock,
119  "unlock () -> None\n"
120  "\n"
121  "Unlocks the application thread." )
122 
123  ;
124 }
125 
126 } // namesapce Python
127 } // namespace hippodraw
128 
129 using namespace hippodraw;
130 
131 PyApp * PyApp::s_instance = 0;
132 QtApp * PyApp::s_app = 0;
133 
134 void *
135 run ( void * arg )
136 {
137 #ifdef HAVE_QT_APP
138  static int argc = 1;
139  static char * argv[1];
140  argv[0] = const_cast< char * > ( "Python" );
141 
142  QtApp app ( argc, argv );
143  app.setFirstWindow ();
144  app.exec ();
145 #endif // have qt app
146  return 0;
147 }
148 
149 
153 PyApp::PyApp ( )
154 {
155 #if QT_VERSION < 0x040200
156 
157 #if HAVE_QT_APP
158  m_thread = new HdThread ( );
159  m_thread->start ();
160 
161  // Wait for application to initialize itself. It is not sufficient
162  // to wait just for the thread to run as it may cause segmentation
163  // fault when we try to use the application.
164  while ( QtApp::startingUp () == true ) {
165  m_thread->wait ( 100 ); // wait for thread to run
166  }
167  s_app = QtApp::instance ();
168 
169 #ifdef _MSC_VER
170  // The following works under Windows, but under Linux leads to
171  // occasional X Windows async errors
172  while ( s_app->currentCanvas () == 0 ) {
173  m_thread->wait ( 100 ); // wait for thread to create first window
174  }
175 #else
176  // The following seems to work better for Linux but not at all for
177  // Windows ...
178  while ( s_app->hasPendingEvents () == true ) {
179  m_thread->wait ( 100 );
180  }
181 #endif
182 
183  while ( s_app->currentCanvas () == 0 ) {
184  m_thread->wait ( 100 ); // wait for thread to create first window
185  }
186 
187 #else // no qt app
188  s_app = 0;
189 #endif // have qt app
190 #else // qt 4.2 or later
191  pthread_t * thread = ( pthread_t * ) malloc ( sizeof ( pthread_t ) );
192  if ( !thread ) {
193  perror ( "Malloc of thread failed" );
194  }
195  if ( pthread_create ( thread, NULL, run, ( void * ) 0 ) ) {
196  perror ( "Failed to create thread");
197  }
198 #ifdef HAVE_QT_APP
199  while ( QtApp::startingUp() == true ) {
200  sleep ( 1 );
201  }
202  s_app = QtApp::instance ();
203 #endif // have qt app
204 #endif // qt 4.2
205 
206  s_instance = this;
207 }
208 
209 
210 PyApp::PyApp ( char * script )
211 {
212 #ifndef _MSC_VER
213  pthread_t * thread = ( pthread_t * ) malloc ( sizeof ( pthread_t ) );
214  if ( !thread ) {
215  perror ( "Malloc of thread failed" );
216  }
217  if ( pthread_create ( thread, NULL, run, ( void * ) 0 ) ) {
218  perror ( "Failed to create thread");
219  }
220 #ifdef HAVE_QT_APP
221  while ( QtApp::startingUp() == true ) {
222  sleep ( 1 );
223  }
224  s_app = QtApp::instance ();
225 #endif
226 #endif
227 }
228 
229 
230 PyApp::PyApp ( int ) // parameter only used to make unique function
231 {
232 #ifdef HAVE_QT_APP
233  static int argc = 1;
234  static char * argv[1];
235  argv[0] = const_cast < char * > ( "/HippoDraw" );
236 
237  s_app = new QtApp ( argc, argv, true );
238 #else
239  s_app = 0;
240 #endif
241 }
242 
243 PyApp::~PyApp ( )
244 {
245  // Nothing to delete
246  s_instance = 0;
247 }
248 
249 PyApp * PyApp::instance ()
250 {
251  if ( s_instance == 0 ) {
252  s_instance = new PyApp ();
253  }
254 
255  return s_instance;
256 }
257 
258 int PyApp::exec ()
259 {
260 #ifdef HAVE_QT_APP
261  return s_app->exec();
262 #else
263  return 0;
264 #endif
265 }
266 
267 bool
268 PyApp::
269 hasTerminated () const
270 {
271 #ifdef HAVE_QT_APP
272  return QApplication::closingDown ();
273 #else
274  return true;
275 #endif
276 }
277 
278 void
279 PyApp::
280 quit ()
281 {
282 #ifdef HAVE_QT_APP
283  s_app -> closeAllWindows ();
284 #endif
285 }
286 
287 PyCanvas * PyApp::currentCanvas ()
288 {
289 #ifdef HAVE_QT_APP
290  PyCanvas * pycanvas = 0;
291 
292 #if QT_VERSION < 0x040000
293  if ( m_thread -> running() ) {
294  PyApp::lock();
295 #else
296 // if ( m_thread -> isRunning () ) {
297 #endif
298  CanvasWindow * canvas = s_app->currentCanvas();
299  while ( canvas == 0 ) {
300 #ifdef _MSC_VER
301  Sleep ( 1000000 ); // milliseconds
302 #else
303  sleep (1);
304 #endif
305  canvas = s_app-> currentCanvas();
306  }
307 
308  pycanvas = new PyCanvas ( canvas );
309 #if QT_VERSION < 0x040000
310  PyApp::unlock ();
311  }
312 #endif
313  return pycanvas;
314 #else
315  return 0;
316 #endif
317 }
318 
319 void PyApp::openDocument ( const std::string & filename )
320 {
321 #ifdef HAVE_QT_APP
322  PyApp::lock(); // definitely need it else documents.py crashes
323 
324  CanvasWindow * window = new CanvasWindow ();
325  window -> initFromFile ( filename );
326 
327  PyApp::unlock ();
328 #endif
329 }
330 
331 void PyApp::lock ()
332 {
333 #if QT_VERSION < 0x040000
334 #ifdef HAVE_QT_APP
335  if ( s_app != 0 && QApplication::closingDown () == false ) {
336 // while ( PyApp::hasPendingEvents () ) {}
337 
338  s_app->lock ();
339  }
340 #endif
341 #endif
342 }
343 
344 bool PyApp::locked ()
345 {
346  bool yes = false;
347 #if QT_VERSION < 0x040000
348 #ifdef HAVE_QT_APP
349  if ( s_app != 0 && QApplication::closingDown () == false ) {
350  yes = s_app->locked ();
351  }
352 #endif
353 #endif
354  return yes;
355 }
356 
357 void PyApp::unlock ()
358 {
359 #if QT_VERSION < 0x040000
360 #ifdef HAVE_QT_APP
361  if ( s_app != 0 && QApplication::closingDown () == false ) {
362  s_app->unlock ();
363  }
364 #endif
365 #endif
366 }
367 
368 bool
369 PyApp::
370 hasPendingEvents ()
371 {
372  bool yes = false;
373 #ifdef HAVE_QT_APP
374  if ( s_app != 0 && QApplication::closingDown () == false ) {
375  yes = s_app -> hasPendingEvents ();
376  }
377 #endif
378  return yes;
379 }
380 
381 void
382 PyApp::
383 quitOnLastWindowClose ( bool yes )
384 {
385 #ifdef HAVE_QT_APP
386  WindowController * controller = WindowController::instance ();
387 
388  controller -> quitOnLastWindowClose ( yes );
389 #endif
390 }

Generated for HippoDraw Class Library by doxygen