00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "PreCompiled.h"
00028
00029 #ifndef _PreComp_
00030 # include <iostream>
00031 # include <sstream>
00032 # include <exception>
00033 # if defined(FC_OS_LINUX) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD)
00034 # include <unistd.h>
00035 # include <pwd.h>
00036 # include <sys/types.h>
00037 # endif
00038 # include <ctime>
00039 # include <csignal>
00040 # include <boost/program_options.hpp>
00041 #endif
00042
00043 #ifdef FC_OS_WIN32
00044 # include <Shlobj.h>
00045
00046 # if (defined(_MSC_VER) && (_MSC_VER < 1800))
00047 # include <Shfolder.h>
00048 # endif
00049 #endif
00050
00051
00052
00053 #include "Application.h"
00054 #include "Document.h"
00055
00056
00057 #include <Base/Interpreter.h>
00058 #include <Base/Exception.h>
00059 #include <Base/Parameter.h>
00060 #include <Base/Console.h>
00061 #include <Base/Factory.h>
00062 #include <Base/FileInfo.h>
00063 #include <Base/Type.h>
00064 #include <Base/BaseClass.h>
00065 #include <Base/Persistence.h>
00066 #include <Base/Reader.h>
00067 #include <Base/MatrixPy.h>
00068 #include <Base/VectorPy.h>
00069 #include <Base/BoundBoxPy.h>
00070 #include <Base/PlacementPy.h>
00071 #include <Base/RotationPy.h>
00072 #include <Base/Sequencer.h>
00073 #include <Base/Tools.h>
00074 #include <Base/UnitsApi.h>
00075
00076 #include "GeoFeature.h"
00077 #include "FeatureTest.h"
00078 #include "FeaturePython.h"
00079 #include "ComplexGeoData.h"
00080 #include "Property.h"
00081 #include "PropertyContainer.h"
00082 #include "PropertyUnits.h"
00083 #include "PropertyFile.h"
00084 #include "PropertyLinks.h"
00085 #include "PropertyPythonObject.h"
00086 #include "Document.h"
00087 #include "DocumentObjectGroup.h"
00088 #include "DocumentObjectFileIncluded.h"
00089 #include "InventorObject.h"
00090 #include "VRMLObject.h"
00091 #include "Annotation.h"
00092 #include "MeasureDistance.h"
00093
00094
00095
00096
00097 #include <Build/Version.h>
00098
00099 #include <boost/tokenizer.hpp>
00100 #include <boost/token_functions.hpp>
00101 #include <boost/signals.hpp>
00102 #include <boost/bind.hpp>
00103 #include <boost/version.hpp>
00104
00105 using namespace App;
00106 using namespace std;
00107 using namespace boost;
00108 using namespace boost::program_options;
00109
00110
00111
00112 #include "InitScript.h"
00113 #include "TestScript.h"
00114
00115 #ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
00116 # include <new.h>
00117 #else // Ansi C/C++ new handler
00118 # include <new>
00119 #endif
00120
00121 #ifdef MemDebugOn
00122 # define new DEBUG_CLIENTBLOCK
00123 #endif
00124
00125
00126
00127 using namespace Base;
00128 using namespace App;
00129 using namespace std;
00130
00131
00132
00133
00134
00135
00136 ParameterManager *App::Application::_pcSysParamMngr;
00137 ParameterManager *App::Application::_pcUserParamMngr;
00138 Base::ConsoleObserverStd *Application::_pConsoleObserverStd =0;
00139 Base::ConsoleObserverFile *Application::_pConsoleObserverFile =0;
00140
00141 AppExport std::map<std::string,std::string> Application::mConfig;
00142
00143
00144
00145
00146
00147 PyDoc_STRVAR(FreeCAD_doc,
00148 "The functions in the FreeCAD module allow working with documents.\n"
00149 "The FreeCAD instance provides a list of references of documents which\n"
00150 "can be addressed by a string. Hence the document name must be unique.\n"
00151 "\n"
00152 "The document has the read-only attribute FileName which points to the\n"
00153 "file the document should be stored to.\n"
00154 );
00155
00156 PyDoc_STRVAR(Console_doc,
00157 "FreeCAD Console\n"
00158 );
00159
00160 Application::Application(ParameterManager * ,
00161 ParameterManager * ,
00162 std::map<std::string,std::string> &mConfig)
00163 :
00164
00165 _mConfig(mConfig),
00166 _pActiveDoc(0)
00167 {
00168
00169 mpcPramManager["System parameter"] = _pcSysParamMngr;
00170 mpcPramManager["User parameter"] = _pcUserParamMngr;
00171
00172
00173
00174 Base::PyGILStateLocker lock;
00175 PyObject* pAppModule = Py_InitModule3("FreeCAD", Application::Methods, FreeCAD_doc);
00176 Py::Module(pAppModule).setAttr(std::string("ActiveDocument"),Py::None());
00177
00178 PyObject* pConsoleModule = Py_InitModule3("__FreeCADConsole__", ConsoleSingleton::Methods, Console_doc);
00179
00180
00181
00182
00183
00184
00185 if (PyType_Ready(&Base::VectorPy::Type) < 0) return;
00186 union PyType_Object pyVecType = {&Base::VectorPy::Type};
00187 PyModule_AddObject(pAppModule, "Vector", pyVecType.o);
00188
00189 if (PyType_Ready(&Base::MatrixPy::Type) < 0) return;
00190 union PyType_Object pyMtxType = {&Base::MatrixPy::Type};
00191 PyModule_AddObject(pAppModule, "Matrix", pyMtxType.o);
00192
00193 if (PyType_Ready(&Base::BoundBoxPy::Type) < 0) return;
00194 union PyType_Object pyBoundBoxType = {&Base::BoundBoxPy::Type};
00195 PyModule_AddObject(pAppModule, "BoundBox", pyBoundBoxType.o);
00196
00197 if (PyType_Ready(&Base::PlacementPy::Type) < 0) return;
00198 union PyType_Object pyPlacementPyType = {&Base::PlacementPy::Type};
00199 PyModule_AddObject(pAppModule, "Placement", pyPlacementPyType.o);
00200
00201 if (PyType_Ready(&Base::RotationPy::Type) < 0) return;
00202 union PyType_Object pyRotationPyType = {&Base::RotationPy::Type};
00203 PyModule_AddObject(pAppModule, "Rotation", pyRotationPyType.o);
00204
00205
00206
00207
00208 PyObject* pBaseModule = Py_InitModule3("__FreeCADBase__", NULL,
00209 "The Base module contains the classes for the geometric basics\n"
00210 "like vector, matrix, bounding box, placement, rotation, ...");
00211 Base::Interpreter().addType(&Base::VectorPy ::Type,pBaseModule,"Vector");
00212 Base::Interpreter().addType(&Base::MatrixPy ::Type,pBaseModule,"Matrix");
00213 Base::Interpreter().addType(&Base::BoundBoxPy ::Type,pBaseModule,"BoundBox");
00214 Base::Interpreter().addType(&Base::PlacementPy ::Type,pBaseModule,"Placement");
00215 Base::Interpreter().addType(&Base::RotationPy ::Type,pBaseModule,"Rotation");
00216
00217
00218 Py_INCREF(pBaseModule);
00219 PyModule_AddObject(pAppModule, "Base", pBaseModule);
00220 Py_INCREF(pConsoleModule);
00221 PyModule_AddObject(pAppModule, "Console", pConsoleModule);
00222
00223
00224 PyObject* pUnitsModule = Py_InitModule3("Units", Base::UnitsApi::Methods,
00225 "The Unit API");
00226 Py_INCREF(pUnitsModule);
00227 PyModule_AddObject(pAppModule, "Units", pUnitsModule);
00228
00229 Base::ProgressIndicatorPy::init_type();
00230 Base::Interpreter().addType(Base::ProgressIndicatorPy::type_object(),
00231 pBaseModule,"ProgressIndicator");
00232 }
00233
00234 Application::~Application()
00235 {
00236 }
00237
00238
00239
00240
00242 void Application::renameDocument(const char *OldName, const char *NewName)
00243 {
00244 std::map<std::string,Document*>::iterator pos;
00245 pos = DocMap.find(OldName);
00246
00247 if (pos != DocMap.end()) {
00248 Document* temp;
00249 temp = pos->second;
00250 DocMap.erase(pos);
00251 DocMap[NewName] = temp;
00252 signalRenameDocument(*temp);
00253 }
00254 else
00255 Base::Exception("Application::renameDocument(): no document with this name to rename!");
00256
00257 }
00258
00259 Document* Application::newDocument(const char * Name, const char * UserName)
00260 {
00261
00262 if (!Name || Name[0] == '\0')
00263 Name = "Unnamed";
00264 string name = getUniqueDocumentName(Name);
00265
00266
00267 auto_ptr<Document> newDoc(new Document() );
00268
00269
00270 DocMap[name] = newDoc.release();
00271 _pActiveDoc = DocMap[name];
00272
00273
00274
00275 _pActiveDoc->signalNewObject.connect(boost::bind(&App::Application::slotNewObject, this, _1));
00276 _pActiveDoc->signalDeletedObject.connect(boost::bind(&App::Application::slotDeletedObject, this, _1));
00277 _pActiveDoc->signalChangedObject.connect(boost::bind(&App::Application::slotChangedObject, this, _1, _2));
00278 _pActiveDoc->signalRenamedObject.connect(boost::bind(&App::Application::slotRenamedObject, this, _1));
00279 _pActiveDoc->signalActivatedObject.connect(boost::bind(&App::Application::slotActivatedObject, this, _1));
00280
00281
00282 {
00283 Base::PyGILStateLocker lock;
00284 Py::Object active(_pActiveDoc->getPyObject(), true);
00285 Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),active);
00286 }
00287
00288 signalNewDocument(*_pActiveDoc);
00289
00290
00291 if (UserName)
00292 _pActiveDoc->Label.setValue(UserName);
00293 else
00294 _pActiveDoc->Label.setValue(name);
00295
00296 return _pActiveDoc;
00297 }
00298
00299 bool Application::closeDocument(const char* name)
00300 {
00301 map<string,Document*>::iterator pos = DocMap.find( name );
00302 if (pos == DocMap.end())
00303 return false;
00304
00305 if (!pos->second->isClosable())
00306 return false;
00307
00308
00309
00310 signalDeleteDocument(*pos->second);
00311
00312
00313 if (_pActiveDoc == pos->second)
00314 setActiveDocument((Document*)0);
00315 auto_ptr<Document> delDoc (pos->second);
00316 DocMap.erase( pos );
00317
00318
00319 signalDeletedDocument();
00320
00321 return true;
00322 }
00323
00324 void Application::closeAllDocuments(void)
00325 {
00326 std::map<std::string,Document*>::iterator pos;
00327 while((pos = DocMap.begin()) != DocMap.end())
00328 closeDocument(pos->first.c_str());
00329 }
00330
00331 App::Document* Application::getDocument(const char *Name) const
00332 {
00333 std::map<std::string,Document*>::const_iterator pos;
00334
00335 pos = DocMap.find(Name);
00336
00337 if (pos == DocMap.end())
00338 return 0;
00339
00340 return pos->second;
00341 }
00342
00343 const char * Application::getDocumentName(const App::Document* doc) const
00344 {
00345 for (std::map<std::string,Document*>::const_iterator it = DocMap.begin(); it != DocMap.end(); ++it)
00346 if (it->second == doc)
00347 return it->first.c_str();
00348
00349 return 0;
00350 }
00351
00352 std::vector<App::Document*> Application::getDocuments() const
00353 {
00354 std::vector<App::Document*> docs;
00355 for (std::map<std::string,Document*>::const_iterator it = DocMap.begin(); it != DocMap.end(); ++it)
00356 docs.push_back(it->second);
00357 return docs;
00358 }
00359
00360 std::string Application::getUniqueDocumentName(const char *Name) const
00361 {
00362 if (!Name || *Name == '\0')
00363 return std::string();
00364 std::string CleanName = Base::Tools::getIdentifier(Name);
00365
00366
00367 std::map<string,Document*>::const_iterator pos;
00368 pos = DocMap.find(CleanName);
00369
00370 if (pos == DocMap.end()) {
00371
00372 return CleanName;
00373 }
00374 else {
00375 std::vector<std::string> names;
00376 names.reserve(DocMap.size());
00377 for (pos = DocMap.begin();pos != DocMap.end();++pos) {
00378 names.push_back(pos->first);
00379 }
00380 return Base::Tools::getUniqueName(CleanName, names);
00381 }
00382 }
00383
00384 Document* Application::openDocument(const char * FileName)
00385 {
00386 FileInfo File(FileName);
00387
00388 if (!File.exists()) {
00389 std::stringstream str;
00390 str << "File '" << FileName << "' does not exist!";
00391 throw Base::Exception(str.str().c_str());
00392 }
00393
00394
00395 std::string filepath = File.filePath();
00396 for (std::map<std::string,Document*>::iterator it = DocMap.begin(); it != DocMap.end(); ++it) {
00397
00398 std::string fi = FileInfo(it->second->FileName.getValue()).filePath();
00399 if (filepath == fi) {
00400 std::stringstream str;
00401 str << "The project '" << FileName << "' is already open!";
00402 throw Base::Exception(str.str().c_str());
00403 }
00404 }
00405
00406
00407
00408
00409 Document* newDoc = newDocument(File.fileNamePure().c_str(), File.fileNamePure().c_str());
00410
00411 newDoc->FileName.setValue(File.filePath());
00412
00413
00414 newDoc->restore();
00415
00416 return newDoc;
00417 }
00418
00419 Document* Application::getActiveDocument(void) const
00420 {
00421 return _pActiveDoc;
00422 }
00423
00424 void Application::setActiveDocument(Document* pDoc)
00425 {
00426 _pActiveDoc = pDoc;
00427
00428
00429 if (pDoc) {
00430 Base::PyGILStateLocker lock;
00431 Py::Object active(pDoc->getPyObject(), true);
00432 Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),active);
00433 }
00434 else {
00435 Base::PyGILStateLocker lock;
00436 Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),Py::None());
00437 }
00438
00439 if (pDoc)
00440 signalActiveDocument(*pDoc);
00441 }
00442
00443 void Application::setActiveDocument(const char *Name)
00444 {
00445
00446 if (*Name == '\0') {
00447 _pActiveDoc = 0;
00448 return;
00449 }
00450
00451 std::map<std::string,Document*>::iterator pos;
00452 pos = DocMap.find(Name);
00453
00454 if (pos != DocMap.end()) {
00455 setActiveDocument(pos->second);
00456 }
00457 else {
00458 std::stringstream s;
00459 s << "Try to activate unknown document '" << Name << "'";
00460 throw Base::Exception(s.str());
00461 }
00462 }
00463
00464 const char* Application::GetHomePath(void) const
00465 {
00466 return _mConfig["AppHomePath"].c_str();
00467 }
00468
00469 const char* Application::getExecutableName(void) const
00470 {
00471 return _mConfig["ExeName"].c_str();
00472 }
00473
00474 std::string Application::getUserAppDataDir()
00475 {
00476 return mConfig["UserAppData"];
00477 }
00478
00479 std::string Application::getResourceDir()
00480 {
00481 # ifdef RESOURCEDIR
00482 return std::string(RESOURCEDIR) + "/";
00483 #else
00484 return mConfig["AppHomePath"];
00485 #endif
00486 }
00487
00488 std::string Application::getHelpDir()
00489 {
00490 # ifdef DOCDIR
00491 return std::string(DOCDIR) + "/";
00492 #else
00493 return mConfig["DocPath"];
00494 #endif
00495 }
00496
00497 ParameterManager & Application::GetSystemParameter(void)
00498 {
00499 return *_pcSysParamMngr;
00500 }
00501
00502 ParameterManager & Application::GetUserParameter(void)
00503 {
00504 return *_pcUserParamMngr;
00505 }
00506
00507 ParameterManager * Application::GetParameterSet(const char* sName) const
00508 {
00509 std::map<std::string,ParameterManager *>::const_iterator it = mpcPramManager.find(sName);
00510 if ( it != mpcPramManager.end() )
00511 return it->second;
00512 else
00513 return 0;
00514 }
00515
00516 const std::map<std::string,ParameterManager *> & Application::GetParameterSetList(void) const
00517 {
00518 return mpcPramManager;
00519 }
00520
00521 void Application::AddParameterSet(const char* sName)
00522 {
00523 std::map<std::string,ParameterManager *>::const_iterator it = mpcPramManager.find(sName);
00524 if ( it != mpcPramManager.end() )
00525 return;
00526 mpcPramManager[sName] = new ParameterManager();
00527 }
00528
00529 void Application::RemoveParameterSet(const char* sName)
00530 {
00531 std::map<std::string,ParameterManager *>::iterator it = mpcPramManager.find(sName);
00532
00533 if ( it == mpcPramManager.end() || it->second == _pcUserParamMngr || it->second == _pcSysParamMngr )
00534 return;
00535 delete it->second;
00536 mpcPramManager.erase(it);
00537 }
00538
00539 Base::Reference<ParameterGrp> Application::GetParameterGroupByPath(const char* sName)
00540 {
00541 std::string cName = sName,cTemp;
00542
00543 std::string::size_type pos = cName.find(':');
00544
00545
00546 if (pos == std::string::npos) {
00547 throw Base::Exception("Application::GetParameterGroupByPath() no parameter set name specified");
00548 }
00549
00550 cTemp.assign(cName,0,pos);
00551 cName.erase(0,pos+1);
00552
00553
00554 std::map<std::string,ParameterManager *>::iterator It = mpcPramManager.find(cTemp.c_str());
00555 if (It == mpcPramManager.end())
00556 throw Base::Exception("Application::GetParameterGroupByPath() unknown parameter set name specified");
00557
00558 return It->second->GetGroup(cName.c_str());
00559 }
00560
00561 void Application::addImportType(const char* Type, const char* ModuleName)
00562 {
00563 FileTypeItem item;
00564 item.filter = Type;
00565 item.module = ModuleName;
00566
00567
00568 std::string::size_type pos = item.filter.find("*.");
00569 while ( pos != std::string::npos ) {
00570 std::string::size_type next = item.filter.find_first_of(" )", pos+1);
00571 std::string::size_type len = next-pos-2;
00572 std::string type = item.filter.substr(pos+2,len);
00573 item.types.push_back(type);
00574 pos = item.filter.find("*.", next);
00575 }
00576
00577
00578 if (strncmp(Type, "FreeCAD", 7) == 0) {
00579 std::string AppName = Config()["ExeName"];
00580 AppName += item.filter.substr(7);
00581 item.filter = AppName;
00582
00583 _mImportTypes.insert(_mImportTypes.begin(),item);
00584 }
00585 else {
00586 _mImportTypes.push_back(item);
00587 }
00588 }
00589
00590 std::vector<std::string> Application::getImportModules(const char* Type) const
00591 {
00592 std::vector<std::string> modules;
00593 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
00594 const std::vector<std::string>& types = it->types;
00595 for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {
00596 #ifdef __GNUC__
00597 if (strcasecmp(Type,jt->c_str()) == 0)
00598 #else
00599 if (_stricmp(Type,jt->c_str()) == 0)
00600 #endif
00601 modules.push_back(it->module);
00602 }
00603 }
00604
00605 return modules;
00606 }
00607
00608 std::vector<std::string> Application::getImportModules() const
00609 {
00610 std::vector<std::string> modules;
00611 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it)
00612 modules.push_back(it->module);
00613 std::sort(modules.begin(), modules.end());
00614 modules.erase(std::unique(modules.begin(), modules.end()), modules.end());
00615 return modules;
00616 }
00617
00618 std::vector<std::string> Application::getImportTypes(const char* Module) const
00619 {
00620 std::vector<std::string> types;
00621 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
00622 #ifdef __GNUC__
00623 if (strcasecmp(Module,it->module.c_str()) == 0)
00624 #else
00625 if (_stricmp(Module,it->module.c_str()) == 0)
00626 #endif
00627 types.insert(types.end(), it->types.begin(), it->types.end());
00628 }
00629
00630 return types;
00631 }
00632
00633 std::vector<std::string> Application::getImportTypes(void) const
00634 {
00635 std::vector<std::string> types;
00636 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
00637 types.insert(types.end(), it->types.begin(), it->types.end());
00638 }
00639
00640 std::sort(types.begin(), types.end());
00641 types.erase(std::unique(types.begin(), types.end()), types.end());
00642
00643 return types;
00644 }
00645
00646 std::map<std::string, std::string> Application::getImportFilters(const char* Type) const
00647 {
00648 std::map<std::string, std::string> moduleFilter;
00649 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
00650 const std::vector<std::string>& types = it->types;
00651 for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {
00652 #ifdef __GNUC__
00653 if (strcasecmp(Type,jt->c_str()) == 0)
00654 #else
00655 if (_stricmp(Type,jt->c_str()) == 0)
00656 #endif
00657 moduleFilter[it->filter] = it->module;
00658 }
00659 }
00660
00661 return moduleFilter;
00662 }
00663
00664 std::map<std::string, std::string> Application::getImportFilters(void) const
00665 {
00666 std::map<std::string, std::string> filter;
00667 for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
00668 filter[it->filter] = it->module;
00669 }
00670
00671 return filter;
00672 }
00673
00674 void Application::addExportType(const char* Type, const char* ModuleName)
00675 {
00676 FileTypeItem item;
00677 item.filter = Type;
00678 item.module = ModuleName;
00679
00680
00681 std::string::size_type pos = item.filter.find("*.");
00682 while ( pos != std::string::npos ) {
00683 std::string::size_type next = item.filter.find_first_of(" )", pos+1);
00684 std::string::size_type len = next-pos-2;
00685 std::string type = item.filter.substr(pos+2,len);
00686 item.types.push_back(type);
00687 pos = item.filter.find("*.", next);
00688 }
00689
00690
00691 if (strncmp(Type, "FreeCAD", 7) == 0) {
00692 std::string AppName = Config()["ExeName"];
00693 AppName += item.filter.substr(7);
00694 item.filter = AppName;
00695
00696 _mExportTypes.insert(_mExportTypes.begin(),item);
00697 }
00698 else {
00699 _mExportTypes.push_back(item);
00700 }
00701 }
00702
00703 std::vector<std::string> Application::getExportModules(const char* Type) const
00704 {
00705 std::vector<std::string> modules;
00706 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
00707 const std::vector<std::string>& types = it->types;
00708 for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {
00709 #ifdef __GNUC__
00710 if (strcasecmp(Type,jt->c_str()) == 0)
00711 #else
00712 if (_stricmp(Type,jt->c_str()) == 0)
00713 #endif
00714 modules.push_back(it->module);
00715 }
00716 }
00717
00718 return modules;
00719 }
00720
00721 std::vector<std::string> Application::getExportModules() const
00722 {
00723 std::vector<std::string> modules;
00724 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it)
00725 modules.push_back(it->module);
00726 std::sort(modules.begin(), modules.end());
00727 modules.erase(std::unique(modules.begin(), modules.end()), modules.end());
00728 return modules;
00729 }
00730
00731 std::vector<std::string> Application::getExportTypes(const char* Module) const
00732 {
00733 std::vector<std::string> types;
00734 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
00735 #ifdef __GNUC__
00736 if (strcasecmp(Module,it->module.c_str()) == 0)
00737 #else
00738 if (_stricmp(Module,it->module.c_str()) == 0)
00739 #endif
00740 types.insert(types.end(), it->types.begin(), it->types.end());
00741 }
00742
00743 return types;
00744 }
00745
00746 std::vector<std::string> Application::getExportTypes(void) const
00747 {
00748 std::vector<std::string> types;
00749 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
00750 types.insert(types.end(), it->types.begin(), it->types.end());
00751 }
00752
00753 std::sort(types.begin(), types.end());
00754 types.erase(std::unique(types.begin(), types.end()), types.end());
00755
00756 return types;
00757 }
00758
00759 std::map<std::string, std::string> Application::getExportFilters(const char* Type) const
00760 {
00761 std::map<std::string, std::string> moduleFilter;
00762 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
00763 const std::vector<std::string>& types = it->types;
00764 for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {
00765 #ifdef __GNUC__
00766 if (strcasecmp(Type,jt->c_str()) == 0)
00767 #else
00768 if (_stricmp(Type,jt->c_str()) == 0)
00769 #endif
00770 moduleFilter[it->filter] = it->module;
00771 }
00772 }
00773
00774 return moduleFilter;
00775 }
00776
00777 std::map<std::string, std::string> Application::getExportFilters(void) const
00778 {
00779 std::map<std::string, std::string> filter;
00780 for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
00781 filter[it->filter] = it->module;
00782 }
00783
00784 return filter;
00785 }
00786
00787
00788
00789 void Application::slotNewObject(const App::DocumentObject&O)
00790 {
00791 this->signalNewObject(O);
00792 }
00793
00794 void Application::slotDeletedObject(const App::DocumentObject&O)
00795 {
00796 this->signalDeletedObject(O);
00797 }
00798
00799 void Application::slotChangedObject(const App::DocumentObject&O, const App::Property& P)
00800 {
00801 this->signalChangedObject(O,P);
00802 }
00803
00804 void Application::slotRenamedObject(const App::DocumentObject&O)
00805 {
00806 this->signalRenamedObject(O);
00807 }
00808
00809 void Application::slotActivatedObject(const App::DocumentObject&O)
00810 {
00811 this->signalActivatedObject(O);
00812 }
00813
00814
00815
00816
00817
00818 Application * Application::_pcSingleton = 0;
00819
00820 int Application::_argc;
00821 char ** Application::_argv;
00822
00823
00824 void Application::destruct(void)
00825 {
00826
00827 Console().Log("Saving system parameter...\n");
00828 _pcSysParamMngr->SaveDocument(mConfig["SystemParameter"].c_str());
00829
00830 Console().Log("Saving system parameter...done\n");
00831 Console().Log("Saving user parameter...\n");
00832 _pcUserParamMngr->SaveDocument(mConfig["UserParameter"].c_str());
00833 Console().Log("Saving user parameter...done\n");
00834
00835 delete _pcSysParamMngr;
00836 delete _pcUserParamMngr;
00837
00838
00839 assert(_pcSingleton);
00840 delete _pcSingleton;
00841
00842
00843 destructObserver();
00844
00845 Base::Interpreter().finalize();
00846
00847 ScriptFactorySingleton::Destruct();
00848 InterpreterSingleton::Destruct();
00849 Base::Type::destruct();
00850 }
00851
00852 void Application::destructObserver(void)
00853 {
00854 if ( _pConsoleObserverFile ) {
00855 Console().DetachObserver(_pConsoleObserverFile);
00856 delete _pConsoleObserverFile;
00857 _pConsoleObserverFile = 0;
00858 }
00859 if ( _pConsoleObserverStd ) {
00860 Console().DetachObserver(_pConsoleObserverStd);
00861 delete _pConsoleObserverStd;
00862 _pConsoleObserverFile = 0;
00863 }
00864 }
00865
00869 #ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
00870 int __cdecl freecadNewHandler(size_t size )
00871 {
00872
00873 throw Base::MemoryException();
00874 return 0;
00875 }
00876 #else // Ansi C/C++ new handler
00877 static void freecadNewHandler ()
00878 {
00879
00880 throw Base::MemoryException();
00881 }
00882 #endif
00883
00884 void segmentation_fault_handler(int sig)
00885 {
00886 switch (sig) {
00887 case SIGSEGV:
00888 std::cerr << "Illegal storage access..." << std::endl;
00889 break;
00890 case SIGABRT:
00891 std::cerr << "Abnormal program termination..." << std::endl;
00892 break;
00893 default:
00894 std::cerr << "Unknown error occurred..." << std::endl;
00895 break;
00896 }
00897
00898 #if defined(__GNUC__)
00899
00900 exit(3);
00901 #endif
00902 }
00903
00904 void unhandled_exception_handler()
00905 {
00906 std::cerr << "Unhandled exception..." << std::endl;
00907 }
00908
00909 void unexpection_error_handler()
00910 {
00911 std::cerr << "Unexpected error occurred..." << std::endl;
00912 terminate();
00913 }
00914
00915
00916 void Application::init(int argc, char ** argv)
00917 {
00918 try {
00919
00920 #ifdef _MSC_VER // Microsoft compiler
00921 _set_new_handler ( freecadNewHandler );
00922 _set_new_mode( 1 );
00923 #else // Ansi compiler
00924 std::set_new_handler (freecadNewHandler);
00925 #endif
00926
00927
00928 std::signal(SIGSEGV,segmentation_fault_handler);
00929 std::signal(SIGABRT,segmentation_fault_handler);
00930 std::set_terminate(unhandled_exception_handler);
00931 std::set_unexpected(unexpection_error_handler);
00932
00933 initTypes();
00934
00935 #if (BOOST_VERSION < 104600) || (BOOST_FILESYSTEM_VERSION == 2)
00936 boost::filesystem::path::default_name_check(boost::filesystem::no_check);
00937 #endif
00938
00939 initConfig(argc,argv);
00940 initApplication();
00941 }
00942 catch (...) {
00943
00944 destructObserver();
00945 throw;
00946 }
00947 }
00948
00949 void Application::initTypes(void)
00950 {
00951
00952 Base::Type ::init();
00953 Base::BaseClass ::init();
00954 Base::Exception ::init();
00955 Base::Persistence ::init();
00956
00957
00958 Data::ComplexGeoData ::init();
00959 Data::Segment ::init();
00960
00961
00962 App ::Property ::init();
00963 App ::PropertyContainer ::init();
00964 App ::PropertyLists ::init();
00965 App ::PropertyBool ::init();
00966 App ::PropertyFloat ::init();
00967 App ::PropertyFloatList ::init();
00968 App ::PropertyFloatConstraint ::init();
00969 App ::PropertyAngle ::init();
00970 App ::PropertyDistance ::init();
00971 App ::PropertyLength ::init();
00972 App ::PropertySpeed ::init();
00973 App ::PropertyAcceleration ::init();
00974 App ::PropertyInteger ::init();
00975 App ::PropertyIntegerConstraint ::init();
00976 App ::PropertyPercent ::init();
00977 App ::PropertyEnumeration ::init();
00978 App ::PropertyIntegerList ::init();
00979 App ::PropertyString ::init();
00980 App ::PropertyFont ::init();
00981 App ::PropertyStringList ::init();
00982 App ::PropertyLink ::init();
00983 App ::PropertyLinkSub ::init();
00984 App ::PropertyLinkList ::init();
00985 App ::PropertyLinkSubList ::init();
00986 App ::PropertyMatrix ::init();
00987 App ::PropertyVector ::init();
00988 App ::PropertyVectorList ::init();
00989 App ::PropertyPlacement ::init();
00990 App ::PropertyPlacementLink ::init();
00991 App ::PropertyGeometry ::init();
00992 App ::PropertyComplexGeoData ::init();
00993 App ::PropertyColor ::init();
00994 App ::PropertyColorList ::init();
00995 App ::PropertyMaterial ::init();
00996 App ::PropertyPath ::init();
00997 App ::PropertyFile ::init();
00998 App ::PropertyFileIncluded ::init();
00999 App ::PropertyPythonObject ::init();
01000
01001 App ::DocumentObject ::init();
01002 App ::GeoFeature ::init();
01003 App ::FeatureTest ::init();
01004 App ::FeatureTestException ::init();
01005 App ::FeaturePython ::init();
01006 App ::GeometryPython ::init();
01007 App ::Document ::init();
01008 App ::DocumentObjectGroup ::init();
01009 App ::DocumentObjectGroupPython ::init();
01010 App ::DocumentObjectFileIncluded::init();
01011 App ::InventorObject ::init();
01012 App ::VRMLObject ::init();
01013 App ::Annotation ::init();
01014 App ::AnnotationLabel ::init();
01015 App ::MeasureDistance ::init();
01016 }
01017
01018 void Application::initConfig(int argc, char ** argv)
01019 {
01020
01021 mConfig["AppHomePath"] = FindHomePath(argv[0]);
01022
01023
01024
01025
01026 if (App::Application::Config().find("BuildVersionMajor") == App::Application::Config().end()) {
01027 std::stringstream str; str << FCVersionMajor << "." << FCVersionMinor;
01028 App::Application::Config()["ExeVersion"] = str.str();
01029 App::Application::Config()["BuildVersionMajor"] = FCVersionMajor;
01030 App::Application::Config()["BuildVersionMinor"] = FCVersionMinor;
01031 App::Application::Config()["BuildRevision"] = FCRevision;
01032 App::Application::Config()["BuildRepositoryURL"] = FCRepositoryURL;
01033 App::Application::Config()["BuildRevisionDate"] = FCCurrentDateT;
01034 }
01035
01036 _argc = argc;
01037 _argv = argv;
01038
01039
01040 ExtractUserPath();
01041
01042 # ifdef FC_DEBUG
01043 mConfig["Debug"] = "1";
01044 # else
01045 mConfig["Debug"] = "0";
01046 # endif
01047
01048
01049 mConfig["PythonSearchPath"] = Interpreter().init(argc,argv);
01050
01051
01052 ParseOptions(argc,argv);
01053
01054
01055 Base::PyGILStateLocker lock;
01056 _pConsoleObserverStd = new ConsoleObserverStd();
01057 Console().AttachObserver(_pConsoleObserverStd);
01058 if (mConfig["Verbose"] == "Strict")
01059 Console().SetMode(ConsoleSingleton::Verbose);
01060
01061
01062 if (mConfig["LoggingFile"] == "1") {
01063 _pConsoleObserverFile = new ConsoleObserverFile(mConfig["LoggingFileName"].c_str());
01064 Console().AttachObserver(_pConsoleObserverFile);
01065 }
01066 else
01067 _pConsoleObserverFile = 0;
01068
01069
01070 if (!(mConfig["Verbose"] == "Strict"))
01071 Console().Message("%s %s, Libs: %s.%sR%s\n%s",mConfig["ExeName"].c_str(),
01072 mConfig["ExeVersion"].c_str(),
01073 mConfig["BuildVersionMajor"].c_str(),
01074 mConfig["BuildVersionMinor"].c_str(),
01075 mConfig["BuildRevision"].c_str(),
01076 mConfig["ConsoleBanner"].c_str());
01077 else
01078 Console().Message("%s %s, Libs: %s.%sB%s\n",mConfig["ExeName"].c_str(),
01079 mConfig["ExeVersion"].c_str(),
01080 mConfig["BuildVersionMajor"].c_str(),
01081 mConfig["BuildVersionMinor"].c_str(),
01082 mConfig["BuildRevision"].c_str());
01083
01084 LoadParameters();
01085
01086
01087 UnitsApi::setDefaults();
01088
01089
01090 SaveEnv("PYTHONPATH");
01091 SaveEnv("PYTHONHOME");
01092 SaveEnv("TCL_LIBRARY");
01093 SaveEnv("TCLLIBPATH");
01094
01095
01096 SaveEnv("CSF_MDTVFontDirectory");
01097 SaveEnv("CSF_MDTVTexturesDirectory");
01098 SaveEnv("CSF_UnitsDefinition");
01099 SaveEnv("CSF_UnitsLexicon");
01100 SaveEnv("CSF_StandardDefaults");
01101 SaveEnv("CSF_PluginDefaults");
01102 SaveEnv("CSF_LANGUAGE");
01103 SaveEnv("CSF_SHMessage");
01104 SaveEnv("CSF_XCAFDefaults");
01105 SaveEnv("CSF_GraphicShr");
01106 SaveEnv("CSF_IGESDefaults");
01107 SaveEnv("CSF_STEPDefaults");
01108
01109
01110 SaveEnv("PATH");
01111 logStatus();
01112 }
01113
01114 void Application::SaveEnv(const char* s)
01115 {
01116 char *c = getenv(s);
01117 if (c)
01118 mConfig[s] = c;
01119 }
01120
01121 void Application::initApplication(void)
01122 {
01123
01124
01125 new ScriptProducer( "FreeCADInit", FreeCADInit );
01126 new ScriptProducer( "FreeCADTest", FreeCADTest );
01127
01128
01129 if (!(mConfig["Verbose"] == "Strict")) Console().Log("Create Application\n");
01130 Application::_pcSingleton = new Application(0,0,mConfig);
01131
01132
01133
01134
01135
01136
01137
01138 Interpreter().runString(Base::ScriptFactory().ProduceScript("FreeCADInit"));
01139 }
01140
01141 void Application::processCmdLineFiles(void)
01142 {
01143 Base::Console().Log("Init: Processing command line files\n");
01144
01145
01146 unsigned short count = 0;
01147 count = atoi(mConfig["OpenFileCount"].c_str());
01148 std::string File;
01149
01150 if (count == 0 && mConfig["RunMode"] == "Exit")
01151 mConfig["RunMode"] = "Cmd";
01152
01153 for (unsigned short i=0; i<count; i++) {
01154
01155 std::ostringstream temp;
01156 temp << "OpenFile" << i;
01157
01158 FileInfo File(mConfig[temp.str()].c_str());
01159
01160 std::string Ext = File.extension();
01161 Base::Console().Log("Init: Processing file: %s\n",File.filePath().c_str());
01162 try {
01163
01164 if (File.hasExtension("fcstd") || File.hasExtension("std")) {
01165
01166 Application::_pcSingleton->openDocument(File.filePath().c_str());
01167 }
01168 else if (File.hasExtension("fcscript")||File.hasExtension("fcmacro")) {
01169 Base::Interpreter().runFile(File.filePath().c_str());
01170 }
01171 else if (File.hasExtension("py")) {
01172 Base::Interpreter().loadModule(File.fileNamePure().c_str());
01173 }
01174 else {
01175 std::vector<std::string> mods = App::GetApplication().getImportModules(Ext.c_str());
01176 if (!mods.empty()) {
01177 Base::Interpreter().loadModule(mods.front().c_str());
01178 Base::Interpreter().runStringArg("import %s",mods.front().c_str());
01179 Base::Interpreter().runStringArg("%s.open(\"%s\")",mods.front().c_str(),File.filePath().c_str());
01180 Base::Console().Log("Command line open: %s.Open(\"%s\")\n",mods.front().c_str(),File.filePath().c_str());
01181 }
01182 else {
01183 Console().Warning("File format not supported: %s \n", File.filePath().c_str());
01184 }
01185 }
01186 }
01187 catch (const Base::Exception& e) {
01188 Console().Error("Exception while processing file: %s [%s]\n", File.filePath().c_str(), e.what());
01189 }
01190 catch (...) {
01191 Console().Error("Unknown exception while processing file: %s \n", File.filePath().c_str());
01192 }
01193 }
01194 }
01195
01196 void Application::runApplication()
01197 {
01198
01199 processCmdLineFiles();
01200
01201 if (mConfig["RunMode"] == "Cmd") {
01202
01203 Interpreter().runCommandLine("FreeCAD Console mode");
01204 }
01205 else if (mConfig["RunMode"] == "Internal") {
01206
01207 Console().Log("Running internal script:\n");
01208 Interpreter().runString(Base::ScriptFactory().ProduceScript(mConfig["ScriptFileName"].c_str()));
01209 }
01210 else if (mConfig["RunMode"] == "Exit") {
01211
01212 Console().Log("Exiting on purpose\n");
01213 }
01214 else {
01215 Console().Log("Unknown Run mode (%d) in main()?!?\n\n",mConfig["RunMode"].c_str());
01216 }
01217 }
01218
01219 void Application::logStatus()
01220 {
01221 time_t now;
01222 time(&now);
01223 Console().Log("Time = %s", ctime(&now));
01224
01225 for (std::map<std::string,std::string>::iterator It = mConfig.begin();It!= mConfig.end();It++) {
01226 Console().Log("%s = %s\n",It->first.c_str(),It->second.c_str());
01227 }
01228 }
01229
01230 void Application::LoadParameters(void)
01231 {
01232
01233 _pcSysParamMngr = new ParameterManager();
01234 _pcUserParamMngr = new ParameterManager();
01235
01236
01237
01238 if (mConfig.find("UserParameter") == mConfig.end())
01239 mConfig["UserParameter"] = mConfig["UserAppData"] + "user.cfg";
01240 if (mConfig.find("SystemParameter") == mConfig.end())
01241 mConfig["SystemParameter"] = mConfig["UserAppData"] + "system.cfg";
01242
01243
01244 try {
01245 if (_pcSysParamMngr->LoadOrCreateDocument(mConfig["SystemParameter"].c_str()) && !(mConfig["Verbose"] == "Strict")) {
01246
01247 if (!Py_IsInitialized()) {
01248 Console().Warning(" Parameter not existing, write initial one\n");
01249 Console().Message(" This warning normally means that FreeCAD is running the first time\n"
01250 " or the configuration was deleted or moved. Build up the standard\n"
01251 " configuration.\n");
01252 }
01253 }
01254 }
01255 catch (const Base::Exception& e) {
01256
01257 Base::Console().Error("%s in file %s.\n"
01258 "Continue with an empty configuration.",
01259 e.what(), mConfig["SystemParameter"].c_str());
01260 _pcSysParamMngr->CreateDocument();
01261 }
01262
01263 try {
01264 if (_pcUserParamMngr->LoadOrCreateDocument(mConfig["UserParameter"].c_str()) && !(mConfig["Verbose"] == "Strict")) {
01265
01266 if (!Py_IsInitialized()) {
01267 Console().Warning(" User settings not existing, write initial one\n");
01268 Console().Message(" This warning normally means that FreeCAD is running the first time\n"
01269 " or your configuration was deleted or moved. The system defaults\n"
01270 " will be reestablished for you.\n");
01271 }
01272 }
01273 }
01274 catch (const Base::Exception& e) {
01275
01276 Base::Console().Error("%s in file %s.\n"
01277 "Continue with an empty configuration.",
01278 e.what(), mConfig["UserParameter"].c_str());
01279 _pcUserParamMngr->CreateDocument();
01280 }
01281 }
01282
01283
01284 #if (defined(_MSC_VER) && (_MSC_VER != 1600))
01285
01286 namespace boost { namespace program_options { std::string arg="arg"; } }
01287 #if (defined (BOOST_VERSION) && (BOOST_VERSION == 104100))
01288 namespace boost { namespace program_options {
01289 const unsigned options_description::m_default_line_length = 80;
01290 } }
01291 #endif
01292 #endif
01293
01294 #if 0 // it seemse the SUSE has fixed the broken boost package
01295
01296 #if defined(__GNUC__)
01297 #if BOOST_VERSION == 104400
01298 namespace boost { namespace filesystem {
01299 bool no_check( const std::string & ) { return true; }
01300 } }
01301 #endif
01302 #endif
01303 #endif
01304
01305 pair<string, string> customSyntax(const string& s)
01306 {
01307 if (s.find("-display") == 0)
01308 return make_pair(string("display"), string("null"));
01309 else if (s.find("-style") == 0)
01310 return make_pair(string("style"), string("null"));
01311 else if (s.find("-geometry") == 0)
01312 return make_pair(string("geometry"), string("null"));
01313 else if (s.find("-font") == 0)
01314 return make_pair(string("font"), string("null"));
01315 else if (s.find("-fn") == 0)
01316 return make_pair(string("fn"), string("null"));
01317 else if (s.find("-background") == 0)
01318 return make_pair(string("background"), string("null"));
01319 else if (s.find("-bg") == 0)
01320 return make_pair(string("bg"), string("null"));
01321 else if (s.find("-foreground") == 0)
01322 return make_pair(string("foreground"), string("null"));
01323 else if (s.find("-fg") == 0)
01324 return make_pair(string("fg"), string("null"));
01325 else if (s.find("-button") == 0)
01326 return make_pair(string("button"), string("null"));
01327 else if (s.find("-button") == 0)
01328 return make_pair(string("button"), string("null"));
01329 else if (s.find("-btn") == 0)
01330 return make_pair(string("btn"), string("null"));
01331 else if (s.find("-name") == 0)
01332 return make_pair(string("name"), string("null"));
01333 else if (s.find("-title") == 0)
01334 return make_pair(string("title"), string("null"));
01335 else if (s.find("-visual") == 0)
01336 return make_pair(string("visual"), string("null"));
01337
01338
01339
01340
01341 else if ('@' == s[0])
01342 return std::make_pair(string("response-file"), s.substr(1));
01343 else
01344 return make_pair(string(), string());
01345
01346 }
01347
01348
01349 template<class T>
01350 ostream& operator<<(ostream& os, const vector<T>& v)
01351 {
01352 copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));
01353 return os;
01354 }
01355
01356 void Application::ParseOptions(int ac, char ** av)
01357 {
01358
01359
01360 options_description generic("Generic options");
01361 generic.add_options()
01362 ("version,v", "Prints version string")
01363 ("help,h", "Prints help message")
01364 ("console,c", "Starts in console mode")
01365 ("response-file", value<string>(),"Can be specified with '@name', too")
01366 ;
01367
01368
01369
01370
01371 std::string descr("Writes a log file to:\n");
01372 descr += mConfig["UserAppData"];
01373 descr += mConfig["ExeName"];
01374 descr += ".log";
01375 boost::program_options::options_description config("Configuration");
01376 config.add_options()
01377
01378 ("write-log,l", descr.c_str())
01379 ("log-file", value<string>(), "Unlike to --write-log this allows to log to an arbitrary file")
01380 ("user-cfg,u", value<string>(),"User config file to load/save user settings")
01381 ("system-cfg,s", value<string>(),"Systen config file to load/save system settings")
01382 ("run-test,t", value<int>() ,"Test level")
01383 ("module-path,M", value< vector<string> >()->composing(),"Additional module paths")
01384 ("python-path,P", value< vector<string> >()->composing(),"Additional python paths")
01385 ;
01386
01387
01388
01389
01390 boost::program_options::options_description hidden("Hidden options");
01391 hidden.add_options()
01392 ("input-file", boost::program_options::value< vector<string> >(), "input file")
01393
01394 ("style", boost::program_options::value< string >(), "set the application GUI style")
01395 ("display", boost::program_options::value< string >(), "set the X-Server")
01396 ("geometry ", boost::program_options::value< string >(), "set the X-Window geometry")
01397 ("font", boost::program_options::value< string >(), "set the X-Window font")
01398 ("fn", boost::program_options::value< string >(), "set the X-Window font")
01399 ("background", boost::program_options::value< string >(), "set the X-Window background color")
01400 ("bg", boost::program_options::value< string >(), "set the X-Window background color")
01401 ("foreground", boost::program_options::value< string >(), "set the X-Window foreground color")
01402 ("fg", boost::program_options::value< string >(), "set the X-Window foreground color")
01403 ("button", boost::program_options::value< string >(), "set the X-Window button color")
01404 ("btn", boost::program_options::value< string >(), "set the X-Window button color")
01405 ("name", boost::program_options::value< string >(), "set the X-Window name")
01406 ("title", boost::program_options::value< string >(), "set the X-Window title")
01407 ("visual", boost::program_options::value< string >(), "set the X-Window to color scema")
01408 ("ncols", boost::program_options::value< int >(), "set the X-Window to color scema")
01409 ("cmap", "set the X-Window to color scema")
01410 ;
01411
01412
01413
01414
01415
01416
01417
01418 options_description cmdline_options;
01419 cmdline_options.add(generic).add(config).add(hidden);
01420
01421 boost::program_options::options_description config_file_options;
01422 config_file_options.add(config).add(hidden);
01423
01424 boost::program_options::options_description visible("Allowed options");
01425 visible.add(generic).add(config);
01426
01427 boost::program_options::positional_options_description p;
01428 p.add("input-file", -1);
01429
01430 variables_map vm;
01431 try {
01432 store( boost::program_options::command_line_parser(ac, av).
01433 options(cmdline_options).positional(p).extra_parser(customSyntax).run(), vm);
01434
01435 std::ifstream ifs("FreeCAD.cfg");
01436 store(parse_config_file(ifs, config_file_options), vm);
01437 notify(vm);
01438 }
01439 catch (const std::exception& e) {
01440 cerr << e.what() << endl << endl << visible << endl;
01441 exit(1);
01442 }
01443 catch (...) {
01444 cerr << "Wrong or unknown option, bailing out!" << endl << endl << visible << endl;
01445 exit(1);
01446 }
01447
01448 if (vm.count("help")) {
01449 cout << mConfig["ExeName"] << endl << endl;
01450 cout << "For detailed descripton see http://free-cad.sf.net" << endl<<endl;
01451 cout << "Usage: " << mConfig["ExeName"] << " [options] File1 File2 ..." << endl << endl;
01452 cout << visible << endl;
01453 exit(0);
01454 }
01455
01456 if (vm.count("response-file")) {
01457
01458 std::ifstream ifs(vm["response-file"].as<string>().c_str());
01459 if (!ifs) {
01460 Base::Console().Error("Could no open the response file\n");
01461 cerr << "Could no open the response file: '"
01462 << vm["response-file"].as<string>() << "'" << endl;
01463 exit(1);
01464 }
01465
01466 stringstream ss;
01467 ss << ifs.rdbuf();
01468
01469 char_separator<char> sep(" \n\r");
01470 tokenizer<char_separator<char> > tok(ss.str(), sep);
01471 vector<string> args;
01472 copy(tok.begin(), tok.end(), back_inserter(args));
01473
01474 store( boost::program_options::command_line_parser(ac, av).
01475 options(cmdline_options).positional(p).extra_parser(customSyntax).run(), vm);
01476 }
01477
01478 if (vm.count("version")) {
01479 std::cout << mConfig["ExeName"] << " " << mConfig["ExeVersion"]
01480 << " Revision: " << mConfig["BuildRevision"] << std::endl;
01481 exit(0);
01482 }
01483
01484 if (vm.count("console")) {
01485 mConfig["RunMode"] = "Cmd";
01486 }
01487
01488 if (vm.count("module-path")) {
01489 vector<string> Mods = vm["module-path"].as< vector<string> >();
01490 string temp;
01491 for (vector<string>::const_iterator It= Mods.begin();It != Mods.end();++It)
01492 temp += *It + ";";
01493 temp.erase(temp.end()-1);
01494 mConfig["AdditionalModulePaths"] = temp;
01495 }
01496
01497 if (vm.count("python-path")) {
01498 vector<string> Paths = vm["python-path"].as< vector<string> >();
01499 for (vector<string>::const_iterator It= Paths.begin();It != Paths.end();++It)
01500 Base::Interpreter().addPythonPath(It->c_str());
01501 }
01502
01503 if (vm.count("input-file")) {
01504 vector<string> files(vm["input-file"].as< vector<string> >());
01505 int OpenFileCount=0;
01506 for (vector<string>::const_iterator It = files.begin();It != files.end();++It) {
01507
01508
01509
01510
01511 std::ostringstream temp;
01512 temp << "OpenFile" << OpenFileCount;
01513 mConfig[temp.str()] = *It;
01514 OpenFileCount++;
01515 }
01516 std::ostringstream buffer;
01517 buffer << OpenFileCount;
01518 mConfig["OpenFileCount"] = buffer.str();
01519 }
01520
01521 if (vm.count("write-log")) {
01522 mConfig["LoggingFile"] = "1";
01523
01524 mConfig["LoggingFileName"] = mConfig["UserAppData"] + mConfig["ExeName"] + ".log";
01525 }
01526
01527 if (vm.count("log-file")) {
01528 mConfig["LoggingFile"] = "1";
01529 mConfig["LoggingFileName"] = vm["log-file"].as<string>();
01530 }
01531
01532 if (vm.count("user-cfg")) {
01533 mConfig["UserParameter"] = vm["user-cfg"].as<string>();
01534 }
01535
01536 if (vm.count("system-cfg")) {
01537 mConfig["SystemParameter"] = vm["system-cfg"].as<string>();
01538 }
01539
01540 if (vm.count("run-test")) {
01541 int level = vm["run-test"].as<int>();
01542 switch (level) {
01543 case '0':
01544
01545 mConfig["RunMode"] = "Internal";
01546 mConfig["ScriptFileName"] = "FreeCADTest";
01547
01548 break;
01549 default:
01550
01551 mConfig["RunMode"] = "Internal";
01552 mConfig["ScriptFileName"] = "FreeCADTest";
01553
01554 break;
01555 };
01556 }
01557
01558 }
01559
01560 void Application::ExtractUserPath()
01561 {
01562
01563 mConfig["BinPath"] = mConfig["AppHomePath"] + "bin" + PATHSEP;
01564 mConfig["DocPath"] = mConfig["AppHomePath"] + "doc" + PATHSEP;
01565
01566 #if defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_BSD)
01567
01568 struct passwd *pwd = getpwuid(getuid());
01569 if (pwd == NULL)
01570 throw Base::Exception("Getting HOME path from system failed!");
01571 mConfig["UserHomePath"] = pwd->pw_dir;
01572 std::string appData = pwd->pw_dir;
01573 Base::FileInfo fi(appData.c_str());
01574 if (!fi.exists()) {
01575
01576 std::stringstream str;
01577 str << "Application data directory " << appData << " does not exist!";
01578 throw Base::Exception(str.str());
01579 }
01580
01581
01582
01583
01584 appData += PATHSEP;
01585 appData += ".";
01586 if (mConfig.find("AppDataSkipVendor") == mConfig.end()) {
01587 appData += mConfig["ExeVendor"];
01588 fi.setFile(appData.c_str());
01589 if (!fi.exists() && !Py_IsInitialized()) {
01590 if (!fi.createDirectory()) {
01591 std::string error = "Cannot create directory ";
01592 error += appData;
01593
01594 std::cerr << error << std::endl;
01595 throw Base::Exception(error);
01596 }
01597 }
01598 appData += PATHSEP;
01599 }
01600
01601 appData += mConfig["ExeName"];
01602 fi.setFile(appData.c_str());
01603 if (!fi.exists() && !Py_IsInitialized()) {
01604 if (!fi.createDirectory()) {
01605 std::string error = "Cannot create directory ";
01606 error += appData;
01607
01608 std::cerr << error << std::endl;
01609 throw Base::Exception(error);
01610 }
01611 }
01612
01613
01614
01615 appData += PATHSEP;
01616 mConfig["UserAppData"] = appData;
01617
01618 #elif defined(FC_OS_MACOSX)
01619
01620 struct passwd *pwd = getpwuid(getuid());
01621 if (pwd == NULL)
01622 throw Base::Exception("Getting HOME path from system failed!");
01623 mConfig["UserHomePath"] = pwd->pw_dir;
01624 std::string appData = pwd->pw_dir;
01625 appData += PATHSEP;
01626 appData += "Library";
01627 appData += PATHSEP;
01628 appData += "Preferences";
01629 Base::FileInfo fi(appData.c_str());
01630 if (!fi.exists()) {
01631
01632 std::stringstream str;
01633 str << "Application data directory " << appData << " does not exist!";
01634 throw Base::Exception(str.str());
01635 }
01636
01637
01638
01639
01640 appData += PATHSEP;
01641 if (mConfig.find("AppDataSkipVendor") == mConfig.end()) {
01642 appData += mConfig["ExeVendor"];
01643 fi.setFile(appData.c_str());
01644 if (!fi.exists() && !Py_IsInitialized()) {
01645 if (!fi.createDirectory()) {
01646 std::string error = "Cannot create directory ";
01647 error += appData;
01648
01649 std::cerr << error << std::endl;
01650 throw Base::Exception(error);
01651 }
01652 }
01653 appData += PATHSEP;
01654 }
01655
01656 appData += mConfig["ExeName"];
01657 fi.setFile(appData.c_str());
01658 if (!fi.exists() && !Py_IsInitialized()) {
01659 if (!fi.createDirectory()) {
01660 std::string error = "Cannot create directory ";
01661 error += appData;
01662
01663 std::cerr << error << std::endl;
01664 throw Base::Exception(error);
01665 }
01666 }
01667
01668
01669
01670 appData += PATHSEP;
01671 mConfig["UserAppData"] = appData;
01672
01673 #elif defined(FC_OS_WIN32)
01674 WCHAR szPath[MAX_PATH];
01675 TCHAR dest[MAX_PATH*3];
01676
01677
01678
01679 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, szPath))) {
01680 WideCharToMultiByte(CP_UTF8, 0, szPath, -1,dest, 256, NULL, NULL);
01681 mConfig["UserHomePath"] = dest;
01682 }
01683 else
01684 mConfig["UserHomePath"] = mConfig["AppHomePath"];
01685
01686
01687
01688
01689 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, szPath))) {
01690
01691 WideCharToMultiByte(CP_UTF8, 0, szPath, -1,dest, 256, NULL, NULL);
01692
01693 std::string appData = dest;
01694 Base::FileInfo fi(appData.c_str());
01695 if (!fi.exists()) {
01696
01697 std::stringstream str;
01698 str << "Application data directory " << appData << " does not exist!";
01699 throw Base::Exception(str.str());
01700 }
01701
01702
01703
01704
01705 if (mConfig.find("AppDataSkipVendor") == mConfig.end()) {
01706 appData += PATHSEP;
01707 appData += mConfig["ExeVendor"];
01708 fi.setFile(appData.c_str());
01709 if (!fi.exists() && !Py_IsInitialized()) {
01710 if (!fi.createDirectory()) {
01711 std::string error = "Cannot create directory ";
01712 error += appData;
01713
01714 std::cerr << error << std::endl;
01715 throw Base::Exception(error);
01716 }
01717 }
01718 }
01719
01720 appData += PATHSEP;
01721 appData += mConfig["ExeName"];
01722 fi.setFile(appData.c_str());
01723 if (!fi.exists() && !Py_IsInitialized()) {
01724 if (!fi.createDirectory()) {
01725 std::string error = "Cannot create directory ";
01726 error += appData;
01727
01728 std::cerr << error << std::endl;
01729 throw Base::Exception(error);
01730 }
01731 }
01732
01733
01734
01735 appData += PATHSEP;
01736 mConfig["UserAppData"] = appData;
01737 }
01738 #else
01739 # error "Implement ExtractUserPath() for your platform."
01740 #endif
01741 }
01742
01743 #if defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_BSD)
01744 #include <stdio.h>
01745 #include <stdlib.h>
01746 #include <sys/param.h>
01747
01748 std::string Application::FindHomePath(const char* sCall)
01749 {
01750
01751
01752
01753 std::string absPath;
01754 std::string homePath;
01755 if (Py_IsInitialized()) {
01756
01757
01758
01759
01760 char resolved[PATH_MAX];
01761 char* path = realpath(sCall, resolved);
01762 if (path)
01763 absPath = path;
01764 }
01765 else {
01766
01767
01768
01769
01770
01771 char resolved[PATH_MAX];
01772 int nchars = readlink("/proc/self/exe", resolved, PATH_MAX);
01773 if (nchars < 0 || nchars >= PATH_MAX)
01774 throw Base::Exception("Cannot determine the absolute path of the executable");
01775 resolved[nchars] = '\0';
01776 absPath = resolved;
01777 }
01778
01779
01780 std::string::size_type pos = absPath.find_last_of("/");
01781 homePath.assign(absPath,0,pos);
01782 pos = homePath.find_last_of("/");
01783 homePath.assign(homePath,0,pos+1);
01784
01785 return homePath;
01786 }
01787
01788 #elif defined(FC_OS_MACOSX)
01789 #include <mach-o/dyld.h>
01790 #include <string>
01791 #include <stdlib.h>
01792 #include <sys/param.h>
01793
01794 std::string Application::FindHomePath(const char* call)
01795 {
01796 uint32_t sz = 0;
01797 char *buf;
01798
01799 _NSGetExecutablePath(NULL, &sz);
01800 buf = (char*) malloc(++sz);
01801
01802 if (_NSGetExecutablePath(buf, &sz) == 0) {
01803 char resolved[PATH_MAX];
01804 char* path = realpath(buf, resolved);
01805 free(buf);
01806
01807 if (path) {
01808 std::string Call(resolved), TempHomePath;
01809 std::string::size_type pos = Call.find_last_of(PATHSEP);
01810 TempHomePath.assign(Call,0,pos);
01811 pos = TempHomePath.find_last_of(PATHSEP);
01812 TempHomePath.assign(TempHomePath,0,pos+1);
01813 return TempHomePath;
01814 }
01815 }
01816
01817 return call;
01818 }
01819
01820 #elif defined (FC_OS_WIN32)
01821 std::string Application::FindHomePath(const char* sCall)
01822 {
01823
01824
01825
01826 char szFileName [MAX_PATH] ;
01827 if (Py_IsInitialized()) {
01828 GetModuleFileName(GetModuleHandle(sCall),szFileName, MAX_PATH-1);
01829 }
01830 else {
01831 GetModuleFileName(0, szFileName, MAX_PATH-1);
01832 }
01833
01834 std::string Call(szFileName), TempHomePath;
01835 std::string::size_type pos = Call.find_last_of(PATHSEP);
01836 TempHomePath.assign(Call,0,pos);
01837 pos = TempHomePath.find_last_of(PATHSEP);
01838 TempHomePath.assign(TempHomePath,0,pos+1);
01839
01840
01841 for (std::string::iterator i=TempHomePath.begin();i!=TempHomePath.end();++i) {
01842 if (*i == '\\')
01843 *i = '/';
01844 }
01845
01846 return TempHomePath;
01847 }
01848
01849 #else
01850 # error "std::string Application::FindHomePath(const char*) not implemented"
01851 #endif