From e9fa6b96b942411309e9890da2796b1257760b85 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Sun, 30 Jul 2023 14:14:38 +0200 Subject: [PATCH 1/9] feat: add file stats sync task --- .../core/components/CoreTaskFactory.java | 14 ++- .../core/controllers/PluginsController.java | 6 ++ .../com/owlplug/core/dao/FileStatDAO.java | 33 ++++++ .../java/com/owlplug/core/model/FileStat.java | 100 ++++++++++++++++++ .../owlplug/core/services/PluginService.java | 4 + .../com/owlplug/core/tasks/FileSyncTask.java | 100 ++++++++++++++++++ .../src/main/resources/fxml/PluginsView.fxml | 9 ++ 7 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java create mode 100644 owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java create mode 100644 owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java index fde6e9e4..d1a81321 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java @@ -18,11 +18,13 @@ package com.owlplug.core.components; +import com.owlplug.core.dao.FileStatDAO; import com.owlplug.core.dao.PluginDAO; import com.owlplug.core.dao.PluginFootprintDAO; import com.owlplug.core.dao.SymlinkDAO; import com.owlplug.core.model.Plugin; import com.owlplug.core.services.NativeHostService; +import com.owlplug.core.tasks.FileSyncTask; import com.owlplug.core.tasks.PluginRemoveTask; import com.owlplug.core.tasks.PluginSyncTask; import com.owlplug.core.tasks.SimpleEventListener; @@ -49,6 +51,9 @@ public class CoreTaskFactory extends BaseTaskFactory { @Autowired private NativeHostService nativeHostService; + @Autowired + private FileStatDAO fileStatDAO; + private ArrayList syncPluginsListeners = new ArrayList<>(); @@ -89,7 +94,7 @@ public TaskExecutionContext createPluginSyncTask(String directoryScope) { parameters.setDirectoryScope(FileUtils.convertPath(directoryScope)); } - PluginSyncTask task = new PluginSyncTask(parameters, + PluginSyncTask task = new PluginSyncTask(parameters, pluginDAO, pluginFootprintDAO, symlinkDAO, @@ -100,6 +105,13 @@ public TaskExecutionContext createPluginSyncTask(String directoryScope) { }); return create(task); } + + public TaskExecutionContext createFileStatSyncTask() { + String directory = prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); + FileSyncTask task = new FileSyncTask(fileStatDAO, directory); + + return create(task); + } /** diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 06798ca0..f0139b23 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -73,6 +73,8 @@ public class PluginsController extends BaseController { @FXML private JFXButton syncButton; @FXML + private JFXButton fullSyncButton; + @FXML private JFXButton exportButton; @FXML private JFXTreeView pluginTreeView; @@ -165,6 +167,10 @@ public TreeCell call(TreeView p) { pluginService.syncPlugins(); }); + fullSyncButton.setOnAction(e -> { + pluginService.syncFiles(); + }); + taskFactory.addSyncPluginsListener(() -> clearAndFillPluginTree()); exportButton.setOnAction(e -> { diff --git a/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java new file mode 100644 index 00000000..9d66384d --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java @@ -0,0 +1,33 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + +package com.owlplug.core.dao; + +import com.owlplug.core.model.FileStat; +import jakarta.transaction.Transactional; +import java.util.List; +import org.springframework.data.repository.CrudRepository; + +public interface FileStatDAO extends CrudRepository { + + List findByParentPath(String parentPath); + + @Transactional + List deleteByPath(String path); + +} diff --git a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java new file mode 100644 index 00000000..3e4614e5 --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java @@ -0,0 +1,100 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + +package com.owlplug.core.model; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class FileStat { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + private String path; + + @OneToOne + @JoinColumn(name = "parent_id") + private FileStat parent; + + private String parentPath; + private long length; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) + private Set childs = new HashSet<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public FileStat getParent() { + return parent; + } + + public void setParent(FileStat parent) { + this.parent = parent; + } + + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public long getLength() { + return length; + } + + public void setLength(long length) { + this.length = length; + } +} diff --git a/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java b/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java index 80d1c94f..1541fbec 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java +++ b/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java @@ -56,6 +56,10 @@ public void syncPlugins() { taskFactory.createPluginSyncTask().schedule(); } + public void syncFiles() { + taskFactory.createFileStatSyncTask().schedule(); + } + public Iterable getAllPlugins() { return pluginDAO.findAll(); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java new file mode 100644 index 00000000..fc530381 --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java @@ -0,0 +1,100 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + +package com.owlplug.core.tasks; + +import com.owlplug.core.dao.FileStatDAO; +import com.owlplug.core.model.FileStat; +import java.io.File; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileSyncTask extends AbstractTask { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + private FileStatDAO fileStatDAO; + + private String directoryPath; + + public FileSyncTask(FileStatDAO fileStatDAO, String directoryPath) { + this.fileStatDAO = fileStatDAO; + this.directoryPath = directoryPath; + } + + + @Override + protected TaskResult call() throws Exception { + + log.info("Starting file sync task on directory {}", directoryPath); + this.updateProgress(1, 3); + + long length = 0; + try { + File directory = new File(directoryPath); + length = extractFolderSize(directory); + } catch (Exception e) { + log.error("An error occurred during file sync task execution", e); + throw new TaskException(e); + } + + log.info("Completed file sync task on directory {}, computed length: {}", directoryPath, length); + this.updateMessage("File sync task completed"); + this.updateProgress(3, 3); + + return success(); + } + + public long extractFolderSize(File directory) { + long length = 0; + + this.updateMessage("Running file sync on directory: " + directory.getAbsolutePath()); + fileStatDAO.deleteByPath(directory.getAbsolutePath()); + + FileStat directoryStat = new FileStat(); + directoryStat.setName(directory.getName()); + directoryStat.setPath(directory.getAbsolutePath()); + directoryStat.setParentPath(directory.getAbsolutePath()); + directoryStat.setLength(0); + fileStatDAO.save(directoryStat); + + // TODO, set directorStat parent object + + for (File file : directory.listFiles()) { + if (file.isFile()) { + FileStat fileStat = new FileStat(); + fileStat.setName(file.getName()); + fileStat.setPath(file.getAbsolutePath()); + fileStat.setParentPath(directory.getAbsolutePath()); + fileStat.setLength(file.length()); + fileStat.setParent(directoryStat); + + fileStatDAO.save(fileStat); + length += fileStat.getLength(); + + } else { + length += extractFolderSize(file); + } + } + + directoryStat.setLength(length); + fileStatDAO.save(directoryStat); + return length; + + } +} diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index 93b88345..ca85e7c6 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -76,6 +76,15 @@ + + + + + + + + + From 04943d540dbab3b22dd74c558e49ceb51b1d5de7 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 31 Jul 2023 22:36:28 +0200 Subject: [PATCH 2/9] feat: display pie chart on directory view --- .../controllers/DirectoryInfoController.java | 32 +++++++++++++++++++ .../com/owlplug/core/dao/FileStatDAO.java | 2 +- .../java/com/owlplug/core/model/FileStat.java | 23 +++++++------ .../com/owlplug/core/tasks/FileSyncTask.java | 26 +++++++++------ .../resources/fxml/DirectoryInfoView.fxml | 11 ++++--- 5 files changed, 69 insertions(+), 25 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index 9312b12c..832c2e8f 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -23,22 +23,31 @@ import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.controls.JFXListView; import com.owlplug.core.components.CoreTaskFactory; +import com.owlplug.core.dao.FileStatDAO; +import com.owlplug.core.model.FileStat; import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginDirectory; import com.owlplug.core.tasks.DirectoryRemoveTask; import com.owlplug.core.ui.PluginListCellFactory; import com.owlplug.core.utils.PlatformUtils; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXML; +import javafx.scene.chart.PieChart; import javafx.scene.control.Label; import javafx.scene.image.ImageView; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import java.util.List; + @Controller public class DirectoryInfoController extends BaseController { @Autowired private CoreTaskFactory taskFactory; + @Autowired + private FileStatDAO fileStatDAO; @FXML private Label directoryPathLabel; @@ -48,6 +57,8 @@ public class DirectoryInfoController extends BaseController { private JFXButton openDirectoryButton; @FXML private JFXButton deleteDirectoryButton; + @FXML + private PieChart pieChart; private PluginDirectory pluginDirectory; @@ -90,12 +101,33 @@ public void initialize() { dialog.setContent(layout); dialog.show(); }); + + pieChart.setLegendVisible(false); } public void setPluginDirectory(PluginDirectory pluginDirectory) { this.pluginDirectory = pluginDirectory; directoryPathLabel.setText(pluginDirectory.getPath()); pluginDirectoryListView.getItems().setAll(pluginDirectory.getPluginList()); + + String path = pluginDirectory.getPath(); + if (path.endsWith("/")) { + path = path.substring(0,path.length() - 1); + } + + List fileStats = fileStatDAO.findByParentPathOrderByLengthDesc(path); + + ObservableList chartData = FXCollections.observableArrayList(); + + for (FileStat fileStat : fileStats) { + System.out.println(fileStat.getName().toString()); + chartData.add(new PieChart.Data(fileStat.getName() + " - " + fileStat.getLengthHumanReadable(), + fileStat.getLength())); + } + + pieChart.setData(chartData); + pieChart.layout(); + } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java index 9d66384d..15d2770b 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java +++ b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java @@ -25,7 +25,7 @@ public interface FileStatDAO extends CrudRepository { - List findByParentPath(String parentPath); + List findByParentPathOrderByLengthDesc(String parentPath); @Transactional List deleteByPath(String path); diff --git a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java index 3e4614e5..45b6549d 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java +++ b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java @@ -18,14 +18,8 @@ package com.owlplug.core.model; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; +import jakarta.persistence.*; + import java.util.HashSet; import java.util.Set; @@ -40,13 +34,15 @@ public class FileStat { private String path; - @OneToOne + @ManyToOne @JoinColumn(name = "parent_id") private FileStat parent; private String parentPath; private long length; + private String lengthHumanReadable; + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) private Set childs = new HashSet<>(); @@ -97,4 +93,13 @@ public long getLength() { public void setLength(long length) { this.length = length; } + + public String getLengthHumanReadable() { + return lengthHumanReadable; + } + + public void setLengthHumanReadable(String lengthHumanReadable) { + this.lengthHumanReadable = lengthHumanReadable; + } + } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java index fc530381..83a16f72 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java @@ -21,6 +21,8 @@ import com.owlplug.core.dao.FileStatDAO; import com.owlplug.core.model.FileStat; import java.io.File; + +import com.owlplug.core.utils.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +49,7 @@ protected TaskResult call() throws Exception { long length = 0; try { File directory = new File(directoryPath); - length = extractFolderSize(directory); + length = extractFolderSize(directory, null); } catch (Exception e) { log.error("An error occurred during file sync task execution", e); throw new TaskException(e); @@ -60,39 +62,43 @@ protected TaskResult call() throws Exception { return success(); } - public long extractFolderSize(File directory) { + public long extractFolderSize(File directory, FileStat parent) { long length = 0; this.updateMessage("Running file sync on directory: " + directory.getAbsolutePath()); - fileStatDAO.deleteByPath(directory.getAbsolutePath()); + fileStatDAO.deleteByPath(FileUtils.convertPath(directory.getAbsolutePath())); FileStat directoryStat = new FileStat(); directoryStat.setName(directory.getName()); - directoryStat.setPath(directory.getAbsolutePath()); - directoryStat.setParentPath(directory.getAbsolutePath()); + directoryStat.setPath(FileUtils.convertPath(directory.getAbsolutePath())); + + if(parent != null) { + directoryStat.setParentPath(parent.getPath()); + directoryStat.setParent(parent); + } directoryStat.setLength(0); fileStatDAO.save(directoryStat); - // TODO, set directorStat parent object - for (File file : directory.listFiles()) { if (file.isFile()) { FileStat fileStat = new FileStat(); fileStat.setName(file.getName()); - fileStat.setPath(file.getAbsolutePath()); - fileStat.setParentPath(directory.getAbsolutePath()); + fileStat.setPath(FileUtils.convertPath(file.getAbsolutePath())); + fileStat.setParentPath(FileUtils.convertPath(directory.getAbsolutePath())); fileStat.setLength(file.length()); + fileStat.setLengthHumanReadable(FileUtils.humanReadableByteCount(file.length(), true)); fileStat.setParent(directoryStat); fileStatDAO.save(fileStat); length += fileStat.getLength(); } else { - length += extractFolderSize(file); + length += extractFolderSize(file, directoryStat); } } directoryStat.setLength(length); + directoryStat.setLengthHumanReadable(FileUtils.humanReadableByteCount(length, true)); fileStatDAO.save(directoryStat); return length; diff --git a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml index ccc6db0c..4203c4f3 100644 --- a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml +++ b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml @@ -1,13 +1,13 @@ - - + + - + - + @@ -44,11 +44,12 @@ - + + From fe321033245feb32c7bc4d108035ade4209188b2 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Fri, 4 Aug 2023 17:45:26 +0200 Subject: [PATCH 3/9] feat: improve filestat chart display with legend and grouping --- .../controllers/DirectoryInfoController.java | 60 +++++++++++++++++-- .../java/com/owlplug/core/model/FileStat.java | 10 ---- .../com/owlplug/core/tasks/FileSyncTask.java | 2 - .../resources/fxml/DirectoryInfoView.fxml | 16 ++--- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index 832c2e8f..a5f0fd0b 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -29,17 +29,23 @@ import com.owlplug.core.model.PluginDirectory; import com.owlplug.core.tasks.DirectoryRemoveTask; import com.owlplug.core.ui.PluginListCellFactory; +import com.owlplug.core.utils.FileUtils; import com.owlplug.core.utils.PlatformUtils; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; +import javafx.scene.Node; import javafx.scene.chart.PieChart; import javafx.scene.control.Label; import javafx.scene.image.ImageView; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import java.util.List; +import java.util.Optional; @Controller public class DirectoryInfoController extends BaseController { @@ -58,6 +64,8 @@ public class DirectoryInfoController extends BaseController { @FXML private JFXButton deleteDirectoryButton; @FXML + private VBox pieChartContainer; + private PieChart pieChart; private PluginDirectory pluginDirectory; @@ -102,7 +110,27 @@ public void initialize() { dialog.show(); }); - pieChart.setLegendVisible(false); + pieChart = new PieChart() { + @Override + protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) { + if (getLabelsVisible()) { + getData().forEach(d -> { + Optional opTextNode = this.lookupAll(".chart-pie-label").stream().filter( + n -> n instanceof Text && ((Text) n).getText().equals(d.getName())).findAny(); + if (opTextNode.isPresent()) { + String label = ellipsisString(d.getName(), 15, 3) + + " - " + FileUtils.humanReadableByteCount((long) d.getPieValue(), true); + ((Text) opTextNode.get()).setText(label); + } + }); + } + super.layoutChartChildren(top, left, contentWidth, contentHeight); + } + }; + + pieChartContainer.getChildren().add(pieChart); + VBox.setVgrow(pieChart, Priority.ALWAYS); + } public void setPluginDirectory(PluginDirectory pluginDirectory) { @@ -112,17 +140,27 @@ public void setPluginDirectory(PluginDirectory pluginDirectory) { String path = pluginDirectory.getPath(); if (path.endsWith("/")) { - path = path.substring(0,path.length() - 1); + path = path.substring(0, path.length() - 1); } List fileStats = fileStatDAO.findByParentPathOrderByLengthDesc(path); ObservableList chartData = FXCollections.observableArrayList(); - for (FileStat fileStat : fileStats) { - System.out.println(fileStat.getName().toString()); - chartData.add(new PieChart.Data(fileStat.getName() + " - " + fileStat.getLengthHumanReadable(), - fileStat.getLength())); + int i = 0; + int maxBucket = 8; + while (i < fileStats.size() && i < maxBucket) { + chartData.add(new PieChart.Data(fileStats.get(i).getName(), fileStats.get(i).getLength())); + i = i + 1; + } + + if (i < fileStats.size()) { + long groupLength = 0; + while (i < fileStats.size()) { + groupLength += fileStats.get(i).getLength(); + i = i + 1; + } + chartData.add(new PieChart.Data("Others", groupLength)); } pieChart.setData(chartData); @@ -130,4 +168,14 @@ public void setPluginDirectory(PluginDirectory pluginDirectory) { } + private String ellipsisString(String input, int maxLength, int clearEndLength) { + if (input == null || input.length() <= maxLength + || clearEndLength >= maxLength) { + return input; + } else { + String truncatedString = input.substring(0, maxLength - clearEndLength); + return truncatedString + "..." + input.substring(input.length() - clearEndLength); + } + } + } diff --git a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java index 45b6549d..648868b3 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java +++ b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java @@ -41,8 +41,6 @@ public class FileStat { private String parentPath; private long length; - private String lengthHumanReadable; - @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) private Set childs = new HashSet<>(); @@ -94,12 +92,4 @@ public void setLength(long length) { this.length = length; } - public String getLengthHumanReadable() { - return lengthHumanReadable; - } - - public void setLengthHumanReadable(String lengthHumanReadable) { - this.lengthHumanReadable = lengthHumanReadable; - } - } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java index 83a16f72..413817b5 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java @@ -86,7 +86,6 @@ public long extractFolderSize(File directory, FileStat parent) { fileStat.setPath(FileUtils.convertPath(file.getAbsolutePath())); fileStat.setParentPath(FileUtils.convertPath(directory.getAbsolutePath())); fileStat.setLength(file.length()); - fileStat.setLengthHumanReadable(FileUtils.humanReadableByteCount(file.length(), true)); fileStat.setParent(directoryStat); fileStatDAO.save(fileStat); @@ -98,7 +97,6 @@ public long extractFolderSize(File directory, FileStat parent) { } directoryStat.setLength(length); - directoryStat.setLengthHumanReadable(FileUtils.humanReadableByteCount(length, true)); fileStatDAO.save(directoryStat); return length; diff --git a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml index 4203c4f3..008ab588 100644 --- a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml +++ b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml @@ -2,12 +2,11 @@ - - + @@ -20,21 +19,22 @@ - + - + - + + - + @@ -44,12 +44,12 @@ - + - + From 3fff6a472bb283a55b1520210ca024bbf0087619 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Fri, 4 Aug 2023 18:21:56 +0200 Subject: [PATCH 4/9] feat: update filestat chart style and colors --- .../controllers/DirectoryInfoController.java | 3 +-- owlplug-client/src/main/resources/owlplug.css | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index a5f0fd0b..bda77bc9 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -144,11 +144,10 @@ public void setPluginDirectory(PluginDirectory pluginDirectory) { } List fileStats = fileStatDAO.findByParentPathOrderByLengthDesc(path); - ObservableList chartData = FXCollections.observableArrayList(); int i = 0; - int maxBucket = 8; + int maxBucket = 7; while (i < fileStats.size() && i < maxBucket) { chartData.add(new PieChart.Data(fileStats.get(i).getName(), fileStats.get(i).getLength())); i = i + 1; diff --git a/owlplug-client/src/main/resources/owlplug.css b/owlplug-client/src/main/resources/owlplug.css index 4c804e6b..5d0f3419 100644 --- a/owlplug-client/src/main/resources/owlplug.css +++ b/owlplug-client/src/main/resources/owlplug.css @@ -450,6 +450,28 @@ ProgressIndicator{ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 0); } + +/**************************************************************** + JavaFx Charts theme +****************************************************************/ + +.default-color0.chart-pie { -fx-pie-color: #116A7B; } +.default-color1.chart-pie { -fx-pie-color: #85586F; } +.default-color2.chart-pie { -fx-pie-color: #7F8B52; } +.default-color3.chart-pie { -fx-pie-color: #FFDBA4; } +.default-color4.chart-pie { -fx-pie-color: #47A992; } +.default-color5.chart-pie { -fx-pie-color: #C84B31; } +.default-color6.chart-pie { -fx-pie-color: #BCCC9A; } +.default-color7.chart-pie { -fx-pie-color: #968C83; } + +.chart-pie { + -fx-border-width: 0px; +} + +.chart-legend { + -fx-background-color: card-pane-color; +} + /**************************************************************** * * Utilities From c0b5a216962d4553b1d40b623ad706c9100ae375 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Sat, 5 Aug 2023 13:19:17 +0200 Subject: [PATCH 5/9] feat: add doughnut chart ui component --- .../controllers/DirectoryInfoController.java | 3 +- .../com/owlplug/core/ui/DoughnutChart.java | 69 +++++++++++++++++++ owlplug-client/src/main/resources/owlplug.css | 4 ++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index bda77bc9..9b727429 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -28,6 +28,7 @@ import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginDirectory; import com.owlplug.core.tasks.DirectoryRemoveTask; +import com.owlplug.core.ui.DoughnutChart; import com.owlplug.core.ui.PluginListCellFactory; import com.owlplug.core.utils.FileUtils; import com.owlplug.core.utils.PlatformUtils; @@ -110,7 +111,7 @@ public void initialize() { dialog.show(); }); - pieChart = new PieChart() { + pieChart = new DoughnutChart() { @Override protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) { if (getLabelsVisible()) { diff --git a/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java b/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java new file mode 100644 index 00000000..98b9dfff --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java @@ -0,0 +1,69 @@ +package com.owlplug.core.ui; + +import javafx.collections.ObservableList; +import javafx.geometry.Bounds; +import javafx.scene.Node; +import javafx.scene.chart.PieChart; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; + +public class DoughnutChart extends PieChart { + private final Circle innerCircle; + + public DoughnutChart() { + super(); + + innerCircle = new Circle(); + innerCircle.getStyleClass().add("doughnut-inner-circle"); + } + + @Override + protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) { + super.layoutChartChildren(top, left, contentWidth, contentHeight); + + addInnerCircleIfNotPresent(); + updateInnerCircleLayout(); + } + + private void addInnerCircleIfNotPresent() { + if (getData().size() > 0) { + Node pie = getData().get(0).getNode(); + if (pie.getParent() instanceof Pane) { + Pane parent = (Pane) pie.getParent(); + + if (!parent.getChildren().contains(innerCircle)) { + parent.getChildren().add(innerCircle); + } + } + } + } + + private void updateInnerCircleLayout() { + double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE; + double maxX = Double.MIN_VALUE, maxY = Double.MIN_VALUE; + for (PieChart.Data data: getData()) { + Node node = data.getNode(); + + Bounds bounds = node.getBoundsInParent(); + if (bounds.getMinX() < minX) { + minX = bounds.getMinX(); + } + if (bounds.getMinY() < minY) { + minY = bounds.getMinY(); + } + if (bounds.getMaxX() > maxX) { + maxX = bounds.getMaxX(); + } + if (bounds.getMaxY() > maxY) { + maxY = bounds.getMaxY(); + } + } + + innerCircle.setCenterX(minX + (maxX - minX) / 2); + innerCircle.setCenterY(minY + (maxY - minY) / 2); + + innerCircle.setRadius((maxX - minX) / 4); + innerCircle.toFront(); + } +} \ No newline at end of file diff --git a/owlplug-client/src/main/resources/owlplug.css b/owlplug-client/src/main/resources/owlplug.css index 5d0f3419..dd37f9bd 100644 --- a/owlplug-client/src/main/resources/owlplug.css +++ b/owlplug-client/src/main/resources/owlplug.css @@ -472,6 +472,10 @@ ProgressIndicator{ -fx-background-color: card-pane-color; } +.doughnut-inner-circle { + -fx-fill: card-pane-color; +} + /**************************************************************** * * Utilities From c0bbd15b7bb23958311aabee8d9762dc38844789 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Tue, 8 Aug 2023 00:03:09 +0200 Subject: [PATCH 6/9] feat: run FileSync after PluginSync tasks --- .../core/components/CoreTaskFactory.java | 33 +++++++++++++- .../controllers/DirectoryInfoController.java | 7 ++- .../core/controllers/PluginsController.java | 6 --- .../java/com/owlplug/core/model/FileStat.java | 10 ++++- .../com/owlplug/core/tasks/FileSyncTask.java | 43 ++++++++++++------- .../com/owlplug/core/ui/DoughnutChart.java | 30 ++++++++++--- .../src/main/resources/fxml/PluginsView.fxml | 9 ---- 7 files changed, 92 insertions(+), 46 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java index d1a81321..ce0402f7 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java @@ -32,6 +32,8 @@ import com.owlplug.core.tasks.plugins.discovery.PluginSyncTaskParameters; import com.owlplug.core.utils.FileUtils; import java.util.ArrayList; +import java.util.Set; +import java.util.TreeSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -102,14 +104,41 @@ public TaskExecutionContext createPluginSyncTask(String directoryScope) { task.setOnSucceeded(e -> { notifyListeners(syncPluginsListeners); + if (directoryScope != null) { + createFileStatSyncTask(directoryScope).scheduleNow(); + } else { + createFileStatSyncTask().scheduleNow(); + } }); return create(task); } public TaskExecutionContext createFileStatSyncTask() { - String directory = prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); - FileSyncTask task = new FileSyncTask(fileStatDAO, directory); + Set directorySet = new TreeSet<>(); + if (prefs.getBoolean(ApplicationDefaults.VST2_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, "")); + directorySet.addAll(prefs.getList(ApplicationDefaults.VST2_EXTRA_DIRECTORY_KEY)); + } + if (prefs.getBoolean(ApplicationDefaults.VST3_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, "")); + directorySet.addAll(prefs.getList(ApplicationDefaults.VST3_EXTRA_DIRECTORY_KEY)); + } + if (prefs.getBoolean(ApplicationDefaults.AU_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, "")); + directorySet.addAll(prefs.getList(ApplicationDefaults.AU_EXTRA_DIRECTORY_KEY)); + } + if (prefs.getBoolean(ApplicationDefaults.LV2_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, "")); + directorySet.addAll(prefs.getList(ApplicationDefaults.LV2_EXTRA_DIRECTORY_KEY)); + } + FileSyncTask task = new FileSyncTask(fileStatDAO, directorySet.stream().toList()); + + return create(task); + } + + public TaskExecutionContext createFileStatSyncTask(String directoryScope) { + FileSyncTask task = new FileSyncTask(fileStatDAO, directoryScope); return create(task); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index 9b727429..ce1514b8 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -32,6 +32,8 @@ import com.owlplug.core.ui.PluginListCellFactory; import com.owlplug.core.utils.FileUtils; import com.owlplug.core.utils.PlatformUtils; +import java.util.List; +import java.util.Optional; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; @@ -45,9 +47,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import java.util.List; -import java.util.Optional; - @Controller public class DirectoryInfoController extends BaseController { @@ -102,7 +101,7 @@ public void initialize() { dialog.close(); taskFactory.create(new DirectoryRemoveTask(pluginDirectory)) .setOnSucceeded(x -> taskFactory.createPluginSyncTask(pluginDirectory.getPath()).schedule()) - .schedule(); + .schedule(); }); removeButton.getStyleClass().add("button-danger"); diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index f0139b23..06798ca0 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -73,8 +73,6 @@ public class PluginsController extends BaseController { @FXML private JFXButton syncButton; @FXML - private JFXButton fullSyncButton; - @FXML private JFXButton exportButton; @FXML private JFXTreeView pluginTreeView; @@ -167,10 +165,6 @@ public TreeCell call(TreeView p) { pluginService.syncPlugins(); }); - fullSyncButton.setOnAction(e -> { - pluginService.syncFiles(); - }); - taskFactory.addSyncPluginsListener(() -> clearAndFillPluginTree()); exportButton.setOnAction(e -> { diff --git a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java index 648868b3..ac0483cc 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java +++ b/owlplug-client/src/main/java/com/owlplug/core/model/FileStat.java @@ -18,8 +18,14 @@ package com.owlplug.core.model; -import jakarta.persistence.*; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.util.HashSet; import java.util.Set; diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java index 413817b5..0a81a50f 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/FileSyncTask.java @@ -20,9 +20,12 @@ import com.owlplug.core.dao.FileStatDAO; import com.owlplug.core.model.FileStat; -import java.io.File; - import com.owlplug.core.utils.FileUtils; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,33 +35,41 @@ public class FileSyncTask extends AbstractTask { private FileStatDAO fileStatDAO; - private String directoryPath; + private List directories; public FileSyncTask(FileStatDAO fileStatDAO, String directoryPath) { this.fileStatDAO = fileStatDAO; - this.directoryPath = directoryPath; + directories = Arrays.asList(directoryPath); + } + + public FileSyncTask(FileStatDAO fileStatDAO, List directories) { + this.fileStatDAO = fileStatDAO; + this.directories = directories; } @Override protected TaskResult call() throws Exception { - log.info("Starting file sync task on directory {}", directoryPath); this.updateProgress(1, 3); long length = 0; - try { - File directory = new File(directoryPath); - length = extractFolderSize(directory, null); - } catch (Exception e) { - log.error("An error occurred during file sync task execution", e); - throw new TaskException(e); + for (String directoryPath : directories) { + try { + log.info("Starting file sync task on directory {}", directoryPath); + File directory = new File(directoryPath); + if (directory.exists() && directory.isDirectory()) { + length = extractFolderSize(directory, null); + log.info("Completed file sync task on directory {}, computed length: {}", directoryPath, length); + } + + } catch (Exception e) { + log.error("An error occurred during file sync task execution", e); + throw new TaskException(e); + } } - - log.info("Completed file sync task on directory {}, computed length: {}", directoryPath, length); - this.updateMessage("File sync task completed"); + this.updateMessage("Plugin and file sync task completed"); this.updateProgress(3, 3); - return success(); } @@ -72,7 +83,7 @@ public long extractFolderSize(File directory, FileStat parent) { directoryStat.setName(directory.getName()); directoryStat.setPath(FileUtils.convertPath(directory.getAbsolutePath())); - if(parent != null) { + if (parent != null) { directoryStat.setParentPath(parent.getPath()); directoryStat.setParent(parent); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java b/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java index 98b9dfff..40b5b1db 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java +++ b/owlplug-client/src/main/java/com/owlplug/core/ui/DoughnutChart.java @@ -1,6 +1,23 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + package com.owlplug.core.ui; -import javafx.collections.ObservableList; import javafx.geometry.Bounds; import javafx.scene.Node; import javafx.scene.chart.PieChart; @@ -29,9 +46,7 @@ protected void layoutChartChildren(double top, double left, double contentWidth, private void addInnerCircleIfNotPresent() { if (getData().size() > 0) { Node pie = getData().get(0).getNode(); - if (pie.getParent() instanceof Pane) { - Pane parent = (Pane) pie.getParent(); - + if (pie.getParent() instanceof Pane parent) { if (!parent.getChildren().contains(innerCircle)) { parent.getChildren().add(innerCircle); } @@ -40,8 +55,10 @@ private void addInnerCircleIfNotPresent() { } private void updateInnerCircleLayout() { - double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE; - double maxX = Double.MIN_VALUE, maxY = Double.MIN_VALUE; + double minX = Double.MAX_VALUE; + double minY = Double.MAX_VALUE; + double maxX = Double.MIN_VALUE; + double maxY = Double.MIN_VALUE; for (PieChart.Data data: getData()) { Node node = data.getNode(); @@ -62,7 +79,6 @@ private void updateInnerCircleLayout() { innerCircle.setCenterX(minX + (maxX - minX) / 2); innerCircle.setCenterY(minY + (maxY - minY) / 2); - innerCircle.setRadius((maxX - minX) / 4); innerCircle.toFront(); } diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index ca85e7c6..93b88345 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -76,15 +76,6 @@ - - - - - - - - - From 061e00e13206c8df51b4175a72a1425c239239f6 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Fri, 11 Aug 2023 14:44:25 +0200 Subject: [PATCH 7/9] feat: display directory metrics in info view --- .../controllers/DirectoryInfoController.java | 15 ++++++++- .../com/owlplug/core/dao/FileStatDAO.java | 2 ++ .../resources/fxml/DirectoryInfoView.fxml | 30 +++++++++++++----- .../main/resources/icons/chart-white-16.png | Bin 0 -> 192 bytes .../main/resources/icons/share-white-16.png | Bin 0 -> 269 bytes 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 owlplug-client/src/main/resources/icons/chart-white-16.png create mode 100644 owlplug-client/src/main/resources/icons/share-white-16.png diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java index ce1514b8..025528bd 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/DirectoryInfoController.java @@ -32,6 +32,7 @@ import com.owlplug.core.ui.PluginListCellFactory; import com.owlplug.core.utils.FileUtils; import com.owlplug.core.utils.PlatformUtils; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import javafx.collections.FXCollections; @@ -58,6 +59,8 @@ public class DirectoryInfoController extends BaseController { @FXML private Label directoryPathLabel; @FXML + private Label directoryMetricsLabel; + @FXML private JFXListView pluginDirectoryListView; @FXML private JFXButton openDirectoryButton; @@ -75,7 +78,6 @@ public class DirectoryInfoController extends BaseController { */ public void initialize() { - openDirectoryButton.setGraphic(new ImageView(this.getApplicationDefaults().directoryImage)); openDirectoryButton.setOnAction(e -> { PlatformUtils.openDirectoryExplorer(pluginDirectory.getPath()); }); @@ -138,12 +140,23 @@ public void setPluginDirectory(PluginDirectory pluginDirectory) { directoryPathLabel.setText(pluginDirectory.getPath()); pluginDirectoryListView.getItems().setAll(pluginDirectory.getPluginList()); + String path = pluginDirectory.getPath(); if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } + List directoryMetrics = new ArrayList<>(); + Optional directoryStat = fileStatDAO.findByPath(path); + directoryStat.ifPresent(fileStat -> directoryMetrics.add( + FileUtils.humanReadableByteCount(fileStat.getLength(), true))); + directoryMetrics.add(pluginDirectory.getPluginList().size() + " plugin(s)"); + List fileStats = fileStatDAO.findByParentPathOrderByLengthDesc(path); + directoryMetrics.add(fileStats.size() + " file(s)"); + + directoryMetricsLabel.setText(String.join(" | ", directoryMetrics)); + ObservableList chartData = FXCollections.observableArrayList(); int i = 0; diff --git a/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java index 15d2770b..68a22f67 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java +++ b/owlplug-client/src/main/java/com/owlplug/core/dao/FileStatDAO.java @@ -21,10 +21,12 @@ import com.owlplug.core.model.FileStat; import jakarta.transaction.Transactional; import java.util.List; +import java.util.Optional; import org.springframework.data.repository.CrudRepository; public interface FileStatDAO extends CrudRepository { + Optional findByPath(String path); List findByParentPathOrderByLengthDesc(String parentPath); @Transactional diff --git a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml index 008ab588..b605ef1c 100644 --- a/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml +++ b/owlplug-client/src/main/resources/fxml/DirectoryInfoView.fxml @@ -6,9 +6,9 @@ - + - +