FreeCADGuiPy.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
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 // FreeCAD Base header
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); // special DeferredDelete
00078     return CallNextHookEx(hhook, nCode, wParam, lParam);
00079 }
00080 #endif
00081 
00082 static PyObject *
00083 FreeCADGui_showMainWindow(PyObject * /*self*/, 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         // When QApplication is constructed
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 * /*self*/, 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 * /*self*/, 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         // init the Inventor subsystem
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 * /*self*/, 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     //SetWindowLong(widget->winId(), GWL_STYLE,
00197     //    WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
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}  /* sentinel */
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             // init the Inventor subsystem
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         // Activate the correct workbench
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         // if the auto workbench is not visible then force to use the default workbech
00281         // and replace the wrong entry in the parameters
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 

Generated on Wed Nov 23 19:00:15 2011 for FreeCAD by  doxygen 1.6.1