* rewrite Analyze panel
This commit is contained in:
parent
7385a8d307
commit
3678e7388d
|
@ -42,7 +42,7 @@ public class AnalyzePanel extends JComponent {
|
||||||
// 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.setSourceModel(fileTreePanel.getFileTree().getRoot());
|
tool.updateRoot(fileTreePanel.getFileTree().getRoot().getFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static net.filebot.MediaTypes.*;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -16,13 +16,13 @@ import javax.swing.JTable;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
import net.filebot.media.MetaAttributes;
|
import net.filebot.media.MetaAttributes;
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
import net.filebot.util.FileUtilities;
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
import net.filebot.web.Episode;
|
import net.filebot.web.Episode;
|
||||||
import net.filebot.web.Movie;
|
import net.filebot.web.Movie;
|
||||||
import net.filebot.web.SearchResult;
|
import net.filebot.web.SearchResult;
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
class AttributeTool extends Tool<TableModel> {
|
class AttributeTool extends Tool<TableModel> {
|
||||||
|
|
||||||
|
@ -44,12 +44,11 @@ class AttributeTool extends Tool<TableModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createModelInBackground(FolderNode sourceModel) throws InterruptedException {
|
protected TableModel createModelInBackground(File root) throws InterruptedException {
|
||||||
|
List<File> files = (root != null) ? FileUtilities.listFiles(root) : Collections.emptyList();
|
||||||
|
|
||||||
FileAttributesTableModel model = new FileAttributesTableModel();
|
FileAttributesTableModel model = new FileAttributesTableModel();
|
||||||
|
for (File file : files) {
|
||||||
for (Iterator<File> iterator = sourceModel.fileIterator(); iterator.hasNext();) {
|
|
||||||
File file = iterator.next();
|
|
||||||
|
|
||||||
if (VIDEO_FILES.accept(file)) {
|
if (VIDEO_FILES.accept(file)) {
|
||||||
try {
|
try {
|
||||||
MetaAttributes attributes = new MetaAttributes(file);
|
MetaAttributes attributes = new MetaAttributes(file);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import java.beans.PropertyChangeEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -31,11 +31,9 @@ import javax.swing.SwingWorker;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
import net.filebot.ResourceManager;
|
import net.filebot.ResourceManager;
|
||||||
import net.filebot.archive.Archive;
|
import net.filebot.archive.Archive;
|
||||||
import net.filebot.archive.FileMapper;
|
import net.filebot.archive.FileMapper;
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
|
||||||
import net.filebot.util.FileUtilities;
|
import net.filebot.util.FileUtilities;
|
||||||
import net.filebot.util.ui.GradientStyle;
|
import net.filebot.util.ui.GradientStyle;
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
|
@ -44,6 +42,7 @@ import net.filebot.util.ui.ProgressDialog.Cancellable;
|
||||||
import net.filebot.util.ui.SwingWorkerPropertyChangeAdapter;
|
import net.filebot.util.ui.SwingWorkerPropertyChangeAdapter;
|
||||||
import net.filebot.util.ui.notification.SeparatorBorder;
|
import net.filebot.util.ui.notification.SeparatorBorder;
|
||||||
import net.filebot.vfs.FileInfo;
|
import net.filebot.vfs.FileInfo;
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
class ExtractTool extends Tool<TableModel> {
|
class ExtractTool extends Tool<TableModel> {
|
||||||
|
|
||||||
|
@ -73,13 +72,12 @@ class ExtractTool extends Tool<TableModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createModelInBackground(FolderNode sourceModel) throws InterruptedException {
|
protected TableModel createModelInBackground(File root) throws InterruptedException {
|
||||||
|
List<File> files = (root != null) ? FileUtilities.listFiles(root) : Collections.emptyList();
|
||||||
|
|
||||||
List<ArchiveEntry> entries = new ArrayList<ArchiveEntry>();
|
List<ArchiveEntry> entries = new ArrayList<ArchiveEntry>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (Iterator<File> iterator = sourceModel.fileIterator(); iterator.hasNext();) {
|
for (File file : files) {
|
||||||
File file = iterator.next();
|
|
||||||
|
|
||||||
// ignore non-archives files and trailing multi-volume parts
|
// ignore non-archives files and trailing multi-volume parts
|
||||||
if (Archive.VOLUME_ONE_FILTER.accept(file)) {
|
if (Archive.VOLUME_ONE_FILTER.accept(file)) {
|
||||||
Archive archive = new Archive(file);
|
Archive archive = new Archive(file);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
import static java.util.Collections.*;
|
||||||
import static net.filebot.ui.NotificationLogging.*;
|
import static net.filebot.ui.NotificationLogging.*;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
|
@ -10,11 +9,8 @@ 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.Collections;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -36,117 +32,89 @@ import net.filebot.util.ExceptionUtilities;
|
||||||
import net.filebot.util.FilterIterator;
|
import net.filebot.util.FilterIterator;
|
||||||
import net.filebot.util.TreeIterator;
|
import net.filebot.util.TreeIterator;
|
||||||
|
|
||||||
|
|
||||||
public class FileTree extends JTree {
|
public class FileTree extends JTree {
|
||||||
|
|
||||||
public FileTree() {
|
public FileTree() {
|
||||||
super(new DefaultTreeModel(new FolderNode()));
|
super(new DefaultTreeModel(new FolderNode()));
|
||||||
getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
||||||
setCellRenderer(new FileTreeCellRenderer());
|
setCellRenderer(new FileTreeCellRenderer());
|
||||||
setShowsRootHandles(true);
|
setShowsRootHandles(true);
|
||||||
setRootVisible(false);
|
setRootVisible(false);
|
||||||
|
|
||||||
setRowHeight(22);
|
setRowHeight(22);
|
||||||
setLargeModel(true);
|
setLargeModel(true);
|
||||||
|
|
||||||
addMouseListener(new ExpandCollapsePopupListener());
|
addMouseListener(new ExpandCollapsePopupListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultTreeModel getModel() {
|
public DefaultTreeModel getModel() {
|
||||||
return (DefaultTreeModel) super.getModel();
|
return (DefaultTreeModel) super.getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FolderNode getRoot() {
|
public FolderNode getRoot() {
|
||||||
return (FolderNode) getModel().getRoot();
|
return (FolderNode) getModel().getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
getRoot().clear();
|
getModel().setRoot(new FolderNode());
|
||||||
getModel().reload();
|
getModel().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removeTreeNode(TreePath... paths) {
|
|
||||||
Set<TreeNode> dirtyNodes = new HashSet<TreeNode>();
|
|
||||||
|
|
||||||
for (TreePath path : paths) {
|
|
||||||
AbstractTreeNode node = (AbstractTreeNode) (path.getLastPathComponent());
|
|
||||||
|
|
||||||
FolderNode parent = (FolderNode) node.getParent();
|
|
||||||
if (parent != null) {
|
|
||||||
parent.remove(node);
|
|
||||||
dirtyNodes.add(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TreeNode dirtyNode : dirtyNodes) {
|
|
||||||
getModel().reload(dirtyNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void expandAll() {
|
public void expandAll() {
|
||||||
for (int row = 0; row < getRowCount(); row++) {
|
for (int row = 0; row < getRowCount(); row++) {
|
||||||
expandRow(row);
|
expandRow(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void collapseAll() {
|
public void collapseAll() {
|
||||||
for (int row = 0; row < getRowCount(); row++) {
|
for (int row = 0; row < getRowCount(); row++) {
|
||||||
collapseRow(row);
|
collapseRow(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class OpenExpandCollapsePopup extends JPopupMenu {
|
private class OpenExpandCollapsePopup extends JPopupMenu {
|
||||||
|
|
||||||
public OpenExpandCollapsePopup() {
|
public OpenExpandCollapsePopup() {
|
||||||
TreePath[] selectionPaths = getSelectionPaths();
|
TreePath[] selectionPaths = getSelectionPaths();
|
||||||
Set<File> selectionFiles = null;
|
Set<File> selectionFiles = null;
|
||||||
|
|
||||||
if (selectionPaths != null) {
|
if (selectionPaths != null) {
|
||||||
selectionFiles = new LinkedHashSet<File>(selectionPaths.length);
|
selectionFiles = new LinkedHashSet<File>(selectionPaths.length);
|
||||||
|
|
||||||
for (TreePath treePath : selectionPaths) {
|
for (TreePath treePath : selectionPaths) {
|
||||||
Object node = treePath.getLastPathComponent();
|
Object node = treePath.getLastPathComponent();
|
||||||
|
|
||||||
if (node instanceof FileNode) {
|
if (node instanceof FileNode) {
|
||||||
selectionFiles.add(((FileNode) node).getFile());
|
selectionFiles.add(((FileNode) node).getFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectionFiles != null && !selectionFiles.isEmpty()) {
|
if (selectionFiles != null && !selectionFiles.isEmpty()) {
|
||||||
JMenuItem openItem = new JMenuItem(new OpenAction("Open", selectionFiles));
|
JMenuItem openItem = new JMenuItem(new OpenAction("Open", selectionFiles));
|
||||||
openItem.setFont(openItem.getFont().deriveFont(Font.BOLD));
|
openItem.setFont(openItem.getFont().deriveFont(Font.BOLD));
|
||||||
add(openItem);
|
add(openItem);
|
||||||
|
|
||||||
Set<File> selectionParentFolders = new LinkedHashSet<File>(selectionFiles.size());
|
Set<File> selectionParentFolders = new LinkedHashSet<File>(selectionFiles.size());
|
||||||
for (File file : selectionFiles) {
|
for (File file : selectionFiles) {
|
||||||
selectionParentFolders.add(file.getParentFile());
|
selectionParentFolders.add(file.getParentFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
add(new OpenAction("Open Folder", selectionParentFolders));
|
add(new OpenAction("Open Folder", selectionParentFolders));
|
||||||
addSeparator();
|
addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
add(expandAction);
|
add(expandAction);
|
||||||
add(collapseAction);
|
add(collapseAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class OpenAction extends AbstractAction {
|
private class OpenAction extends AbstractAction {
|
||||||
|
|
||||||
public OpenAction(String text, Collection<File> files) {
|
public OpenAction(String text, Collection<File> files) {
|
||||||
super(text);
|
super(text);
|
||||||
putValue("files", files);
|
putValue("files", files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent event) {
|
public void actionPerformed(ActionEvent event) {
|
||||||
try {
|
try {
|
||||||
|
@ -158,104 +126,91 @@ public class FileTree extends JTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final Action expandAction = new AbstractAction("Expand all", ResourceManager.getIcon("tree.expand")) {
|
private final Action expandAction = new AbstractAction("Expand all", ResourceManager.getIcon("tree.expand")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
expandAll();
|
expandAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Action collapseAction = new AbstractAction("Collapse all", ResourceManager.getIcon("tree.collapse")) {
|
private final Action collapseAction = new AbstractAction("Collapse all", ResourceManager.getIcon("tree.collapse")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
collapseAll();
|
collapseAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class ExpandCollapsePopupListener extends MouseAdapter {
|
private class ExpandCollapsePopupListener extends MouseAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
maybeShowPopup(e);
|
maybeShowPopup(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
maybeShowPopup(e);
|
maybeShowPopup(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void maybeShowPopup(MouseEvent e) {
|
private void maybeShowPopup(MouseEvent e) {
|
||||||
if (e.isPopupTrigger()) {
|
if (e.isPopupTrigger()) {
|
||||||
TreePath path = getPathForLocation(e.getX(), e.getY());
|
TreePath path = getPathForLocation(e.getX(), e.getY());
|
||||||
|
|
||||||
if (!getSelectionModel().isPathSelected(path)) {
|
if (!getSelectionModel().isPathSelected(path)) {
|
||||||
// if clicked node is not selected, set selection to this node (and deselect all other currently selected nodes)
|
// if clicked node is not selected, set selection to this node (and deselect all other currently selected nodes)
|
||||||
setSelectionPath(path);
|
setSelectionPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenExpandCollapsePopup popup = new OpenExpandCollapsePopup();
|
OpenExpandCollapsePopup popup = new OpenExpandCollapsePopup();
|
||||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class AbstractTreeNode implements TreeNode {
|
public static class AbstractTreeNode implements TreeNode {
|
||||||
|
|
||||||
private TreeNode parent;
|
private TreeNode parent;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TreeNode getParent() {
|
public TreeNode getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setParent(TreeNode parent) {
|
public void setParent(TreeNode parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<? extends TreeNode> children() {
|
public Enumeration<? extends TreeNode> children() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getAllowsChildren() {
|
public boolean getAllowsChildren() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TreeNode getChildAt(int childIndex) {
|
public TreeNode getChildAt(int childIndex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getChildCount() {
|
public int getChildCount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIndex(TreeNode node) {
|
public int getIndex(TreeNode node) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLeaf() {
|
public boolean isLeaf() {
|
||||||
|
@ -263,155 +218,117 @@ public class FileTree extends JTree {
|
||||||
// so that it won't display any good-for-nothing expand buttons
|
// so that it won't display any good-for-nothing expand buttons
|
||||||
return getChildCount() == 0;
|
return getChildCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class FileNode extends AbstractTreeNode {
|
public static class FileNode extends AbstractTreeNode {
|
||||||
|
|
||||||
private final File file;
|
private final File file;
|
||||||
|
|
||||||
|
|
||||||
public FileNode(File file) {
|
public FileNode(File file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return file.getName();
|
return file.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class FolderNode extends AbstractTreeNode {
|
public static class FolderNode extends AbstractTreeNode {
|
||||||
|
|
||||||
private List<AbstractTreeNode> children;
|
private final File file;
|
||||||
private String title;
|
|
||||||
|
private final String title;
|
||||||
|
private final List<TreeNode> children;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a root node (no parent, no title, empty list of children)
|
* Creates a root node (no parent, no title, empty list of children)
|
||||||
*/
|
*/
|
||||||
public FolderNode() {
|
public FolderNode() {
|
||||||
this(null, 5);
|
this(null, "", emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FolderNode(String title, int initialCapacity) {
|
public FolderNode(String title, List<TreeNode> children) {
|
||||||
this.title = title;
|
this(null, title, children);
|
||||||
this.children = new ArrayList<AbstractTreeNode>(initialCapacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public FolderNode(File file, String title, List<TreeNode> children) {
|
||||||
|
this.file = file;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<AbstractTreeNode> getChildren() {
|
public List<TreeNode> getChildren() {
|
||||||
return Collections.unmodifiableList(children);
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void add(AbstractTreeNode node) {
|
|
||||||
if (children.add(node)) {
|
|
||||||
// node added, set parent
|
|
||||||
node.setParent(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void remove(AbstractTreeNode node) {
|
|
||||||
if (children.remove(node)) {
|
|
||||||
// node removed, reset parent
|
|
||||||
node.setParent(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
// reset parent of all children
|
|
||||||
for (AbstractTreeNode node : children) {
|
|
||||||
node.setParent(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear children
|
|
||||||
children.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<? extends TreeNode> children() {
|
public Enumeration<? extends TreeNode> children() {
|
||||||
return Collections.enumeration(children);
|
return enumeration(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getAllowsChildren() {
|
public boolean getAllowsChildren() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TreeNode getChildAt(int childIndex) {
|
public TreeNode getChildAt(int childIndex) {
|
||||||
return children.get(childIndex);
|
return children.get(childIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getChildCount() {
|
public int getChildCount() {
|
||||||
return children.size();
|
return children.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIndex(TreeNode node) {
|
public int getIndex(TreeNode node) {
|
||||||
return children.indexOf(node);
|
return children.indexOf(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Iterator<AbstractTreeNode> treeIterator() {
|
public Iterator<TreeNode> treeIterator() {
|
||||||
return new TreeIterator<AbstractTreeNode>(this) {
|
return new TreeIterator<TreeNode>(this) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Iterator<AbstractTreeNode> children(AbstractTreeNode 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Iterator<File> fileIterator() {
|
public Iterator<File> fileIterator() {
|
||||||
return new FilterIterator<AbstractTreeNode, File>(treeIterator()) {
|
return new FilterIterator<TreeNode, File>(treeIterator()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File filter(AbstractTreeNode 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -17,18 +15,16 @@ import net.filebot.ui.analyze.FileTree.FolderNode;
|
||||||
import net.filebot.ui.transfer.FileTransferable;
|
import net.filebot.ui.transfer.FileTransferable;
|
||||||
import net.filebot.ui.transfer.TransferableExportHandler;
|
import net.filebot.ui.transfer.TransferableExportHandler;
|
||||||
|
|
||||||
|
|
||||||
class FileTreeExportHandler implements TransferableExportHandler {
|
class FileTreeExportHandler implements TransferableExportHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transferable createTransferable(JComponent c) {
|
public Transferable createTransferable(JComponent c) {
|
||||||
FileTree tree = (FileTree) c;
|
FileTree tree = (FileTree) c;
|
||||||
|
|
||||||
LinkedHashSet<File> files = new LinkedHashSet<File>();
|
LinkedHashSet<File> files = new LinkedHashSet<File>();
|
||||||
|
|
||||||
for (TreePath path : tree.getSelectionPaths()) {
|
for (TreePath path : tree.getSelectionPaths()) {
|
||||||
TreeNode node = (TreeNode) path.getLastPathComponent();
|
TreeNode node = (TreeNode) path.getLastPathComponent();
|
||||||
|
|
||||||
if (node instanceof FileNode) {
|
if (node instanceof FileNode) {
|
||||||
files.add(((FileNode) node).getFile());
|
files.add(((FileNode) node).getFile());
|
||||||
} else if (node instanceof FolderNode) {
|
} else if (node instanceof FolderNode) {
|
||||||
|
@ -37,23 +33,21 @@ class FileTreeExportHandler implements TransferableExportHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!files.isEmpty())
|
if (files.isEmpty())
|
||||||
return new FileTransferable(files);
|
return null;
|
||||||
|
|
||||||
return null;
|
return new FileTransferable(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exportDone(JComponent source, Transferable data, int action) {
|
public void exportDone(JComponent source, Transferable data, int action) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSourceActions(JComponent c) {
|
public int getSourceActions(JComponent c) {
|
||||||
return TransferHandler.COPY;
|
return TransferHandler.COPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
|
||||||
import static net.filebot.ui.transfer.BackgroundFileTransferablePolicy.*;
|
import static net.filebot.ui.transfer.BackgroundFileTransferablePolicy.*;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
|
||||||
|
@ -14,36 +11,32 @@ import javax.swing.BorderFactory;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.KeyStroke;
|
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
import net.filebot.ResourceManager;
|
import net.filebot.ResourceManager;
|
||||||
import net.filebot.ui.transfer.DefaultTransferHandler;
|
import net.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.filebot.ui.transfer.LoadAction;
|
import net.filebot.ui.transfer.LoadAction;
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
import net.filebot.util.ui.TunedUtilities;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
|
|
||||||
class FileTreePanel extends JComponent {
|
class FileTreePanel extends JComponent {
|
||||||
|
|
||||||
private FileTree fileTree = new FileTree();
|
private FileTree fileTree = new FileTree();
|
||||||
|
|
||||||
private FileTreeTransferablePolicy transferablePolicy = new FileTreeTransferablePolicy(fileTree);
|
private FileTreeTransferablePolicy transferablePolicy = new FileTreeTransferablePolicy(fileTree);
|
||||||
|
|
||||||
|
|
||||||
public FileTreePanel() {
|
public FileTreePanel() {
|
||||||
fileTree.setTransferHandler(new DefaultTransferHandler(transferablePolicy, null));
|
fileTree.setTransferHandler(new DefaultTransferHandler(transferablePolicy, null));
|
||||||
|
|
||||||
setBorder(BorderFactory.createTitledBorder("File Tree"));
|
setBorder(BorderFactory.createTitledBorder("File Tree"));
|
||||||
|
|
||||||
setLayout(new MigLayout("insets 0, nogrid, fill", "align center", "[fill][pref!]"));
|
setLayout(new MigLayout("insets 0, nogrid, fill", "align center", "[fill][pref!]"));
|
||||||
add(new LoadingOverlayPane(new JScrollPane(fileTree), this), "grow, wrap 1.2mm");
|
add(new LoadingOverlayPane(new JScrollPane(fileTree), this), "grow, wrap 1.2mm");
|
||||||
add(new JButton(loadAction));
|
add(new JButton(loadAction));
|
||||||
add(new JButton(clearAction), "gap 1.2mm, wrap 1.2mm");
|
add(new JButton(clearAction), "gap 1.2mm, wrap 1.2mm");
|
||||||
|
|
||||||
// forward loading events
|
// forward loading events
|
||||||
transferablePolicy.addPropertyChangeListener(new PropertyChangeListener() {
|
transferablePolicy.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (LOADING_PROPERTY.equals(evt.getPropertyName())) {
|
if (LOADING_PROPERTY.equals(evt.getPropertyName())) {
|
||||||
|
@ -51,10 +44,10 @@ class FileTreePanel extends JComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// update tree when loading is finished
|
// update tree when loading is finished
|
||||||
transferablePolicy.addPropertyChangeListener(new PropertyChangeListener() {
|
transferablePolicy.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (LOADING_PROPERTY.equals(evt.getPropertyName()) && !(Boolean) evt.getNewValue()) {
|
if (LOADING_PROPERTY.equals(evt.getPropertyName()) && !(Boolean) evt.getNewValue()) {
|
||||||
|
@ -62,26 +55,20 @@ class FileTreePanel extends JComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Shortcut DELETE
|
|
||||||
TunedUtilities.installAction(fileTree, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), removeAction);
|
|
||||||
TunedUtilities.installAction(fileTree, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), removeAction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FileTree getFileTree() {
|
public FileTree getFileTree() {
|
||||||
return fileTree;
|
return fileTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FileTreeTransferablePolicy getTransferablePolicy() {
|
public FileTreeTransferablePolicy getTransferablePolicy() {
|
||||||
return transferablePolicy;
|
return transferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LoadAction loadAction = new LoadAction(transferablePolicy);
|
private final LoadAction loadAction = new LoadAction(transferablePolicy);
|
||||||
|
|
||||||
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
transferablePolicy.reset();
|
transferablePolicy.reset();
|
||||||
|
@ -89,32 +76,9 @@ class FileTreePanel extends JComponent {
|
||||||
fireFileTreeChange();
|
fireFileTreeChange();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final AbstractAction removeAction = new AbstractAction("Remove") {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (fileTree.getSelectionCount() < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int row = fileTree.getMinSelectionRow();
|
|
||||||
|
|
||||||
fileTree.removeTreeNode(fileTree.getSelectionPaths());
|
|
||||||
|
|
||||||
int maxRow = fileTree.getRowCount() - 1;
|
|
||||||
|
|
||||||
if (row > maxRow)
|
|
||||||
row = maxRow;
|
|
||||||
|
|
||||||
fileTree.setSelectionRow(row);
|
|
||||||
|
|
||||||
fireFileTreeChange();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private void fireFileTreeChange() {
|
private void fireFileTreeChange() {
|
||||||
firePropertyChange("filetree", null, fileTree);
|
firePropertyChange("filetree", null, fileTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,21 @@ import static net.filebot.ui.NotificationLogging.*;
|
||||||
import static net.filebot.util.FileUtilities.*;
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import net.filebot.ui.analyze.FileTree.AbstractTreeNode;
|
import javax.swing.tree.TreeNode;
|
||||||
|
|
||||||
import net.filebot.ui.analyze.FileTree.FileNode;
|
import net.filebot.ui.analyze.FileTree.FileNode;
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
import net.filebot.ui.analyze.FileTree.FolderNode;
|
||||||
import net.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
import net.filebot.ui.transfer.BackgroundFileTransferablePolicy;
|
||||||
import net.filebot.util.ExceptionUtilities;
|
import net.filebot.util.ExceptionUtilities;
|
||||||
import net.filebot.util.FastFile;
|
import net.filebot.util.FastFile;
|
||||||
|
|
||||||
class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<AbstractTreeNode> {
|
class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<TreeNode> {
|
||||||
|
|
||||||
private final FileTree tree;
|
private final FileTree tree;
|
||||||
|
|
||||||
|
@ -30,18 +34,12 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Abstra
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
super.clear();
|
super.clear();
|
||||||
|
|
||||||
tree.clear();
|
tree.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void process(List<AbstractTreeNode> chunks) {
|
protected void process(List<TreeNode> root) {
|
||||||
FolderNode root = tree.getRoot();
|
tree.getModel().setRoot(root.get(0));
|
||||||
|
|
||||||
for (AbstractTreeNode node : chunks) {
|
|
||||||
root.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
tree.getModel().reload();
|
tree.getModel().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,40 +51,39 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Abstra
|
||||||
@Override
|
@Override
|
||||||
protected void load(List<File> files) {
|
protected void load(List<File> files) {
|
||||||
try {
|
try {
|
||||||
for (File file : files) {
|
if (files.size() > 1 || containsOnly(files, FILES)) {
|
||||||
// use fast file to minimize system calls like length(), isDirectory(), isFile(), ...
|
files = Arrays.asList(files.get(0).getParentFile());
|
||||||
AbstractTreeNode node = getTreeNode(new FastFile(file.getPath()));
|
|
||||||
|
|
||||||
// publish on EDT
|
|
||||||
publish(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use fast file to minimize system calls like length(), isDirectory(), isFile(), ...
|
||||||
|
FastFile root = FastFile.create(filter(files, FOLDERS)).get(0);
|
||||||
|
|
||||||
|
// publish on EDT
|
||||||
|
publish(getTreeNode(root));
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// supposed to happen if background execution was aborted
|
// supposed to happen if background execution was aborted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AbstractTreeNode getTreeNode(File file) throws InterruptedException {
|
private TreeNode getTreeNode(File file) throws InterruptedException {
|
||||||
if (Thread.interrupted())
|
if (Thread.interrupted()) {
|
||||||
throw new InterruptedException();
|
throw new InterruptedException();
|
||||||
|
}
|
||||||
|
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
List<File> files = getChildren(file);
|
LinkedList<TreeNode> children = new LinkedList<TreeNode>();
|
||||||
FolderNode node = new FolderNode(getFolderName(file), files.size());
|
for (File f : getChildren(file)) {
|
||||||
|
if (f.isHidden())
|
||||||
|
continue;
|
||||||
|
|
||||||
// add folders first
|
|
||||||
for (File f : files) {
|
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
node.add(getTreeNode(f));
|
children.addFirst(getTreeNode(f));
|
||||||
|
} else {
|
||||||
|
children.addLast(getTreeNode(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (File f : files) {
|
return new FolderNode(file, getFolderName(file), new ArrayList<TreeNode>(children));
|
||||||
if (f.isFile()) {
|
|
||||||
node.add(getTreeNode(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FileNode(file);
|
return new FileNode(file);
|
||||||
|
@ -94,7 +91,7 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Abstra
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFileFilterDescription() {
|
public String getFileFilterDescription() {
|
||||||
return "files and folders";
|
return "folders";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
|
@ -18,125 +14,106 @@ import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
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 net.miginfocom.swing.MigLayout;
|
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
import net.filebot.ui.analyze.FileTree.FolderNode;
|
||||||
import net.filebot.ui.transfer.DefaultTransferHandler;
|
import net.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.filebot.util.FileUtilities;
|
import net.filebot.util.FileUtilities;
|
||||||
import net.filebot.util.ui.GradientStyle;
|
import net.filebot.util.ui.GradientStyle;
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
import net.filebot.util.ui.notification.SeparatorBorder;
|
import net.filebot.util.ui.notification.SeparatorBorder;
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
|
class SplitTool extends Tool<TreeModel> {
|
||||||
|
|
||||||
class SplitTool extends Tool<TreeModel> implements ChangeListener {
|
|
||||||
|
|
||||||
private FileTree tree = new FileTree();
|
private FileTree tree = new FileTree();
|
||||||
|
|
||||||
private SpinnerNumberModel spinnerModel = new SpinnerNumberModel(4480, 0, Integer.MAX_VALUE, 100);
|
private SpinnerNumberModel spinnerModel = new SpinnerNumberModel(4480, 0, Integer.MAX_VALUE, 100);
|
||||||
|
|
||||||
|
|
||||||
public SplitTool() {
|
public SplitTool() {
|
||||||
super("Disks");
|
super("Disks");
|
||||||
|
|
||||||
JScrollPane treeScrollPane = new JScrollPane(tree);
|
JScrollPane treeScrollPane = new JScrollPane(tree);
|
||||||
treeScrollPane.setBorder(new SeparatorBorder(2, new Color(0, 0, 0, 90), GradientStyle.TOP_TO_BOTTOM, SeparatorBorder.Position.BOTTOM));
|
treeScrollPane.setBorder(new SeparatorBorder(2, new Color(0, 0, 0, 90), GradientStyle.TOP_TO_BOTTOM, SeparatorBorder.Position.BOTTOM));
|
||||||
|
|
||||||
JSpinner spinner = new JSpinner(spinnerModel);
|
JSpinner spinner = new JSpinner(spinnerModel);
|
||||||
spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));
|
spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));
|
||||||
|
|
||||||
setLayout(new MigLayout("insets 0, nogrid, fill", "align center", "[fill][pref!]"));
|
setLayout(new MigLayout("insets 0, nogrid, fill", "align center", "[fill][pref!]"));
|
||||||
|
|
||||||
add(new LoadingOverlayPane(treeScrollPane, this), "grow, wrap");
|
add(new LoadingOverlayPane(treeScrollPane, this), "grow, wrap");
|
||||||
|
|
||||||
add(new JLabel("Split every"));
|
add(new JLabel("Split every"));
|
||||||
add(spinner, "wmax 80, gap top rel, gap bottom unrel");
|
add(spinner, "wmax 80, gap top rel, gap bottom unrel");
|
||||||
add(new JLabel("MB."));
|
add(new JLabel("MB."));
|
||||||
|
|
||||||
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
||||||
tree.setDragEnabled(true);
|
tree.setDragEnabled(true);
|
||||||
|
|
||||||
spinnerModel.addChangeListener(this);
|
spinnerModel.addChangeListener(new ChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent evt) {
|
||||||
|
// update model in foreground, will be much faster than the initial load because length() is cached now
|
||||||
|
if (getRoot() != null) {
|
||||||
|
updateRoot(getRoot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private long getSplitSize() {
|
private long getSplitSize() {
|
||||||
return spinnerModel.getNumber().intValue() * FileUtilities.MEGA;
|
return spinnerModel.getNumber().intValue() * FileUtilities.MEGA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private FolderNode sourceModel = null;
|
|
||||||
|
|
||||||
|
|
||||||
public void stateChanged(ChangeEvent evt) {
|
|
||||||
if (sourceModel != null) {
|
|
||||||
try {
|
|
||||||
// update model in foreground, will be much faster than the initial load because length() is cached now
|
|
||||||
setModel(createModelInBackground(sourceModel));
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// will not happen
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TreeModel createModelInBackground(FolderNode sourceModel) throws InterruptedException {
|
protected TreeModel createModelInBackground(File root) throws InterruptedException {
|
||||||
this.sourceModel = sourceModel;
|
|
||||||
|
|
||||||
FolderNode root = new FolderNode();
|
|
||||||
int nextPart = 1;
|
int nextPart = 1;
|
||||||
|
|
||||||
long splitSize = getSplitSize();
|
long splitSize = getSplitSize();
|
||||||
|
|
||||||
List<File> currentPart = new ArrayList<File>(50);
|
List<File> files = (root != null) ? FileUtilities.listFiles(root) : Collections.emptyList();
|
||||||
List<File> remainder = new ArrayList<File>(50);
|
|
||||||
|
List<TreeNode> rootGroup = new ArrayList<TreeNode>();
|
||||||
|
List<File> currentPart = new ArrayList<File>();
|
||||||
|
List<File> remainder = new ArrayList<File>();
|
||||||
long totalSize = 0;
|
long totalSize = 0;
|
||||||
|
|
||||||
for (Iterator<File> iterator = sourceModel.fileIterator(); iterator.hasNext();) {
|
for (File f : files) {
|
||||||
File file = iterator.next();
|
long fileSize = f.length();
|
||||||
|
|
||||||
long fileSize = file.length();
|
|
||||||
|
|
||||||
if (fileSize > splitSize) {
|
if (fileSize > splitSize) {
|
||||||
remainder.add(file);
|
remainder.add(f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
root.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
rootGroup.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
||||||
|
|
||||||
// reset total size and file list
|
// reset total size and file list
|
||||||
totalSize = 0;
|
totalSize = 0;
|
||||||
currentPart.clear();
|
currentPart.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
totalSize += fileSize;
|
totalSize += fileSize;
|
||||||
currentPart.add(file);
|
currentPart.add(f);
|
||||||
|
|
||||||
// unwind thread, if we have been cancelled
|
|
||||||
if (Thread.interrupted()) {
|
|
||||||
throw new InterruptedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentPart.isEmpty()) {
|
if (!currentPart.isEmpty()) {
|
||||||
// add last part
|
// add last part
|
||||||
root.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
rootGroup.add(createStatisticsNode(String.format("Disk %d", nextPart++), currentPart));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remainder.isEmpty()) {
|
if (!remainder.isEmpty()) {
|
||||||
root.add(createStatisticsNode("Remainder", remainder));
|
rootGroup.add(createStatisticsNode("Remainder", remainder));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DefaultTreeModel(root);
|
return new DefaultTreeModel(new FolderNode("Volumes", rootGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setModel(TreeModel model) {
|
protected void setModel(TreeModel model) {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -10,6 +10,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
import javax.swing.tree.TreeNode;
|
||||||
|
|
||||||
import net.filebot.ui.analyze.FileTree.FileNode;
|
import net.filebot.ui.analyze.FileTree.FileNode;
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
import net.filebot.ui.analyze.FileTree.FolderNode;
|
||||||
|
@ -17,63 +18,63 @@ 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;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
abstract class Tool<M> extends JComponent {
|
abstract class Tool<M> extends JComponent {
|
||||||
|
|
||||||
private UpdateModelTask updateTask = null;
|
private UpdateModelTask updateTask = null;
|
||||||
|
private File root = null;
|
||||||
|
|
||||||
public Tool(String name) {
|
public Tool(String name) {
|
||||||
setName(name);
|
setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getRoot() {
|
||||||
public void setSourceModel(FolderNode sourceModel) {
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateRoot(File root) {
|
||||||
|
this.root = root;
|
||||||
|
|
||||||
if (updateTask != null) {
|
if (updateTask != null) {
|
||||||
updateTask.cancel(true);
|
updateTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, false, true);
|
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, false, true);
|
||||||
updateTask = new UpdateModelTask(sourceModel);
|
updateTask = new UpdateModelTask(root);
|
||||||
updateTask.execute();
|
updateTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract M createModelInBackground(File root) throws InterruptedException;
|
||||||
protected abstract M createModelInBackground(FolderNode sourceModel) throws InterruptedException;
|
|
||||||
|
|
||||||
|
|
||||||
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 FolderNode sourceModel;
|
private final File root;
|
||||||
|
|
||||||
|
public UpdateModelTask(File root) {
|
||||||
public UpdateModelTask(FolderNode sourceModel) {
|
this.root = root;
|
||||||
this.sourceModel = sourceModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected M doInBackground() throws Exception {
|
protected M doInBackground() throws Exception {
|
||||||
return createModelInBackground(sourceModel);
|
return createModelInBackground(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
if (this == updateTask) {
|
if (this == updateTask) {
|
||||||
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, true, false);
|
Tool.this.firePropertyChange(LoadingOverlayPane.LOADING_PROPERTY, true, 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
|
||||||
if (this == updateTask && !isCancelled()) {
|
if (this == updateTask && !isCancelled()) {
|
||||||
try {
|
try {
|
||||||
setModel(get());
|
setModel(get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Throwable cause = ExceptionUtilities.getRootCause(e);
|
Throwable cause = ExceptionUtilities.getRootCause(e);
|
||||||
|
|
||||||
if (cause instanceof ConcurrentModificationException || cause instanceof InterruptedException) {
|
if (cause instanceof ConcurrentModificationException || cause instanceof InterruptedException) {
|
||||||
// if it happens, it is supposed to
|
// if it happens, it is supposed to
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,25 +85,28 @@ abstract class Tool<M> extends JComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<TreeNode> createFileNodes(Collection<File> files) {
|
||||||
protected FolderNode createStatisticsNode(String name, List<File> files) {
|
List<TreeNode> nodes = new ArrayList<TreeNode>(files.size());
|
||||||
FolderNode folder = new FolderNode(null, files.size());
|
for (File f : files) {
|
||||||
|
nodes.add(new FileNode(f));
|
||||||
long totalSize = 0;
|
|
||||||
|
|
||||||
for (File file : files) {
|
|
||||||
folder.add(new FileNode(file));
|
|
||||||
totalSize += file.length();
|
|
||||||
}
|
}
|
||||||
|
return nodes;
|
||||||
// format the number of files string (e.g. 1 file, 2 files, ...)
|
|
||||||
String numberOfFiles = String.format("%,d %s", files.size(), files.size() == 1 ? "file" : "files");
|
|
||||||
|
|
||||||
// set node text (e.g. txt (1 file, 42 Byte))
|
|
||||||
folder.setTitle(String.format("%s (%s, %s)", name, numberOfFiles, FileUtilities.formatSize(totalSize)));
|
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected FolderNode createStatisticsNode(String name, List<File> files) {
|
||||||
|
long totalCount = 0;
|
||||||
|
long totalSize = 0;
|
||||||
|
|
||||||
|
for (File f : files) {
|
||||||
|
totalCount += FileUtilities.listFiles(f).size();
|
||||||
|
totalSize += FileUtils.sizeOf(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
return new FolderNode(null, title, createFileNodes(files));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,99 +1,96 @@
|
||||||
|
|
||||||
package net.filebot.ui.analyze;
|
package net.filebot.ui.analyze;
|
||||||
|
|
||||||
|
import static java.util.Collections.*;
|
||||||
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
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 net.miginfocom.swing.MigLayout;
|
import net.filebot.MediaTypes;
|
||||||
|
import net.filebot.media.MediaDetection;
|
||||||
import net.filebot.ui.analyze.FileTree.FolderNode;
|
import net.filebot.ui.analyze.FileTree.FolderNode;
|
||||||
import net.filebot.ui.transfer.DefaultTransferHandler;
|
import net.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.filebot.util.FileUtilities;
|
|
||||||
import net.filebot.util.ui.LoadingOverlayPane;
|
import net.filebot.util.ui.LoadingOverlayPane;
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
class TypeTool extends Tool<TreeModel> {
|
class TypeTool extends Tool<TreeModel> {
|
||||||
|
|
||||||
private FileTree tree = new FileTree();
|
private FileTree tree = new FileTree();
|
||||||
|
|
||||||
|
|
||||||
public TypeTool() {
|
public TypeTool() {
|
||||||
super("Types");
|
super("Types");
|
||||||
|
|
||||||
setLayout(new MigLayout("insets 0, fill"));
|
setLayout(new MigLayout("insets 0, fill"));
|
||||||
|
|
||||||
JScrollPane treeScrollPane = new JScrollPane(tree);
|
JScrollPane treeScrollPane = new JScrollPane(tree);
|
||||||
treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
add(new LoadingOverlayPane(treeScrollPane, this), "grow");
|
add(new LoadingOverlayPane(treeScrollPane, this), "grow");
|
||||||
|
|
||||||
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
tree.setTransferHandler(new DefaultTransferHandler(null, new FileTreeExportHandler()));
|
||||||
tree.setDragEnabled(true);
|
tree.setDragEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TreeModel createModelInBackground(FolderNode sourceModel) throws InterruptedException {
|
protected TreeModel createModelInBackground(File root) throws InterruptedException {
|
||||||
Map<String, List<File>> map = new HashMap<String, List<File>>();
|
List<File> filesAndFolders = (root != null) ? listFiles(singleton(root), FILE_WALK_MAX_DEPTH, false, true, true) : emptyList();
|
||||||
|
List<TreeNode> groups = new ArrayList<TreeNode>();
|
||||||
for (Iterator<File> iterator = sourceModel.fileIterator(); iterator.hasNext();) {
|
|
||||||
File file = iterator.next();
|
for (Entry<String, FileFilter> it : getMetaTypes().entrySet()) {
|
||||||
|
List<File> selection = filter(filesAndFolders, it.getValue());
|
||||||
String extension = FileUtilities.getExtension(file);
|
if (selection.size() > 0) {
|
||||||
if (extension != null) {
|
groups.add(createStatisticsNode(it.getKey(), selection));
|
||||||
extension = extension.toLowerCase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<File> files = map.get(extension);
|
|
||||||
if (files == null) {
|
|
||||||
files = new ArrayList<File>(50);
|
|
||||||
map.put(extension, files);
|
|
||||||
}
|
|
||||||
|
|
||||||
files.add(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> keys = new ArrayList<String>(map.keySet());
|
SortedMap<String, TreeNode> extensionGroups = new TreeMap<String, TreeNode>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
for (Entry<String, List<File>> it : mapByExtension(filter(filesAndFolders, FILES)).entrySet()) {
|
||||||
// sort strings like always, handle null as empty string
|
if (it.getKey() == null)
|
||||||
Collections.sort(keys, new Comparator<String>() {
|
continue;
|
||||||
|
|
||||||
@Override
|
extensionGroups.put(it.getKey(), createStatisticsNode(it.getKey(), it.getValue()));
|
||||||
public int compare(String s1, String s2) {
|
}
|
||||||
return ((s1 != null) ? s1 : "").compareTo((s2 != null) ? s2 : "");
|
groups.addAll(extensionGroups.values());
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// create tree model
|
// create tree model
|
||||||
FolderNode root = new FolderNode();
|
return new DefaultTreeModel(new FolderNode("Types", groups));
|
||||||
|
|
||||||
for (String key : keys) {
|
|
||||||
root.add(createStatisticsNode(key, map.get(key)));
|
|
||||||
|
|
||||||
// unwind thread, if we have been cancelled
|
|
||||||
if (Thread.interrupted()) {
|
|
||||||
throw new InterruptedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DefaultTreeModel(root);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, FileFilter> getMetaTypes() {
|
||||||
|
Map<String, FileFilter> types = new LinkedHashMap<String, FileFilter>();
|
||||||
|
types.put("Video", MediaTypes.VIDEO_FILES);
|
||||||
|
types.put("Disk Folder", MediaDetection.getDiskFolderFilter());
|
||||||
|
types.put("Subtitle", MediaTypes.SUBTITLE_FILES);
|
||||||
|
types.put("Audio", MediaTypes.AUDIO_FILES);
|
||||||
|
types.put("Archive", MediaTypes.ARCHIVE_FILES);
|
||||||
|
types.put("Verification", MediaTypes.VERIFICATION_FILES);
|
||||||
|
try {
|
||||||
|
types.put("Clutter", MediaDetection.getClutterFileFilter());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(TypeTool.class.getName()).log(Level.WARNING, e.getMessage());
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setModel(TreeModel model) {
|
protected void setModel(TreeModel model) {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ class FilesListTransferablePolicy extends FileTransferablePolicy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
model.addAll(FastFile.get(entries));
|
model.addAll(FastFile.create(entries));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -96,7 +96,7 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
|
||||||
loadTorrentFiles(files, values);
|
loadTorrentFiles(files, values);
|
||||||
} else {
|
} else {
|
||||||
// load all files from the given folders recursively up do a depth of 32
|
// load all files from the given folders recursively up do a depth of 32
|
||||||
values.addAll(FastFile.get(listFiles(files)));
|
values.addAll(FastFile.create(listFiles(files)));
|
||||||
}
|
}
|
||||||
|
|
||||||
model.addAll(values);
|
model.addAll(values);
|
||||||
|
|
|
@ -77,9 +77,10 @@ public class RenameModel extends MatchModel<Object, File> {
|
||||||
|
|
||||||
for (int i = 0; i < names.size(); i++) {
|
for (int i = 0; i < names.size(); i++) {
|
||||||
if (hasComplement(i)) {
|
if (hasComplement(i)) {
|
||||||
File originalFile = files().get(i);
|
// make sure we're dealing with regular File objects form here on out
|
||||||
FormattedFuture formattedFuture = names.get(i);
|
File originalFile = new File(files().get(i).getPath());
|
||||||
|
|
||||||
|
FormattedFuture formattedFuture = names.get(i);
|
||||||
StringBuilder nameBuilder = new StringBuilder();
|
StringBuilder nameBuilder = new StringBuilder();
|
||||||
|
|
||||||
// append formatted name, throw exception if not ready
|
// append formatted name, throw exception if not ready
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.filebot.util;
|
package net.filebot.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -8,8 +9,14 @@ import java.util.List;
|
||||||
public class FastFile extends File {
|
public class FastFile extends File {
|
||||||
|
|
||||||
private Long length;
|
private Long length;
|
||||||
|
private Long lastModified;
|
||||||
|
private Boolean exists;
|
||||||
private Boolean isDirectory;
|
private Boolean isDirectory;
|
||||||
private Boolean isFile;
|
private Boolean isFile;
|
||||||
|
private Boolean isHidden;
|
||||||
|
|
||||||
|
private String[] list;
|
||||||
|
private File[] listFiles;
|
||||||
|
|
||||||
public FastFile(String path) {
|
public FastFile(String path) {
|
||||||
super(path);
|
super(path);
|
||||||
|
@ -24,6 +31,11 @@ public class FastFile extends File {
|
||||||
return length != null ? length : (length = super.length());
|
return length != null ? length : (length = super.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists() {
|
||||||
|
return exists != null ? exists : (exists = super.exists());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirectory() {
|
public boolean isDirectory() {
|
||||||
return isDirectory != null ? isDirectory : (isDirectory = super.isDirectory());
|
return isDirectory != null ? isDirectory : (isDirectory = super.isDirectory());
|
||||||
|
@ -35,23 +47,154 @@ public class FastFile extends File {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File[] listFiles() {
|
public boolean isHidden() {
|
||||||
String[] names = list();
|
return isHidden != null ? isHidden : (isHidden = super.isHidden());
|
||||||
if (names == null)
|
}
|
||||||
return null;
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long lastModified() {
|
||||||
|
return lastModified != null ? lastModified : (lastModified = super.lastModified());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] list() {
|
||||||
|
if (list != null) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] names = super.list();
|
||||||
|
if (names == null) {
|
||||||
|
names = new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (list = names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File[] listFiles() {
|
||||||
|
if (listFiles != null) {
|
||||||
|
return listFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] names = list();
|
||||||
File[] files = new File[names.length];
|
File[] files = new File[names.length];
|
||||||
for (int i = 0; i < names.length; i++) {
|
for (int i = 0; i < names.length; i++) {
|
||||||
files[i] = new FastFile(this, names[i]);
|
files[i] = new FastFile(this, names[i]);
|
||||||
}
|
}
|
||||||
return files;
|
|
||||||
|
return (listFiles = files);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FastFile get(File file) {
|
@Override
|
||||||
return new FastFile(file.getPath());
|
public boolean canRead() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<FastFile> get(Collection<File> files) {
|
@Override
|
||||||
|
public boolean canWrite() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canExecute() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createNewFile() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean delete() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteOnExit() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mkdir() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mkdirs() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean renameTo(File dest) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setLastModified(long time) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setReadOnly() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setWritable(boolean writable, boolean ownerOnly) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setWritable(boolean writable) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setReadable(boolean readable, boolean ownerOnly) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setReadable(boolean readable) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setExecutable(boolean executable, boolean ownerOnly) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setExecutable(boolean executable) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTotalSpace() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getFreeSpace() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getUsableSpace() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<FastFile> create(Collection<File> files) {
|
||||||
List<FastFile> result = new ArrayList<FastFile>(files.size());
|
List<FastFile> result = new ArrayList<FastFile>(files.size());
|
||||||
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
|
|
Loading…
Reference in New Issue