Refactor Filter / Tools
This commit is contained in:
parent
fcf3bd75f2
commit
8656af9508
|
@ -8,6 +8,7 @@ import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
|
@ -48,10 +49,10 @@ class AttributeTool extends Tool<TableModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createModelInBackground(File root) {
|
protected TableModel createModelInBackground(List<File> root) {
|
||||||
FileAttributesTableModel model = new FileAttributesTableModel();
|
FileAttributesTableModel model = new FileAttributesTableModel();
|
||||||
|
|
||||||
if (root == null) {
|
if (root.isEmpty()) {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +75,10 @@ class AttributeTool extends Tool<TableModel> {
|
||||||
model.addRow(String.format("%s::%d", "OMDb", movie.getImdbId()), metaObject, originalName, file);
|
model.addRow(String.format("%s::%d", "OMDb", movie.getImdbId()), metaObject, originalName, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new CancellationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
|
|
@ -2,11 +2,10 @@ package net.filebot.ui.filter;
|
||||||
|
|
||||||
import static net.filebot.Logging.*;
|
import static net.filebot.Logging.*;
|
||||||
import static net.filebot.UserFiles.*;
|
import static net.filebot.UserFiles.*;
|
||||||
import static net.filebot.util.ExceptionUtilities.*;
|
|
||||||
import static net.filebot.util.FileUtilities.*;
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
import static net.filebot.util.ui.SwingUI.*;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -21,7 +20,6 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
|
@ -76,8 +74,8 @@ class ExtractTool extends Tool<TableModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createModelInBackground(File root) throws InterruptedException {
|
protected TableModel createModelInBackground(List<File> root) throws Exception {
|
||||||
if (root == null) {
|
if (root.isEmpty()) {
|
||||||
return new ArchiveEntryModel();
|
return new ArchiveEntryModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,46 +83,34 @@ class ExtractTool extends Tool<TableModel> {
|
||||||
List<File> files = listFiles(root, Archive.VOLUME_ONE_FILTER, HUMAN_NAME_ORDER);
|
List<File> files = listFiles(root, Archive.VOLUME_ONE_FILTER, HUMAN_NAME_ORDER);
|
||||||
List<ArchiveEntry> entries = new ArrayList<ArchiveEntry>();
|
List<ArchiveEntry> entries = new ArrayList<ArchiveEntry>();
|
||||||
|
|
||||||
try {
|
for (File file : files) {
|
||||||
for (File file : files) {
|
try (Archive archive = Archive.open(file)) {
|
||||||
try (Archive archive = Archive.open(file)) {
|
for (FileInfo it : archive.listFiles()) {
|
||||||
for (FileInfo it : archive.listFiles()) {
|
entries.add(new ArchiveEntry(file, it));
|
||||||
entries.add(new ArchiveEntry(file, it));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unwind thread, if we have been cancelled
|
|
||||||
if (Thread.interrupted()) {
|
|
||||||
throw new InterruptedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// unwind thread, if we have been cancelled
|
// unwind thread, if we have been cancelled
|
||||||
if (findCause(e, InterruptedException.class) != null) {
|
if (Thread.interrupted()) {
|
||||||
throw findCause(e, InterruptedException.class);
|
throw new CancellationException();
|
||||||
}
|
}
|
||||||
log.log(Level.WARNING, e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ArchiveEntryModel(entries);
|
return new ArchiveEntryModel(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action extractAction = new AbstractAction("Extract All", ResourceManager.getIcon("package.extract")) {
|
private Action extractAction = newAction("Extract All", ResourceManager.getIcon("package.extract"), evt -> {
|
||||||
|
List<File> archives = ((ArchiveEntryModel) table.getModel()).getArchiveList();
|
||||||
|
if (archives.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
@Override
|
File selectedFile = showOpenDialogSelectFolder(archives.get(0).getParentFile(), "Extract to ...", evt);
|
||||||
public void actionPerformed(ActionEvent evt) {
|
if (selectedFile == null)
|
||||||
final List<File> archives = ((ArchiveEntryModel) table.getModel()).getArchiveList();
|
return;
|
||||||
if (archives.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
File selectedFile = showOpenDialogSelectFolder(archives.get(0).getParentFile(), "Extract to ...", evt);
|
ExtractWorker worker = new ExtractWorker(archives, selectedFile, null, true, ConflictAction.AUTO);
|
||||||
if (selectedFile == null)
|
ProgressMonitor.runTask("Extract", "Extracting files...", worker);
|
||||||
return;
|
});
|
||||||
|
|
||||||
ExtractWorker worker = new ExtractWorker(archives, selectedFile, null, true, ConflictAction.AUTO);
|
|
||||||
ProgressMonitor.runTask("Extract", "Extracting files...", worker);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static class ArchiveEntry {
|
private static class ArchiveEntry {
|
||||||
|
|
||||||
|
@ -199,7 +185,7 @@ class ExtractTool extends Tool<TableModel> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class ExtractWorker implements ProgressWorker<Void> {
|
private static class ExtractWorker implements ProgressWorker<Void> {
|
||||||
|
|
||||||
private final File[] archives;
|
private final File[] archives;
|
||||||
private final File outputFolder;
|
private final File outputFolder;
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -54,8 +53,20 @@ public class FileTree extends JTree {
|
||||||
return (DefaultTreeModel) super.getModel();
|
return (DefaultTreeModel) super.getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FolderNode getRoot() {
|
public List<File> getRoot() {
|
||||||
return (FolderNode) getModel().getRoot();
|
FolderNode model = (FolderNode) getModel().getRoot();
|
||||||
|
|
||||||
|
return model.getChildren().stream().map(node -> {
|
||||||
|
if (node instanceof FolderNode) {
|
||||||
|
FolderNode folder = (FolderNode) node;
|
||||||
|
return folder.getFile();
|
||||||
|
}
|
||||||
|
if (node instanceof FileNode) {
|
||||||
|
FileNode file = (FileNode) node;
|
||||||
|
return file.getFile();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}).collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -258,15 +269,16 @@ public class FileTree extends JTree {
|
||||||
private final String title;
|
private final String title;
|
||||||
private final List<TreeNode> children;
|
private final List<TreeNode> children;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a root node (no parent, no title, empty list of children)
|
|
||||||
*/
|
|
||||||
public FolderNode() {
|
public FolderNode() {
|
||||||
this(null, "", new ArrayList<TreeNode>(0));
|
this(emptyList()); // empty root node
|
||||||
|
}
|
||||||
|
|
||||||
|
public FolderNode(List<TreeNode> children) {
|
||||||
|
this(null, "/", children); // root node
|
||||||
}
|
}
|
||||||
|
|
||||||
public FolderNode(String title, List<TreeNode> children) {
|
public FolderNode(String title, List<TreeNode> children) {
|
||||||
this(null, title, children);
|
this(null, title, children); // virtual node
|
||||||
}
|
}
|
||||||
|
|
||||||
public FolderNode(File file, String title, List<TreeNode> children) {
|
public FolderNode(File file, String title, List<TreeNode> children) {
|
||||||
|
@ -318,8 +330,9 @@ public class FileTree extends JTree {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Iterator<TreeNode> children(TreeNode node) {
|
protected Iterator<TreeNode> children(TreeNode node) {
|
||||||
if (node instanceof FolderNode)
|
if (node instanceof FolderNode) {
|
||||||
return ((FolderNode) node).getChildren().iterator();
|
return ((FolderNode) node).getChildren().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
// can't step into non-folder nodes
|
// can't step into non-folder nodes
|
||||||
return null;
|
return null;
|
||||||
|
@ -333,8 +346,9 @@ public class FileTree extends JTree {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File filter(TreeNode node) {
|
protected File filter(TreeNode node) {
|
||||||
if (node instanceof FileNode)
|
if (node instanceof FileNode) {
|
||||||
return ((FileNode) node).getFile();
|
return ((FileNode) node).getFile();
|
||||||
|
}
|
||||||
|
|
||||||
// filter out non-file nodes
|
// filter out non-file nodes
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -63,8 +63,10 @@ class FileTreePanel extends JComponent {
|
||||||
fireFileTreeChange();
|
fireFileTreeChange();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public static final String FILE_TREE_PROPERTY = "FILE_TREE";
|
||||||
|
|
||||||
private void fireFileTreeChange() {
|
private void fireFileTreeChange() {
|
||||||
firePropertyChange("filetree", null, fileTree);
|
firePropertyChange(FILE_TREE_PROPERTY, null, fileTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,15 @@ package net.filebot.ui.filter;
|
||||||
|
|
||||||
import static net.filebot.Logging.*;
|
import static net.filebot.Logging.*;
|
||||||
import static net.filebot.Settings.*;
|
import static net.filebot.Settings.*;
|
||||||
|
import static net.filebot.util.ExceptionUtilities.*;
|
||||||
import static net.filebot.util.FileUtilities.*;
|
import static net.filebot.util.FileUtilities.*;
|
||||||
import static net.filebot.util.ui.SwingUI.*;
|
import static net.filebot.util.ui.SwingUI.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.swing.tree.TreeNode;
|
import javax.swing.tree.TreeNode;
|
||||||
|
@ -18,7 +19,6 @@ import net.filebot.mac.MacAppUtilities;
|
||||||
import net.filebot.ui.filter.FileTree.FileNode;
|
import net.filebot.ui.filter.FileTree.FileNode;
|
||||||
import net.filebot.ui.filter.FileTree.FolderNode;
|
import net.filebot.ui.filter.FileTree.FolderNode;
|
||||||
import net.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
import net.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
||||||
import net.filebot.util.ExceptionUtilities;
|
|
||||||
import net.filebot.util.FastFile;
|
import net.filebot.util.FastFile;
|
||||||
|
|
||||||
class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<TreeNode> {
|
class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<TreeNode> {
|
||||||
|
@ -42,46 +42,36 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<TreeNo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void process(List<TreeNode> root) {
|
protected void process(List<TreeNode> root) {
|
||||||
tree.getModel().setRoot(root.get(0));
|
tree.getModel().setRoot(new FolderNode(root));
|
||||||
tree.getModel().reload();
|
tree.getModel().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void process(Exception e) {
|
protected void process(Exception e) {
|
||||||
log.log(Level.WARNING, ExceptionUtilities.getRootCauseMessage(e), e);
|
log.log(Level.WARNING, getRootCauseMessage(e), e);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleInBackground(List<File> files, TransferAction action) {
|
|
||||||
super.handleInBackground(files, action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void load(List<File> files, TransferAction action) {
|
protected void load(List<File> files, TransferAction action) {
|
||||||
|
// make sure we have access to the parent folder structure, not just the dropped file
|
||||||
|
if (isMacSandbox()) {
|
||||||
|
MacAppUtilities.askUnlockFolders(getWindow(tree), files);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (files.size() > 1 || containsOnly(files, FILES)) {
|
|
||||||
files = Arrays.asList(files.get(0).getParentFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we have access to the parent folder structure, not just the dropped file
|
|
||||||
if (isMacSandbox()) {
|
|
||||||
MacAppUtilities.askUnlockFolders(getWindow(tree), files);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use fast file to minimize system calls like length(), isDirectory(), isFile(), ...
|
// use fast file to minimize system calls like length(), isDirectory(), isFile(), ...
|
||||||
FastFile root = new FastFile(filter(files, FOLDERS).get(0));
|
TreeNode[] node = files.stream().map(FastFile::new).map(this::getTreeNode).toArray(TreeNode[]::new);
|
||||||
|
|
||||||
// publish on EDT
|
// publish on EDT
|
||||||
TreeNode[] node = { getTreeNode(root) };
|
|
||||||
publish(node);
|
publish(node);
|
||||||
} catch (InterruptedException e) {
|
} catch (CancellationException e) {
|
||||||
// supposed to happen if background execution was aborted
|
// supposed to happen if background execution was aborted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TreeNode getTreeNode(File file) throws InterruptedException {
|
private TreeNode getTreeNode(File file) {
|
||||||
if (Thread.interrupted()) {
|
if (Thread.interrupted()) {
|
||||||
throw new InterruptedException();
|
throw new CancellationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
|
|
|
@ -21,11 +21,11 @@ public class FilterPanel extends JComponent {
|
||||||
add(fileTreePanel, "grow 1, w 300:pref:500");
|
add(fileTreePanel, "grow 1, w 300:pref:500");
|
||||||
add(toolsPanel, "grow 2");
|
add(toolsPanel, "grow 2");
|
||||||
|
|
||||||
fileTreePanel.addPropertyChangeListener("filetree", evt -> {
|
fileTreePanel.addPropertyChangeListener(FileTreePanel.FILE_TREE_PROPERTY, evt -> {
|
||||||
// stopped loading, refresh tools
|
// stopped loading, refresh tools
|
||||||
for (int i = 0; i < toolsPanel.getTabCount(); i++) {
|
for (int i = 0; i < toolsPanel.getTabCount(); i++) {
|
||||||
Tool<?> tool = (Tool<?>) toolsPanel.getComponentAt(i);
|
Tool<?> tool = (Tool<?>) toolsPanel.getComponentAt(i);
|
||||||
tool.updateRoot(fileTreePanel.getFileTree().getRoot().getFile());
|
tool.setRoot(fileTreePanel.getFileTree().getRoot());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
@ -53,8 +54,8 @@ class MediaInfoTool extends Tool<TableModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createModelInBackground(File root) {
|
protected TableModel createModelInBackground(List<File> root) {
|
||||||
if (root == null) {
|
if (root.isEmpty()) {
|
||||||
return new MediaInfoTableModel();
|
return new MediaInfoTableModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +75,13 @@ class MediaInfoTool extends Tool<TableModel> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
debug.finest(e.getMessage());
|
debug.finest(e::toString);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
debug.warning(e.getMessage());
|
debug.warning(e::toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new CancellationException();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,12 @@ import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSpinner;
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.SpinnerNumberModel;
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
import javax.swing.event.ChangeListener;
|
|
||||||
import javax.swing.tree.DefaultTreeModel;
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
import javax.swing.tree.TreeModel;
|
import javax.swing.tree.TreeModel;
|
||||||
import javax.swing.tree.TreeNode;
|
import javax.swing.tree.TreeNode;
|
||||||
|
@ -51,14 +50,11 @@ class SplitTool extends Tool<TreeModel> {
|
||||||
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
||||||
tree.setDragEnabled(true);
|
tree.setDragEnabled(true);
|
||||||
|
|
||||||
spinnerModel.addChangeListener(new ChangeListener() {
|
// update model in foreground, will be much faster than the initial load because length() is cached now
|
||||||
|
spinnerModel.addChangeListener(evt -> {
|
||||||
@Override
|
List<File> root = getRoot();
|
||||||
public void stateChanged(ChangeEvent evt) {
|
if (root.size() > 0) {
|
||||||
// update model in foreground, will be much faster than the initial load because length() is cached now
|
setRoot(root);
|
||||||
if (getRoot() != null) {
|
|
||||||
updateRoot(getRoot());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -68,8 +64,8 @@ class SplitTool extends Tool<TreeModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TreeModel createModelInBackground(File root) throws InterruptedException {
|
protected TreeModel createModelInBackground(List<File> root) {
|
||||||
if (root == null) {
|
if (root.isEmpty()) {
|
||||||
return new DefaultTreeModel(new FolderNode("Volumes", emptyList()));
|
return new DefaultTreeModel(new FolderNode("Volumes", emptyList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +89,7 @@ class SplitTool extends Tool<TreeModel> {
|
||||||
|
|
||||||
if (totalSize + fileSize > splitSize) {
|
if (totalSize + fileSize > splitSize) {
|
||||||
// part is full, add node and start with next one
|
// part is full, add node and start with next one
|
||||||
rootGroup.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
rootGroup.add(createStatisticsNode(nextPart++, currentPart));
|
||||||
|
|
||||||
// reset total size and file list
|
// reset total size and file list
|
||||||
totalSize = 0;
|
totalSize = 0;
|
||||||
|
@ -102,11 +98,15 @@ class SplitTool extends Tool<TreeModel> {
|
||||||
|
|
||||||
totalSize += fileSize;
|
totalSize += fileSize;
|
||||||
currentPart.add(f);
|
currentPart.add(f);
|
||||||
|
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new CancellationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentPart.isEmpty()) {
|
if (!currentPart.isEmpty()) {
|
||||||
// add last part
|
// add last part
|
||||||
rootGroup.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
rootGroup.add(createStatisticsNode(nextPart++, currentPart));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remainder.isEmpty()) {
|
if (!remainder.isEmpty()) {
|
||||||
|
@ -121,4 +121,9 @@ class SplitTool extends Tool<TreeModel> {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected FolderNode createStatisticsNode(int disk, List<File> files) {
|
||||||
|
System.out.println(files);
|
||||||
|
return createStatisticsNode(String.format("Disk %,d", disk), files);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,66 @@
|
||||||
package net.filebot.ui.filter;
|
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.Logging.*;
|
||||||
|
import static net.filebot.util.ExceptionUtilities.*;
|
||||||
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.ConcurrentModificationException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
import javax.swing.tree.TreeNode;
|
import javax.swing.tree.TreeNode;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import net.filebot.ui.filter.FileTree.FileNode;
|
import net.filebot.ui.filter.FileTree.FileNode;
|
||||||
import net.filebot.ui.filter.FileTree.FolderNode;
|
import net.filebot.ui.filter.FileTree.FolderNode;
|
||||||
import net.filebot.util.ExceptionUtilities;
|
|
||||||
import net.filebot.util.FileUtilities;
|
import net.filebot.util.FileUtilities;
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
|
|
||||||
abstract class Tool<M> extends JComponent {
|
abstract class Tool<M> extends JComponent {
|
||||||
|
|
||||||
private UpdateModelTask updateTask = null;
|
private List<File> root = emptyList();
|
||||||
private File root = null;
|
|
||||||
|
private UpdateModelTask updateTask;
|
||||||
|
|
||||||
public Tool(String name) {
|
public Tool(String name) {
|
||||||
setName(name);
|
setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getRoot() {
|
public List<File> getRoot() {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRoot(File root) {
|
public void setRoot(List<File> root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
|
|
||||||
if (updateTask != null) {
|
if (updateTask != null) {
|
||||||
updateTask.cancel(true);
|
updateTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, false, true);
|
setLoading(true);
|
||||||
|
|
||||||
updateTask = new UpdateModelTask(root);
|
updateTask = new UpdateModelTask(root);
|
||||||
updateTask.execute();
|
updateTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract M createModelInBackground(File root) throws InterruptedException;
|
protected void setLoading(boolean loading) {
|
||||||
|
firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, !loading, loading);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract M createModelInBackground(List<File> root) throws Exception;
|
||||||
|
|
||||||
protected abstract void setModel(M model);
|
protected abstract void setModel(M model);
|
||||||
|
|
||||||
private class UpdateModelTask extends SwingWorker<M, Void> {
|
private class UpdateModelTask extends SwingWorker<M, Void> {
|
||||||
|
|
||||||
private final File root;
|
private final List<File> root;
|
||||||
|
|
||||||
public UpdateModelTask(File root) {
|
public UpdateModelTask(List<File> root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +72,7 @@ abstract class Tool<M> extends JComponent {
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
if (this == updateTask) {
|
if (this == updateTask) {
|
||||||
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, true, false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update task will only be cancelled if a newer update task has been started
|
// update task will only be cancelled if a newer update task has been started
|
||||||
|
@ -74,14 +80,12 @@ abstract class Tool<M> extends JComponent {
|
||||||
try {
|
try {
|
||||||
setModel(get());
|
setModel(get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Throwable cause = ExceptionUtilities.getRootCause(e);
|
Throwable cause = getRootCause(e);
|
||||||
|
|
||||||
if (cause instanceof ConcurrentModificationException || cause instanceof InterruptedException) {
|
if (cause instanceof InterruptedException || cause instanceof CancellationException) {
|
||||||
// if it happens, it is supposed to
|
debug.log(Level.FINEST, e, e::toString); // if it happens, it is supposed to
|
||||||
debug.log(Level.FINEST, e.getMessage(), e);
|
|
||||||
} else {
|
} else {
|
||||||
// should not happen
|
debug.log(Level.WARNING, e, e::toString); // should not happen
|
||||||
debug.log(Level.WARNING, e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,26 +93,17 @@ abstract class Tool<M> extends JComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<TreeNode> createFileNodes(Collection<File> files) {
|
protected List<TreeNode> createFileNodes(Collection<File> files) {
|
||||||
List<TreeNode> nodes = new ArrayList<TreeNode>(files.size());
|
return files.stream().map(FileNode::new).collect(toList());
|
||||||
for (File f : files) {
|
|
||||||
nodes.add(new FileNode(f));
|
|
||||||
}
|
|
||||||
return nodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FolderNode createStatisticsNode(String name, List<File> files) {
|
protected FolderNode createStatisticsNode(String name, List<File> files) {
|
||||||
long totalCount = 0;
|
List<File> selection = listFiles(files, FILES, null);
|
||||||
long totalSize = 0;
|
long size = selection.stream().mapToLong(File::length).sum();
|
||||||
|
|
||||||
for (File f : files) {
|
|
||||||
totalCount += FileUtilities.listFiles(f, FileUtilities.FILES).size();
|
|
||||||
totalSize += FileUtils.sizeOf(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set node text (e.g. txt (1 file, 42 Byte))
|
// set node text (e.g. txt (1 file, 42 Byte))
|
||||||
String title = String.format("%s (%,d %s, %s)", name, totalCount, totalCount == 1 ? "file" : "files", FileUtilities.formatSize(totalSize));
|
String title = String.format("%s (%,d %s, %s)", name, selection.size(), selection.size() == 1 ? "file" : "files", FileUtilities.formatSize(size));
|
||||||
|
|
||||||
return new FolderNode(null, title, createFileNodes(files));
|
return new FolderNode(title, createFileNodes(files));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
@ -44,12 +45,13 @@ class TypeTool extends Tool<TreeModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TreeModel createModelInBackground(File root) throws InterruptedException {
|
protected TreeModel createModelInBackground(List<File> root) {
|
||||||
if (root == null) {
|
if (root.isEmpty()) {
|
||||||
return new DefaultTreeModel(new FolderNode("Types", emptyList()));
|
return new DefaultTreeModel(new FolderNode("Types", emptyList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<File> filesAndFolders = listFiles(root, NOT_HIDDEN, HUMAN_NAME_ORDER);
|
List<File> filesAndFolders = listFiles(root, NOT_HIDDEN, HUMAN_NAME_ORDER);
|
||||||
|
|
||||||
List<TreeNode> groups = new ArrayList<TreeNode>();
|
List<TreeNode> groups = new ArrayList<TreeNode>();
|
||||||
|
|
||||||
for (Entry<String, FileFilter> it : getMetaTypes().entrySet()) {
|
for (Entry<String, FileFilter> it : getMetaTypes().entrySet()) {
|
||||||
|
@ -57,15 +59,24 @@ class TypeTool extends Tool<TreeModel> {
|
||||||
if (selection.size() > 0) {
|
if (selection.size() > 0) {
|
||||||
groups.add(createStatisticsNode(it.getKey(), selection));
|
groups.add(createStatisticsNode(it.getKey(), selection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new CancellationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedMap<String, TreeNode> extensionGroups = new TreeMap<String, TreeNode>(String.CASE_INSENSITIVE_ORDER);
|
SortedMap<String, TreeNode> extensionGroups = new TreeMap<String, TreeNode>(String.CASE_INSENSITIVE_ORDER);
|
||||||
for (Entry<String, List<File>> it : mapByExtension(filter(filesAndFolders, FILES)).entrySet()) {
|
|
||||||
if (it.getKey() == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
extensionGroups.put(it.getKey(), createStatisticsNode(it.getKey(), it.getValue()));
|
for (Entry<String, List<File>> it : mapByExtension(filter(filesAndFolders, FILES)).entrySet()) {
|
||||||
|
if (it.getKey() != null) {
|
||||||
|
extensionGroups.put(it.getKey(), createStatisticsNode(it.getKey(), it.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
throw new CancellationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.addAll(extensionGroups.values());
|
groups.addAll(extensionGroups.values());
|
||||||
|
|
||||||
// create tree model
|
// create tree model
|
||||||
|
|
Loading…
Reference in New Issue