Materials: External interface refinements (#21524)
This commit is contained in:
@@ -300,6 +300,36 @@ public:
|
||||
~ReplacementError() noexcept override = default;
|
||||
};
|
||||
|
||||
class UpdateError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
UpdateError()
|
||||
: Base::Exception("Unable to update object")
|
||||
{}
|
||||
explicit UpdateError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit UpdateError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~UpdateError() noexcept override = default;
|
||||
};
|
||||
|
||||
class MoveError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
MoveError()
|
||||
: Base::Exception("Unable to move object")
|
||||
{}
|
||||
explicit MoveError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit MoveError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~MoveError() noexcept override = default;
|
||||
};
|
||||
|
||||
class ConnectionError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -36,8 +36,10 @@
|
||||
#include "ExternalManager.h"
|
||||
#include "MaterialLibrary.h"
|
||||
#include "MaterialLibraryPy.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "ModelLibrary.h"
|
||||
#include "ModelManager.h"
|
||||
#include "ModelPy.h"
|
||||
#include "MaterialFilterPy.h"
|
||||
#include "MaterialFilterOptionsPy.h"
|
||||
@@ -98,10 +100,10 @@ void ExternalManager::getConfiguration()
|
||||
void ExternalManager::instantiate()
|
||||
{
|
||||
_instantiated = false;
|
||||
Base::Console().Log("Loading external manager...\n");
|
||||
Base::Console().log("Loading external manager...\n");
|
||||
|
||||
if (_moduleName.empty() || _className.empty()) {
|
||||
Base::Console().Log("External module not defined\n");
|
||||
Base::Console().log("External module not defined\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,7 +112,7 @@ void ExternalManager::instantiate()
|
||||
Py::Module mod(PyImport_ImportModule(_moduleName.c_str()), true);
|
||||
|
||||
if (mod.isNull()) {
|
||||
Base::Console().Log(" failed\n");
|
||||
Base::Console().log(" failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -121,14 +123,14 @@ void ExternalManager::instantiate()
|
||||
}
|
||||
|
||||
if (_instantiated) {
|
||||
Base::Console().Log("done\n");
|
||||
Base::Console().log("done\n");
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("failed\n");
|
||||
Base::Console().log("failed\n");
|
||||
}
|
||||
}
|
||||
catch (Py::Exception& e) {
|
||||
Base::Console().Log("failed\n");
|
||||
Base::Console().log("failed\n");
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
@@ -168,8 +170,7 @@ ExternalManager* ExternalManager::getManager()
|
||||
|
||||
bool ExternalManager::checkMaterialLibraryType(const Py::Object& entry)
|
||||
{
|
||||
return entry.hasAttr("name") && entry.hasAttr("icon") && entry.hasAttr("readOnly")
|
||||
&& entry.hasAttr("timestamp");
|
||||
return entry.hasAttr("name") && entry.hasAttr("icon") && entry.hasAttr("readOnly");
|
||||
}
|
||||
|
||||
std::shared_ptr<Library>
|
||||
@@ -180,57 +181,53 @@ ExternalManager::libraryFromObject(const Py::Object& entry)
|
||||
}
|
||||
|
||||
Py::String pyName(entry.getAttr("name"));
|
||||
Py::Bytes pyIcon(entry.getAttr("icon"));
|
||||
Py::Bytes pyIcon;
|
||||
if (entry.getAttr("icon") != Py::None()) {
|
||||
pyIcon = Py::Bytes(entry.getAttr("icon"));
|
||||
}
|
||||
Py::Boolean pyReadOnly(entry.getAttr("readOnly"));
|
||||
Py::String pyTimestamp(entry.getAttr("timestamp"));
|
||||
|
||||
QString libraryName;
|
||||
if (!pyName.isNone()) {
|
||||
libraryName = QString::fromStdString(pyName.as_string());
|
||||
}
|
||||
QString icon;
|
||||
QByteArray icon;
|
||||
if (!pyIcon.isNone()) {
|
||||
icon = QString::fromStdString(pyIcon.as_string());
|
||||
icon = QByteArray(pyIcon.as_std_string().data(), pyIcon.size());
|
||||
}
|
||||
|
||||
bool readOnly = pyReadOnly.as_bool();
|
||||
|
||||
QString timestamp;
|
||||
if (!pyTimestamp.isNone()) {
|
||||
timestamp = QString::fromStdString(pyTimestamp.as_string());
|
||||
}
|
||||
|
||||
auto library = std::make_shared<Library>(libraryName, icon, readOnly, timestamp);
|
||||
auto library = std::make_shared<Library>(libraryName, icon, readOnly);
|
||||
return library;
|
||||
}
|
||||
|
||||
bool ExternalManager::checkMaterialObjectType(const Py::Object& entry)
|
||||
bool ExternalManager::checkMaterialLibraryObjectType(const Py::Object& entry)
|
||||
{
|
||||
return entry.hasAttr("UUID") && entry.hasAttr("path") && entry.hasAttr("name");
|
||||
}
|
||||
|
||||
std::tuple<QString, QString, QString>
|
||||
ExternalManager::materialObjectTypeFromObject(const Py::Object& entry)
|
||||
LibraryObject ExternalManager::materialLibraryObjectTypeFromObject(const Py::Object& entry)
|
||||
{
|
||||
QString uuid;
|
||||
std::string uuid;
|
||||
auto pyUUID = entry.getAttr("UUID");
|
||||
if (!pyUUID.isNone()) {
|
||||
uuid = QString::fromStdString(pyUUID.as_string());
|
||||
uuid = pyUUID.as_string();
|
||||
}
|
||||
|
||||
QString path;
|
||||
std::string path;
|
||||
auto pyPath = entry.getAttr("path");
|
||||
if (!pyPath.isNone()) {
|
||||
path = QString::fromStdString(pyPath.as_string());
|
||||
path = pyPath.as_string();
|
||||
}
|
||||
|
||||
QString name;
|
||||
std::string name;
|
||||
auto pyName = entry.getAttr("name");
|
||||
if (!pyName.isNone()) {
|
||||
name = QString::fromStdString(pyName.as_string());
|
||||
name = pyName.as_string();
|
||||
}
|
||||
|
||||
return std::tuple<QString, QString, QString>(uuid, path, name);
|
||||
return LibraryObject(uuid, path, name);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Library>>>
|
||||
@@ -251,12 +248,13 @@ ExternalManager::libraries()
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tlibraries() not found\n");
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -280,7 +278,7 @@ std::shared_ptr<std::vector<std::shared_ptr<Library>>> ExternalManager::modelLib
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tmodelLibraries() not found\n");
|
||||
Base::Console().log("\tmodelLibraries() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -309,7 +307,7 @@ std::shared_ptr<std::vector<std::shared_ptr<Library>>> ExternalManager::material
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tmaterialLibraries() not found\n");
|
||||
Base::Console().log("\tmaterialLibraries() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -332,24 +330,26 @@ std::shared_ptr<Library> ExternalManager::getLibrary(const QString& name)
|
||||
Py::Callable libraries(_managerObject.getAttr("getLibrary"));
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::String(name.toStdString()));
|
||||
Py::Tuple result(libraries.apply(args));
|
||||
Py::Object result(libraries.apply(args));
|
||||
|
||||
Py::Object libObject = result.getItem(0);
|
||||
auto lib = libraryFromObject(Py::Tuple(libObject));
|
||||
auto lib = libraryFromObject(result);
|
||||
return std::make_shared<Library>(*lib);
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tgetLibrary() not found\n");
|
||||
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 CreationError(e1.what());
|
||||
throw LibraryNotFound(e1.what());
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalManager::createLibrary(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
void ExternalManager::createLibrary(const QString& libraryName, const QByteArray& icon, bool readOnly)
|
||||
{
|
||||
connect();
|
||||
|
||||
@@ -359,12 +359,12 @@ void ExternalManager::createLibrary(const QString& libraryName, const QString& i
|
||||
Py::Callable libraries(_managerObject.getAttr("createLibrary"));
|
||||
Py::Tuple args(3);
|
||||
args.setItem(0, Py::String(libraryName.toStdString()));
|
||||
args.setItem(1, Py::String(icon.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");
|
||||
Base::Console().log("\tcreateLibrary() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -388,7 +388,7 @@ void ExternalManager::renameLibrary(const QString& libraryName, const QString& n
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\trenameLibrary() not found\n");
|
||||
Base::Console().log("\trenameLibrary() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -398,7 +398,7 @@ void ExternalManager::renameLibrary(const QString& libraryName, const QString& n
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalManager::changeIcon(const QString& libraryName, const QString& icon)
|
||||
void ExternalManager::changeIcon(const QString& libraryName, const QByteArray& icon)
|
||||
{
|
||||
connect();
|
||||
|
||||
@@ -408,11 +408,11 @@ void ExternalManager::changeIcon(const QString& libraryName, const QString& icon
|
||||
Py::Callable libraries(_managerObject.getAttr("changeIcon"));
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::String(libraryName.toStdString()));
|
||||
args.setItem(1, Py::String(icon.toStdString()));
|
||||
args.setItem(1, Py::Bytes(icon.data(), icon.size()));
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tchangeIcon() not found\n");
|
||||
Base::Console().log("\tchangeIcon() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ void ExternalManager::removeLibrary(const QString& libraryName)
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tremoveLibrary() not found\n");
|
||||
Base::Console().log("\tremoveLibrary() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -445,10 +445,10 @@ void ExternalManager::removeLibrary(const QString& libraryName)
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ExternalManager::libraryModels(const QString& libraryName)
|
||||
{
|
||||
auto modelList = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto modelList = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
connect();
|
||||
|
||||
@@ -461,15 +461,15 @@ ExternalManager::libraryModels(const QString& libraryName)
|
||||
Py::List list(libraries.apply(args));
|
||||
for (auto library : list) {
|
||||
auto entry = Py::Object(library);
|
||||
if (!checkMaterialObjectType(entry)) {
|
||||
if (!checkMaterialLibraryObjectType(entry)) {
|
||||
throw InvalidModel();
|
||||
}
|
||||
|
||||
modelList->push_back(materialObjectTypeFromObject(entry));
|
||||
modelList->push_back(materialLibraryObjectTypeFromObject(entry));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tlibraryModels() not found\n");
|
||||
Base::Console().log("\tlibraryModels() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -481,10 +481,10 @@ ExternalManager::libraryModels(const QString& libraryName)
|
||||
return modelList;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ExternalManager::libraryMaterials(const QString& libraryName)
|
||||
{
|
||||
auto materialList = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto materialList = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
connect();
|
||||
|
||||
@@ -497,15 +497,15 @@ ExternalManager::libraryMaterials(const QString& libraryName)
|
||||
Py::List list(libraries.apply(args));
|
||||
for (auto library : list) {
|
||||
auto entry = Py::Object(library);
|
||||
if (!checkMaterialObjectType(entry)) {
|
||||
if (!checkMaterialLibraryObjectType(entry)) {
|
||||
throw InvalidMaterial();
|
||||
}
|
||||
|
||||
materialList->push_back(materialObjectTypeFromObject(entry));
|
||||
materialList->push_back(materialLibraryObjectTypeFromObject(entry));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tlibraryMaterials() not found\n");
|
||||
Base::Console().log("\tlibraryMaterials() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -517,12 +517,12 @@ ExternalManager::libraryMaterials(const QString& libraryName)
|
||||
return materialList;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ExternalManager::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
{
|
||||
auto materialList = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto materialList = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
connect();
|
||||
|
||||
@@ -545,15 +545,15 @@ ExternalManager::libraryMaterials(const QString& libraryName,
|
||||
Py::List list(libraries.apply(args));
|
||||
for (auto library : list) {
|
||||
auto entry = Py::Object(library);
|
||||
if (!checkMaterialObjectType(entry)) {
|
||||
if (!checkMaterialLibraryObjectType(entry)) {
|
||||
throw InvalidMaterial();
|
||||
}
|
||||
|
||||
materialList->push_back(materialObjectTypeFromObject(entry));
|
||||
materialList->push_back(materialLibraryObjectTypeFromObject(entry));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tlibraryMaterials() not found\n");
|
||||
Base::Console().log("\tlibraryMaterials() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -565,12 +565,162 @@ ExternalManager::libraryMaterials(const QString& libraryName,
|
||||
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();
|
||||
@@ -581,36 +731,14 @@ std::shared_ptr<Model> ExternalManager::getModel(const QString& uuid)
|
||||
Py::Callable libraries(_managerObject.getAttr("getModel"));
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::String(uuid.toStdString()));
|
||||
Py::Tuple result(libraries.apply(args)); // ignore return for now
|
||||
Py::Object result(libraries.apply(args)); // ignore return for now
|
||||
|
||||
Py::Object uuidObject = result.getItem(0);
|
||||
Py::Tuple libraryObject(result.getItem(1));
|
||||
Py::Object modelObject = result.getItem(2);
|
||||
|
||||
Py::Object pyName = libraryObject.getItem(0);
|
||||
Py::Object pyIcon = libraryObject.getItem(1);
|
||||
Py::Object readOnly = libraryObject.getItem(2);
|
||||
|
||||
QString name;
|
||||
if (!pyName.isNone()) {
|
||||
name = QString::fromStdString(pyName.as_string());
|
||||
}
|
||||
QString icon;
|
||||
if (!pyIcon.isNone()) {
|
||||
icon = QString::fromStdString(pyIcon.as_string());
|
||||
}
|
||||
auto library =
|
||||
std::make_shared<ModelLibrary>(name, QString(), icon, readOnly.as_bool());
|
||||
|
||||
Model* model = static_cast<ModelPy*>(*modelObject)->getModelPtr();
|
||||
model->setUUID(uuid);
|
||||
model->setLibrary(library);
|
||||
auto shared = std::make_shared<Model>(*model);
|
||||
auto shared = modelFromObject(result, uuid);
|
||||
|
||||
return shared;
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tgetModel() not found\n");
|
||||
Base::Console().log("\tgetModel() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -637,7 +765,7 @@ void ExternalManager::addModel(const QString& libraryName,
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\taddModel() not found\n");
|
||||
Base::Console().log("\taddModel() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -664,7 +792,7 @@ void ExternalManager::migrateModel(const QString& libraryName,
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tmigrateModel() not found\n");
|
||||
Base::Console().log("\tmigrateModel() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -674,12 +802,174 @@ void ExternalManager::migrateModel(const QString& libraryName,
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalManager::updateModel(const QString& libraryName,
|
||||
const QString& path,
|
||||
const std::shared_ptr<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();
|
||||
@@ -690,36 +980,14 @@ std::shared_ptr<Material> ExternalManager::getMaterial(const QString& uuid)
|
||||
Py::Callable libraries(_managerObject.getAttr("getMaterial"));
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::String(uuid.toStdString()));
|
||||
Py::Tuple result(libraries.apply(args));
|
||||
Py::Object result(libraries.apply(args));
|
||||
|
||||
Py::Object uuidObject = result.getItem(0);
|
||||
Py::Tuple libraryObject(result.getItem(1));
|
||||
Py::Object materialObject = result.getItem(2);
|
||||
|
||||
Py::Object pyName = libraryObject.getItem(0);
|
||||
Py::Object pyIcon = libraryObject.getItem(1);
|
||||
Py::Object readOnly = libraryObject.getItem(2);
|
||||
|
||||
QString name;
|
||||
if (!pyName.isNone()) {
|
||||
name = QString::fromStdString(pyName.as_string());
|
||||
}
|
||||
QString icon;
|
||||
if (!pyIcon.isNone()) {
|
||||
icon = QString::fromStdString(pyIcon.as_string());
|
||||
}
|
||||
auto library =
|
||||
std::make_shared<MaterialLibrary>(name, QString(), icon, readOnly.as_bool());
|
||||
|
||||
Material* material = static_cast<MaterialPy*>(*materialObject)->getMaterialPtr();
|
||||
material->setUUID(uuid);
|
||||
material->setLibrary(library);
|
||||
auto shared = std::make_shared<Material>(*material);
|
||||
auto shared = materialFromObject(result, uuid);
|
||||
|
||||
return shared;
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tgetMaterial() not found\n");
|
||||
Base::Console().log("\tgetMaterial() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -746,7 +1014,7 @@ void ExternalManager::addMaterial(const QString& libraryName,
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\taddMaterial() not found\n");
|
||||
Base::Console().log("\taddMaterial() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -774,7 +1042,7 @@ void ExternalManager::migrateMaterial(const QString& libraryName,
|
||||
libraries.apply(args); // No return expected
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("\tmigrateMaterial() not found\n");
|
||||
Base::Console().log("\tmigrateMaterial() not found\n");
|
||||
throw ConnectionError();
|
||||
}
|
||||
}
|
||||
@@ -783,3 +1051,134 @@ void ExternalManager::migrateMaterial(const QString& libraryName,
|
||||
throw CreationError(e1.what());
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalManager::updateMaterial(const QString& libraryName,
|
||||
const QString& path,
|
||||
const std::shared_ptr<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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
|
||||
class QMutex;
|
||||
class QString;
|
||||
class QByteArray;
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class Library;
|
||||
class LibraryObject;
|
||||
class Material;
|
||||
class Model;
|
||||
class MaterialFilter;
|
||||
@@ -53,18 +55,26 @@ public:
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Library>>> modelLibraries();
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Library>>> materialLibraries();
|
||||
std::shared_ptr<Library> getLibrary(const QString& name);
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QByteArray& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void changeIcon(const QString& libraryName, const QByteArray& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryModels(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>> libraryModels(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<LibraryObject>> libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
std::shared_ptr<std::vector<QString>> libraryFolders(const QString& libraryName);
|
||||
|
||||
// Folder management
|
||||
void createFolder(const QString& libraryName, const QString& path);
|
||||
void renameFolder(const QString& libraryName,
|
||||
const QString& oldPath,
|
||||
const QString& newPath);
|
||||
void deleteRecursive(const QString& libraryName, const QString& path);
|
||||
|
||||
// Model management
|
||||
std::shared_ptr<Model> getModel(const QString& uuid);
|
||||
@@ -72,6 +82,13 @@ public:
|
||||
addModel(const QString& libraryName, const QString& path, const std::shared_ptr<Model>& model);
|
||||
void
|
||||
migrateModel(const QString& libraryName, const QString& path, const std::shared_ptr<Model>& model);
|
||||
void updateModel(const QString& libraryName,
|
||||
const QString& path,
|
||||
const std::shared_ptr<Model>& model);
|
||||
void setModelPath(const QString& libraryName, const QString& path, const QString& uuid);
|
||||
void renameModel(const QString& libraryName, const QString& name, const QString& uuid);
|
||||
void moveModel(const QString& libraryName, const QString& path, const QString& uuid);
|
||||
void removeModel(const QString& uuid);
|
||||
|
||||
// Material management
|
||||
std::shared_ptr<Material> getMaterial(const QString& uuid);
|
||||
@@ -81,6 +98,13 @@ public:
|
||||
void migrateMaterial(const QString& libraryName,
|
||||
const QString& path,
|
||||
const std::shared_ptr<Material>& material);
|
||||
void updateMaterial(const QString& libraryName,
|
||||
const QString& path,
|
||||
const std::shared_ptr<Material>& material);
|
||||
void setMaterialPath(const QString& libraryName, const QString& path, const QString& uuid);
|
||||
void renameMaterial(const QString& libraryName, const QString& name, const QString& uuid);
|
||||
void moveMaterial(const QString& libraryName, const QString& path, const QString& uuid);
|
||||
void removeMaterial(const QString& uuid);
|
||||
|
||||
private:
|
||||
ExternalManager();
|
||||
@@ -92,8 +116,12 @@ private:
|
||||
void connect();
|
||||
bool checkMaterialLibraryType(const Py::Object& entry);
|
||||
std::shared_ptr<Library> libraryFromObject(const Py::Object& entry);
|
||||
bool checkMaterialLibraryObjectType(const Py::Object& entry);
|
||||
LibraryObject materialLibraryObjectTypeFromObject(const Py::Object& entry);
|
||||
bool checkModelObjectType(const Py::Object& entry);
|
||||
std::shared_ptr<Model> modelFromObject(const Py::Object& entry, const QString& uuid);
|
||||
bool checkMaterialObjectType(const Py::Object& entry);
|
||||
std::tuple<QString, QString, QString> materialObjectTypeFromObject(const Py::Object& entry);
|
||||
std::shared_ptr<Material> materialFromObject(const Py::Object& entry, const QString& uuid);
|
||||
|
||||
static ExternalManager* _manager;
|
||||
static QMutex _mutex;
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
|
||||
FolderTreeNode()
|
||||
: _type(NodeType::UnknownNode)
|
||||
, _oldFormat(false)
|
||||
, _readOnly(false)
|
||||
{}
|
||||
virtual ~FolderTreeNode() = default;
|
||||
|
||||
@@ -76,6 +78,14 @@ public:
|
||||
assert(_type == NodeType::DataNode);
|
||||
return _uuid;
|
||||
}
|
||||
bool isOldFormat() const
|
||||
{
|
||||
return _oldFormat;
|
||||
}
|
||||
bool isReadOnly() const
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
|
||||
void setFolder(std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> folder)
|
||||
{
|
||||
@@ -92,12 +102,22 @@ public:
|
||||
setType(NodeType::DataNode);
|
||||
_uuid = uuid;
|
||||
}
|
||||
void setOldFormat(bool oldFormat)
|
||||
{
|
||||
_oldFormat = oldFormat;
|
||||
}
|
||||
void setReadOnly(bool readOnly)
|
||||
{
|
||||
_readOnly = readOnly;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeType _type;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> _folder;
|
||||
QString _uuid;
|
||||
std::shared_ptr<T> _data;
|
||||
bool _oldFormat;
|
||||
bool _readOnly;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
@@ -34,28 +34,60 @@ using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Library, Base::BaseClass)
|
||||
|
||||
Library::Library(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
Library::Library(const QString& libraryName, const QString& iconPath, bool readOnly)
|
||||
: _name(libraryName)
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
, _local(false)
|
||||
{
|
||||
setIcon(iconPath);
|
||||
}
|
||||
|
||||
Library::Library(const QString& libraryName, const QByteArray& icon, bool readOnly)
|
||||
: _name(libraryName)
|
||||
, _icon(icon)
|
||||
, _readOnly(readOnly)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
Library::Library(const QString& libraryName,
|
||||
const QString& icon,
|
||||
bool readOnly,
|
||||
const QString& timestamp)
|
||||
: _name(libraryName)
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
, _timestamp(timestamp)
|
||||
{}
|
||||
|
||||
Library::Library(const QString& libraryName, const QString& dir, const QString& icon, bool readOnly)
|
||||
const QString& dir,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
: _name(libraryName)
|
||||
, _directory(QDir::cleanPath(dir))
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
{}
|
||||
, _local(false)
|
||||
{
|
||||
setIcon(iconPath);
|
||||
}
|
||||
|
||||
QByteArray Library::getIcon(const QString& iconPath)
|
||||
{
|
||||
QFile file(iconPath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
Base::Console().log("Failed to open icon file '%s'\n", iconPath.toStdString().c_str());
|
||||
return QByteArray(); // Return an empty QByteArray if file opening fails
|
||||
}
|
||||
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
void Library::setIcon(const QString& iconPath)
|
||||
{
|
||||
_icon = getIcon(iconPath);
|
||||
}
|
||||
|
||||
bool Library::isLocal() const
|
||||
{
|
||||
return _local;
|
||||
}
|
||||
|
||||
void Library::setLocal(bool local)
|
||||
{
|
||||
_local = local;
|
||||
}
|
||||
|
||||
bool Library::operator==(const Library& library) const
|
||||
{
|
||||
@@ -67,10 +99,8 @@ void Library::validate(const Library& remote) const
|
||||
if (getName() != remote.getName()) {
|
||||
throw InvalidLibrary("Library names don't match");
|
||||
}
|
||||
if (getIconPath() != remote.getIconPath()) {
|
||||
Base::Console().log("Icon path 1 '%s'\n", getIconPath().toStdString().c_str());
|
||||
Base::Console().log("Icon path 2 '%s'\n", remote.getIconPath().toStdString().c_str());
|
||||
throw InvalidLibrary("Library icon paths don't match");
|
||||
if (getIcon() != remote.getIcon()) {
|
||||
throw InvalidLibrary("Library icons don't match");
|
||||
}
|
||||
|
||||
// Local and remote paths will differ
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define MATERIAL_LIBRARY_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
@@ -40,16 +41,16 @@ public:
|
||||
Library() = default;
|
||||
Library(const Library &other) = default;
|
||||
Library(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
Library(const QString& libraryName,
|
||||
const QString& icon,
|
||||
bool readOnly,
|
||||
const QString& timestamp);
|
||||
Library(const QString& libraryName, const QByteArray& icon, bool readOnly);
|
||||
Library(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
~Library() override = default;
|
||||
|
||||
bool isLocal() const;
|
||||
void setLocal(bool local);
|
||||
|
||||
QString getName() const
|
||||
{
|
||||
return _name;
|
||||
@@ -63,13 +64,19 @@ public:
|
||||
return (_name == name);
|
||||
}
|
||||
|
||||
QString getIconPath() const
|
||||
QByteArray getIcon() const
|
||||
{
|
||||
return _iconPath;
|
||||
return _icon;
|
||||
}
|
||||
void setIconPath(const QString& icon)
|
||||
static QByteArray getIcon(const QString& iconPath);
|
||||
void setIcon(const QByteArray& icon)
|
||||
{
|
||||
_iconPath = icon;
|
||||
_icon = icon;
|
||||
}
|
||||
void setIcon(const QString& iconPath);
|
||||
bool hasIcon() const
|
||||
{
|
||||
return !_icon.isEmpty();
|
||||
}
|
||||
bool isReadOnly() const
|
||||
{
|
||||
@@ -92,14 +99,6 @@ public:
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
QString getTimestamp() const
|
||||
{
|
||||
return _timestamp;
|
||||
}
|
||||
void setTimestamp(const QString& timestamp)
|
||||
{
|
||||
_timestamp = timestamp;
|
||||
}
|
||||
|
||||
bool operator==(const Library& library) const;
|
||||
bool operator!=(const Library& library) const
|
||||
@@ -118,9 +117,72 @@ public:
|
||||
private:
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _iconPath;
|
||||
QByteArray _icon;
|
||||
bool _readOnly;
|
||||
QString _timestamp;
|
||||
|
||||
bool _local;
|
||||
|
||||
QByteArray loadByteArrayFromFile(const QString& filePath) const;
|
||||
};
|
||||
|
||||
class MaterialsExport LibraryObject
|
||||
{
|
||||
public:
|
||||
LibraryObject(const QString& uuid, const QString& path, const QString& name)
|
||||
: _uuid(uuid)
|
||||
, _path(path)
|
||||
, _name(name)
|
||||
{}
|
||||
LibraryObject(const std::string& uuid, const std::string& path, const std::string& name)
|
||||
: _uuid(QString::fromStdString(uuid))
|
||||
, _path(QString::fromStdString(path))
|
||||
, _name(QString::fromStdString(name))
|
||||
{}
|
||||
~LibraryObject() = default;
|
||||
|
||||
void setUUID(const QString& uuid)
|
||||
{
|
||||
_uuid = uuid;
|
||||
}
|
||||
void setUUID(const std::string& uuid)
|
||||
{
|
||||
_uuid = QString::fromStdString(uuid);
|
||||
}
|
||||
QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
void setPath(const QString& path)
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
void setPath(const std::string& path)
|
||||
{
|
||||
_path = QString::fromStdString(path);
|
||||
}
|
||||
QString getPath() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
void setName(const QString& name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
void setName(const std::string& name)
|
||||
{
|
||||
_name = QString::fromStdString(name);
|
||||
}
|
||||
QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
private:
|
||||
QString _uuid;
|
||||
QString _path;
|
||||
QString _name;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
@@ -19,22 +19,22 @@ class Material(BaseClass):
|
||||
"""
|
||||
|
||||
LibraryName: Final[str] = ...
|
||||
"""Model library name."""
|
||||
"""Material library name."""
|
||||
|
||||
LibraryRoot: Final[str] = ...
|
||||
"""Model library path."""
|
||||
"""Material library path."""
|
||||
|
||||
LibraryIcon: Final[str] = ...
|
||||
"""Model icon path."""
|
||||
LibraryIcon: Final[bytes] = ...
|
||||
"""Material icon."""
|
||||
|
||||
Name: str = ...
|
||||
"""Model name."""
|
||||
"""Material name."""
|
||||
|
||||
Directory: str = ...
|
||||
"""Model directory relative to the library root."""
|
||||
"""Material directory relative to the library root."""
|
||||
|
||||
UUID: Final[str] = ...
|
||||
"""Unique model identifier. This is only valid after the material is saved."""
|
||||
"""Unique material identifier. This is only valid after the material is saved."""
|
||||
|
||||
Description: str = ...
|
||||
"""Description of the material."""
|
||||
|
||||
@@ -32,7 +32,6 @@ class MaterialLibraryType:
|
||||
name: str
|
||||
icon: bytes
|
||||
readOnly: bool
|
||||
timestamp: str
|
||||
|
||||
@dataclass
|
||||
class MaterialLibraryObjectType:
|
||||
@@ -40,6 +39,16 @@ class MaterialLibraryObjectType:
|
||||
path: str
|
||||
name: str
|
||||
|
||||
@dataclass
|
||||
class ModelObjectType:
|
||||
libraryName: str
|
||||
model: Materials.Model
|
||||
|
||||
@dataclass
|
||||
class MaterialObjectType:
|
||||
libraryName: str
|
||||
material: Materials.Material
|
||||
|
||||
class MaterialManagerExternal(ABC):
|
||||
"""Abstract base class for all external material managers
|
||||
|
||||
@@ -63,9 +72,7 @@ class MaterialManagerExternal(ABC):
|
||||
|
||||
The list contains a series of tuples describing all libraries managed by
|
||||
this module. Each tuple contains the library name, icon, a boolean to indicate
|
||||
if it is a read only library, and a timestamp that indicates when it was last
|
||||
modified."""
|
||||
pass
|
||||
if it is a read only library."""
|
||||
|
||||
@abstractmethod
|
||||
def modelLibraries(self) -> list[MaterialLibraryType]:
|
||||
@@ -73,12 +80,10 @@ class MaterialManagerExternal(ABC):
|
||||
|
||||
The list contains a series of tuples describing all libraries managed by
|
||||
this module. Each tuple contains the library name, icon, and a boolean to indicate
|
||||
if it is a read only library, and a timestamp that indicates when it was last
|
||||
modified.
|
||||
if it is a read only library.
|
||||
|
||||
This differs from the libraries() function in that it only returns libraries
|
||||
containing model objects."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def materialLibraries(self) -> list[MaterialLibraryType]:
|
||||
@@ -86,164 +91,165 @@ class MaterialManagerExternal(ABC):
|
||||
|
||||
The list contains a series of tuples describing all libraries managed by
|
||||
this module. Each tuple contains the library name, icon, and a boolean to indicate
|
||||
if it is a read only library, and a timestamp that indicates when it was last
|
||||
modified.
|
||||
if it is a read only library.
|
||||
|
||||
This differs from the libraries() function in that it only returns libraries
|
||||
containing material objects."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def getLibrary(self, name: str) -> tuple:
|
||||
def getLibrary(self, libraryName: str) -> MaterialLibraryType:
|
||||
"""Get the library
|
||||
|
||||
Retrieve the library with the given name"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def createLibrary(self, name: str, icon: bytes, readOnly: bool) -> None:
|
||||
def createLibrary(self, libraryName: str, icon: bytes, readOnly: bool) -> None:
|
||||
"""Create a new library
|
||||
|
||||
Create a new library with the given name"""
|
||||
pass
|
||||
Create a new library with the given name."""
|
||||
|
||||
@abstractmethod
|
||||
def renameLibrary(self, oldName: str, newName: str) -> None:
|
||||
"""Rename an existing library
|
||||
|
||||
Change the name of an existing library"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def changeIcon(self, name: str, icon: bytes) -> None:
|
||||
def changeIcon(self, libraryName: str, icon: bytes) -> None:
|
||||
"""Change the library icon
|
||||
|
||||
Change the library icon"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def removeLibrary(self, library: str) -> None:
|
||||
def removeLibrary(self, libraryName: str) -> None:
|
||||
"""Delete a library and its contents
|
||||
|
||||
Deletes the library and any models or materials it contains"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def libraryModels(self, library: str) -> list[MaterialLibraryObjectType]:
|
||||
def libraryModels(self, libraryName: str) -> list[MaterialLibraryObjectType]:
|
||||
"""Returns a list of models managed by this library
|
||||
|
||||
Each list entry is a tuple containing the UUID, path, and name of the model"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def libraryMaterials(self, library: str,
|
||||
filter: Materials.MaterialFilter = None,
|
||||
options: Materials.MaterialFilterOptions = None) -> list[MaterialLibraryObjectType]:
|
||||
def libraryMaterials(self, libraryName: str,
|
||||
materialFilter: Materials.MaterialFilter = None,
|
||||
options: Materials.MaterialFilterOptions = None) -> \
|
||||
list[MaterialLibraryObjectType]:
|
||||
"""Returns a list of materials managed by this library
|
||||
|
||||
Each list entry is a tuple containing the UUID, path, and name of the material"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def libraryFolders(self, libraryName: str) -> list[str]:
|
||||
"""Returns a list of folders managed by this library
|
||||
|
||||
This will return a list of all folders in the library including empty folders"""
|
||||
|
||||
#
|
||||
# Folder methods
|
||||
#
|
||||
|
||||
@abstractmethod
|
||||
def createFolder(self, libraryName: str, path: str) -> None:
|
||||
"""Create a new folder in the given library"""
|
||||
|
||||
@abstractmethod
|
||||
def renameFolder(self, libraryName: str, oldPath: str, newPath: str) -> None:
|
||||
"""Rename the folder"""
|
||||
|
||||
@abstractmethod
|
||||
def deleteRecursive(self, libraryName: str, path: str) -> None:
|
||||
"""Delete the folder and all of its contents"""
|
||||
|
||||
#
|
||||
# Model methods
|
||||
#
|
||||
|
||||
@abstractmethod
|
||||
def getModel(self, uuid: str) -> Materials.Model:
|
||||
def getModel(self, uuid: str) -> ModelObjectType:
|
||||
"""Retrieve a model given its UUID"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def addModel(self, library: str, path: str, model: Materials.Model) -> None:
|
||||
"""Add a model to a library in the given folder.
|
||||
def addModel(self, libraryName: str, path: str, model: Materials.Model) -> None:
|
||||
"""Add a model to a library in the given folder. The folder path is relative to
|
||||
the library and will be created if it doesn't already exist.
|
||||
|
||||
This will throw a DatabaseModelExistsError exception if the model already exists."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def migrateModel(self, library: str, path: str, model: Materials.Model) -> None:
|
||||
def migrateModel(self, libraryName: str, path: str, model: Materials.Model) -> None:
|
||||
"""Add the model to the library.
|
||||
|
||||
If the model already exists, then no action is performed."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def updateModel(self, library: str, path: str, model: Materials.Model) -> None:
|
||||
def updateModel(self, libraryName: str, path: str, model: Materials.Model) -> None:
|
||||
"""Update the given model"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def setModelPath(self, library: str, path: str, model: Materials.Model) -> None:
|
||||
def setModelPath(self, libraryName: str, path: str, uuid: str) -> None:
|
||||
"""Change the model path within the library"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def renameModel(self, library: str, name: str, model: Materials.Model) -> None:
|
||||
def renameModel(self, libraryName: str, name: str, uuid: str) -> None:
|
||||
"""Change the model name"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def moveModel(self, library: str, path: str, model: Materials.Model) -> None:
|
||||
def moveModel(self, libraryName: str, path: str, uuid: str) -> None:
|
||||
"""Move a model across libraries
|
||||
|
||||
Move the model to the desired path in a different library. This should also
|
||||
remove the model from the old library if that library is managed by this
|
||||
interface"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def removeModel(self, model: Materials.Model) -> None:
|
||||
def removeModel(self, uuid: str) -> None:
|
||||
"""Remove the model from the library"""
|
||||
pass
|
||||
|
||||
#
|
||||
# Material methods
|
||||
#
|
||||
|
||||
@abstractmethod
|
||||
def getMaterial(self, uuid: str) -> Materials.Material:
|
||||
def getMaterial(self, uuid: str) -> MaterialObjectType:
|
||||
""" Retrieve a material given its UUID """
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def addMaterial(self, library: str, path: str, material: Materials.Material) -> None:
|
||||
"""Add a material to a library in the given folder.
|
||||
def addMaterial(self, libraryName: str, path: str, material: Materials.Material) -> None:
|
||||
"""Add a material to a library in the given folder. The folder path is relative to
|
||||
the library and will be created if it doesn't already exist.
|
||||
|
||||
This will throw a DatabaseMaterialExistsError exception if the model already exists."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def migrateMaterial(self, library: str, path: str, material: Materials.Material) -> None:
|
||||
"""Add the material to the library in the given folder.
|
||||
def migrateMaterial(self, libraryName: str, path: str, material: Materials.Material) -> None:
|
||||
"""Add the material to the library in the given folder. The folder path is relative to
|
||||
the library and will be created if it doesn't already exist.
|
||||
|
||||
If the material already exists, then no action is performed."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def updateMaterial(self, library: str, path: str, material: Materials.Material) -> None:
|
||||
def updateMaterial(self, libraryName: str, path: str, material: Materials.Material) -> None:
|
||||
"""Update the given material"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def setMaterialPath(self, library: str, path: str, material: Materials.Material) -> None:
|
||||
def setMaterialPath(self, libraryName: str, path: str, uuid: str) -> None:
|
||||
"""Change the material path within the library"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def renameMaterial(self, library: str, name: str, material: Materials.Material) -> None:
|
||||
def renameMaterial(self, libraryName: str, name: str, uuid: str) -> None:
|
||||
"""Change the material name"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def moveMaterial(self, library: str, path: str, material: Materials.Material) -> None:
|
||||
def moveMaterial(self, libraryName: str, path: str, uuid: str) -> None:
|
||||
"""Move a material across libraries
|
||||
|
||||
Move the material to the desired path in a different library. This should also
|
||||
remove the material from the old library if that library is managed by this
|
||||
interface"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def removeMaterial(self, material: Materials.Material) -> None:
|
||||
def removeMaterial(self, uuid: str) -> None:
|
||||
"""Remove the material from the library"""
|
||||
pass
|
||||
|
||||
@@ -45,7 +45,6 @@ TYPESYSTEM_SOURCE(Materials::MaterialLibrary, Base::BaseClass)
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
: Library(libraryName, icon, readOnly)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const QString& libraryName,
|
||||
@@ -53,24 +52,12 @@ MaterialLibrary::MaterialLibrary(const QString& libraryName,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: Library(libraryName, dir, icon, readOnly)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const Library& library)
|
||||
: Library(library)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
bool MaterialLibrary::isLocal() const
|
||||
{
|
||||
return _local;
|
||||
}
|
||||
|
||||
void MaterialLibrary::setLocal(bool local)
|
||||
{
|
||||
_local = local;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const
|
||||
@@ -78,11 +65,11 @@ MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> materialTree =
|
||||
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
|
||||
|
||||
auto materials = MaterialManager::getManager().libraryMaterials(getName(), filter, options);
|
||||
auto materials = MaterialManager::getManager().libraryMaterials(getName(), filter, options, isLocal());
|
||||
for (auto& it : *materials) {
|
||||
auto uuid = std::get<0>(it);
|
||||
auto path = std::get<1>(it);
|
||||
auto filename = std::get<2>(it);
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto filename = it.getName();
|
||||
|
||||
QStringList list = path.split(QStringLiteral("/"));
|
||||
|
||||
@@ -98,6 +85,7 @@ MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter
|
||||
std::shared_ptr<MaterialTreeNode> child =
|
||||
std::make_shared<MaterialTreeNode>();
|
||||
child->setFolder(mapPtr);
|
||||
child->setReadOnly(isReadOnly());
|
||||
(*node)[itp] = child;
|
||||
node = mapPtr;
|
||||
}
|
||||
@@ -108,6 +96,11 @@ MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter
|
||||
}
|
||||
std::shared_ptr<MaterialTreeNode> child = std::make_shared<MaterialTreeNode>();
|
||||
child->setUUID(uuid);
|
||||
child->setReadOnly(isReadOnly());
|
||||
if (isLocal()) {
|
||||
auto material = MaterialManager::getManager().getMaterial(uuid);
|
||||
child->setOldFormat(material->isOldFormat());
|
||||
}
|
||||
(*node)[filename] = child;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,15 +55,12 @@ public:
|
||||
MaterialLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
MaterialLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
MaterialLibrary(const Library& library);
|
||||
MaterialLibrary(const MaterialLibrary&) = delete;
|
||||
~MaterialLibrary() override = default;
|
||||
|
||||
bool isLocal() const;
|
||||
void setLocal(bool local);
|
||||
|
||||
virtual std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const;
|
||||
@@ -73,9 +70,6 @@ public:
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _local;
|
||||
};
|
||||
|
||||
class MaterialsExport MaterialLibraryLocal: public MaterialLibrary
|
||||
@@ -86,7 +80,7 @@ public:
|
||||
MaterialLibraryLocal() = default;
|
||||
MaterialLibraryLocal(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
~MaterialLibraryLocal() override = default;
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ class MaterialLibrary(BaseClass):
|
||||
Name: str = ...
|
||||
"""Name of the library"""
|
||||
|
||||
Icon: str = ...
|
||||
"""String value of the icon."""
|
||||
Icon: bytes = ...
|
||||
"""Icon as an array of bytes."""
|
||||
|
||||
Directory: str = ...
|
||||
"""Local directory where the library is located. For non-local libraries this will be empty"""
|
||||
|
||||
@@ -72,15 +72,22 @@ void MaterialLibraryPy::setName(const Py::String value)
|
||||
getMaterialLibraryPtr()->setName(QString::fromStdString(value));
|
||||
}
|
||||
|
||||
Py::String MaterialLibraryPy::getIcon() const
|
||||
Py::Object MaterialLibraryPy::getIcon() const
|
||||
{
|
||||
auto path = getMaterialLibraryPtr()->getIconPath();
|
||||
return {path.toStdString()};
|
||||
auto icon = getMaterialLibraryPtr()->getIcon();
|
||||
return Py::Bytes(icon.data(), icon.size());
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setIcon(const Py::String value)
|
||||
void MaterialLibraryPy::setIcon(const Py::Object value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setIconPath(QString::fromStdString(value));
|
||||
if (value.isNone()) {
|
||||
getMaterialLibraryPtr()->setIcon(QByteArray());
|
||||
}
|
||||
else {
|
||||
auto pyBytes = Py::Bytes(value);
|
||||
getMaterialLibraryPtr()->setIcon(
|
||||
QByteArray(pyBytes.as_std_string().data(), pyBytes.size()));
|
||||
}
|
||||
}
|
||||
|
||||
Py::String MaterialLibraryPy::getDirectory() const
|
||||
|
||||
@@ -61,15 +61,21 @@ std::unique_ptr<MaterialManagerExternal> MaterialManager::_externalManager;
|
||||
|
||||
MaterialManager::MaterialManager()
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
_hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/ExternalInterface");
|
||||
_useExternal = _hGrp->GetBool("UseExternal", false);
|
||||
_hGrp->Attach(this);
|
||||
#else
|
||||
_useExternal = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
MaterialManager::~MaterialManager()
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
_hGrp->Detach(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
MaterialManager& MaterialManager::getManager()
|
||||
@@ -267,26 +273,49 @@ std::shared_ptr<MaterialLibrary> MaterialManager::getLibrary(const QString& name
|
||||
return _localManager->getLibrary(name);
|
||||
}
|
||||
|
||||
void MaterialManager::createLibrary(const QString& /*libraryName*/, const QString& /*icon*/, bool /*readOnly*/)
|
||||
void MaterialManager::createLibrary(const QString& libraryName,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
if (_useExternal) {
|
||||
auto icon = Materials::Library::getIcon(iconPath);
|
||||
_externalManager->createLibrary(libraryName, icon, readOnly);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
throw CreationError("Local library requires a path");
|
||||
}
|
||||
|
||||
void MaterialManager::createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
{
|
||||
_localManager->createLibrary(libraryName, directory, icon, readOnly);
|
||||
_localManager->createLibrary(libraryName, directory, iconPath, readOnly);
|
||||
}
|
||||
|
||||
void MaterialManager::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
_localManager->renameLibrary(libraryName, newName);
|
||||
auto library = getLibrary(libraryName);
|
||||
if (library) {
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
if (!library->isLocal()) {
|
||||
if (_useExternal) {
|
||||
_externalManager->renameLibrary(libraryName, newName);
|
||||
return;
|
||||
}
|
||||
|
||||
throw Materials::RenameError();
|
||||
}
|
||||
#endif
|
||||
_localManager->renameLibrary(libraryName, newName);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::changeIcon(const QString& libraryName, const QString& icon)
|
||||
void MaterialManager::changeIcon(const QString& libraryName, const QString& iconPath)
|
||||
{
|
||||
auto icon = Materials::Library::getIcon(iconPath);
|
||||
_localManager->changeIcon(libraryName, icon);
|
||||
}
|
||||
|
||||
@@ -295,11 +324,11 @@ void MaterialManager::removeLibrary(const QString& libraryName)
|
||||
_localManager->removeLibrary(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
MaterialManager::libraryMaterials(const QString& libraryName)
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManager::libraryMaterials(const QString& libraryName, bool local)
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
if (_useExternal) {
|
||||
if (_useExternal && !local) {
|
||||
try {
|
||||
auto materials = _externalManager->libraryMaterials(libraryName);
|
||||
if (materials) {
|
||||
@@ -313,13 +342,14 @@ MaterialManager::libraryMaterials(const QString& libraryName)
|
||||
return _localManager->libraryMaterials(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManager::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
const MaterialFilterOptions& options,
|
||||
bool local)
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
if (_useExternal) {
|
||||
if (_useExternal && !local) {
|
||||
try {
|
||||
auto materials = _externalManager->libraryMaterials(libraryName, filter, options);
|
||||
if (materials) {
|
||||
@@ -383,6 +413,14 @@ void MaterialManager::createFolder(const std::shared_ptr<MaterialLibrary>& libra
|
||||
|
||||
_localManager->createFolder(materialLibrary, path);
|
||||
}
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
else if (_useExternal) {
|
||||
_externalManager->createFolder(library, path);
|
||||
}
|
||||
else {
|
||||
throw Materials::CreationError("External materials are not enabled");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MaterialManager::renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
@@ -395,6 +433,14 @@ void MaterialManager::renameFolder(const std::shared_ptr<MaterialLibrary>& libra
|
||||
|
||||
_localManager->renameFolder(materialLibrary, oldPath, newPath);
|
||||
}
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
else if (_useExternal) {
|
||||
_externalManager->renameFolder(library, oldPath, newPath);
|
||||
}
|
||||
else {
|
||||
throw Materials::RenameError("External materials are not enabled");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MaterialManager::deleteRecursive(const std::shared_ptr<MaterialLibrary>& library,
|
||||
@@ -406,6 +452,14 @@ void MaterialManager::deleteRecursive(const std::shared_ptr<MaterialLibrary>& li
|
||||
|
||||
_localManager->deleteRecursive(materialLibrary, path);
|
||||
}
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
else if (_useExternal) {
|
||||
_externalManager->deleteRecursive(library, path);
|
||||
}
|
||||
else {
|
||||
throw Materials::DeleteError("External materials are not enabled");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=====
|
||||
@@ -562,16 +616,22 @@ void MaterialManager::dereference(std::shared_ptr<Material> material) const
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
void MaterialManager::migrateToExternal(const std::shared_ptr<Materials::MaterialLibrary>& library)
|
||||
{
|
||||
_externalManager->createLibrary(library->getName(),
|
||||
library->getIconPath(),
|
||||
library->isReadOnly());
|
||||
try {
|
||||
_externalManager->createLibrary(library->getName(),
|
||||
library->getIcon(),
|
||||
library->isReadOnly());
|
||||
}
|
||||
catch (const CreationError&) {
|
||||
}
|
||||
catch (const ConnectionError&) {
|
||||
}
|
||||
|
||||
auto materials = _localManager->libraryMaterials(library->getName());
|
||||
for (auto& tuple : *materials) {
|
||||
auto uuid = std::get<0>(tuple);
|
||||
auto path = std::get<1>(tuple);
|
||||
auto name = std::get<2>(tuple);
|
||||
Base::Console().Log("\t('%s', '%s', '%s')\n",
|
||||
for (auto& it : *materials) {
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto name = it.getName();
|
||||
Base::Console().log("\t('%s', '%s', '%s')\n",
|
||||
uuid.toStdString().c_str(),
|
||||
path.toStdString().c_str(),
|
||||
name.toStdString().c_str());
|
||||
@@ -586,11 +646,12 @@ void MaterialManager::migrateToExternal(const std::shared_ptr<Materials::Materia
|
||||
void MaterialManager::validateMigration(const std::shared_ptr<Materials::MaterialLibrary>& library)
|
||||
{
|
||||
auto materials = _localManager->libraryMaterials(library->getName());
|
||||
for (auto& tuple : *materials) {
|
||||
auto uuid = std::get<0>(tuple);
|
||||
auto path = std::get<1>(tuple);
|
||||
auto name = std::get<2>(tuple);
|
||||
Base::Console().Log("\t('%s', '%s', '%s')\n",
|
||||
_externalManager->resetCache();
|
||||
for (auto& it : *materials) {
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto name = it.getName();
|
||||
Base::Console().log("\t('%s', '%s', '%s')\n",
|
||||
uuid.toStdString().c_str(),
|
||||
path.toStdString().c_str(),
|
||||
name.toStdString().c_str());
|
||||
|
||||
@@ -69,23 +69,27 @@ public:
|
||||
static QString defaultMaterialUUID();
|
||||
|
||||
// Library management
|
||||
bool useExternal() const { return _useExternal; }
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLocalLibraries();
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
void createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void changeIcon(const QString& libraryName, const QString& iconPath);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName, bool local = false);
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
const MaterialFilterOptions& options,
|
||||
bool local = false);
|
||||
bool isLocalLibrary(const QString& libraryName);
|
||||
|
||||
// Folder management
|
||||
|
||||
@@ -124,22 +124,40 @@ std::shared_ptr<MaterialLibrary> MaterialManagerExternal::getLibrary(const QStri
|
||||
catch (const ConnectionError& e) {
|
||||
throw LibraryNotFound(e.what());
|
||||
}
|
||||
catch (...) {
|
||||
throw LibraryNotFound("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManagerExternal::createLibrary(const QString& libraryName,
|
||||
const QString& icon,
|
||||
const QByteArray& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
ExternalManager::getManager()->createLibrary(libraryName, icon, readOnly);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
void MaterialManagerExternal::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
ExternalManager::getManager()->renameLibrary(libraryName, newName);
|
||||
}
|
||||
|
||||
void MaterialManagerExternal::changeIcon(const QString& libraryName, const QByteArray& icon)
|
||||
{
|
||||
ExternalManager::getManager()->changeIcon(libraryName, icon);
|
||||
}
|
||||
|
||||
void MaterialManagerExternal::removeLibrary(const QString& libraryName)
|
||||
{
|
||||
ExternalManager::getManager()->removeLibrary(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManagerExternal::libraryMaterials(const QString& libraryName)
|
||||
{
|
||||
return ExternalManager::getManager()->libraryMaterials(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManagerExternal::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
@@ -147,12 +165,44 @@ MaterialManagerExternal::libraryMaterials(const QString& libraryName,
|
||||
return ExternalManager::getManager()->libraryMaterials(libraryName, filter, options);
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Folder management
|
||||
//
|
||||
//=====
|
||||
|
||||
void MaterialManagerExternal::createFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& path)
|
||||
{
|
||||
ExternalManager::getManager()->createFolder(library->getName(), path);
|
||||
}
|
||||
|
||||
void MaterialManagerExternal::renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath)
|
||||
{
|
||||
ExternalManager::getManager()->renameFolder(library->getName(), oldPath, newPath);
|
||||
}
|
||||
|
||||
void MaterialManagerExternal::deleteRecursive(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& path)
|
||||
{
|
||||
ExternalManager::getManager()->deleteRecursive(library->getName(), path);
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Material management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<Material> MaterialManagerExternal::materialNotFound(const QString& uuid) const
|
||||
{
|
||||
// Setting the cache value to nullptr prevents repeated lookups
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManagerExternal::getMaterial(const QString& uuid) const
|
||||
{
|
||||
if (_cache.contains(uuid.toStdString())) {
|
||||
@@ -164,12 +214,13 @@ std::shared_ptr<Material> MaterialManagerExternal::getMaterial(const QString& uu
|
||||
return material;
|
||||
}
|
||||
catch (const MaterialNotFound& e) {
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
return materialNotFound(uuid);
|
||||
}
|
||||
catch (const ConnectionError& e) {
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
return materialNotFound(uuid);
|
||||
}
|
||||
catch (...) {
|
||||
return materialNotFound(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ class Material;
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class LibraryObject;
|
||||
class MaterialLibrary;
|
||||
class MaterialLibraryExternal;
|
||||
class MaterialFilter;
|
||||
@@ -64,15 +65,25 @@ public:
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries();
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QByteArray& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QByteArray& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
|
||||
// Folder management
|
||||
void createFolder(const std::shared_ptr<MaterialLibrary>& library, const QString& path);
|
||||
void renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath);
|
||||
void deleteRecursive(const std::shared_ptr<MaterialLibrary>& library, const QString& path);
|
||||
|
||||
// Material management
|
||||
std::shared_ptr<Material> getMaterial(const QString& uuid) const;
|
||||
@@ -89,6 +100,7 @@ public:
|
||||
|
||||
private:
|
||||
static void initCache();
|
||||
std::shared_ptr<Material> materialNotFound(const QString& uuid) const;
|
||||
|
||||
static QMutex _mutex;
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ std::shared_ptr<MaterialLibrary> MaterialManagerLocal::getLibrary(const QString&
|
||||
|
||||
void MaterialManagerLocal::createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
{
|
||||
QDir dir;
|
||||
@@ -151,7 +151,7 @@ void MaterialManagerLocal::createLibrary(const QString& libraryName,
|
||||
}
|
||||
|
||||
auto materialLibrary =
|
||||
std::make_shared<MaterialLibraryLocal>(libraryName, directory, icon, readOnly);
|
||||
std::make_shared<MaterialLibraryLocal>(libraryName, directory, iconPath, readOnly);
|
||||
_libraryList->push_back(materialLibrary);
|
||||
|
||||
// This needs to be persisted somehow
|
||||
@@ -171,13 +171,13 @@ void MaterialManagerLocal::renameLibrary(const QString& libraryName, const QStri
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::changeIcon(const QString& libraryName, const QString& icon)
|
||||
void MaterialManagerLocal::changeIcon(const QString& libraryName, const QByteArray& icon)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal() && library->isName(libraryName)) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
materialLibrary->setIconPath(icon);
|
||||
materialLibrary->setIcon(icon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -199,18 +199,17 @@ void MaterialManagerLocal::removeLibrary(const QString& libraryName)
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManagerLocal::libraryMaterials(const QString& libraryName)
|
||||
{
|
||||
auto materials = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto materials = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
auto library = it.second->getLibrary();
|
||||
if (library->isName(libraryName)) {
|
||||
materials->push_back(std::tuple<QString, QString, QString>(it.first,
|
||||
it.second->getDirectory(),
|
||||
it.second->getName()));
|
||||
materials->push_back(
|
||||
LibraryObject(it.first, it.second->getDirectory(), it.second->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,21 +234,20 @@ bool MaterialManagerLocal::passFilter(const std::shared_ptr<Material>& material,
|
||||
return filter->modelIncluded(material);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
MaterialManagerLocal::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
{
|
||||
auto materials = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto materials = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
auto library = it.second->getLibrary();
|
||||
if (library->isName(libraryName)) {
|
||||
if (passFilter(it.second, filter, options)) {
|
||||
materials->push_back(std::tuple<QString, QString, QString>(it.first,
|
||||
it.second->getDirectory(),
|
||||
it.second->getName()));
|
||||
materials->push_back(
|
||||
LibraryObject(it.first, it.second->getDirectory(), it.second->getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ class Material;
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class LibraryObject;
|
||||
class MaterialLibrary;
|
||||
class MaterialLibraryLocal;
|
||||
class MaterialFilter;
|
||||
@@ -65,14 +66,14 @@ public:
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void changeIcon(const QString& libraryName, const QByteArray& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
|
||||
@@ -147,13 +147,15 @@ Py::List MaterialManagerPy::getMaterialLibraries() const
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(lib);
|
||||
libTuple.setItem(0, Py::String(materialLibrary->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(materialLibrary->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(materialLibrary->getIconPath().toStdString()));
|
||||
libTuple.setItem(2,
|
||||
Py::Bytes(Py::Bytes(materialLibrary->getIcon().data(),
|
||||
materialLibrary->getIcon().size())));
|
||||
}
|
||||
else
|
||||
{
|
||||
libTuple.setItem(0, Py::String());
|
||||
libTuple.setItem(1, Py::String());
|
||||
libTuple.setItem(2, Py::String());
|
||||
libTuple.setItem(2, Py::Bytes());
|
||||
}
|
||||
|
||||
list.append(libTuple);
|
||||
|
||||
@@ -87,15 +87,19 @@ Py::String MaterialPy::getLibraryRoot() const
|
||||
return "";
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryIcon() const
|
||||
Py::Object MaterialPy::getLibraryIcon() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return {materialLibrary ? materialLibrary->getIconPath().toStdString() : ""};
|
||||
auto icon = materialLibrary->getIcon();
|
||||
if (icon.isNull()) {
|
||||
return Py::Bytes();
|
||||
}
|
||||
return Py::Bytes(icon.data(), icon.size());
|
||||
}
|
||||
return "";
|
||||
return Py::Bytes();
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getName() const
|
||||
|
||||
@@ -22,8 +22,8 @@ class Model(BaseClass):
|
||||
LibraryRoot: Final[str] = ""
|
||||
"""Model library path."""
|
||||
|
||||
LibraryIcon: Final[str] = ""
|
||||
"""Model icon path."""
|
||||
LibraryIcon: Final[bytes] = ""
|
||||
"""Model icon."""
|
||||
|
||||
Name: str = ""
|
||||
"""Model name."""
|
||||
|
||||
@@ -41,32 +41,19 @@ TYPESYSTEM_SOURCE(Materials::ModelLibrary, Materials::Library)
|
||||
|
||||
ModelLibrary::ModelLibrary(const Library& other)
|
||||
: Library(other)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
ModelLibrary::ModelLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
: Library(libraryName, dir, icon, readOnly)
|
||||
, _local(false)
|
||||
: Library(libraryName, dir, iconPath, readOnly)
|
||||
{}
|
||||
|
||||
ModelLibrary::ModelLibrary()
|
||||
: _local(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool ModelLibrary::isLocal() const
|
||||
{
|
||||
return _local;
|
||||
}
|
||||
|
||||
void ModelLibrary::setLocal(bool local)
|
||||
{
|
||||
_local = local;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
|
||||
ModelLibrary::getModelTree(ModelFilter filter) const
|
||||
{
|
||||
@@ -75,9 +62,9 @@ ModelLibrary::getModelTree(ModelFilter filter) const
|
||||
|
||||
auto models = ModelManager::getManager().libraryModels(getName());
|
||||
for (auto& it : *models) {
|
||||
auto uuid = std::get<0>(it);
|
||||
auto path = std::get<1>(it);
|
||||
auto filename = std::get<2>(it);
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto filename = it.getName();
|
||||
|
||||
auto model = ModelManager::getManager().getModel(getName(), uuid);
|
||||
if (ModelManager::passFilter(filter, model->getType())) {
|
||||
@@ -121,9 +108,9 @@ ModelLibraryLocal::ModelLibraryLocal(const Library& other)
|
||||
|
||||
ModelLibraryLocal::ModelLibraryLocal(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly)
|
||||
: ModelLibrary(libraryName, dir, icon, readOnly)
|
||||
: ModelLibrary(libraryName, dir, iconPath, readOnly)
|
||||
{
|
||||
setLocal(true);
|
||||
|
||||
|
||||
@@ -49,14 +49,11 @@ public:
|
||||
ModelLibrary(const Library& library);
|
||||
ModelLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
ModelLibrary(const ModelLibrary& other) = delete;
|
||||
~ModelLibrary() override = default;
|
||||
|
||||
bool isLocal() const;
|
||||
void setLocal(bool local);
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
|
||||
getModelTree(ModelFilter filter) const;
|
||||
|
||||
@@ -65,9 +62,6 @@ public:
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _local;
|
||||
};
|
||||
|
||||
class MaterialsExport ModelLibraryLocal: public ModelLibrary
|
||||
@@ -78,9 +72,9 @@ public:
|
||||
ModelLibraryLocal();
|
||||
ModelLibraryLocal(const Library& other);
|
||||
ModelLibraryLocal(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
const QString& dir,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
ModelLibraryLocal(const ModelLibraryLocal& other) = delete;
|
||||
~ModelLibraryLocal() override = default;
|
||||
|
||||
|
||||
@@ -158,10 +158,12 @@ std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManager::getLocal
|
||||
return _localManager->getLibraries();
|
||||
}
|
||||
|
||||
void ModelManager::createLibrary([[maybe_unused]] const QString& libraryName, [[maybe_unused]] const QString& icon,
|
||||
[[maybe_unused]] bool readOnly)
|
||||
void ModelManager::createLibrary([[maybe_unused]] const QString& libraryName,
|
||||
[[maybe_unused]] const QString& iconPath,
|
||||
[[maybe_unused]] bool readOnly)
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
auto icon = Materials::Library::getIcon(iconPath);
|
||||
_externalManager->createLibrary(libraryName, icon, readOnly);
|
||||
#endif
|
||||
}
|
||||
@@ -202,7 +204,7 @@ void ModelManager::removeLibrary(const QString& libraryName)
|
||||
_localManager->removeLibrary(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ModelManager::libraryModels(const QString& libraryName)
|
||||
{
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
@@ -319,16 +321,22 @@ bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType)
|
||||
#if defined(BUILD_MATERIAL_EXTERNAL)
|
||||
void ModelManager::migrateToExternal(const std::shared_ptr<Materials::ModelLibrary>& library)
|
||||
{
|
||||
_externalManager->createLibrary(library->getName(),
|
||||
library->getIconPath(),
|
||||
library->isReadOnly());
|
||||
try {
|
||||
_externalManager->createLibrary(library->getName(),
|
||||
library->getIcon(),
|
||||
library->isReadOnly());
|
||||
}
|
||||
catch (const CreationError&) {
|
||||
}
|
||||
catch (const ConnectionError&) {
|
||||
}
|
||||
|
||||
auto models = _localManager->libraryModels(library->getName());
|
||||
for (auto& tuple : *models) {
|
||||
auto uuid = std::get<0>(tuple);
|
||||
auto path = std::get<1>(tuple);
|
||||
auto name = std::get<2>(tuple);
|
||||
Base::Console().Log("\t('%s', '%s', '%s')\n",
|
||||
for (auto& it : *models) {
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto name = it.getName();
|
||||
Base::Console().log("\t('%s', '%s', '%s')\n",
|
||||
uuid.toStdString().c_str(),
|
||||
path.toStdString().c_str(),
|
||||
name.toStdString().c_str());
|
||||
@@ -341,11 +349,11 @@ void ModelManager::migrateToExternal(const std::shared_ptr<Materials::ModelLibra
|
||||
void ModelManager::validateMigration(const std::shared_ptr<Materials::ModelLibrary>& library)
|
||||
{
|
||||
auto models = _localManager->libraryModels(library->getName());
|
||||
for (auto& tuple : *models) {
|
||||
auto uuid = std::get<0>(tuple);
|
||||
auto path = std::get<1>(tuple);
|
||||
auto name = std::get<2>(tuple);
|
||||
Base::Console().Log("\t('%s', '%s', '%s')\n",
|
||||
for (auto& it : *models) {
|
||||
auto uuid = it.getUUID();
|
||||
auto path = it.getPath();
|
||||
auto name = it.getName();
|
||||
Base::Console().log("\t('%s', '%s', '%s')\n",
|
||||
uuid.toStdString().c_str(),
|
||||
path.toStdString().c_str(),
|
||||
name.toStdString().c_str());
|
||||
|
||||
@@ -55,7 +55,9 @@ public:
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLocalLibraries();
|
||||
std::shared_ptr<ModelLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& iconPath,
|
||||
bool readOnly = true);
|
||||
void createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
@@ -63,7 +65,7 @@ public:
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryModels(const QString& libraryName);
|
||||
bool isLocalLibrary(const QString& libraryName);
|
||||
|
||||
|
||||
@@ -102,16 +102,19 @@ std::shared_ptr<ModelLibrary> ModelManagerExternal::getLibrary(const QString& na
|
||||
catch (const ConnectionError& e) {
|
||||
throw LibraryNotFound(e.what());
|
||||
}
|
||||
catch (...) {
|
||||
throw LibraryNotFound("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
void ModelManagerExternal::createLibrary(const QString& libraryName,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
const QByteArray& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
ExternalManager::getManager()->createLibrary(libraryName, icon, readOnly);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ModelManagerExternal::libraryModels(const QString& libraryName)
|
||||
{
|
||||
return ExternalManager::getManager()->libraryModels(libraryName);
|
||||
@@ -123,6 +126,13 @@ ModelManagerExternal::libraryModels(const QString& libraryName)
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<Model> ModelManagerExternal::modelNotFound(const QString& uuid)
|
||||
{
|
||||
// Setting the cache value to nullptr prevents repeated lookups
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManagerExternal::getModel(const QString& uuid)
|
||||
{
|
||||
if (_cache.contains(uuid.toStdString())) {
|
||||
@@ -135,12 +145,13 @@ std::shared_ptr<Model> ModelManagerExternal::getModel(const QString& uuid)
|
||||
return model;
|
||||
}
|
||||
catch (const ModelNotFound& e) {
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
return modelNotFound(uuid);
|
||||
}
|
||||
catch (const ConnectionError& e) {
|
||||
_cache.emplace(uuid.toStdString(), nullptr);
|
||||
return nullptr;
|
||||
return modelNotFound(uuid);
|
||||
}
|
||||
catch (...) {
|
||||
return modelNotFound(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ public:
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLibraries();
|
||||
std::shared_ptr<ModelLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& icon,
|
||||
const QByteArray& icon,
|
||||
bool readOnly = true);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryModels(const QString& libraryName);
|
||||
|
||||
// Model management
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
|
||||
private:
|
||||
static void initCache();
|
||||
std::shared_ptr<Model> modelNotFound(const QString& uuid);
|
||||
|
||||
static QMutex _mutex;
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ void ModelManagerLocal::changeIcon(const QString& libraryName, const QString& ic
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isName(libraryName)) {
|
||||
library->setIconPath(icon);
|
||||
library->setIcon(icon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -156,16 +156,16 @@ void ModelManagerLocal::removeLibrary(const QString& libraryName)
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
ModelManagerLocal::libraryModels(const QString& libraryName)
|
||||
{
|
||||
auto models = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
auto models = std::make_shared<std::vector<LibraryObject>>();
|
||||
|
||||
for (auto& it : *_modelMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
if (it.second->getLibrary()->isName(libraryName)) {
|
||||
models->push_back(
|
||||
std::tuple<QString, QString, QString>(it.first, it.second->getDirectory(), it.second->getName()));
|
||||
LibraryObject(it.first, it.second->getDirectory(), it.second->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
std::shared_ptr<std::vector<LibraryObject>>
|
||||
libraryModels(const QString& libraryName);
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getModels()
|
||||
|
||||
@@ -124,7 +124,7 @@ Py::List ModelManagerPy::getModelLibraries() const
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
libTuple.setItem(2, Py::Bytes(lib->getIcon().data(), lib->getIcon().size()));
|
||||
libTuple.setItem(3, Py::Boolean(lib->isReadOnly()));
|
||||
|
||||
list.append(libTuple);
|
||||
@@ -143,7 +143,7 @@ Py::List ModelManagerPy::getLocalModelLibraries() const
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
libTuple.setItem(2, Py::Bytes(lib->getIcon().data(), lib->getIcon().size()));
|
||||
libTuple.setItem(3, Py::Boolean(lib->isReadOnly()));
|
||||
|
||||
list.append(libTuple);
|
||||
|
||||
@@ -61,13 +61,16 @@ Py::String ModelPy::getLibraryName() const
|
||||
Py::String ModelPy::getLibraryRoot() const
|
||||
{
|
||||
auto library = getModelPtr()->getLibrary();
|
||||
if (!library->isLocal()) {
|
||||
return "";
|
||||
}
|
||||
return Py::String(library ? library->getDirectoryPath().toStdString() : "");
|
||||
}
|
||||
|
||||
Py::String ModelPy::getLibraryIcon() const
|
||||
Py::Object ModelPy::getLibraryIcon() const
|
||||
{
|
||||
auto library = getModelPtr()->getLibrary();
|
||||
return Py::String(library ? library->getIconPath().toStdString() : "");
|
||||
return Py::Bytes(library->getIcon().data(), library->getIcon().size());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getName() const
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <Mod/Material/App/MaterialLibrary.h>
|
||||
|
||||
#include "MaterialsEditor.h"
|
||||
#include "MaterialSave.h"
|
||||
#include "ui_MaterialSave.h"
|
||||
|
||||
@@ -360,7 +361,7 @@ void MaterialSave::showSelectedTree()
|
||||
if (ui->comboLibrary->count() > 0) {
|
||||
auto variant = ui->comboLibrary->currentData();
|
||||
auto library = variant.value<std::shared_ptr<Materials::MaterialLibrary>>();
|
||||
QIcon icon(library->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(library);
|
||||
QIcon folderIcon(QStringLiteral(":/icons/folder.svg"));
|
||||
_libraryName = library->getName();
|
||||
_selectedPath = QStringLiteral("/") + _libraryName;
|
||||
|
||||
@@ -572,7 +572,7 @@ void MaterialTreeWidget::fillMaterialTree()
|
||||
lib->setFlags(Qt::ItemIsEnabled);
|
||||
addExpanded(model, lib, param);
|
||||
|
||||
QIcon icon(library->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(library);
|
||||
QIcon folderIcon(QStringLiteral(":/icons/folder.svg"));
|
||||
|
||||
addMaterials(*lib, materialTree, folderIcon, icon, param);
|
||||
@@ -619,7 +619,7 @@ void MaterialTreeWidget::addRecents(QStandardItem* parent)
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
QIcon icon(material->getLibrary()->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(material->getLibrary());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
@@ -636,7 +636,7 @@ void MaterialTreeWidget::addFavorites(QStandardItem* parent)
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
QIcon icon(material->getLibrary()->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(material->getLibrary());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
@@ -801,6 +801,33 @@ void MaterialsEditor::createAppearanceTree()
|
||||
connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange);
|
||||
}
|
||||
|
||||
QIcon MaterialsEditor::getIcon(const std::shared_ptr<Materials::Library>& library)
|
||||
{
|
||||
// Load from the QByteArray if available
|
||||
QIcon icon;
|
||||
if (library->hasIcon()) {
|
||||
QImage image;
|
||||
if (!image.loadFromData(library->getIcon())) {
|
||||
Base::Console().log("Unable to load icon image for library '%s'\n",
|
||||
library->getName().toStdString().c_str());
|
||||
return QIcon();
|
||||
}
|
||||
icon = QIcon(QPixmap::fromImage(image));
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
QIcon MaterialsEditor::getIcon(const std::shared_ptr<Materials::ModelLibrary>& library)
|
||||
{
|
||||
return getIcon(std::static_pointer_cast<Materials::Library>(library));
|
||||
}
|
||||
|
||||
QIcon MaterialsEditor::getIcon(const std::shared_ptr<Materials::MaterialLibrary>& library)
|
||||
{
|
||||
return getIcon(std::static_pointer_cast<Materials::Library>(library));
|
||||
}
|
||||
|
||||
void MaterialsEditor::addRecents(QStandardItem* parent)
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
@@ -808,13 +835,13 @@ void MaterialsEditor::addRecents(QStandardItem* parent)
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
// if (material->getLibrary()->isLocal()) {
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, libraryPath(material));
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
QIcon icon = getIcon(material->getLibrary());
|
||||
auto card = new QStandardItem(icon, libraryPath(material));
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
addExpanded(tree, parent, card);
|
||||
// }
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
@@ -828,7 +855,7 @@ void MaterialsEditor::addFavorites(QStandardItem* parent)
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
QIcon icon = getIcon(material->getLibrary());
|
||||
auto card = new QStandardItem(icon, libraryPath(material));
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
@@ -877,7 +904,7 @@ void MaterialsEditor::fillMaterialTree()
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib, param);
|
||||
|
||||
QIcon icon(library->getIconPath());
|
||||
QIcon icon = getIcon(library);
|
||||
QIcon folderIcon(QStringLiteral(":/icons/folder.svg"));
|
||||
|
||||
addMaterials(*lib, materialTree, folderIcon, icon, param);
|
||||
|
||||
@@ -87,6 +87,10 @@ public:
|
||||
|
||||
static QString libraryPath(const std::shared_ptr<Materials::Material>& material);
|
||||
|
||||
static QIcon getIcon(const std::shared_ptr<Materials::MaterialLibrary>& library);
|
||||
static QIcon getIcon(const std::shared_ptr<Materials::ModelLibrary>& library);
|
||||
static QIcon getIcon(const std::shared_ptr<Materials::Library>& library);
|
||||
|
||||
void updateMaterialAppearance();
|
||||
void updateMaterialProperties();
|
||||
void updateMaterialGeneral();
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include "MaterialsEditor.h"
|
||||
#include "ModelSelect.h"
|
||||
#include "ui_ModelSelect.h"
|
||||
|
||||
@@ -272,7 +273,7 @@ void ModelSelect::addRecents(QStandardItem* parent)
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
|
||||
if (Materials::ModelManager::getManager().passFilter(_filter, model->getType())) {
|
||||
QIcon icon = QIcon(model->getLibrary()->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(model->getLibrary());
|
||||
auto card = new QStandardItem(icon, model->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
@@ -294,7 +295,7 @@ void ModelSelect::addFavorites(QStandardItem* parent)
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
|
||||
if (Materials::ModelManager::getManager().passFilter(_filter, model->getType())) {
|
||||
QIcon icon = QIcon(model->getLibrary()->getIconPath());
|
||||
auto icon = MaterialsEditor::getIcon(model->getLibrary());
|
||||
auto card = new QStandardItem(icon, model->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
@@ -350,7 +351,7 @@ void ModelSelect::fillTree()
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
auto modelTree = Materials::ModelManager::getManager().getModelTree(library, _filter);
|
||||
addModels(*lib, modelTree, QIcon(library->getIconPath()));
|
||||
addModels(*lib, modelTree, MaterialsEditor::getIcon(library));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ void DlgMigrateExternal::migrate()
|
||||
|
||||
void DlgMigrateExternal::statusUpdate(const QString& status)
|
||||
{
|
||||
Base::Console().Log("%s\n", status.toStdString().c_str());
|
||||
Base::Console().log("%s\n", status.toStdString().c_str());
|
||||
ui->textStatus->append(status);
|
||||
|
||||
// This is required to update in real time
|
||||
|
||||
Reference in New Issue
Block a user