diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 986382f5..fa5c1fdf 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,6 +13,7 @@ on: jobs: create_release: + permissions: write-all name: Create release runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index d7ab5275..1f76021d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # uPMT: micro Phenomenology Modelling Tool +GitHub page for this project: https://yprie.github.io/uPMT/ + uPMT is aimed at researchers using microphenomenology interviews (also know as explicitation interviews) to study lived experience. It has been designed to help analyze the micro-dynamics of experience as described in interview transcriptions, by modelling and formalizing the sequential unfolding of "experience moments" described with categories and properties, and linked to the descriptemes - excerpts of the transcript - that justify them. Current work is carried out by Gabriel Jolly, Thomas Clouet and Célian Rolland. Past developers were Yves Motteux and Esteban Jamin (20-21), Xavier Tremillon, Yahuan Chen and Nathan Seva (19-20), Gwenaelle Gouriten, Salma Hichami and Othman Houmair (18-19), and Mehdi Haddad, Eva Boon and Yinxing Huang (17-18), under the supervision of Yannick Prié. The first version of the software was implemented by Corentin Jezequel in late 2017, under the supervision of Yannick Prié and Thomas Rabeyron. diff --git a/src/main/java/application/UPMTApp.java b/src/main/java/application/UPMTApp.java index 359e64fa..45885614 100644 --- a/src/main/java/application/UPMTApp.java +++ b/src/main/java/application/UPMTApp.java @@ -9,9 +9,9 @@ import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; +import javafx.application.Platform; import models.Project; import utils.GlobalVariables; - import java.io.IOException; import java.util.UUID; @@ -21,16 +21,21 @@ public class UPMTApp { private Stage primaryStage; private RootLayoutController rootLayoutController; private ApplicationCommandFactory appCommandFactory; - private Project currentProject; + private static Project currentProject; private String currentProjectPath; private UUID lastSavedCommandId; + private long autoSaveIntervalMillis; + + public UPMTApp(Stage primaryStage) throws IOException { this.primaryStage = primaryStage; this.appCommandFactory = new ApplicationCommandFactory(this); this.rootLayoutController = new RootLayoutController(appCommandFactory); + this.autoSaveIntervalMillis = 10000; + Configuration.loadAppConfiguration(); HistoryManager.init(appCommandFactory); @@ -54,6 +59,7 @@ public UPMTApp(Stage primaryStage) throws IOException { appCommandFactory.openProjectManagerCommand().execute(); } + startAutoSave(); FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/views/MainView/MainView.fxml")); @@ -63,6 +69,7 @@ public UPMTApp(Stage primaryStage) throws IOException { } + public Stage getPrimaryStage() { return primaryStage; } @@ -73,7 +80,7 @@ public void setCurrentProject(Project project, String path) { GlobalVariables.setCurrentProjectPath(currentProjectPath); rootLayoutController.setProject(project); } - public Project getCurrentProject() { + public static Project getCurrentProject() { return currentProject; } public String getCurrentProjectPath() { return currentProjectPath; } @@ -87,5 +94,30 @@ public void restartApp() { if(getCurrentProject() != null) setCurrentProject(getCurrentProject(), currentProjectPath); } - + + public void startAutoSave() { + if (currentProject != null) { + // Créez et démarrez un nouveau thread pour la sauvegarde automatique + Thread autoSaveThread = new Thread(() -> { + while (true) { + try { + // Effectuez la sauvegarde automatique + //currentProject.saveAs("auto_save", getCurrentProjectPath()); + + // Utilisez Platform.runLater() pour exécuter l'opération sur le thread de l'interface utilisateur + Platform.runLater(() -> appCommandFactory.saveProject().execute()); + + // Pause pour l'intervalle spécifié + Thread.sleep(autoSaveIntervalMillis); + } catch (InterruptedException e) { + e.printStackTrace(); + // Gérer les exceptions si nécessaire + } + } + }); + autoSaveThread.setDaemon(true); // Le thread s'exécutera en arrière-plan et se terminera lorsque le programme principal se termine + autoSaveThread.start(); + } + } + } \ No newline at end of file diff --git a/src/main/java/application/appCommands/CloseApplicationCommand.java b/src/main/java/application/appCommands/CloseApplicationCommand.java index 90e02b83..e5b8f83b 100644 --- a/src/main/java/application/appCommands/CloseApplicationCommand.java +++ b/src/main/java/application/appCommands/CloseApplicationCommand.java @@ -33,7 +33,6 @@ public CloseApplicationCommand(ApplicationCommandFactory appCommandFactory, UPMT @Override public Void execute() { - boolean workUnsaved = false; String currentTitle = upmtApp.getPrimaryStage().getTitle(); UUID currentCommandId = HistoryManager.getCurrentCommandId(); @@ -54,7 +53,8 @@ public Void execute() { } } } - if(workUnsaved) { + + if (upmtApp.getCurrentProjectPath() == null) { Alert alert = new Alert(AlertType.CONFIRMATION); alert.setHeaderText(""); alert.setTitle(Configuration.langBundle.getString("alert_unsaved_project_title")); @@ -70,7 +70,7 @@ public Void execute() { Optional result = alert.showAndWait(); if (result.get() == buttonTypeOne){ - // ... user chose "Save And Quit" + // ... user chose "Save And Quit" appCommandFactory.saveProject().execute(); System.exit(0); } else if (result.get() == buttonTypeTwo) { @@ -85,6 +85,7 @@ public Void execute() { } } else { System.exit(0); + appCommandFactory.saveProject().execute(); } return null; diff --git a/src/main/java/application/appCommands/SaveProjectCommand.java b/src/main/java/application/appCommands/SaveProjectCommand.java index ca7fe7b3..7ab67e94 100644 --- a/src/main/java/application/appCommands/SaveProjectCommand.java +++ b/src/main/java/application/appCommands/SaveProjectCommand.java @@ -21,6 +21,8 @@ public Void execute() { ProjectSaver.save(upmtApp.getCurrentProject(), Configuration.getProjectsPath()[0]); upmtApp.setLastSavedCommandId(HistoryManager.getCurrentCommandId()); new ProjectSavingStatusChangedCommand(upmtApp).execute(); + System.out.println("Projet saved"); + } catch (Exception e) { ProjectDialogBox.projectSavingFailed(); e.printStackTrace(); diff --git a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java index 5e642b32..f4d17253 100644 --- a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java +++ b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java @@ -16,6 +16,7 @@ import javafx.scene.layout.Pane; import models.SchemaCategory; import models.SchemaFolder; +import utils.GlobalVariables; import utils.ResourceLoader; import utils.GlobalVariables; import utils.autoSuggestion.AutoSuggestionsTextField; @@ -82,13 +83,12 @@ public void initialize(URL url, ResourceBundle resourceBundle) { } }); - Platform.runLater(() -> { - if (element.mustBeRenamed()) + Platform.runLater(()-> { + if(element.mustBeRenamed()) passInRenamingMode(true, true); }); - } public void passInRenamingMode(boolean YoN,boolean deleteIfUnavailable) { if(YoN != renamingMode) { if(YoN){ @@ -107,7 +107,8 @@ public void passInRenamingMode(boolean YoN,boolean deleteIfUnavailable) { if(keyEvent.getCode() == KeyCode.ENTER) { if(renamingField.getLength() > 0){ for (SchemaFolder folder : GlobalVariables.getSchemaTreeRoot().foldersProperty() - ) { + + ) { for (SchemaCategory category : folder.categoriesProperty() ) { if (renamingField.getText().equals(name.getText())){ @@ -169,6 +170,7 @@ public void passInRenamingMode(boolean YoN,boolean deleteIfUnavailable) { } } + public void setOnHover(boolean YoN) { if (optionsMenu.isShowing()) shouldRemoveMenuButtonVisibility = true; diff --git a/src/main/java/models/ConcreteCategory.java b/src/main/java/models/ConcreteCategory.java index d5995c2c..4360a6f8 100644 --- a/src/main/java/models/ConcreteCategory.java +++ b/src/main/java/models/ConcreteCategory.java @@ -1,5 +1,6 @@ package models; +import application.UPMTApp; import components.modelisationSpace.category.controllers.ConcreteCategoryController; import components.modelisationSpace.property.appCommands.AddConcretePropertyCommand; import components.modelisationSpace.property.appCommands.RemoveConcretePropertyCommand; diff --git a/src/main/java/models/Project.java b/src/main/java/models/Project.java index 0d59a457..688f3eef 100644 --- a/src/main/java/models/Project.java +++ b/src/main/java/models/Project.java @@ -38,6 +38,7 @@ public Project(String name, SchemaTreeRoot baseScheme) { this.momentTypeControllers = new LinkedList<>(); globalVariables.setProject(this); + } public String getName() { return this.name.get(); }