From a8cfd960024050d97d4191db5e288d1c43be501f Mon Sep 17 00:00:00 2001 From: LoneGit <100798196+LoneGit@users.noreply.github.com> Date: Wed, 22 Nov 2023 01:01:08 +0300 Subject: [PATCH 1/4] fix: settings transfer (#125) --- src/entry_window.py | 3 ++- src/settings.py | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/entry_window.py b/src/entry_window.py index 74d8e82..e3f23f3 100644 --- a/src/entry_window.py +++ b/src/entry_window.py @@ -9,7 +9,7 @@ from typing import List from src.gui_utils import showErrorDialog -from src.settings import sett, get_version, paths_transfer_in_settings, PathBuilder +from src.settings import sett, get_version, set_version, paths_transfer_in_settings, PathBuilder import src.locales as locales import shutil @@ -234,3 +234,4 @@ def сheck_project_version(self, project_path): shutil.copyfile(project_settings_filename, project_settings_old_filename) shutil.copyfile("settings.yaml", project_settings_filename) paths_transfer_in_settings(project_settings_old_filename, project_settings_filename) + set_version(project_settings_filename, build_version) diff --git a/src/settings.py b/src/settings.py index 16b98d7..4cc8850 100644 --- a/src/settings.py +++ b/src/settings.py @@ -114,6 +114,19 @@ def get_version(settings_filename): print("Error reading version") return "" +def set_version(settings_filename, version): + try: + with open(settings_filename, "r") as settings_file: + settings = yaml.safe_load(settings_file) + + settings["common"]["version"] = version + + with open(settings_filename, "w") as settings_file: + yaml.dump(settings, settings_file, default_flow_style=False) + + except Exception as e: + print("Error writing version") + def paths_transfer_in_settings(initial_settings_filename, final_settings_filename): with open(initial_settings_filename, "r") as settings_file: initial_settings = yaml.safe_load(settings_file) @@ -121,13 +134,20 @@ def paths_transfer_in_settings(initial_settings_filename, final_settings_filenam with open(final_settings_filename, "r") as settings_file: final_settings = yaml.safe_load(settings_file) - for k, v in initial_settings.items(): - if k in final_settings: - final_settings[k] = v + compare_settings(initial_settings, final_settings) with open(final_settings_filename, "w") as settings_file: yaml.dump(final_settings, settings_file, default_flow_style=False) +def compare_settings(settings1, settings2): + for key in set(settings2): + if isinstance(settings2[key], dict): + compare_settings(settings1[key], settings2[key]) + else: + if key in settings1: + if not settings1[key] is None: + settings2[key] = settings1[key] + class Settings(object): def __init__(self, d): for a, b in d.items(): From 41f9140fd37601ead47ee57318de76d2f9e8255e Mon Sep 17 00:00:00 2001 From: LoneGit <100798196+LoneGit@users.noreply.github.com> Date: Mon, 27 Nov 2023 01:13:53 +0300 Subject: [PATCH 2/4] fix: vtk error (#126) --- src/window.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/window.py b/src/window.py index 4618229..f560bbc 100644 --- a/src/window.py +++ b/src/window.py @@ -147,7 +147,8 @@ def __init__(self, parent=None): # main parts central_widget = QWidget() main_grid = QGridLayout() - main_grid.addWidget(self.init3d_widget(), 0, 0, 20, 5) + self.widget3d = self.init3d_widget() + main_grid.addWidget(self.widget3d, 0, 0, 20, 5) main_grid.addWidget(self.init_right_panel(), 0, 5, 21, 2) # Tabs @@ -206,6 +207,8 @@ def closeEvent(self, event): self.close_signal.emit() event.accept() + self.widget3d.Finalize() + def init3d_widget(self): widget3d = QVTKRenderWindowInteractor(self) From 9de5d8a5781dd2461f6623b745ff4ed24e907c6e Mon Sep 17 00:00:00 2001 From: LoneGit <100798196+LoneGit@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:57:19 +0300 Subject: [PATCH 3/4] feat: save project button (#127) --- src/controller.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++- src/locales.py | 8 ++++++ src/window.py | 4 +++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/controller.py b/src/controller.py index 9b86c50..231d16a 100644 --- a/src/controller.py +++ b/src/controller.py @@ -14,7 +14,8 @@ import vtk from PyQt5 import QtCore -from PyQt5.QtWidgets import QFileDialog, QInputDialog +from PyQt5.QtCore import QSettings +from PyQt5.QtWidgets import QFileDialog, QInputDialog, QMessageBox from src import gui_utils, locales, qt_utils from src.figure_editor import PlaneEditor, ConeEditor @@ -73,6 +74,8 @@ def _connect_signals(self): self.view.open_action.triggered.connect(self.open_file) self.view.save_gcode_action.triggered.connect(partial(self.save_gcode_file)) self.view.save_sett_action.triggered.connect(self.save_settings_file) + self.view.save_project_action.triggered.connect(self.save_project) + self.view.save_project_as_action.triggered.connect(self.save_project_as) self.view.load_sett_action.triggered.connect(self.load_settings_file) self.view.slicing_info_action.triggered.connect(self.get_slicer_version) self.view.check_updates_action.triggered.connect(self.open_updater) @@ -607,6 +610,72 @@ def save_settings_file(self): except IOError as e: showErrorDialog("Error during file saving:" + str(e)) + def save_project_files(self): + save_splanes_to_file(self.model.splanes, PathBuilder.splanes_file()) + self.save_settings("vip", PathBuilder.settings_file()) + + def save_project(self): + try: + self.save_project_files() + self.successful_saving_project() + except IOError as e: + showErrorDialog("Error during project saving: " + str(e)) + + def save_project_as(self): + project_path = PathBuilder.project_path() + + try: + save_directory = str(QFileDialog.getExistingDirectory(self.view, locales.getLocale().SavingProject)) + + if not save_directory: + return + + sett().project_path = save_directory + self.save_settings("vip") + self.save_project_files() + + for root, _, files in os.walk(project_path): + target_root = os.path.join(save_directory, os.path.relpath(root, project_path)) + os.makedirs(target_root, exist_ok=True) + + for file in files: + source_file = os.path.join(root, file) + target_file = os.path.join(target_root, file) + shutil.copy2(source_file, target_file) + + self.add_recent_project(save_directory) + self.successful_saving_project() + + except IOError as e: + sett().project_path = project_path + self.save_settings("vip") + showErrorDialog("Error during project saving: " + str(e)) + + def add_recent_project(self, project_path): + settings = QSettings('Epit3D', 'Spycer') + + if settings.contains('recent_projects'): + recent_projects = settings.value('recent_projects', type=list) + + # filter projects which do not exist + import pathlib + recent_projects = [p for p in recent_projects if pathlib.Path(p).exists()] + + # adds recent project to system settings + if project_path in recent_projects: + return + + recent_projects.append(str(project_path)) + settings = QSettings('Epit3D', 'Spycer') + settings.setValue('recent_projects', recent_projects) + + def successful_saving_project(self): + message_box = QMessageBox(parent=self.view) + message_box.setWindowTitle(locales.getLocale().SavingProject) + message_box.setText(locales.getLocale().ProjectSaved) + message_box.setIcon(QMessageBox.Information) + message_box.exec_() + def load_settings_file(self): try: filename = str(self.view.open_dialog(self.view.locale.LoadSettings,"YAML (*.yaml *.YAML)")) diff --git a/src/locales.py b/src/locales.py index 06d7556..4265947 100644 --- a/src/locales.py +++ b/src/locales.py @@ -81,6 +81,8 @@ class Locale: Open = "Open" SaveSettings = "Save settings" LoadSettings = "Load settings" + SaveProject = "Save project" + SaveProjectAs = "Save project as..." SlicerInfo = "Slicer info" SlicerVersion = "Slicer version: " SlicingTitle = "Slicing" @@ -113,6 +115,8 @@ class Locale: ReportSubmitSuccessfully = "Report submit successfully. \nYou will be notified as soon as the problem is resolved. If necessary, our specialists will contact you for additional information. Thank you for helping us make the product better!" ErrorReport = "An error occurred while submitting the report" PlaceModelOnEdge = "Place the model on the edge" + SavingProject = "Saving the project" + ProjectSaved = "The project was successfully saved" ErrorHardwareModule = "Hardware module is unavailable in public" ErrorBugModule = "Bug reporting is unavailable in public" @@ -215,6 +219,8 @@ def __init__(self, **entries): Open = "Открыть", SaveSettings = "Сохранить настройки", LoadSettings = "Загрузить настройки", + SaveProject = "Сохранить проект", + SaveProjectAs = "Сохранить проект как...", SlicerInfo = "Информация о слайсере", SlicerVersion = "Версия слайсера: ", SlicingTitle = "Слайсинг", @@ -247,6 +253,8 @@ def __init__(self, **entries): ReportSubmitSuccessfully = "Отчет успешно отправлен. \nВы будете уведомлены, как только проблема будет устранена. При необходимости, наши специалисты свяжутся с вами для получения дополнительной информации. Благодарим Вас, что помогаете нам сделать продукт лучше!", ErrorReport = "Произошла ошибка при отправке отчета", PlaceModelOnEdge = "Положить модель на грань", + SavingProject = "Сохранение проекта", + ProjectSaved = "Проект успешно сохранен", ErrorHardwareModule = "Модуль калибровки недоступен публично", ErrorBugModule = "Модуль отправки багов недоступен публично", diff --git a/src/window.py b/src/window.py index f560bbc..765ce4c 100644 --- a/src/window.py +++ b/src/window.py @@ -126,6 +126,10 @@ def __init__(self, parent=None): # file_menu.addAction(close_action) self.save_gcode_action = QAction(self.locale.SaveGCode, self) + self.save_project_action = QAction(self.locale.SaveProject, self) + file_menu.addAction(self.save_project_action) + self.save_project_as_action = QAction(self.locale.SaveProjectAs, self) + file_menu.addAction(self.save_project_as_action) file_menu.addAction(self.save_gcode_action) self.save_sett_action = QAction(self.locale.SaveSettings, self) file_menu.addAction(self.save_sett_action) From 248de8768f74dcb176b3dc57e48c08886439e1fd Mon Sep 17 00:00:00 2001 From: LoneGit <100798196+LoneGit@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:11:14 +0300 Subject: [PATCH 4/4] fix: settings transfer (#128) --- src/entry_window.py | 10 ++++++++-- src/locales.py | 6 ++---- src/settings.py | 16 ++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/entry_window.py b/src/entry_window.py index e3f23f3..c7b6452 100644 --- a/src/entry_window.py +++ b/src/entry_window.py @@ -205,7 +205,8 @@ def open_existing_project(self): # add existing project to recent projects self.add_recent_project(selected_project) - self.сheck_project_version(selected_project) + if not self.сheck_project_version(selected_project): + return # emit signal with path to project file self.open_project_signal.emit(selected_project) @@ -225,7 +226,7 @@ def сheck_project_version(self, project_path): message_box.addButton(QMessageBox.Yes) message_box.addButton(QMessageBox.No) message_box.button(QMessageBox.Yes).setText(locale.Update) - message_box.button(QMessageBox.No).setText(locale.ContinueWithoutUpdating) + message_box.button(QMessageBox.No).setText(locale.Cancel) reply = message_box.exec() @@ -235,3 +236,8 @@ def сheck_project_version(self, project_path): shutil.copyfile("settings.yaml", project_settings_filename) paths_transfer_in_settings(project_settings_old_filename, project_settings_filename) set_version(project_settings_filename, build_version) + return True + + return False + + return True diff --git a/src/locales.py b/src/locales.py index 4265947..dba5eec 100644 --- a/src/locales.py +++ b/src/locales.py @@ -127,9 +127,8 @@ class Locale: DefaultPrinterWarn = "Be aware that you are using default printer. New data might be removed after update. We recommend to create new printer and calibrate it." CheckUpdates = "Check for updates" ProjectUpdate = "Project update" - SettingsUpdate = "The current project's settings are outdated. This may lead to errors in the program. Do you want to update? New setting's fields will be set to default values, please recheck." + SettingsUpdate = "We want to update the project settings. Please check the values of the new fields. They will be set to default values." Update = "Update" - ContinueWithoutUpdating = "Continue without updating" EmptyDescription = "The error description cannot be empty" def __init__(self, **entries): @@ -265,9 +264,8 @@ def __init__(self, **entries): DefaultPrinterWarn = "Будьте внимательны, Вы используете принтер по умолчанию. Данные этого принтера будут перезаписываться при обновлениях. Мы рекомендуем создать и использовать свою конфигурацию принтера.", CheckUpdates = "Проверить наличие обновлений", ProjectUpdate = "Обновление проекта", - SettingsUpdate = "Настройки текущего проекта устарели. Это может привести к ошибкам в работе программы. Хотите обновить? Новые поля настроек будут выставлены в значения по умолчанию, пожалуйста проверьте.", + SettingsUpdate = "Мы хотим обновить настройки проекта. Пожалуйста, проверьте значения новых полей. Они будут выставлены в значения по умолчанию.", Update = "Обновить", - ContinueWithoutUpdating = "Продолжить без обновления", EmptyDescription = "Описание ошибки не может быть пустым", ), } diff --git a/src/settings.py b/src/settings.py index 4cc8850..ec4370c 100644 --- a/src/settings.py +++ b/src/settings.py @@ -139,14 +139,14 @@ def paths_transfer_in_settings(initial_settings_filename, final_settings_filenam with open(final_settings_filename, "w") as settings_file: yaml.dump(final_settings, settings_file, default_flow_style=False) -def compare_settings(settings1, settings2): - for key in set(settings2): - if isinstance(settings2[key], dict): - compare_settings(settings1[key], settings2[key]) - else: - if key in settings1: - if not settings1[key] is None: - settings2[key] = settings1[key] +def compare_settings(initial_settings, final_settings): + for key in set(final_settings): + if key in initial_settings: + if isinstance(final_settings[key], dict): + compare_settings(initial_settings[key], final_settings[key]) + else: + if not initial_settings[key] is None: + final_settings[key] = initial_settings[key] class Settings(object): def __init__(self, d):