fix: add, backup and restore db works

This commit is contained in:
lantzelot-swe 2024-05-23 16:30:03 +02:00
parent 812a3b16f2
commit 00d739401a
6 changed files with 256 additions and 94 deletions

View File

@ -33,6 +33,7 @@ import se.lantz.util.GameListDataComparator;
public class DbConnector public class DbConnector
{ {
public static String DB_FILE_NAME = "pcusb.db";
public static String DB_FILE = ""; public static String DB_FILE = "";
private static final String COMMA = "\",\""; private static final String COMMA = "\",\"";
// @J- // @J-
@ -109,23 +110,28 @@ public class DbConnector
for (String dbFolder : dbFolders) for (String dbFolder : dbFolders)
{ {
setCurrentDbFolder(dbFolder); setCurrentDbFolder(dbFolder);
createDbIfMissing(dbFolder);
}
}
public void createDbIfMissing(String folderName)
{
//Check if databases file exists, if not create an empty db. //Check if databases file exists, if not create an empty db.
File dbFile = new File("./" + DB_FILE); File dbFile = new File("./" + DB_FILE);
if (!dbFile.exists()) if (!dbFile.exists())
{ {
createNewDb(); createNewDb();
logger.debug("Database {} missing, new db created.", dbFolder); logger.debug("Database {} missing, new db created.", folderName);
} }
//To be backwards compatible with 1.0 db, update if missing //To be backwards compatible with 1.0 db, update if missing
addLanguageAndDuplicateColumnsIfMissing(); addLanguageAndDuplicateColumnsIfMissing();
//To be backwards compatible with 2.8.2 db, update if missing //To be backwards compatible with 2.8.2 db, update if missing
addDiskColumnsIfMissing(); addDiskColumnsIfMissing();
} }
}
public static void setCurrentDbFolder(String dbFolder) public static void setCurrentDbFolder(String dbFolder)
{ {
DB_FILE = "./databases/" + dbFolder + "/pcusb.db"; DB_FILE = "./databases/" + dbFolder + "/" + DB_FILE_NAME;
} }
private void createNewDb() private void createNewDb()

View File

