PyApp.cxx

Go to the documentation of this file.
00001 
00014 #ifdef HAVE_CONFIG_H
00015 // for have qt app
00016 #include "config.h"
00017 #endif
00018 
00019 #ifdef _MSC_VER
00020 #include "msdevstudio/MSconfig.h"
00021 #include <windows.h>
00022 #endif
00023 
00024 // with Python 2.3, include before Qt headers to avoid conflict
00025 // with symbol `slots'
00026 // include first to avoid _POSIX_C_SOURCE warning.
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 } // namesapce Python
00127 } // namespace hippodraw
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   // Wait for application to initialize itself.  It is not sufficient
00162   // to wait just for the thread to run as it may cause segmentation
00163   // fault when we try to use the application.
00164   while ( QtApp::startingUp () == true  ) {
00165     m_thread->wait ( 100 ); // wait for thread to run
00166   }
00167   s_app = QtApp::instance ();
00168 
00169 #ifdef _MSC_VER
00170   // The following works under Windows, but under Linux leads to
00171   // occasional X Windows async errors
00172   while ( s_app->currentCanvas () == 0 ) {
00173     m_thread->wait ( 100 ); // wait for thread to create first window
00174   }
00175 #else
00176   // The following seems to work better for Linux but not at all for
00177   // Windows ...
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 ); // wait for thread to create first window
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 ) // parameter only used to make unique function
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   // Nothing to delete
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 //   if ( m_thread -> isRunning () ) {
00297 #endif
00298     CanvasWindow * canvas = s_app->currentCanvas();
00299     while ( canvas == 0 ) {
00300 #ifdef _MSC_VER
00301         Sleep ( 1000000 ); // milliseconds
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(); // definitely need it else documents.py crashes
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 //     while ( PyApp::hasPendingEvents () ) {}
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 }

Generated for HippoDraw Class Library by doxygen