From daa2102667920caebff37cd558b83ee8b803540c Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Tue, 14 Jan 2025 18:36:14 +0100 Subject: [PATCH 01/17] Container: library_load() log additional info in case of failure (#10) * model identifier should not contain ".fmu" * update Changelog * improve librayr_load() in case of error * refactor logger code * remove warning --- CHANGELOG.md | 6 + container/CMakeLists.txt | 6 +- container/container.c | 64 +++++------ container/hash.c | 161 +++++++++++++++++++++++++++ container/hash.h | 54 +++++++++ container/library.c | 158 ++++++++++++++++++++++++++ container/library.h | 13 --- container/logger.c | 28 +++-- container/logger.h | 3 +- fmu_manipulation_toolbox/assembly.py | 3 +- 10 files changed, 441 insertions(+), 55 deletions(-) create mode 100644 container/hash.c create mode 100644 container/hash.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d9694f..9a558e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ This package was formerly known as `fmutool`. +## Version 1.8.2 (upcoming) +* FIXED: `fmucontainer` identifier (for coSimulation) does not contain ".fmu" anymore +* TODO: ADDED: take care of stoptime +* TODO: Expose parameters +* ADDED: GUI for `fmucontainer` + ## Version 1.8.1 * FIXED: `fmucontainer` read links from `.json` input files * CHANGED: switch to PyQT6 and add minor GUI improvements diff --git a/container/CMakeLists.txt b/container/CMakeLists.txt index 4a5e04d..81a3e67 100644 --- a/container/CMakeLists.txt +++ b/container/CMakeLists.txt @@ -34,6 +34,7 @@ message("FMI_PLATFORM: ${FMI_PLATFORM}") add_library(container SHARED container.c container.h fmu.c fmu.h + hash.c hash.h library.c library.h logger.c logger.h profile.c profile.h @@ -45,9 +46,12 @@ target_include_directories(container PRIVATE if (UNIX AND NOT APPLE) target_link_libraries(container Threads::Threads) endif() +if (WIN32) + target_link_libraries(container Imagehlp.lib) +endif() set_target_properties(container PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../fmu_manipulation_toolbox/resources/${FMI_PLATFORM}" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../fmu_manipulation_toolbox/resources/${FMI_PLATFORM}") - #target_compile_options(container PRIVATE /W4 /WX) +#target_compile_options(container PRIVATE /W4 /WX) diff --git a/container/container.c b/container/container.c index aba2072..e9f0f24 100644 --- a/container/container.c +++ b/container/container.c @@ -20,8 +20,7 @@ /* unimplemented fmi2 functions */ #define __NOT_IMPLEMENTED__ \ - container_t* container = (container_t*)c; \ - logger(container, fmi2Error, "Function '%s' is not implemented", __func__); \ + logger(fmi2Error, "Function '%s' is not implemented", __func__); \ return fmi2Error; @@ -58,9 +57,9 @@ static int read_mt_flag(container_t* container, config_file_t* file) { return -2; if (container->mt) - logger(container, fmi2Warning, "Container use MULTI thread"); + logger(fmi2Warning, "Container use MULTI thread"); else - logger(container, fmi2Warning, "Container use MONO thread"); + logger(fmi2Warning, "Container use MONO thread"); return 0; } @@ -73,7 +72,7 @@ static int read_profiling_flag(container_t* container, config_file_t* file) { return -2; if (container->profiling) - logger(container, fmi2Warning, "Container use PROFILING"); + logger(fmi2Warning, "Container use PROFILING"); return 0; } @@ -84,7 +83,7 @@ static int read_conf_time_step(container_t* container, config_file_t* file) { return -1; if (sscanf(file->line, "%le", &container->time_step) < 1) return -2; - logger(container, fmi2OK, "Container time_step = %e", container->time_step); + logger(fmi2OK, "Container time_step = %e", container->time_step); return 0; } @@ -97,7 +96,7 @@ static int read_conf_fmu(container_t *container, const char *dirname, config_fil if (sscanf(file->line, "%d", &nb_fmu) < 1) return -2; - logger(container, fmi2OK, "%d FMU's to be loaded", nb_fmu); + logger(fmi2OK, "%d FMU's to be loaded", nb_fmu); if (!nb_fmu) { container->fmu = NULL; return 0; @@ -130,10 +129,10 @@ static int read_conf_fmu(container_t *container, const char *dirname, config_fil return -1; const char *guid = file->line; - logger(container, fmi2OK, "Loading '%s.dll' from directory '%s'", identifier, directory); + logger(fmi2OK, "Loading '%s.dll' from directory '%s'", identifier, directory); if (fmu_load_from_directory(container, i, directory, identifier, guid)) { - logger(container, fmi2Error, "Cannot load from directory '%s'", directory); + logger(fmi2Error, "Cannot load from directory '%s'", directory); free(identifier); return -4; } @@ -413,52 +412,52 @@ static int read_conf(container_t* container, const char* dirname) { filename[sizeof(filename) - 1] = '\0'; strncat(filename, "/container.txt", sizeof(filename) - strlen(filename) - 1); - logger(container, fmi2OK, "Reading '%s'...", filename); + logger(fmi2OK, "Reading '%s'...", filename); file.fp = fopen(filename, "rt"); if (!file.fp) { - logger(container, fmi2Error, "Cannot open '%s': %s.", filename, strerror(errno)); + logger(fmi2Error, "Cannot open '%s': %s.", filename, strerror(errno)); return -1; } if (read_mt_flag(container, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot configure MT flag."); + logger(fmi2Error, "Cannot configure MT flag."); return -2; } if (read_profiling_flag(container, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot configure PROFILING flag."); + logger(fmi2Error, "Cannot configure PROFILING flag."); return -2; } if (read_conf_time_step(container, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot set time step."); + logger(fmi2Error, "Cannot set time step."); return -2; } if (read_conf_fmu(container, dirname, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot load embedded FMU's."); + logger(fmi2Error, "Cannot load embedded FMU's."); return -3; } if (read_conf_io(container, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot allocate local variables."); + logger(fmi2Error, "Cannot allocate local variables."); return -4; } if (read_conf_vr(container, &file)) { fclose(file.fp); - logger(container, fmi2Error, "Cannot read translation table."); + logger(fmi2Error, "Cannot read translation table."); return -5; } - logger(container, fmi2OK, "Real : %d local variables and %d ports", container->nb_local_reals, container->nb_ports_reals); - logger(container, fmi2OK, "Integer : %d local variables and %d ports", container->nb_local_integers, container->nb_ports_integers); - logger(container, fmi2OK, "Boolean : %d local variables and %d ports", container->nb_local_booleans, container->nb_ports_booleans); - logger(container, fmi2OK, "String : %d local variables and %d ports", container->nb_local_strings, container->nb_ports_strings); + logger(fmi2OK, "Real : %d local variables and %d ports", container->nb_local_reals, container->nb_ports_reals); + logger(fmi2OK, "Integer : %d local variables and %d ports", container->nb_local_integers, container->nb_ports_integers); + logger(fmi2OK, "Boolean : %d local variables and %d ports", container->nb_local_booleans, container->nb_ports_booleans); + logger(fmi2OK, "String : %d local variables and %d ports", container->nb_local_strings, container->nb_ports_strings); for (int i = 0; i < container->nb_fmu; i += 1) { if (read_conf_fmu_io(&container->fmu[i].fmu_io, &file)) { @@ -466,17 +465,17 @@ static int read_conf(container_t* container, const char* dirname) { return -6; } - logger(container, fmi2OK, "FMU#%d: IN %d reals, %d integers, %d booleans, %d strings", i, + logger(fmi2OK, "FMU#%d: IN %d reals, %d integers, %d booleans, %d strings", i, container->fmu[i].fmu_io.reals.in.nb, container->fmu[i].fmu_io.integers.in.nb, container->fmu[i].fmu_io.booleans.in.nb, container->fmu[i].fmu_io.strings.in.nb); - logger(container, fmi2OK, "FMU#%d: START %d reals, %d integers, %d booleans, %d strings", i, + logger(fmi2OK, "FMU#%d: START %d reals, %d integers, %d booleans, %d strings", i, container->fmu[i].fmu_io.start_reals.nb, container->fmu[i].fmu_io.start_integers.nb, container->fmu[i].fmu_io.start_strings.nb, container->fmu[i].fmu_io.start_strings.nb); - logger(container, fmi2OK, "FMU#%d: OUT %d reals, %d integers, %d booleans, %d strings", i, + logger(fmi2OK, "FMU#%d: OUT %d reals, %d integers, %d booleans, %d strings", i, container->fmu[i].fmu_io.reals.out.nb, container->fmu[i].fmu_io.integers.out.nb, container->fmu[i].fmu_io.booleans.out.nb, @@ -533,6 +532,7 @@ fmi2Component fmi2Instantiate(fmi2String instanceName, container->debug = loggingOn; container->logger = functions->logger; + logger_init(container); /* logger() is available starting this point ! */ container->mt = 0; container->nb_fmu = 0; container->fmu = NULL; @@ -559,13 +559,13 @@ fmi2Component fmi2Instantiate(fmi2String instanceName, container->time = 0.0; container->tolerance = 1.0e-8; - logger(container, fmi2OK, "Container model loading..."); + logger(fmi2OK, "Container model loading..."); if (read_conf(container, fmuResourceLocation + strlen("file:///"))) { - logger(container, fmi2Error, "Cannot read container configuration."); + logger(fmi2Error, "Cannot read container configuration."); fmi2FreeInstance(container); return NULL; } - logger(container, fmi2OK, "Container configuration read."); + logger(fmi2OK, "Container configuration read."); for(int i=0; i < container->nb_fmu; i += 1) { fmi2Status status = fmuInstantiate(&container->fmu[i], @@ -574,7 +574,7 @@ fmi2Component fmi2Instantiate(fmi2String instanceName, visible, container->debug); if (status != fmi2OK) { - logger(container, fmi2Error, "Cannot Instiantiate FMU#%d", i); + logger(fmi2Error, "Cannot Instiantiate FMU#%d", i); fmi2FreeInstance(container); return NULL; } @@ -659,7 +659,7 @@ fmi2Status fmi2SetupExperiment(fmi2Component c, } container->time = startTime; - logger(container, fmi2OK, "fmi2SetupExperiment -- OK"); + logger(fmi2OK, "fmi2SetupExperiment -- OK"); return fmi2OK; } @@ -940,7 +940,7 @@ static fmi2Status do_internal_step_parallel_mt(container_t* container, fmi2Real for (int i = 0; i < container->nb_fmu; i += 1) { status = do_step_get_outputs(container, i); if (status != fmi2OK) { - logger(container, fmi2Error, "Container: FMU#%d failed doStep.", i); + logger(fmi2Error, "Container: FMU#%d failed doStep.", i); return status; } @@ -970,7 +970,7 @@ static fmi2Status do_internal_step_parallel(container_t* container, fmi2Real cur /* COMPUTATION */ status = fmuDoStep(fmu, currentCommunicationPoint, step_size, noSetFMUStatePriorToCurrentPoint); if (status != fmi2OK) { - logger(container, fmi2Error, "Container: FMU#%d failed doStep.", i); + logger(fmi2Error, "Container: FMU#%d failed doStep.", i); return status; } } @@ -1014,7 +1014,7 @@ fmi2Status fmi2DoStep(fmi2Component c, container->time = current_time; if (fabs(currentCommunicationPoint + communicationStepSize - current_time) > container->tolerance) { - logger(container, fmi2Warning, "CommunicationStepSize should be divisible by %e", container->time_step); + logger(fmi2Warning, "CommunicationStepSize should be divisible by %e", container->time_step); return fmi2Warning; } diff --git a/container/hash.c b/container/hash.c new file mode 100644 index 0000000..c0eb82b --- /dev/null +++ b/container/hash.c @@ -0,0 +1,161 @@ +#include +#include + +#include "hash.h" + + +#define HASH_DEFAULT_SIZE 201 /* prime number far from power of 2 numbers */ +#define HASH_COLLISION_MAX 100 + + +static unsigned long hash_function(const char *key, unsigned long hash_size) { + register unsigned long int val=0; + + while(*key != '\0') + { + register unsigned long int tmp; + val = (val << 4) + (*key); + tmp = val & 0xf0000000; + if (tmp) + { + val ^= tmp >> 24; + val ^= tmp; + } + + key++; + } + + return(val % hash_size); +} + + +hash_entry_t* hash_get_entry(const hash_t* hash, const char* key) { + unsigned long index = hash_function(key, hash->size); + + for (hash_entry_t* entry = hash->entry[index]; entry; entry = entry->next) + if (strcmp(entry->key, key) == 0) + return entry; + + return NULL; +} + + +void *hash_get_value(const hash_t *hash, const char *key) { + hash_entry_t *entry = hash_get_entry(hash, key); + if (entry) + return entry->value; + + return NULL; +} + + +static hash_entry_t *hash_entry_new(char *key, void *value) { + hash_entry_t *entry; + + entry = malloc(sizeof(*entry)); + entry->key = key; + entry->value = value; + entry->next = NULL; + + return entry; +} + + +static void hash_entry_free(hash_entry_t *entry) { + free(entry->key); + free(entry->value); + free(entry); +} + + +unsigned long hash_entries_number(const hash_t *hash) { + return hash->nb; +} + + +static void hash_reorder(hash_t *hash) +{ + unsigned long i; + const unsigned long N = hash->size; + const unsigned long N2 = N * 2 + 1; /* pour avoir un nombre impaire */ + hash_entry_t **new_entry; + + /* Initialisation de la nouvelle table */ + new_entry = malloc(sizeof(*new_entry) * N2); + for (i = 0; ientry[i]; e; e = next) + { + unsigned long indice; + next = e->next; + + indice = hash_function(e->key, N2); + e->next = new_entry[indice]; + new_entry[indice] = e; + } + } + + /* lib�ration de l'ancienne et M-�-J */ + free(hash->entry); + hash->entry = new_entry; + hash->size = N2; + + return; +} + + +void hash_set_value(hash_t *hash, char *key, void *value) { + hash_entry_t *entry = hash_get_entry(hash, key); + if (entry) { + free(entry->value); + entry->value = value; + } else { + unsigned collision = 0; + unsigned long index = hash_function(key, hash->size); + hash_entry_t *current = hash->entry[index]; + hash->entry[index] = hash_entry_new(key, value); + hash->entry[index]->next = current; + hash->nb += 1; + + /* calculate collision */ + for (entry = hash->entry[index]; entry->next; entry = entry->next) + collision += 1; + if (collision >= HASH_COLLISION_MAX) + hash_reorder(hash); + } +} + + +hash_t *hash_new(void) { + hash_t *hash; + + hash = malloc(sizeof(*hash)); + hash->size = HASH_DEFAULT_SIZE; + hash->nb = 0; + hash->entry = malloc(sizeof(*hash->entry) * hash->size); + for(unsigned long i = 0; i < hash->size; i += 1) + hash->entry[i] = NULL; + + return hash; +} + + +void hash_free(hash_t *hash) { + for(unsigned long i = 0; i < hash->size; i += 1) { + hash_entry_t *entry = hash->entry[i]; + while(entry) { + hash_entry_t *next = entry->next; + hash_entry_free(entry); + entry =next; + } + } + free(hash->entry); + free(hash); +} diff --git a/container/hash.h b/container/hash.h new file mode 100644 index 0000000..4a6c54d --- /dev/null +++ b/container/hash.h @@ -0,0 +1,54 @@ +#ifndef HASH_T +#define HASH_T + +# ifdef __cplusplus +extern "C" { +# endif + + +/*---------------------------------------------------------------------------- + H A S H _ E N T R Y _ T +----------------------------------------------------------------------------*/ + +typedef struct hash_entry_s { + char *key; + void *value; + struct hash_entry_s *next; +} hash_entry_t; + + +/*---------------------------------------------------------------------------- + H A S H _ T +----------------------------------------------------------------------------*/ + +typedef struct { + unsigned long size; + unsigned long nb; + hash_entry_t **entry; +} hash_t; + + +/*---------------------------------------------------------------------------- + H A S H _ LOOP _ F U N C T I O N _ T +----------------------------------------------------------------------------*/ + +typedef void (*hash_loop_function_t)(const hash_entry_t *, void *data); + + +/*---------------------------------------------------------------------------- + P R O T O T Y P E S +----------------------------------------------------------------------------*/ + +extern void hash_free(hash_t *hash); +extern hash_t *hash_new(void); +extern unsigned long hash_entries_number(const hash_t *hash); +extern void hash_set_value(hash_t *hash, char *key, void *value); +extern void *hash_get_value(const hash_t *hash, const char *key); +extern hash_entry_t *hash_get_entry(const hash_t* hash, const char* key); +extern hash_entry_t* hash_get_entry_closest(const hash_t* hash, const char* key); +extern void hash_loop(const hash_t* hash, hash_loop_function_t function, void *data); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/container/library.c b/container/library.c index 6221585..2458f42 100644 --- a/container/library.c +++ b/container/library.c @@ -6,14 +6,27 @@ #ifdef WIN32 # include +# include #else # include # include #endif +#include "hash.h" #include "library.h" +#include "logger.h" +#ifdef WIN32 +typedef enum { + LIBRARY_DLL_NOT_FOUND, + LIBRARY_DLL_MISSING_DEPENDENCIES, + LIBRARY_DLL_OK +} libray_status_t; + +static libray_status_t* libray_analyse(hash_t* dll_db, const char* filename); +#endif + void *library_symbol(library_t library, const char *symbol_name) { #ifdef WIN32 return (void *)GetProcAddress(library, symbol_name); @@ -23,6 +36,20 @@ void *library_symbol(library_t library, const char *symbol_name) { } +static void library_load_error(const char* library_filename) { +#ifdef WIN32 + hash_t* dll_db = hash_new(); + libray_analyse(dll_db, library_filename); + hash_free(dll_db); +#else + logger(fmi2Error, "dlopen Error: %s", dlerror()); +#endif + logger(fmi2Error, "Cannot load `%s'", library_filename); + + return; /* Never reached */ +} + + library_t library_load(const char* library_filename) { library_t handle; #ifdef WIN32 @@ -30,6 +57,9 @@ library_t library_load(const char* library_filename) { #else handle = dlopen(library_filename, RTLD_LAZY); /* RTLD_LOCAL can lead to failure */ #endif + if (!handle) + library_load_error(library_filename); + return handle; } @@ -44,3 +74,131 @@ void library_unload(library_t library) { } } +/*---------------------------------------------------------------------------- + D E P E N D E N C I E S A N A L Y S I S +----------------------------------------------------------------------------*/ +/* + * see: https://stackoverflow.com/questions/597260/how-to-determine-a-windows-executables-dll-dependencies-programmatically + */ +#ifdef WIN32 +static PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader) { + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); + unsigned i; + + for (i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++) + { + // This 3 line idiocy is because Watcom's linker actually sets the + // Misc.VirtualSize field to 0. (!!! - Retards....!!!) + DWORD size = section->Misc.VirtualSize; + if (0 == size) + size = section->SizeOfRawData; + + // Is the RVA within this section? + if ((rva >= section->VirtualAddress) && + (rva < (section->VirtualAddress + size))) + return section; + } + + return 0; +} + + +static LPVOID GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, PBYTE imageBase) { + PIMAGE_SECTION_HEADER pSectionHdr; + INT delta; + + pSectionHdr = GetEnclosingSectionHeader(rva, pNTHeader); + if (!pSectionHdr) + return 0; + + delta = (INT)(pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData); + return (PVOID)(imageBase + rva - delta); +} + + +static libray_status_t* libray_try_load(const char* filename) { + libray_status_t* status = malloc(sizeof(*status)); + + HINSTANCE handle = LoadLibraryExA(filename, NULL, DONT_RESOLVE_DLL_REFERENCES); + if (handle) { + FreeLibrary(handle); + + handle = LoadLibraryA(filename); + if (handle) { + FreeLibrary(handle); + *status = LIBRARY_DLL_OK; + } + else { + *status = LIBRARY_DLL_MISSING_DEPENDENCIES; + } + } + else { + *status = LIBRARY_DLL_NOT_FOUND; + } + return status; +} + + +static void libray_log_status(const char* filename, libray_status_t* status) { + switch (*status) { + case LIBRARY_DLL_OK: + logger(fmi2Warning, "DLL `%s' is found.", filename); + break; + case LIBRARY_DLL_NOT_FOUND: + logger(fmi2Warning, "DLL `%s' is not found.", filename); + break; + case LIBRARY_DLL_MISSING_DEPENDENCIES: + logger(fmi2Warning, "DLL `%s' has missing dependencies.", filename); + break; + } +} + + +static void libray_analyse_deeply(hash_t* dll_db, const char* filename) { + PLOADED_IMAGE image = ImageLoad(filename, NULL); + if (!image) { + logger(fmi2Error, "Cannot ImageLoad(%s)", filename); + } + else { + if (image->FileHeader->OptionalHeader.NumberOfRvaAndSizes >= 2) { + PIMAGE_IMPORT_DESCRIPTOR importDesc = + (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA( + image->FileHeader->OptionalHeader.DataDirectory[1].VirtualAddress, + image->FileHeader, image->MappedAddress); + while (1) { + // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR + if ((importDesc->TimeDateStamp == 0) && (importDesc->Name == 0)) + break; + const char* dll_filename = GetPtrFromRVA(importDesc->Name, image->FileHeader, image->MappedAddress); + libray_analyse(dll_db, dll_filename); + importDesc++; + } + } + ImageUnload(image); + } + return; +} + + +static libray_status_t* libray_analyse_really(hash_t* dll_db, const char* filename) { + libray_status_t* status = libray_try_load(filename); + hash_set_value(dll_db, strdup(filename), status); + if (*status == LIBRARY_DLL_MISSING_DEPENDENCIES) + libray_analyse_deeply(dll_db, filename); + + libray_log_status(filename, status); + + return status; +} + + +static libray_status_t* libray_analyse(hash_t* dll_db, const char* filename) { + libray_status_t* status; + + status = hash_get_value(dll_db, filename); + if (!status) + status = libray_analyse_really(dll_db, filename); + + return status; +} +#endif /* WIN32 */ diff --git a/container/library.h b/container/library.h index 0325b9f..9d16a03 100644 --- a/container/library.h +++ b/container/library.h @@ -26,19 +26,6 @@ typedef void* library_t; #endif -/*---------------------------------------------------------------------------- - L I B R A R Y _ S T A T U S _ T -----------------------------------------------------------------------------*/ - -#ifdef WIN32 -typedef enum { - LIBRARY_DLL_NOT_FOUND, - LIBRARY_DLL_MISSING_DEPENDENCIES, - LIBRARY_DLL_OK -} libray_status_t; -#endif - - /*---------------------------------------------------------------------------- P R O T O T Y P E S ----------------------------------------------------------------------------*/ diff --git a/container/logger.c b/container/logger.c index 4bbc6bb..0e571d9 100644 --- a/container/logger.c +++ b/container/logger.c @@ -7,15 +7,29 @@ #include "container.h" -void logger(const container_t *container, fmi2Status status, const char *message, ...) { - char buffer[4096]; +static const container_t *logger_container = NULL; + +void logger_init(const container_t *container) { + logger_container = container; +} + +void logger(fmi2Status status, const char *message, ...) { va_list ap; va_start(ap, message); - vsnprintf(buffer, sizeof(buffer), message, ap); - va_end(ap); - - if ((status != fmi2OK) || (container->debug)) - container->logger(container->environment, container->instance_name, status, NULL, "%s", buffer); + if (logger_container) { + char buffer[4096]; + + vsnprintf(buffer, sizeof(buffer), message, ap); + va_end(ap); + + if ((status != fmi2OK) || (logger_container->debug)) { + logger_container->logger(logger_container->environment, + logger_container->instance_name, + status, NULL, "%s", buffer); + } + } else { + vprintf(message, ap); + } return; } diff --git a/container/logger.h b/container/logger.h index 425fdf0..6b4de36 100644 --- a/container/logger.h +++ b/container/logger.h @@ -10,7 +10,8 @@ P R O T O T Y P E S ----------------------------------------------------------------------------*/ -void logger(const container_t *container, fmi2Status status, const char *message, ...); +void logger_init(const container_t *container); +void logger(fmi2Status status, const char *message, ...); void logger_embedded_fmu(fmu_t *fmu, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...); diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index f2ca00f..b7e4016 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -92,7 +92,8 @@ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None): for node in self.children: node.make_fmu(fmu_directory, debug=debug) - container = FMUContainer(self.name, fmu_directory, description_pathname=description_pathname) + identifier = str(Path(self.name).stem) + container = FMUContainer(identifier, fmu_directory, description_pathname=description_pathname) for fmu_name in sorted(self.fmu_names_list): container.get_fmu(fmu_name) From e7e0cf6b740b04a1a81d0720685c2de6ddcd0b82 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Wed, 15 Jan 2025 14:00:56 +0100 Subject: [PATCH 02/17] Expose the parameters of the embedded FMUs (#11) * startTime and stopTime are deduced from 1st embedded FMU * improve log message * fix ChangeLog * Include parameters in XML * Handle parameters as inputs so that they can be exposed at container level * auto-parameter can be configured through json or cmd line * Update changelog * Update README to mention -auto-parameter option * fix default auto_param to false and fix test plan --- CHANGELOG.md | 10 +-- README.md | 3 +- fmu_manipulation_toolbox/assembly.py | 61 ++++++++++--------- fmu_manipulation_toolbox/cli.py | 7 ++- fmu_manipulation_toolbox/fmu_container.py | 29 +++++++-- tests/containers/arch/REF-flat-dump.json | 1 + .../arch/REF-hierarchical-dump.json | 2 + tests/containers/arch/REF-reversed-dump.json | 2 + .../bouncing_ball/REF-bouncing.json | 1 + tests/containers/ssp/REF-bouncing-dump.json | 1 + tests/test_suite.py | 1 + 11 files changed, 78 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a558e2..cfc5047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,16 +4,18 @@ This package was formerly known as `fmutool`. ## Version 1.8.2 (upcoming) * FIXED: `fmucontainer` identifier (for coSimulation) does not contain ".fmu" anymore -* TODO: ADDED: take care of stoptime -* TODO: Expose parameters -* ADDED: GUI for `fmucontainer` +* ADDED: `fmucontainer` log more information when embedded FMU cannot be loaded +* ADDED: `fmucontainer` startTime and stopTime are deduced from 1st embedded FMU +* ADDED: `fmucontainer` support new option `-auto-parameter` (parameters are not exposed by default) +* [ ] ADDED: preliminary version of GUI for `fmucontainer` + ## Version 1.8.1 * FIXED: `fmucontainer` read links from `.json` input files * CHANGED: switch to PyQT6 and add minor GUI improvements ## Version 1.8 -* CHANGE: Package in now known as `fmu_manipulation` +* CHANGE: Python Package in now known as `fmu-manipulation-toolbox` * ADDED: `fmucontainer` support `canHandleVariableCommunicationStepSize` * ADDED: `fmucontainer` support `.spp` or `.json` as input files * ADDED: `fmucontainer` new `-dump` option to save container description diff --git a/README.md b/README.md index 84ede3d..2c927fd 100755 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ optional arguments: ``` usage: fmucontainer [-h] [-fmu-directory FMU_DIRECTORY] -container filename.{csv|json|ssp},[:step_size] [-debug] - [-no-auto-input] [-no-auto-output] [-no-auto-link] [-mt] [-profile] [-dump-json] + [-no-auto-input] [-no-auto-output] [-auto-parameter] [-no-auto-link] [-mt] [-profile] [-dump-json] Generate FMU from FMU's @@ -136,6 +136,7 @@ optional arguments: -debug Add lot of useful log during the process. (default: False) -no-auto-input Create ONLY explicit input. (default: True) -no-auto-output Create ONLY explicit output. (default: True) + -auto-parameter Expose parameters of the embedded fmu's. (default: False) -no-auto-link Create ONLY explicit links. (default: True) -mt Enable Multi-Threaded mode for the generated container. (default: False) -profile Enable Profiling mode for the generated container. (default: False) diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index b7e4016..4c4ccb7 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -32,7 +32,7 @@ def __init__(self, from_port: Port, to_port: Port): class AssemblyNode: def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False, - auto_link=True, auto_input=True, auto_output=True): + auto_link=True, auto_input=True, auto_output=True, auto_parameter=False): self.name = name if step_size: try: @@ -47,6 +47,7 @@ def __init__(self, name: Optional[str], step_size: float = None, mt=False, profi self.auto_link = auto_link self.auto_input = auto_input self.auto_output = auto_output + self.auto_parameter = auto_parameter self.parent: Optional[AssemblyNode] = None self.children: List[AssemblyNode] = [] # sub-containers @@ -68,7 +69,6 @@ def add_sub_node(self, sub_node): self.fmu_names_list.add(sub_node.name) self.children.append(sub_node) - def add_fmu(self, fmu_name: str): self.fmu_names_list.add(fmu_name) @@ -116,7 +116,8 @@ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None): container.add_implicit_rule(auto_input=self.auto_input, auto_output=self.auto_output, - auto_link=self.auto_link) + auto_link=self.auto_link, + auto_parameter=self.auto_parameter) container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, debug=debug) @@ -135,13 +136,14 @@ def __repr__(self): class Assembly: def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False, - auto_output=True, mt=False, profiling=False, fmu_directory: Path = "."): + auto_output=True, mt=False, profiling=False, fmu_directory: Path = ".", auto_parameter=False): self.filename = Path(filename) self.default_auto_input = auto_input self.debug = debug self.default_auto_output = auto_output self.default_step_size = step_size self.default_auto_link = auto_link + self.default_auto_parameter = auto_parameter self.default_mt = mt self.default_profiling = profiling self.fmu_directory = fmu_directory @@ -198,7 +200,8 @@ def read_csv(self): name = str(self.filename.with_suffix(".fmu")) self.root = AssemblyNode(name, step_size=self.default_step_size, auto_link=self.default_auto_link, mt=self.default_mt, profiling=self.default_profiling, - auto_input=self.default_auto_input, auto_output=self.default_auto_output) + auto_input=self.default_auto_input, auto_output=self.default_auto_output, + auto_parameter=self.default_auto_parameter) with open(self.input_pathname) as file: reader = csv.reader(file, delimiter=';') @@ -295,47 +298,49 @@ def read_json(self): if not self.root.name: self.root.name = str(self.filename.with_suffix(".fmu")) - def _json_decode_node(self, data:Dict) -> AssemblyNode: + def _json_decode_node(self, data: Dict) -> AssemblyNode: name = data.get("name", None) # 1 - step_size = data.get("step_size", self.default_step_size) # 7 + mt = data.get("mt", self.default_mt) # 2 + profiling = data.get("profiling", self.default_profiling) # 3 auto_link = data.get("auto_link", self.default_auto_link) # 4 auto_input = data.get("auto_input", self.default_auto_input) # 5 auto_output = data.get("auto_output", self.default_auto_output) # 6 - mt = data.get("mt", self.default_mt) # 2 - profiling = data.get("profiling", self.default_profiling) # 3 + auto_parameter = data.get("auto_parameter", self.default_auto_parameter) # 6b + step_size = data.get("step_size", self.default_step_size) # 7 node = AssemblyNode(name, step_size=step_size, auto_link=auto_link, mt=mt, profiling=profiling, - auto_input=auto_input, auto_output=auto_output) + auto_input=auto_input, auto_output=auto_output, auto_parameter=auto_parameter) for key, value in data.items(): - if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling'): + if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling', + 'auto_parameter'): continue # Already read - elif key == "container": # 8 + elif key == "container": # 8 if not isinstance(value, list): raise AssemblyError("JSON: 'container' keyword should define a list.") for sub_data in value: node.add_sub_node(self._json_decode_node(sub_data)) - elif key == "fmu": # 9 + elif key == "fmu": # 9 if not isinstance(value, list): raise AssemblyError("JSON: 'fmu' keyword should define a list.") for fmu in value: node.add_fmu(fmu) - elif key == "input": # 10 + elif key == "input": # 10 self._json_decode_keyword('input', value, node.add_input) - elif key == "output": # 11 + elif key == "output": # 11 self._json_decode_keyword('output', value, node.add_output) - elif key == "link": # 12 + elif key == "link": # 12 self._json_decode_keyword('link', value, node.add_link) - elif key == "start": # 13 + elif key == "start": # 13 self._json_decode_keyword('start', value, node.add_start_value) - elif key == "drop": #14 + elif key == "drop": # 14 self._json_decode_keyword('drop', value, node.add_drop_port) else: @@ -355,7 +360,6 @@ def _json_decode_keyword(keyword: str, value, function): except TypeError: raise AssemblyError(f"JSON: '{keyword}' value does not contain right number of fields: {line}.") - def write_json(self, filename: Union[str, Path]): with open(self.fmu_directory / filename, "wt") as file: data = self._json_encode_node(self.root) @@ -363,21 +367,22 @@ def write_json(self, filename: Union[str, Path]): def _json_encode_node(self, node: AssemblyNode) -> Dict[str, Any]: json_node = dict() - json_node["name"] = node.name # 1 - json_node["mt"] = node.mt # 2 - json_node["profiling"] = node.profiling # 3 - json_node["auto_link"] = node.auto_link # 4 - json_node["auto_input"] = node.auto_input # 5 - json_node["auto_output"] = node.auto_output # 6 + json_node["name"] = node.name # 1 + json_node["mt"] = node.mt # 2 + json_node["profiling"] = node.profiling # 3 + json_node["auto_link"] = node.auto_link # 4 + json_node["auto_input"] = node.auto_input # 5 + json_node["auto_output"] = node.auto_output # 6 + json_node["auto_parameter"] = node.auto_parameter # 6b if node.step_size: - json_node["step_size"] = node.step_size # 7 + json_node["step_size"] = node.step_size # 7 if node.children: json_node["container"] = [self._json_encode_node(child) for child in node.children] # 8 if node.fmu_names_list: - json_node["fmu"] = [f"{fmu_name}" for fmu_name in sorted(node.fmu_names_list)] #9 + json_node["fmu"] = [f"{fmu_name}" for fmu_name in sorted(node.fmu_names_list)] # 9 if node.input_ports: json_node["input"] = [[f"{source}", f"{port.fmu_name}", f"{port.port_name}"] # 10 @@ -397,7 +402,7 @@ def _json_encode_node(self, node: AssemblyNode) -> Dict[str, Any]: for port, value in node.start_values.items()] if node.drop_ports: - json_node["drop"] = [[f"{port.fmu_name}", f"{port.port_name}"] for port in node.drop_ports] # 14 + json_node["drop"] = [[f"{port.fmu_name}", f"{port.port_name}"] for port in node.drop_ports] # 14 return json_node diff --git a/fmu_manipulation_toolbox/cli.py b/fmu_manipulation_toolbox/cli.py index 749120e..85f097d 100644 --- a/fmu_manipulation_toolbox/cli.py +++ b/fmu_manipulation_toolbox/cli.py @@ -176,6 +176,9 @@ def fmucontainer(): parser.add_argument("-no-auto-output", action="store_false", dest="auto_output", default=True, help="Create ONLY explicit output.") + parser.add_argument("-auto-parameter", action="store_true", dest="auto_parameter", default=False, + help="Expose parameters of the embedded fmu's.") + parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True, help="Create ONLY explicit links.") @@ -206,8 +209,8 @@ def fmucontainer(): try: assembly = Assembly(filename, step_size=step_size, auto_link=config.auto_link, auto_input=config.auto_input, auto_output=config.auto_output, mt=config.mt, - profiling=config.profiling, fmu_directory=fmu_directory, debug=config.debug) - + profiling=config.profiling, fmu_directory=fmu_directory, debug=config.debug, + auto_parameter=config.auto_parameter) except FileNotFoundError as e: logger.fatal(f"Cannot read file: {e}") continue diff --git a/fmu_manipulation_toolbox/fmu_container.py b/fmu_manipulation_toolbox/fmu_container.py index c0efe50..25d7ddb 100644 --- a/fmu_manipulation_toolbox/fmu_container.py +++ b/fmu_manipulation_toolbox/fmu_container.py @@ -77,6 +77,8 @@ def __init__(self, filename): self.fmi_version = None self.step_size = None + self.start_time = None + self.stop_time = None self.model_identifier = None self.guid = None self.ports: Dict[str, FMUPort] = {} @@ -103,12 +105,13 @@ def cosimulation_attrs(self, attrs: Dict[str, str]): for capability in self.capability_list: self.capabilities[capability] = attrs.get(capability, "false") - def experiment_attrs(self, attrs): + def experiment_attrs(self, attrs: Dict[str, str]): try: self.step_size = float(attrs['stepSize']) except KeyError: logger.warning(f"FMU '{self.name}' does not specify preferred step size") - pass + self.start_time = float(attrs.get("startTime", 0.0)) + self.stop_time = float(attrs.get("stopTime", self.start_time + 1.0)) def scalar_type(self, type_name, attrs): if self.current_port: @@ -195,6 +198,9 @@ def __init__(self, identifier: str, fmu_directory: Union[str, Path], description self.description_pathname = description_pathname + self.start_time = None + self.stop_time = None + # Rules self.inputs: Dict[str, ContainerPort] = {} self.outputs: Dict[str, ContainerPort] = {} @@ -299,13 +305,18 @@ def find_input(self, port_to_connect: FMUPort) -> Optional[ContainerPort]: return ContainerPort(fmu, port.name) return None - def add_implicit_rule(self, auto_input: bool = True, auto_output: bool = True, auto_link: bool = True): + def add_implicit_rule(self, auto_input=True, auto_output=True, auto_link=True, auto_parameter=False): # Auto Link outputs for fmu in self.execution_order: for port_name in fmu.ports: cport = ContainerPort(fmu, port_name) if cport not in self.rules: - if cport.port.causality == 'output': + if cport.port.causality == 'parameter' and auto_parameter: + parameter_name = cport.fmu.model_identifier+"."+cport.port.name + logger.info(f"AUTO PARAMETER: {cport} as {parameter_name}") + self.inputs[parameter_name] = cport + self.mark_ruled(cport, 'PARAMETER') + elif cport.port.causality == 'output': candidate_cport = self.find_input(cport.port) if auto_link and candidate_cport: local = Local(cport) @@ -406,6 +417,14 @@ def make_fmu_xml(self, xml_file, step_size: float, profiling: bool): if fmu.capabilities[capability] == "true": capabilities[capability] = "true" + if self.start_time is None: + self.start_time = self.execution_order[0].start_time + logger.info(f"start_time={self.start_time} (deduced from the _first_ embedded FMU)") + + if self.stop_time is None: + self.stop_time = self.execution_order[0].stop_time + logger.info(f"stop_time={self.stop_time} (deduced from the _first_ embedded FMU)") + xml_file.write(f""" - + """) diff --git a/tests/containers/arch/REF-flat-dump.json b/tests/containers/arch/REF-flat-dump.json index f8483de..758de08 100644 --- a/tests/containers/arch/REF-flat-dump.json +++ b/tests/containers/arch/REF-flat-dump.json @@ -5,6 +5,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "step_size": 0.5, "fmu": [ "gain.fmu", diff --git a/tests/containers/arch/REF-hierarchical-dump.json b/tests/containers/arch/REF-hierarchical-dump.json index 5ec0a7e..bb15569 100644 --- a/tests/containers/arch/REF-hierarchical-dump.json +++ b/tests/containers/arch/REF-hierarchical-dump.json @@ -5,6 +5,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "step_size": 0.5, "container": [ { @@ -14,6 +15,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "step_size": 0.01, "fmu": [ "integrate.fmu", diff --git a/tests/containers/arch/REF-reversed-dump.json b/tests/containers/arch/REF-reversed-dump.json index 3e8f4cb..c0ba425 100644 --- a/tests/containers/arch/REF-reversed-dump.json +++ b/tests/containers/arch/REF-reversed-dump.json @@ -5,6 +5,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "step_size": 0.01, "container": [ { @@ -14,6 +15,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "step_size": 0.5, "fmu": [ "gain.fmu" diff --git a/tests/containers/bouncing_ball/REF-bouncing.json b/tests/containers/bouncing_ball/REF-bouncing.json index 4173b65..a255b19 100644 --- a/tests/containers/bouncing_ball/REF-bouncing.json +++ b/tests/containers/bouncing_ball/REF-bouncing.json @@ -5,6 +5,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "fmu": [ "bb_position.fmu", "bb_velocity.fmu" diff --git a/tests/containers/ssp/REF-bouncing-dump.json b/tests/containers/ssp/REF-bouncing-dump.json index 79d4899..b8f8b5a 100644 --- a/tests/containers/ssp/REF-bouncing-dump.json +++ b/tests/containers/ssp/REF-bouncing-dump.json @@ -5,6 +5,7 @@ "auto_link": true, "auto_input": true, "auto_output": true, + "auto_parameter": false, "fmu": [ "resources/bb_position.fmu", "resources/bb_velocity.fmu" diff --git a/tests/test_suite.py b/tests/test_suite.py index 788bb1f..4dd21e0 100755 --- a/tests/test_suite.py +++ b/tests/test_suite.py @@ -89,5 +89,6 @@ def test_container_json_reversed(self): self.assert_identical_files("containers/arch/REF-reversed-dump.json", "containers/arch/reversed-dump.json") + if __name__ == '__main__': unittest.main() From c943bd5cad0262d8cfc36be540a626b0312fc0fa Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Fri, 3 Jan 2025 09:47:26 +0100 Subject: [PATCH 03/17] switch to pyside --- fmu_manipulation_toolbox/gui.py | 23 +++++++++++++---------- requirements.txt | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index ab6ff15..0e41fea 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -1,10 +1,10 @@ import os.path import sys from .version import __version__ as version -from PyQt6.QtCore import Qt, QObject, QUrl, pyqtSignal, QDir, QSize, QPoint -from PyQt6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, +from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint +from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QTextBrowser, QInputDialog, QMenu) -from PyQt6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QIcon, QDesktopServices, QAction, QPainter, QColor) +from PySide6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QIcon, QDesktopServices, QAction, QPainter, QColor) import textwrap from functools import partial from typing import Optional @@ -19,10 +19,10 @@ class DropZoneWidget(QLabel): HEIGHT = 150 fmu = None last_directory = None - clicked = pyqtSignal() + clicked = Signal() - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent) self.setAcceptDrops(True) self.set_image(None) self.setProperty("class", "dropped_fmu") @@ -60,7 +60,7 @@ def mousePressEvent(self, event): default_directory = os.path.expanduser('~') fmu_filename, _ = QFileDialog.getOpenFileName(parent=self, caption='Select FMU to Manipulate', - directory=default_directory, filter="FMU files (*.fmu)") + dir=default_directory, filter="FMU files (*.fmu)") if fmu_filename: self.set_fmu(fmu_filename) @@ -87,8 +87,7 @@ def set_image(self, filename=None): self.setPixmap(pixmap) - - def set_fmu(self, filename): + def set_fmu(self, filename: str): try: self.last_directory = os.path.dirname(filename) self.fmu = FMU(filename) @@ -104,7 +103,10 @@ class LogWidget(QTextBrowser): class XStream(QObject): _stdout = None _stderr = None - messageWritten = pyqtSignal(str) + messageWritten = Signal(str) + + def __init__(self): + super().__init__() def flush(self): pass @@ -223,6 +225,7 @@ def __init__(self, *args, **kwargs): self.dropped_fmu = DropZoneWidget() self.dropped_fmu.clicked.connect(self.update_fmu) + self.layout.addWidget(self.dropped_fmu, 0, 0, 4, 1) font = QFont('Verdana') diff --git a/requirements.txt b/requirements.txt index deecccc..c6a05dd 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -PyQt6 +PySide6 >= 6.8.0 xmlschema >= 3.3.1 elementpath >= 4.4.0 colorama >= 0.4.6 From 4623277110c1f58055a6819deb876629ef7eeb6a Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Sat, 4 Jan 2025 21:18:12 +0100 Subject: [PATCH 04/17] Fix Filter menu --- fmu_manipulation_toolbox/gui.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 0e41fea..3dc9c4f 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -177,14 +177,14 @@ def __init__(self, items: Optional[list[str]] = (), parent=None): self.nb_items = len(items) self.update_filter_text() if items: - menu = QMenu() + self.menu = QMenu() for item in items: action = QAction(item, self) action.setCheckable(True) action.setChecked(True) action.triggered.connect(partial(self.toggle_item, action)) - menu.addAction(action) - self.setMenu(menu) + self.menu.addAction(action) + self.setMenu(self.menu) def toggle_item(self, action: QAction): if not action.isChecked() and len(self.items_selected) == 1: @@ -507,3 +507,7 @@ def main(): print(application.__doc__) sys.exit(application.exec()) + + +if __name__ == "__main__": + main() From a6b6d85de691f7a1af2fc0f3b1be6821d1a2a1b5 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Sun, 5 Jan 2025 21:13:16 +0100 Subject: [PATCH 05/17] Update icons --- .../resources/drop_fmu.png | Bin 10365 -> 10344 bytes fmu_manipulation_toolbox/resources/fmu.png | Bin 12048 -> 47050 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/fmu_manipulation_toolbox/resources/drop_fmu.png b/fmu_manipulation_toolbox/resources/drop_fmu.png index f06a4f390ff77b50c68d9ef2c94694aa0eb1e750..203cb48160f1df517086ba120ef52b9b984f7cfa 100644 GIT binary patch delta 9196 zcmbuERZ!eP*QW;yE+M!>Ah^4`ySvN)NeIDR|2RQIg1fuB!yw7v?(PJ4mu%ksYOCI@ z+Pm$$?&qSPzUZpoIp;;=k4DWfBJfR7MpDNU?!*r@1OHd!UFqTOnlSnZJW3xQbbw<8 zE{5UrmXt<(c%&ShIb>#E*|&=}?Gpj-7rv3?V#vtWIITH_mm&|RoaThW#Ey%!B@eD9 z1~ĺB7NJ;$~gNQtje0pKtJljsVq$1T-)J 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
    fwMU$;Dh=b7`8_K?M*(?SVM^WK!-JX z7Uz$jb$_s+wvy72@pqwax7Lorw5Zw@X~Ob8^pXBEmUWTWW=99(GyNJ*z?lQXojDu_ zp@DXB7Pl6flju}gZ4Yesdwx*}I>AKix@tgyEds?fMmunkv#PDz=uP>Ih4qpRQ-wFc zmI~ca$H)kNGsjfdZDRPakS&N1+)1_Gf#0M2!=3E0)$~UTlJ@oAZP)WH`137etkPKq zcAA0?J;AZ>oR#dbhF7`?e+s*dASJ8-bC2Nf-8;VW!{qoDk~{6e$TbaMXPUP@%vNEo z>~FGmY9oM>%t z#+!J0PYdH4dPPOWkNH4<+M;fU{7(KH)ib@0D?~s&o~kHb+d6{J?~Q?4PjE<{PWnBb z-65e{#t0G!gP*1Y*KaY1h4OvjYSf?Yh&`gvhrR5{d2Wrhb&Vwjuj&=cqqfD@A??Tr`PhSg zbBPYa+K1Y8mmnN9Mq4zHNue^s021~o>-ll_s(`HKyoZ;lxxA%V5M;o;-z|$I06DZ+ z^+UPrlY^|;jC2a-Mu@`qx9iv4M;;bnp;YuY9Qp3&5}$YswWZ9?+#`R9k^!#p6=5cj ztTq!uwB1-~DAZbCPwe$0Qxecvrz6lP)fdp3)1RQXIf+LIL>B%wn5nc1o|Vkz#Bjm- z60cwnjsNR6A+`GXh|2FCJ5YW5R$5#{q}-P?U^h+G9%QYo9Q6{fAajZLYs|;dq$ZD< zWz%SNBsGc?vu)Z(+3&?a3s@2sP*G>=o~YW7r7cSEQc!F54FGoxe|SzcKR>?K6Osjx zTFkQr>m3QE3}Gd|bWRUVRD%7ZJ#6ra1MJg%LEOr#`FoG#1~>}E1x7wH^WWt1i*o9+ zbFb*BD$PpwmZy2xDsk0p>Ej2JNTjg^b7n1)7}Qef_5wJ!nC&TK0b3Js)>`O-O=%sK zp7VA2+d0S1j?&5>u_#zumxjgnS>4TG>*sU{;W!i_G)= z$v<=+&f*%c0AV6qT-RxSBtiQWX;cc|bS2G^zm`yu;|1%Ea*jj3##l4Q2i}K=QSMr; zyT>`hWicHxiWGl05^h2jWV6p)RY(keSf^N)8^A$H|FNoWdDbS0o2ajIWHg`m2h?gh z#pMT)DZSvO#uQrL-Vm!L>rPiy9HVuYjrk9*`Ao6}WN7>|kK}#U<9(?mBR;c)?@V7b_GE0 zQ8b7FUf;YDPMnE<_<3>l_9JTI7niUZX)?(~gYV%OC`vyozzYil|FjN=T=P7puB0s8qyGO41(gB$(xVox5J})UNlRhgbqW*rl z@I*(KtTN%2SZLGe!^}L-d;1CfgNgv_&rDHoEh``YYZI7nXGMi$B!M!8TDrXV7#A6% zCnavVxUSgMPj+nBD|V>Z-JOo7%42kC5gC3XbZn;VoFYClSn0pJ@BgA<=Qi{&vRemI U7`5EJCg|T%lvR_dlClW;U$AG!DgXcg delta 9217 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 delta 10996 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 BB_jX; From 2ef406d4acf1b81c1dd2f316f95611de5e1d1a89 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Sun, 5 Jan 2025 21:41:42 +0100 Subject: [PATCH 06/17] First GUI work for container --- fmu_manipulation_toolbox/gui.py | 153 +++++++++++++++++- .../resources/container.png | Bin 0 -> 16682 bytes .../resources/icon_fmu.png | Bin 0 -> 5189 bytes 3 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 fmu_manipulation_toolbox/resources/container.png create mode 100644 fmu_manipulation_toolbox/resources/icon_fmu.png diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 3dc9c4f..80b2195 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -1,15 +1,16 @@ import os.path import sys from .version import __version__ as version -from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint +from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint, QModelIndex, QMimeData, QByteArray, QDataStream, QIODevice, QItemSelectionModel, QItemSelection from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, - QTextBrowser, QInputDialog, QMenu) -from PySide6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QIcon, QDesktopServices, QAction, QPainter, QColor) + QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QMainWindow) +from PySide6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction, QPainter, QColor, QStandardItemModel) import textwrap from functools import partial from typing import Optional from .fmu_operations import * +from .assembly import Assembly, AssemblyNode from .checker import checker_list from .help import Help @@ -210,7 +211,125 @@ def get(self): return sorted(self.items_selected) +class AssemblyTreeModel(QStandardItemModel): + dragDropFinished = Signal() + + def __init__(self, assembly: Assembly, parent=None): + super().__init__(parent) + + self.lastDroppedItems = [] + self.pendingRemoveRowsAfterDrop = False + self.setHorizontalHeaderLabels(['col1']) + self.add_node(assembly.root, self) + + def add_node(self, node: AssemblyNode, parent_item): + item = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'container.png')), + node.name) + item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled) + children_name = [child.name for child in node.children] + for fmu_name in node.fmu_names_list: + if not fmu_name in children_name: + fmu_node = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon_fmu.png')), + fmu_name) + fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled |Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled) + item.appendRow(fmu_node) + for child in node.children: + self.add_node(child, item) + parent_item.appendRow(item) + + def supportedDropActions(self): + return Qt.DropAction.MoveAction + + def _flags(self, index): + if not index.isValid(): + return Qt.ItemFlag.ItemIsEnabled + if index.row() % 2: + return Qt.ItemFlag.ItemIsEnabled | \ + Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled + else: + return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | \ + Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled + + def insertRows(self, row, count, parent): + print("insertRows") + return super().insertRows(row, count, parent) + + def removeRows(self, row, count, parent): + print("removeRows") + return super().removeRows(row, count, parent) + + def _setData(self, index, value, role): + print("setData") + return super().setData(index, value, role) + + def _mimeTypes(self): + print("mimeTypes") + return super().mimeTypes() + + def _mimeData(self, indexes): + print("mimeData") + return super().mimeData(indexes) + + def dropMimeData(self, data, action, row, column, parent): + print(f"dropMineData: {action} {row} {column} {parent}") + return super().dropMimeData(data, action, row, column, parent) + +class SelectionModel(QItemSelectionModel): + def __init__(self, parent=None): + QItemSelectionModel.__init__(self, parent) + + def onModelItemsReordered(self): + new_selection = QItemSelection() + new_index = QModelIndex() + for item in self.model().lastDroppedItems: + row = self.model().rowForItem(item) + if row is None: + continue + new_index = self.model().index(row, 0, QModelIndex()) + new_selection.select(new_index, new_index) + + self.clearSelection() + flags = QItemSelectionModel.ClearAndSelect | \ + QItemSelectionModel.Rows | \ + QItemSelectionModel.Current + self.select(new_selection, flags) + self.setCurrentIndex(new_index, flags) + +class ContainerWindow(QMainWindow): + def __init__(self, parent=None): + super().__init__(parent) + assembly = Assembly("tests/containers/arch/reversed.json") + self.model = AssemblyTreeModel(assembly) + self.selectionModel = SelectionModel(self.model) + self.model.dragDropFinished.connect(self.selectionModel.onModelItemsReordered) + self.view = QTreeView() + self.view.setModel(self.model) + self.view.expandAll() + self.view.setSelectionModel(self.selectionModel) + self.view.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + self.view.setDragDropOverwriteMode(False) + self.setCentralWidget(self.view) + + self.show() + + +class ContainerWindow2(QWidget): + def __init__(self, main_window, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.main_window = main_window + self.setWindowTitle('FMU Manipulation Toolbox - Container') + + # show the window + self.show() + + def closeEvent(self, event): + self.main_window.container_closed.emit() + event.accept() + + class FMUManipulationToolboxlMainWindow(QWidget): + container_closed = Signal() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -235,6 +354,15 @@ def __init__(self, *args, **kwargs): self.fmu_title.setFont(font) self.layout.addWidget(self.fmu_title, 0, 1, 1, 4) + + self.container_window = None + container_button = QPushButton("Make a container") + container_button.setProperty("class", "quit") + container_button.clicked.connect(self.launch_container) + self.container_closed.connect(self.closing_container) + self.layout.addWidget(container_button, 4, 1, 1, 1) + + help_widget = HelpWidget() self.layout.addWidget(help_widget, 0, 5, 1, 1) @@ -270,8 +398,8 @@ def __init__(self, *args, **kwargs): self.add_operation(operation[0], operation[1], operation[2], operation[3], line, col, **operation[4]) line += 1 - self.apply_filter_label = QLabel("Apply modification only on: ") - self.layout.addWidget(self.apply_filter_label, line, 1, 1, 2, alignment=Qt.AlignmentFlag.AlignRight) + self.apply_filter_label = QLabel("Apply only on: ") + self.layout.addWidget(self.apply_filter_label, line, 2, 1, 1, alignment=Qt.AlignmentFlag.AlignRight) self.set_tooltip(self.apply_filter_label, 'gui-apply-only') causality = ["parameter", "calculatedParameter", "input", "output", "local", "independent"] @@ -311,6 +439,20 @@ def __init__(self, *args, **kwargs): # show the window self.show() + def closeEvent(self, event): + if self.container_window: + self.container_window.close() + event.accept() + + def launch_container(self): + if not self.container_window: + self.container_window = ContainerWindow(self) + + def closing_container(self): + print("coucouc") + self.container_window = None + + def set_tooltip(self, widget, usage): widget.setToolTip("\n".join(textwrap.wrap(self.help.usage(usage)))) @@ -474,6 +616,7 @@ def __init__(self, *args, **kwargs): QLabel.dropped_fmu {background-color: #b5bab9} QLabel.dropped_fmu:hover {background-color: #c6cbca} QTextBrowser {background-color: #282830; color: #b5bab9;} +QTreeView {background-color: #282830; color: #b5bab9;} QMenu {font-size: 18px;} QMenu::item {padding: 2px 250px 2px 20px; border: 1px solid transparent;} QMenu::item::indicator {width: 32px; height: 32px; } diff --git a/fmu_manipulation_toolbox/resources/container.png b/fmu_manipulation_toolbox/resources/container.png new file mode 100644 index 0000000000000000000000000000000000000000..730c9073b41e67a6a728dffd78cb9bf9a0504c71 GIT binary patch literal 16682 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 wM;M1&07*qoM6N<$f|~1G+5i9m literal 0 HcmV?d00001 diff --git a/fmu_manipulation_toolbox/resources/icon_fmu.png b/fmu_manipulation_toolbox/resources/icon_fmu.png new file mode 100644 index 0000000000000000000000000000000000000000..9811053d807c77ed02d49b1fe13b9ff450431e4c GIT binary patch literal 5189 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 literal 0 HcmV?d00001 From 2bdc6df4efae0f4a4364e40af0741065db27c4a1 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Mon, 6 Jan 2025 22:14:10 +0100 Subject: [PATCH 07/17] Remove alpha on logo --- .../resources/fmu_manipulation_toolbox.png | Bin 37997 -> 28141 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png b/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png index 9405aa6099ba86d68e36393a380d9d0431ce5929..bf6a3c7db0cf7a86ba97a834ead6ca04f6b7f763 100644 GIT binary patch delta 27128 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 delta 37062 zcmdqI^-o=2_%7HYMO)m87K%F*w?dKPP+Sl0Qryoj?oiy_-QC^2Kyi0DxE?sSpYP3N z?)(EY$>jNE@0FeXzAJgNvhv8;%GLi>7^bJ8vFL&*K@CA{H^zQD5Ki?Ku65M&Em{cnr_Wz| z+p73lpJ9);a#Lw3i$eBh>oH$jV?EaN7OReR)VemRz-oFGs)u3-|0jU|^X318XW;+Q z&Hwui{Qqga(Xjwz zEM8qK3$HU5W(DKZy=7JTsJtS1b&|@5pj+VwWC{W)6{45TVGMNuq;g>?2bze{9p%n+*MH&0}3F>VwYD-2*KT8%Aq@ zSl+yoMD1&j&V1`|ap44&%EnJW&(lX7`_hEpK~e?czF-h(M_r4Q_pTp;$jni$jwcEX zhnJ#zn4e`{_K28Zq)aC-y<#E&!r{Gb6xL(m58~Hg~1b zNoC`XOXRw0aMy=;YU7K5dQ}(#Ti5_;$I60D>F4{q1U>p~Jq_vAS>C9;%#$V86RCt{ zqlBPGp{9z%CyF(nbicrj&diFkuEQir=(4ⅈ0q2g~6x#xi!-(TTsnWq)ZAadgopR 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 Date: Mon, 6 Jan 2025 22:08:59 +0100 Subject: [PATCH 08/17] Implement (a part of) drag and drop --- fmu_manipulation_toolbox/assembly.py | 2 +- fmu_manipulation_toolbox/gui.py | 112 ++++++++++----------------- 2 files changed, 40 insertions(+), 74 deletions(-) diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index 4c4ccb7..fc8896f 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -296,7 +296,7 @@ def read_json(self): raise AssemblyError(f"Cannot read json: {e}") self.root = self._json_decode_node(data) if not self.root.name: - self.root.name = str(self.filename.with_suffix(".fmu")) + self.root.name = str(self.filename.with_suffix(".fmu").name) def _json_decode_node(self, data: Dict) -> AssemblyNode: name = data.get("name", None) # 1 diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 80b2195..70a51bc 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -146,7 +146,7 @@ def __init__(self): self.setMinimumWidth(800) self.setMinimumHeight(480) - self.insertHtml('

    ') + self.insertHtml('

    ') LogWidget.XStream.stdout().messageWritten.connect(self.insertPlainText) LogWidget.XStream.stderr().messageWritten.connect(self.insertPlainText) @@ -212,8 +212,6 @@ def get(self): class AssemblyTreeModel(QStandardItemModel): - dragDropFinished = Signal() - def __init__(self, assembly: Assembly, parent=None): super().__init__(parent) @@ -221,97 +219,74 @@ def __init__(self, assembly: Assembly, parent=None): self.pendingRemoveRowsAfterDrop = False self.setHorizontalHeaderLabels(['col1']) self.add_node(assembly.root, self) + self.drop_node: Optional[AssemblyNode] = None def add_node(self, node: AssemblyNode, parent_item): item = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'container.png')), node.name) item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled) + item.setData(node) children_name = [child.name for child in node.children] for fmu_name in node.fmu_names_list: if not fmu_name in children_name: fmu_node = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon_fmu.png')), fmu_name) - fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled |Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled) + fmu_node.setData(fmu_name) + fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled) item.appendRow(fmu_node) for child in node.children: self.add_node(child, item) parent_item.appendRow(item) - def supportedDropActions(self): - return Qt.DropAction.MoveAction + def insertRows(self, row, count, parent=QModelIndex()): + self.drop_node = parent.data(role=Qt.ItemDataRole.UserRole+1) + return super().insertRows(row, count, parent=parent) - def _flags(self, index): - if not index.isValid(): - return Qt.ItemFlag.ItemIsEnabled - if index.row() % 2: - return Qt.ItemFlag.ItemIsEnabled | \ - Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled - else: - return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | \ - Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled + def removeRows(self, row, count, parent=QModelIndex()): + if not self.drop_node: + print("NO DROP NODE!?") - def insertRows(self, row, count, parent): - print("insertRows") - return super().insertRows(row, count, parent) + source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1) + print(f"{source_index} ==> {self.drop_node.name}") - def removeRows(self, row, count, parent): - print("removeRows") + self.drop_node = None return super().removeRows(row, count, parent) - def _setData(self, index, value, role): - print("setData") - return super().setData(index, value, role) - - def _mimeTypes(self): - print("mimeTypes") - return super().mimeTypes() - - def _mimeData(self, indexes): - print("mimeData") - return super().mimeData(indexes) - - def dropMimeData(self, data, action, row, column, parent): - print(f"dropMineData: {action} {row} {column} {parent}") + def dropMimeData(self, data, action, row, column, parent: QModelIndex): + if parent.column() < 0: # Avoid to drop item as a sibling of the root. + return False return super().dropMimeData(data, action, row, column, parent) -class SelectionModel(QItemSelectionModel): - def __init__(self, parent=None): - QItemSelectionModel.__init__(self, parent) - - def onModelItemsReordered(self): - new_selection = QItemSelection() - new_index = QModelIndex() - for item in self.model().lastDroppedItems: - row = self.model().rowForItem(item) - if row is None: - continue - new_index = self.model().index(row, 0, QModelIndex()) - new_selection.select(new_index, new_index) - - self.clearSelection() - flags = QItemSelectionModel.ClearAndSelect | \ - QItemSelectionModel.Rows | \ - QItemSelectionModel.Current - self.select(new_selection, flags) - self.setCurrentIndex(new_index, flags) - -class ContainerWindow(QMainWindow): + +class ContainerWindow(QWidget): def __init__(self, parent=None): - super().__init__(parent) + super().__init__(None) + self.main_window = parent assembly = Assembly("tests/containers/arch/reversed.json") self.model = AssemblyTreeModel(assembly) - self.selectionModel = SelectionModel(self.model) - self.model.dragDropFinished.connect(self.selectionModel.onModelItemsReordered) self.view = QTreeView() self.view.setModel(self.model) self.view.expandAll() - self.view.setSelectionModel(self.selectionModel) - self.view.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + + self.view.setDropIndicatorShown(True) self.view.setDragDropOverwriteMode(False) - self.setCentralWidget(self.view) + self.view.setAcceptDrops(True) + self.view.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + + self.layout = QGridLayout() + self.layout.setVerticalSpacing(4) + self.layout.setHorizontalSpacing(4) + self.layout.setContentsMargins(10, 10, 10, 10) + self.setLayout(self.layout) + self.layout.addWidget(self.view, 0, 0) + self.setWindowTitle('FMU Manipulation Toolbox - Container') self.show() + def closeEvent(self, event): + self.main_window.closing_container() + event.accept() + class ContainerWindow2(QWidget): def __init__(self, main_window, *args, **kwargs): @@ -323,13 +298,8 @@ def __init__(self, main_window, *args, **kwargs): # show the window self.show() - def closeEvent(self, event): - self.main_window.container_closed.emit() - event.accept() - class FMUManipulationToolboxlMainWindow(QWidget): - container_closed = Signal() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -354,15 +324,12 @@ def __init__(self, *args, **kwargs): self.fmu_title.setFont(font) self.layout.addWidget(self.fmu_title, 0, 1, 1, 4) - self.container_window = None container_button = QPushButton("Make a container") container_button.setProperty("class", "quit") container_button.clicked.connect(self.launch_container) - self.container_closed.connect(self.closing_container) self.layout.addWidget(container_button, 4, 1, 1, 1) - help_widget = HelpWidget() self.layout.addWidget(help_widget, 0, 5, 1, 1) @@ -442,6 +409,7 @@ def __init__(self, *args, **kwargs): def closeEvent(self, event): if self.container_window: self.container_window.close() + self.container_window = None event.accept() def launch_container(self): @@ -449,10 +417,8 @@ def launch_container(self): self.container_window = ContainerWindow(self) def closing_container(self): - print("coucouc") self.container_window = None - def set_tooltip(self, widget, usage): widget.setToolTip("\n".join(textwrap.wrap(self.help.usage(usage)))) @@ -616,7 +582,7 @@ def __init__(self, *args, **kwargs): QLabel.dropped_fmu {background-color: #b5bab9} QLabel.dropped_fmu:hover {background-color: #c6cbca} QTextBrowser {background-color: #282830; color: #b5bab9;} -QTreeView {background-color: #282830; color: #b5bab9;} +QTreeView {background-color: #282830; color: #b5bab9;} QMenu {font-size: 18px;} QMenu::item {padding: 2px 250px 2px 20px; border: 1px solid transparent;} QMenu::item::indicator {width: 32px; height: 32px; } From 6635f9e9390d0c51a1599f08f8e5d813762c56b7 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Tue, 7 Jan 2025 14:48:15 +0100 Subject: [PATCH 09/17] re-add alpha on logo --- .../resources/fmu_manipulation_toolbox.png | Bin 28141 -> 38023 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png b/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png index bf6a3c7db0cf7a86ba97a834ead6ca04f6b7f763..58c903f6a2a3470c3586d7a203089a6bb9af6ca6 100644 GIT binary patch delta 37088 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

    X{id}3 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 z zx%H=F87=!_;(09@PLGkXnTXj)BNnCNO%9NQmh+2OO}+OIt~ePjJX5HQyEjb{HJw8> zg}~gnshlA!`+k#>>wCt5AW1UM=iZ6v%_@f1r8UvcKdd0|~mOb^HT*^(^`4Y&=3cb#$15zJ;4r95Wx8MHy0| zkWcVC=5#hh2V>_og@s+KqodR=cfydeaxB(M(;`M6)~>7d%8Egg0URX!jjWVW5PnO2 zH|3lwOu#3XL7UU_S@1&_K=ASbjH6%5R!oYGjhK6ZrKo*A|C*G^Wo?&x-5;(K-hi=s zkv$pa4+bQ*UMt@@bH~p41FA~1XrMf}b+W*Luozm77rk!M_UO38-x_`u!AqKs&|4ha zDbdGi>a@Ba^!r67tFCLMKIWegwN&z44VZf7Nq{&HW?c*AAYeobjJaVZGx72hN5y?j|c>}7H)SjS+E zG%of`!OV(}D`XO$Tg^4-UEl5YZ$DFn#4m&$!Kd62w@gc^NIGl6RfYff3k*lS5n755 zbS->y(mV{cais#0ZZyHPFLPV`eHhlHqtr85mKF}eaa_d5PC;%6p|4ey*QMkVYd9_@ z9QZI;@&$qANPkIj_ulZ@&t7Bx5GWNTh2#1_tp!aT2J`2=m=t%wnVVwP{ZD@F`eV$I z;lgdTU-*w%-2$H_<>Mzsm%_drxKpY@f9~hCvDS&EZH<$hAx7`y9hA=I9JcDqEgGN$v7j)IitJpb8p zIC(Bb0RXHqjqqEK`$6gRaXsTH$FC!9v~n=}z}6 z2D_q_u#{ZQflG{B-kPWlw1e26ia9=Y?n7&&VxQri;6xQyRMF%nU zkrttk_3${s&zPkTKD?!pt{!GEGb;kDInbFq6c6D4vJzRbIwLCe4{=5bR| zG>()G+(x8};O)cIW{I)MgQYJe8@!as#&mtpq(k7oknG}Iez5|OA=l0FaWAac+2sn~ zXvy_$>scvyB7UDjHg>IZ-PgCL9Ic_54AQ6%4Un+Wi%b>WblyrN$mx z3jc~qt{FjBwRERBS(_~LMC_y__@S1jbsaL{17B{nTI{pYWUK_!0keZn{NTqcP~Ln4c_{$VRM!52fo>!TY@9=0pVmaJrwXtk`q%rc&}6C@ z71LVoou*@xNJ?244sdhwJb7#f&ue|$;Xk)9JY;w(RLDM<(6G7N@suoiC>AuQxZq6g z^D{-$23OwbzYaJoA=t;Q>J>U-tEtX=(qtdEbl@`+;4wB@JT5YIafIGX>GxY*H~Rcm zW)$dqVsSt@7Co1D$Ld?#8C=@yj!YEtOm=&Ck4e#qP6 z7%*$)qew=ayotgNiICKcS*0cG|J%<0li2)!W&f+%D2!vEbD|%2HCI8aK7&rfNZ(Yi IPRBLwKQzP9%>V!Z delta 27128 zcmcG#byQU0*FP#H2m%5EN{R?bcS@)Th&Ui1-5o=B3>-p1T0pv`8DPkvySry#h(Wr$ z^YXpF_pbZCcilhk?~l9of9I@q&R);6&)(1ZL~tSI?kq;xI5x1`gqz7JueLvbK9|}t z*XQ}zJV+cb;8jxeo6mn%$e37tLw(nN7%paIHs>3AJpLX)n%;{0%g^su4nyeY0UbXdV(Vl)oeZBRV45c2VpqJJA)&B@XYr4cF zfGU6R?fxM4IXNahFxn*ql1khiQH3B^37r9 z=adR(bNYicbIxB;2@(Ad+n!j8Yi<$0N#`50_irH7c+ADq!fpmj?gy?pF@?g}f-;9> znX~?6lGll|LtnD-bzv0eS&4)JrCBrEdhQgnnHOLQ*YrJK?Lz6?>G>n}O#U z;AKJlb;V!CtD*96%iZb|c;M3s=#wgK8_Mm9jI&m|ZWY?KXmx3S8u${&t^*0K6 zRDx!U-)pWTMyM|)%;?&^g4*31^Ew-PQ(sG743p8T(`Z*z5X%~s2c*X7H1jd%&9#=AF8C<$KjqL!NPk zn#U43#_(vpgofoqMwm@}X7#Sagl`8pj~Ui}{ksg!&(OBftjxJ+0&4GmjafC5UzX>m zX{VMc3f(WCc4Zab7N;1LaEpP}4hQAZzd_EnXG4|lknOqz$6#gQ^E9furG;7mGE3ey zo<=Y$?4Ew{ZJu4jo!uiG!8PNmP`N{+hoDUV@MI!1 z810_c*R&Kg-vjYGtqRWgmg=~4w9M9ebr)>QHY{o;a~M=(U_e8&djzn;f;-|wuUA&P zj_CoFa+8rZ6UkQN6YKM!>qKb6UVY)QBp>~5x%Wg@SKG2+>$u;iSs(B7?!X8P1ir*R zYK>@D{P17$y9BIa$Lq}xL)7S&tFK+$6PJ#>)i6BbVsSHF9U^MUmSKFH*RgK`dXxj9 z@)z81hVB?_-4?9a34nm&OGS(Hsz#4#pEZMF$ZYf_JuRJK&WW%A1TJf>K|_nr{W~7_ zgt4xdo{95!O=TkE6xOvyx|rZp9);mySKnC7MU34z34C?7R9t(IrYPTsb~2!gon-u& zK0jqoJbzvC?2`|1c|q+7HJ5XGm)TiQ9WGaMk9E`8tZr)KA+S+r!TBk6l_cutfm6I= zj<;blvTYKxm~r09^)?>uqeUxF)wr>^5Q0^iHHiC+X#d?Gg_gRK+O;)_E)%-i55#{j zsjc;!U6c<`_9e2W;oI*I+Z5LA7Z&`y`Tx`GGuQlYrrd`Z_C%XAJ43`+VhxMJaZ+Na&DzT?u77TS6H14l0 zwTcgZja=N-%c#w+T^wwS!jQE~&3<~Qhp+D}b|m3YE$fIrX*0PFL*%I&UbVhG-;}wc zaal9GcH$1E;N&uwYc`;-X*o|xHjFImxW7rv#^}Mm48YZ_rwQYvyqhNZ*GTRK5^?g& zT_pzM!Pww`IcFcoMN>wk;7R45ej$Tl?b)9kj$-?)EG>_CAvR0Y36vB zd_jkldKteN*80(Z;%!KrJ|!&`q5E@RIRbzP_C)@ecjneJ>bUFavE}gCICVw(|24L= zy$svr%4F4S7!J&Z|OWn1aZQ+e6Q=z zkQn3@Su>|l%GrWxTlZad$-}rhd!;g`%W%%$^@ z@QCg+TDl)+3KI~$H+0-iyAB20+v*?K7cj2*wNimt?6uX44VrSMS-kDzxLcej(v8vn zCfi789tH)+OQ-fLrY=-mSXf|kQH^RgRM>7tXU^lgS=7VfPF_jENXs!EWwp!J#1^}t zGerrjw{mwpAKn~UT}iG7)?c#QV$9xdVVw-I+t1k|+irAFuZ@})zHcrJY3mi&OH=~E z6mxU-I+eUWD~lC`UA~+J5QnZOoL@jh=ACvS6jgM88dRK+l-C+x_Kr3OXbqN=msc~) z-q}z3R@GQV@1z;Ke}>sr8U773phDnMO# zYWdb5X4IBbT%N1YP+}k$N_3~-Zsgv_goI_2AL8xr6-|yS#JdJ}Aag5V%Fo#+n^-CE zC`eDsyg3GffDSM|Om1m#WBZtqHL{YxoyNLwOz%F8VM!Xe`gmwd-&FE~!sfO+Y0EqQX;5LyFSK`c?==yr@#>pR+&d)|&OF~M3INltT>L~}hlZ;|9J(71&s zPK>tN4LKM8SkiSNEeNOAwM8tL3h@mWJyG-Ox>rMYGN!1jN^@=u0U>W9f3=lJM6KHi;lZA_2|9adx6t>YbOpW$Y4N+{p z=NO7!+1IxqmaO_nk=;31m>T8zCzp@lw^sdeka3(_>wz%-{0BAy*8LfWed7cQp0sT& zA4uJ~yc6+$<9L#fJ0;Y<P=>98q8h7xlP;L9O^}? z07$C(BxsX>s{hc$0Htl?*><-if3>tvjCSovrEAAy{N-J`=IU4p)X?$7=IkQ^_p7mXwwigO`q0oG-Np~Zxx(;=Ys@3e2rAv9%!n>xAGAEY zq~HFb1iOM;95nK^&L!+!9k13_OGMUF>;GPq5+EqR0>)&UR>bHW!+#tRqeGSpsIw*7 zdpB>#d0X$$d3@~hbC;5*O79Pv&UFmLwS|C%}nEsR! z6?0*^oS)%SAE8MyecvHx&j~cU?%Gwi`Ch+H$h`2i_70Fk9bI~X?q==l;1@?`^EVn? zIyPS4<(gk8-`!@2XfT?xb1N5d&AWx;XJnKN)`wJ=~~sPS9K zc&~WCZQc^V-Mjc$zFV~)JE%H4O8#perdfWPg2IR0qlf|oYkcdcYu0EYXs*=37&Voc zEv~}8Ij(3u3i5e?@$NV-GVBppeU|&;=p0FS5$&mlt%d!?ws8A&G2N4(3{|D&A>u#k z{T#1J*Sk;Rm?R}kcw1I7p)+2@!t(Si3b-s?62f6yW)6T#-OqSWvy1sA-EVr^?Lby5 zR6dMHfn8R+sK~FDGelc1ve1`siC;l|W*4yHeM72X zkRIIkGr{+swM$9zxN6B&%FV7^p=}x%G};%Fr7PN8Rg%cPD6~k^hp2s6f!?1bFQIgj zv3%nJ5fCg_zXX>}!LY1nISkl8ik6)!I$C2i;4f6}l#Lj@J>}Lj)Y&rJ-nSG8N9qn) zh2i{G0=zc5myq{8T5I%}zqeAG@9&0(mkL{sP9>dWcM|Wu`a+x?jH7o>HaTn{w$cPKUxR9v==<@cYr{o18vgZsd45_ur9^ zU^KwpNGY4-+3Ff{r}wp?Plr;fMfT{)I_2FkP(yX?n9$gvRr3j!BBXon>r*m~Ag-@A zVe3WdNET|C3Qy}hXEzfq3nH(!7g*|IBf1sYYG#witP|{8+A&q`lSHTpXZLIx*D^v& zETksV6SBXRjQ5Uj%}U9MODQj@ZFfV_R^H2dGn1qnmOsF=n@Zz!{`TOf6rMPBd)>qU zrF+`-jsIBLRE-Z@vjTS6!=)oV@6#QNYst))^RwVG-<;rR?CC<~-Cy<7%j7b_&B9R% zL)y`XGpqsOni#qWa$DlI`|JIhZMB80r8?~ypULQ7Lf4m5ilI+VY&}2@0l7#km%!){ zWYeyfcbe+08v0YE&Nlcq8uJw*&Da+}jBHMgzTI@?mO?h$+-yoUS6tk>&y8Mwivio5 z{1{_L5SetolKqlwT76mfJ0wYJDsWhn4RvX9+3z%ih5dPm#=HHe)N75R^V% z*&?5M>jZUi?t?X5l9Ay^0NCu?uzSCVIl|bMEBFXGcOc_@p zG=twd8J}!<$TzBAtZ3}R2}9|#G`__$(-B40qQz1mcb6pVcxqgn`<==bjP+A+zdrMX4z7jF?C1;-;5iHR! zuf0%g9kqzfy?2WDR zwKbpPWW8h)mtX)#;{^8eYl65(;E;d)9zud*|WY!V_R`PCy%UxuI6SM$nj zh;_C|xq|*WkX_bSZ{+O>>~3lbp15Br2#bjNK=B47R>iP7E!shM_Vu5oe6T>h5zO-> zYkWa)-3se^4{lIeP5g3d;|p^FNoDkE`a9h{q7~m#g&pAgb`gQG^T2e=QjT%d<>z{$ zBtuEY7Fg3JTI^ISuSRlkck4@Km_`w3Sg7u6jzwnyJ40+MoRe3{8m5l}XObPK*q2vT z9EY~S>yX}6klyr&=5kN!7OPgu8;jk)#&D5M>U;0k^XJ74@4-co`%hI6y>@SH->ylr zv}h*kGr+D^qv=bwhQ`xY%+XVAUI%8Wk$=Mib)$-3m>bAE#0_HSrB16G-Z{>)0pBo4 zW5-^Sq`W!gVQktA6pjKZI<)K3=`SDPEFfWa_pguSGF(ENmKZdtgqtoqY7#TJ#(K$) zbJk)!UL5g0BI{v!Vz_W{wk^m4P8(8P3dE$_kOQoZ>8Lkp>03&itI9z4BR(b#LzO0f z%(F;g(Etd>;+Z=DZhKdAI`WT7hIq~Wb_&;yOTRFh$)ibyG0!&S)d>gAVEE^9#d(pC z=wf29J{^6cxQa6}uc>riq&_@A;Z>)25xjFQm6pW^##{#5k=7~_tsF#Z|AkE_lQPma z0%Ibze=m1Cwq_->Mc?fr`?x^E=5|vTPA!Qm!?(d2v3ejL%#_`H{lAy;zGwlO(!lX#y4jW1-pp=*t{^SpOJAhl<> zZlkhJ({H@+sFh9#?|6j*jiPlo z>|Yk(kMCmdS_Dj0ASrYi3e-jXAACQI|ES?*u7)*kgG<={ z8g>%bGbQ$}?{!?)0Vk@@?E6<<;79#$rx4B=;G63J_FBurp!pQ~?=}+Ko7Vno7(a5g zW!n+?G{3j}W^%FR5~?OCt^y9>#`A>t<5$+d_iArXSPE__*5sxg$qj+sDY%Gj#~+)N z$^xMz$B<@i%WI}ei}{}=5fBay9((I(uF>fwa~hqDgL!HKX5M4=Z zlXka4RQK>#YAQu^&AGwF8(Ot{!s4d5XzpUYz7|}?r)_tA3J~3uZR11S(@%aawT9;1 z&5~6bzzE%0N39j~ZnBKDa_6^k(Ly*a53ZyDgMdPBXsR#m&kyz(RcKhriNXa3K|Ow#Vx&#KdE0=4If+hNLMb=CbYc^#K1JHm@@fy1ON7=yUp5abtC z%OBgp?YpVLyl~kdHt2PJ*@al(lxFJCw6R`=^Yr+o2O@p#%D@Te^GN!K>=`FeQ!Xgxy;G zK-&3pas3Y!!!sfwBts9twG&N@=rWxFM*Q3q`HOO*&w|y>bd#^GDixyUaMh-Qtkz9{ zc2{jcBK1jMHZuhT;)l?_>YjQRW^eiN=-=mJr`t>dxrVowjR2PwOg}Itp3}BDB)tDx z2dUVjQA{Fh904=o>@flAaN@+P80KpCe%mL>R~|VZk#sd2_dIB; zjiniRe`);Cvl3CLS{hTej5IDpJ*z63fzUWS2JcRDtcjJEGOR{U?@80ktYhe3f{E>m z7Xc(g$_X1Uh8+dMJ4g-x{gJ<0Yn1d`adL$3?ls%2yRIH^8ZcIYVs?@T1e0gw+Qa}S zd%yC=b`fW<^!tn0!3}vinCzh@HPLaQrrg#(aM~VC&#?@7f_Nj`e3k-c*UydX%8xdV za}F3ZVJ(05_BeClFxh*CLYBa4R>mrFUN`WtXt-_rBj;b#pEVTsvVSM|j!}?Tv~HI? zYRI1IkRj6N`klT8=Zv>S20{EzS~{RBJAxtwOAT2VoBo15mIFOttK*^dn(S>F6HCb> zMXnwCgzAoc^c$m&&*^!QrC^-%qQn0YCs0#liqe6d`Y37-=*Fwm{{AWFOGmbah_1Odx|$M*Wpie{{ct z+=o9|4}Z#|w5G;wO-}?1oda48a=#k|Gq#wVyPW)r!bcEl-ETWgYbJO`O=wuoX2pid zNf|Z?dF%}tnQ*-XW?K(JcZ5m?WK)h-X`M4YKs`>+30@k?lzE*;9!gCY%+jnTGIn(j zfvj2}4#h09wRK&+(#eeyid*flfx-l+Q=)*RB9+{p2t=+;qRQi|Uc=uuG#q2D7G?4IPv3}F{?DQ~Ako9nu$`nx7)Vh z^c+81#ncSyZM+?;*GhG>o3{2Q#p6v_t9J|};2{tn`B04n6MoG{n6iw(UR^#VcVnl4 z{XrJSEMGZbd?~2idCUwt+rPmmYc22buabA((Gex2?DGAM9oqvoZvG11+Ia-}t|#@) z+DR;EKZ#O6-`c)Kn%1d1b}V52=+unB?HvEO8optZ!s|16Mm2p(!}&tn5h+}ywBoJ} z$_|itsxg1}(>OuMRe!@p_pv6N=$CA{I+%ah>#r7oTsVmqo9_QwW^;{S9-WCbEkw-m zxjv{5D}PfwJaWo4KicC_=iQHyG3I`bKhu9+7#aWT83CMUJ2TL@2Ks%Cmq@OvU4v<% zwTS&XtG}ys0q8M@hb}Sq&?P*BUi1|m(Of5~F_o??tJ&ZPsGqr42Qw;oLU!5CbQ%$| zbUlD^S!-``o}xA^B0oQ_UzvBe(4&!=nWrWft|zE{NL)2yv;wWMPEOn8*4Q@h*454; zxE~$7DQ%l%YOq#aX*eLBQa6yA+{|_}2rk~L1J{KbjmTY;k(?*%+%@%A2#ypTUnA0? zo|-H*OM`MUoIf&%N#vMEnrOYrxC%i#1OUNVsc6j$_ls&<&6x8M+l<23Q8*LK@(Sm3 zD0!iwrUYZ4eO=tV5|M9BaeY&jN2~)M6udO`HHpp zzqn)+9Qv1pAl^E?s&E-U3EYy#)+iPjS(_|o6mp~5mD``TnZ@%U2N|24TIFh51Ft>K zFSyDaCE5tmx044dYt5DygqRu*ww;K$z-V&|$AO{)vcBEl6W#VS7lS+cIP|;6(_4-8 z`mm{%`2DjnJy%59Dm)IskW9PAc*~~izARTodTV)1|B_S3y(75O!wBtAB~J0~*6Hi_ zBbhdTvu44bg2$jUuQIa&O=%b|prcMDOD}dCGrx?hHL%~@IFahu%(ZEn)Bn&8aNg5H zIbF6wo~%cWEydSZubu+;*2i#i*JL=K&aC*_5~0xg+I{2wnow2N!Hd3^p(1iWtZ+EL zE@a5oBWLc^sE)_CLaGx!A5xX;OIdqzg=sWzgxn3p3{|lBNWe#r2b$A?_@mnU%L$!| zRg5dkAE2og!LmQ{13spc-J+ofiQg84k~Y?Di@Qu@LEx}6rt4@&=V?*=J_K_>ued#J&kVO8pQ@+AJvnRF-*zWeb z>QrM}&nO9U-s6K`i~#V=6D9JUx8rl%pYr7=M3PdgoWw~^hy^Eq!@ z-iSJWNDcN_26FZqUmv_6jmkQwS%?YG7FdlJNGjw5h4@)b zMoVJ84?yH~ngf%1fy80esj?cGRerkrlV z4gUo;QFAR#CaPQQ?F`=SmNN99kWs$y3pic`x~Tjo$m)u;GYI&SmstjPsJ|s`Oedpe_QV4)G(hY zw-@&4cTuy)dm!ScW2zE8?b##HaAOHY*i%nKU`eWmq8vV=`$N%W=7)uZb>(ih2&DuO z?k=%qQdnJ1z63H9~eVBsjmGs)o{?H3*CZ z`k}jYl57$lyfp_8+>seg1%_^ET)vdCbGiM!&EbO5&@FDCpI`RVG7a`JdP}X0kn6bz zAQD-dV3^n^WTBT$V?)AU_OkrfB?$`7_1sBV_g%nT`5?Fv(P3= zF*Bukc2W6E_O-S_;gAxN-3je-`Yw#D)C*j``R?8_TW9W5{8SCZ@|$IpP!A1o=Jl*X zo=%K@^zKJPHBPWZ?*uq6aZWNK_vI)%95>13BX9N_siU0O(?Y=eS!k+Nu8}W|I=xpJ zVj?W(Jjb~w^SaOC3RdS1Y4lV?Yn)EeZC+QcbidgYrSdeon@XtqaP}so%RoLB&RNxR zaKkTaH(PrSOKMLx%=kXqj|m5Cuzu1rgIZ1k_(KKp1M2jr`7C&7KeT+sjROaNErJL9 zrhP#F;<)LLQyo@yc8gA*p z&;H6`Hg_n9l8tx9C)*bStGgt_InF*HfgQx#-@26_zT1CWFQm4{-V8`k?;{Jgd~Lm& zEaoMsw;z=@FB8OEE5>$gi^oDg_>;T)mQ1@$&7N?8fi8u`*)s-&vF&W-)!9gOzZvfs z7W5`~_yMEDr(m#EV2A6OUsX>j5i}oQAgTm1Na=%qG)TYlohsn3{?y^D*5O8xu^zVP z7v$-ldX-pLg!j62vV{c=zh1 zcT~@>r5yDgec2{69f6z;_r+rr{nrH49oASkBAv zTC?hsN$$LNr$6Gh3_c~MU}e&C==NaL2YDU(wAwdrQhDEAg>j3h-Y%@y3;u(*y}0#S zk`|i5rQwip`kHGbj3hESw-T^A5Av=tE;H>&o|QC_5)wAJLw2pP->FN9q4T@`!Yp%* zSfXt$#0#B)T<5*>SE4z*yV1% z&^P5SYW&gap+CQ;Q83MOeW4@~L6meWWT~i2-(p+<1{d_S)rC z)#;AKrg0LwPVTVi2lB^Z(SaVS-c)$>+E#;t#TC3_nX~chAyudDw+0Q$c|1j8k7a~j$W_`)_{%ILQ`CHDbb<7fCm$;4y|0+|E~jeL@#?KjoLwwW6tf6VwZO$+!9 zY3UIv*uPuuqZ)_Q%1-1V-keP>rzIaCg;ut7>_)V_O&pS%Ay->*?`%dy5CTha|E{GZ z7V`2s?Cy$vTx-r!ug6%@RBo~Yf{)o^x3<*}tapMl98?a|(RDRV&0byfy2`rwb+X8X zEf}5_#p2yMjEhU$d37|{Chc6HALyW)n;P;!|D77ta^C4fR~BC6qwC!r`vQflO5b%$ z-)%;TWO?j^_f^HU2ec0kfWB>R_C2}^hgDojZ;M0UrY$pYa!u3L-=#w0*-0_u?gc;C zU36t=%XJ)q&FW3UecLKxq2p%U?08nnx1q$}wdGiy^8VGOjrT;5l3|xRAa4(x%5)J_ zZC&p-@74#9h^@sOs?mFcBsUqTZQsO2G;fD+vr4&argc3*Rg&s#!XPDmRNs03H7oKL zhwtm>Mi-k=ao!q8x%wVnX{64ckIALo8Bwv`1fy#;4o&ch>?in`xqWU|&rS_#?LQ1; z6G6FhR8XEvdzI<>JE&>kwv|4Q)W3D!LMnSBxpSe1v2VU<)am+9VlfYN(c*zF+tRft zkKi}xmwxv}tk&4s5m`6FjkmEDlla?r-E)K;b;fK;_tF`LB4t#=Jwa8l(oW`_r+Jma zb04&Kl~D|+t#y0@K8?p8q?`>kOrz?L^=;L@3;r;30SNa0jq#&t=0*LCFq z1cwgg!Tw0bM!+hAdWXqc@~3O|ZWIag=gs#=rH_nltryeguu z{L;-fZ;&n?YKpW^k}Gp2%DKh@r$uE7*i0A@@&$Nh*`+y*3{C0rt5R+ocGE- z4EkM-rj4D7t8sf9cHbM~Sp(jbKKcD2`^}z{|g3L?4yd58CT9(zby@Q)u-I48K@9tP=_?XJH45y zzGN_w*iYPcS@-0g1oy%;pM6Ku)GMe7b;<&3bj%Yqx5>%#`v!z?aRS>bg;{Xd8%P2s zkEEAn3XRe%UyoRP&O|IF$cK?x*&jBn^$-E=QdgZGD5AxUCRc&um#{ugN5hvu@ zK3(j!!-?4}j4R%fR9Ds5vFZV3v?^jV+Oe8k(Ol>`t~LUX_m@H8klbponjmc!z*C~9 z^Sv0(yPw=RUw4Wf?vwvWGbuq6vq!chpdV*Mf zgGnVD^djVHBVn(CB-?RgWU3=&6?<>48BMofTQw-N6gNXA_{A~9S%WfvJFDS4qi~L% zH!*6#)!^nVaw$WqCif!p>}@fN1MqTHWVzF?7(A zS|i7}*7$ghWq!B*BEsl-6Jo}YULrU+y|#flRK7&;Xw?B@0M5IXqQ$VWDY#32o|%yS)^pD4){P0licM+!c1D?u6=^?iu=J)f znR9vi(I}|PU9U`*(S+UW7Erym(D!6?CaWRepTOhJF3Qe{04F>j@mevDXx(Fd&D1988e*6+C1M^Y-vL-D4YmukUQ4DU`*@3p1Z4ZW2NXi7-+<9Kq7h!so}& z`y`1gwK#vaN;sgCouAWe_8iA-Hg+!&*sZx=>Q_(14J7;<(1};G1iXDq=8mTRTJ6sS z4j|5DwKvI`kUuWhNID}o@xMf8I30@{w5ViUz=r9e>5b6WIMJM zPhNZwDjPQ6{*j{u&R$x_<~&V_#iiIJGrCrh-H#yf*(yrcD)ScYXq)?{4PaD#Hv409 zx|?BNC~?*L)zpG_LS6$yYMjH4plr+Qs3R&fj09T8wWhsJYqo~ZsmI5^e;oKx|Mu(R zFd8zVR5Xxg?wO1F+no_(c5`ufn3J61{yAkv4uiB!@rn5xmEA_On|4IDtmrYj|<2 zV2MDr#*eq1->5TMk51(jCr%%w9lrup4Ha0lU7zA;)S7Z-gH#uqr}4IGjX*WyRRZ#zndh$SIk!da8NO^}brOe&~frU{b;LmXU9 zlRF{{7LP{9#?}|1z!^8cCEv)~j)V z|2&cS>z@B+$rGMBq9nfmy8pjiCyR+k?}^GH3)cp_|8K7e@Zbq}Lib>ph#tk)3f}P# z#a-gJem@1lVX~z=Nb!2fm|G5Es9#(>d-3r_iT_ z>LvjH`9dJH8S30OPAuXwTrq6Pv6?7iX6yRkr^} zo!gUydxVE@L@dtCF-~A%YlYeT=$9*hyaX%C3pb$aZkLmahw@1J-9keNV?QV7ph#W$y?MX##B;W^T=n^ zQL2KIZ&>5UX9A&2DBr;MVW0e5N6+NGe4rq-%+@R#1X)V<2U~e(I&l{Qrh5I43{mYp zD@Zqz!J717g}ubRm+xWQ5(d6S15aeu6!Z`1-R#B{#NrnD_`}COpQ=7Bi&izx3f!WNnS9iRq|4^ltV#LxA2^6ekey zulsU&eocw}6=Le|{dfBde<68EXUodKhRg2A&su#rC;@5?~#L>dm2&S-d_X_lcE&W>; zw{`=yxj92=ts7bMN@ElW@tko9W2G`G)=Qh5Me1#S!wZ{m_x?4py^R0;g(YH~)HONA zBj9TcOT1nTE)&tmZh%Y@?bJ~GVWR%7;{c4PzJLz9ep8H40+;_)3M+m^t7QJup67)K zu@lYvkOh^gp>!YKsgF)40BWR5^s(l+(2RMDOYJNe*VY?PGc%5@TwTjO&O9o7sqzCc z;m;E~A%@n~sMj#LS#EO(>d@?5AtxG(v{9u_{b_Lp;npK|4It!C&nsEU;t#(TRDHH= ze!pt|VrC;N{-I?LUt3i8L>^nmned52^m(q_nY^`W6 zb8QmU2zQ_d_11u^+F54f_u2QOkBTbTj>%4yctTGwRnvd}|ZDs-4d#-bh+k zKuaw~hST9j+iy<}z-uHi#qQfwJHA|x&qUTmu{EuKPo@KoMn{hpDbE>(%}GQy+XYTO z8M0u7XM_1mFXw0tTmgC~QZRnP<&S7>%eN&n6Ft?9-c{oPbVtb>;GG*TY7#-=`A$(B zsZc#!m6^710Gpg)a;#+bkyy^T!je3DbTIalKYC4>1d>5^BK_6O+4$r5>V98n*;;L>*ddrc&*#}qxtM=tx2MtM_G|rG{7Xmp zKD|ZzbwTL+>Cqn@f|O-!Vk<@sT5*^|Ms6P09jrKN#*>>m-E>we~HreUSs+nlayqyd3BR+)b(39=-*Htl9!I_r}MIU+cb- z@>(mXj4E}OvgT~+h>V{mo^zk|e>Fv_u+iAbM4bG>e4uu=vX7GwBl|=dppC+>d;FAR zPh2vspH3jIr#?$~>zcJ)4k013P_+Uhz)s7tC44!DgyWE(H2Pc}{5+ zZ@5XyQ-P3thD^7=X-oxTiDG1Hfvlyh2blA$x0Xj9?*n5zrj&9mm8sO!s>bSQYwKB0 zC;rqhNejjV5%BFe+R#GzWI{M9p+6Fmass@2)&7>M7>rGb7ZwT4lT{u~!sHGF%)Zc= z0y2azCnosGY0PBIk*-g=6dV42TA|}%|6(4gS)ImKI#Sl*5r5;AG&(Dg-84}2uUYWr zx9>NPJxfIJHlN6k>#EP#bsN?~>>I@RfBDzxmxe_$C2J-3t9dKu%E=Wb@35)3-g<4E z)6>LofLn>EYbEffWRw8l9~Xz}k}`jFW32i)&Q-)jb11 zm6fA#7D=H!J+q?-ng21$mlg;Y;EAqD->L`zixk9_6_3(#uPzraeUn)GP+DHR@r)|o zw|M$_g!a}GCoJ0w+h1&^&?(Ob+t8F+Wp(iqQNDQDz#}X_3BEEPD6mcf-f(IItL| zYUN-2r;$-C11Z!lehLEXJCFPdo%{fG*QHny{CUR)TXHxFUX5L_nz9vM;er|7w1T|i zrpa^S#Fx=7?X3K|vR*&EKWF3~<`bEHptxYpTf^P(e6JupsgV4q0u=tmZ9vwBR+=X; z^x1vvE+3EeEk&j z?4RQabsnD-ZqN((TqP1tX3A}l+cI0K5I?0hdY_SG8I?R<#6Me}C|-+z{Ycmf4`@6L zWbcC+A=y_6$BMI1s!JHHCjljfvT}i~RoplXt=7!}rlD`>G7DN9mxPS#*pm9(wJVie z!~XD6$SR~Mzatft%`lXYH(?S39c+F%ZQk5{nr6kiP?dj#tr6z3kD#|0aL(Oq=9DLG zGaxnpIz~y?IS{07(?O21qPUqQlMfJ6IVwoM3JanN73CPje1OEU*489^0O?(49Vxrck zokW6ZTRvhNsbyw`C>YSc&-y(z(f&q70R4*xVk#~zD>nONWpwm1k-jxwGVAR6MdlOb zril{>xzFTfJy!2_U2i3ztfi{MAwXlQdvl35un4_*@laaqZ(dDuzjBs-sk^x(uv@r} zDRcM-8S*MzWz*7Zp8PSVLgtCeBu3VU+i*EA$`^E`;xu8;JDh1Hz;eIhYBkdm4u2sC zp1(U*;F@1k3Es#SoMq!&juQ*jy!TYIo|N4V2X(a)=nWD1O_JgP9~31I;e0m*AwM3i z?pozElIK2qd8>rW_a$6Et2lrSHW{sZ^D{!x%;pdm@}`Q;w2u8#;9Hw#L>PV@piEcw zcX*#41T`u%CxH@AFQPs%d2FowZ8D3Y)PzxE(0nNb#$+HSdRl#YBT!Hmp z_?(DNzy?cg5Tjm2BcXyO-5AF+Hxjif`j)`Kb#g>JIn5UozGQdTaOAHad|Fw=D(cZ$ z-KMqmf4;KRTh>5$WVjzAoT0A^K0`2V&Ya4`pcD*uC(YP%OaN9;;dy5!F`tRDKGe+K z6@Ku!>gr;`L$&m5Bqj>lTiz1!H1fOA*%M)IRd62y80A}B(5pP>Dn_B?$j6la zcg~bTd;QMDta7CkoaK;k!B3C~`xMgLLG_bYnID?5PTTg;X}vaiJK zB&gm{M-oOR{U;-NID8-A)O6yFsEx*KM#e*hy9fSLfFL1}!{J2}3FPs+Z-x2Krn_H? z8jdBT(&2A?nihL zjIS0AM6WW{T{*D~}`zf{Jbka)P`?e;FF^g2GW<08Wg=xm(iV;zq&o|q8SR3d`DNy6# z|Iyf021NmdTY8Bl7o@vGx;vyBmXuhOQb1}!dSNN)1w;g4=~SeZrKBVk=}l~Bqt1hp4`d+||d;m8>2$%uiqivfF zY=B7|WQ{L4u4sYae`u|jvKf2f{JxyS`1q5=pm6j$z+?^IikCr;NZXvdzi1AX`Wbhb zs|-+t4$C}^0;+Aqg>(#A0%T4`LRC;snvy3_X(gcf>=t3+RG_Y#RI#q7Lbk}y7bpx8 zm?4?QJ-@(ja8~|9qiA2E!|LGq>#%iSm`pM_@V*Voy7_LU6_4TqkSDo?H;z+>lSR{V zBQ@AF$#J{2)FrwZzc!<|`z3S+8Dl~+;f-J!S9w_YnL5uGB^!3$wI_R%Z`c?m_6zP5VDi1GWiLur8c5}^ZI5DALIgX>j&7Ds~+XFhsG`UaqsOkuqhZnfaDOtM&(&5 zWnYpzd{j_BlK7rmna6DS@Jm*wRPjUmKhBE`D=F$eM(*4fnr}WNyx|aLnim@s@`YwP zoFb^-bS_`FL*5p-osP zGwez|t^y^pjXQH>?zxbzAE1ax7`9Xb7Ds1yExC1a^>lJM?CzysT>@?bS+rKe}(uJ$3u%PFX91Qc0$rMnwb7F9V2VX}BX%Y7l%$ z5@_fvX4BsAq>Di30IjFwqN6;U@@F(n$8{W)Vjc!tYO{6^9)mS9nqPg1p)%N9H0iIaNzvQ3CRv)9TaULZ7dsxe5H1IA z>*oBs75-ksDEdw#J}^K@DZ}$|^g@F176_45Y&XrwH6%f_RX#8bBY1mkme+U8{rNWY z?NuoIs%q?RQq{W`4j=jg-5a0A0J1DssiYg5m)WmfynZTGD1AGP41;I8_8H%eT-hf2 zL7OEenQPWA4@ahRQbYxLLF6=_An!2i-J9)wYO1)8BNwq)gITdT5CPgKAjLoTZt_Q} zMoUE3!;mQ9&~(aE@7rvMjsxl~8BL%L6@N7gv47NO1lAoXLbs=Lo#4 zAdjinR}DNJAk8sa!Y`>pS=Od^umuUsDxkFZ&NumXu2e$C(7qo>AGWSvrr*7pCI(hX z`JhBh(9Ro(NBCTxH*8w%YCvIMnkJ_kW;tE@eznyyG}i++lx;T~G#824(`0Br z6njUp3_G9vdF05j15(A|D~lperO^DeMkT*rd-*dM+h{MCZbyeqhhrZiL}R-9U9MJw z2+y_&eoDpd`?59VXBv0a(&2ekckKU~| zzv>H;KF>-QfXsX(346tM__wEiW`mperPZh*WHrYD%$t%*5*GJ;=F;yG;7#fv(aEh` z1g0NWICeyaCzR(Kow+T*)p20RSeEDjJJh{w#_$#g5|0dyyG-;9d z^Y{}RIikxNw+K|O79U?l%^<(Gt zVVLwJV1n%3^3e?^#lvp~ZZy80je>Wm!kScXoRa!8$?hjlevrS{u{qNM5WhBHulS?^ zqcj(OOjj8PP}Ab7X5>Kk4!e;(L2i__S-e%IX7{Swp{*{@jmgw{oS)B z##&hfB*OJr{iJ!@MW}9#>>~-TPH6#7i5QX5TR!53+N_(Leit?jZ`wD%AvuqUDhZ~$ zO_m1YkWmQVqE(LgTY9?mnD}LiS=^ak*av?@kM@XgzW{UYX_iD0MIZ?=y-=DCH<+1{ zF{_viWMb7?5D3=*s2vM1Pr7Q*wwM@Kov%{(U+K$Nk~K8|x+r*}b~adz1}nm_=iC2q zb5rjXA~9oh3EhyVPSSlrRVIaEi#*5AzJSL>oB`bU|dgS+l_tGP8RnXE8Y;br1$-zEq)i;{f<#LMA$f{q$TFtMiinVE^nHwCZrtM&tHrRYYiApBRroN?@YH~3c|6k)hTuX- zc-n?jpJRx+G?P&c+t1}@6?5RB69b#^LL}2T9taB1g)O+fROX4<3+OT@z;RE_ z+*7p0x)1xq)_MlptB<*DPYksO1O&sHIj_pe62^fa=g$>C;gn7~^L&Z5{b#MimRz%j zw`DGn`!r^*doVj~y2tWe5$q03%aG$neG1E71qcV~(Y;C2f-~}kf^jC%@eIe>4Ou~e zrW+Gn0DON1S|Xp(iG}5vjYPqcbV^wAPt%wqJ~WEOU;oM8AvWmgnCKP6{GH7+G6{SD zQ^fO@U{1$Y3{E30@%n!srVUFNslD5W{w^$YpwxRFFgfDdVKhH>=kWuMo<8xQqKsGA(NSed3`lp9pI1j_f+PAwH@$8R{#8rKR{shZ-5y6bFWu4Iw-oUTbS%8*~#I=i-3PWOeXo z#5(jX6wj0{6gr@#8IL$;n8}|XXNN?_KwKZ3UiOQ zF|clprfbUx<#4-}pXg8~Lvc zv=QdW$2fB)?8w^Te&-P*;qbKs$7PbzQR9|QVfWeG+MG-vV#6k7)+%>%i)*l1rXP>c zk(xo(&k4XYkCLm-%gQS=(DKHNEh&5hYj6ff944RS)M7%DiS8M)$T*3sf^ps?`9P~098aG1|X@pfch)3Q%j zKRw`Y1O9GnLTT&>RViUKSOUgXZV7R*w1j8uWm0h@^K@uYT;v{b&qT+P9wC09fSShm z^L=$xbjsRhvw)GmL)7fC*;wHERBHBWaPTMVv62>zZZgMcCH8=i`~?o5P6;T4X%5tX zDSBa^>{hcJfD8aJ*^FwgT*A~9`4^z8OsZ+&N(&rb(Dk5AXm~?>3@kclJ<2v6=tntI zWcs6cQ#mh#r+UWX%;X(|ov|q>m!x}lvVVMOY-5Gk*Om81h#6#O5I|T>84k2jM)_gu zU&yAGOIUEl8cRQNSGqOsMlUKaxCA&Buo|ZaR5;AnycW(&Mdmv^Q$L9|Z$D4d;ZY` zlsdvJ$#LMk(|gtQ+BJ)kUGS-oH_p8T2|M$%N51dW1S39X_vCoPg^!qfUxlre<(@kV zBG61o6`N(*qh^5;rs41I-n6(ac=j*-pj0Z1FK7pqOsOEV<*;}Oi#f3{T6J@5?Z{a0 z0AS9g+LS_a#x*48!<)+#93lB@LJ!u|bPe5x^n}E?ex4V`Te82)sze2m!2{85pHvdp8h-HdvC5#{SKzCn}FKg`W?bOJMfNi_RKIcN;U* zvWSb1@$>9yoM6Sf`>JqtLbB(LCRRCdr*@0rr{nZ&J~*oN+WN!j)Oh(bb(n1gEWnNeTU}-a=dzmK^T$G3UfqTkb(?Mz%hiK@m%n7rCX{f%b^F>RO{PQx%`iQTK#2-+;J zgv3*QE7!y;>ijsGRh;uPL)FhFL=PBl1*?1ij;h4k8`cJ2&%7_DU{o_X_)CVOX)Uo| z*uN~Q#wEK}%tsC`gfO!oZnR__W(GH-MO=@5>A-4BiLa%?t}0wZ(1lgP@F&V%@?H@f_3?x;GH#pG2QOCA z4_1=aphN=DuKBG?5er-!6jooy1e+)Q4sw5AQ*E7(kHbRuBMiUFt#CqkRhNi|t zECA$fito~?Z0ADy`gXoug0bu<*E0{Cxa=YkV=4%WBUN_WQrc~&TE8Ybk1*YIV#Nco)IPLy(cEu?T7rk#g0A$m__r{l37BwqLoXQy;c;A!mctjj); z)(Z5W61@1=p_`m=S^&$*=)Ai+3EC)3_FQ~hqj{C^p5lqD6|^{pd(s8`8$)lqTQsH@ z7Z9-M|8N-YkwI3$2$g01Fp7r6yD&O9eC0PY>k>1cW3LLSAnXpZr&jP;G`!J+)ge5) zv>qD@B*ecvZE2b73@`R=|+>SfwLK9IhuJ8t)@?5L97pESJo#w>f|D zDdP+z=d2H}ae2;2Zd9+&OfUe`pKoxO-UP8?bN-O2>Q_hXj8E8!C$>B6y@wNs);_6H z;Lq&fiALgdR9p!mgl-8mlWnxS{&4@)UrPdO=Fi6(I`W8F(yMPCsEPB!Oa#3)Z#XB6 z;?7dX5z=zdkxM|nZJwwo`SL@Xo9}r~o7JLGuq$E%0=^O3MJh`DkUm1E5b0y6^$WUU zG(McLU#4pIFl_>ENE3DRlk_*vXZymj)MeYHswAf!)pfqeQcfW2BEotz;1s9&3%WlF zrEj8mK9WN*H8pJ51*CxuC)KMc5%dQm$w=}hmBOP+d~2cwIVG?<&Og;#9;}8GlDI-C z?1CR=8;6Bdr0WAtEq7u+k%;wnEh92R-Z|W~j9r95kB-HuBNMB$$LH<^l+=8^PMlV_LFFTO zBD6uUw&6BUWBr&9NPGjuOhrEpB8vQGxzLZJDcpvPWK3kaD<;yHHiaR{B0@ zmh)S^_8p*dY*zCE|R`W`b^Ce|A&=Rd{ictbx;xEar25 z`b;Kf3pOI^Ku8L+<{U3=_2zh7Ga9daGTEmT1w(+^#CLeXl1y%+JsgKHsqOeZAk45te^mfk;%4s~^I?Qx& zcp2nl_*pJ1=Cz#|va%3Bm1`wJm1Y`Oxfb=w#mIy9>sCNX?wvp(?{8NefxQ9}N^8p> z6r>+#T(A#iE0AVW`QA{Y)B~3Gx7~^YdE^ON&U%VM_^&dR^lF3QuJf-|*b6JG@Y}Ex z8Vch`8yNLtY|t}MP)!k&sb?4o2&3c{&RD<0+i)B)YjOtt&H3xKUb_uY&Td5(`)R(w zyiUs1ghZUQm&|N<2V?&uhE?QYh7rO-yG2YJ9plx#g{*4oO~nP=#dwYgyv7$~YnlMB z&RFOozDC+b#z~IYGO2BLLO$H$m^Ku!+tfSv!g|hgv4+c@hFOyfy`*zaBngEps(r2D zoZK&ZN?8dhRp**{`4%@jvmGXe`#SkY&2ABBGyX?^^Vm4#Mvcp}e9F{zTu;(8o?s#e zA_Y-fIOFNDgdbmj&buaOskLMulC@;Cm8odjBViX(;E$MIJn%y$EnsIv@oy|NzRZ~8 z!HyL|PkpL^WM!9s4SR$7gYOe>dJb+b@Ni?=5 zM{6)?Nic+dyE-ucbc(#MTEx`vD}Om#BaA7_CYeG7@}}UqiR_l<#y3`nAnIZg^tg`m zP;*M3pJk%t3Ws8{^AbUJR=J5`6So|TmSK}&7hzm0Cq^9!?(1Y2s!nez0?pi#5-_8W zolGU9=e62`C3e5TqMHB|Z@;1h8S{nqb;#i%A%5Trzak)3U*Iop^oFe;f7wAF3>ZUa zjSPYn7mmnq@QT{Lg7=6>72axESr>=c0`m7L>Zbi$68WAGNQrxR0cVN+Oo-_lO*yc& zC9!*|jGJTGbXjx!C?ot(qFCHAFCw|(JiU$XpE3Xab=c%Rm=%lJU@teb14k-U>F)uU0elkN(g=B!)oFC>Usx;cRANuzgk$zKKeBI zn*k++ug^*FK)T`!o+l8D@a-%TP7&GR=rN|9_)ay@p9~hz7*+Gr+e(~ZW7@Uo+Wqz? zX^>=n$7es{wvqIxI~WfFQ(=y32Y+bbcWCdlf0_dW z&(k6-HhURX)_5Fqa&cZf;>Wb%vsml!wwLkkMm%}Jfojg`O#700-Dt%d56f(aGH{S` zqNWq^i~{np=GP3)-dI=@Shk7O_=JuMD&u^y5q&YssGQR&hGBF(w|cJoUe=){`sdwVS+&z+p_qsINC^ry zqCL#(C9WrD;zRkOTf#gOFI^zAO!mY~d&*Tf@4-#b0NVr#`FfazEXz{A_K@C#_H6zt zd=D?rQAd*Q8U7WAN27nf^5~w=_U4Wo`w#ANFQN;3SIGV`;yUaNb)1>Lgt3b;0aG%!MniZD9&iw;iKBs=bsqXh(eEz4v4kcHgGaTN&jUTAa<&V)JN#+X%^IPSg_YoOvn!n6;H(<2E%p79&P5K%hfXwGvLOLF=8G zvl*_~p+ce||GHN?>di|Ax1HnnE)1o`HQsTx0bzyYWO#o8b@;49&$vy=LpLbcxxs@4 z#aVY(`hGBv>6g&Z3h;(o04}dz{U=RQsuJFGd?T@rnsT9-<7B|*@l&vRnbr>`Q=#I< zp2YSU4bV~pDDSdsRS=R>bv=)xqMa%x9x<$C5~`Ji)XBjG8i|RsK%tVL-+QMyq$5%e z@8o|-;daHppnoSh_yE=N>~&fpdu>20{l0z-MI9^&h;mvMna2R}S1|bo$vZr37q^q#GatRJqlow!g_4=*E|il%~Mi zW=7k^R(Vl|e-=;w$?2rPa^goha)L^!o)cuGERiPn=YmnszG-Inw2)% zFxcU>40Xu)qahM}k=JhqZ*%F5d&N0s#49X4K;Qh^AY71R!~V2fZdBBu-lV$xk`lFI zQVfaYS`u@>?RpEdyPefD*GUF7fzlQ4*g_n4A-XI#xqjEc3C1)Ee_1$q3r}Bef-P{9 zK{5B}1HPtbXV$1*69qtv#Va-FB*M;Z2ZqIz$iIN&nv`3~icY@*dE`=-n?B(Rei%z_ z>xX@pb3HVQE&iycKxU<Hs*KAcCE!vx-` z>g>r9>fqTqi#ul3WgcBqCQ}{4V?U9;bfiI=Sdqeo*)jM+B$#|+$8}`^sfb@cC?ht0 zE7?BAmA&yV(llnL${}^{COWx11ocszr@3B zTN^|orxwWq=+3~3?5pl&v-~`#)Y9qrYA?$-EpQ#sH!@W1?FGdtQqa+N4apgreBOG8 z`#f^Ta&N8jH9m4mHvYP2tjp}L{<-Jay_ks@-4o3*c9wYfl_#-0+XZFhw`#LyswxEf z;%^EfvbB;>NxabTN=9i&!g``)R#Uf%u}1C>hXyr#t{a= z!|8aTa&p8zujFqztl2_B9%^T`JXE471h$qwEvc#Td>bVmF(Tp&JJ!H8FHcs)Jqf00 zQ6DtrP>T6OVr!<*jlnZucfiSU{M9X_6=*{!w)XQrjx}Oc0Z~eW6y+vi>H*^1gxx=Q z#Q2%}`QA3$eYHP(F;~!?A|8oMxDRzOVd4sEhR~_Txn+;L0D`oQ`>vnT{R!vmnZ#UQ zIVJI6rj#H$ye0|=`@j}K1qWV+`_)|l1hf)<8^wFc@)Wf!JcZ6>A{Mgka|zi-@P|DO z*ZSo$&r^1eB~7arDnCn@c<&S)C(ANIqD0~e0{RthQvQ4;kcIG4?drSqKm6l9;Ch?)3nwP~d0*WLaIC`vr=+28^N zR)*6W6BYM`F5bJ(s9#mZ_;=JV7CKEDC_>k48;ksy9?#)521dJnVr=$Qi)}~p&5sR^ zVHI{vxxVYdWb)wcY7(O}t45VoU+6SwL0_89D78#iewXf_aehezq5d}K(KOXXs~+a| zq;}-x#6P|vka57MvtD=p3my=aJ;@Zjp>p$H@X8~y#x)2ze6(Yr>CeOds)ivzXcgxg zWx&mIC&oIJv2*Y$wN`KAmzM**GyMZ;(Xkg)R&2u<7{Y6IsXVnZrorGboukIV$Ojy+ zi#!?~=SF^vd$r8e&aiZhjm8HP$NqjeYn`8$rryD?*0)fhtnd>k~=QYr+>K zJLZgH$?2erGpaBY(pX;;zhhu9sZ=$I{h|S=uk(h&P1T5)XS`Pp5>yZtNhk)@_^oJH z{8eEe#&+ffkuEUo9`Bm2N6a7iKon%FE46a#T*}UuEsByKZESv$ZfYzl z5zP$qsx}X0vWoW|#ycDddeAwKTUr~yX8v!A>;cHUBhgwRUsxwQ1=nX+J6hS{qpL=Q|R6a!=$4nGUdD7V@enaBk9}HKS|14TI+*$as~Y=a zOd3Cx^o-xv?;jdPx!SqI*M_$RJGp>sG6#S#(wj@*d5VCi?%X`}UTJigA&*Y4&8y6c zN&}ntOHSSgn}VFyP_g&JEhja@)}M~~?01)j1{UYh=R13CbY(ZSH>7vUU0}A2c|TJf zJGYBj1v@)Hws)eUPJDMhojogTdQ=e{I_qC6GTMpI=>x^AVa#&OPdF{zT=i=Hd5Nvq zjkRL7_D8BY2(pEas?*yAm`zx#4PuyzHD*Iz%vKG&Sd~v;DVr1O4oYdgnqnpmb^~XPG-653AvDQ`pFt6o1SxfY2oq}rkt81Y%B-%mf+p9Z)vVVy zhuNsWiape>8jJf-&j@Vggno=IA*Vfwj3-TNI=_%Tv+zr6$uuqE;1|o7ZRfG!w+Li6 z$l(C%zmE?&WXxWjPBelU$9I>EO9&0cfjR-u{igyey;9?J)=%B5s37qJ=C5lQnaV8{ zvT;aX@V3>LXOxi>&!L=fv4Da^?5M2HpEMbhb8gJV8l& zTpwqRvu)CX>{#>%Sq?C-B}k9V{R~nPJQU9vO;l+HHHR50hpSyhnMNB^smR(guA58r!Ccw_|X??=j4nKVUNAqJn?;C{b z!yG{wihqfvD}Kj17rYNk?WtlyoG(({3Mt>XQe<1!*JCx@ErYDkesQYa9=6-Rc*;qv zpUOP(PsW{lMMDnr2_s4s4YHRU+LRKFS}sLR&0lW@{8zxxJHXaPl#~y08ZAdr@9+2P zmKp0GnwFALpzo>qWjB;Xbz{}qZRT`(z1b{cFQ9Xu%tB_~&GWzR{`cNP@SpB30+W9f y)IZzQ|CHmuW9!_PF9QB|p3(o&{{Qa2y2s_MeY{`R-Lr}FZ|Q5BJo=~!f&T}4T`Rx< From f8f80d0710464d60e13f2c87a8054f5ce1acd0a4 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Tue, 7 Jan 2025 17:01:19 +0100 Subject: [PATCH 10/17] Take care of HighDPI --- fmu_manipulation_toolbox/gui.py | 35 +++++++++++++-------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 70a51bc..e84aee3 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -1,11 +1,12 @@ import os.path import sys -from .version import __version__ as version -from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint, QModelIndex, QMimeData, QByteArray, QDataStream, QIODevice, QItemSelectionModel, QItemSelection -from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, - QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QMainWindow) -from PySide6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction, QPainter, QColor, QStandardItemModel) import textwrap + +from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint, QModelIndex +from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, + QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView) +from PySide6.QtGui import (QPixmap, QFont, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction, + QPainter, QColor,QImage, QStandardItemModel) from functools import partial from typing import Optional @@ -13,6 +14,7 @@ from .assembly import Assembly, AssemblyNode from .checker import checker_list from .help import Help +from .version import __version__ as version class DropZoneWidget(QLabel): @@ -138,14 +140,14 @@ def __init__(self): super().__init__() if os.name == 'nt': font = QFont('Consolas') - font.setPointSize(10) + font.setPointSize(11) else: font = QFont('Courier New') font.setPointSize(12) self.setFont(font) - self.setMinimumWidth(800) - self.setMinimumHeight(480) - + self.setMinimumWidth(900) + self.setMinimumHeight(500) + self.setSearchPaths([os.path.join(os.path.dirname(__file__), "resources")]) self.insertHtml('


    ') LogWidget.XStream.stdout().messageWritten.connect(self.insertPlainText) LogWidget.XStream.stderr().messageWritten.connect(self.insertPlainText) @@ -288,17 +290,6 @@ def closeEvent(self, event): event.accept() -class ContainerWindow2(QWidget): - def __init__(self, main_window, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.main_window = main_window - self.setWindowTitle('FMU Manipulation Toolbox - Container') - - # show the window - self.show() - - class FMUManipulationToolboxlMainWindow(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -557,6 +548,7 @@ class Application(QApplication): """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.RoundPreferFloor) QDir.addSearchPath('images', os.path.join(os.path.dirname(__file__), "resources")) font = QFont("Verdana") @@ -597,10 +589,11 @@ def __init__(self, *args, **kwargs): self.setStyleSheet(css_dark) if os.name == 'nt': + import ctypes self.setWindowIcon(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon-round.png'))) # https://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7/1552105#1552105 - import ctypes + application_id = 'FMU_Manipulation_Toolbox' # arbitrary string ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(application_id) else: From 863ca1289017e48b454e9fa7609aebe10999a350 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Tue, 7 Jan 2025 20:11:38 +0100 Subject: [PATCH 11/17] Code refactoring (GUI) --- fmu_manipulation_toolbox/gui.py | 196 +++++++++++++++++++------------- 1 file changed, 117 insertions(+), 79 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index e84aee3..2aabd6a 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -6,7 +6,7 @@ from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView) from PySide6.QtGui import (QPixmap, QFont, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction, - QPainter, QColor,QImage, QStandardItemModel) + QPainter, QColor, QImage, QStandardItemModel) from functools import partial from typing import Optional @@ -74,7 +74,7 @@ def set_image(self, filename=None): filename = os.path.join(os.path.dirname(__file__), "resources", "fmu.png") base_image = QImage(filename).scaled(self.WIDTH, self.HEIGHT, Qt.AspectRatioMode.IgnoreAspectRatio, - Qt.TransformationMode.SmoothTransformation) + Qt.TransformationMode.SmoothTransformation) mask_filename = os.path.join(os.path.dirname(__file__), "resources", "mask.png") mask_image = QImage(mask_filename).scaled(self.WIDTH, self.HEIGHT, Qt.AspectRatioMode.IgnoreAspectRatio, Qt.TransformationMode.SmoothTransformation) @@ -213,96 +213,117 @@ def get(self): return sorted(self.items_selected) -class AssemblyTreeModel(QStandardItemModel): - def __init__(self, assembly: Assembly, parent=None): - super().__init__(parent) +class AssemblyTreeWidget(QTreeView): + class AssemblyTreeModel(QStandardItemModel): - self.lastDroppedItems = [] - self.pendingRemoveRowsAfterDrop = False - self.setHorizontalHeaderLabels(['col1']) - self.add_node(assembly.root, self) - self.drop_node: Optional[AssemblyNode] = None - - def add_node(self, node: AssemblyNode, parent_item): - item = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'container.png')), - node.name) - item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled) - item.setData(node) - children_name = [child.name for child in node.children] - for fmu_name in node.fmu_names_list: - if not fmu_name in children_name: - fmu_node = QStandardItem(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon_fmu.png')), - fmu_name) - fmu_node.setData(fmu_name) - fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled) - item.appendRow(fmu_node) - for child in node.children: - self.add_node(child, item) - parent_item.appendRow(item) - - def insertRows(self, row, count, parent=QModelIndex()): - self.drop_node = parent.data(role=Qt.ItemDataRole.UserRole+1) - return super().insertRows(row, count, parent=parent) - - def removeRows(self, row, count, parent=QModelIndex()): - if not self.drop_node: - print("NO DROP NODE!?") - - source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1) - print(f"{source_index} ==> {self.drop_node.name}") - - self.drop_node = None - return super().removeRows(row, count, parent) - - def dropMimeData(self, data, action, row, column, parent: QModelIndex): - if parent.column() < 0: # Avoid to drop item as a sibling of the root. - return False - return super().dropMimeData(data, action, row, column, parent) - - -class ContainerWindow(QWidget): - def __init__(self, parent=None): - super().__init__(None) - self.main_window = parent - assembly = Assembly("tests/containers/arch/reversed.json") - self.model = AssemblyTreeModel(assembly) - self.view = QTreeView() - self.view.setModel(self.model) - self.view.expandAll() + def __init__(self, assembly: Assembly, parent=None): + super().__init__(parent) - self.view.setDropIndicatorShown(True) - self.view.setDragDropOverwriteMode(False) - self.view.setAcceptDrops(True) - self.view.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + self.lastDroppedItems = [] + self.pendingRemoveRowsAfterDrop = False + self.setHorizontalHeaderLabels(['col1']) + self.dnd_target_node: Optional[AssemblyNode] = None - self.layout = QGridLayout() - self.layout.setVerticalSpacing(4) - self.layout.setHorizontalSpacing(4) - self.layout.setContentsMargins(10, 10, 10, 10) - self.setLayout(self.layout) - self.layout.addWidget(self.view, 0, 0) - self.setWindowTitle('FMU Manipulation Toolbox - Container') + self.icon_container = QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'container.png')) + self.icon_fmu = QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon_fmu.png')) - self.show() + self.add_node(assembly.root, self) - def closeEvent(self, event): - self.main_window.closing_container() - event.accept() + def add_node(self, node: AssemblyNode, parent_item): + # Add Container + item = QStandardItem(self.icon_container, node.name) + parent_item.appendRow(item) + item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled | + Qt.ItemFlag.ItemIsDropEnabled) + item.setData(node) + # Add FMU's + children_name = [child.name for child in node.children] + for fmu_name in node.fmu_names_list: + if fmu_name not in children_name: + fmu_node = QStandardItem(self.icon_fmu, fmu_name) + fmu_node.setData(node) + fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | + Qt.ItemFlag.ItemIsDragEnabled) + item.appendRow(fmu_node) -class FMUManipulationToolboxlMainWindow(QWidget): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + # Add Sub-Containers + for child in node.children: + self.add_node(child, item) + + def insertRows(self, row, count, parent=QModelIndex()): + self.dnd_target_node = parent.data(role=Qt.ItemDataRole.UserRole + 1) + return super().insertRows(row, count, parent=parent) + + def removeRows(self, row, count, parent=QModelIndex()): + if not self.dnd_target_node: + print("NO DROP NODE!?") + + source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1) + print(f"{source_index} ==> {self.dnd_target_node.name}") + + self.dnd_target_node = None + return super().removeRows(row, count, parent) + + def dropMimeData(self, data, action, row, column, parent: QModelIndex): + if parent.column() < 0: # Avoid to drop item as a sibling of the root. + return False + return super().dropMimeData(data, action, row, column, parent) + + def __init__(self, assembly: Optional[Assembly] = None, parent=None): + super().__init__(parent) + + self.model = self.AssemblyTreeModel(assembly) + self.setModel(self.model) + self.expandAll() + self.setDropIndicatorShown(True) + self.setDragDropOverwriteMode(False) + self.setAcceptDrops(True) + self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + self.setRootIsDecorated(False) + self.setHeaderHidden(True) + + def dragEnterEvent(self, event): + if event.mimeData().hasImage: + event.accept() + else: + event.ignore() + + def dragMoveEvent(self, event): + if event.mimeData().hasImage: + event.accept() + else: + event.ignore() + + def dropEvent(self, event): + if event.mimeData().hasImage: + event.setDropAction(Qt.DropAction.CopyAction) + try: + file_path = event.mimeData().urls()[0].toLocalFile() + except IndexError: + print("Please select a regular file.") + return + print(f"DROP: {file_path}") + event.accept() + else: + event.ignore() - self.setWindowTitle('FMU Manipulation Toolbox') +class WindowWithLayout(QWidget): + def __init__(self, title: str): + super().__init__(None) # Do not set parent to have a separated window + self.setWindowTitle(title) - # set the grid layout self.layout = QGridLayout() self.layout.setVerticalSpacing(4) self.layout.setHorizontalSpacing(4) self.layout.setContentsMargins(10, 10, 10, 10) self.setLayout(self.layout) + +class MainWindow(WindowWithLayout): + def __init__(self): + super().__init__('FMU Manipulation Toolbox') + self.dropped_fmu = DropZoneWidget() self.dropped_fmu.clicked.connect(self.update_fmu) @@ -487,7 +508,7 @@ def operation_handler(): self.layout.addWidget(button, x, y) def prompt_string(self, message): - text, ok = QInputDialog().getText(self, "Enter value", f"{message}:", QLineEdit.Normal, "") + text, ok = QInputDialog().getText(self, "Enter value", f"{message}:", QLineEdit.EchoMode.Normal, "") if ok and text: return text @@ -538,6 +559,23 @@ def apply_operation(self, operation): scroll_bar.setValue(scroll_bar.maximum()) +class ContainerWindow(WindowWithLayout): + def __init__(self, parent: MainWindow): + super().__init__('FMU Manipulation Toolbox - Container') + self.main_window = parent + + assembly = Assembly("tests/containers/arch/reversed.json") + self.assembly_tree = AssemblyTreeWidget(assembly, parent=self) + self.layout.addWidget(self.assembly_tree, 0, 0) + + self.show() + + def closeEvent(self, event): + if self.main_window: + self.main_window.closing_container() + event.accept() + + class Application(QApplication): """ Analyse and modify your FMUs. @@ -599,7 +637,7 @@ def __init__(self, *args, **kwargs): else: self.setWindowIcon(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon.png'))) - self.window = FMUManipulationToolboxlMainWindow() + self.window = MainWindow() def main(): From c3bc7dd262a521a2244cf5d501f2649dd474adad Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Wed, 8 Jan 2025 20:08:20 +0100 Subject: [PATCH 12/17] WIP --- fmu_manipulation_toolbox/gui.py | 72 +++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 2aabd6a..7f6474c 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -4,7 +4,8 @@ from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint, QModelIndex from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog, - QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView) + QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QTabWidget, QTableView, + QCheckBox) from PySide6.QtGui import (QPixmap, QFont, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction, QPainter, QColor, QImage, QStandardItemModel) from functools import partial @@ -283,19 +284,27 @@ def __init__(self, assembly: Optional[Assembly] = None, parent=None): self.setRootIsDecorated(False) self.setHeaderHidden(True) - def dragEnterEvent(self, event): + if os.name == 'nt': + font = QFont('Consolas') + font.setPointSize(11) + else: + font = QFont('Courier New') + font.setPointSize(12) + self.setFont(font) + + def dragEnterEvent2(self, event): if event.mimeData().hasImage: event.accept() else: event.ignore() - def dragMoveEvent(self, event): + def dragMoveEvent2(self, event): if event.mimeData().hasImage: event.accept() else: event.ignore() - def dropEvent(self, event): + def dropEvent2(self, event): if event.mimeData().hasImage: event.setDropAction(Qt.DropAction.CopyAction) try: @@ -308,6 +317,52 @@ def dropEvent(self, event): else: event.ignore() + +class AssemblPropertiesWidget(QWidget): + def __init__(self, parent=None): + super().__init__(parent) + + self.layout = QGridLayout() + self.layout.setVerticalSpacing(4) + self.layout.setHorizontalSpacing(4) + self.layout.setContentsMargins(10, 10, 10, 10) + self.setLayout(self.layout) + + mt_check = QCheckBox("Multi-Threaded", self) + self.layout.addWidget(mt_check, 1, 0) + + profiling_check = QCheckBox("Profiling", self) + self.layout.addWidget(profiling_check, 1, 1) + + auto_inputs_check = QCheckBox("Auto Inputs", self) + self.layout.addWidget(auto_inputs_check, 0, 0) + + auto_outputs_check = QCheckBox("Auto Outputs", self) + self.layout.addWidget(auto_outputs_check, 0, 1) + + auto_links_check = QCheckBox("Auto Links", self) + self.layout.addWidget(auto_links_check, 0, 2) + + +class AssemblyTabWidget(QTabWidget): + def __init__(self, parent=None): + super().__init__(parent) + + table = AssemblPropertiesWidget(parent=self) + self.addTab(table, "Properties") + table = QTableView() + self.addTab(table, "Links") + table = QTableView() + self.addTab(table, "Inputs") + table = QTableView() + self.addTab(table, "Outputs") + table = QTableView() + self.addTab(table, "Start values") + + + + + class WindowWithLayout(QWidget): def __init__(self, title: str): super().__init__(None) # Do not set parent to have a separated window @@ -568,6 +623,15 @@ def __init__(self, parent: MainWindow): self.assembly_tree = AssemblyTreeWidget(assembly, parent=self) self.layout.addWidget(self.assembly_tree, 0, 0) + self.assembly_tab = AssemblyTabWidget(parent=self) + self.layout.addWidget(self.assembly_tab, 0, 1) + + fmu_button = QPushButton("Add FMU") + self.layout.addWidget(fmu_button, 1, 0) + + fmu_button = QPushButton("Add Container") + self.layout.addWidget(fmu_button, 1, 1) + self.show() def closeEvent(self, event): From 4f9641e5f6c4fa6c7e5544a3456e0d2557f42731 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Mon, 13 Jan 2025 22:30:38 +0100 Subject: [PATCH 13/17] WIP: prepare moving AssemblyNode feature --- fmu_manipulation_toolbox/assembly.py | 107 +++++++++++++++++++++++++-- fmu_manipulation_toolbox/gui.py | 6 +- tests/containers/arch/nested.json | 73 ++++++++++++++++++ tests/test_suite.py | 18 +++++ 4 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 tests/containers/arch/nested.json diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index fc8896f..fcc6fec 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -23,12 +23,18 @@ def __hash__(self): def __eq__(self, other): return str(self) == str(other) + def __str__(self): + return f"{self.fmu_name}/{self.port_name}" + class Connection: def __init__(self, from_port: Port, to_port: Port): self.from_port = from_port self.to_port = to_port + def __str__(self): + return f"{self.from_port} -> {self.to_port}" + class AssemblyNode: def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False, @@ -50,10 +56,10 @@ def __init__(self, name: Optional[str], step_size: float = None, mt=False, profi self.auto_parameter = auto_parameter self.parent: Optional[AssemblyNode] = None - self.children: List[AssemblyNode] = [] # sub-containers + self.children: Dict[str, AssemblyNode] = {} # sub-containers self.fmu_names_list: Set[str] = set() # FMUs contained at this level - self.input_ports: Dict[Port, str] = {} - self.output_ports: Dict[Port, str] = {} + self.input_ports: Dict[Port, str] = {} # value is input port name, key is the source + self.output_ports: Dict[Port, str] = {} # value is output port name, key is the origin self.start_values: Dict[Port, str] = {} self.drop_ports: List[Port] = [] self.links: List[Connection] = [] @@ -65,9 +71,12 @@ def add_sub_node(self, sub_node): if sub_node.parent is not None: raise AssemblyError(f"Internal Error: AssemblyNode {sub_node.name} is already parented.") + if sub_node.name in self.children: + raise AssemblyError(f"Internal Error: AssemblyNode {sub_node.name} is already child of {self.name}") + sub_node.parent = self self.fmu_names_list.add(sub_node.name) - self.children.append(sub_node) + self.children[sub_node.name] = sub_node def add_fmu(self, fmu_name: str): self.fmu_names_list.add(fmu_name) @@ -89,7 +98,7 @@ def add_start_value(self, fmu_filename: str, port_name: str, value: str): self.start_values[Port(fmu_filename, port_name)] = value def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None): - for node in self.children: + for node in self.children.values(): node.make_fmu(fmu_directory, debug=debug) identifier = str(Path(self.name).stem) @@ -121,10 +130,94 @@ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None): container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, debug=debug) - for node in self.children: + for node in self.children.values(): logger.info(f"Deleting transient FMU Container '{node.name}'") (fmu_directory / node.name).unlink() + def get_final_from(self, port: Port) -> Port: + if port.fmu_name in self.fmu_names_list: + if port.fmu_name in self.children: + child = self.children[port.fmu_name] + ancestors = [key for key, val in child.output_ports.items() if val == port.port_name] + if len(ancestors) == 1: + return child.get_final_from(ancestors[0]) + else: + return port + + #for link in self.links: + # if link.to_port == port: + # from_port = link.from_port + # if from_port.fmu_name in self.children: # linked to child container + # return self.children[from_port.fmu_name].get_final_from(from_port) + # elif from_port.fmu_name in self.fmu_names_list: # embedded FMU + # return from_port + # else: + # raise AssemblyError(f"{self.name}: Port {port} is not connected to upstream known object.") + + if port in self.input_ports: + ancestor = Port(self.name, self.input_ports[port]) + if self.parent: + return self.parent.get_final_from(ancestor) + else: + return ancestor + + raise AssemblyError(f"{self.name}: Port {port} is not connected upstream.") + + def get_final_to(self, port: Port) -> Port: + if port.fmu_name in self.fmu_names_list: + if port.fmu_name in self.children: + child = self.children[port.fmu_name] + successors = [key for key, val in child.input_ports.items() if val == port.port_name] + if len(successors) == 1: + return child.get_final_to(successors[0]) #CASE 2 + else: + return port # CASE 1 + + #for link in self.links: + # if link.from_port == port: + # to_port = link.to_port + # if to_port.fmu_name in self.children: # linked to child container + # return self.children[to_port.fmu_name].get_final_to(to_port) + # elif to_port.fmu_name in self.fmu_names_list: # embedded FMU + # return to_port + # else: + # raise AssemblyError(f"Port {port} is not connected to downstream known object.") + + if port in self.output_ports: + successor = Port(self.name, self.output_ports[port]) + if self.parent: + return self.parent.get_final_to(successor) + else: + return successor + + raise AssemblyError(f"Node {self.name}: Port {port} is not connected downstream.") + + def get_fmu_connections(self, fmu_name: str) -> List[Connection]: + connections = [] + if fmu_name not in self.fmu_names_list: + raise AssemblyError(f"Internal Error: FMU {fmu_name} is not embedded by {self.name}.") + for link in self.links: + if link.from_port.fmu_name == fmu_name: + connections.append(Connection(link.from_port, self.get_final_to(link.to_port))) + elif link.to_port.fmu_name == fmu_name: + connections.append(Connection(self.get_final_from(link.from_port), link.to_port)) + + for to_port, input_port_name in self.input_ports.items(): + if to_port.fmu_name == fmu_name: + if self.parent: + connections.append(Connection(self.parent.get_final_from(Port(self.name, input_port_name)), to_port)) + else: + connections.append(Connection(Port(self.name, input_port_name), to_port)) + + for from_port, output_port_name in self.output_ports.items(): + if from_port.fmu_name == fmu_name: + if self.parent: + connections.append(Connection(from_port, self.parent.get_final_to(Port(self.name, output_port_name)))) + else: + connections.append(Connection(from_port, Port(self.name, output_port_name))) ###HERE + + return connections + class AssemblyError(Exception): def __init__(self, reason: str): @@ -379,7 +472,7 @@ def _json_encode_node(self, node: AssemblyNode) -> Dict[str, Any]: json_node["step_size"] = node.step_size # 7 if node.children: - json_node["container"] = [self._json_encode_node(child) for child in node.children] # 8 + json_node["container"] = [self._json_encode_node(child) for child in node.children.values()] # 8 if node.fmu_names_list: json_node["fmu"] = [f"{fmu_name}" for fmu_name in sorted(node.fmu_names_list)] # 9 diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 7f6474c..31591d5 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -239,7 +239,7 @@ def add_node(self, node: AssemblyNode, parent_item): item.setData(node) # Add FMU's - children_name = [child.name for child in node.children] + children_name = node.children.keys() for fmu_name in node.fmu_names_list: if fmu_name not in children_name: fmu_node = QStandardItem(self.icon_fmu, fmu_name) @@ -249,7 +249,7 @@ def add_node(self, node: AssemblyNode, parent_item): item.appendRow(fmu_node) # Add Sub-Containers - for child in node.children: + for child in node.children.values(): self.add_node(child, item) def insertRows(self, row, count, parent=QModelIndex()): @@ -619,7 +619,7 @@ def __init__(self, parent: MainWindow): super().__init__('FMU Manipulation Toolbox - Container') self.main_window = parent - assembly = Assembly("tests/containers/arch/reversed.json") + assembly = Assembly("tests/containers/arch/nested.json") self.assembly_tree = AssemblyTreeWidget(assembly, parent=self) self.layout.addWidget(self.assembly_tree, 0, 0) diff --git a/tests/containers/arch/nested.json b/tests/containers/arch/nested.json new file mode 100644 index 0000000..3036357 --- /dev/null +++ b/tests/containers/arch/nested.json @@ -0,0 +1,73 @@ +{ + "name": "level0.fmu", + "fmu": [ + "fmu0a.fmu", + "fmu0b.fmu" + ], + "container": [ + { + "name": "level1.fmu", + "fmu": [ + "fmu1a.fmu", + "fmu1b.fmu", + "fmu1c.fmu" + ], + "link": [ + ["fmu1a.fmu", "fmu1a_out0", "fmu1b.fmu", "fmu1b_in1"], + ["level2a.fmu", "level2a_out0", "fmu1b.fmu", "fmu1b_in2"], + ["fmu1b.fmu", "fmu1b_out1", "fmu1c.fmu", "fmu1c_in0"], + ["fmu1b.fmu", "fmu1b_out2", "level2b.fmu", "level2b_in0"] + ], + "input": [ + ["level1_in0", "fmu1b.fmu", "fmu1b_in0"], + ["level1_in1", "fmu1a.fmu", "fmu1a_in0"], + ["level1_in2", "level2a.fmu", "level2a_in0"] + ], + "output": [ + [ "fmu1b.fmu", "fmu1b_out0", "level1_out0"], + [ "fmu1c.fmu", "fmu1c_out0", "level1_out1"], + [ "level2b.fmu", "level2b_out0", "level1_out2"] + ], + "container": [ + { + "name": "level2a.fmu", + "fmu": [ + "fmu2a.fmu" + ], + "input": [ + ["level2a_in0", "fmu2a.fmu", "fmu2a_in0"] + ], + "output": [ + ["fmu2a.fmu", "fmu2a_out0", "level2a_out0"] + ] + }, + { + "name": "level2b.fmu", + "fmu": [ + "fmu2b.fmu" + ], + "input": [ + ["level2b_in0", "fmu2b.fmu", "fmu2b_in0"] + ], + "output": [ + ["fmu2b.fmu", "fmu2b_out0", "level2b_out0"] + ] + } + ] + } + ], + "input": [ + ["IN_A", "level1.fmu", "level1_in0"], + ["IN_B", "fmu0a.fmu", "fmu0a_in0"] + ], + "output": [ + ["level1.fmu", "level1_out0", "OUT_A"], + ["fmu0b.fmu", "fmu0b_out0", "OUT_B"] + ], + "link": [ + ["fmu0a.fmu", "fmu0a_out0", "level1.fmu", "level1_in1"], + ["fmu0a.fmu", "fmu0a_out1", "level1.fmu", "level1_in2"], + ["level1.fmu", "level1_out1", "fmu0b.fmu", "fmu0b_in0"], + ["level1.fmu", "level1_out2", "fmu0b.fmu", "fmu0b_in1"] + ] +} diff --git a/tests/test_suite.py b/tests/test_suite.py index 4dd21e0..2e16960 100755 --- a/tests/test_suite.py +++ b/tests/test_suite.py @@ -89,6 +89,24 @@ def test_container_json_reversed(self): self.assert_identical_files("containers/arch/REF-reversed-dump.json", "containers/arch/reversed-dump.json") + def test_container_move(self): + #bb = Assembly("bouncing.csv", fmu_directory=Path("containers/bouncing_ball")) + #links = bb.root.get_fmu_connections("bb_position.fmu") + #print("Links: ", links) + #bb.write_json("bouncing.json") + assembly = Assembly("nested.json", fmu_directory=Path("containers/arch")) + fmu_name = "fmu1b.fmu" + links_fmu1b = assembly.root.children["level1.fmu"].get_fmu_connections("fmu1b.fmu") + + print("RESULTS:") + for link in links_fmu1b: + print(f"{link}") + + links_fmu0a = assembly.root.get_fmu_connections("fmu0a.fmu") + print("RESULTS:") + for link in links_fmu0a: + print(f"{link}") + if __name__ == '__main__': unittest.main() From 619972e10658a1cbb8cfa055ad95b211ee487cab Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Tue, 7 Jan 2025 20:49:30 +0100 Subject: [PATCH 14/17] Fix DropZone --- fmu_manipulation_toolbox/gui.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index 31591d5..bda3dfb 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -33,19 +33,19 @@ def __init__(self, parent=None): self.setFixedSize(self.WIDTH, self.HEIGHT) def dragEnterEvent(self, event): - if event.mimeData().hasImage: + if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dragMoveEvent(self, event): - if event.mimeData().hasImage: + if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): - if event.mimeData().hasImage: + if event.mimeData().hasUrls(): event.setDropAction(Qt.DropAction.CopyAction) try: file_path = event.mimeData().urls()[0].toLocalFile() From da4e9efc8778d975a642a3f873d3b3cc22caca90 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Tue, 14 Jan 2025 15:56:32 +0100 Subject: [PATCH 15/17] Refactor code --- fmu_manipulation_toolbox/assembly.py | 58 +++++++++------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index fcc6fec..745bfe4 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -135,60 +135,38 @@ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None): (fmu_directory / node.name).unlink() def get_final_from(self, port: Port) -> Port: - if port.fmu_name in self.fmu_names_list: + if port in self.input_ports: + ancestor = Port(self.name, self.input_ports[port]) + if self.parent: + return self.parent.get_final_from(ancestor) # input port + else: + return ancestor # TOPLEVEL input port + elif port.fmu_name in self.fmu_names_list: if port.fmu_name in self.children: child = self.children[port.fmu_name] ancestors = [key for key, val in child.output_ports.items() if val == port.port_name] if len(ancestors) == 1: - return child.get_final_from(ancestors[0]) - else: - return port - - #for link in self.links: - # if link.to_port == port: - # from_port = link.from_port - # if from_port.fmu_name in self.children: # linked to child container - # return self.children[from_port.fmu_name].get_final_from(from_port) - # elif from_port.fmu_name in self.fmu_names_list: # embedded FMU - # return from_port - # else: - # raise AssemblyError(f"{self.name}: Port {port} is not connected to upstream known object.") - - if port in self.input_ports: - ancestor = Port(self.name, self.input_ports[port]) - if self.parent: - return self.parent.get_final_from(ancestor) + return child.get_final_from(ancestors[0]) # child output port else: - return ancestor + return port # embedded FMU raise AssemblyError(f"{self.name}: Port {port} is not connected upstream.") def get_final_to(self, port: Port) -> Port: - if port.fmu_name in self.fmu_names_list: + if port in self.output_ports: + successor = Port(self.name, self.output_ports[port]) + if self.parent: + return self.parent.get_final_to(successor) # Output port + else: + return successor # TOLEVEL output port + elif port.fmu_name in self.fmu_names_list: if port.fmu_name in self.children: child = self.children[port.fmu_name] successors = [key for key, val in child.input_ports.items() if val == port.port_name] if len(successors) == 1: - return child.get_final_to(successors[0]) #CASE 2 - else: - return port # CASE 1 - - #for link in self.links: - # if link.from_port == port: - # to_port = link.to_port - # if to_port.fmu_name in self.children: # linked to child container - # return self.children[to_port.fmu_name].get_final_to(to_port) - # elif to_port.fmu_name in self.fmu_names_list: # embedded FMU - # return to_port - # else: - # raise AssemblyError(f"Port {port} is not connected to downstream known object.") - - if port in self.output_ports: - successor = Port(self.name, self.output_ports[port]) - if self.parent: - return self.parent.get_final_to(successor) + return child.get_final_to(successors[0]) # Child input port else: - return successor + return port # embedded FMU raise AssemblyError(f"Node {self.name}: Port {port} is not connected downstream.") From 62794cac6386b0a221250e6df1288e652a1c45f7 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Wed, 15 Jan 2025 14:09:45 +0100 Subject: [PATCH 16/17] Fix rebase --- fmu_manipulation_toolbox/assembly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fmu_manipulation_toolbox/assembly.py b/fmu_manipulation_toolbox/assembly.py index 745bfe4..347ab97 100644 --- a/fmu_manipulation_toolbox/assembly.py +++ b/fmu_manipulation_toolbox/assembly.py @@ -207,7 +207,7 @@ def __repr__(self): class Assembly: def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False, - auto_output=True, mt=False, profiling=False, fmu_directory: Path = ".", auto_parameter=False): + auto_output=True, mt=False, profiling=False, fmu_directory: Path = Path("."), auto_parameter=False): self.filename = Path(filename) self.default_auto_input = auto_input self.debug = debug From bf21c55bed05bc73c3c443a5567a09a47ccc3c08 Mon Sep 17 00:00:00 2001 From: Nicolas LAURENT Date: Sat, 18 Jan 2025 18:02:42 +0100 Subject: [PATCH 17/17] Add style on CheckBox --- fmu_manipulation_toolbox/gui.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fmu_manipulation_toolbox/gui.py b/fmu_manipulation_toolbox/gui.py index bda3dfb..0a0213d 100644 --- a/fmu_manipulation_toolbox/gui.py +++ b/fmu_manipulation_toolbox/gui.py @@ -683,9 +683,17 @@ def __init__(self, *args, **kwargs): QMenu::indicator:checked {image: url(images:checkbox-checked.png);} QMenu::indicator:checked:hover {image: url(images:checkbox-checked-hover.png);} QMenu::indicator:checked:disabled {image: url(images:checkbox-checked-disabled.png);} -QMenu::indicator:unchecked {IconWidth: 50px; image: url(images:checkbox-unchecked.png); } -QMenu::indicator:unchecked:hover {width: 35px; image: url(images:checkbox-unchecked-hover.png); } -QMenu::indicator:unchecked:disabled {width: 35px; image: url(images:checkbox-unchecked-disabled.png); } +QMenu::indicator:unchecked {image: url(images:checkbox-unchecked.png); } +QMenu::indicator:unchecked:hover {image: url(images:checkbox-unchecked-hover.png); } +QMenu::indicator:unchecked:disabled {image: url(images:checkbox-unchecked-disabled.png); } +QCheckBox::item {padding: 2px 250px 2px 20px; border: 1px solid transparent;} +QCheckBox::item::indicator {width: 32px; height: 32px; } +QCheckBox::indicator:checked {image: url(images:checkbox-checked.png);} +QCheckBox::indicator:checked:hover {image: url(images:checkbox-checked-hover.png);} +QCheckBox::indicator:checked:disabled {image: url(images:checkbox-checked-disabled.png);} +QCheckBox::indicator:unchecked {image: url(images:checkbox-unchecked.png); } +QCheckBox::indicator:unchecked:hover {image: url(images:checkbox-unchecked-hover.png); } +QCheckBox::indicator:unchecked:disabled {image: url(images:checkbox-unchecked-disabled.png); } """ self.setStyleSheet(css_dark)