backup config
This commit is contained in:
parent
4624e9f8d4
commit
e72f9d602f
@ -51,6 +51,25 @@ public class AppConfig {
|
|||||||
System.err.println("Could not save configuration: " + e.getMessage());
|
System.err.println("Could not save configuration: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export current configuration to a specified file
|
||||||
|
*/
|
||||||
|
public void exportConfig(File targetFile) throws IOException {
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(targetFile)) {
|
||||||
|
properties.store(fos, "KF File Manager Exported Configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import configuration from a specified file
|
||||||
|
*/
|
||||||
|
public void importConfig(File sourceFile) throws IOException {
|
||||||
|
try (FileInputStream fis = new FileInputStream(sourceFile)) {
|
||||||
|
properties.load(fis);
|
||||||
|
}
|
||||||
|
saveConfig(); // Persist imported settings
|
||||||
|
}
|
||||||
|
|
||||||
// Getters and setters for individual configuration values
|
// Getters and setters for individual configuration values
|
||||||
|
|
||||||
@ -126,6 +145,39 @@ public class AppConfig {
|
|||||||
properties.setProperty("fileeditor.height", String.valueOf(height));
|
properties.setProperty("fileeditor.height", String.valueOf(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLastFileChooserDirectory() {
|
||||||
|
return properties.getProperty("filechooser.last.dir", System.getProperty("user.home"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastFileChooserDirectory(String path) {
|
||||||
|
if (path != null) {
|
||||||
|
properties.setProperty("filechooser.last.dir", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileChooserX() {
|
||||||
|
return Integer.parseInt(properties.getProperty("filechooser.x", "-1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileChooserY() {
|
||||||
|
return Integer.parseInt(properties.getProperty("filechooser.y", "-1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileChooserWidth() {
|
||||||
|
return Integer.parseInt(properties.getProperty("filechooser.width", "600"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileChooserHeight() {
|
||||||
|
return Integer.parseInt(properties.getProperty("filechooser.height", "450"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileChooserBounds(int x, int y, int width, int height) {
|
||||||
|
properties.setProperty("filechooser.x", String.valueOf(x));
|
||||||
|
properties.setProperty("filechooser.y", String.valueOf(y));
|
||||||
|
properties.setProperty("filechooser.width", String.valueOf(width));
|
||||||
|
properties.setProperty("filechooser.height", String.valueOf(height));
|
||||||
|
}
|
||||||
|
|
||||||
public String getActivePanel() {
|
public String getActivePanel() {
|
||||||
return properties.getProperty("active.panel", "left");
|
return properties.getProperty("active.panel", "left");
|
||||||
}
|
}
|
||||||
@ -744,4 +796,12 @@ public class AppConfig {
|
|||||||
properties.setProperty("toolbar.shortcut." + i + ".workingDir", s.workingDir != null ? s.workingDir : "");
|
properties.setProperty("toolbar.shortcut." + i + ".workingDir", s.workingDir != null ? s.workingDir : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMigrationPath() {
|
||||||
|
return properties.getProperty("migration.path", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMigrationPath(String path) {
|
||||||
|
properties.setProperty("migration.path", path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/main/java/cz/kamma/kfmanager/ui/FileChooserUtils.java
Normal file
73
src/main/java/cz/kamma/kfmanager/ui/FileChooserUtils.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package cz.kamma.kfmanager.ui;
|
||||||
|
|
||||||
|
import cz.kamma.kfmanager.config.AppConfig;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class FileChooserUtils {
|
||||||
|
|
||||||
|
public static int showOpenDialog(Component parent, JFileChooser chooser, AppConfig config) {
|
||||||
|
return showDialog(parent, chooser, config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int showSaveDialog(Component parent, JFileChooser chooser, AppConfig config) {
|
||||||
|
return showDialog(parent, chooser, config, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int showDialog(Component parent, JFileChooser chooser, AppConfig config, boolean open) {
|
||||||
|
// Set initial directory only if not already set or points to home
|
||||||
|
File current = chooser.getCurrentDirectory();
|
||||||
|
if (current == null || current.getAbsolutePath().equals(System.getProperty("user.home"))) {
|
||||||
|
String lastDir = config.getLastFileChooserDirectory();
|
||||||
|
if (lastDir != null && !lastDir.isEmpty()) {
|
||||||
|
File dir = new File(lastDir);
|
||||||
|
if (dir.exists() && dir.isDirectory()) {
|
||||||
|
chooser.setCurrentDirectory(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final JDialog[] dialogRef = {null};
|
||||||
|
HierarchyListener hierarchyListener = new HierarchyListener() {
|
||||||
|
@Override
|
||||||
|
public void hierarchyChanged(HierarchyEvent e) {
|
||||||
|
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 && chooser.isShowing()) {
|
||||||
|
Window window = SwingUtilities.getWindowAncestor(chooser);
|
||||||
|
if (window instanceof JDialog) {
|
||||||
|
dialogRef[0] = (JDialog) window;
|
||||||
|
// Restore size and position
|
||||||
|
int w = config.getFileChooserWidth();
|
||||||
|
int h = config.getFileChooserHeight();
|
||||||
|
if (w > 0 && h > 0) dialogRef[0].setSize(w, h);
|
||||||
|
|
||||||
|
int x = config.getFileChooserX();
|
||||||
|
int y = config.getFileChooserY();
|
||||||
|
if (x >= 0 && y >= 0) {
|
||||||
|
dialogRef[0].setLocation(x, y);
|
||||||
|
} else {
|
||||||
|
dialogRef[0].setLocationRelativeTo(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
chooser.addHierarchyListener(hierarchyListener);
|
||||||
|
int result = open ? chooser.showOpenDialog(parent) : chooser.showSaveDialog(parent);
|
||||||
|
chooser.removeHierarchyListener(hierarchyListener);
|
||||||
|
|
||||||
|
if (dialogRef[0] != null) {
|
||||||
|
config.setFileChooserBounds(dialogRef[0].getX(), dialogRef[0].getY(), dialogRef[0].getWidth(), dialogRef[0].getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
File currentDir = chooser.getCurrentDirectory();
|
||||||
|
if (currentDir != null) {
|
||||||
|
config.setLastFileChooserDirectory(currentDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
config.saveConfig();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -608,7 +608,7 @@ public class MainWindow extends JFrame {
|
|||||||
browseWorkDir.addActionListener(e -> {
|
browseWorkDir.addActionListener(e -> {
|
||||||
JFileChooser chooser = new JFileChooser(workingDirField.getText());
|
JFileChooser chooser = new JFileChooser(workingDirField.getText());
|
||||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
if (FileChooserUtils.showOpenDialog(this, chooser, config) == JFileChooser.APPROVE_OPTION) {
|
||||||
workingDirField.setText(chooser.getSelectedFile().getAbsolutePath());
|
workingDirField.setText(chooser.getSelectedFile().getAbsolutePath());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -630,7 +630,7 @@ public class MainWindow extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JFileChooser chooser = new JFileChooser(startPath);
|
JFileChooser chooser = new JFileChooser(startPath);
|
||||||
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
if (FileChooserUtils.showOpenDialog(this, chooser, config) == JFileChooser.APPROVE_OPTION) {
|
||||||
iconField.setText(chooser.getSelectedFile().getAbsolutePath());
|
iconField.setText(chooser.getSelectedFile().getAbsolutePath());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -74,6 +74,7 @@ public class SettingsDialog extends JDialog {
|
|||||||
model.addElement("Sorting");
|
model.addElement("Sorting");
|
||||||
model.addElement("Toolbar");
|
model.addElement("Toolbar");
|
||||||
model.addElement("Associations");
|
model.addElement("Associations");
|
||||||
|
model.addElement("Import/Export");
|
||||||
categoryList = new JList<>(model);
|
categoryList = new JList<>(model);
|
||||||
categoryList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
categoryList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
categoryList.setSelectedIndex(0);
|
categoryList.setSelectedIndex(0);
|
||||||
@ -88,6 +89,7 @@ public class SettingsDialog extends JDialog {
|
|||||||
cards.add(buildSortingPanel(), "Sorting");
|
cards.add(buildSortingPanel(), "Sorting");
|
||||||
cards.add(buildToolbarPanel(), "Toolbar");
|
cards.add(buildToolbarPanel(), "Toolbar");
|
||||||
cards.add(buildAssociationsPanel(), "Associations");
|
cards.add(buildAssociationsPanel(), "Associations");
|
||||||
|
cards.add(buildImportExportPanel(), "Import/Export");
|
||||||
|
|
||||||
categoryList.addListSelectionListener(e -> {
|
categoryList.addListSelectionListener(e -> {
|
||||||
if (!e.getValueIsAdjusting()) {
|
if (!e.getValueIsAdjusting()) {
|
||||||
@ -393,7 +395,7 @@ public class SettingsDialog extends JDialog {
|
|||||||
File f = new File(externalEditorField.getText());
|
File f = new File(externalEditorField.getText());
|
||||||
if (f.exists()) fc.setSelectedFile(f);
|
if (f.exists()) fc.setSelectedFile(f);
|
||||||
}
|
}
|
||||||
int r = fc.showOpenDialog(this);
|
int r = FileChooserUtils.showOpenDialog(this, fc, config);
|
||||||
if (r == JFileChooser.APPROVE_OPTION) {
|
if (r == JFileChooser.APPROVE_OPTION) {
|
||||||
File sel = fc.getSelectedFile();
|
File sel = fc.getSelectedFile();
|
||||||
externalEditorField.setText(sel.getAbsolutePath());
|
externalEditorField.setText(sel.getAbsolutePath());
|
||||||
@ -617,6 +619,113 @@ public class SettingsDialog extends JDialog {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JPanel buildImportExportPanel() {
|
||||||
|
JPanel p = new JPanel(new GridBagLayout());
|
||||||
|
p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
gbc.gridwidth = 3;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
gbc.insets = new Insets(0, 0, 5, 0);
|
||||||
|
|
||||||
|
p.add(new JLabel("Migration File Path:"), gbc);
|
||||||
|
|
||||||
|
gbc.gridy++;
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
gbc.insets = new Insets(0, 0, 15, 5);
|
||||||
|
JTextField pathField = new JTextField(config.getMigrationPath());
|
||||||
|
p.add(pathField, gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 0;
|
||||||
|
JButton browseBtn = new JButton("Browse...");
|
||||||
|
browseBtn.addActionListener(e -> {
|
||||||
|
JFileChooser chooser = new JFileChooser();
|
||||||
|
String currentPath = pathField.getText();
|
||||||
|
if (!currentPath.isEmpty()) {
|
||||||
|
File f = new File(currentPath);
|
||||||
|
if (f.exists()) {
|
||||||
|
chooser.setSelectedFile(f);
|
||||||
|
} else {
|
||||||
|
chooser.setSelectedFile(new File(f.getParentFile(), "kfmanager.backup"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chooser.setSelectedFile(new File("kfmanager.backup"));
|
||||||
|
}
|
||||||
|
if (FileChooserUtils.showOpenDialog(this, chooser, config) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
String path = chooser.getSelectedFile().getAbsolutePath();
|
||||||
|
pathField.setText(path);
|
||||||
|
config.setMigrationPath(path);
|
||||||
|
config.saveConfig();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.add(browseBtn, gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy++;
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
gbc.weightx = 0.5;
|
||||||
|
JButton exportBtn = new JButton("Export");
|
||||||
|
exportBtn.addActionListener(e -> {
|
||||||
|
String path = pathField.getText();
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Please specify a file path first.", "Warning", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
config.exportConfig(new File(path));
|
||||||
|
JOptionPane.showMessageDialog(this, "Configuration exported successfully.", "Success", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
config.setMigrationPath(path);
|
||||||
|
config.saveConfig();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Error exporting configuration: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.add(exportBtn, gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 1;
|
||||||
|
JButton importBtn = new JButton("Import");
|
||||||
|
importBtn.addActionListener(e -> {
|
||||||
|
String path = pathField.getText();
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Please specify a file path first.", "Warning", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File source = new File(path);
|
||||||
|
if (!source.exists()) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Specified file does not exist.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int res = JOptionPane.showConfirmDialog(this,
|
||||||
|
"Importing configuration will overwrite current settings and close the dialog. Continue?",
|
||||||
|
"Import",
|
||||||
|
JOptionPane.YES_NO_OPTION);
|
||||||
|
if (res == JOptionPane.YES_OPTION) {
|
||||||
|
try {
|
||||||
|
config.importConfig(source);
|
||||||
|
config.setMigrationPath(path);
|
||||||
|
config.saveConfig();
|
||||||
|
if (onChange != null) onChange.run();
|
||||||
|
dispose();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Error importing configuration: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
p.add(importBtn, gbc);
|
||||||
|
|
||||||
|
// Add spacer
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy++;
|
||||||
|
gbc.gridwidth = 3;
|
||||||
|
gbc.weighty = 1.0;
|
||||||
|
p.add(new JPanel(), gbc);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
private static String capitalize(String s) {
|
private static String capitalize(String s) {
|
||||||
if (s == null || s.isEmpty()) return s;
|
if (s == null || s.isEmpty()) return s;
|
||||||
return s.substring(0,1).toUpperCase() + s.substring(1).toLowerCase();
|
return s.substring(0,1).toUpperCase() + s.substring(1).toLowerCase();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user