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 "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include "InventorAll.h"
00028 # include <boost/signals.hpp>
00029 # include <boost/bind.hpp>
00030 # include <sstream>
00031 # include <stdexcept>
00032 # include <QCloseEvent>
00033 # include <QLocale>
00034 # include <QMessageBox>
00035 # include <QPointer>
00036 # include <QGLFormat>
00037 # include <QGLPixelBuffer>
00038 #if QT_VERSION >= 0x040200
00039 # include <QGLFramebufferObject>
00040 #endif
00041 # include <QSessionManager>
00042 #endif
00043
00044
00045
00046 #include <Base/Console.h>
00047 #include <Base/Interpreter.h>
00048 #include <Base/Parameter.h>
00049 #include <Base/Exception.h>
00050 #include <Base/Factory.h>
00051 #include <Base/FileInfo.h>
00052 #include <Base/Tools.h>
00053 #include <App/Document.h>
00054 #include <App/DocumentObjectPy.h>
00055
00056 #include "Application.h"
00057 #include "GuiApplicationNativeEventAware.h"
00058 #include "MainWindow.h"
00059 #include "Document.h"
00060 #include "View.h"
00061 #include "View3DPy.h"
00062 #include "WidgetFactory.h"
00063 #include "Command.h"
00064 #include "Macro.h"
00065 #include "ProgressBar.h"
00066 #include "Workbench.h"
00067 #include "WorkbenchManager.h"
00068 #include "ToolBoxManager.h"
00069 #include "WaitCursor.h"
00070 #include "MenuManager.h"
00071 #include "Window.h"
00072 #include "Selection.h"
00073 #include "BitmapFactory.h"
00074 #include "SoFCDB.h"
00075 #include "PythonConsolePy.h"
00076 #include "PythonDebugger.h"
00077 #include "View3DPy.h"
00078 #include "DlgOnlineHelpImp.h"
00079 #include "SpaceballEvent.h"
00080
00081 #include "View3DInventor.h"
00082 #include "ViewProvider.h"
00083 #include "ViewProviderExtern.h"
00084 #include "ViewProviderFeature.h"
00085 #include "ViewProviderPythonFeature.h"
00086 #include "ViewProviderDocumentObjectGroup.h"
00087 #include "ViewProviderGeometryObject.h"
00088 #include "ViewProviderInventorObject.h"
00089 #include "ViewProviderVRMLObject.h"
00090 #include "ViewProviderAnnotation.h"
00091 #include "ViewProviderMeasureDistance.h"
00092
00093 #include "Language/Translator.h"
00094 #include "TaskView/TaskDialogPython.h"
00095 #include "GuiInitScript.h"
00096
00097
00098 using namespace Gui;
00099 using namespace Gui::DockWnd;
00100 using namespace std;
00101
00102
00103 Application* Application::Instance = 0L;
00104
00105 namespace Gui {
00106
00107
00108 struct ApplicationP
00109 {
00110 ApplicationP() :
00111 activeDocument(0L),
00112 isClosing(false),
00113 startingUp(true)
00114 {
00115
00116 macroMngr = new MacroManager();
00117 }
00118
00119 ~ApplicationP()
00120 {
00121 delete macroMngr;
00122 }
00123
00125 std::map<const App::Document*, Gui::Document*> documents;
00127 Gui::Document* activeDocument;
00128 MacroManager* macroMngr;
00130 std::list<Gui::BaseView*> passive;
00131 bool isClosing;
00132 bool startingUp;
00134 CommandManager commandManager;
00135 };
00136
00143 class ObjectLabelObserver
00144 {
00145 public:
00147 static ObjectLabelObserver* instance();
00149 static void destruct ();
00150
00154 void slotRelabelObject(const App::DocumentObject&, const App::Property&);
00155
00156 private:
00157 static ObjectLabelObserver* _singleton;
00158
00159 ObjectLabelObserver();
00160 ~ObjectLabelObserver();
00161 const App::DocumentObject* current;
00162 ParameterGrp::handle _hPGrp;
00163 };
00164
00165 ObjectLabelObserver* ObjectLabelObserver::_singleton = 0;
00166
00167 ObjectLabelObserver* ObjectLabelObserver::instance()
00168 {
00169 if (!_singleton)
00170 _singleton = new ObjectLabelObserver;
00171 return _singleton;
00172 }
00173
00174 void ObjectLabelObserver::destruct ()
00175 {
00176 delete _singleton;
00177 _singleton = 0;
00178 }
00179
00180 void ObjectLabelObserver::slotRelabelObject(const App::DocumentObject& obj, const App::Property& prop)
00181 {
00182
00183 if (&prop == &obj.Label) {
00184
00185 if (current) {
00186 return;
00187 }
00188
00189 std::string label = obj.Label.getValue();
00190 App::Document* doc = obj.getDocument();
00191 if (doc && !_hPGrp->GetBool("DuplicateLabels")) {
00192 std::vector<std::string> objectLabels;
00193 std::vector<App::DocumentObject*>::const_iterator it;
00194 std::vector<App::DocumentObject*> objs = doc->getObjects();
00195 bool match = false;
00196
00197 for (it = objs.begin();it != objs.end();++it) {
00198 if (*it == &obj)
00199 continue;
00200 std::string objLabel = (*it)->Label.getValue();
00201 if (!match && objLabel == label)
00202 match = true;
00203 objectLabels.push_back(objLabel);
00204 }
00205
00206
00207 if (match) {
00208
00209 size_t lastpos = label.length()-1;
00210 while (label[lastpos] >= 48 && label[lastpos] <= 57)
00211 lastpos--;
00212 label = label.substr(0, lastpos+1);
00213 label = Base::Tools::getUniqueName(label, objectLabels, 3);
00214 this->current = &obj;
00215 const_cast<App::DocumentObject&>(obj).Label.setValue(label);
00216 this->current = 0;
00217 }
00218 }
00219 }
00220 }
00221
00222 ObjectLabelObserver::ObjectLabelObserver() : current(0)
00223 {
00224 App::GetApplication().signalChangedObject.connect(boost::bind
00225 (&ObjectLabelObserver::slotRelabelObject, this, _1, _2));
00226 _hPGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp");
00227 _hPGrp = _hPGrp->GetGroup("Preferences")->GetGroup("Document");
00228 }
00229
00230 ObjectLabelObserver::~ObjectLabelObserver()
00231 {
00232 }
00233
00234 static PyObject *
00235 FreeCADGui_subgraphFromObject(PyObject * , PyObject *args)
00236 {
00237 PyObject *o;
00238 if (!PyArg_ParseTuple(args, "O!",&(App::DocumentObjectPy::Type), &o))
00239 return NULL;
00240 App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(o)->getDocumentObjectPtr();
00241 std::string vp = obj->getViewProviderName();
00242 SoNode* node = 0;
00243 try {
00244 Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(vp.c_str(), true));
00245 if (base && base->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) {
00246 std::auto_ptr<Gui::ViewProviderDocumentObject> vp(static_cast<Gui::ViewProviderDocumentObject*>(base));
00247 std::map<std::string, App::Property*> Map;
00248 obj->getPropertyMap(Map);
00249 vp->attach(obj);
00250 for (std::map<std::string, App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it) {
00251 vp->updateData(it->second);
00252 }
00253
00254 std::vector<std::string> modes = vp->getDisplayModes();
00255 if (!modes.empty())
00256 vp->setDisplayMode(modes.front().c_str());
00257 node = vp->getRoot()->copy();
00258 node->ref();
00259 std::string type = "So";
00260 type += node->getTypeId().getName().getString();
00261 type += " *";
00262 PyObject* proxy = 0;
00263 proxy = Base::Interpreter().createSWIGPointerObj("pivy.coin", type.c_str(), (void*)node, 1);
00264 return Py::new_reference_to(Py::Object(proxy, true));
00265 }
00266 }
00267 catch (const Base::Exception& e) {
00268 if (node) node->unref();
00269 PyErr_SetString(PyExc_RuntimeError, e.what());
00270 return 0;
00271 }
00272
00273 Py_INCREF(Py_None);
00274 return Py_None;
00275 }
00276
00277 static PyObject *
00278 FreeCADGui_getSoDBVersion(PyObject * , PyObject *args)
00279 {
00280 if (!PyArg_ParseTuple(args, ""))
00281 return NULL;
00282 return PyString_FromString(SoDB::getVersion());
00283 }
00284
00285 static PyObject *
00286 FreeCADGui_getSoQtVersion(PyObject * , PyObject *args)
00287 {
00288 if (!PyArg_ParseTuple(args, ""))
00289 return NULL;
00290 return PyString_FromString(SoQt::getVersionString());
00291 }
00292
00293 struct PyMethodDef FreeCADGui_methods[] = {
00294 {"subgraphFromObject",FreeCADGui_subgraphFromObject,METH_VARARGS,
00295 "subgraphFromObject(object) -> Node\n\n"
00296 "Return the Inventor subgraph to an object"},
00297 {"getSoDBVersion",FreeCADGui_getSoDBVersion,METH_VARARGS,
00298 "getSoDBVersion() -> String\n\n"
00299 "Return a text string containing the name\n"
00300 "of the Coin library and version information"},
00301 {"getSoQtVersion",FreeCADGui_getSoQtVersion,METH_VARARGS,
00302 "getSoQtVersion() -> String\n\n"
00303 "Return a text string containing the name\n"
00304 "of the SoQt library and version information"},
00305 {NULL, NULL}
00306 };
00307
00308 }
00309
00310 Application::Application(bool GUIenabled)
00311 {
00312
00313 if (GUIenabled) {
00314 App::GetApplication().signalNewDocument.connect(boost::bind(&Gui::Application::slotNewDocument, this, _1));
00315 App::GetApplication().signalDeleteDocument.connect(boost::bind(&Gui::Application::slotDeleteDocument, this, _1));
00316 App::GetApplication().signalRenameDocument.connect(boost::bind(&Gui::Application::slotRenameDocument, this, _1));
00317 App::GetApplication().signalActiveDocument.connect(boost::bind(&Gui::Application::slotActiveDocument, this, _1));
00318 App::GetApplication().signalRelabelDocument.connect(boost::bind(&Gui::Application::slotRelabelDocument, this, _1));
00319
00320
00321
00322 ParameterGrp::handle hPGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp");
00323 hPGrp = hPGrp->GetGroup("Preferences")->GetGroup("General");
00324 QString lang = QLocale::languageToString(QLocale::system().language());
00325 Translator::instance()->activateLanguage(hPGrp->GetASCII("Language", (const char*)lang.toAscii()).c_str());
00326 GetWidgetFactorySupplier();
00327
00328
00329 Base::PyGILStateLocker lock;
00330 PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods,
00331 "The functions in the FreeCADGui module allow working with GUI documents,\n"
00332 "view providers, views, workbenches and much more.\n\n"
00333 "The FreeCADGui instance provides a list of references of GUI documents which\n"
00334 "can be addressed by a string. These documents contain the view providers for\n"
00335 "objects in the associated App document. An App and GUI document can be\n"
00336 "accessed with the same name.\n\n"
00337 "The FreeCADGui module also provides a set of functions to work with so called\n"
00338 "workbenches.");
00339 Py::Module(module).setAttr(std::string("ActiveDocument"),Py::None());
00340
00341
00342 PyObject* pSelectionModule = Py_InitModule3("Selection", SelectionSingleton::Methods,
00343 "Selection module");
00344 Py_INCREF(pSelectionModule);
00345 PyModule_AddObject(module, "Selection", pSelectionModule);
00346
00347 SelectionFilterPy::init_type();
00348 Base::Interpreter().addType(SelectionFilterPy::type_object(),
00349 pSelectionModule,"Filter");
00350
00351 Gui::TaskView::ControlPy::init_type();
00352 Py::Module(module).setAttr(std::string("Control"),
00353 Py::Object(Gui::TaskView::ControlPy::getInstance(), true));
00354 }
00355
00356 Base::PyGILStateLocker lock;
00357 PyObject *module = PyImport_AddModule("FreeCADGui");
00358 PyMethodDef *meth = FreeCADGui_methods;
00359 PyObject *dict = PyModule_GetDict(module);
00360 for (; meth->ml_name != NULL; meth++) {
00361 PyObject *descr;
00362 descr = PyCFunction_NewEx(meth,0,0);
00363 if (descr == NULL)
00364 break;
00365 if (PyDict_SetItemString(dict, meth->ml_name, descr) != 0)
00366 break;
00367 Py_DECREF(descr);
00368 }
00369
00370
00371 PythonDebugModule ::init_module();
00372 PythonStdout ::init_type();
00373 PythonStderr ::init_type();
00374 OutputStdout ::init_type();
00375 OutputStderr ::init_type();
00376 PythonStdin ::init_type();
00377 View3DInventorPy ::init_type();
00378
00379 d = new ApplicationP;
00380
00381
00382 Instance = this;
00383
00384
00385 _pcWorkbenchDictionary = PyDict_New();
00386
00387 createStandardOperations();
00388 MacroCommand::load();
00389 ObjectLabelObserver::instance();
00390 }
00391
00392 Application::~Application()
00393 {
00394 Base::Console().Log("Destruct Gui::Application\n");
00395 WorkbenchManager::destruct();
00396 SelectionSingleton::destruct();
00397 Translator::destruct();
00398 WidgetFactorySupplier::destruct();
00399 BitmapFactoryInst::destruct();
00400
00401 #if 0
00402
00403
00404 Base::Interpreter().cleanupSWIG("SoBase *");
00405
00406 SoFCDB::finish();
00407 SoQt::done();
00408
00409 #if (COIN_MAJOR_VERSION >= 2) && (COIN_MINOR_VERSION >= 4)
00410 SoDB::finish();
00411 #elif (COIN_MAJOR_VERSION >= 3)
00412 SoDB::finish();
00413 #else
00414 SoDB::cleanup();
00415 #endif
00416 #endif
00417 {
00418 Base::PyGILStateLocker lock;
00419 Py_DECREF(_pcWorkbenchDictionary);
00420 }
00421
00422
00423 MacroCommand::save();
00424
00425
00426 delete d;
00427 Instance = 0;
00428 }
00429
00430
00431
00432
00433
00434
00435 void Application::open(const char* FileName, const char* Module)
00436 {
00437 WaitCursor wc;
00438 Base::FileInfo File(FileName);
00439 string te = File.extension();
00440
00441
00442
00443 App::Document* act = App::GetApplication().getActiveDocument();
00444 Gui::Document* gui = this->getDocument(act);
00445 if (act && act->countObjects() == 0 && gui && gui->isModified() == false){
00446 Command::doCommand(Command::App, "App.closeDocument('%s')", act->getName());
00447 qApp->processEvents();
00448 }
00449
00450 if (Module != 0) {
00451
00452 Command::doCommand(Command::App, "import %s", Module);
00453 try {
00454
00455 Command::doCommand(Command::App, "%s.open(\"%s\")", Module, File.filePath().c_str());
00456
00457 if (!File.hasExtension("FCStd") && sendHasMsgToActiveView("ViewFit"))
00458
00459 Command::doCommand(Command::Gui, "Gui.SendMsgToActiveView(\"ViewFit\")");
00460
00461 getMainWindow()->appendRecentFile(QString::fromUtf8(File.filePath().c_str()));
00462 }
00463 catch (const Base::PyException& e){
00464
00465 e.ReportException();
00466 }
00467 }
00468 else {
00469 wc.restoreCursor();
00470 QMessageBox::warning(getMainWindow(), QObject::tr("Unknown filetype"),
00471 QObject::tr("Cannot open unknown filetype: %1").arg(QLatin1String(te.c_str())));
00472 wc.setWaitCursor();
00473 return;
00474 }
00475 }
00476
00477 void Application::importFrom(const char* FileName, const char* DocName, const char* Module)
00478 {
00479 WaitCursor wc;
00480 Base::FileInfo File(FileName);
00481 std::string te = File.extension();
00482
00483 if (Module != 0) {
00484
00485 Command::doCommand(Command::App, "import %s", Module);
00486
00487 try {
00488
00489 if (File.hasExtension("FCStd")) {
00490 Command::doCommand(Command::App, "%s.open(\"%s\")"
00491 , Module, File.filePath().c_str());
00492 if (activeDocument())
00493 activeDocument()->setModified(false);
00494 }
00495 else {
00496 Command::doCommand(Command::App, "%s.insert(\"%s\",\"%s\")"
00497 , Module, File.filePath().c_str(), DocName);
00498 Command::doCommand(Command::Gui, "Gui.SendMsgToActiveView(\"ViewFit\")");
00499 if (getDocument(DocName))
00500 getDocument(DocName)->setModified(true);
00501 }
00502
00503
00504 getMainWindow()->appendRecentFile(QString::fromUtf8(File.filePath().c_str()));
00505 }
00506 catch (const Base::PyException& e){
00507
00508 e.ReportException();
00509 }
00510 }
00511 else {
00512 wc.restoreCursor();
00513 QMessageBox::warning(getMainWindow(), QObject::tr("Unknown filetype"),
00514 QObject::tr("Cannot open unknown filetype: %1").arg(QLatin1String(te.c_str())));
00515 wc.setWaitCursor();
00516 }
00517 }
00518
00519 void Application::exportTo(const char* FileName, const char* DocName, const char* Module)
00520 {
00521 WaitCursor wc;
00522 Base::FileInfo File(FileName);
00523 std::string te = File.extension();
00524
00525 if (Module != 0) {
00526 try {
00527 std::vector<App::DocumentObject*> sel = Gui::Selection().getObjectsOfType
00528 (App::DocumentObject::getClassTypeId(),DocName);
00529 if (sel.empty()) {
00530 App::Document* doc = App::GetApplication().getDocument(DocName);
00531 sel = doc->getObjectsOfType(App::DocumentObject::getClassTypeId());
00532 }
00533
00534 std::stringstream str;
00535 str << "__objs__=[]" << std::endl;
00536 for (std::vector<App::DocumentObject*>::iterator it = sel.begin(); it != sel.end(); ++it) {
00537 str << "__objs__.append(FreeCAD.getDocument(\"" << DocName << "\").getObject(\""
00538 << (*it)->getNameInDocument() << "\"))" << std::endl;
00539 }
00540
00541 str << "import " << Module << std::endl;
00542 str << Module << ".export(__objs__,\"" << File.filePath() << "\")" << std::endl;
00543 str << "del __objs__" << std::endl;
00544
00545 std::string code = str.str();
00546
00547 if (runPythonCode(code.c_str(), false))
00548 getMainWindow()->appendRecentFile(QString::fromUtf8(File.filePath().c_str()));
00549 }
00550 catch (const Base::PyException& e){
00551
00552 e.ReportException();
00553 }
00554 }
00555 else {
00556 wc.restoreCursor();
00557 QMessageBox::warning(getMainWindow(), QObject::tr("Unknown filetype"),
00558 QObject::tr("Cannot save to unknown filetype: %1").arg(QLatin1String(te.c_str())));
00559 wc.setWaitCursor();
00560 }
00561 }
00562
00563 void Application::createStandardOperations()
00564 {
00565
00566 Gui::CreateStdCommands();
00567 Gui::CreateDocCommands();
00568 Gui::CreateFeatCommands();
00569 Gui::CreateMacroCommands();
00570 Gui::CreateViewStdCommands();
00571 Gui::CreateWindowStdCommands();
00572 Gui::CreateTestCommands();
00573 }
00574
00575 void Application::slotNewDocument(const App::Document& Doc)
00576 {
00577 #ifdef FC_DEBUG
00578 std::map<const App::Document*, Gui::Document*>::const_iterator it = d->documents.find(&Doc);
00579 assert(it==d->documents.end());
00580 #endif
00581 Gui::Document* pDoc = new Gui::Document(const_cast<App::Document*>(&Doc),this);
00582 d->documents[&Doc] = pDoc;
00583
00584
00585 pDoc->signalNewObject.connect(boost::bind(&Gui::Application::slotNewObject, this, _1));
00586 pDoc->signalDeletedObject.connect(boost::bind(&Gui::Application::slotDeletedObject, this, _1));
00587 pDoc->signalChangedObject.connect(boost::bind(&Gui::Application::slotChangedObject, this, _1, _2));
00588 pDoc->signalRenamedObject.connect(boost::bind(&Gui::Application::slotRenamedObject, this, _1));
00589 pDoc->signalActivatedObject.connect(boost::bind(&Gui::Application::slotActivatedObject, this, _1));
00590
00591
00592 signalNewDocument(*pDoc);
00593 pDoc->createView("View3DIv");
00594 qApp->processEvents();
00595 }
00596
00597 void Application::slotDeleteDocument(const App::Document& Doc)
00598 {
00599 std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
00600 if (doc == d->documents.end()) {
00601 Base::Console().Log("GUI document '%s' already deleted\n", Doc.getName());
00602 return;
00603 }
00604
00605
00606 Gui::Selection().clearSelection(doc->second->getDocument()->getName());
00607 signalDeleteDocument(*doc->second);
00608
00609
00610
00611 if (d->activeDocument == doc->second)
00612 setActiveDocument(0);
00613
00614
00615 auto_ptr<Document> delDoc (doc->second);
00616 d->documents.erase(doc);
00617 }
00618
00619 void Application::slotRelabelDocument(const App::Document& Doc)
00620 {
00621 std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
00622 #ifdef FC_DEBUG
00623 assert(doc!=d->documents.end());
00624 #endif
00625
00626 signalRelabelDocument(*doc->second);
00627 doc->second->onRelabel();
00628 }
00629
00630 void Application::slotRenameDocument(const App::Document& Doc)
00631 {
00632 std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
00633 #ifdef FC_DEBUG
00634 assert(doc!=d->documents.end());
00635 #endif
00636
00637 signalRenameDocument(*doc->second);
00638 }
00639
00640 void Application::slotActiveDocument(const App::Document& Doc)
00641 {
00642 std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
00643
00644 if (doc != d->documents.end())
00645 signalActiveDocument(*doc->second);
00646 }
00647
00648 void Application::slotNewObject(const ViewProvider& vp)
00649 {
00650 this->signalNewObject(vp);
00651 }
00652
00653 void Application::slotDeletedObject(const ViewProvider& vp)
00654 {
00655 this->signalDeletedObject(vp);
00656 }
00657
00658 void Application::slotChangedObject(const ViewProvider& vp, const App::Property& prop)
00659 {
00660 this->signalChangedObject(vp,prop);
00661 }
00662
00663 void Application::slotRenamedObject(const ViewProvider& vp)
00664 {
00665 this->signalRenamedObject(vp);
00666 }
00667
00668 void Application::slotActivatedObject(const ViewProvider& vp)
00669 {
00670 this->signalActivatedObject(vp);
00671 }
00672
00673 void Application::onLastWindowClosed(Gui::Document* pcDoc)
00674 {
00675 if (!d->isClosing && pcDoc) {
00676 try {
00677
00678 Command::doCommand(Command::Doc, "App.closeDocument(\"%s\")", pcDoc->getDocument()->getName());
00679 }
00680 catch (const Base::PyException& e) {
00681 e.ReportException();
00682 }
00683 }
00684 }
00685
00687 bool Application::sendMsgToActiveView(const char* pMsg, const char** ppReturn)
00688 {
00689 MDIView* pView = getMainWindow()->activeWindow();
00690 return pView ? pView->onMsg(pMsg,ppReturn) : false;
00691 }
00692
00693 bool Application::sendHasMsgToActiveView(const char* pMsg)
00694 {
00695 MDIView* pView = getMainWindow()->activeWindow();
00696 return pView ? pView->onHasMsg(pMsg) : false;
00697 }
00698
00700 Gui::Document* Application::activeDocument(void) const
00701 {
00702 return d->activeDocument;
00703 }
00704
00705 void Application::setActiveDocument(Gui::Document* pcDocument)
00706 {
00707 if (d->activeDocument == pcDocument)
00708 return;
00709 d->activeDocument = pcDocument;
00710 std::string name;
00711
00712
00713 if (pcDocument){
00714 name += "App.setActiveDocument(\"";
00715 name += pcDocument->getDocument()->getName();
00716 name += "\")\n";
00717 name += "App.ActiveDocument=App.getDocument(\"";
00718 name += pcDocument->getDocument()->getName();
00719 name += "\")\n";
00720 name += "Gui.ActiveDocument=Gui.getDocument(\"";
00721 name += pcDocument->getDocument()->getName();
00722 name += "\")";
00723 macroManager()->addLine(MacroManager::Gui,name.c_str());
00724 }
00725 else {
00726 name += "App.setActiveDocument(\"\")\n";
00727 name += "App.ActiveDocument=None\n";
00728 name += "Gui.ActiveDocument=None";
00729 macroManager()->addLine(MacroManager::Gui,name.c_str());
00730 }
00731
00732
00733 try {
00734 Base::Interpreter().runString(name.c_str());
00735 }
00736 catch (const Base::Exception& e) {
00737 Base::Console().Warning(e.what());
00738 return;
00739 }
00740
00741
00742 if (d->activeDocument) {
00743 App::Document* doc = d->activeDocument->getDocument();
00744 Base::Console().Log("Active document is %s (at %p)\n",doc->getName(), doc);
00745 }
00746 else {
00747 Base::Console().Log("No active document\n");
00748 }
00749
00750
00751 for(list<Gui::BaseView*>::iterator It=d->passive.begin();It!=d->passive.end();It++)
00752 (*It)->setDocument(pcDocument);
00753 }
00754
00755 Gui::Document* Application::getDocument(const char* name) const
00756 {
00757 App::Document* pDoc = App::GetApplication().getDocument( name );
00758 std::map<const App::Document*, Gui::Document*>::const_iterator it = d->documents.find(pDoc);
00759 if ( it!=d->documents.end() )
00760 return it->second;
00761 else
00762 return 0;
00763 }
00764
00765 Gui::Document* Application::getDocument(const App::Document* pDoc) const
00766 {
00767 std::map<const App::Document*, Gui::Document*>::const_iterator it = d->documents.find(pDoc);
00768 if ( it!=d->documents.end() )
00769 return it->second;
00770 else
00771 return 0;
00772 }
00773
00774 void Application::showViewProvider(App::DocumentObject* obj)
00775 {
00776 ViewProvider* vp = getViewProvider(obj);
00777 if (vp) vp->show();
00778 }
00779
00780 void Application::hideViewProvider(App::DocumentObject* obj)
00781 {
00782 ViewProvider* vp = getViewProvider(obj);
00783 if (vp) vp->hide();
00784 }
00785
00786 Gui::ViewProvider* Application::getViewProvider(App::DocumentObject* obj) const
00787 {
00788 App::Document* doc = obj->getDocument();
00789 if (doc) {
00790 Gui::Document* gui = getDocument(doc);
00791 if (gui) {
00792 ViewProvider* vp = gui->getViewProvider(obj);
00793 return vp;
00794 }
00795 }
00796
00797 return 0;
00798 }
00799
00800 void Application::attachView(Gui::BaseView* pcView)
00801 {
00802 d->passive.push_back(pcView);
00803 }
00804
00805 void Application::detachView(Gui::BaseView* pcView)
00806 {
00807 d->passive.remove(pcView);
00808 }
00809
00810 void Application::onUpdate(void)
00811 {
00812
00813 std::map<const App::Document*, Gui::Document*>::iterator It;
00814 for (It = d->documents.begin();It != d->documents.end();It++)
00815 It->second->onUpdate();
00816
00817 for (std::list<Gui::BaseView*>::iterator It2 = d->passive.begin();It2 != d->passive.end();It2++)
00818 (*It2)->onUpdate();
00819 }
00820
00822 void Application::viewActivated(MDIView* pcView)
00823 {
00824
00825 Base::Console().Log("Active view is %s (at %p)\n",
00826 (const char*)pcView->windowTitle().toUtf8(),pcView);
00827
00828 signalActivateView(pcView);
00829
00830
00831
00832
00833 if (!pcView->isPassive())
00834 setActiveDocument(pcView->getGuiDocument());
00835 }
00836
00837
00838 void Application::updateActive(void)
00839 {
00840 activeDocument()->onUpdate();
00841 }
00842
00843 void Application::tryClose(QCloseEvent * e)
00844 {
00845 if (d->documents.size() == 0) {
00846 e->accept();
00847 }
00848 else {
00849
00850 std::map<const App::Document*, Gui::Document*>::iterator It;
00851 for (It = d->documents.begin();It!=d->documents.end();It++) {
00852 MDIView* active = It->second->getActiveView();
00853 e->setAccepted(active->canClose());
00854 if (!e->isAccepted())
00855 return;
00856 }
00857 }
00858
00859
00860 for (std::list<Gui::BaseView*>::iterator It = d->passive.begin();It!=d->passive.end();It++) {
00861 e->setAccepted((*It)->canClose());
00862 if (!e->isAccepted())
00863 return;
00864 }
00865
00866 if (e->isAccepted()) {
00867 d->isClosing = true;
00868
00869 std::map<const App::Document*, Gui::Document*>::iterator It;
00870
00871
00872
00873 std::list<Gui::BaseView*>::iterator itp = d->passive.begin();
00874 while (itp != d->passive.end()) {
00875 (*itp)->onClose();
00876 itp = d->passive.begin();
00877 }
00878
00879
00880 size_t cnt = d->documents.size();
00881 while (d->documents.size() > 0 && cnt > 0) {
00882
00883 It = d->documents.begin();
00884 App::GetApplication().closeDocument(It->second->getDocument()->getName());
00885 --cnt;
00886 }
00887 }
00888 }
00889
00899 bool Application::activateWorkbench(const char* name)
00900 {
00901 bool ok = false;
00902 WaitCursor wc;
00903 Workbench* oldWb = WorkbenchManager::instance()->active();
00904 if (oldWb && oldWb->name() == name)
00905 return false;
00906
00907
00908
00909 PyObject* pcOldWorkbench = 0;
00910 if (oldWb) {
00911 pcOldWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, oldWb->name().c_str());
00912 }
00913
00914
00915 Base::PyGILStateLocker lock;
00916 PyObject* pcWorkbench = 0;
00917 pcWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, name);
00918
00919 if (!pcWorkbench)
00920 return false;
00921
00922 try {
00923 std::string type;
00924 Py::Object handler(pcWorkbench);
00925 if (!handler.hasAttr(std::string("__Workbench__"))) {
00926
00927 Py::Callable method(handler.getAttr(std::string("GetClassName")));
00928 Py::Tuple args;
00929 Py::String result(method.apply(args));
00930 type = result.as_std_string();
00931 if (type == "Gui::PythonWorkbench") {
00932 Workbench* wb = WorkbenchManager::instance()->createWorkbench(name, type);
00933 handler.setAttr(std::string("__Workbench__"), Py::Object(wb->getPyObject(), true));
00934 }
00935
00936
00937 Py::Callable activate(handler.getAttr(std::string("Initialize")));
00938 activate.apply(args);
00939 }
00940
00941
00942 Workbench* curWb = WorkbenchManager::instance()->active();
00943 if (curWb && curWb->name() == name)
00944 ok = true;
00945
00946 else if (WorkbenchManager::instance()->activate(name, type)) {
00947 getMainWindow()->activateWorkbench(QString::fromAscii(name));
00948 this->signalActivateWorkbench(name);
00949 ok = true;
00950 }
00951
00952
00953
00954 if (!handler.hasAttr(std::string("__Workbench__"))) {
00955 Workbench* wb = WorkbenchManager::instance()->getWorkbench(name);
00956 if (wb) handler.setAttr(std::string("__Workbench__"), Py::Object(wb->getPyObject(), true));
00957 }
00958
00959
00960 if (pcOldWorkbench) {
00961 Py::Object handler(pcOldWorkbench);
00962 if (handler.hasAttr(std::string("Deactivated"))) {
00963 Py::Object method(handler.getAttr(std::string("Deactivated")));
00964 if (method.isCallable()) {
00965 Py::Tuple args;
00966 Py::Callable activate(method);
00967 activate.apply(args);
00968 }
00969 }
00970 }
00971
00972 if (oldWb)
00973 oldWb->deactivated();
00974
00975
00976 if (handler.hasAttr(std::string("Activated"))) {
00977 Py::Object method(handler.getAttr(std::string("Activated")));
00978 if (method.isCallable()) {
00979 Py::Tuple args;
00980 Py::Callable activate(method);
00981 activate.apply(args);
00982 }
00983 }
00984
00985
00986 Workbench* newWb = WorkbenchManager::instance()->active();
00987 if (newWb)
00988 newWb->activated();
00989 }
00990 catch (Py::Exception&) {
00991 Base::PyException e;
00992 QString msg = QString::fromAscii(e.what());
00993 QRegExp rx;
00994
00995 rx.setPattern(QLatin1String("^\\s*<type 'exceptions.ImportError'>:\\s*"));
00996 int pos = rx.indexIn(msg);
00997 while ( pos != -1 ) {
00998 msg = msg.mid(rx.matchedLength());
00999 pos = rx.indexIn(msg);
01000 }
01001
01002 Base::Console().Error("%s\n", (const char*)msg.toAscii());
01003 Base::Console().Log("%s\n", e.getStackTrace().c_str());
01004 if (!d->startingUp) {
01005 wc.restoreCursor();
01006 QMessageBox::critical(getMainWindow(), QObject::tr("Workbench failure"),
01007 QObject::tr("%1").arg(msg));
01008 wc.setWaitCursor();
01009 }
01010 }
01011
01012 return ok;
01013 }
01014
01015 QPixmap Application::workbenchIcon(const QString& wb) const
01016 {
01017 Base::PyGILStateLocker lock;
01018
01019 PyObject* pcWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, wb.toAscii());
01020
01021 if (pcWorkbench) {
01022
01023 std::stringstream str;
01024 str << static_cast<const void *>(pcWorkbench) << std::ends;
01025 std::string iconName = str.str();
01026 QPixmap icon;
01027 if (BitmapFactory().findPixmapInCache(iconName.c_str(), icon))
01028 return icon;
01029
01030
01031 try {
01032 Py::Object handler(pcWorkbench);
01033 Py::Object member = handler.getAttr(std::string("Icon"));
01034 Py::String data(member);
01035 std::string content = data.as_std_string();
01036
01037
01038 QByteArray ary;
01039 int strlen = (int)content.size();
01040 ary.resize(strlen);
01041 for (int j=0; j<strlen; j++)
01042 ary[j]=content[j];
01043 if (ary.indexOf("/* XPM */") > 0) {
01044
01045 QList<QByteArray> lines = ary.split('\n');
01046 QByteArray buffer;
01047 buffer.reserve(ary.size()+lines.size());
01048 for (QList<QByteArray>::iterator it = lines.begin(); it != lines.end(); ++it) {
01049 QByteArray trim = it->trimmed();
01050 if (!trim.isEmpty()) {
01051 buffer.append(trim);
01052 buffer.append('\n');
01053 }
01054 }
01055 icon.loadFromData(buffer, "XPM");
01056 }
01057 else {
01058
01059 QString file = QString::fromUtf8(content.c_str());
01060 icon.load(file);
01061 if (icon.isNull()) {
01062
01063 icon = BitmapFactory().pixmap(file.toUtf8());
01064 }
01065 }
01066
01067 if (!icon.isNull()) {
01068 BitmapFactory().addPixmapToCache(iconName.c_str(), icon);
01069 }
01070
01071 return icon;
01072 }
01073 catch (Py::Exception& e) {
01074 e.clear();
01075 }
01076 }
01077
01078 return QPixmap();
01079 }
01080
01081 QString Application::workbenchToolTip(const QString& wb) const
01082 {
01083
01084 Base::PyGILStateLocker lock;
01085 PyObject* pcWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, wb.toAscii());
01086
01087 if (pcWorkbench) {
01088
01089 try {
01090 Py::Object handler(pcWorkbench);
01091 Py::Object member = handler.getAttr(std::string("ToolTip"));
01092 if (member.isString()) {
01093 Py::String tip(member);
01094 return QString::fromUtf8(tip.as_std_string().c_str());
01095 }
01096 }
01097 catch (Py::Exception& e) {
01098 e.clear();
01099 }
01100 }
01101
01102 return QString();
01103 }
01104
01105 QString Application::workbenchMenuText(const QString& wb) const
01106 {
01107
01108 Base::PyGILStateLocker lock;
01109 PyObject* pcWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, wb.toAscii());
01110
01111 if (pcWorkbench) {
01112
01113 Base::PyGILStateLocker locker;
01114 try {
01115 Py::Object handler(pcWorkbench);
01116 Py::Object member = handler.getAttr(std::string("MenuText"));
01117 if (member.isString()) {
01118 Py::String tip(member);
01119 return QString::fromUtf8(tip.as_std_string().c_str());
01120 }
01121 }
01122 catch (Py::Exception& e) {
01123 e.clear();
01124 }
01125 }
01126
01127 return QString();
01128 }
01129
01130 QStringList Application::workbenches(void) const
01131 {
01132
01133 const std::map<std::string,std::string>& config = App::Application::Config();
01134 std::map<std::string, std::string>::const_iterator ht = config.find("HiddenWorkbench");
01135 std::map<std::string, std::string>::const_iterator et = config.find("ExtraWorkbench");
01136 std::map<std::string, std::string>::const_iterator st = config.find("StartWorkbench");
01137 const char* start = (st != config.end() ? st->second.c_str() : "<none>");
01138 QStringList hidden, extra;
01139 if (ht != config.end()) {
01140 QString items = QString::fromAscii(ht->second.c_str());
01141 hidden = items.split(QLatin1Char(';'), QString::SkipEmptyParts);
01142 if (hidden.isEmpty())
01143 hidden.push_back(QLatin1String(""));
01144 }
01145 if (et != config.end()) {
01146 QString items = QString::fromAscii(et->second.c_str());
01147 extra = items.split(QLatin1Char(';'), QString::SkipEmptyParts);
01148 if (extra.isEmpty())
01149 extra.push_back(QLatin1String(""));
01150 }
01151
01152 PyObject *key, *value;
01153 Py_ssize_t pos = 0;
01154 QStringList wb;
01155
01156 while (PyDict_Next(_pcWorkbenchDictionary, &pos, &key, &value)) {
01157
01158 const char* wbName = PyString_AsString(key);
01159
01160 bool ok = true;
01161 if (!extra.isEmpty()&&ok) {
01162 ok = (extra.indexOf(QString::fromAscii(wbName)) != -1);
01163 }
01164 if (!hidden.isEmpty()&&ok) {
01165 ok = (hidden.indexOf(QString::fromAscii(wbName)) == -1);
01166 }
01167
01168
01169 if (ok)
01170 wb.push_back(QString::fromAscii(wbName));
01171
01172 else if (strcmp(wbName, start) == 0)
01173 wb.push_back(QString::fromAscii(wbName));
01174 }
01175
01176 return wb;
01177 }
01178
01179 void Application::setupContextMenu(const char* recipient, MenuItem* items) const
01180 {
01181 Workbench* actWb = WorkbenchManager::instance()->active();
01182 if (actWb) {
01183
01184
01185 if (actWb->getTypeId().isDerivedFrom(PythonWorkbench::getClassTypeId())) {
01186 static_cast<PythonWorkbench*>(actWb)->clearContextMenu();
01187 Base::PyGILStateLocker lock;
01188 PyObject* pWorkbench = 0;
01189 pWorkbench = PyDict_GetItemString(_pcWorkbenchDictionary, actWb->name().c_str());
01190
01191 try {
01192
01193 Py::Object handler(pWorkbench);
01194 Py::Callable method(handler.getAttr(std::string("ContextMenu")));
01195 Py::Tuple args(1);
01196 args.setItem(0, Py::String(recipient));
01197 method.apply(args);
01198 }
01199 catch (Py::Exception& e) {
01200 Py::Object o = Py::type(e);
01201 e.clear();
01202 if (o.isString()) {
01203 Py::String s(o);
01204 std::clog << "Application::setupContextMenu: " << s.as_std_string() << std::endl;
01205 }
01206 }
01207 }
01208 actWb->setupContextMenu(recipient, items);
01209 }
01210 }
01211
01212 bool Application::isClosing(void)
01213 {
01214 return d->isClosing;
01215 }
01216
01217 MacroManager *Application::macroManager(void)
01218 {
01219 return d->macroMngr;
01220 }
01221
01222 CommandManager &Application::commandManager(void)
01223 {
01224 return d->commandManager;
01225 }
01226
01227 void Application::runCommand(bool bForce, const char* sCmd,...)
01228 {
01229
01230 size_t format_len = std::strlen(sCmd)+4024;
01231 char* format = (char*) malloc(format_len);
01232 va_list namelessVars;
01233 va_start(namelessVars, sCmd);
01234 vsnprintf(format, format_len, sCmd, namelessVars);
01235 va_end(namelessVars);
01236
01237 if (bForce)
01238 d->macroMngr->addLine(MacroManager::Base,format);
01239 else
01240 d->macroMngr->addLine(MacroManager::Gui,format);
01241
01242 try {
01243 Base::Interpreter().runString(format);
01244 }
01245 catch (...) {
01246
01247 free (format);
01248 throw;
01249 }
01250
01251 free (format);
01252 }
01253
01254 bool Application::runPythonCode(const char* cmd, bool gui, bool pyexc)
01255 {
01256 if (gui)
01257 d->macroMngr->addLine(MacroManager::Gui,cmd);
01258 else
01259 d->macroMngr->addLine(MacroManager::Base,cmd);
01260
01261 try {
01262 Base::Interpreter().runString(cmd);
01263 return true;
01264 }
01265 catch (Base::PyException &e) {
01266 if (pyexc) {
01267 e.ReportException();
01268 Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str());
01269 }
01270 else {
01271 throw;
01272 }
01273 }
01274 catch (Base::AbortException&) {
01275 }
01276 catch (Base::Exception &e) {
01277 e.ReportException();
01278 }
01279 catch (std::exception &e) {
01280 std::string str;
01281 str += "C++ exception thrown (";
01282 str += e.what();
01283 str += ")";
01284 Base::Console().Error(str.c_str());
01285 }
01286 catch (const char* e) {
01287 Base::Console().Error("%s\n", e);
01288 }
01289 #ifndef FC_DEBUG
01290 catch (...) {
01291 Base::Console().Error("Unknown C++ exception in command thrown\n");
01292 }
01293 #endif
01294 return false;
01295 }
01296
01297
01298
01299
01300 typedef void (*_qt_msg_handler_old)(QtMsgType type, const char *msg);
01301 _qt_msg_handler_old old_qtmsg_handler = 0;
01302
01303 void messageHandler(QtMsgType type, const char *msg)
01304 {
01305 #ifdef FC_DEBUG
01306 switch (type)
01307 {
01308 case QtDebugMsg:
01309 Base::Console().Message("%s\n", msg);
01310 break;
01311 case QtWarningMsg:
01312 Base::Console().Warning("%s\n", msg);
01313 break;
01314 case QtFatalMsg:
01315 Base::Console().Error("%s\n", msg);
01316 abort();
01317 }
01318 #ifdef FC_OS_WIN32
01319 if (old_qtmsg_handler)
01320 (*old_qtmsg_handler)(type, msg);
01321 #endif
01322 #else
01323
01324 Base::Console().Log("%s\n", msg);
01325 #endif
01326 }
01327
01328 #ifdef FC_DEBUG // redirect Coin messages to FreeCAD
01329 void messageHandlerCoin(const SoError * error, void * userdata)
01330 {
01331 if (error && error->getTypeId() == SoDebugError::getClassTypeId()) {
01332 const SoDebugError* dbg = static_cast<const SoDebugError*>(error);
01333 const char* msg = error->getDebugString().getString();
01334 switch (dbg->getSeverity())
01335 {
01336 case SoDebugError::INFO:
01337 Base::Console().Message( msg );
01338 break;
01339 case SoDebugError::WARNING:
01340 Base::Console().Warning( msg );
01341 break;
01342 default:
01343 Base::Console().Error( msg );
01344 break;
01345 }
01346 #ifdef FC_OS_WIN32
01347 if (old_qtmsg_handler)
01348 (*old_qtmsg_handler)(QtDebugMsg, msg);
01349 #endif
01350 }
01351 else if (error) {
01352 const char* msg = error->getDebugString().getString();
01353 Base::Console().Log( msg );
01354 }
01355 }
01356
01357 void messageHandlerSoQt(const SbString errmsg, SoQt::FatalErrors errcode, void *userdata)
01358 {
01359 Base::Console().Error( errmsg.getString() );
01360 }
01361 #endif
01362
01363
01364 static void init_resources()
01365 {
01366
01367 Q_INIT_RESOURCE(resource);
01368 Q_INIT_RESOURCE(translation);
01369 }
01370
01371 void Application::initApplication(void)
01372 {
01373 try {
01374 initTypes();
01375 new Base::ScriptProducer( "FreeCADGuiInit", FreeCADGuiInit );
01376 init_resources();
01377 old_qtmsg_handler = qInstallMsgHandler(messageHandler);
01378 }
01379 catch (...) {
01380
01381 App::Application::destructObserver();
01382 throw;
01383 }
01384 }
01385
01386 void Application::initTypes(void)
01387 {
01388
01389 Gui::BaseView ::init();
01390 Gui::MDIView ::init();
01391 Gui::View3DInventor ::init();
01392
01393 Gui::ViewProvider ::init();
01394 Gui::ViewProviderExtern ::init();
01395 Gui::ViewProviderDocumentObject ::init();
01396 Gui::ViewProviderFeature ::init();
01397 Gui::ViewProviderDocumentObjectGroup ::init();
01398 Gui::ViewProviderGeometryObject ::init();
01399 Gui::ViewProviderInventorObject ::init();
01400 Gui::ViewProviderVRMLObject ::init();
01401 Gui::ViewProviderAnnotation ::init();
01402 Gui::ViewProviderAnnotationLabel ::init();
01403 Gui::ViewProviderPointMarker ::init();
01404 Gui::ViewProviderMeasureDistance ::init();
01405 Gui::ViewProviderPythonFeature ::init();
01406 Gui::ViewProviderPythonGeometry ::init();
01407
01408
01409 Gui::Workbench ::init();
01410 Gui::StdWorkbench ::init();
01411 Gui::BlankWorkbench ::init();
01412 Gui::NoneWorkbench ::init();
01413 Gui::TestWorkbench ::init();
01414 Gui::PythonWorkbench ::init();
01415 }
01416
01417 namespace Gui {
01421 class GUIApplication : public GUIApplicationNativeEventAware
01422 {
01423 public:
01424 GUIApplication(int & argc, char ** argv)
01425 : GUIApplicationNativeEventAware(argc, argv)
01426 {
01427 }
01428
01433 bool notify (QObject * receiver, QEvent * event)
01434 {
01435 if (!receiver && event) {
01436 Base::Console().Log("GUIApplication::notify: Unexpected null receiver, event type: %d\n",
01437 (int)event->type());
01438 }
01439 try {
01440 if (event->type() == Spaceball::ButtonEvent::ButtonEventType)
01441 return processSpaceballEvent(receiver, event);
01442 else
01443 return QApplication::notify(receiver, event);
01444 }
01445 catch (const Base::Exception& e) {
01446 Base::Console().Error("Unhandled Base::Exception caught in GUIApplication::notify.\n"
01447 "The error message is: %s\n", e.what());
01448 }
01449 catch (const std::exception& e) {
01450 Base::Console().Error("Unhandled std::exception caught in GUIApplication::notify.\n"
01451 "The error message is: %s\n", e.what());
01452 }
01453 catch (...) {
01454 Base::Console().Error("Unhandled unknown exception caught in GUIApplication::notify.\n");
01455 }
01456
01457
01458 if (receiver && event) {
01459 std::stringstream dump;
01460 dump << "The event type " << (int)event->type() << " was sent to "
01461 << receiver->metaObject()->className() << "\n";
01462 dump << "Object tree:\n";
01463 if (receiver->isWidgetType()) {
01464 QWidget* w = qobject_cast<QWidget*>(receiver);
01465 while (w) {
01466 dump << "\t";
01467 dump << w->metaObject()->className();
01468 QString name = w->objectName();
01469 if (!name.isEmpty())
01470 dump << " (" << (const char*)name.toUtf8() << ")";
01471 w = w->parentWidget();
01472 if (w)
01473 dump << " is child of\n";
01474 }
01475 std::string str = dump.str();
01476 Base::Console().Log("%s",str.c_str());
01477 }
01478 }
01479
01480 return true;
01481 }
01482 void commitData(QSessionManager &manager)
01483 {
01484 if (manager.allowsInteraction()) {
01485 if (!Gui::getMainWindow()->close()) {
01486
01487 manager.release();
01488 manager.cancel();
01489 }
01490 }
01491 else {
01492
01493
01494 App::GetApplication().closeAllDocuments();
01495 Gui::getMainWindow()->close();
01496 }
01497
01498 }
01499 };
01500 }
01501
01502 void Application::runApplication(void)
01503 {
01504
01505 Base::Console().Log("Init: Creating Gui::Application and QApplication\n");
01506
01507 int argc = App::Application::GetARGC();
01508 GUIApplication mainApp(argc, App::Application::GetARGV());
01509
01510 mainApp.setWindowIcon(Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str()));
01511 mainApp.setApplicationName(QString::fromAscii(App::GetApplication().getExecutableName()));
01512 QString plugin;
01513 plugin = QString::fromUtf8(App::GetApplication().GetHomePath());
01514 plugin += QLatin1String("/plugins");
01515 QCoreApplication::addLibraryPath(plugin);
01516
01517
01518 if (!QGLFormat::hasOpenGL()) {
01519 QMessageBox::critical(0, QObject::tr("No OpenGL"), QObject::tr("This system does not support OpenGL"));
01520 throw Base::Exception("This system does not support OpenGL");
01521 }
01522 #if QT_VERSION >= 0x040200
01523 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) {
01524 Base::Console().Log("This system does not support framebuffer objects");
01525 }
01526 #endif
01527 if (!QGLPixelBuffer::hasOpenGLPbuffers()) {
01528 Base::Console().Log("This system does not support pbuffers");
01529 }
01530
01531 QGLFormat::OpenGLVersionFlags version = QGLFormat::openGLVersionFlags ();
01532 #if QT_VERSION >= 0x040500
01533 if (version & QGLFormat::OpenGL_Version_3_0)
01534 Base::Console().Log("OpenGL version 3.0 or higher is present\n");
01535 else
01536 #endif
01537 if (version & QGLFormat::OpenGL_Version_2_1)
01538 Base::Console().Log("OpenGL version 2.1 or higher is present\n");
01539 else if (version & QGLFormat::OpenGL_Version_2_0)
01540 Base::Console().Log("OpenGL version 2.0 or higher is present\n");
01541 else if (version & QGLFormat::OpenGL_Version_1_5)
01542 Base::Console().Log("OpenGL version 1.5 or higher is present\n");
01543 else if (version & QGLFormat::OpenGL_Version_1_4)
01544 Base::Console().Log("OpenGL version 1.4 or higher is present\n");
01545 else if (version & QGLFormat::OpenGL_Version_1_3)
01546 Base::Console().Log("OpenGL version 1.3 or higher is present\n");
01547 else if (version & QGLFormat::OpenGL_Version_1_2)
01548 Base::Console().Log("OpenGL version 1.2 or higher is present\n");
01549 else if (version & QGLFormat::OpenGL_Version_1_1)
01550 Base::Console().Log("OpenGL version 1.1 or higher is present\n");
01551 else if (version & QGLFormat::OpenGL_Version_None)
01552 Base::Console().Log("No OpenGL is present or no OpenGL context is current\n");
01553
01554 Application app(true);
01555 MainWindow mw;
01556 mw.setWindowTitle(mainApp.applicationName());
01557
01558
01559 ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
01560 int size = hGrp->GetInt("ToolbarIconSize", 0);
01561 if (size >= 16)
01562 mw.setIconSize(QSize(size,size));
01563
01564
01565 SoDB::init();
01566 SoQt::init(&mw);
01567 SoFCDB::init();
01568
01569 const std::map<std::string,std::string>& cfg = App::Application::Config();
01570 std::map<std::string,std::string>::const_iterator it;
01571 it = cfg.find("WindowTitle");
01572 if (it != cfg.end()) {
01573 QString title = QString::fromUtf8(it->second.c_str());
01574 mw.setWindowTitle(title);
01575 }
01576 it = cfg.find("WindowIcon");
01577 if (it != cfg.end()) {
01578 QString path = QString::fromUtf8(it->second.c_str());
01579 QApplication::setWindowIcon(QIcon(path));
01580 }
01581 it = cfg.find("ProgramLogo");
01582 if (it != cfg.end()) {
01583 QString path = QString::fromUtf8(it->second.c_str());
01584 QPixmap px(path);
01585 if (!px.isNull()) {
01586 QLabel* logo = new QLabel();
01587 logo->setPixmap(px.scaledToHeight(32));
01588 mw.statusBar()->addPermanentWidget(logo, 0);
01589 logo->setFrameShape(QFrame::NoFrame);
01590 }
01591 }
01592
01593
01594 mw.startSplasher();
01595
01596
01597 try {
01598 Base::Interpreter().runString(Base::ScriptFactory().ProduceScript("FreeCADGuiInit"));
01599 }
01600 catch (const Base::Exception& e) {
01601 Base::Console().Error("Error in FreeCADGuiInit.py: %s\n", e.what());
01602 mw.stopSplasher();
01603 throw;
01604 }
01605
01606
01607
01608 mw.stopSplasher();
01609 mainApp.setActiveWindow(&mw);
01610
01611
01612 std::string start = App::Application::Config()["StartWorkbench"];
01613 Base::Console().Log("Init: Activating default workbench %s\n", start.c_str());
01614 start = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
01615 GetASCII("AutoloadModule", start.c_str());
01616
01617
01618 QStringList wb = app.workbenches();
01619 if (!wb.contains(QString::fromAscii(start.c_str()))) {
01620 start = App::Application::Config()["StartWorkbench"];
01621 App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
01622 SetASCII("AutoloadModule", start.c_str());
01623 }
01624
01625 app.activateWorkbench(start.c_str());
01626
01627
01628 Base::Console().Log("Init: Showing main window\n");
01629 mw.loadWindowSettings();
01630
01631
01632 mainApp.initSpaceball(&mw);
01633
01634 #ifdef FC_DEBUG // redirect Coin messages to FreeCAD
01635 SoDebugError::setHandlerCallback( messageHandlerCoin, 0 );
01636 SoQt::setFatalErrorHandler( messageHandlerSoQt, 0 );
01637 #endif
01638
01639 Instance->d->startingUp = false;
01640
01641 #if 0
01642
01643 App::Application::processCmdLineFiles();
01644
01645
01646 ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Document");
01647 if (hGrp->GetBool("CreateNewDoc", false)) {
01648 App::GetApplication().newDocument();
01649 }
01650 #else
01651
01652 QTimer::singleShot(0, &mw, SLOT(delayedStartup()));
01653 #endif
01654
01655
01656 Base::Console().Log("Init: Entering event loop\n");
01657
01658 try {
01659 mainApp.exec();
01660 }
01661 catch(...) {
01662
01663 App::Application::destructObserver();
01664 Base::Console().Error("Event loop left through unhandled exception\n");
01665 throw;
01666 }
01667
01668 Base::Console().Log("Finish: Event loop left\n");
01669 }