/* * pykcm_launcher.cpp * * Launch Control Centre modules written in Python using an embedded Python * interpreter. * Based on David Boddie's PyKDE-components. */ // pythonize.h must be included first. #include #include #include #include #include #include #include #include #include #define MODULE_DIR "/opt/trinity/share/apps/guidance" #define EXTRA_MODULE_DIR "/opt/trinity/share/python-support/tde-guidance-trinity" #define EXTRA_MODULE_DIR_TWO "/opt/trinity/share/python-support/guidance-backends-trinity" #define EXTRA_MODULE_DIR_THREE "/opt/trinity/share/python-support/tde-guidance-powermanager-trinity" #define MODULE_NAME "wineconfig" #define FACTORY "create_wineconfig" #define CPP_FACTORY create_wineconfig #define LIB_PYTHON "libpython2.5.so" #define debug 1 static KCModule *report_error(char *msg) { if (debug) printf ("error: %s\n", msg); return NULL; } static KCModule* return_instance( QWidget *parent, const char *name ) { KCModule* kcmodule; PyObject *pyKCModuleTuple; PyObject *pyKCModule; Pythonize *pyize; // Pythonize object to manage the Python interpreter. int isErr; // Try to determine what py script we're loading. Note that "name" // typically appears to be NULL. QString script(MODULE_NAME); // Reload libpython, but this time tell the runtime linker to make the // symbols global and available for later loaded libraries/module. KLibLoader::self()->globalLibrary(LIB_PYTHON); // Start the interpreter. pyize = initialize(); if (!pyize) { return report_error ("***Failed to start interpreter\n"); } // Add the path to the python script to the interpreter search path. QString path = QString(MODULE_DIR); if(path == QString::null) { return report_error ("***Failed to locate script path"); } if(!pyize->appendToSysPath (path.latin1 ())) { return report_error ("***Failed to set sys.path\n"); } QString extrapath = QString(EXTRA_MODULE_DIR); if(!pyize->appendToSysPath (extrapath.latin1 ())) { return report_error ("***Failed to set extra sys.path\n"); } QString extrapath_two = QString(EXTRA_MODULE_DIR_TWO); if(!pyize->appendToSysPath (extrapath_two.latin1 ())) { return report_error ("***Failed to set extra 2 sys.path\n"); } QString extrapath_three = QString(EXTRA_MODULE_DIR_THREE); if(!pyize->appendToSysPath (extrapath_three.latin1 ())) { return report_error ("***Failed to set extra 3 sys.path\n"); } // Load the Python script. PyObject *pyModule = pyize->importModule ((char *)script.latin1 ()); if(!pyModule) { PyErr_Print(); return report_error ("***failed to import module\n"); } // Inject a helper function QString bridge = QString("import sip\n" "import qt\n" "def kcontrol_bridge_" FACTORY "(parent,name):\n" " if parent!=0:\n" #if SIP_VERSION >= 0x040200 " wparent = sip.wrapinstance(parent,qt.QWidget)\n" #else " wparent = sip.wrapinstance(parent,'QWidget')\n" #endif " else:\n" " wparent = None\n" " inst = " FACTORY "(wparent, name)\n" " return (inst,sip.unwrapinstance(inst))\n"); PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule)); // Get the Python module's factory function. PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY); if(!kcmFactory) { return report_error ("***failed to find module factory\n"); } // Call the factory function. Set up the args. PyObject *pyParent = PyLong_FromVoidPtr(parent); PyObject *pyName = PyString_FromString(MODULE_NAME); // Using NN here is effect gives our references to the arguement away. PyObject *args = Py_BuildValue ("NN", pyParent, pyName); if(pyName && pyParent && args) { // run the factory function pyKCModuleTuple = pyize->runFunction(kcmFactory, args); if(!pyKCModuleTuple) { PyErr_Print(); return report_error ("*** runFunction failure\n;"); } } else { return report_error ("***failed to create args\n"); } // cleanup a bit pyize->decref(args); pyize->decref(kcmFactory); // Stop this from getting garbage collected. Py_INCREF(PyTuple_GET_ITEM(pyKCModuleTuple,0)); // convert the KCModule PyObject to a real C++ KCModule *. isErr = 0; pyKCModule = PyTuple_GET_ITEM(pyKCModuleTuple,1); kcmodule = (KCModule *)PyLong_AsVoidPtr(pyKCModule); if(!kcmodule) { return report_error ("***failed sip conversion to C++ pointer\n"); } pyize->decref(pyKCModuleTuple); // PyKDE can't run the module without this - Pythonize // grabs the lock at initialization and we have to give // it back before exiting. At this point, we no longer need // it. //pyize->releaseLock (); // take care of any translation info TDEGlobal::locale()->insertCatalogue(script); // Return the pointer to our new KCModule return kcmodule; } extern "C" { // Factory function that kcontrol will call. KCModule* CPP_FACTORY(QWidget *parent, const char *name) { return return_instance(parent, name); } }