From dd95a40d11131404c5f8f8fd5c96bdfd8afb4f13 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Thu, 20 Dec 2018 18:22:53 +0700 Subject: [PATCH] Add "Move to Trash" action to Filter Tools and add additional type filters that might come in handy when batch deleting clutter files --- source/net/filebot/media/MediaDetection.java | 4 +++ source/net/filebot/media/ReleaseInfo.java | 31 +++++++++++------ .../net/filebot/media/ReleaseInfo.properties | 3 ++ source/net/filebot/ui/filter/FileTree.java | 33 ++++++++++++++++++- source/net/filebot/ui/filter/FilterPanel.java | 12 +++++++ source/net/filebot/ui/filter/TypeTool.java | 7 ++-- source/net/filebot/util/FileUtilities.java | 23 +++++++++++-- 7 files changed, 97 insertions(+), 16 deletions(-) diff --git a/source/net/filebot/media/MediaDetection.java b/source/net/filebot/media/MediaDetection.java index 3f859b44..86e76500 100644 --- a/source/net/filebot/media/MediaDetection.java +++ b/source/net/filebot/media/MediaDetection.java @@ -85,6 +85,10 @@ public class MediaDetection { return releaseInfo.getClutterFileFilter(); } + public static FileFilter getClutterTypeFilter() { + return releaseInfo.getClutterTypeFilter(); + } + public static boolean isDiskFolder(File folder) { return getDiskFolderFilter().accept(folder); } diff --git a/source/net/filebot/media/ReleaseInfo.java b/source/net/filebot/media/ReleaseInfo.java index 43df71c5..a567b2df 100644 --- a/source/net/filebot/media/ReleaseInfo.java +++ b/source/net/filebot/media/ReleaseInfo.java @@ -44,7 +44,8 @@ import net.filebot.ApplicationFolder; import net.filebot.Cache; import net.filebot.CacheType; import net.filebot.Resource; -import net.filebot.util.FileUtilities.RegexFileFilter; +import net.filebot.util.FileUtilities.RegexFindFilter; +import net.filebot.util.FileUtilities.RegexMatchFilter; import net.filebot.util.SystemProperty; import net.filebot.web.Movie; import net.filebot.web.SearchResult; @@ -393,29 +394,38 @@ public class ReleaseInfo { return diskFolderFilter; } - private static RegexFileFilter diskFolderEntryFilter; + private static RegexMatchFilter diskFolderEntryFilter; public FileFilter getDiskFolderEntryFilter() { if (diskFolderEntryFilter == null) { - diskFolderEntryFilter = new RegexFileFilter(compile(getProperty("pattern.diskfolder.entry"))); + diskFolderEntryFilter = new RegexMatchFilter(compile(getProperty("pattern.diskfolder.entry"))); } return diskFolderEntryFilter; } + private static ClutterFileFilter clutterTypeFilter; + + public FileFilter getClutterTypeFilter() { + if (clutterTypeFilter == null) { + clutterTypeFilter = new ClutterFileFilter(new RegexFindFilter(compile(getProperty("pattern.clutter.types"), CASE_INSENSITIVE)), Long.parseLong(getProperty("number.clutter.maxfilesize"))); + } + return clutterTypeFilter; + } + private static ClutterFileFilter clutterFileFilter; public FileFilter getClutterFileFilter() { if (clutterFileFilter == null) { - clutterFileFilter = new ClutterFileFilter(getExcludePattern(), Long.parseLong(getProperty("number.clutter.maxfilesize"))); // only files smaller than 250 MB may be considered clutter + clutterFileFilter = new ClutterFileFilter(new FileFolderNameFilter(getExcludePattern()), Long.parseLong(getProperty("number.clutter.maxfilesize"))); } return clutterFileFilter; } - private static RegexFileFilter systemFilesFilter; + private static RegexMatchFilter systemFilesFilter; public FileFilter getSystemFilesFilter() { if (systemFilesFilter == null) { - systemFilesFilter = new RegexFileFilter(compile(getProperty("pattern.system.files"), CASE_INSENSITIVE)); + systemFilesFilter = new RegexMatchFilter(compile(getProperty("pattern.system.files"), CASE_INSENSITIVE)); } return systemFilesFilter; } @@ -535,18 +545,19 @@ public class ReleaseInfo { } } - public static class ClutterFileFilter extends FileFolderNameFilter { + public static class ClutterFileFilter implements FileFilter { + private FileFilter filter; private long maxFileSize; - public ClutterFileFilter(Pattern namePattern, long maxFileSize) { - super(namePattern); + public ClutterFileFilter(FileFilter filter, long maxFileSize) { + this.filter = filter; this.maxFileSize = maxFileSize; } @Override public boolean accept(File file) { - return super.accept(file) && file.isFile() && file.length() < maxFileSize; + return filter.accept(file) && file.isFile() && file.length() < maxFileSize; } } diff --git a/source/net/filebot/media/ReleaseInfo.properties b/source/net/filebot/media/ReleaseInfo.properties index 4b3abf20..7aad4793 100644 --- a/source/net/filebot/media/ReleaseInfo.properties +++ b/source/net/filebot/media/ReleaseInfo.properties @@ -19,6 +19,9 @@ pattern.video.format: DivX[345]?|Xvid|AVC|(x|h)[.]?(264|265)|HEVC|3ivx|PGS|MP[E] # clutter file exclude pattern pattern.clutter.excludes: (?<=[!\\-\\(\\[])(Sample|Trailer)|(Sample|Trailer)(?=[\\-\\)\\]])|(?<=[.\\-])(s|t|Sample|Trailer)$|(NCED|NCOP|(OP|ED)\\p{Digit}\\p{Alpha})|(Extras|Trailers|Featurettes|Interviews|Scenes|Shorts)$|Behind.the.Scenes|Deleted.and.Extended.Scenes|Deleted.Scenes +# clutter file types +pattern.clutter.types: [.](jpg|jpeg|png|gif|ico|nfo|info|xml|htm|html|log|m3u|cue|srt|sub|idx|smi|sup|md5|sfv|txt|rtf|url|db|dna|log|tgmd|json|data|ignore|srv|srr|nzb|vbs|ini|vsmeta|DS_Store)$ + # only files smaller than 150 MB may be considered clutter number.clutter.maxfilesize: 150000000 diff --git a/source/net/filebot/ui/filter/FileTree.java b/source/net/filebot/ui/filter/FileTree.java index 57cc6c4d..2aa97c39 100644 --- a/source/net/filebot/ui/filter/FileTree.java +++ b/source/net/filebot/ui/filter/FileTree.java @@ -2,6 +2,7 @@ package net.filebot.ui.filter; import static java.util.Collections.*; import static java.util.stream.Collectors.*; +import static net.filebot.Logging.*; import static net.filebot.util.ui.SwingUI.*; import java.awt.event.ActionEvent; @@ -14,12 +15,14 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTree; +import javax.swing.SwingUtilities; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; @@ -66,7 +69,7 @@ public class FileTree extends JTree { return file.getFile(); } return null; - }).collect(toList()); + }).filter(f -> f != null && f.exists()).collect(toList()); } public void clear() { @@ -109,6 +112,9 @@ public class FileTree extends JTree { add(newAction("Expand all", ResourceManager.getIcon("tree.expand"), evt -> expandAll())); add(newAction("Collapse all", ResourceManager.getIcon("tree.collapse"), evt -> collapseAll())); + + addSeparator(); + add(new TrashAction(selectedFiles)); } private Collection getFiles(TreePath[] selection) { @@ -148,6 +154,31 @@ public class FileTree extends JTree { } } + private class TrashAction extends AbstractAction { + + private Collection files; + + public TrashAction(Collection files) { + super("Move to Trash"); + this.files = files; + } + + @Override + public void actionPerformed(ActionEvent event) { + try { + for (File f : files) { + UserFiles.trash(f); + } + } catch (Exception e) { + log.log(Level.SEVERE, e, e::toString); + } + + // reload file tree after files have been deleted + FilterPanel parent = (FilterPanel) SwingUtilities.getAncestorOfClass(FilterPanel.class, FileTree.this); + parent.reload(); + } + } + private class ImportAction extends AbstractAction { private PanelBuilder panel; diff --git a/source/net/filebot/ui/filter/FilterPanel.java b/source/net/filebot/ui/filter/FilterPanel.java index 06243c52..f26fc5b2 100644 --- a/source/net/filebot/ui/filter/FilterPanel.java +++ b/source/net/filebot/ui/filter/FilterPanel.java @@ -1,12 +1,16 @@ package net.filebot.ui.filter; +import static net.filebot.Logging.*; + import java.awt.datatransfer.Transferable; +import java.util.logging.Level; import javax.swing.JComponent; import javax.swing.JTabbedPane; import com.google.common.eventbus.Subscribe; +import net.filebot.ui.transfer.FileTransferable; import net.filebot.ui.transfer.TransferablePolicy; import net.filebot.ui.transfer.TransferablePolicy.TransferAction; import net.miginfocom.swing.MigLayout; @@ -34,6 +38,14 @@ public class FilterPanel extends JComponent { toolsPanel.addTab(tool.getName(), tool); } + public void reload() { + try { + fileTreePanel.getTransferablePolicy().handleTransferable(new FileTransferable(fileTreePanel.getFileTree().getRoot()), TransferAction.PUT); + } catch (Exception e) { + debug.log(Level.WARNING, e, e::toString); + } + } + @Subscribe public void handle(Transferable transferable) throws Exception { TransferablePolicy handler = fileTreePanel.getTransferablePolicy(); diff --git a/source/net/filebot/ui/filter/TypeTool.java b/source/net/filebot/ui/filter/TypeTool.java index a06d3493..c09ae476 100644 --- a/source/net/filebot/ui/filter/TypeTool.java +++ b/source/net/filebot/ui/filter/TypeTool.java @@ -85,14 +85,15 @@ class TypeTool extends Tool { public Map getMetaTypes() { Map types = new LinkedHashMap(); - types.put("Movie", (f) -> MediaDetection.isMovie(f, true)); - types.put("Episode", (f) -> MediaDetection.isEpisode(f, true)); + types.put("Movie", f -> MediaDetection.isMovie(f, true)); + types.put("Episode", f -> MediaDetection.isEpisode(f, true)); + types.put("Extras", MediaDetection.getClutterFileFilter()); types.put("Video", MediaTypes.VIDEO_FILES); types.put("Subtitle", MediaTypes.SUBTITLE_FILES); types.put("Audio", MediaTypes.AUDIO_FILES); types.put("Archive", MediaTypes.ARCHIVE_FILES); types.put("Verification", MediaTypes.VERIFICATION_FILES); - types.put("Clutter", MediaDetection.getClutterFileFilter()); + types.put("Clutter", MediaDetection.getClutterTypeFilter()); types.put("Disk Folder", MediaDetection.getDiskFolderFilter()); return types; } diff --git a/source/net/filebot/util/FileUtilities.java b/source/net/filebot/util/FileUtilities.java index 6b082367..0372a17d 100644 --- a/source/net/filebot/util/FileUtilities.java +++ b/source/net/filebot/util/FileUtilities.java @@ -853,11 +853,11 @@ public final class FileUtilities { } } - public static class RegexFileFilter implements FileFilter, FilenameFilter { + public static class RegexMatchFilter implements FileFilter, FilenameFilter { private final Pattern pattern; - public RegexFileFilter(Pattern pattern) { + public RegexMatchFilter(Pattern pattern) { this.pattern = pattern; } @@ -872,6 +872,25 @@ public final class FileUtilities { } } + public static class RegexFindFilter implements FileFilter, FilenameFilter { + + private final Pattern pattern; + + public RegexFindFilter(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean accept(File dir, String name) { + return pattern.matcher(name).find(); + } + + @Override + public boolean accept(File file) { + return accept(file.getParentFile(), file.getName()); + } + } + public static final Comparator CASE_INSENSITIVE_PATH_ORDER = comparing(File::getPath, String.CASE_INSENSITIVE_ORDER); public static final Comparator HUMAN_NAME_ORDER = comparing(File::getName, new AlphanumComparator(Locale.ENGLISH));