00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <FCConfig.h>
00025
00026 #if HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif // HAVE_CONFIG_H
00029
00030 #include <Python.h>
00031 #include <QApplication>
00032 #include <QIcon>
00033 #include <QThread>
00034 #include <Inventor/Qt/SoQt.h>
00035 #if defined(Q_OS_WIN)
00036 #include <windows.h>
00037 #elif defined(Q_WS_X11)
00038 #include <QX11EmbedWidget>
00039 #endif
00040
00041 #include <Base/Exception.h>
00042 #include <Base/Factory.h>
00043 #include <Base/Interpreter.h>
00044 #include <App/Application.h>
00045 #include <Gui/Application.h>
00046 #include <Gui/BitmapFactory.h>
00047 #include <Gui/MainWindow.h>
00048 #include <Gui/SoFCDB.h>
00049
00050
00051 static
00052 QWidget* setupMainWindow();
00053
00054 class GUIThread : public QThread
00055 {
00056 public:
00057 GUIThread()
00058 {
00059 }
00060 void run()
00061 {
00062 int argc = 0;
00063 char **argv = {0};
00064 QApplication app(argc, argv);
00065 if (setupMainWindow()) {
00066 app.exec();
00067 }
00068 }
00069 };
00070
00071 #if defined(Q_OS_WIN)
00072 HHOOK hhook;
00073
00074 LRESULT CALLBACK
00075 FilterProc(int nCode, WPARAM wParam, LPARAM lParam) {
00076 if (qApp)
00077 qApp->sendPostedEvents(0, -1);
00078 return CallNextHookEx(hhook, nCode, wParam, lParam);
00079 }
00080 #endif
00081
00082 static PyObject *
00083 FreeCADGui_showMainWindow(PyObject * , PyObject *args)
00084 {
00085 if (!PyArg_ParseTuple(args, ""))
00086 return NULL;
00087
00088 static GUIThread* thr = 0;
00089 if (!qApp) {
00090 #if 0
00091 if (!thr) thr = new GUIThread();
00092 thr->start();
00093 #elif defined(Q_OS_WIN)
00094 static int argc = 0;
00095 static char **argv = {0};
00096 (void)new QApplication(argc, argv);
00097
00098 hhook = SetWindowsHookEx(WH_GETMESSAGE,
00099 FilterProc, 0, GetCurrentThreadId());
00100 #elif !defined(QT_NO_GLIB)
00101 static int argc = 0;
00102 static char **argv = {0};
00103 (void)new QApplication(argc, argv);
00104 #else
00105 PyErr_SetString(PyExc_RuntimeError, "Must construct a QApplication before a QPaintDevice\n");
00106 return NULL;
00107 #endif
00108 }
00109 else if (!qobject_cast<QApplication*>(qApp)) {
00110 PyErr_SetString(PyExc_RuntimeError, "Cannot create widget when no GUI is being used\n");
00111 return NULL;
00112 }
00113
00114 if (!thr) {
00115 if (!setupMainWindow())
00116 return NULL;
00117 }
00118
00119 Py_INCREF(Py_None);
00120 return Py_None;
00121 }
00122
00123 static PyObject *
00124 FreeCADGui_exec_loop(PyObject * , PyObject *args)
00125 {
00126 if (!PyArg_ParseTuple(args, ""))
00127 return NULL;
00128
00129 if (!qApp) {
00130 PyErr_SetString(PyExc_RuntimeError, "Must construct a QApplication before a QPaintDevice\n");
00131 return NULL;
00132 }
00133 else if (!qobject_cast<QApplication*>(qApp)) {
00134 PyErr_SetString(PyExc_RuntimeError, "Cannot create widget when no GUI is being used\n");
00135 return NULL;
00136 }
00137
00138 qApp->exec();
00139
00140 Py_INCREF(Py_None);
00141 return Py_None;
00142 }
00143
00144 static PyObject *
00145 FreeCADGui_setupWithoutGUI(PyObject * , PyObject *args)
00146 {
00147 if (!PyArg_ParseTuple(args, ""))
00148 return NULL;
00149
00150 if (!Gui::Application::Instance) {
00151 static Gui::Application *app = new Gui::Application(false);
00152 Q_UNUSED(app);
00153 }
00154 else {
00155 PyErr_SetString(PyExc_RuntimeError, "FreeCADGui already initialized");
00156 return 0;
00157 }
00158
00159 if (!SoDB::isInitialized()) {
00160
00161 SoDB::init();
00162 SoQt::init("FreeCAD");
00163 }
00164 if (!Gui::SoFCDB::isInitialized()) {
00165 Gui::SoFCDB::init();
00166 }
00167
00168 Py_INCREF(Py_None);
00169 return Py_None;
00170 }
00171
00172 static PyObject *
00173 FreeCADGui_embedToWindow(PyObject * , PyObject *args)
00174 {
00175 char* pointer;
00176 if (!PyArg_ParseTuple(args, "s", &pointer))
00177 return NULL;
00178
00179 QWidget* widget = Gui::getMainWindow();
00180 if (!widget) {
00181 PyErr_SetString(PyExc_Exception, "No main window");
00182 return 0;
00183 }
00184
00185 std::string pointer_str = pointer;
00186 std::stringstream str(pointer_str);
00187
00188 #if defined(Q_OS_WIN)
00189 void* window = 0;
00190 str >> window;
00191 WId winid = (WId)window;
00192
00193 LONG oldLong = GetWindowLong(winid, GWL_STYLE);
00194 SetWindowLong(winid, GWL_STYLE,
00195 oldLong | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
00196
00197
00198 SetParent(widget->winId(), winid);
00199
00200 QEvent embeddingEvent(QEvent::EmbeddingControl);
00201 QApplication::sendEvent(widget, &embeddingEvent);
00202 #elif defined(Q_WS_X11)
00203 WId winid;
00204 str >> winid;
00205
00206 QX11EmbedWidget* x11 = new QX11EmbedWidget();
00207 widget->setParent(x11);
00208 x11->embedInto(winid);
00209 x11->show();
00210 #else
00211 PyErr_SetString(PyExc_NotImplementedError, "Not implemented for this platform");
00212 return 0;
00213 #endif
00214
00215 Py_INCREF(Py_None);
00216 return Py_None;
00217 }
00218
00219 struct PyMethodDef FreeCADGui_methods[] = {
00220 {"showMainWindow",FreeCADGui_showMainWindow,METH_VARARGS,
00221 "showMainWindow() -- Show the main window\n"
00222 "If no main window does exist one gets created"},
00223 {"exec_loop",FreeCADGui_exec_loop,METH_VARARGS,
00224 "exec_loop() -- Starts the event loop\n"
00225 "Note: this will block the call until the event loop has terminated"},
00226 {"setupWithoutGUI",FreeCADGui_setupWithoutGUI,METH_VARARGS,
00227 "setupWithoutGUI() -- Uses this module without starting\n"
00228 "an event loop or showing up any GUI\n"},
00229 {"embedToWindow",FreeCADGui_embedToWindow,METH_VARARGS,
00230 "embedToWindow() -- Embeds the main window into another window\n"},
00231 {NULL, NULL}
00232 };
00233
00234 static
00235 QWidget* setupMainWindow()
00236 {
00237 if (!Gui::Application::Instance) {
00238 static Gui::Application *app = new Gui::Application(true);
00239 Q_UNUSED(app);
00240 }
00241
00242 if (!Gui::MainWindow::getInstance()) {
00243 Gui::MainWindow *mw = new Gui::MainWindow();
00244 QIcon icon = qApp->windowIcon();
00245 if (icon.isNull())
00246 qApp->setWindowIcon(Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str()));
00247 mw->setWindowIcon(qApp->windowIcon());
00248 QString appName = qApp->applicationName();
00249 if (!appName.isEmpty())
00250 mw->setWindowTitle(appName);
00251 else
00252 mw->setWindowTitle(QString::fromAscii(App::Application::Config()["ExeName"].c_str()));
00253
00254 if (!SoDB::isInitialized()) {
00255
00256 SoDB::init();
00257 SoQt::init(mw);
00258 Gui::SoFCDB::init();
00259 }
00260
00261 static bool init = false;
00262 if (!init) {
00263 try {
00264 Base::Interpreter().runString(Base::ScriptFactory().ProduceScript("FreeCADGuiInit"));
00265 }
00266 catch (const Base::Exception& e) {
00267 PyErr_Format(PyExc_Exception, "Error in FreeCADGuiInit.py: %s\n", e.what());
00268 return 0;
00269 }
00270 init = true;
00271 }
00272
00273 qApp->setActiveWindow(mw);
00274
00275
00276 std::string start = App::Application::Config()["StartWorkbench"];
00277 Base::Console().Log("Init: Activating default workbench %s\n", start.c_str());
00278 start = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
00279 GetASCII("AutoloadModule", start.c_str());
00280
00281
00282 QStringList wb = Gui::Application::Instance->workbenches();
00283 if (!wb.contains(QString::fromAscii(start.c_str()))) {
00284 start = App::Application::Config()["StartWorkbench"];
00285 App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
00286 SetASCII("AutoloadModule", start.c_str());
00287 }
00288
00289 Gui::Application::Instance->activateWorkbench(start.c_str());
00290 mw->loadWindowSettings();
00291 }
00292 else {
00293 Gui::getMainWindow()->show();
00294 }
00295
00296 return Gui::getMainWindow();
00297 }
00298
00299 PyMODINIT_FUNC initFreeCADGui()
00300 {
00301 try {
00302 Base::Interpreter().loadModule("FreeCAD");
00303 App::Application::Config()["AppIcon"] = "freecad";
00304 App::Application::Config()["SplashPicture"] = "freecadsplash";
00305 App::Application::Config()["ConsoleBanner"] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2001-2011\n";
00306 Gui::Application::initApplication();
00307 Py_InitModule("FreeCADGui", FreeCADGui_methods);
00308 }
00309 catch (const Base::Exception& e) {
00310 PyErr_Format(PyExc_ImportError, "%s\n", e.what());
00311 }
00312 catch (...) {
00313 PyErr_SetString(PyExc_ImportError, "Unknown runtime error occurred");
00314 }
00315 }
00316