00001
00014 #ifdef HAVE_CONFIG_H
00015
00016 #include "config.h"
00017 #endif
00018
00019 #ifdef _MSC_VER
00020 #include "msdevstudio/MSconfig.h"
00021 #include <windows.h>
00022 #endif
00023
00024
00025
00026
00027 #include <boost/python.hpp>
00028
00029 #include "PyApp.h"
00030
00031 #include "PyCanvas.h"
00032
00033 #ifdef HAVE_QT_APP
00034 #include "qt/CanvasWindow.h"
00035 #include "qt/HdThread.h"
00036 #include "qt/QtApp.h"
00037 #include "qt/WindowController.h"
00038 #include "qapplication.h"
00039 #include "qwaitcondition.h"
00040 #endif
00041
00042 #ifndef _MSC_VER
00043 #include <pthread.h>
00044 #endif
00045 using namespace boost::python;
00046
00047 namespace hippodraw {
00048 namespace Python {
00049
00050 void
00051 export_HDApp()
00052 {
00053 class_ < PyApp > ( "HDApp",
00054 "The HippoDraw application class.\n" )
00055
00056 .def ( init < int >
00057 ( "HDApp () -> HDApp\n"
00058 "HDApp ( value ) -> HDApp\n"
00059 "\n"
00060 "Using the constructor with no arguments creates\n"
00061 "a HippoDraw application that runs in a separate\n"
00062 "thread.\n"
00063 "Using the constructor with one argument creates\n"
00064 "a HippoDraw application in same thread. Use\n"
00065 "app.exec_loop() to start it." ) )
00066
00067 .def ( init < char * >
00068 ("HDapp ( string ) -> HDapp" ) )
00069
00070 .def ( "instance", &PyApp::instance,
00071 return_value_policy < reference_existing_object > (),
00072 "instance () -> HDApp\n"
00073 "\n"
00074 "Returns a singleton instance of the HippoDraw \n"
00075 "application object" )
00076
00077 .staticmethod ( "instance" )
00078
00079 .def ( "canvas", &PyApp::currentCanvas,
00080 return_value_policy < reference_existing_object > (),
00081 "canvas () -> Canvas\n"
00082 "\n"
00083 "Returns the current canvas window." )
00084
00085 .def ( "exec_loop", &PyApp::exec,
00086 "exec_loop () -> value\n"
00087 "\n"
00088 "Starts the application object. Returns the value returned\n"
00089 "by the application object upon exiting." )
00090
00091 .def ( "quit", &PyApp::quit,
00092 "quit () -> None\n"
00093 "\n"
00094 "Closes all Canvas windows and Terminates the application." )
00095
00096 .def ( "quitOnLastWindowClose", &PyApp::quitOnLastWindowClose,
00097 "quitOnLastWindowClose ( Boolean ) -> None\n"
00098 "\n"
00099 "If argument is True, allows application to quit when last\n"
00100 "Canvas is closed." )
00101
00102 .def ( "hasTerminated", &PyApp::hasTerminated,
00103 "hasTerminated () -> Boolean\n"
00104 "\n"
00105 "Returns True if the application has terminated." )
00106
00107 .def ( "openDocument", &PyApp::openDocument,
00108 "openDocument ( string ) -> None\n"
00109 "\n"
00110 "Opens new canvas window from saved document file." )
00111
00112 .def ( "lock", &PyApp::lock,
00113 "lock () -> None\n"
00114 "\n"
00115 "Lock the Qt library Mutex. Will not return until no\n"
00116 "other thread has the lock." )
00117
00118 .def ( "unlock", &PyApp::unlock,
00119 "unlock () -> None\n"
00120 "\n"
00121 "Unlocks the application thread." )
00122
00123 ;
00124 }
00125
00126 }
00127 }
00128
00129 using namespace hippodraw;
00130
00131 PyApp * PyApp::s_instance = 0;
00132 QtApp * PyApp::s_app = 0;
00133
00134 void *
00135 run ( void * arg )
00136 {
00137 #ifdef HAVE_QT_APP
00138 static int argc = 1;
00139 static char * argv[1];
00140 argv[0] = const_cast< char * > ( "Python" );
00141
00142 QtApp app ( argc, argv );
00143 app.setFirstWindow ();
00144 app.exec ();
00145 #endif // have qt app
00146 return 0;
00147 }
00148
00149
00153 PyApp::PyApp ( )
00154 {
00155 #if QT_VERSION < 0x040200
00156
00157 #if HAVE_QT_APP
00158 m_thread = new HdThread ( );
00159 m_thread->start ();
00160
00161
00162
00163
00164 while ( QtApp::startingUp () == true ) {
00165 m_thread->wait ( 100 );
00166 }
00167 s_app = QtApp::instance ();
00168
00169 #ifdef _MSC_VER
00170
00171
00172 while ( s_app->currentCanvas () == 0 ) {
00173 m_thread->wait ( 100 );
00174 }
00175 #else
00176
00177
00178 while ( s_app->hasPendingEvents () == true ) {
00179 m_thread->wait ( 100 );
00180 }
00181 #endif
00182
00183 while ( s_app->currentCanvas () == 0 ) {
00184 m_thread->wait ( 100 );
00185 }
00186
00187 #else // no qt app
00188 s_app = 0;
00189 #endif // have qt app
00190 #else // qt 4.2 or later
00191 pthread_t * thread = ( pthread_t * ) malloc ( sizeof ( pthread_t ) );
00192 if ( !thread ) {
00193 perror ( "Malloc of thread failed" );
00194 }
00195 if ( pthread_create ( thread, NULL, run, ( void * ) 0 ) ) {
00196 perror ( "Failed to create thread");
00197 }
00198 #ifdef HAVE_QT_APP
00199 while ( QtApp::startingUp() == true ) {
00200 sleep ( 1 );
00201 }
00202 s_app = QtApp::instance ();
00203 #endif // have qt app
00204 #endif // qt 4.2
00205
00206 s_instance = this;
00207 }
00208
00209
00210 PyApp::PyApp ( char * script )
00211 {
00212 #ifndef _MSC_VER
00213 pthread_t * thread = ( pthread_t * ) malloc ( sizeof ( pthread_t ) );
00214 if ( !thread ) {
00215 perror ( "Malloc of thread failed" );
00216 }
00217 if ( pthread_create ( thread, NULL, run, ( void * ) 0 ) ) {
00218 perror ( "Failed to create thread");
00219 }
00220 #ifdef HAVE_QT_APP
00221 while ( QtApp::startingUp() == true ) {
00222 sleep ( 1 );
00223 }
00224 s_app = QtApp::instance ();
00225 #endif
00226 #endif
00227 }
00228
00229
00230 PyApp::PyApp ( int )
00231 {
00232 #ifdef HAVE_QT_APP
00233 static int argc = 1;
00234 static char * argv[1];
00235 argv[0] = const_cast < char * > ( "/HippoDraw" );
00236
00237 s_app = new QtApp ( argc, argv, true );
00238 #else
00239 s_app = 0;
00240 #endif
00241 }
00242
00243 PyApp::~PyApp ( )
00244 {
00245
00246 s_instance = 0;
00247 }
00248
00249 PyApp * PyApp::instance ()
00250 {
00251 if ( s_instance == 0 ) {
00252 s_instance = new PyApp ();
00253 }
00254
00255 return s_instance;
00256 }
00257
00258 int PyApp::exec ()
00259 {
00260 #ifdef HAVE_QT_APP
00261 return s_app->exec();
00262 #else
00263 return 0;
00264 #endif
00265 }
00266
00267 bool
00268 PyApp::
00269 hasTerminated () const
00270 {
00271 #ifdef HAVE_QT_APP
00272 return QApplication::closingDown ();
00273 #else
00274 return true;
00275 #endif
00276 }
00277
00278 void
00279 PyApp::
00280 quit ()
00281 {
00282 #ifdef HAVE_QT_APP
00283 s_app -> closeAllWindows ();
00284 #endif
00285 }
00286
00287 PyCanvas * PyApp::currentCanvas ()
00288 {
00289 #ifdef HAVE_QT_APP
00290 PyCanvas * pycanvas = 0;
00291
00292 #if QT_VERSION < 0x040000
00293 if ( m_thread -> running() ) {
00294 PyApp::lock();
00295 #else
00296
00297 #endif
00298 CanvasWindow * canvas = s_app->currentCanvas();
00299 while ( canvas == 0 ) {
00300 #ifdef _MSC_VER
00301 Sleep ( 1000000 );
00302 #else
00303 sleep (1);
00304 #endif
00305 canvas = s_app-> currentCanvas();
00306 }
00307
00308 pycanvas = new PyCanvas ( canvas );
00309 #if QT_VERSION < 0x040000
00310 PyApp::unlock ();
00311 }
00312 #endif
00313 return pycanvas;
00314 #else
00315 return 0;
00316 #endif
00317 }
00318
00319 void PyApp::openDocument ( const std::string & filename )
00320 {
00321 #ifdef HAVE_QT_APP
00322 PyApp::lock();
00323
00324 CanvasWindow * window = new CanvasWindow ();
00325 window -> initFromFile ( filename );
00326
00327 PyApp::unlock ();
00328 #endif
00329 }
00330
00331 void PyApp::lock ()
00332 {
00333 #if QT_VERSION < 0x040000
00334 #ifdef HAVE_QT_APP
00335 if ( s_app != 0 && QApplication::closingDown () == false ) {
00336
00337
00338 s_app->lock ();
00339 }
00340 #endif
00341 #endif
00342 }
00343
00344 bool PyApp::locked ()
00345 {
00346 bool yes = false;
00347 #if QT_VERSION < 0x040000
00348 #ifdef HAVE_QT_APP
00349 if ( s_app != 0 && QApplication::closingDown () == false ) {
00350 yes = s_app->locked ();
00351 }
00352 #endif
00353 #endif
00354 return yes;
00355 }
00356
00357 void PyApp::unlock ()
00358 {
00359 #if QT_VERSION < 0x040000
00360 #ifdef HAVE_QT_APP
00361 if ( s_app != 0 && QApplication::closingDown () == false ) {
00362 s_app->unlock ();
00363 }
00364 #endif
00365 #endif
00366 }
00367
00368 bool
00369 PyApp::
00370 hasPendingEvents ()
00371 {
00372 bool yes = false;
00373 #ifdef HAVE_QT_APP
00374 if ( s_app != 0 && QApplication::closingDown () == false ) {
00375 yes = s_app -> hasPendingEvents ();
00376 }
00377 #endif
00378 return yes;
00379 }
00380
00381 void
00382 PyApp::
00383 quitOnLastWindowClose ( bool yes )
00384 {
00385 #ifdef HAVE_QT_APP
00386 WindowController * controller = WindowController::instance ();
00387
00388 controller -> quitOnLastWindowClose ( yes );
00389 #endif
00390 }