@ -14,10 +14,7 @@ import java.awt.image.BufferedImage;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class DraggableTabbedPane extends JTabbedPane public class DraggableTabbedPane extends JTabbedPane
{ {
@ -32,14 +29,13 @@ public class DraggableTabbedPane extends JTabbedPane
private ActionListener draggedTabListener = null; private ActionListener draggedTabListener = null;
private ActionListener tabStructureChangedListener = null; private ActionListener tabStructureChangedListener = null;
private boolean removingTab = false;
public DraggableTabbedPane() public DraggableTabbedPane()
{ {
super(); super();
addMouseMotionListener(new MouseMotionAdapter() addMouseMotionListener(new MouseMotionAdapter()
{ {
public void mouseDragged(MouseEvent e) public void mouseDragged(MouseEvent e)
{ {
@ -165,28 +161,25 @@ public class DraggableTabbedPane extends JTabbedPane
// Need to repaint // Need to repaint
repaint(); repaint();
} }
});
}
@Override @Override
public void mouseClicked(MouseEvent e) public void removeTabAt(int index)
{ {
if (SwingUtilities.isRightMouseButton(e)) //Select a proper tab after removing
if (getSelectedIndex() == getTabCount() - 2)
{ {
this.removingTab = true;
int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), 10); super.removeTabAt(index);
this.removingTab = false;
if (tabNumber > -1 && (tabNumber < getTabCount() - 1)) setSelectedIndex(getTabCount() - 2);
}
else
{ {
JPopupMenu menu = new JPopupMenu(); super.removeTabAt(index);
JMenuItem renameTabItem = new JMenuItem("Rename database");
JMenuItem deleteTabItem = new JMenuItem("Delete database");
menu.add(renameTabItem);
menu.add(deleteTabItem);
menu.show(DraggableTabbedPane.this, e.getX(), e.getY());
} }
} }
}
});
}
public void addTabDraggedListener(ActionListener listener) public void addTabDraggedListener(ActionListener listener)
{ {
@ -219,6 +212,11 @@ public class DraggableTabbedPane extends JTabbedPane
return dragging; return dragging;
} }
public boolean isRemovingTab()
{
return removingTab;
}
public int getPreviouslySelectedIndex() public int getPreviouslySelectedIndex()
{ {
return previouslySelectedIndex; return previouslySelectedIndex;

View File

@ -1,16 +1,24 @@
package se.lantz.gui; package se.lantz.gui;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSplitPane; import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import se.lantz.model.MainViewModel; import se.lantz.model.MainViewModel;
import se.lantz.model.data.GameListData; import se.lantz.model.data.GameListData;
import se.lantz.util.ExceptionHandler;
public class MainPanel extends JPanel public class MainPanel extends JPanel
{ {
@ -58,11 +66,11 @@ public class MainPanel extends JPanel
//Update previous selected index once a tab is dragged to a new position //Update previous selected index once a tab is dragged to a new position
tabbedPane.addTabDraggedListener(e -> previouslySelectedIndex = e.getID()); tabbedPane.addTabDraggedListener(e -> previouslySelectedIndex = e.getID());
//Update preferences when the tab structure changes (renamed, deleted, re-arranged) //Update preferences when the tab positions changes
tabbedPane.addTabStructureChangedListener(e -> updateTabOrderPreferences()); tabbedPane.addTabStructureChangedListener(e -> updateTabOrderPreferences());
tabbedPane.addChangeListener(e -> { tabbedPane.addChangeListener(e -> {
if (!tabbedPane.isDragging()) if (!tabbedPane.isRemovingTab() && !tabbedPane.isDragging())
{ {
if (tabbedPane.getSelectedIndex() == uiModel.getAvailableDatabases().size()) if (tabbedPane.getSelectedIndex() == uiModel.getAvailableDatabases().size())
{ {
@ -70,6 +78,7 @@ public class MainPanel extends JPanel
tabbedPane.setSelectedIndex(previouslySelectedIndex); tabbedPane.setSelectedIndex(previouslySelectedIndex);
ignoreTabChange = false; ignoreTabChange = false;
String name = JOptionPane.showInputDialog(this, "Write a new name!"); String name = JOptionPane.showInputDialog(this, "Write a new name!");
createNewTab(name);
//Create a new empty one! //Create a new empty one!
return; return;
} }
@ -92,10 +101,114 @@ public class MainPanel extends JPanel
repaint(); repaint();
} }
}); });
tabbedPane.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (SwingUtilities.isRightMouseButton(e))
{
int tabNumber = tabbedPane.getUI().tabForCoordinate(tabbedPane, e.getX(), 10);
if (tabNumber > -1 && (tabNumber < tabbedPane.getTabCount() - 1))
{
JPopupMenu menu = new JPopupMenu();
JMenuItem renameTabItem = new JMenuItem("Rename database");
renameTabItem.addActionListener(ev -> renameTab(tabNumber));
JMenuItem deleteTabItem = new JMenuItem("Delete database");
deleteTabItem.addActionListener(ev -> deleteTab(tabNumber));
menu.add(renameTabItem);
menu.add(deleteTabItem);
menu.show(tabbedPane, e.getX(), e.getY());
}
}
}
});
} }
return tabbedPane; return tabbedPane;
} }
private void renameTab(int tabIndex)
{
String oldName = tabbedPane.getTitleAt(tabIndex);
String newName = (String) JOptionPane.showInputDialog(this,
"Enter new name for \"" + oldName + "\"",
"Rename database",
JOptionPane.QUESTION_MESSAGE,
null,
null,
oldName);
if (newName != null)
{
try
{
uiModel.renameTab(oldName, newName);
tabbedPane.setTitleAt(tabIndex, newName);
updateTabOrderPreferences();
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not rename database");
}
}
}
private void deleteTab(int tabIndex)
{
String selectedTab = tabbedPane.getTitleAt(tabIndex);
int answer = JOptionPane.showConfirmDialog(this,
"Are you sure you want to delete the " + selectedTab +
" database?\nIt will be removed completely from the databases folder.",
"Delete database",
JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.YES_OPTION)
{
try
{
uiModel.deleteTab(selectedTab);
tabbedPane.removeTabAt(tabIndex);
updateTabOrderPreferences();
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not delete database");
}
}
}
private void createNewTab(String name)
{
//TODO: Check name here, do not add one with same name as existing, or null, or empty
if (name == null || name.isEmpty() || name.isBlank())
{
//Do nothing
return;
}
List<String> lowerCaseNames =
uiModel.getAvailableDatabases().stream().map(x -> x.toLowerCase()).collect(Collectors.toList());
if (lowerCaseNames.contains(name.toLowerCase().trim()))
{
JOptionPane.showMessageDialog(this,
"A database with name " + name.trim() + " already exists",
"Duplicate db name",
JOptionPane.INFORMATION_MESSAGE);
return;
}
try
{
uiModel.addTab(name);
tabbedPane.insertTab(name, null, getNewContentPanel(null), null, tabbedPane.getTabCount() - 1);
tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 2);
updateTabOrderPreferences();
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not create database");
}
}
private void updateTabOrderPreferences() private void updateTabOrderPreferences()
{ {
List<String> tabTitles = new ArrayList<>(); List<String> tabTitles = new ArrayList<>();

View File

@ -27,6 +27,8 @@ public class BackupManager
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
//String for current date and time //String for current date and time
currentFolderName = dtf.format(now); currentFolderName = dtf.format(now);
currentFolderName = FileManager.getCurrentDbName() + "-" + currentFolderName;
return currentFolderName; return currentFolderName;
} }

