Download src/Mod/Material/App/ExternalManager.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 37.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Material/App/ExternalManager.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Material/App/ExternalManager.cpp
-
curl -L -o ExternalManager.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Material/App/ExternalManager.cpp
37.3 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2024 David Carter <dcarter@david.carter.ca> * | |
| * * | |
| * This file is part of FreeCAD. * | |
| * * | |
| * FreeCAD is free software: you can redistribute it and/or modify it * | |
| * under the terms of the GNU Lesser General Public License as * | |
| * published by the Free Software Foundation, either version 2.1 of the * | |
| * License, or (at your option) any later version. * | |
| * * | |
| * FreeCAD is distributed in the hope that it will be useful, but * | |
| * WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * | |
| * Lesser General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Lesser General Public * | |
| * License along with FreeCAD. If not, see * | |
| * <https://www.gnu.org/licenses/>. * | |
| * * | |
| **************************************************************************/ | |
| using namespace Materials; | |
| /* TRANSLATOR Material::Materials */ | |
| ExternalManager* ExternalManager::_manager = nullptr; | |
| QMutex ExternalManager::_mutex; | |
| ExternalManager::ExternalManager() | |
| : _instantiated(false) | |
| { | |
| _hGrp = App::GetApplication().GetParameterGroupByPath( | |
| "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface"); | |
| _hGrp->Attach(this); | |
| getConfiguration(); | |
| } | |
| ExternalManager::~ExternalManager() | |
| { | |
| _hGrp->Detach(this); | |
| } | |
| void ExternalManager::OnChange(ParameterGrp::SubjectType& /*rCaller*/, ParameterGrp::MessageType Reason) | |
| { | |
| if (std::strncmp(Reason, "Current", 7) == 0) { | |
| if (_instantiated) { | |
| // The old manager object will be deleted when reconnecting | |
| _instantiated = false; | |
| } | |
| getConfiguration(); | |
| } | |
| } | |
| void ExternalManager::getConfiguration() | |
| { | |
| // _hGrp = App::GetApplication().GetParameterGroupByPath( | |
| // "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface"); | |
| auto current = _hGrp->GetASCII("Current", "None"); | |
| if (current == "None") { | |
| _moduleName = ""; | |
| _className = ""; | |
| } | |
| else { | |
| auto groupName = | |
| "User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface/Interfaces/" | |
| + current; | |
| auto hGrp = App::GetApplication().GetParameterGroupByPath(groupName.c_str()); | |
| _moduleName = hGrp->GetASCII("Module", ""); | |
| _className = hGrp->GetASCII("Class", ""); | |
| } | |
| } | |
| void ExternalManager::instantiate() | |
| { | |
| _instantiated = false; | |
| Base::Console().log("Loading external manager…\n"); | |
| if (_moduleName.empty() || _className.empty()) { | |
| Base::Console().log("External module not defined\n"); | |
| return; | |
| } | |
| try { | |
| Base::PyGILStateLocker lock; | |
| Py::Module mod(PyImport_ImportModule(_moduleName.c_str()), true); | |
| if (mod.isNull()) { | |
| Base::Console().log(" failed\n"); | |
| return; | |
| } | |
| Py::Callable managerClass(mod.getAttr(_className)); | |
| _managerObject = managerClass.apply(); | |
| if (!_managerObject.isNull() && _managerObject.hasAttr("APIVersion")) { | |
| _instantiated = true; | |
| } | |
| if (_instantiated) { | |
| Base::Console().log("done\n"); | |
| } | |
| else { | |
| Base::Console().log("failed\n"); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::Console().log("failed\n"); | |
| e.clear(); | |
| } | |
| } | |
| void ExternalManager::connect() | |
| { | |
| if (!_instantiated) { | |
| instantiate(); | |
| if (!_instantiated) { | |
| throw ConnectionError(); | |
| } | |
| } | |
| } | |
| void ExternalManager::initManager() | |
| { | |
| QMutexLocker locker(&_mutex); | |
| if (!_manager) { | |
| _manager = new ExternalManager(); | |
| } | |
| } | |
| ExternalManager* ExternalManager::getManager() | |
| { | |
| initManager(); | |
| return _manager; | |
| } | |
| //===== | |
| // | |
| // Library management | |
| // | |
| //===== | |
| bool ExternalManager::checkMaterialLibraryType(const Py::Object& entry) | |
| { | |
| return entry.hasAttr("name") && entry.hasAttr("icon") && entry.hasAttr("readOnly"); | |
| } | |
| std::shared_ptr<Library> | |
| ExternalManager::libraryFromObject(const Py::Object& entry) | |
| { | |
| if (!checkMaterialLibraryType(entry)) { | |
| throw InvalidLibrary(); | |
| } | |
| Py::String pyName(entry.getAttr("name")); | |
| Py::Bytes pyIcon; | |
| if (entry.getAttr("icon") != Py::None()) { | |
| pyIcon = Py::Bytes(entry.getAttr("icon")); | |
| } | |
| Py::Boolean pyReadOnly(entry.getAttr("readOnly")); | |
| QString libraryName; | |
| if (!pyName.isNone()) { | |
| libraryName = QString::fromStdString(pyName.as_string()); | |
| } | |
| QByteArray icon; | |
| if (!pyIcon.isNone()) { | |
| icon = QByteArray(pyIcon.as_std_string().data(), pyIcon.size()); | |
| } | |
| bool readOnly = pyReadOnly.as_bool(); | |
| auto library = std::make_shared<Library>(libraryName, icon, readOnly); | |
| return library; | |
| } | |
| bool ExternalManager::checkMaterialLibraryObjectType(const Py::Object& entry) | |
| { | |
| return entry.hasAttr("UUID") && entry.hasAttr("path") && entry.hasAttr("name"); | |
| } | |
| LibraryObject ExternalManager::materialLibraryObjectTypeFromObject(const Py::Object& entry) | |
| { | |
| std::string uuid; | |
| auto pyUUID = entry.getAttr("UUID"); | |
| if (!pyUUID.isNone()) { | |
| uuid = pyUUID.as_string(); | |
| } | |
| std::string path; | |
| auto pyPath = entry.getAttr("path"); | |
| if (!pyPath.isNone()) { | |
| path = pyPath.as_string(); | |
| } | |
| std::string name; | |
| auto pyName = entry.getAttr("name"); | |
| if (!pyName.isNone()) { | |
| name = pyName.as_string(); | |
| } | |
| return LibraryObject(uuid, path, name); | |
| } | |
| std::shared_ptr<std::vector<std::shared_ptr<Library>>> | |
| ExternalManager::libraries() | |
| { | |
| auto libList = std::make_shared<std::vector<std::shared_ptr<Library>>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("libraries")) { | |
| Py::Callable libraries(_managerObject.getAttr("libraries")); | |
| Py::List list(libraries.apply()); | |
| for (auto lib : list) { | |
| auto library = libraryFromObject(Py::Object(lib)); | |
| libList->push_back(library); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tlibraries() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| Base::Console().log("Library error %s", e1.what()); | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return libList; | |
| } | |
| std::shared_ptr<std::vector<std::shared_ptr<Library>>> ExternalManager::modelLibraries() | |
| { | |
| auto libList = std::make_shared<std::vector<std::shared_ptr<Library>>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("modelLibraries")) { | |
| Py::Callable libraries(_managerObject.getAttr("modelLibraries")); | |
| Py::List list(libraries.apply()); | |
| for (auto lib : list) { | |
| auto library = libraryFromObject(Py::Tuple(lib)); | |
| libList->push_back(library); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tmodelLibraries() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return libList; | |
| } | |
| std::shared_ptr<std::vector<std::shared_ptr<Library>>> ExternalManager::materialLibraries() | |
| { | |
| auto libList = std::make_shared<std::vector<std::shared_ptr<Library>>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("materialLibraries")) { | |
| Py::Callable libraries(_managerObject.getAttr("materialLibraries")); | |
| Py::List list(libraries.apply()); | |
| for (auto lib : list) { | |
| auto library = libraryFromObject(Py::Tuple(lib)); | |
| libList->push_back(library); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tmaterialLibraries() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return libList; | |
| } | |
| std::shared_ptr<Library> ExternalManager::getLibrary(const QString& name) | |
| { | |
| // throw LibraryNotFound("Not yet implemented"); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("getLibrary")) { | |
| Py::Callable libraries(_managerObject.getAttr("getLibrary")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(name.toStdString())); | |
| Py::Object result(libraries.apply(args)); | |
| auto lib = libraryFromObject(result); | |
| return std::make_shared<Library>(*lib); | |
| } | |
| else { | |
| Base::Console().log("\tgetLibrary() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (const InvalidLibrary&) { | |
| throw LibraryNotFound(); | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| } | |
| void ExternalManager::createLibrary(const QString& libraryName, const QByteArray& icon, bool readOnly) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("createLibrary")) { | |
| Py::Callable libraries(_managerObject.getAttr("createLibrary")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::Bytes(icon.data(), icon.size())); | |
| args.setItem(2, Py::Boolean(readOnly)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tcreateLibrary() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::renameLibrary(const QString& libraryName, const QString& newName) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("renameLibrary")) { | |
| Py::Callable libraries(_managerObject.getAttr("renameLibrary")); | |
| Py::Tuple args(2); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(newName.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\trenameLibrary() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw RenameError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::changeIcon(const QString& libraryName, const QByteArray& icon) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("changeIcon")) { | |
| Py::Callable libraries(_managerObject.getAttr("changeIcon")); | |
| Py::Tuple args(2); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::Bytes(icon.data(), icon.size())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tchangeIcon() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw ReplacementError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::removeLibrary(const QString& libraryName) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("removeLibrary")) { | |
| Py::Callable libraries(_managerObject.getAttr("removeLibrary")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tremoveLibrary() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw DeleteError(e1.what()); | |
| } | |
| } | |
| std::shared_ptr<std::vector<LibraryObject>> | |
| ExternalManager::libraryModels(const QString& libraryName) | |
| { | |
| auto modelList = std::make_shared<std::vector<LibraryObject>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("libraryModels")) { | |
| Py::Callable libraries(_managerObject.getAttr("libraryModels")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| Py::List list(libraries.apply(args)); | |
| for (auto library : list) { | |
| auto entry = Py::Object(library); | |
| if (!checkMaterialLibraryObjectType(entry)) { | |
| throw InvalidModel(); | |
| } | |
| modelList->push_back(materialLibraryObjectTypeFromObject(entry)); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tlibraryModels() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return modelList; | |
| } | |
| std::shared_ptr<std::vector<LibraryObject>> | |
| ExternalManager::libraryMaterials(const QString& libraryName) | |
| { | |
| auto materialList = std::make_shared<std::vector<LibraryObject>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("libraryMaterials")) { | |
| Py::Callable libraries(_managerObject.getAttr("libraryMaterials")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| Py::List list(libraries.apply(args)); | |
| for (auto library : list) { | |
| auto entry = Py::Object(library); | |
| if (!checkMaterialLibraryObjectType(entry)) { | |
| throw InvalidMaterial(); | |
| } | |
| materialList->push_back(materialLibraryObjectTypeFromObject(entry)); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tlibraryMaterials() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return materialList; | |
| } | |
| std::shared_ptr<std::vector<LibraryObject>> | |
| ExternalManager::libraryMaterials(const QString& libraryName, | |
| const MaterialFilter& filter, | |
| const MaterialFilterOptions& options) | |
| { | |
| auto materialList = std::make_shared<std::vector<LibraryObject>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("libraryMaterials")) { | |
| Py::Callable libraries(_managerObject.getAttr("libraryMaterials")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::Object(new MaterialFilterPy(new MaterialFilter(filter)), true)); | |
| args.setItem( | |
| 2, | |
| Py::Object(new MaterialFilterOptionsPy(new MaterialFilterOptions(options)), true)); | |
| Py::List list(libraries.apply(args)); | |
| for (auto library : list) { | |
| auto entry = Py::Object(library); | |
| if (!checkMaterialLibraryObjectType(entry)) { | |
| throw InvalidMaterial(); | |
| } | |
| materialList->push_back(materialLibraryObjectTypeFromObject(entry)); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tlibraryMaterials() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return materialList; | |
| } | |
| std::shared_ptr<std::vector<QString>> ExternalManager::libraryFolders(const QString& libraryName) | |
| { | |
| auto folderList = std::make_shared<std::vector<QString>>(); | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("libraryFolders")) { | |
| Py::Callable folders(_managerObject.getAttr("libraryFolders")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| Py::List list(folders.apply(args)); | |
| for (auto folder : list) { | |
| auto entry = Py::Object(folder); | |
| Py::String pyName(entry.getAttr("name")); | |
| QString folderName; | |
| if (!pyName.isNone()) { | |
| folderName = QString::fromStdString(pyName.as_string()); | |
| } | |
| folderList->push_back(folderName); | |
| } | |
| } | |
| else { | |
| Base::Console().log("\tlibraryFolders() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw LibraryNotFound(e1.what()); | |
| } | |
| return folderList; | |
| } | |
| //===== | |
| // | |
| // Folder management | |
| // | |
| //===== | |
| void ExternalManager::createFolder(const QString& libraryName, const QString& path) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("createFolder")) { | |
| Py::Callable libraries(_managerObject.getAttr("createFolder")); | |
| Py::Tuple args(2); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| Py::Object result(libraries.apply(args)); | |
| } | |
| else { | |
| Base::Console().log("\tcreateFolder() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::renameFolder(const QString& libraryName, | |
| const QString& oldPath, | |
| const QString& newPath) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("renameFolder")) { | |
| Py::Callable libraries(_managerObject.getAttr("renameFolder")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(oldPath.toStdString())); | |
| args.setItem(2, Py::String(newPath.toStdString())); | |
| Py::Object result(libraries.apply(args)); | |
| } | |
| else { | |
| Base::Console().log("\trenameFolder() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw RenameError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::deleteRecursive(const QString& libraryName, const QString& path) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("deleteRecursive")) { | |
| Py::Callable libraries(_managerObject.getAttr("deleteRecursive")); | |
| Py::Tuple args(2); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| Py::Object result(libraries.apply(args)); | |
| } | |
| else { | |
| Base::Console().log("\tdeleteRecursive() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw DeleteError(e1.what()); | |
| } | |
| } | |
| //===== | |
| // | |
| // Model management | |
| // | |
| //===== | |
| bool ExternalManager::checkModelObjectType(const Py::Object& entry) | |
| { | |
| return entry.hasAttr("libraryName") && entry.hasAttr("model"); | |
| } | |
| std::shared_ptr<Model> ExternalManager::modelFromObject(const Py::Object& entry, | |
| const QString& uuid) | |
| { | |
| if (!checkModelObjectType(entry)) { | |
| throw InvalidModel(); | |
| } | |
| Py::String pyName(entry.getAttr("libraryName")); | |
| Py::Object modelObject(entry.getAttr("model")); | |
| QString libraryName; | |
| if (!pyName.isNone()) { | |
| libraryName = QString::fromStdString(pyName.as_string()); | |
| } | |
| // Using this call will use caching, whereas using our class function will not | |
| auto library = ModelManager::getManager().getLibrary(libraryName); | |
| Model* model = static_cast<ModelPy*>(*modelObject)->getModelPtr(); | |
| model->setUUID(uuid); | |
| model->setLibrary(library); | |
| auto shared = std::make_shared<Model>(*model); | |
| return shared; | |
| } | |
| std::shared_ptr<Model> ExternalManager::getModel(const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("getModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("getModel")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(uuid.toStdString())); | |
| Py::Object result(libraries.apply(args)); // ignore return for now | |
| auto shared = modelFromObject(result, uuid); | |
| return shared; | |
| } | |
| else { | |
| Base::Console().log("\tgetModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw ModelNotFound(e1.what()); | |
| } | |
| } | |
| void ExternalManager::addModel(const QString& libraryName, | |
| const QString& path, | |
| const Model& model) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("addModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("addModel")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::Object(new ModelPy(new Model(model)), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\taddModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::migrateModel(const QString& libraryName, | |
| const QString& path, | |
| const Model& model) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("migrateModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("migrateModel")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::Object(new ModelPy(new Model(model)), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tmigrateModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::updateModel(const QString& libraryName, | |
| const QString& path, | |
| const Model& model) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("updateModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("updateModel")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::Object(new ModelPy(new Model(model)), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tupdateModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw UpdateError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::setModelPath(const QString& libraryName, | |
| const QString& path, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("setModelPath")) { | |
| Py::Callable libraries(_managerObject.getAttr("setModelPath")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tsetModelPath() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw UpdateError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::renameModel(const QString& libraryName, | |
| const QString& name, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("renameModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("renameModel")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(name.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\trenameModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw RenameError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::moveModel(const QString& libraryName, | |
| const QString& path, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("moveModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("moveModel")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tmoveModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw MoveError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::removeModel(const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("removeModel")) { | |
| Py::Callable libraries(_managerObject.getAttr("removeModel")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tremoveModel() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw DeleteError(e1.what()); | |
| } | |
| } | |
| //===== | |
| // | |
| // Material management | |
| // | |
| //===== | |
| bool ExternalManager::checkMaterialObjectType(const Py::Object& entry) | |
| { | |
| return entry.hasAttr("libraryName") && entry.hasAttr("material"); | |
| } | |
| std::shared_ptr<Material> ExternalManager::materialFromObject(const Py::Object& entry, | |
| const QString& uuid) | |
| { | |
| if (!checkMaterialObjectType(entry)) { | |
| throw InvalidMaterial(); | |
| } | |
| Py::String pyName(entry.getAttr("libraryName")); | |
| Py::Object materialObject(entry.getAttr("material")); | |
| QString libraryName; | |
| if (!pyName.isNone()) { | |
| libraryName = QString::fromStdString(pyName.as_string()); | |
| } | |
| // Using this call will use caching, whereas using our class function will not | |
| auto library = MaterialManager::getManager().getLibrary(libraryName); | |
| Material* material = static_cast<MaterialPy*>(*materialObject)->getMaterialPtr(); | |
| material->setUUID(uuid); | |
| material->setLibrary(library); | |
| auto shared = std::make_shared<Material>(*material); | |
| return shared; | |
| } | |
| std::shared_ptr<Material> ExternalManager::getMaterial(const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("getMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("getMaterial")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(uuid.toStdString())); | |
| Py::Object result(libraries.apply(args)); | |
| auto shared = materialFromObject(result, uuid); | |
| return shared; | |
| } | |
| else { | |
| Base::Console().log("\tgetMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw MaterialNotFound(e1.what()); | |
| } | |
| } | |
| void ExternalManager::addMaterial(const QString& libraryName, | |
| const QString& path, | |
| const Material& material) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("addMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("addMaterial")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::Object(new MaterialPy(new Material(material)), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\taddMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::migrateMaterial(const QString& libraryName, | |
| const QString& path, | |
| const Material& material) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("migrateMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("migrateMaterial")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| auto mat = new Material(material); | |
| args.setItem(2, Py::Object(new MaterialPy(mat), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tmigrateMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw CreationError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::updateMaterial(const QString& libraryName, | |
| const QString& path, | |
| const Material& material) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("updateMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("updateMaterial")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::Object(new MaterialPy(new Material(material)), true)); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tupdateMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw UpdateError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::setMaterialPath(const QString& libraryName, | |
| const QString& path, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("setMaterialPath")) { | |
| Py::Callable libraries(_managerObject.getAttr("setMaterialPath")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tsetMaterialPath() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw UpdateError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::renameMaterial(const QString& libraryName, | |
| const QString& name, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("renameMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("renameMaterial")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(name.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\trenameMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw RenameError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::moveMaterial(const QString& libraryName, | |
| const QString& path, | |
| const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("moveMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("moveMaterial")); | |
| Py::Tuple args(3); | |
| args.setItem(0, Py::String(libraryName.toStdString())); | |
| args.setItem(1, Py::String(path.toStdString())); | |
| args.setItem(2, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tmoveMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw MoveError(e1.what()); | |
| } | |
| } | |
| void ExternalManager::removeMaterial(const QString& uuid) | |
| { | |
| connect(); | |
| Base::PyGILStateLocker lock; | |
| try { | |
| if (_managerObject.hasAttr("removeMaterial")) { | |
| Py::Callable libraries(_managerObject.getAttr("removeMaterial")); | |
| Py::Tuple args(1); | |
| args.setItem(0, Py::String(uuid.toStdString())); | |
| libraries.apply(args); // No return expected | |
| } | |
| else { | |
| Base::Console().log("\tremoveMaterial() not found\n"); | |
| throw ConnectionError(); | |
| } | |
| } | |
| catch (Py::Exception& e) { | |
| Base::PyException e1; // extract the Python error text | |
| throw DeleteError(e1.what()); | |
| } | |
| } | |