diff --git a/pom.xml b/pom.xml
index 19d13d5..ef1fade 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,8 +9,8 @@
1.0-SNAPSHOT
- 17
- 17
+ 11
+ 11
UTF-8
@@ -29,8 +29,8 @@
maven-compiler-plugin
3.11.0
- 17
- 17
+ 11
+ 11
diff --git a/src/main/java/cz/kamma/jkeepass/KeepassApp.java b/src/main/java/cz/kamma/jkeepass/KeepassApp.java
index e91e736..22e7ab1 100644
--- a/src/main/java/cz/kamma/jkeepass/KeepassApp.java
+++ b/src/main/java/cz/kamma/jkeepass/KeepassApp.java
@@ -88,6 +88,15 @@ public class KeepassApp extends JFrame {
private String currentPassword;
private TrayIcon trayIcon;
+
+ // Menu items that need state management
+ private JMenuItem menuSave;
+ private JMenuItem menuLock;
+ private JMenuItem menuEntryAdd;
+ private JMenuItem menuEntryEdit;
+ private JMenuItem menuEntryDelete;
+ private JMenuItem menuEditCopyUser;
+ private JMenuItem menuEditCopyPass;
public KeepassApp() {
@@ -282,22 +291,22 @@ public class KeepassApp extends JFrame {
JMenu fileMenu = new JMenu("File");
JMenuItem openItem = new JMenuItem("Open Database...");
recentMenu = new JMenu("Open Recent");
- JMenuItem saveItem = new JMenuItem("Save");
+ menuSave = new JMenuItem("Save");
JMenuItem minimizeItem = new JMenuItem(SystemTray.isSupported() ? "Minimize to Tray" : "Minimize & Lock");
- JMenuItem lockItem = new JMenuItem("Lock Database");
+ menuLock = new JMenuItem("Lock Database");
JMenuItem exitItem = new JMenuItem("Exit");
openItem.addActionListener(e -> openDatabase(null));
- saveItem.addActionListener(e -> saveDatabase());
+ menuSave.addActionListener(e -> saveDatabase());
minimizeItem.addActionListener(e -> minimizeToCustomTray());
- lockItem.addActionListener(e -> lockDatabase());
+ menuLock.addActionListener(e -> lockDatabase());
exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(openItem);
fileMenu.add(recentMenu);
- fileMenu.add(saveItem);
+ fileMenu.add(menuSave);
fileMenu.addSeparator();
- fileMenu.add(lockItem);
+ fileMenu.add(menuLock);
fileMenu.add(minimizeItem);
fileMenu.add(exitItem);
@@ -305,40 +314,42 @@ public class KeepassApp extends JFrame {
// Entry Menu
JMenu entryMenu = new JMenu("Entry");
- JMenuItem addItem = new JMenuItem("Add Entry...");
- JMenuItem editItem = new JMenuItem("Edit Entry...");
- JMenuItem delItem = new JMenuItem("Delete Entry");
+ menuEntryAdd = new JMenuItem("Add Entry...");
+ menuEntryEdit = new JMenuItem("Edit Entry...");
+ menuEntryDelete = new JMenuItem("Delete Entry");
- addItem.addActionListener(e -> addEntry());
- editItem.addActionListener(e -> editEntry());
- delItem.addActionListener(e -> deleteEntry());
+ menuEntryAdd.addActionListener(e -> addEntry());
+ menuEntryEdit.addActionListener(e -> editEntry());
+ menuEntryDelete.addActionListener(e -> deleteEntry());
- entryMenu.add(addItem);
- entryMenu.add(editItem);
- entryMenu.add(delItem);
+ entryMenu.add(menuEntryAdd);
+ entryMenu.add(menuEntryEdit);
+ entryMenu.add(menuEntryDelete);
// Edit Menu
JMenu editMenu = new JMenu("Edit");
- JMenuItem copyUserItem = new JMenuItem("Copy Username");
- JMenuItem copyPassItem = new JMenuItem("Copy Password");
+ menuEditCopyUser = new JMenuItem("Copy Username");
+ menuEditCopyPass = new JMenuItem("Copy Password");
- copyUserItem.addActionListener(e -> copyToClipboard(true));
- copyPassItem.addActionListener(e -> copyToClipboard(false));
+ menuEditCopyUser.addActionListener(e -> copyToClipboard(true));
+ menuEditCopyPass.addActionListener(e -> copyToClipboard(false));
- editMenu.add(copyUserItem);
- editMenu.add(copyPassItem);
+ editMenu.add(menuEditCopyUser);
+ editMenu.add(menuEditCopyPass);
// View Menu
JMenu viewMenu = new JMenu("View");
JCheckBoxMenuItem onTopItem = new JCheckBoxMenuItem("Always on Top");
onTopItem.addActionListener(e -> setAlwaysOnTop(onTopItem.isSelected()));
viewMenu.add(onTopItem);
-
menuBar.add(fileMenu);
menuBar.add(entryMenu);
menuBar.add(editMenu);
menuBar.add(viewMenu);
setJMenuBar(menuBar);
+
+ // Initialize menu state (all disabled until database is loaded)
+ updateMenuState();
}
private void initComponents() {
@@ -350,6 +361,7 @@ public class KeepassApp extends JFrame {
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) groupTree.getLastSelectedPathComponent();
if (selectedNode != null && selectedNode.getUserObject() instanceof GroupWrapper) {
displayEntriesInGroup(((GroupWrapper) selectedNode.getUserObject()).getGroup());
+ updateMenuState();
}
});
groupTree.addMouseListener(new MouseAdapter() {
@@ -419,6 +431,7 @@ public class KeepassApp extends JFrame {
} else {
notesArea.setText("");
}
+ updateMenuState();
}
});
entryTable.addMouseListener(new MouseAdapter() {
@@ -430,14 +443,26 @@ public class KeepassApp extends JFrame {
if (row >= 0 && col >= 0) {
int modelRow = entryTable.convertRowIndexToModel(row);
Entry entry = currentEntries.get(modelRow);
- String content = switch (col) {
- case 0 -> entry.getTitle();
- case 1 -> entry.getUsername();
- case 2 -> entry.getPassword();
- case 3 -> entry.getUrl();
- case 4 -> entry.getNotes();
- default -> "";
- };
+ String content;
+ switch (col) {
+ case 0:
+ content = entry.getTitle();
+ break;
+ case 1:
+ content = entry.getUsername();
+ break;
+ case 2:
+ content = entry.getPassword();
+ break;
+ case 3:
+ content = entry.getUrl();
+ break;
+ case 4:
+ content = entry.getNotes();
+ break;
+ default:
+ content = "";
+ }
copyTextToClipboard(content, entryTable.getColumnName(col));
}
}
@@ -462,11 +487,20 @@ public class KeepassApp extends JFrame {
JPopupMenu popup = new JPopupMenu();
+ boolean hasGroup = currentGroup != null;
+ boolean hasEntry = row >= 0;
+
JMenuItem addPop = new JMenuItem("Add Entry");
JMenuItem editPop = new JMenuItem("Edit");
JMenuItem copyPop = new JMenuItem("Copy Username");
JMenuItem copyPassPop = new JMenuItem("Copy Password");
JMenuItem delPop = new JMenuItem("Delete");
+
+ addPop.setEnabled(hasGroup);
+ editPop.setEnabled(hasEntry);
+ copyPop.setEnabled(hasEntry);
+ copyPassPop.setEnabled(hasEntry);
+ delPop.setEnabled(hasEntry);
addPop.addActionListener(al -> addEntry());
editPop.addActionListener(al -> editEntry());
@@ -551,6 +585,35 @@ public class KeepassApp extends JFrame {
}
}
+ /**
+ * Update menu item enabled states based on current application state
+ */
+ private void updateMenuState() {
+ // Safely check if menu items are initialized (they might not be during early init)
+ if (menuSave == null || menuLock == null || menuEntryAdd == null ||
+ menuEntryEdit == null || menuEntryDelete == null ||
+ menuEditCopyUser == null || menuEditCopyPass == null) {
+ return;
+ }
+
+ boolean dbIsLoaded = database != null;
+ boolean hasGroupSelected = currentGroup != null;
+ boolean hasEntrySelected = entryTable != null && entryTable.getSelectedRow() >= 0;
+
+ // File menu items
+ menuSave.setEnabled(dbIsLoaded);
+ menuLock.setEnabled(dbIsLoaded);
+
+ // Entry menu items
+ menuEntryAdd.setEnabled(dbIsLoaded && hasGroupSelected);
+ menuEntryEdit.setEnabled(hasEntrySelected);
+ menuEntryDelete.setEnabled(hasEntrySelected);
+
+ // Edit menu items
+ menuEditCopyUser.setEnabled(hasEntrySelected);
+ menuEditCopyPass.setEnabled(hasEntrySelected);
+ }
+
private void updateRecentMenu() {
recentMenu.removeAll();
String recentFiles = prefs.get(PREF_RECENT_LIST, "");
@@ -630,6 +693,7 @@ public class KeepassApp extends JFrame {
updateTree(this.database.getRootGroup());
saveRecentFile(selectedFile.getAbsolutePath());
statusLabel.setText(" Database loaded: " + selectedFile.getName());
+ updateMenuState();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Error loading database: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
@@ -664,6 +728,7 @@ public class KeepassApp extends JFrame {
treeModel.setRoot(new DefaultMutableTreeNode("Database locked"));
statusLabel.setText(" Database locked.");
+ updateMenuState();
// Re-open password prompt
if (currentFile != null) {
@@ -686,6 +751,7 @@ public class KeepassApp extends JFrame {
updateEntryFromDialog(entry, dialog);
displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry added. Remember to Save.");
+ updateMenuState();
}
}
@@ -699,6 +765,7 @@ public class KeepassApp extends JFrame {
updateEntryFromDialog(entry, dialog);
displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry updated. Remember to Save.");
+ updateMenuState();
}
} else {
JOptionPane.showMessageDialog(this, "Please select an entry to edit.", "Warning", JOptionPane.WARNING_MESSAGE);
@@ -715,6 +782,7 @@ public class KeepassApp extends JFrame {
currentGroup.removeEntry(entry);
displayEntriesInGroup(currentGroup);
statusLabel.setText(" Entry deleted. Remember to Save.");
+ updateMenuState();
}
} else {
JOptionPane.showMessageDialog(this, "Please select an entry to delete.", "Warning", JOptionPane.WARNING_MESSAGE);
@@ -735,6 +803,7 @@ public class KeepassApp extends JFrame {
parentGroup.addGroup(database.newGroup(name.trim()));
updateTree(database.getRootGroup());
statusLabel.setText(" Category added. Remember to Save.");
+ updateMenuState();
}
}
@@ -770,6 +839,7 @@ public class KeepassApp extends JFrame {
parentGroup.removeGroup(group);
updateTree(database.getRootGroup());
statusLabel.setText(" Category deleted. Remember to Save.");
+ updateMenuState();
}
}