View File

@ -121,8 +121,7 @@ public class MainViewModel extends AbstractModel
{ {
List<String> preferencesOrder = Arrays.asList(tabOrder.split("\\s*,\\s*")); List<String> preferencesOrder = Arrays.asList(tabOrder.split("\\s*,\\s*"));
Collections.sort(availableDatabases, Collections.sort(availableDatabases, Comparator.comparing(item -> preferencesOrder.indexOf(item)));
Comparator.comparing(item -> preferencesOrder.indexOf(item)));
} }
selectedDatabase = availableDatabases.get(0); selectedDatabase = availableDatabases.get(0);
@ -137,6 +136,30 @@ public class MainViewModel extends AbstractModel
configuredProperties.put(DB_TAB_ORDER, prefValue); configuredProperties.put(DB_TAB_ORDER, prefValue);
} }
public void renameTab(String oldName, String newName) throws IOException
{
Path source = Paths.get("./databases" + "/" + oldName);
Files.move(source, source.resolveSibling(newName));
selectedDatabase = newName;
FileManager.setCurrentDbFolder(selectedDatabase);
DbConnector.setCurrentDbFolder(selectedDatabase);
}
public void deleteTab(String dbName) throws IOException
{
availableDatabases.remove(dbName);
Path source = Paths.get("./databases" + "/" + dbName);
Files.walk(source).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
public void addTab(String name) throws IOException
{
FileManager.createNewDb(name);
availableDatabases.add(name);
}
public void setSavedStatesManager(SavedStatesManager savedStatesManager) public void setSavedStatesManager(SavedStatesManager savedStatesManager)
{ {
this.stateManager = savedStatesManager; this.stateManager = savedStatesManager;

View File

@ -70,11 +70,12 @@ public class FileManager
public static BufferedImage infoSlotVic20Cover; public static BufferedImage infoSlotVic20Cover;
private static String currentDbPath = "./"; private static String currentDbPath = "./";
private static String currentDbName = "";
public static String GAMES = "./games/"; public static String GAMES = "./games/";
public static String SCREENS = "./screens/"; public static String SCREENS = "./screens/";
public static String COVERS = "./covers/"; public static String COVERS = "./covers/";
public static String SAVES = "./saves/"; public static String SAVES = "./saves/";
private static String BACKUP = "./backup/"; private static final String BACKUP = "./backup/";
public static String DISKS = "./extradisks/"; public static String DISKS = "./extradisks/";
private static final Path TEMP_PATH = Paths.get("./temp"); private static final Path TEMP_PATH = Paths.get("./temp");
@ -134,15 +135,32 @@ public class FileManager
public static void setCurrentDbFolder(String dbFolder) public static void setCurrentDbFolder(String dbFolder)
{ {
currentDbName = dbFolder;
currentDbPath = "./databases/" + dbFolder + "/"; currentDbPath = "./databases/" + dbFolder + "/";
GAMES = currentDbPath + "games/"; GAMES = currentDbPath + "games/";
SCREENS = currentDbPath + "screens/"; SCREENS = currentDbPath + "screens/";
COVERS = currentDbPath + "covers/"; COVERS = currentDbPath + "covers/";
SAVES = currentDbPath + "saves/"; SAVES = currentDbPath + "saves/";
BACKUP = currentDbPath + "backup/";
DISKS = currentDbPath + "extradisks/"; DISKS = currentDbPath + "extradisks/";
} }
public static void createNewDb(String name) throws IOException
{
setCurrentDbFolder(name);
Files.createDirectories(Paths.get(GAMES));
Files.createDirectories(Paths.get(SCREENS));
Files.createDirectories(Paths.get(COVERS));
Files.createDirectories(Paths.get(SAVES));
Files.createDirectories(Paths.get(DISKS));
dbconnector.setCurrentDbFolder(name);
dbconnector.createDbIfMissing(name);
}
public static String getCurrentDbName()
{
return currentDbName;
}
public static InputStream getMissingC64GameFile() throws URISyntaxException public static InputStream getMissingC64GameFile() throws URISyntaxException
{ {
return FileManager.class.getResourceAsStream("/se/lantz/MissingGame-C64.vsf.gz"); return FileManager.class.getResourceAsStream("/se/lantz/MissingGame-C64.vsf.gz");
@ -970,9 +988,8 @@ public class FileManager
} }
else else
{ {
gamePathString = SAVES + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) +
SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + "/" + savedStatesModel.getState1File();
savedStatesModel.getState1File();
} }
} }
break; break;
@ -985,9 +1002,8 @@ public class FileManager
} }
else else
{ {
gamePathString = SAVES + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) +
SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + "/" + savedStatesModel.getState2File();
savedStatesModel.getState2File();
} }
break; break;
case Save2: case Save2:
@ -999,9 +1015,8 @@ public class FileManager
} }
else else
{ {
gamePathString = SAVES + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) +
SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + "/" + savedStatesModel.getState3File();
savedStatesModel.getState3File();
} }
break; break;
case Save3: case Save3:
@ -1013,9 +1028,8 @@ public class FileManager
} }
else else
{ {
gamePathString = SAVES + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) +
SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + "/" + savedStatesModel.getState4File();
savedStatesModel.getState4File();
} }
break; break;
default: default:
@ -1386,19 +1400,25 @@ public class FileManager
{ {
if (showCropDialogForCover.isEmpty()) if (showCropDialogForCover.isEmpty())
{ {
showCropDialogForCover = FileManager.getConfiguredProperties().getProperty(PreferencesModel.SHOW_CROP_DIALOG_FOR_COVER, "true"); showCropDialogForCover =
FileManager.getConfiguredProperties().getProperty(PreferencesModel.SHOW_CROP_DIALOG_FOR_COVER, "true");
} }
return Boolean.parseBoolean(showCropDialogForCover); return Boolean.parseBoolean(showCropDialogForCover);
} }
private static String getBackupFolderName(String targetFolderName)
{
return BACKUP + "/" + targetFolderName + "/";
}
public static void backupDb(String targetFolderName) public static void backupDb(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
File dbFile = new File("./" + DbConnector.DB_FILE); File dbFile = new File(DbConnector.DB_FILE);
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
Path targetFile = outputFolder.toPath().resolve(DbConnector.DB_FILE); Path targetFile = outputFolder.toPath().resolve(DbConnector.DB_FILE_NAME);
Files.copy(dbFile.toPath(), targetFile); Files.copy(dbFile.toPath(), targetFile);
} }
catch (IOException e) catch (IOException e)
@ -1409,7 +1429,7 @@ public class FileManager
public static void backupScreens(String targetFolderName) public static void backupScreens(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
@ -1424,7 +1444,7 @@ public class FileManager
public static void backupCovers(String targetFolderName) public static void backupCovers(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
@ -1439,7 +1459,7 @@ public class FileManager
public static void backupGames(String targetFolderName) public static void backupGames(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
@ -1454,7 +1474,7 @@ public class FileManager
public static void backupExtraDisks(String targetFolderName) public static void backupExtraDisks(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
@ -1469,7 +1489,7 @@ public class FileManager
public static void backupSaves(String targetFolderName) public static void backupSaves(String targetFolderName)
{ {
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); File outputFolder = new File(getBackupFolderName(targetFolderName));
try try
{ {
Files.createDirectories(outputFolder.toPath()); Files.createDirectories(outputFolder.toPath());
@ -1583,10 +1603,10 @@ public class FileManager
public static void restoreDb(String backupFolderName) public static void restoreDb(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
Path backupFile = backupFolder.toPath().resolve(DbConnector.DB_FILE); Path backupFile = backupFolder.toPath().resolve(DbConnector.DB_FILE_NAME);
Path dbFile = new File("./" + DbConnector.DB_FILE).toPath(); Path dbFile = new File("./" + DbConnector.DB_FILE).toPath();
Files.copy(backupFile, dbFile, StandardCopyOption.REPLACE_EXISTING); Files.copy(backupFile, dbFile, StandardCopyOption.REPLACE_EXISTING);
} }
@ -1598,7 +1618,7 @@ public class FileManager
public static void restoreCovers(String backupFolderName) public static void restoreCovers(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
File coversDir = new File(COVERS); File coversDir = new File(COVERS);
@ -1613,7 +1633,7 @@ public class FileManager
public static void restoreScreens(String backupFolderName) public static void restoreScreens(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
File screensDir = new File(SCREENS); File screensDir = new File(SCREENS);
@ -1628,7 +1648,7 @@ public class FileManager
public static void restoreGames(String backupFolderName) public static void restoreGames(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
File gamesDir = new File(GAMES); File gamesDir = new File(GAMES);
@ -1643,7 +1663,7 @@ public class FileManager
public static void restoreExtraDisks(String backupFolderName) public static void restoreExtraDisks(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
File extradisksDir = new File(DISKS); File extradisksDir = new File(DISKS);
@ -1662,7 +1682,7 @@ public class FileManager
public static void restoreSaves(String backupFolderName) public static void restoreSaves(String backupFolderName)
{ {
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); File backupFolder = new File(getBackupFolderName(backupFolderName));
try try
{ {
File savesDir = new File(SAVES); File savesDir = new File(SAVES);