Added methods to delete songs and song groups.
- OsuGroupList.get().deleteSongGroup() will delete a song group from the list. - OsuGroupList.get().deleteSong() will delete an individual song from the list (must be expanded), and will delete the song group if there are no remaining songs in the group. - If possible, deleted beatmap files are moved to system trash (using JNA); otherwise, they are deleted immediately. This is done through Utils.deleteToTrash(). Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
484bb1ba31
commit
b69ff68d7c
10
pom.xml
10
pom.xml
|
@ -143,5 +143,15 @@
|
|||
<artifactId>json</artifactId>
|
||||
<version>20140107</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<version>4.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -262,9 +262,9 @@ public class OsuFile implements Comparable<OsuFile> {
|
|||
try {
|
||||
Image bgImage = bgImageMap.get(this);
|
||||
if (bgImage == null) {
|
||||
bgImage = new Image(bg);
|
||||
if (bgImageMap.size() > MAX_CACHE_SIZE)
|
||||
clearImageCache();
|
||||
bgImage = new Image(bg);
|
||||
bgImageMap.put(this, bgImage);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package itdelatrisu.opsu;
|
||||
|
||||
import itdelatrisu.opsu.audio.MusicController;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -54,6 +58,9 @@ public class OsuGroupList {
|
|||
/** Index of current expanded node (-1 if no node is expanded). */
|
||||
private int expandedIndex;
|
||||
|
||||
/** Start and end nodes of expanded group. */
|
||||
private OsuGroupNode expandedStartNode, expandedEndNode;
|
||||
|
||||
/** The last search query. */
|
||||
private String lastQuery;
|
||||
|
||||
|
@ -83,6 +90,7 @@ public class OsuGroupList {
|
|||
public void reset() {
|
||||
nodes = parsedNodes;
|
||||
expandedIndex = -1;
|
||||
expandedStartNode = expandedEndNode = null;
|
||||
lastQuery = "";
|
||||
}
|
||||
|
||||
|
@ -109,6 +117,123 @@ public class OsuGroupList {
|
|||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a song group from the list, and also deletes the beatmap
|
||||
* directory associated with the node.
|
||||
* @param node the node containing the song group to delete
|
||||
* @return true if the song group was deleted, false otherwise
|
||||
*/
|
||||
public boolean deleteSongGroup(OsuGroupNode node) {
|
||||
if (node == null)
|
||||
return false;
|
||||
|
||||
// re-link base nodes
|
||||
int index = node.index;
|
||||
OsuGroupNode ePrev = getBaseNode(index - 1), eCur = getBaseNode(index), eNext = getBaseNode(index + 1);
|
||||
if (ePrev != null) {
|
||||
if (ePrev.index == expandedIndex)
|
||||
expandedEndNode.next = eNext;
|
||||
else if (eNext != null && eNext.index == expandedIndex)
|
||||
ePrev.next = expandedStartNode;
|
||||
else
|
||||
ePrev.next = eNext;
|
||||
}
|
||||
if (eNext != null) {
|
||||
if (eNext.index == expandedIndex)
|
||||
expandedStartNode.prev = ePrev;
|
||||
else if (ePrev != null && ePrev.index == expandedIndex)
|
||||
eNext.prev = expandedEndNode;
|
||||
else
|
||||
eNext.prev = ePrev;
|
||||
}
|
||||
|
||||
// remove all node references
|
||||
OsuFile osu = node.osuFiles.get(0);
|
||||
nodes.remove(index);
|
||||
parsedNodes.remove(eCur);
|
||||
mapCount -= node.osuFiles.size();
|
||||
if (osu.beatmapSetID > 0)
|
||||
MSIDdb.remove(osu.beatmapSetID);
|
||||
|
||||
// reset indices
|
||||
for (int i = index, size = size(); i < size; i++)
|
||||
nodes.get(i).index = i;
|
||||
if (index == expandedIndex) {
|
||||
expandedIndex = -1;
|
||||
expandedStartNode = expandedEndNode = null;
|
||||
} else if (expandedIndex > index) {
|
||||
expandedIndex--;
|
||||
OsuGroupNode expandedNode = expandedStartNode;
|
||||
for (int i = 0, size = expandedNode.osuFiles.size();
|
||||
i < size && expandedNode != null;
|
||||
i++, expandedNode = expandedNode.next)
|
||||
expandedNode.index = expandedIndex;
|
||||
}
|
||||
|
||||
// stop playing the track
|
||||
File dir = osu.getFile().getParentFile();
|
||||
if (MusicController.trackExists() || MusicController.isTrackLoading()) {
|
||||
File audioFile = MusicController.getOsuFile().audioFilename;
|
||||
if (audioFile != null && audioFile.equals(osu.audioFilename)) {
|
||||
MusicController.reset();
|
||||
System.gc(); // TODO: why can't files be deleted without calling this?
|
||||
}
|
||||
}
|
||||
|
||||
// delete the associated directory
|
||||
try {
|
||||
Utils.deleteToTrash(dir);
|
||||
} catch (IOException e) {
|
||||
ErrorHandler.error("Could not delete song group.", e, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a song from a song group, and also deletes the beatmap file.
|
||||
* If this causes the song group to be empty, then the song group and
|
||||
* beatmap directory will be deleted altogether.
|
||||
* @param node the node containing the song group to delete (expanded only)
|
||||
* @return true if the song or song group was deleted, false otherwise
|
||||
* @see #deleteSongGroup(OsuGroupNode)
|
||||
*/
|
||||
public boolean deleteSong(OsuGroupNode node) {
|
||||
if (node == null || node.osuFileIndex == -1 || node.index != expandedIndex)
|
||||
return false;
|
||||
|
||||
// last song in group?
|
||||
int size = node.osuFiles.size();
|
||||
if (node.osuFiles.size() == 1)
|
||||
return deleteSongGroup(node);
|
||||
|
||||
// reset indices
|
||||
OsuGroupNode expandedNode = node.next;
|
||||
for (int i = node.osuFileIndex + 1;
|
||||
i < size && expandedNode != null && expandedNode.index == node.index;
|
||||
i++, expandedNode = expandedNode.next)
|
||||
expandedNode.osuFileIndex--;
|
||||
|
||||
// remove song reference
|
||||
OsuFile osu = node.osuFiles.remove(node.osuFileIndex);
|
||||
mapCount--;
|
||||
|
||||
// re-link nodes
|
||||
if (node.prev != null)
|
||||
node.prev.next = node.next;
|
||||
if (node.next != null)
|
||||
node.next.prev = node.prev;
|
||||
|
||||
// delete the associated file
|
||||
try {
|
||||
Utils.deleteToTrash(osu.getFile());
|
||||
} catch (IOException e) {
|
||||
ErrorHandler.error("Could not delete song.", e, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of parsed maps (i.e. OsuFile objects).
|
||||
*/
|
||||
|
@ -169,13 +294,13 @@ public class OsuGroupList {
|
|||
if (node == null)
|
||||
return null;
|
||||
|
||||
OsuGroupNode firstInserted = null;
|
||||
expandedStartNode = expandedEndNode = null;
|
||||
|
||||
// create new nodes
|
||||
ArrayList<OsuFile> osuFiles = node.osuFiles;
|
||||
OsuGroupNode prevNode = node.prev;
|
||||
OsuGroupNode nextNode = node.next;
|
||||
for (int i = 0; i < node.osuFiles.size(); i++) {
|
||||
for (int i = 0, size = node.osuFiles.size(); i < size; i++) {
|
||||
OsuGroupNode newNode = new OsuGroupNode(osuFiles);
|
||||
newNode.index = index;
|
||||
newNode.osuFileIndex = i;
|
||||
|
@ -183,7 +308,7 @@ public class OsuGroupList {
|
|||
|
||||
// unlink the group node
|
||||
if (i == 0) {
|
||||
firstInserted = newNode;
|
||||
expandedStartNode = newNode;
|
||||
newNode.prev = prevNode;
|
||||
if (prevNode != null)
|
||||
prevNode.next = newNode;
|
||||
|
@ -196,9 +321,10 @@ public class OsuGroupList {
|
|||
node.next = nextNode;
|
||||
nextNode.prev = node;
|
||||
}
|
||||
expandedEndNode = node;
|
||||
|
||||
expandedIndex = index;
|
||||
return firstInserted;
|
||||
return expandedStartNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,6 +348,7 @@ public class OsuGroupList {
|
|||
eNext.prev = eCur;
|
||||
|
||||
expandedIndex = -1;
|
||||
expandedStartNode = expandedEndNode = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -235,6 +362,7 @@ public class OsuGroupList {
|
|||
// sort the list
|
||||
Collections.sort(nodes, SongSort.getSort().getComparator());
|
||||
expandedIndex = -1;
|
||||
expandedStartNode = expandedEndNode = null;
|
||||
|
||||
// create links
|
||||
OsuGroupNode lastNode = nodes.get(0);
|
||||
|
|
|
@ -72,9 +72,12 @@ public class OsuParser {
|
|||
* Invokes parser for each directory in the given array and
|
||||
* adds the OsuFiles to the existing OsuGroupList.
|
||||
* @param dirs the array of directories to parse
|
||||
* @return the last OsuGroupNode parsed
|
||||
* @return the last OsuGroupNode parsed, or null if none
|
||||
*/
|
||||
public static OsuGroupNode parseDirectories(File[] dirs) {
|
||||
if (dirs == null)
|
||||
return null;
|
||||
|
||||
// progress tracking
|
||||
currentDirectoryIndex = 0;
|
||||
totalDirectories = dirs.length;
|
||||
|
|
|
@ -56,7 +56,7 @@ public class OszUnpacker {
|
|||
return name.toLowerCase().endsWith(".osz");
|
||||
}
|
||||
});
|
||||
if (files.length < 1) {
|
||||
if (files == null || files.length < 1) {
|
||||
files = null;
|
||||
return new File[0];
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import itdelatrisu.opsu.downloads.DownloadNode;
|
|||
import java.awt.Font;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -55,6 +56,8 @@ import org.newdawn.slick.state.StateBasedGame;
|
|||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
import com.sun.jna.platform.FileUtils;
|
||||
|
||||
/**
|
||||
* Contains miscellaneous utilities.
|
||||
*/
|
||||
|
@ -738,4 +741,60 @@ public class Utils {
|
|||
}
|
||||
return cleanName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file or directory. If a system trash directory is available,
|
||||
* the file or directory will be moved there instead.
|
||||
* @param file the file or directory to delete
|
||||
* @return true if moved to trash, and false if deleted
|
||||
* @throws IOException if given file does not exist
|
||||
*/
|
||||
public static boolean deleteToTrash(File file) throws IOException {
|
||||
if (file == null)
|
||||
throw new IOException("File cannot be null.");
|
||||
if (!file.exists())
|
||||
throw new IOException(String.format("File '%s' does not exist.", file.getAbsolutePath()));
|
||||
|
||||
// move to system trash, if possible
|
||||
FileUtils fileUtils = FileUtils.getInstance();
|
||||
if (fileUtils.hasTrash()) {
|
||||
try {
|
||||
fileUtils.moveToTrash(new File[] { file });
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.warn(String.format("Failed to move file '%s' to trash.", file.getAbsolutePath()), e);
|
||||
}
|
||||
}
|
||||
|
||||
// delete otherwise
|
||||
if (file.isDirectory())
|
||||
deleteDirectory(file);
|
||||
else
|
||||
file.delete();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively deletes all files and folders in a directory, then
|
||||
* deletes the directory itself.
|
||||
* @param dir the directory to delete
|
||||
*/
|
||||
private static void deleteDirectory(File dir) {
|
||||
if (dir == null || !dir.isDirectory())
|
||||
return;
|
||||
|
||||
// recursively delete contents of directory
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory())
|
||||
deleteDirectory(file);
|
||||
else
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
// delete the directory
|
||||
dir.delete();
|
||||
}
|
||||
}
|
|
@ -396,6 +396,8 @@ public class SongMenu extends BasicGameState {
|
|||
|
||||
// search produced new list: re-initialize it
|
||||
startNode = focusNode = null;
|
||||
scoreMap = null;
|
||||
focusScores = null;
|
||||
if (OsuGroupList.get().size() > 0) {
|
||||
OsuGroupList.get().init();
|
||||
if (search.getText().isEmpty()) { // cleared search
|
||||
|
@ -606,6 +608,8 @@ public class SongMenu extends BasicGameState {
|
|||
// reset state and node references
|
||||
MusicController.reset();
|
||||
startNode = focusNode = null;
|
||||
scoreMap = null;
|
||||
focusScores = null;
|
||||
oldFocusNode = null;
|
||||
randomStack = new Stack<SongNode>();
|
||||
songInfo = null;
|
||||
|
|
Loading…
Reference in New Issue
Block a user