1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-08-13 17:03:45 -04:00

* split ExportHandler interface into TransferableExportHandler and FileExportHandler

* added string flavour to all text transfer operations
* text file for dnd transfer will only be created on demand

* removed ImportHandler interface

* moved sfv renderer classes to sfv package
* removed sfv renderer package

* rename-lists now titled "Proposed" and "Current"

* DefaultClipboardHandler will export null values as empty string, not "null"
* refactored OpenSubtitlesHasher

* adapted to the new tvrage episode list xml feed syntax
This commit is contained in:
Reinhard Pointner 2008-10-06 19:13:58 +00:00
parent 074e103ddf
commit aefc84085b
36 changed files with 474 additions and 909 deletions

View File

@ -15,7 +15,7 @@ import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
import net.sourceforge.filebot.ui.transfer.FileExportHandler;
import net.sourceforge.filebot.ui.transfer.TextFileExportHandler;
import net.sourceforge.filebot.ui.transfer.TransferablePolicy;
import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer;
import net.sourceforge.tuned.ui.TunedUtil;
@ -72,27 +72,25 @@ public class FileBotList<E> extends JPanel {
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
getTransferHandler().setImportHandler(transferablePolicy);
getTransferHandler().setTransferablePolicy(transferablePolicy);
}
public TransferablePolicy getTransferablePolicy() {
TransferablePolicy importHandler = (TransferablePolicy) getTransferHandler().getImportHandler();
return importHandler;
return getTransferHandler().getTransferablePolicy();
}
public void setExportHandler(FileExportHandler exportHandler) {
public void setExportHandler(TextFileExportHandler exportHandler) {
getTransferHandler().setExportHandler(exportHandler);
// enable drag if ExportHandler is available
// enable drag if export handler is available
list.setDragEnabled(exportHandler != null);
}
public FileExportHandler getExportHandler() {
return (FileExportHandler) getTransferHandler().getExportHandler();
public TextFileExportHandler getExportHandler() {
return (TextFileExportHandler) getTransferHandler().getExportHandler();
}

View File

@ -2,14 +2,12 @@
package net.sourceforge.filebot.ui;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import net.sourceforge.filebot.ui.transfer.FileExportHandler;
import net.sourceforge.filebot.ui.transfer.TextFileExportHandler;
public class FileBotListExportHandler extends FileExportHandler {
public class FileBotListExportHandler extends TextFileExportHandler {
private final FileBotList<?> list;
@ -26,11 +24,9 @@ public class FileBotListExportHandler extends FileExportHandler {
@Override
public void export(OutputStream out) throws IOException {
PrintStream printer = new PrintStream(out, false, "UTF-8");
public void export(PrintWriter out) {
for (Object entry : list.getModel()) {
printer.println(entry);
out.println(entry);
}
}

View File

@ -12,11 +12,11 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import net.sourceforge.filebot.ui.FileBotTree;
import net.sourceforge.filebot.ui.transfer.ExportHandler;
import net.sourceforge.filebot.ui.transfer.TransferableExportHandler;
import net.sourceforge.filebot.ui.transfer.FileTransferable;
class FileTreeExportHandler implements ExportHandler {
class FileTreeExportHandler implements TransferableExportHandler {
@Override
public Transferable createTransferable(JComponent c) {

View File

@ -47,6 +47,8 @@ public class ListPanel extends FileBotPanel {
public ListPanel() {
super("List", ResourceManager.getIcon("panel.list"));
list.setTitle("Title");
list.setTransferablePolicy(new FileListTransferablePolicy(list));
list.setExportHandler(new FileBotListExportHandler(list));

View File

@ -48,10 +48,10 @@ public class RenamePanel extends FileBotPanel {
public RenamePanel() {
super("Rename", ResourceManager.getIcon("panel.rename"));
namesList.setTitle("Names");
namesList.setTitle("Proposed");
namesList.setTransferablePolicy(new NamesListTransferablePolicy(namesList));
filesList.setTitle("Files");
filesList.setTitle("Current");
filesList.setTransferablePolicy(new FilesListTransferablePolicy(filesList.getModel()));
JList namesListComponent = namesList.getListComponent();

View File

@ -7,6 +7,8 @@ import java.awt.Window;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.text.NumberFormat;
import java.util.ArrayList;
@ -36,7 +38,6 @@ import net.sourceforge.filebot.ui.FileBotPanel;
import net.sourceforge.filebot.ui.HistoryPanel;
import net.sourceforge.filebot.ui.MessageManager;
import net.sourceforge.filebot.ui.SelectDialog;
import net.sourceforge.filebot.ui.transfer.AdaptiveFileExportHandler;
import net.sourceforge.filebot.ui.transfer.FileExportHandler;
import net.sourceforge.filebot.ui.transfer.SaveAction;
import net.sourceforge.filebot.web.AnidbClient;
@ -183,13 +184,12 @@ public class SearchPanel extends FileBotPanel {
private final SaveAction saveAction = new SaveAction(new SelectedTabExportHandler());
private class SelectedTabExportHandler extends AdaptiveFileExportHandler {
private class SelectedTabExportHandler implements FileExportHandler {
/**
* @return the <code>FileExportHandler</code> of the currently selected tab
*/
@Override
protected FileExportHandler getExportHandler() {
private FileExportHandler getExportHandler() {
try {
FileBotList<?> list = (FileBotList<?>) tabbedPane.getSelectedComponent();
return list.getExportHandler();
@ -198,6 +198,30 @@ public class SearchPanel extends FileBotPanel {
return null;
}
}
@Override
public boolean canExport() {
FileExportHandler handler = getExportHandler();
if (handler == null)
return false;
return handler.canExport();
}
@Override
public void export(File file) throws IOException {
getExportHandler().export(file);
}
@Override
public String getDefaultFileName() {
return getExportHandler().getDefaultFileName();
}
}

View File

@ -0,0 +1,111 @@
package net.sourceforge.filebot.ui.panel.sfv;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
class ChecksumTableCellRenderer extends DefaultTableCellRenderer {
private final ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, null, isSelected, false, row, column);
if (value == null)
return this;
Checksum checksum = (Checksum) value;
switch (checksum.getState()) {
case READY:
setText(checksum.getChecksumString());
return this;
case PENDING:
setText("Pending ...");
return this;
case ERROR:
setText(checksum.getErrorMessage());
return this;
default:
return progressBarRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
private static class ProgressBarTableCellRenderer extends JPanel implements TableCellRenderer {
private final JProgressBar progressBar = new JProgressBar(0, 100);
public ProgressBarTableCellRenderer() {
super(new BorderLayout());
progressBar.setStringPainted(true);
add(progressBar, BorderLayout.CENTER);
setBorder(new EmptyBorder(2, 2, 2, 2));
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Checksum checksum = (Checksum) value;
progressBar.setValue(checksum.getProgress());
if (isSelected) {
this.setBackground(table.getSelectionBackground());
} else {
this.setBackground(table.getBackground());
}
return this;
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(long tm, int x, int y, int width, int height) {
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(Rectangle r) {
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint() {
}
/**
* Overridden for performance reasons.
*/
@Override
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
}
}
}

View File

@ -2,22 +2,19 @@
package net.sourceforge.filebot.ui.panel.sfv;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import net.sourceforge.filebot.ui.transfer.FileExportHandler;
import net.sourceforge.filebot.ui.transfer.TextFileExportHandler;
import net.sourceforge.tuned.FileUtil;
public class ChecksumTableExportHandler extends FileExportHandler {
public class ChecksumTableExportHandler extends TextFileExportHandler {
private final ChecksumTableModel model;
@ -34,7 +31,7 @@ public class ChecksumTableExportHandler extends FileExportHandler {
@Override
public void export(OutputStream out) throws IOException {
public void export(PrintWriter out) {
export(out, model.getChecksumColumn(0));
}
@ -46,7 +43,7 @@ public class ChecksumTableExportHandler extends FileExportHandler {
public void export(File file, File column) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
PrintWriter out = new PrintWriter(file, "UTF-8");
try {
export(out, column);
@ -56,21 +53,20 @@ public class ChecksumTableExportHandler extends FileExportHandler {
}
public void export(OutputStream out, File column) throws IOException {
PrintStream printer = new PrintStream(out, false, "UTF-8");
public void export(PrintWriter out, File column) {
SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
Date now = new Date();
printer.println("; Generated by FileBot on " + date.format(now) + " at " + time.format(now));
printer.println(";");
printer.println(";");
out.println("; Generated by FileBot on " + date.format(now) + " at " + time.format(now));
out.println(";");
out.println(";");
Map<String, Checksum> checksumMap = model.getChecksumColumn(column);
for (Entry<String, Checksum> entry : checksumMap.entrySet()) {
printer.println(String.format("%s %s", entry.getKey(), entry.getValue()));
out.println(String.format("%s %s", entry.getKey(), entry.getValue()));
}
}

View File

@ -0,0 +1,34 @@
package net.sourceforge.filebot.ui.panel.sfv;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
/**
* DefaultTableCellRenderer that will highlight CRC32 patterns.
*/
class FileNameTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
if (hasFocus) {
// do not highlight checksum patterns in focused cells, that would look weird
return this;
}
// change font-color of checksum pattern
String htmlText = value.toString().replaceAll("\\[(\\p{XDigit}{8})\\]", "[<font color='#009900'>$1</font>]");
// use no-break, because we really don't want line-wrapping in our table cells
setText("<html><nobr>" + htmlText + "</nobr></html>");
return this;
}
}

View File

@ -14,9 +14,6 @@ import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumTableModel.ChecksumTableModelEvent;
import net.sourceforge.filebot.ui.panel.sfv.renderer.ChecksumTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.renderer.FileNameTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.renderer.StateIconTableCellRenderer;
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;

View File

@ -1,5 +1,5 @@
package net.sourceforge.filebot.ui.panel.sfv.renderer;
package net.sourceforge.filebot.ui.panel.sfv;
import java.awt.Component;
@ -10,11 +10,9 @@ import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow.State;
public class StateIconTableCellRenderer extends DefaultTableCellRenderer {
class StateIconTableCellRenderer extends DefaultTableCellRenderer {
private Icon warning = ResourceManager.getIcon("status.warning");
private Icon error = ResourceManager.getIcon("status.error");
@ -32,7 +30,7 @@ public class StateIconTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, null, isSelected, false, row, column);
ChecksumRow.State state = (State) value;
ChecksumRow.State state = (ChecksumRow.State) value;
switch (state) {
case OK:

View File

@ -1,39 +0,0 @@
package net.sourceforge.filebot.ui.panel.sfv.renderer;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
public class ChecksumTableCellRenderer extends DefaultTableCellRenderer {
private final ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, null, isSelected, false, row, column);
if (value == null)
return this;
Checksum checksum = (Checksum) value;
if (checksum.getState() == Checksum.State.READY) {
setText(checksum.getChecksumString());
} else if (checksum.getState() == Checksum.State.PENDING) {
setText("Pending ...");
} else if (checksum.getState() == Checksum.State.ERROR) {
setText(checksum.getErrorMessage());
} else {
return progressBarRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
return this;
}
}

View File

@ -1,48 +0,0 @@
package net.sourceforge.filebot.ui.panel.sfv.renderer;
import java.awt.Component;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class FileNameTableCellRenderer extends DefaultTableCellRenderer {
private final Pattern checksumPattern = Pattern.compile("\\[(\\p{XDigit}{8})\\]");
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
if (hasFocus) {
// do not highlight text is focused, that just looks weird
return this;
}
String text = value.toString();
Matcher matcher = checksumPattern.matcher(text);
if (!matcher.find()) {
// break if name does not contain a checksum that needs to be highlighted
return this;
}
// html label will word-wrap automatically, so we use nobr to make it single-line
StringBuffer sb = new StringBuffer("<html><nobr>");
matcher.appendReplacement(sb, "[<font color=#009900>$1</font>]");
matcher.appendTail(sb);
sb.append("</nobr></html>");
setText(sb.toString());
return this;
}
}

View File

@ -1,81 +0,0 @@
package net.sourceforge.filebot.ui.panel.sfv.renderer;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
public class ProgressBarTableCellRenderer extends JPanel implements TableCellRenderer {
private final JProgressBar progressBar = new JProgressBar(0, 100);
public ProgressBarTableCellRenderer() {
super(new BorderLayout());
progressBar.setStringPainted(true);
add(progressBar, BorderLayout.CENTER);
setBorder(new EmptyBorder(2, 2, 2, 2));
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Checksum checksum = (Checksum) value;
Integer progress = checksum.getProgress();
progressBar.setValue(progress);
if (isSelected) {
this.setBackground(table.getSelectionBackground());
} else {
this.setBackground(table.getBackground());
}
return this;
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(long tm, int x, int y, int width, int height) {
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(Rectangle r) {
}
/**
* Overridden for performance reasons.
*/
@Override
public void repaint() {
}
/**
* Overridden for performance reasons.
*/
@Override
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
}
}

View File

@ -1,40 +0,0 @@
package net.sourceforge.filebot.ui.transfer;
import java.io.IOException;
import java.io.OutputStream;
public abstract class AdaptiveFileExportHandler extends FileExportHandler {
/**
* @return the <code>FileExportHandler</code> that that should be used, or
* <code>null</code> if export is not possible in the first place
*/
protected abstract FileExportHandler getExportHandler();
@Override
public boolean canExport() {
FileExportHandler handler = getExportHandler();
if (handler == null)
return false;
return handler.canExport();
}
@Override
public void export(OutputStream out) throws IOException {
getExportHandler().export(out);
}
@Override
public String getDefaultFileName() {
return getExportHandler().getDefaultFileName();
}
}

View File

@ -10,4 +10,5 @@ import javax.swing.JComponent;
public interface ClipboardHandler {
public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException;
}

View File

@ -4,8 +4,8 @@ package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.swing.JComponent;
import javax.swing.JList;
@ -17,47 +17,55 @@ import javax.swing.tree.TreePath;
public class DefaultClipboardHandler implements ClipboardHandler {
@Override
public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException {
ArrayList<String> lines = new ArrayList<String>();
public void exportToClipboard(JComponent component, Clipboard clip, int action) throws IllegalStateException {
StringWriter buffer = new StringWriter();
if (comp instanceof JList) {
JList list = (JList) comp;
for (Object value : list.getSelectedValues()) {
lines.add(value.toString());
}
} else if (comp instanceof JTree) {
JTree tree = (JTree) comp;
for (TreePath path : tree.getSelectionPaths()) {
lines.add(path.getLastPathComponent().toString());
}
} else if (comp instanceof JTable) {
JTable table = (JTable) comp;
for (int row : table.getSelectedRows()) {
StringBuilder sb = new StringBuilder();
int maxCol = table.getColumnCount() - 1;
for (int col = 0; col <= maxCol; col++) {
sb.append(table.getModel().getValueAt(row, col));
if (col != maxCol)
sb.append("\t");
}
lines.add(sb.toString());
}
}
StringBuilder buffer = new StringBuilder();
Iterator<String> it = lines.iterator();
while (it.hasNext()) {
buffer.append(it.next());
if (it.hasNext())
buffer.append("\n");
if (component instanceof JList) {
export(new PrintWriter(buffer), (JList) component);
} else if (component instanceof JTree) {
export(new PrintWriter(buffer), (JTree) component);
} else if (component instanceof JTable) {
export(new PrintWriter(buffer), (JTable) component);
}
clip.setContents(new StringSelection(buffer.toString()), null);
}
protected void export(PrintWriter out, JList list) {
for (Object value : list.getSelectedValues()) {
out.println(valueToString(value));
}
}
protected void export(PrintWriter out, JTree tree) {
for (TreePath path : tree.getSelectionPaths()) {
out.println(valueToString(path.getLastPathComponent()));
}
}
protected void export(PrintWriter out, JTable table) {
for (int row : table.getSelectedRows()) {
for (int columnIndex = 0; columnIndex < table.getColumnCount(); columnIndex++) {
out.print(valueToString(table.getModel().getValueAt(row, columnIndex)));
if (columnIndex < table.getColumnCount() - 1)
out.print("\t");
}
out.println();
}
}
protected String valueToString(Object value) {
// return empty string for null values
if (value == null)
return "";
return value.toString();
}
}

View File

@ -11,20 +11,20 @@ import javax.swing.TransferHandler;
public class DefaultTransferHandler extends TransferHandler {
private ImportHandler importHandler;
private ExportHandler exportHandler;
private TransferablePolicy transferablePolicy;
private TransferableExportHandler exportHandler;
private ClipboardHandler clipboardHandler;
private boolean dragging = false;
public DefaultTransferHandler(ImportHandler importHandler, ExportHandler exportHandler) {
this(importHandler, exportHandler, new DefaultClipboardHandler());
public DefaultTransferHandler(TransferablePolicy transferablePolicy, TransferableExportHandler exportHandler) {
this(transferablePolicy, exportHandler, new DefaultClipboardHandler());
}
public DefaultTransferHandler(ImportHandler importHandler, ExportHandler exportHandler, ClipboardHandler clipboardHandler) {
this.importHandler = importHandler;
public DefaultTransferHandler(TransferablePolicy transferablePolicy, TransferableExportHandler exportHandler, ClipboardHandler clipboardHandler) {
this.transferablePolicy = transferablePolicy;
this.exportHandler = exportHandler;
this.clipboardHandler = clipboardHandler;
}
@ -36,8 +36,8 @@ public class DefaultTransferHandler extends TransferHandler {
if (dragging)
return true;
if (importHandler != null)
return importHandler.canImport(support);
if (transferablePolicy != null)
return transferablePolicy.canImport(support);
return false;
}
@ -51,7 +51,7 @@ public class DefaultTransferHandler extends TransferHandler {
if (!canImport(support))
return false;
return importHandler.importData(support);
return transferablePolicy.importData(support);
}
@ -94,22 +94,22 @@ public class DefaultTransferHandler extends TransferHandler {
}
public ImportHandler getImportHandler() {
return importHandler;
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
}
public void setImportHandler(ImportHandler importHandler) {
this.importHandler = importHandler;
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
public ExportHandler getExportHandler() {
public TransferableExportHandler getExportHandler() {
return exportHandler;
}
public void setExportHandler(ExportHandler exportHandler) {
public void setExportHandler(TransferableExportHandler exportHandler) {
this.exportHandler = exportHandler;
}

View File

@ -1,19 +0,0 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.Transferable;
import javax.swing.JComponent;
public interface ExportHandler {
public abstract void exportDone(JComponent source, Transferable data, int action);
public abstract int getSourceActions(JComponent c);
public abstract Transferable createTransferable(JComponent c);
}

View File

@ -2,77 +2,18 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.Transferable;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import net.sourceforge.filebot.FileBotUtil;
import net.sourceforge.filebot.Settings;
import net.sourceforge.tuned.TemporaryFolder;
public abstract class FileExportHandler implements ExportHandler {
public interface FileExportHandler {
public abstract boolean canExport();
public boolean canExport();
public abstract void export(OutputStream out) throws IOException;
public void export(File file) throws IOException;
public abstract String getDefaultFileName();
public void export(File file) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
export(out);
} finally {
out.close();
}
}
@Override
public int getSourceActions(JComponent c) {
if (!canExport())
return TransferHandler.NONE;
return TransferHandler.MOVE | TransferHandler.COPY;
}
@Override
public Transferable createTransferable(JComponent c) {
try {
// remove invalid characters from file name
String name = FileBotUtil.validateFileName(getDefaultFileName());
File temporaryFile = TemporaryFolder.getFolder(Settings.ROOT).createFile(name);
export(temporaryFile);
return new FileTransferable(temporaryFile);
} catch (IOException e) {
// should not happen
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
return null;
}
@Override
public void exportDone(JComponent source, Transferable data, int action) {
}
public String getDefaultFileName();
}

View File

@ -9,7 +9,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -30,9 +29,7 @@ public class FileTransferable implements Transferable {
return null;
}
private final List<File> files;
private final DataFlavor[] supportedFlavors = { DataFlavor.javaFileListFlavor, uriListFlavor };
private final Collection<File> files;
public FileTransferable(File... files) {
@ -45,6 +42,7 @@ public class FileTransferable implements Transferable {
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor.isFlavorJavaFileListType())
return files;
@ -56,7 +54,7 @@ public class FileTransferable implements Transferable {
/**
* @return line separated list of file uris
* @return line separated list of file URIs
*/
private String getUriList() {
StringBuilder sb = new StringBuilder();
@ -70,18 +68,20 @@ public class FileTransferable implements Transferable {
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavors.clone();
return new DataFlavor[] { DataFlavor.javaFileListFlavor, uriListFlavor };
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor supportedFlavor : supportedFlavors) {
if (flavor.equals(supportedFlavor))
return true;
}
return false;
return isFileListFlavor(flavor);
}
public static boolean isFileListFlavor(DataFlavor flavor) {
return flavor.isFlavorJavaFileListType() || flavor.equals(uriListFlavor);
}
}

View File

@ -36,7 +36,7 @@ public abstract class FileTransferablePolicy extends TransferablePolicy {
// file list flavor
return (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor);
} else if (tr.isDataFlavorSupported(FileTransferable.uriListFlavor)) {
// file uri list flavor
// file URI list flavor
String transferString = (String) tr.getTransferData(FileTransferable.uriListFlavor);
String lines[] = transferString.split("\r?\n");

View File

@ -1,15 +0,0 @@
package net.sourceforge.filebot.ui.transfer;
import javax.swing.TransferHandler.TransferSupport;
public interface ImportHandler {
public abstract boolean canImport(TransferSupport support);
public abstract boolean importData(TransferSupport support);
}

View File

@ -0,0 +1,62 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.Transferable;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
public abstract class TextFileExportHandler implements TransferableExportHandler, FileExportHandler {
public abstract boolean canExport();
public abstract void export(PrintWriter out);
public abstract String getDefaultFileName();
@Override
public void export(File file) throws IOException {
PrintWriter out = new PrintWriter(file, "UTF-8");
try {
export(out);
} finally {
out.close();
}
}
@Override
public int getSourceActions(JComponent c) {
if (!canExport())
return TransferHandler.NONE;
return TransferHandler.MOVE | TransferHandler.COPY;
}
@Override
public Transferable createTransferable(JComponent c) {
// get transfer data
StringWriter buffer = new StringWriter();
export(new PrintWriter(buffer));
return new TextFileTransferable(buffer.toString(), getDefaultFileName());
}
@Override
public void exportDone(JComponent source, Transferable data, int action) {
}
}

View File

@ -0,0 +1,81 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import net.sourceforge.filebot.FileBotUtil;
import net.sourceforge.filebot.Settings;
import net.sourceforge.tuned.TemporaryFolder;
public class TextFileTransferable implements Transferable {
private final String text;
private final String defaultFileName;
private FileTransferable fileTransferable = null;
public TextFileTransferable(String text, String defaultFileName) {
this.text = text;
this.defaultFileName = defaultFileName;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor.isFlavorTextType()) {
return text;
} else if (FileTransferable.isFileListFlavor(flavor)) {
try {
// create text file for transfer on demand
if (fileTransferable == null) {
fileTransferable = createFileTransferable();
}
return fileTransferable.getTransferData(flavor);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
throw new UnsupportedFlavorException(flavor);
}
private FileTransferable createFileTransferable() throws IOException {
// remove invalid characters from file name
String filename = FileBotUtil.validateFileName(defaultFileName);
// create new temporary file
File temporaryFile = TemporaryFolder.getFolder(Settings.ROOT).createFile(filename);
// write text to file
FileChannel fileChannel = new FileOutputStream(temporaryFile).getChannel();
fileChannel.write(Charset.forName("UTF-8").encode(text));
fileChannel.close();
return new FileTransferable(temporaryFile);
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.stringFlavor, DataFlavor.javaFileListFlavor, FileTransferable.uriListFlavor };
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.isFlavorTextType() || FileTransferable.isFileListFlavor(flavor);
}
}

View File

@ -0,0 +1,20 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.Transferable;
import javax.swing.JComponent;
public interface TransferableExportHandler {
public Transferable createTransferable(JComponent c);
public int getSourceActions(JComponent c);
public void exportDone(JComponent source, Transferable data, int action);
}

View File

@ -11,7 +11,7 @@ import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
public abstract class TransferablePolicy implements ImportHandler {
public abstract class TransferablePolicy {
public abstract boolean accept(Transferable tr);
@ -19,7 +19,6 @@ public abstract class TransferablePolicy implements ImportHandler {
public abstract void handleTransferable(Transferable tr, TransferAction action);
@Override
public boolean canImport(TransferSupport support) {
if (support.isDrop())
@ -37,7 +36,6 @@ public abstract class TransferablePolicy implements ImportHandler {
}
@Override
public boolean importData(TransferSupport support) {
Transferable transferable = support.getTransferable();

View File

@ -1,147 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.Transferable;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.util.List;
import javax.swing.SwingWorker;
import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter;
public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferablePolicy {
public static final String LOADING_PROPERTY = "loading";
private BackgroundWorker worker = null;
@Override
public boolean accept(Transferable tr) {
if (isActive())
return false;
return super.accept(tr);
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
List<File> files = getFilesFromTransferable(tr);
if ((files == null) || files.isEmpty()) {
return;
}
synchronized (this) {
reset();
if (!add) {
clear();
}
worker = new BackgroundWorker(files);
worker.addPropertyChangeListener(new BackgroundWorkerListener());
worker.execute();
}
}
public synchronized boolean isActive() {
return (worker != null) && !worker.isDone();
}
public synchronized void reset() {
if (isActive()) {
worker.cancel(true);
}
}
/**
* Receives data chunks from the publish method asynchronously on the Event Dispatch
* Thread.
*
* @param chunks
*/
protected abstract void process(List<V> chunks);
/**
* Sends data chunks to the process method.
*
* @param chunks
*/
protected final void publish(V... chunks) {
if (worker != null) {
worker.publishChunks(chunks);
}
}
private class BackgroundWorker extends SwingWorker<Void, V> {
private final List<File> files;
public BackgroundWorker(List<File> files) {
this.files = files;
}
@Override
protected Void doInBackground() {
load(files);
return null;
}
public void publishChunks(V... chunks) {
if (!isCancelled()) {
publish(chunks);
}
}
@Override
protected void process(List<V> chunks) {
if (!isCancelled()) {
BackgroundFileTransferablePolicy.this.process(chunks);
}
}
}
private class BackgroundWorkerListener extends SwingWorkerPropertyChangeAdapter {
@Override
public void started(PropertyChangeEvent evt) {
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, null, true);
}
@Override
public void done(PropertyChangeEvent evt) {
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, null, false);
}
}
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
}

View File

@ -1,99 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.Transferable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class CompositeTransferablePolicy implements TransferablePolicy {
private List<TransferablePolicy> policies = Collections.synchronizedList(new ArrayList<TransferablePolicy>());
public CompositeTransferablePolicy() {
}
public void addPolicy(TransferablePolicy policy) {
policies.add(policy);
}
public void removePolicy(TransferablePolicy policy) {
policies.remove(policy);
}
@Override
public boolean accept(Transferable tr) {
return getFirstAccepted(tr) != null;
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
TransferablePolicy policy = getFirstAccepted(tr);
if (policy == null)
return;
if (!add) {
clear();
}
policy.handleTransferable(tr, add);
}
protected void clear() {
}
public TransferablePolicy getFirstAccepted(Transferable tr) {
synchronized (policies) {
for (TransferablePolicy policy : policies) {
if (policy.accept(tr))
return policy;
}
}
return null;
}
@Override
public String getDescription() {
return getDescription(TransferablePolicy.class);
}
public String getDescription(Class<? extends TransferablePolicy> filter) {
List<String> descriptions = new ArrayList<String>();
for (TransferablePolicy policy : policies) {
String desc = policy.getDescription();
if (filter.isInstance(policy))
descriptions.add(desc);
}
StringBuilder sb = new StringBuilder();
Iterator<String> iterator = descriptions.iterator();
while (iterator.hasNext()) {
sb.append(iterator.next().toString());
if (iterator.hasNext())
sb.append(", ");
}
return sb.toString();
}
}

View File

@ -1,123 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.filebot.ui.transfer.FileTransferable;
public abstract class FileTransferablePolicy implements TransferablePolicy {
@Override
public boolean accept(Transferable tr) {
List<File> files = getFilesFromTransferable(tr);
if ((files == null) || files.isEmpty())
return false;
return accept(files);
}
@SuppressWarnings("unchecked")
protected List<File> getFilesFromTransferable(Transferable tr) {
try {
if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// file list flavor
return (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor);
} else if (tr.isDataFlavorSupported(FileTransferable.uriListFlavor)) {
// file uri list flavor
String transferString = (String) tr.getTransferData(FileTransferable.uriListFlavor);
String lines[] = transferString.split("\r?\n");
ArrayList<File> files = new ArrayList<File>(lines.length);
for (String line : lines) {
if (line.startsWith("#")) {
// the line is a comment (as per the RFC 2483)
continue;
}
try {
File file = new File(new URI(line));
if (!file.exists())
throw new FileNotFoundException(file.toString());
files.add(file);
} catch (Exception e) {
// URISyntaxException, IllegalArgumentException, FileNotFoundException
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.WARNING, "Invalid file url: " + line);
}
}
return files;
}
} catch (UnsupportedFlavorException e) {
// should not happen
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
} catch (IOException e) {
// should not happen
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
return null;
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
List<File> files = getFilesFromTransferable(tr);
if ((files == null) || files.isEmpty())
return;
if (!add)
clear();
load(files);
}
protected boolean accept(List<File> files) {
for (File f : files)
if (!accept(f))
return false;
return true;
}
protected void load(List<File> files) {
for (File file : files) {
load(file);
}
}
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
protected void clear() {
}
protected void load(File file) {
}
}

View File

@ -1,44 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.Transferable;
public class MutableTransferablePolicy implements TransferablePolicy {
private TransferablePolicy transferablePolicy = null;
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
@Override
public boolean accept(Transferable tr) {
if (transferablePolicy == null)
return false;
return transferablePolicy.accept(tr);
}
@Override
public String getDescription() {
if (transferablePolicy == null)
return null;
return transferablePolicy.getDescription();
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
if (transferablePolicy == null)
return;
transferablePolicy.handleTransferable(tr, add);
}
}

View File

@ -1,46 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class TextTransferablePolicy implements TransferablePolicy {
@Override
public boolean accept(Transferable tr) {
return tr.isDataFlavorSupported(DataFlavor.stringFlavor);
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
if (!accept(tr))
return;
try {
String string = (String) tr.getTransferData(DataFlavor.stringFlavor);
if (!add) {
clear();
}
load(string);
} catch (Exception e) {
// should not happen
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
}
protected void clear() {
}
protected abstract void load(String text);
}

View File

@ -1,18 +0,0 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.Transferable;
public interface TransferablePolicy {
public boolean accept(Transferable tr);
public void handleTransferable(Transferable tr, boolean add);
public String getDescription();
}

View File

@ -5,9 +5,9 @@ package net.sourceforge.filebot.web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.LongBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
@ -32,8 +32,8 @@ public class OpenSubtitlesHasher {
FileChannel fileChannel = new FileInputStream(file).getChannel();
try {
long head = computeHashForChunk(fileChannel, 0, chunkSizeForFile);
long tail = computeHashForChunk(fileChannel, Math.max(size - HASH_CHUNK_SIZE, 0), chunkSizeForFile);
long head = computeHashForChunk(fileChannel.map(MapMode.READ_ONLY, 0, chunkSizeForFile));
long tail = computeHashForChunk(fileChannel.map(MapMode.READ_ONLY, Math.max(size - HASH_CHUNK_SIZE, 0), chunkSizeForFile));
return String.format("%016x", size + head + tail);
} finally {
@ -42,10 +42,9 @@ public class OpenSubtitlesHasher {
}
private static long computeHashForChunk(FileChannel fileChannel, long start, long size) throws IOException {
MappedByteBuffer byteBuffer = fileChannel.map(MapMode.READ_ONLY, start, size);
private static long computeHashForChunk(ByteBuffer buffer) {
LongBuffer longBuffer = byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer();
LongBuffer longBuffer = buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer();
long hash = 0;
while (longBuffer.hasRemaining()) {

View File

@ -174,16 +174,16 @@ public class TVRageClient implements EpisodeListClient {
if (season > getTotalSeasons() || season < 0)
throw new IllegalArgumentException(String.format("%s only has %d seasons", getName(), getTotalSeasons()));
String seasonString = Integer.toString(season);
List<Node> nodes = XPathUtil.selectNodes("Season" + seasonString + "/episode", episodeListNode);
List<Node> nodes = XPathUtil.selectNodes("Season[@no='" + season + "']/episode", episodeListNode);
List<Episode> episodes = new ArrayList<Episode>(nodes.size());
String numberOfSeason = Integer.toString(season);
for (Node node : nodes) {
String title = XPathUtil.selectString("title", node);
String episodeNumber = XPathUtil.selectString("seasonnum", node);
episodes.add(new Episode(getName(), seasonString, episodeNumber, title));
episodes.add(new Episode(getName(), numberOfSeason, episodeNumber, title));
}
return episodes;

View File

@ -44,4 +44,22 @@ public class ByteBufferInputStream extends InputStream {
return buffer.remaining();
}
@Override
public boolean markSupported() {
return true;
}
@Override
public synchronized void mark(int readlimit) {
buffer.mark();
}
@Override
public synchronized void reset() throws IOException {
buffer.reset();
}
}