Improved file name generation and handling of duplicate titles
fix: generated file names for covers, screens and game files is improved to consider more characters to avoid that two games point to the same files. fix: When adding a new game where the file names becomes equal to an existing game in the db an additional index is added to the file name as a suffix. fix: file names are re-calculated when a game is saved and renamed if not matching the new rules.
This commit is contained in:
parent
fea8772a6e
commit
1772fab2f3
|
@ -24,6 +24,7 @@ import se.lantz.model.data.GameView;
|
|||
import se.lantz.model.data.ViewFilter;
|
||||
import se.lantz.util.DbConstants;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
import se.lantz.util.FileManager;
|
||||
import se.lantz.util.GameListDataComparator;
|
||||
|
||||
public class DbConnector
|
||||
|
@ -755,12 +756,19 @@ public class DbConnector
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
public int getGameDuplicateIndexToUse(String title)
|
||||
public int getGameDuplicateIndexToUse(String title, String gameId)
|
||||
{
|
||||
//This is only called when the title changes for an existing game or when adding a new game
|
||||
//Use generated name, that is what decides if a duplicate index needs to be used.
|
||||
//Look at the coverFile column since all covers have the same name ending.
|
||||
String fileName = FileManager.generateFileNameFromTitle(title, 0);
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT Duplicate FROM gameinfo WHERE title LIKE \"");
|
||||
sqlBuilder.append(title);
|
||||
sqlBuilder.append("\";");
|
||||
sqlBuilder.append("SELECT rowId, Duplicate FROM gameinfo WHERE Coverfile GLOB \'");
|
||||
sqlBuilder.append(fileName);
|
||||
sqlBuilder.append("-cover*\' OR CoverFile GLOB \'");
|
||||
sqlBuilder.append(fileName);
|
||||
sqlBuilder.append("[0-9][0-9]-cover*\';");
|
||||
String sql = sqlBuilder.toString();
|
||||
logger.debug("Checking if game is in db already: {}", sql);
|
||||
int returnIndex = 0;
|
||||
|
@ -769,8 +777,13 @@ public class DbConnector
|
|||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
{
|
||||
//Increase one to the available index since it's the one supposed to be used.
|
||||
returnIndex = Math.max(returnIndex, rs.getInt(DbConstants.DUPLICATE_INDEX) + 1);
|
||||
int rowId = rs.getInt("rowId");
|
||||
//Ignore the current game if the query matches it
|
||||
if (gameId.isEmpty() || rowId != Integer.parseInt(gameId))
|
||||
{
|
||||
//Increase one to the available index since it's the one supposed to be used.
|
||||
returnIndex = Math.max(returnIndex, rs.getInt(DbConstants.DUPLICATE_INDEX) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
|
|
|
@ -468,7 +468,7 @@ public class ImportManager
|
|||
int duplicateIndex = 0;
|
||||
if (selectedOption == Options.ADD)
|
||||
{
|
||||
duplicateIndex = uiModel.getDbConnector().getGameDuplicateIndexToUse(title);
|
||||
duplicateIndex = uiModel.getDbConnector().getGameDuplicateIndexToUse(title, "");
|
||||
}
|
||||
//Check any duplicates in added rows, always use this otherwise duplicates uses same names.
|
||||
duplicateIndex = duplicateIndex + getDbRowDuplicate(title);
|
||||
|
|
|
@ -99,15 +99,13 @@ public class SavedStatesManager
|
|||
}
|
||||
|
||||
//If the game has been renamed, make sure to rename the saves folder also
|
||||
if (model.getInfoModel().isTitleChanged())
|
||||
String oldFileName = model.getInfoModel().getOldGamesFile();
|
||||
String newFileName = model.getInfoModel().getGamesFile();
|
||||
File oldSaveFolder = new File(SAVES + oldFileName);
|
||||
if (!oldFileName.equals(newFileName) && oldSaveFolder.exists())
|
||||
{
|
||||
String oldFileName = model.getInfoModel().getOldGamesFile();
|
||||
File oldSaveFolder = new File(SAVES + oldFileName);
|
||||
if (oldSaveFolder.exists())
|
||||
{
|
||||
//Rename old folder to new name
|
||||
oldSaveFolder.renameTo(new File(SAVES + model.getInfoModel().getGamesFile()));
|
||||
}
|
||||
//Rename old folder to new name
|
||||
oldSaveFolder.renameTo(new File(SAVES + model.getInfoModel().getGamesFile()));
|
||||
}
|
||||
|
||||
String fileName = model.getInfoModel().getGamesFile();
|
||||
|
@ -557,11 +555,11 @@ public class SavedStatesManager
|
|||
{
|
||||
return savedStatesMap.get(gameFileName) != null ? savedStatesMap.get(gameFileName) : 0;
|
||||
}
|
||||
|
||||
|
||||
public void checkEnablementOfPalNtscMenuItem(boolean check)
|
||||
{
|
||||
boolean palNtscItemEnabled = false;
|
||||
|
||||
|
||||
if (check)
|
||||
{
|
||||
//Check if current game has a 0.vsf file and the current game file is a snapshot
|
||||
|
@ -583,13 +581,13 @@ public class SavedStatesManager
|
|||
}
|
||||
palNtscFixMenuItem.setEnabled(palNtscItemEnabled);
|
||||
}
|
||||
|
||||
|
||||
public boolean swapGameFileAndSavedState()
|
||||
{
|
||||
String gamesFile = model.getInfoModel().getGamesFile();
|
||||
Path gameFilePath = new File(FileManager.GAMES + gamesFile).toPath();
|
||||
Path firstSavedStatePath = new File(SAVES + gamesFile).toPath().resolve(VSZ0);
|
||||
|
||||
|
||||
Path tempFilePath = new File(FileManager.GAMES + "temp.gz").toPath();
|
||||
try
|
||||
{
|
||||
|
|
|
@ -367,39 +367,34 @@ public class InfoModel extends AbstractModel
|
|||
}
|
||||
}
|
||||
|
||||
public boolean updateFileNames()
|
||||
public void updateFileNames()
|
||||
{
|
||||
if (isNewGame() || isTitleChanged() || screenNamesNeedsUpdate())
|
||||
{
|
||||
//Keep track of the old names, used when renaming files when saving
|
||||
oldCoverFile = getCoverFile();
|
||||
oldScreens1File = getScreens1File();
|
||||
oldScreens2File = getScreens2File();
|
||||
oldGamesFile = getGamesFile();
|
||||
//Keep track of the old names, used when renaming files when saving
|
||||
oldCoverFile = getCoverFile();
|
||||
oldScreens1File = getScreens1File();
|
||||
oldScreens2File = getScreens2File();
|
||||
oldGamesFile = getGamesFile();
|
||||
|
||||
disableChangeNotification(true);
|
||||
String fileName = FileManager.generateFileNameFromTitle(this.title, getDuplicateIndex());
|
||||
if (!getCoverFile().isEmpty() || getCoverImage() != null)
|
||||
{
|
||||
setCoverFile(fileName + "-cover.png");
|
||||
}
|
||||
if (!getScreens1File().isEmpty() || getScreen1Image() != null)
|
||||
{
|
||||
setScreens1File(fileName + "-00.png");
|
||||
}
|
||||
if (!getScreens2File().isEmpty() || getScreen2Image() != null)
|
||||
{
|
||||
setScreens2File(fileName + "-01.png");
|
||||
}
|
||||
if (!getGamesFile().isEmpty())
|
||||
{
|
||||
String fileEnding = getGamesFile().substring(getGamesFile().indexOf("."));
|
||||
setGamesFile(fileName + fileEnding);
|
||||
}
|
||||
disableChangeNotification(false);
|
||||
return true;
|
||||
disableChangeNotification(true);
|
||||
String fileName = FileManager.generateFileNameFromTitle(this.title, getDuplicateIndex());
|
||||
if (!getCoverFile().isEmpty() || getCoverImage() != null)
|
||||
{
|
||||
setCoverFile(fileName + "-cover.png");
|
||||
}
|
||||
return false;
|
||||
if (!getScreens1File().isEmpty() || getScreen1Image() != null)
|
||||
{
|
||||
setScreens1File(fileName + "-00.png");
|
||||
}
|
||||
if (!getScreens2File().isEmpty() || getScreen2Image() != null)
|
||||
{
|
||||
setScreens2File(fileName + "-01.png");
|
||||
}
|
||||
if (!getGamesFile().isEmpty())
|
||||
{
|
||||
String fileEnding = getGamesFile().substring(getGamesFile().indexOf("."));
|
||||
setGamesFile(fileName + fileEnding);
|
||||
}
|
||||
disableChangeNotification(false);
|
||||
}
|
||||
|
||||
public void updateCoverAndScreensIfEmpty(boolean isC64)
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.ListModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -72,12 +71,12 @@ public class MainViewModel extends AbstractModel
|
|||
private GameListData selectedData;
|
||||
|
||||
Scraper scraper = new MobyGamesScraper();
|
||||
|
||||
|
||||
public void setSavedStatesManager(SavedStatesManager savedStatesManager)
|
||||
{
|
||||
this.stateManager = savedStatesManager;
|
||||
}
|
||||
|
||||
|
||||
public SavedStatesManager getSavedStatesManager()
|
||||
{
|
||||
return this.stateManager;
|
||||
|
@ -256,7 +255,7 @@ public class MainViewModel extends AbstractModel
|
|||
}
|
||||
//Read available saved states
|
||||
stateManager.readSavedStates();
|
||||
|
||||
|
||||
disableChangeNotification(false);
|
||||
notifyChangeForAllModels();
|
||||
//Do not reset unsaved for new entry
|
||||
|
@ -322,7 +321,7 @@ public class MainViewModel extends AbstractModel
|
|||
{
|
||||
return systemModel;
|
||||
}
|
||||
|
||||
|
||||
public SavedStatesModel getSavedStatesModel()
|
||||
{
|
||||
return stateModel;
|
||||
|
@ -492,7 +491,8 @@ public class MainViewModel extends AbstractModel
|
|||
if (infoModel.isNewGame() || infoModel.isTitleChanged())
|
||||
{
|
||||
//Update duplicate index
|
||||
infoModel.setDuplicateIndex(dbConnector.getGameDuplicateIndexToUse(infoModel.getTitle()));
|
||||
infoModel.setDuplicateIndex(dbConnector.getGameDuplicateIndexToUse(infoModel.getTitle(),
|
||||
this.selectedData.getGameId()));
|
||||
}
|
||||
|
||||
if (!validateRequiredFields().isEmpty())
|
||||
|
@ -589,7 +589,7 @@ public class MainViewModel extends AbstractModel
|
|||
|
||||
fileManager.saveFiles();
|
||||
stateManager.saveSavedStates();
|
||||
|
||||
|
||||
//Reset and images that where added previously
|
||||
infoModel.resetImagesAndOldFileNames();
|
||||
//Reset all models
|
||||
|
@ -835,14 +835,14 @@ public class MainViewModel extends AbstractModel
|
|||
{
|
||||
fileManager.runViceWithoutGame();
|
||||
}
|
||||
|
||||
|
||||
public void runSnapshotInVice(SavedStatesModel.SAVESTATE saveState)
|
||||
{
|
||||
fileManager.runSnapshotInVice(saveState);
|
||||
}
|
||||
|
||||
|
||||
public void checkEnablementOfPalNtscMenuItem(boolean check)
|
||||
{
|
||||
stateManager.checkEnablementOfPalNtscMenuItem(check);
|
||||
stateManager.checkEnablementOfPalNtscMenuItem(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,12 +113,8 @@ public class FileManager
|
|||
|
||||
public void saveFiles()
|
||||
{
|
||||
//Check if title is different that in db, then rename existing files!
|
||||
if (infoModel.isTitleChanged() || infoModel.isAnyScreenRenamed())
|
||||
{
|
||||
//Rename existing covers and screens and game file
|
||||
renameFiles();
|
||||
}
|
||||
//Rename existing covers and screens and game file if needed
|
||||
renameFiles();
|
||||
|
||||
//Fetch images that has been added
|
||||
BufferedImage cover = infoModel.getCoverImage();
|
||||
|
@ -352,14 +348,7 @@ public class FileManager
|
|||
public static String generateFileNameFromTitle(String title, int duplicateIndex)
|
||||
{
|
||||
// All uppercase letters
|
||||
// No spaces or special characters
|
||||
//The maxi game tool seems to work like this: truncate to 23 characters and then remove all special characters.
|
||||
if (title.length() > 23)
|
||||
{
|
||||
title = title.substring(0, 23);
|
||||
logger.debug("FileName: truncating to : {}", title);
|
||||
}
|
||||
// Do the conversion
|
||||
// No spaces or special characters, remove them first
|
||||
List<Character> forbiddenCharsList =
|
||||
" ,:'<27>-.!+*<>()/[]?|".chars().mapToObj(item -> (char) item).collect(Collectors.toList());
|
||||
|
||||
|
@ -367,11 +356,23 @@ public class FileManager
|
|||
title.chars().mapToObj(item -> (char) item).filter(character -> !forbiddenCharsList.contains(character))
|
||||
.map(Character::toUpperCase).collect(Collectors.toList());
|
||||
String newNameString = newName.stream().map(String::valueOf).collect(Collectors.joining());
|
||||
if (duplicateIndex > 0)
|
||||
|
||||
//The maxi game tool seems to truncate to a maximum length of 23 characters. Let's do the same here.
|
||||
if (newNameString.length() > 23)
|
||||
{
|
||||
newNameString = newNameString.substring(0, 23);
|
||||
logger.debug("FileName: truncating to : {}", title);
|
||||
}
|
||||
|
||||
//Just add the duplicate index if there are several games with the same name
|
||||
if (duplicateIndex > 0 && duplicateIndex < 10)
|
||||
{
|
||||
//Just add the duplicate index if there are several games with the same name
|
||||
newNameString = newNameString + "0" + duplicateIndex;
|
||||
}
|
||||
else if (duplicateIndex > 9)
|
||||
{
|
||||
newNameString = newNameString + duplicateIndex;
|
||||
}
|
||||
|
||||
logger.debug("Game title: \"{}\" ---- New fileName: \"{}\"", title, newNameString);
|
||||
return newNameString;
|
||||
|
|
Loading…
Reference in New Issue