Lots of refactoring:
* Removed TransferablePolicySupport and related refactoring * OpenSubtitlesClient: ignore logout status code * Animated-GIF are animated again * Unrar process will not hang anymore * Improved Subscene scraper * Better scaling for ProgressIndicator * Added \r and \n to invalid characters * Some work on SubtitlePanel and related stuff * Setting putMap/List methods clear existing data first
This commit is contained in:
parent
12d453eff4
commit
30a54c2cf4
build.xml
source/net/sourceforge
filebot
FileBotUtil.javaSettings.java
resources
ui
FileBotList.javaFileBotPanel.javaFileBotPanelSelectionList.javaFileBotTabComponent.javaFileBotTree.javaFileTransferableMessageHandler.java
panel
analyze
list
rename
search
sfv
subtitle
transfer
DefaultTransferHandler.javaLoadAction.javaSaveAction.javaTransferablePolicyFileFilter.javaTransferablePolicyImportHandler.javaTransferablePolicySupport.java
transferablepolicies
web
tuned
37
build.xml
37
build.xml
@ -15,10 +15,16 @@
|
|||||||
<property name="lib.nekohtml" value="nekohtml-1.9.7.jar" />
|
<property name="lib.nekohtml" value="nekohtml-1.9.7.jar" />
|
||||||
<property name="lib.simmetrics" value="simmetrics_jar_v1_6_2_d07_02_07.jar" />
|
<property name="lib.simmetrics" value="simmetrics_jar_v1_6_2_d07_02_07.jar" />
|
||||||
<property name="lib.xmlrpc" value="xmlrpc-client-1.1.jar" />
|
<property name="lib.xmlrpc" value="xmlrpc-client-1.1.jar" />
|
||||||
|
|
||||||
|
|
||||||
|
<patternset id="classes">
|
||||||
|
<include name="**/*.class" />
|
||||||
|
<include name="**/*.properties" />
|
||||||
|
<exclude name="**/*Test*" />
|
||||||
|
</patternset>
|
||||||
|
|
||||||
|
|
||||||
<target name="jar" depends="build">
|
<target name="fatjar" depends="build">
|
||||||
<jar destfile="${executable}" duplicate="fail">
|
<jar destfile="${executable}" duplicate="fail">
|
||||||
<fileset dir="${build}" />
|
<fileset dir="${build}" />
|
||||||
|
|
||||||
@ -28,38 +34,27 @@
|
|||||||
<attribute name="Version" value="${version}" />
|
<attribute name="Version" value="${version}" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
||||||
|
|
||||||
<!-- include libs if fatjar is set -->
|
<!-- include libs if fatjar is set -->
|
||||||
<zipfileset src="${lib}/${lib.xerces}">
|
<zipfileset src="${lib}/${lib.xerces}">
|
||||||
<include if="fatjar" name="**/*.class" />
|
<patternset refid="classes" />
|
||||||
<include if="fatjar" name="**/*.properties" />
|
|
||||||
<exclude if="fatjar" name="**/*Test*" />
|
|
||||||
</zipfileset>
|
</zipfileset>
|
||||||
|
|
||||||
<zipfileset src="${lib}/${lib.nekohtml}">
|
<zipfileset src="${lib}/${lib.nekohtml}">
|
||||||
<include if="fatjar" name="**/*.class" />
|
<patternset refid="classes" />
|
||||||
<include if="fatjar" name="**/*.properties" />
|
|
||||||
<exclude if="fatjar" name="**/*Test*" />
|
|
||||||
</zipfileset>
|
</zipfileset>
|
||||||
|
|
||||||
<zipfileset src="${lib}/${lib.simmetrics}">
|
<zipfileset src="${lib}/${lib.simmetrics}">
|
||||||
<include if="fatjar" name="**/*.class" />
|
<patternset refid="classes" />
|
||||||
<include if="fatjar" name="**/*.properties" />
|
|
||||||
<exclude if="fatjar" name="**/*Test*" />
|
|
||||||
</zipfileset>
|
</zipfileset>
|
||||||
|
|
||||||
<zipfileset src="${lib}/${lib.xmlrpc}">
|
<zipfileset src="${lib}/${lib.xmlrpc}">
|
||||||
<include if="fatjar" name="**/*.class" />
|
<patternset refid="classes" />
|
||||||
<include if="fatjar" name="**/*.properties" />
|
|
||||||
<exclude if="fatjar" name="**/*Test*" />
|
|
||||||
</zipfileset>
|
</zipfileset>
|
||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="fatjar">
|
|
||||||
<antcall target="jar">
|
|
||||||
<param name="fatjar" value="true" />
|
|
||||||
</antcall>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
|
|
||||||
<target name="build" depends="clean">
|
<target name="build" depends="clean">
|
||||||
<!-- create build dir -->
|
<!-- create build dir -->
|
||||||
<mkdir dir="${build}" />
|
<mkdir dir="${build}" />
|
||||||
|
@ -4,7 +4,11 @@ package net.sourceforge.filebot;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -16,9 +20,9 @@ public class FileBotUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* invalid characters: \, /, :, *, ?, ", <, > and |
|
* invalid characters: \, /, :, *, ?, ", <, >, |, \r and \n
|
||||||
*/
|
*/
|
||||||
public static final String INVALID_CHARACTERS = "\\/:*?\"<>|";
|
public static final String INVALID_CHARACTERS = "\\/:*?\"<>|\r\n";
|
||||||
public static final Pattern INVALID_CHARACTERS_PATTERN = Pattern.compile(String.format("[%s]+", Pattern.quote(INVALID_CHARACTERS)));
|
public static final Pattern INVALID_CHARACTERS_PATTERN = Pattern.compile(String.format("[%s]+", Pattern.quote(INVALID_CHARACTERS)));
|
||||||
|
|
||||||
|
|
||||||
@ -114,4 +118,12 @@ public class FileBotUtil {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//TODO needed??
|
||||||
|
public static void writeToFile(File file, ByteBuffer data) throws IOException {
|
||||||
|
FileChannel channel = new FileOutputStream(file).getChannel();
|
||||||
|
channel.write(data);
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,14 @@ public class Settings {
|
|||||||
public static final String SUBTITLE_HISTORY = "subtitle/history";
|
public static final String SUBTITLE_HISTORY = "subtitle/history";
|
||||||
public static final String SUBTITLE_LANGUAGE = "subtitle/language";
|
public static final String SUBTITLE_LANGUAGE = "subtitle/language";
|
||||||
|
|
||||||
private static Settings settings = new Settings();
|
private static final Settings settings = new Settings();
|
||||||
|
|
||||||
|
|
||||||
public static Settings getSettings() {
|
public static Settings getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preferences prefs;
|
private final Preferences prefs;
|
||||||
|
|
||||||
|
|
||||||
private Settings() {
|
private Settings() {
|
||||||
@ -89,7 +89,7 @@ public class Settings {
|
|||||||
|
|
||||||
|
|
||||||
public void putStringList(String key, Collection<String> list) {
|
public void putStringList(String key, Collection<String> list) {
|
||||||
Preferences listNode = prefs.node(key);
|
Preferences listNode = getClearNode(key);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ public class Settings {
|
|||||||
|
|
||||||
|
|
||||||
public void putStringMap(String key, Map<String, String> map) {
|
public void putStringMap(String key, Map<String, String> map) {
|
||||||
Preferences mapNode = prefs.node(key);
|
Preferences mapNode = getClearNode(key);
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||||
mapNode.put(entry.getKey(), entry.getValue());
|
mapNode.put(entry.getKey(), entry.getValue());
|
||||||
@ -185,10 +185,24 @@ public class Settings {
|
|||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
try {
|
try {
|
||||||
prefs.removeNode();
|
for (String child : prefs.childrenNames()) {
|
||||||
prefs = Preferences.userRoot().node(ROOT);
|
prefs.node(child).removeNode();
|
||||||
|
}
|
||||||
} catch (BackingStoreException e) {
|
} catch (BackingStoreException e) {
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Preferences getClearNode(String nodeName) {
|
||||||
|
Preferences node = prefs.node(nodeName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
node.clear();
|
||||||
|
} catch (BackingStoreException e) {
|
||||||
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
@ -30,59 +28,47 @@ public class ResourceManager {
|
|||||||
aliasMap.put("loading", "loading.gif");
|
aliasMap.put("loading", "loading.gif");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, Image> cache = Collections.synchronizedMap(new WeakHashMap<String, Image>());
|
private static final Map<String, ImageIcon> iconCache = Collections.synchronizedMap(new WeakHashMap<String, ImageIcon>());
|
||||||
|
|
||||||
|
|
||||||
public static ImageIcon getIcon(String name) {
|
public static ImageIcon getIcon(String name) {
|
||||||
return new ImageIcon(getImage(name));
|
return getIcon(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ImageIcon getIcon(String name, String def) {
|
||||||
|
ImageIcon icon = iconCache.get(name);
|
||||||
|
|
||||||
|
if (icon == null) {
|
||||||
|
// load image if not in cache
|
||||||
|
URL resource = getResource(name, def);
|
||||||
|
|
||||||
|
if (resource != null) {
|
||||||
|
icon = new ImageIcon(resource);
|
||||||
|
iconCache.put(name, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ImageIcon getFlagIcon(String languageCode) {
|
public static ImageIcon getFlagIcon(String languageCode) {
|
||||||
if (languageCode == null)
|
return getIcon(String.format("flags/%s", languageCode), "flags/default");
|
||||||
languageCode = "default";
|
|
||||||
|
|
||||||
return new ImageIcon(getImage(String.format("flags/%s", languageCode.toLowerCase()), "flags/default"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ImageIcon getArchiveIcon(String type) {
|
public static ImageIcon getArchiveIcon(String type) {
|
||||||
if (type == null)
|
return getIcon(String.format("archives/%s", type), "archives/default");
|
||||||
type = "default";
|
|
||||||
|
|
||||||
return new ImageIcon(getImage(String.format("archives/%s", type.toLowerCase()), "archives/default"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Image getImage(String name) {
|
public static Image getImage(String name) {
|
||||||
Image image = cache.get(name);
|
try {
|
||||||
|
return ImageIO.read(getResource(name));
|
||||||
if (image == null) {
|
} catch (IOException e) {
|
||||||
try {
|
throw new RuntimeException(e);
|
||||||
// load image if not in cache
|
|
||||||
URL resource = getResource(name);
|
|
||||||
|
|
||||||
if (resource != null) {
|
|
||||||
image = ImageIO.read(resource);
|
|
||||||
cache.put(name, image);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Image getImage(String name, String def) {
|
|
||||||
Image image = getImage(name);
|
|
||||||
|
|
||||||
// image not found, use default
|
|
||||||
if (image == null)
|
|
||||||
image = getImage(def);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -97,4 +83,14 @@ public class ResourceManager {
|
|||||||
return ResourceManager.class.getResource(resource);
|
return ResourceManager.class.getResource(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static URL getResource(String name, String def) {
|
||||||
|
URL resource = getResource(name);
|
||||||
|
|
||||||
|
if (resource == null)
|
||||||
|
resource = getResource(def);
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,35 +22,28 @@ import javax.swing.border.TitledBorder;
|
|||||||
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.ExportHandler;
|
import net.sourceforge.filebot.ui.transfer.ExportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
||||||
import net.sourceforge.filebot.ui.transfer.ImportHandler;
|
|
||||||
import net.sourceforge.filebot.ui.transfer.Saveable;
|
import net.sourceforge.filebot.ui.transfer.Saveable;
|
||||||
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
|
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
|
import net.sourceforge.filebot.ui.transferablepolicies.MutableTransferablePolicy;
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||||
import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer;
|
import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer;
|
||||||
import net.sourceforge.tuned.ui.SimpleListModel;
|
import net.sourceforge.tuned.ui.SimpleListModel;
|
||||||
import net.sourceforge.tuned.ui.TunedUtil;
|
import net.sourceforge.tuned.ui.TunedUtil;
|
||||||
|
|
||||||
|
|
||||||
public class FileBotList extends JPanel implements Saveable, TransferablePolicySupport {
|
public class FileBotList extends JPanel implements Saveable {
|
||||||
|
|
||||||
private JList list = new JList(new SimpleListModel());
|
private final JList list = new JList(new SimpleListModel());
|
||||||
|
|
||||||
private TitledBorder titledBorder;
|
private final MutableTransferablePolicy mutableTransferablePolicy = new MutableTransferablePolicy();
|
||||||
|
|
||||||
|
private final TitledBorder titledBorder;
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
|
|
||||||
|
|
||||||
|
public FileBotList(boolean enableExport, boolean enableRemoveAction, boolean border) {
|
||||||
public FileBotList(boolean enableDrop, boolean enableDrag, boolean enableRemoveAction) {
|
|
||||||
this(enableDrop, enableDrag, enableRemoveAction, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public FileBotList(boolean enableImport, boolean enableExport, boolean enableRemoveAction, boolean border) {
|
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
|
|
||||||
JScrollPane listScrollPane = new JScrollPane(list);
|
JScrollPane listScrollPane = new JScrollPane(list);
|
||||||
@ -59,6 +52,7 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
|
|||||||
titledBorder = new TitledBorder("");
|
titledBorder = new TitledBorder("");
|
||||||
setBorder(titledBorder);
|
setBorder(titledBorder);
|
||||||
} else {
|
} else {
|
||||||
|
titledBorder = null;
|
||||||
listScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
listScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,16 +61,12 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
|
|||||||
|
|
||||||
add(listScrollPane, BorderLayout.CENTER);
|
add(listScrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
ImportHandler importHander = null;
|
|
||||||
ExportHandler exportHandler = null;
|
ExportHandler exportHandler = null;
|
||||||
|
|
||||||
if (enableImport)
|
|
||||||
importHander = new TransferablePolicyImportHandler(this);
|
|
||||||
|
|
||||||
if (enableExport)
|
if (enableExport)
|
||||||
exportHandler = new SaveableExportHandler(this);
|
exportHandler = new SaveableExportHandler(this);
|
||||||
|
|
||||||
list.setTransferHandler(new DefaultTransferHandler(importHander, exportHandler));
|
list.setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(mutableTransferablePolicy), exportHandler));
|
||||||
list.setDragEnabled(enableExport);
|
list.setDragEnabled(enableExport);
|
||||||
|
|
||||||
if (enableRemoveAction) {
|
if (enableRemoveAction) {
|
||||||
@ -92,12 +82,12 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
|
|||||||
|
|
||||||
|
|
||||||
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
||||||
this.transferablePolicy = transferablePolicy;
|
mutableTransferablePolicy.setTransferablePolicy(transferablePolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TransferablePolicy getTransferablePolicy() {
|
public TransferablePolicy getTransferablePolicy() {
|
||||||
return transferablePolicy;
|
return mutableTransferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -112,10 +102,8 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
|
|||||||
if (titledBorder != null)
|
if (titledBorder != null)
|
||||||
titledBorder.setTitle(title);
|
titledBorder.setTitle(title);
|
||||||
|
|
||||||
if (isVisible()) {
|
revalidate();
|
||||||
revalidate();
|
repaint();
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -153,8 +141,8 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
|
|||||||
public void load(List<File> files) {
|
public void load(List<File> files) {
|
||||||
FileTransferable tr = new FileTransferable(files);
|
FileTransferable tr = new FileTransferable(files);
|
||||||
|
|
||||||
if (transferablePolicy.accept(tr))
|
if (mutableTransferablePolicy.accept(tr))
|
||||||
transferablePolicy.handleTransferable(tr, false);
|
mutableTransferablePolicy.handleTransferable(tr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AbstractAction removeAction = new AbstractAction("Remove") {
|
private final AbstractAction removeAction = new AbstractAction("Remove") {
|
||||||
|
@ -20,19 +20,21 @@ import net.sourceforge.filebot.ui.panel.subtitle.SubtitlePanel;
|
|||||||
|
|
||||||
public class FileBotPanel extends JPanel {
|
public class FileBotPanel extends JPanel {
|
||||||
|
|
||||||
private static final List<FileBotPanel> registry = new ArrayList<FileBotPanel>();
|
private static List<FileBotPanel> registry;
|
||||||
|
|
||||||
static {
|
|
||||||
registry.add(new ListPanel());
|
|
||||||
registry.add(new RenamePanel());
|
|
||||||
registry.add(new AnalyzePanel());
|
|
||||||
registry.add(new SearchPanel());
|
|
||||||
registry.add(new SubtitlePanel());
|
|
||||||
registry.add(new SfvPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static List<FileBotPanel> getAvailablePanels() {
|
public static synchronized List<FileBotPanel> getAvailablePanels() {
|
||||||
|
if (registry == null) {
|
||||||
|
registry = new ArrayList<FileBotPanel>(6);
|
||||||
|
|
||||||
|
registry.add(new ListPanel());
|
||||||
|
registry.add(new RenamePanel());
|
||||||
|
registry.add(new AnalyzePanel());
|
||||||
|
registry.add(new SearchPanel());
|
||||||
|
registry.add(new SubtitlePanel());
|
||||||
|
registry.add(new SfvPanel());
|
||||||
|
}
|
||||||
|
|
||||||
return Collections.unmodifiableList(registry);
|
return Collections.unmodifiableList(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,15 +33,10 @@ class FileBotPanelSelectionList extends JList {
|
|||||||
|
|
||||||
setBorder(new EmptyBorder(4, 5, 4, 5));
|
setBorder(new EmptyBorder(4, 5, 4, 5));
|
||||||
|
|
||||||
|
// initialize "drag over" panel selection
|
||||||
new DropTarget(this, new DragDropListener());
|
new DropTarget(this, new DragDropListener());
|
||||||
|
|
||||||
SimpleListModel model = new SimpleListModel();
|
setModel(new SimpleListModel(FileBotPanel.getAvailablePanels()));
|
||||||
|
|
||||||
for (FileBotPanel panel : FileBotPanel.getAvailablePanels()) {
|
|
||||||
model.add(panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
setModel(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -110,6 +105,7 @@ class FileBotPanelSelectionList extends JList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void drop(DropTargetDropEvent dtde) {
|
public void drop(DropTargetDropEvent dtde) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,42 +4,30 @@ package net.sourceforge.filebot.ui;
|
|||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTabbedPane;
|
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
|
|
||||||
|
|
||||||
public class FileBotTabComponent extends JPanel {
|
public class FileBotTabComponent extends JPanel {
|
||||||
|
|
||||||
private final JLabel label;
|
private final JLabel label = new JLabel();
|
||||||
|
private final JButton closeButton = createCloseButton();
|
||||||
|
|
||||||
|
|
||||||
public FileBotTabComponent() {
|
public FileBotTabComponent() {
|
||||||
this("", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public FileBotTabComponent(String title, Icon icon) {
|
|
||||||
super(new BorderLayout(0, 0));
|
super(new BorderLayout(0, 0));
|
||||||
setOpaque(false);
|
setOpaque(false);
|
||||||
|
|
||||||
label = new JLabel(title, SwingConstants.LEFT);
|
|
||||||
label.setIcon(icon);
|
|
||||||
|
|
||||||
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
|
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
|
||||||
|
|
||||||
add(label, BorderLayout.CENTER);
|
add(label, BorderLayout.CENTER);
|
||||||
add(new CloseButton(tabCloseAction), BorderLayout.EAST);
|
add(closeButton, BorderLayout.EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -58,34 +46,25 @@ public class FileBotTabComponent extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void close() {
|
public JButton getCloseButton() {
|
||||||
JTabbedPane tabs = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, FileBotTabComponent.this);
|
return closeButton;
|
||||||
tabs.removeTabAt(tabs.indexOfTabComponent(FileBotTabComponent.this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AbstractAction tabCloseAction = new AbstractAction(null, null) {
|
|
||||||
|
private JButton createCloseButton() {
|
||||||
|
JButton button = new JButton();
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
button.setContentAreaFilled(false);
|
||||||
close();
|
button.setBorderPainted(false);
|
||||||
}
|
button.setFocusable(false);
|
||||||
};
|
button.setRolloverEnabled(true);
|
||||||
|
|
||||||
|
|
||||||
private class CloseButton extends JButton {
|
|
||||||
|
|
||||||
public CloseButton(AbstractAction action) {
|
button.setIcon(ResourceManager.getIcon("tab.close"));
|
||||||
super(action);
|
button.setRolloverIcon(ResourceManager.getIcon("tab.close.hover"));
|
||||||
|
|
||||||
setContentAreaFilled(false);
|
button.setPreferredSize(new Dimension(17, 17));
|
||||||
setBorderPainted(false);
|
|
||||||
setFocusable(false);
|
return button;
|
||||||
|
}
|
||||||
setIcon(ResourceManager.getIcon("tab.close"));
|
|
||||||
setRolloverIcon(ResourceManager.getIcon("tab.close.hover"));
|
|
||||||
setRolloverEnabled(true);
|
|
||||||
|
|
||||||
setPreferredSize(new Dimension(17, 17));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,9 @@ import javax.swing.tree.TreePath;
|
|||||||
import javax.swing.tree.TreeSelectionModel;
|
import javax.swing.tree.TreeSelectionModel;
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
|
||||||
|
|
||||||
|
|
||||||
public class FileBotTree extends JTree implements TransferablePolicySupport {
|
public class FileBotTree extends JTree {
|
||||||
|
|
||||||
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
|
|
||||||
|
|
||||||
|
|
||||||
public FileBotTree() {
|
public FileBotTree() {
|
||||||
super(new DefaultTreeModel(new DefaultMutableTreeNode()));
|
super(new DefaultTreeModel(new DefaultMutableTreeNode()));
|
||||||
@ -57,16 +51,6 @@ public class FileBotTree extends JTree implements TransferablePolicySupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
|
||||||
this.transferablePolicy = transferablePolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public TransferablePolicy getTransferablePolicy() {
|
|
||||||
return transferablePolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<File> convertToList() {
|
public List<File> convertToList() {
|
||||||
TreeNode node = (TreeNode) getModel().getRoot();
|
TreeNode node = (TreeNode) getModel().getRoot();
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
|
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||||
import net.sourceforge.tuned.MessageBus;
|
import net.sourceforge.tuned.MessageBus;
|
||||||
import net.sourceforge.tuned.MessageHandler;
|
import net.sourceforge.tuned.MessageHandler;
|
||||||
|
|
||||||
@ -18,18 +18,17 @@ import net.sourceforge.tuned.MessageHandler;
|
|||||||
public class FileTransferableMessageHandler implements MessageHandler {
|
public class FileTransferableMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final TransferablePolicySupport transferablePolicySupport;
|
private final TransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public FileTransferableMessageHandler(String name, TransferablePolicySupport transferablePolicySupport) {
|
public FileTransferableMessageHandler(String name, TransferablePolicy transferablePolicy) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.transferablePolicySupport = transferablePolicySupport;
|
this.transferablePolicy = transferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(String topic, String... messages) {
|
public void handle(String topic, String... messages) {
|
||||||
|
|
||||||
// change panel
|
// change panel
|
||||||
MessageBus.getDefault().publish("panel", name);
|
MessageBus.getDefault().publish("panel", name);
|
||||||
|
|
||||||
@ -50,6 +49,6 @@ public class FileTransferableMessageHandler implements MessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transferablePolicySupport.getTransferablePolicy().handleTransferable(new FileTransferable(files), true);
|
transferablePolicy.handleTransferable(new FileTransferable(files), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class AnalyzePanel extends FileBotPanel {
|
|||||||
|
|
||||||
fileTreePanel.getFileTree().addPropertyChangeListener(FileTree.CONTENT_PROPERTY, fileTreeChangeListener);
|
fileTreePanel.getFileTree().addPropertyChangeListener(FileTree.CONTENT_PROPERTY, fileTreeChangeListener);
|
||||||
|
|
||||||
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), fileTreePanel.getFileTree()));
|
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), fileTreePanel.getFileTree().getTransferablePolicy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import net.sourceforge.filebot.ui.FileBotTree;
|
|||||||
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
import net.sourceforge.filebot.ui.transfer.FileTransferable;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
||||||
|
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
class FileTree extends FileBotTree {
|
class FileTree extends FileBotTree {
|
||||||
@ -29,13 +30,19 @@ class FileTree extends FileBotTree {
|
|||||||
|
|
||||||
private PostProcessor postProcessor;
|
private PostProcessor postProcessor;
|
||||||
|
|
||||||
|
private final FileTreeTransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public FileTree() {
|
public FileTree() {
|
||||||
FileTreeTransferablePolicy transferPolicy = new FileTreeTransferablePolicy(this);
|
transferablePolicy = new FileTreeTransferablePolicy(this);
|
||||||
transferPolicy.addPropertyChangeListener(LOADING_PROPERTY, new LoadingPropertyChangeListener());
|
transferablePolicy.addPropertyChangeListener(LOADING_PROPERTY, new LoadingPropertyChangeListener());
|
||||||
|
|
||||||
setTransferablePolicy(transferPolicy);
|
setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(transferablePolicy), null));
|
||||||
setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(this), null));
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TransferablePolicy getTransferablePolicy() {
|
||||||
|
return transferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -64,14 +71,14 @@ class FileTree extends FileBotTree {
|
|||||||
public void load(List<File> files) {
|
public void load(List<File> files) {
|
||||||
FileTransferable tr = new FileTransferable(files);
|
FileTransferable tr = new FileTransferable(files);
|
||||||
|
|
||||||
if (getTransferablePolicy().accept(tr))
|
if (transferablePolicy.accept(tr))
|
||||||
getTransferablePolicy().handleTransferable(tr, true);
|
transferablePolicy.handleTransferable(tr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
((FileTreeTransferablePolicy) getTransferablePolicy()).reset();
|
transferablePolicy.reset();
|
||||||
|
|
||||||
super.clear();
|
super.clear();
|
||||||
contentChanged();
|
contentChanged();
|
||||||
@ -105,7 +112,7 @@ class FileTree extends FileBotTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class PostProcessor extends SwingWorker<List<File>, Object> {
|
private class PostProcessor extends SwingWorker<List<File>, Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<File> doInBackground() throws Exception {
|
protected List<File> doInBackground() throws Exception {
|
||||||
|
@ -50,7 +50,7 @@ class FileTreePanel extends JPanel {
|
|||||||
return fileTree;
|
return fileTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LoadAction loadAction = new LoadAction(fileTree);
|
private final LoadAction loadAction = new LoadAction(fileTree.getTransferablePolicy());
|
||||||
|
|
||||||
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
||||||
|
|
||||||
|
@ -22,12 +22,6 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Defaul
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean accept(File file) {
|
|
||||||
return file.isFile() || file.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
tree.clear();
|
tree.clear();
|
||||||
|
@ -111,7 +111,7 @@ public class SplitPanel extends ToolPanel implements ChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
|
private class UpdateTask extends SwingWorker<DefaultTreeModel, Void> {
|
||||||
|
|
||||||
private final Collection<File> files;
|
private final Collection<File> files;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public class TypePanel extends ToolPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
|
private class UpdateTask extends SwingWorker<DefaultTreeModel, Void> {
|
||||||
|
|
||||||
private final Collection<File> files;
|
private final Collection<File> files;
|
||||||
|
|
||||||
|
@ -26,12 +26,6 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean accept(File file) {
|
|
||||||
return file.isFile() || file.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
list.getModel().clear();
|
list.getModel().clear();
|
||||||
|
@ -39,7 +39,7 @@ public class ListPanel extends FileBotPanel {
|
|||||||
private FileBotList list = new FileBotList(true, true, true);
|
private FileBotList list = new FileBotList(true, true, true);
|
||||||
|
|
||||||
private SaveAction saveAction = new SaveAction(list);
|
private SaveAction saveAction = new SaveAction(list);
|
||||||
private LoadAction loadAction = new LoadAction(list);
|
private LoadAction loadAction = new LoadAction(list.getTransferablePolicy());
|
||||||
|
|
||||||
private JTextField textField = new JTextField(String.format("Name - %s", INDEX_VARIABLE), 25);
|
private JTextField textField = new JTextField(String.format("Name - %s", INDEX_VARIABLE), 25);
|
||||||
private SpinnerNumberModel fromSpinnerModel = new SpinnerNumberModel(1, 0, Integer.MAX_VALUE, 1);
|
private SpinnerNumberModel fromSpinnerModel = new SpinnerNumberModel(1, 0, Integer.MAX_VALUE, 1);
|
||||||
@ -90,7 +90,7 @@ public class ListPanel extends FileBotPanel {
|
|||||||
|
|
||||||
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), createAction);
|
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), createAction);
|
||||||
|
|
||||||
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), list));
|
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), list.getTransferablePolicy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,12 +22,6 @@ class FilesListTransferablePolicy extends FileTransferablePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean accept(File file) {
|
|
||||||
return file.isFile() || file.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
model.clear();
|
model.clear();
|
||||||
|
@ -111,7 +111,7 @@ class MatchAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class BackgroundMatcher extends SwingWorker<List<Match>, Object> {
|
private class BackgroundMatcher extends SwingWorker<List<Match>, Void> {
|
||||||
|
|
||||||
private final RenameList primaryList;
|
private final RenameList primaryList;
|
||||||
private final RenameList secondaryList;
|
private final RenameList secondaryList;
|
||||||
|
@ -69,12 +69,6 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean accept(File file) {
|
|
||||||
return file.isFile() || file.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void load(List<File> files) {
|
protected void load(List<File> files) {
|
||||||
|
|
||||||
@ -146,7 +140,7 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
protected void load(String text) {
|
protected void load(String text) {
|
||||||
List<ListEntry> entries = new ArrayList<ListEntry>();
|
List<ListEntry> entries = new ArrayList<ListEntry>();
|
||||||
|
|
||||||
String[] lines = text.split("\n");
|
String[] lines = text.split("\r?\n");
|
||||||
|
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import net.sourceforge.filebot.ui.transfer.LoadAction;
|
|||||||
class RenameList extends FileBotList {
|
class RenameList extends FileBotList {
|
||||||
|
|
||||||
public RenameList() {
|
public RenameList() {
|
||||||
super(true, false, true);
|
super(false, true, true);
|
||||||
|
|
||||||
Box buttons = Box.createHorizontalBox();
|
Box buttons = Box.createHorizontalBox();
|
||||||
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
|
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
@ -86,7 +86,7 @@ class RenameList extends FileBotList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected final LoadAction loadAction = new LoadAction(this);
|
protected final LoadAction loadAction = new LoadAction(getTransferablePolicy());
|
||||||
|
|
||||||
private MouseAdapter dndReorderMouseAdapter = new MouseAdapter() {
|
private MouseAdapter dndReorderMouseAdapter = new MouseAdapter() {
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.search;
|
|||||||
|
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.ui.FileBotList;
|
import net.sourceforge.filebot.ui.FileBotList;
|
||||||
@ -19,11 +20,11 @@ public class EpisodeListPanel extends FileBotList {
|
|||||||
|
|
||||||
|
|
||||||
public EpisodeListPanel() {
|
public EpisodeListPanel() {
|
||||||
super(false, true, true, false);
|
super(true, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FileBotTabComponent getTabComponent() {
|
public JComponent getTabComponent() {
|
||||||
return tabComponent;
|
return tabComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import net.sourceforge.filebot.web.Episode;
|
|||||||
import net.sourceforge.filebot.web.EpisodeListClient;
|
import net.sourceforge.filebot.web.EpisodeListClient;
|
||||||
|
|
||||||
|
|
||||||
class FetchEpisodeListTask extends SwingWorker<List<Episode>, Object> {
|
class FetchEpisodeListTask extends SwingWorker<List<Episode>, Void> {
|
||||||
|
|
||||||
private final String showName;
|
private final String showName;
|
||||||
private final EpisodeListClient searchEngine;
|
private final EpisodeListClient searchEngine;
|
||||||
|
@ -8,7 +8,6 @@ import java.awt.Window;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -181,41 +180,20 @@ public class SearchPanel extends FileBotPanel {
|
|||||||
|
|
||||||
private final SaveAction saveAction = new SaveAction(null) {
|
private final SaveAction saveAction = new SaveAction(null) {
|
||||||
|
|
||||||
private Saveable current;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Component c = tabbedPane.getSelectedComponent();
|
Component c = tabbedPane.getSelectedComponent();
|
||||||
|
|
||||||
if (c instanceof Saveable) {
|
if (c instanceof Saveable) {
|
||||||
current = (Saveable) c;
|
setSaveable((Saveable) c);
|
||||||
super.actionPerformed(e);
|
super.actionPerformed(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isSaveable() {
|
|
||||||
return current.isSaveable();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getDefaultFileName() {
|
|
||||||
return current.getDefaultFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void save(File file) {
|
|
||||||
current.save(file);
|
|
||||||
current = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private class SearchTask extends SwingWorker<List<String>, Object> {
|
private class SearchTask extends SwingWorker<List<String>, Void> {
|
||||||
|
|
||||||
private String query;
|
private String query;
|
||||||
private EpisodeListClient client;
|
private EpisodeListClient client;
|
||||||
|
@ -10,7 +10,7 @@ import java.util.zip.CheckedInputStream;
|
|||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
|
|
||||||
public class ChecksumComputationTask extends SwingWorker<Long, Object> {
|
public class ChecksumComputationTask extends SwingWorker<Long, Void> {
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 32 * 1024;
|
private static final int BUFFER_SIZE = 32 * 1024;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class SfvPanel extends FileBotPanel {
|
|||||||
// Shortcut DELETE
|
// Shortcut DELETE
|
||||||
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("pressed DELETE"), removeAction);
|
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("pressed DELETE"), removeAction);
|
||||||
|
|
||||||
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), sfvTable));
|
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), sfvTable.getTransferablePolicy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SaveAction saveAction = new SaveAction(sfvTable) {
|
private final SaveAction saveAction = new SaveAction(sfvTable) {
|
||||||
@ -141,7 +141,7 @@ public class SfvPanel extends FileBotPanel {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final LoadAction loadAction = new LoadAction(sfvTable);
|
private final LoadAction loadAction = new LoadAction(sfvTable.getTransferablePolicy());
|
||||||
|
|
||||||
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
||||||
|
|
||||||
|
@ -20,32 +20,28 @@ import net.sourceforge.filebot.FileFormat;
|
|||||||
import net.sourceforge.filebot.ui.panel.sfv.ChecksumTableModel.ChecksumTableModelEvent;
|
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.ChecksumTableCellRenderer;
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.renderer.StateIconTableCellRenderer;
|
import net.sourceforge.filebot.ui.panel.sfv.renderer.StateIconTableCellRenderer;
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.renderer.TextTableCellRenderer;
|
|
||||||
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.ExportHandler;
|
import net.sourceforge.filebot.ui.transfer.ExportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.ImportHandler;
|
import net.sourceforge.filebot.ui.transfer.ImportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.Saveable;
|
import net.sourceforge.filebot.ui.transfer.Saveable;
|
||||||
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
|
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
|
||||||
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
class SfvTable extends JTable implements Saveable {
|
||||||
|
|
||||||
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
|
private final SfvTransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public SfvTable() {
|
public SfvTable() {
|
||||||
final ChecksumTableModel model = (ChecksumTableModel) getModel();
|
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||||
|
|
||||||
setFillsViewportHeight(true);
|
|
||||||
|
|
||||||
transferablePolicy = new SfvTransferablePolicy(model);
|
transferablePolicy = new SfvTransferablePolicy(model);
|
||||||
|
|
||||||
setModel(model);
|
setModel(model);
|
||||||
|
|
||||||
|
setFillsViewportHeight(true);
|
||||||
setAutoCreateRowSorter(true);
|
setAutoCreateRowSorter(true);
|
||||||
setAutoCreateColumnsFromModel(true);
|
setAutoCreateColumnsFromModel(true);
|
||||||
setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
||||||
@ -54,18 +50,22 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||||||
|
|
||||||
setRowHeight(20);
|
setRowHeight(20);
|
||||||
|
|
||||||
ImportHandler importHandler = new TransferablePolicyImportHandler(this);
|
ImportHandler importHandler = new TransferablePolicyImportHandler(transferablePolicy);
|
||||||
ExportHandler exportHandler = new SaveableExportHandler(this);
|
ExportHandler exportHandler = new SaveableExportHandler(this);
|
||||||
|
|
||||||
setTransferHandler(new DefaultTransferHandler(importHandler, exportHandler));
|
setTransferHandler(new DefaultTransferHandler(importHandler, exportHandler));
|
||||||
setDragEnabled(true);
|
setDragEnabled(true);
|
||||||
|
|
||||||
setDefaultRenderer(ChecksumRow.State.class, new StateIconTableCellRenderer());
|
setDefaultRenderer(ChecksumRow.State.class, new StateIconTableCellRenderer());
|
||||||
setDefaultRenderer(String.class, new TextTableCellRenderer());
|
|
||||||
setDefaultRenderer(Checksum.class, new ChecksumTableCellRenderer());
|
setDefaultRenderer(Checksum.class, new ChecksumTableCellRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TransferablePolicy getTransferablePolicy() {
|
||||||
|
return transferablePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableModel createDefaultDataModel() {
|
protected TableModel createDefaultDataModel() {
|
||||||
return new ChecksumTableModel();
|
return new ChecksumTableModel();
|
||||||
@ -90,22 +90,12 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||||||
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
((BackgroundFileTransferablePolicy<?>) getTransferablePolicy()).reset();
|
transferablePolicy.reset();
|
||||||
|
|
||||||
((ChecksumTableModel) getModel()).clear();
|
((ChecksumTableModel) getModel()).clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TransferablePolicy getTransferablePolicy() {
|
|
||||||
return transferablePolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
|
||||||
this.transferablePolicy = transferablePolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getDefaultFileName() {
|
public String getDefaultFileName() {
|
||||||
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||||
File columnRoot = model.getChecksumColumnRoot(0);
|
File columnRoot = model.getChecksumColumnRoot(0);
|
||||||
|
@ -27,12 +27,6 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumTab
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean accept(File file) {
|
|
||||||
return file.isFile() || file.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
tableModel.clear();
|
tableModel.clear();
|
||||||
|
@ -5,13 +5,14 @@ package net.sourceforge.filebot.ui.panel.sfv.renderer;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
|
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
|
||||||
|
|
||||||
|
|
||||||
public class ChecksumTableCellRenderer extends TextTableCellRenderer {
|
public class ChecksumTableCellRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
private ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
|
private final ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,10 +6,10 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.JProgressBar;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
|
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
|
||||||
@ -17,17 +17,17 @@ import net.sourceforge.filebot.ui.panel.sfv.Checksum;
|
|||||||
|
|
||||||
public class ProgressBarTableCellRenderer extends JPanel implements TableCellRenderer {
|
public class ProgressBarTableCellRenderer extends JPanel implements TableCellRenderer {
|
||||||
|
|
||||||
private JProgressBar progressBar = new JProgressBar(0, 100);
|
private final JProgressBar progressBar = new JProgressBar(0, 100);
|
||||||
|
|
||||||
|
|
||||||
public ProgressBarTableCellRenderer() {
|
public ProgressBarTableCellRenderer() {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
|
|
||||||
progressBar.setStringPainted(true);
|
progressBar.setStringPainted(true);
|
||||||
|
|
||||||
add(progressBar, BorderLayout.CENTER);
|
add(progressBar, BorderLayout.CENTER);
|
||||||
|
|
||||||
int margin = 2;
|
setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||||
setBorder(BorderFactory.createEmptyBorder(margin, margin, margin, margin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
|
|||||||
/**
|
/**
|
||||||
* Overridden for performance reasons.
|
* Overridden for performance reasons.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void repaint(long tm, int x, int y, int width, int height) {
|
public void repaint(long tm, int x, int y, int width, int height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
|
|||||||
/**
|
/**
|
||||||
* Overridden for performance reasons.
|
* Overridden for performance reasons.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void repaint(Rectangle r) {
|
public void repaint(Rectangle r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +66,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
|
|||||||
/**
|
/**
|
||||||
* Overridden for performance reasons.
|
* Overridden for performance reasons.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void repaint() {
|
public void repaint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +74,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
|
|||||||
/**
|
/**
|
||||||
* Overridden for performance reasons.
|
* Overridden for performance reasons.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
|
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@ import java.awt.Component;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow;
|
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow;
|
||||||
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow.State;
|
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow.State;
|
||||||
|
|
||||||
|
|
||||||
public class StateIconTableCellRenderer extends TextTableCellRenderer {
|
public class StateIconTableCellRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
private Icon warning = ResourceManager.getIcon("status.warning");
|
private Icon warning = ResourceManager.getIcon("status.warning");
|
||||||
private Icon error = ResourceManager.getIcon("status.error");
|
private Icon error = ResourceManager.getIcon("status.error");
|
||||||
@ -46,8 +47,6 @@ public class StateIconTableCellRenderer extends TextTableCellRenderer {
|
|||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
setIcon(unknown);
|
setIcon(unknown);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.filebot.ui.panel.sfv.renderer;
|
|
||||||
|
|
||||||
|
|
||||||
import java.awt.Component;
|
|
||||||
|
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
|
||||||
|
|
||||||
|
|
||||||
public class TextTableCellRenderer extends DefaultTableCellRenderer {
|
|
||||||
|
|
||||||
public TextTableCellRenderer() {
|
|
||||||
setVerticalAlignment(SwingConstants.CENTER);
|
|
||||||
setHorizontalAlignment(SwingConstants.LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
||||||
super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -20,4 +20,9 @@ public enum ArchiveType {
|
|||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getExtension() {
|
||||||
|
return toString().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import net.sourceforge.filebot.web.SubtitleClient;
|
|||||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||||
|
|
||||||
|
|
||||||
class FetchSubtitleListTask extends SwingWorker<List<? extends SubtitleDescriptor>, Object> {
|
class FetchSubtitleListTask extends SwingWorker<List<? extends SubtitleDescriptor>, Void> {
|
||||||
|
|
||||||
private final SubtitleClient client;
|
private final SubtitleClient client;
|
||||||
private final MovieDescriptor descriptor;
|
private final MovieDescriptor descriptor;
|
||||||
|
121
source/net/sourceforge/filebot/ui/panel/subtitle/FileBotTab.java
Normal file
121
source/net/sourceforge/filebot/ui/panel/subtitle/FileBotTab.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||||
|
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTabbedPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
|
import net.sourceforge.filebot.ui.FileBotTabComponent;
|
||||||
|
|
||||||
|
|
||||||
|
public class FileBotTab<T extends JComponent> extends JPanel {
|
||||||
|
|
||||||
|
private final FileBotTabComponent tabComponent = new FileBotTabComponent();
|
||||||
|
|
||||||
|
private final T component;
|
||||||
|
|
||||||
|
private ImageIcon icon;
|
||||||
|
|
||||||
|
private boolean loading = false;
|
||||||
|
|
||||||
|
|
||||||
|
public FileBotTab(T component) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
|
||||||
|
this.component = component;
|
||||||
|
tabComponent.getCloseButton().addActionListener(closeAction);
|
||||||
|
|
||||||
|
add(component, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addTo(JTabbedPane tabbedPane) {
|
||||||
|
tabbedPane.addTab(this.getTitle(), this);
|
||||||
|
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(this), tabComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (!isClosed()) {
|
||||||
|
getTabbedPane().remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
JTabbedPane tabbedPane = getTabbedPane();
|
||||||
|
|
||||||
|
if (tabbedPane == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return getTabbedPane().indexOfComponent(this) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private JTabbedPane getTabbedPane() {
|
||||||
|
return (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public T getComponent() {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FileBotTabComponent getTabComponent() {
|
||||||
|
return tabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
tabComponent.setText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return tabComponent.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setIcon(ImageIcon icon) {
|
||||||
|
this.icon = icon;
|
||||||
|
|
||||||
|
if (!loading) {
|
||||||
|
tabComponent.setIcon(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ImageIcon getIcon() {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLoading(boolean loading) {
|
||||||
|
this.loading = loading;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
tabComponent.setIcon(ResourceManager.getIcon("tab.loading"));
|
||||||
|
} else {
|
||||||
|
tabComponent.setIcon(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ActionListener closeAction = new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@ public class LanguageResolver {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the locale for a language.
|
* Get the {@link Locale} for a given language name (e.g. "german").
|
||||||
*
|
*
|
||||||
* @param languageName english name of the language
|
* @param languageName english name of the language
|
||||||
* @return the locale for this language or null if no locale for this language exists
|
* @return the locale for this language or null if no locale for this language exists
|
||||||
@ -56,6 +56,13 @@ public class LanguageResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the {@link Locale} for a given language name.
|
||||||
|
*
|
||||||
|
* @param languageName lower-case language name
|
||||||
|
* @return {@link Locale} for the given language, or null if no matching {@link Locale} is
|
||||||
|
* available
|
||||||
|
*/
|
||||||
private Locale findLocale(String languageName) {
|
private Locale findLocale(String languageName) {
|
||||||
for (Locale locale : Locale.getAvailableLocales()) {
|
for (Locale locale : Locale.getAvailableLocales()) {
|
||||||
if (locale.getDisplayLanguage(Locale.ENGLISH).toLowerCase().equals(languageName))
|
if (locale.getDisplayLanguage(Locale.ENGLISH).toLowerCase().equals(languageName))
|
||||||
|
@ -12,8 +12,6 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
|
||||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
|
||||||
import net.sourceforge.tuned.ui.ColorTintImageFilter;
|
import net.sourceforge.tuned.ui.ColorTintImageFilter;
|
||||||
import net.sourceforge.tuned.ui.IconViewCellRenderer;
|
import net.sourceforge.tuned.ui.IconViewCellRenderer;
|
||||||
|
|
||||||
@ -44,18 +42,17 @@ public class SubtitleCellRenderer extends IconViewCellRenderer {
|
|||||||
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
|
||||||
SubtitleDescriptor subtitle = (SubtitleDescriptor) value;
|
SubtitlePackage subtitle = (SubtitlePackage) value;
|
||||||
|
|
||||||
setText(subtitle.getName());
|
setText(subtitle.getName());
|
||||||
|
|
||||||
info1.setText(subtitle.getLanguageName());
|
info1.setText(subtitle.getLanguageName());
|
||||||
info2.setText(subtitle.getAuthor());
|
|
||||||
|
|
||||||
icon = (ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLocale(subtitle.getLanguageName()).getLanguage()));
|
icon = subtitle.getLanguageIcon();
|
||||||
|
|
||||||
info1.setIcon(icon);
|
info1.setIcon(icon);
|
||||||
|
|
||||||
ImageIcon icon = ResourceManager.getArchiveIcon(subtitle.getArchiveType());
|
ImageIcon icon = subtitle.getArchiveIcon();
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
setIcon(new ImageIcon(createImage(new FilteredImageSource(icon.getImage().getSource(), new ColorTintImageFilter(list.getSelectionBackground(), 0.5f)))));
|
setIcon(new ImageIcon(createImage(new FilteredImageSource(icon.getImage().getSource(), new ColorTintImageFilter(list.getSelectionBackground(), 0.5f)))));
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||||
|
import net.sourceforge.tuned.ui.SimpleListModel;
|
||||||
|
|
||||||
|
|
||||||
|
public class SubtitleDownloadPanel extends JPanel {
|
||||||
|
|
||||||
|
private final SubtitlePackagePanel packagePanel = new SubtitlePackagePanel();
|
||||||
|
|
||||||
|
|
||||||
|
public SubtitleDownloadPanel() {
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
add(packagePanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SubtitlePackagePanel getPackagePanel() {
|
||||||
|
return packagePanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addSubtitleDescriptors(List<? extends SubtitleDescriptor> subtitleDescriptors) {
|
||||||
|
SimpleListModel model = new SimpleListModel();
|
||||||
|
|
||||||
|
for (SubtitleDescriptor subtitleDescriptor : subtitleDescriptors) {
|
||||||
|
model.add(new SubtitlePackage(subtitleDescriptor));
|
||||||
|
}
|
||||||
|
//TODO real add, not setModel
|
||||||
|
packagePanel.setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,7 @@ import java.beans.PropertyChangeEvent;
|
|||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.beans.PropertyChangeSupport;
|
import java.beans.PropertyChangeSupport;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||||
@ -17,13 +17,20 @@ public class SubtitlePackage {
|
|||||||
|
|
||||||
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||||
|
|
||||||
private DownloadTask downloadTask = null;
|
|
||||||
|
|
||||||
private final SubtitleDescriptor subtitleDescriptor;
|
private final SubtitleDescriptor subtitleDescriptor;
|
||||||
|
|
||||||
|
private final ImageIcon archiveIcon;
|
||||||
|
|
||||||
|
private final ImageIcon languageIcon;
|
||||||
|
|
||||||
|
private DownloadTask downloadTask;
|
||||||
|
|
||||||
|
|
||||||
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
|
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
|
||||||
this.subtitleDescriptor = subtitleDescriptor;
|
this.subtitleDescriptor = subtitleDescriptor;
|
||||||
|
|
||||||
|
archiveIcon = ResourceManager.getArchiveIcon(subtitleDescriptor.getArchiveType());
|
||||||
|
languageIcon = ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLanguageCode(subtitleDescriptor.getLanguageName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -37,8 +44,8 @@ public class SubtitlePackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Icon getArchiveIcon() {
|
public ImageIcon getArchiveIcon() {
|
||||||
return ResourceManager.getArchiveIcon(getArchiveType().toString());
|
return archiveIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -47,8 +54,8 @@ public class SubtitlePackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Icon getLanguageIcon() {
|
public ImageIcon getLanguageIcon() {
|
||||||
return ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLanguageCode(getLanguageName()));
|
return languageIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +64,7 @@ public class SubtitlePackage {
|
|||||||
throw new IllegalStateException("Download has been started already");
|
throw new IllegalStateException("Download has been started already");
|
||||||
|
|
||||||
downloadTask = subtitleDescriptor.createDownloadTask();
|
downloadTask = subtitleDescriptor.createDownloadTask();
|
||||||
downloadTask.addPropertyChangeListener(new DownloadTaskPropertyChangeRelay());
|
downloadTask.addPropertyChangeListener(new DownloadTaskPropertyChangeAdapter());
|
||||||
|
|
||||||
downloadTask.execute();
|
downloadTask.execute();
|
||||||
}
|
}
|
||||||
@ -81,7 +88,7 @@ public class SubtitlePackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class DownloadTaskPropertyChangeRelay implements PropertyChangeListener {
|
private class DownloadTaskPropertyChangeAdapter implements PropertyChangeListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
@ -20,25 +20,23 @@ import java.util.TreeSet;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolTip;
|
|
||||||
import javax.swing.ListModel;
|
import javax.swing.ListModel;
|
||||||
|
|
||||||
import net.sourceforge.filebot.Settings;
|
import net.sourceforge.filebot.Settings;
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
|
||||||
import net.sourceforge.tuned.ui.IconViewPanel;
|
import net.sourceforge.tuned.ui.IconViewPanel;
|
||||||
import net.sourceforge.tuned.ui.SimpleListModel;
|
import net.sourceforge.tuned.ui.SimpleListModel;
|
||||||
|
|
||||||
|
|
||||||
public class SubtitleViewPanel extends IconViewPanel {
|
public class SubtitlePackagePanel extends IconViewPanel {
|
||||||
|
|
||||||
|
private final JPanel languageFilterPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 1));
|
||||||
|
|
||||||
private ListModel unfilteredModel = new SimpleListModel();
|
private ListModel unfilteredModel = new SimpleListModel();
|
||||||
private JPanel languageFilterPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 1));
|
|
||||||
|
|
||||||
private Map<String, Boolean> languageFilterSelection = new TreeMap<String, Boolean>(String.CASE_INSENSITIVE_ORDER);
|
private Map<String, Boolean> languageFilterSelection = new TreeMap<String, Boolean>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
|
||||||
public SubtitleViewPanel() {
|
public SubtitlePackagePanel() {
|
||||||
setCellRenderer(new SubtitleCellRenderer());
|
setCellRenderer(new SubtitleCellRenderer());
|
||||||
|
|
||||||
languageFilterPanel.setOpaque(false);
|
languageFilterPanel.setOpaque(false);
|
||||||
@ -71,7 +69,7 @@ public class SubtitleViewPanel extends IconViewPanel {
|
|||||||
SortedSet<String> languages = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
|
SortedSet<String> languages = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
for (int i = 0; i < unfilteredModel.getSize(); i++) {
|
for (int i = 0; i < unfilteredModel.getSize(); i++) {
|
||||||
SubtitleDescriptor subtitle = (SubtitleDescriptor) unfilteredModel.getElementAt(i);
|
SubtitlePackage subtitle = (SubtitlePackage) unfilteredModel.getElementAt(i);
|
||||||
languages.add(subtitle.getLanguageName());
|
languages.add(subtitle.getLanguageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +88,7 @@ public class SubtitleViewPanel extends IconViewPanel {
|
|||||||
SimpleListModel model = new SimpleListModel();
|
SimpleListModel model = new SimpleListModel();
|
||||||
|
|
||||||
for (int i = 0; i < unfilteredModel.getSize(); i++) {
|
for (int i = 0; i < unfilteredModel.getSize(); i++) {
|
||||||
SubtitleDescriptor subtitle = (SubtitleDescriptor) unfilteredModel.getElementAt(i);
|
SubtitlePackage subtitle = (SubtitlePackage) unfilteredModel.getElementAt(i);
|
||||||
|
|
||||||
if (isLanguageSelected(subtitle.getLanguageName())) {
|
if (isLanguageSelected(subtitle.getLanguageName())) {
|
||||||
model.add(subtitle);
|
model.add(subtitle);
|
||||||
@ -106,6 +104,12 @@ public class SubtitleViewPanel extends IconViewPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLanguageSelected(String language, boolean selected) {
|
||||||
|
languageFilterSelection.put(language, selected);
|
||||||
|
Settings.getSettings().putBooleanMapEntry(Settings.SUBTITLE_LANGUAGE, language, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private LanguageFilterButton createLanguageFilterButton(String language) {
|
private LanguageFilterButton createLanguageFilterButton(String language) {
|
||||||
Locale locale = LanguageResolver.getDefault().getLocale(language);
|
Locale locale = LanguageResolver.getDefault().getLocale(language);
|
||||||
|
|
||||||
@ -132,8 +136,7 @@ public class SubtitleViewPanel extends IconViewPanel {
|
|||||||
public void itemStateChanged(ItemEvent e) {
|
public void itemStateChanged(ItemEvent e) {
|
||||||
boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
|
boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
|
||||||
|
|
||||||
languageFilterSelection.put(language, selected);
|
setLanguageSelected(language, selected);
|
||||||
Settings.getSettings().putBooleanMapEntry(Settings.SUBTITLE_LANGUAGE, language, selected);
|
|
||||||
|
|
||||||
updateFilteredModel();
|
updateFilteredModel();
|
||||||
}
|
}
|
||||||
@ -170,19 +173,15 @@ public class SubtitleViewPanel extends IconViewPanel {
|
|||||||
protected void paintComponent(Graphics g) {
|
protected void paintComponent(Graphics g) {
|
||||||
Graphics2D g2d = (Graphics2D) g;
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
AlphaComposite composite = AlphaComposite.SrcOver.derive(isSelected() ? 1.0f : 0.2f);
|
// make transparent if not selected
|
||||||
g2d.setComposite(composite);
|
if (!isSelected()) {
|
||||||
|
AlphaComposite composite = AlphaComposite.SrcOver.derive(0.2f);
|
||||||
|
g2d.setComposite(composite);
|
||||||
|
}
|
||||||
|
|
||||||
super.paintComponent(g2d);
|
super.paintComponent(g2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JToolTip createToolTip() {
|
|
||||||
System.out.println("SubtitleViewPanel.createToolTip()");
|
|
||||||
return super.createToolTip();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -30,7 +30,6 @@ import net.sourceforge.filebot.FileBotUtil;
|
|||||||
import net.sourceforge.filebot.Settings;
|
import net.sourceforge.filebot.Settings;
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.filebot.ui.FileBotPanel;
|
import net.sourceforge.filebot.ui.FileBotPanel;
|
||||||
import net.sourceforge.filebot.ui.FileBotTabComponent;
|
|
||||||
import net.sourceforge.filebot.ui.HistoryPanel;
|
import net.sourceforge.filebot.ui.HistoryPanel;
|
||||||
import net.sourceforge.filebot.ui.MessageManager;
|
import net.sourceforge.filebot.ui.MessageManager;
|
||||||
import net.sourceforge.filebot.ui.SelectDialog;
|
import net.sourceforge.filebot.ui.SelectDialog;
|
||||||
@ -133,7 +132,7 @@ public class SubtitlePanel extends FileBotPanel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private class SearchTask extends SwingWorker<List<MovieDescriptor>, Object> {
|
private class SearchTask extends SwingWorker<List<MovieDescriptor>, Void> {
|
||||||
|
|
||||||
private final String query;
|
private final String query;
|
||||||
private final SubtitleClient client;
|
private final SubtitleClient client;
|
||||||
@ -155,26 +154,27 @@ public class SubtitlePanel extends FileBotPanel {
|
|||||||
|
|
||||||
private class SearchTaskListener extends SwingWorkerPropertyChangeAdapter {
|
private class SearchTaskListener extends SwingWorkerPropertyChangeAdapter {
|
||||||
|
|
||||||
private SubtitleViewPanel subtitleSearchResultPanel;
|
private FileBotTab<SubtitleDownloadPanel> downloadPanel;
|
||||||
private FileBotTabComponent tabComponent;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(PropertyChangeEvent evt) {
|
public void started(PropertyChangeEvent evt) {
|
||||||
SearchTask task = (SearchTask) evt.getSource();
|
SearchTask task = (SearchTask) evt.getSource();
|
||||||
|
|
||||||
subtitleSearchResultPanel = new SubtitleViewPanel();
|
downloadPanel = new FileBotTab<SubtitleDownloadPanel>(new SubtitleDownloadPanel());
|
||||||
tabComponent = new FileBotTabComponent(task.query, ResourceManager.getIcon("tab.loading"));
|
|
||||||
|
|
||||||
tabbedPane.addTab(task.query, subtitleSearchResultPanel);
|
downloadPanel.setTitle(task.query);
|
||||||
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(subtitleSearchResultPanel), tabComponent);
|
downloadPanel.setLoading(true);
|
||||||
|
downloadPanel.setIcon(task.client.getIcon());
|
||||||
|
|
||||||
|
downloadPanel.addTo(tabbedPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(PropertyChangeEvent evt) {
|
public void done(PropertyChangeEvent evt) {
|
||||||
// tab might have been closed
|
// tab might have been closed
|
||||||
if (tabbedPane.indexOfComponent(subtitleSearchResultPanel) < 0)
|
if (downloadPanel.isClosed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SearchTask searchTask = (SearchTask) evt.getSource();
|
SearchTask searchTask = (SearchTask) evt.getSource();
|
||||||
@ -185,18 +185,26 @@ public class SubtitlePanel extends FileBotPanel {
|
|||||||
MovieDescriptor descriptor = selectDescriptor(desriptors, searchTask.client);
|
MovieDescriptor descriptor = selectDescriptor(desriptors, searchTask.client);
|
||||||
|
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
|
// user canceled selection, or no subtitles available
|
||||||
if (desriptors.isEmpty()) {
|
if (desriptors.isEmpty()) {
|
||||||
MessageManager.showWarning(String.format("\"%s\" has not been found.", searchTask.query));
|
MessageManager.showWarning(String.format("\"%s\" has not been found.", searchTask.query));
|
||||||
}
|
}
|
||||||
|
|
||||||
tabbedPane.remove(subtitleSearchResultPanel);
|
downloadPanel.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchSubtitles(descriptor, searchTask.client);
|
searchFieldCompletion.addTerm(descriptor.getTitle());
|
||||||
|
Settings.getSettings().putStringList(Settings.SUBTITLE_HISTORY, searchFieldCompletion.getTerms());
|
||||||
|
|
||||||
|
downloadPanel.setTitle(descriptor.getTitle());
|
||||||
|
|
||||||
|
FetchSubtitleListTask fetchListTask = new FetchSubtitleListTask(descriptor, searchTask.client);
|
||||||
|
fetchListTask.addPropertyChangeListener(new FetchSubtitleListTaskListener(downloadPanel));
|
||||||
|
|
||||||
|
fetchListTask.execute();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
tabbedPane.remove(subtitleSearchResultPanel);
|
downloadPanel.close();
|
||||||
|
|
||||||
Throwable cause = FileBotUtil.getRootCause(e);
|
Throwable cause = FileBotUtil.getRootCause(e);
|
||||||
|
|
||||||
@ -224,42 +232,27 @@ public class SubtitlePanel extends FileBotPanel {
|
|||||||
selectDialog.setIconImage(client.getIcon().getImage());
|
selectDialog.setIconImage(client.getIcon().getImage());
|
||||||
selectDialog.setVisible(true);
|
selectDialog.setVisible(true);
|
||||||
|
|
||||||
// selected value or null if cancelled by the user
|
// selected value or null if canceled by the user
|
||||||
return selectDialog.getSelectedValue();
|
return selectDialog.getSelectedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void fetchSubtitles(MovieDescriptor descriptor, SubtitleClient client) {
|
|
||||||
|
|
||||||
Settings.getSettings().putStringList(Settings.SUBTITLE_HISTORY, searchFieldCompletion.getTerms());
|
|
||||||
searchFieldCompletion.addTerm(descriptor.getTitle());
|
|
||||||
|
|
||||||
tabComponent.setText(descriptor.getTitle());
|
|
||||||
|
|
||||||
FetchSubtitleListTask fetchListTask = new FetchSubtitleListTask(descriptor, client);
|
|
||||||
fetchListTask.addPropertyChangeListener(new FetchSubtitleListTaskListener(subtitleSearchResultPanel, tabComponent));
|
|
||||||
|
|
||||||
fetchListTask.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class FetchSubtitleListTaskListener extends SwingWorkerPropertyChangeAdapter {
|
private class FetchSubtitleListTaskListener extends SwingWorkerPropertyChangeAdapter {
|
||||||
|
|
||||||
private final SubtitleViewPanel subtitleSearchResultPanel;
|
private final FileBotTab<SubtitleDownloadPanel> downloadPanel;
|
||||||
private final FileBotTabComponent tabComponent;
|
|
||||||
|
|
||||||
|
|
||||||
public FetchSubtitleListTaskListener(SubtitleViewPanel subtitleSearchResultPanel, FileBotTabComponent tabComponent) {
|
public FetchSubtitleListTaskListener(FileBotTab<SubtitleDownloadPanel> downloadPanel) {
|
||||||
this.subtitleSearchResultPanel = subtitleSearchResultPanel;
|
this.downloadPanel = downloadPanel;
|
||||||
this.tabComponent = tabComponent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(PropertyChangeEvent evt) {
|
public void done(PropertyChangeEvent evt) {
|
||||||
// tab might have been closed
|
// tab might have been closed
|
||||||
if (tabbedPane.indexOfComponent(subtitleSearchResultPanel) < 0)
|
if (downloadPanel.isClosed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FetchSubtitleListTask task = (FetchSubtitleListTask) evt.getSource();
|
FetchSubtitleListTask task = (FetchSubtitleListTask) evt.getSource();
|
||||||
@ -272,17 +265,17 @@ public class SubtitlePanel extends FileBotPanel {
|
|||||||
historyPanel.add(task.getDescriptor().toString(), null, task.getClient().getIcon(), info, NumberFormat.getInstance().format(task.getDuration()) + " ms");
|
historyPanel.add(task.getDescriptor().toString(), null, task.getClient().getIcon(), info, NumberFormat.getInstance().format(task.getDuration()) + " ms");
|
||||||
|
|
||||||
if (subtitleDescriptors.isEmpty()) {
|
if (subtitleDescriptors.isEmpty()) {
|
||||||
tabbedPane.remove(subtitleSearchResultPanel);
|
MessageManager.showWarning(info);
|
||||||
|
downloadPanel.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tabComponent.setIcon(task.getClient().getIcon());
|
downloadPanel.setLoading(false);
|
||||||
|
|
||||||
//TODO icon view
|
downloadPanel.getComponent().getPackagePanel().setTitle(info);
|
||||||
//TODO sysout
|
downloadPanel.getComponent().addSubtitleDescriptors(subtitleDescriptors);
|
||||||
System.out.println(subtitleDescriptors);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
tabbedPane.remove(subtitleSearchResultPanel);
|
downloadPanel.close();
|
||||||
|
|
||||||
MessageManager.showWarning(FileBotUtil.getRootCause(e).getMessage());
|
MessageManager.showWarning(FileBotUtil.getRootCause(e).getMessage());
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
||||||
|
@ -20,12 +20,12 @@ public class Unrar {
|
|||||||
private static final int sleepInterval = 50;
|
private static final int sleepInterval = 50;
|
||||||
|
|
||||||
|
|
||||||
public static void extractFiles(File archive, File destination) throws Exception {
|
public static void extractFiles(File archiveFile, File destinationFolder) throws Exception {
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
throw new IllegalStateException("Unrar could not be initialized");
|
throw new IllegalStateException("Unrar could not be initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
Process process = command.execute(archive, destination);
|
Process process = command.execute(archiveFile, destinationFolder);
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
@ -117,7 +117,15 @@ public class Unrar {
|
|||||||
ProcessBuilder builder = new ProcessBuilder(executable, "x", "-y", archive.getAbsolutePath());
|
ProcessBuilder builder = new ProcessBuilder(executable, "x", "-y", archive.getAbsolutePath());
|
||||||
builder.directory(workingDirectory);
|
builder.directory(workingDirectory);
|
||||||
|
|
||||||
return builder.start();
|
Process process = builder.start();
|
||||||
|
|
||||||
|
// make sure process is non-interactive
|
||||||
|
// e.g. if input stream is not closed 7z.exe sometimes doesn't exit
|
||||||
|
process.getInputStream().close();
|
||||||
|
process.getOutputStream().close();
|
||||||
|
process.getErrorStream().close();
|
||||||
|
|
||||||
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,5 +92,26 @@ public class DefaultTransferHandler extends TransferHandler {
|
|||||||
if (clipboardHandler != null)
|
if (clipboardHandler != null)
|
||||||
clipboardHandler.exportToClipboard(comp, clip, action);
|
clipboardHandler.exportToClipboard(comp, clip, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void setImportHandler(ImportHandler importHandler) {
|
||||||
|
this.importHandler = importHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void setExportHandler(ExportHandler exportHandler) {
|
||||||
|
this.exportHandler = exportHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void setClipboardHandler(ClipboardHandler clipboardHandler) {
|
||||||
|
this.clipboardHandler = clipboardHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,19 +13,19 @@ import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
|||||||
|
|
||||||
public class LoadAction extends AbstractAction {
|
public class LoadAction extends AbstractAction {
|
||||||
|
|
||||||
private TransferablePolicySupport transferablePolicySupport;
|
private final TransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public LoadAction(TransferablePolicySupport transferablePolicySupport) {
|
public LoadAction(TransferablePolicy transferablePolicy) {
|
||||||
super("Load", ResourceManager.getIcon("action.load"));
|
super("Load", ResourceManager.getIcon("action.load"));
|
||||||
this.transferablePolicySupport = transferablePolicySupport;
|
this.transferablePolicy = transferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JFileChooser chooser = new JFileChooser();
|
JFileChooser chooser = new JFileChooser();
|
||||||
|
|
||||||
chooser.setFileFilter(new TransferablePolicyFileFilter(transferablePolicySupport.getTransferablePolicy()));
|
chooser.setFileFilter(new TransferablePolicyFileFilter(transferablePolicy));
|
||||||
|
|
||||||
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||||
chooser.setMultiSelectionEnabled(true);
|
chooser.setMultiSelectionEnabled(true);
|
||||||
@ -35,8 +35,6 @@ public class LoadAction extends AbstractAction {
|
|||||||
|
|
||||||
FileTransferable transferable = new FileTransferable(chooser.getSelectedFiles());
|
FileTransferable transferable = new FileTransferable(chooser.getSelectedFiles());
|
||||||
|
|
||||||
TransferablePolicy transferablePolicy = transferablePolicySupport.getTransferablePolicy();
|
|
||||||
|
|
||||||
boolean add = ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0);
|
boolean add = ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0);
|
||||||
|
|
||||||
if (transferablePolicy.accept(transferable))
|
if (transferablePolicy.accept(transferable))
|
||||||
|
@ -43,6 +43,11 @@ public class SaveAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setSaveable(Saveable saveable) {
|
||||||
|
this.saveable = saveable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (!isSaveable())
|
if (!isSaveable())
|
||||||
return;
|
return;
|
||||||
|
@ -13,7 +13,7 @@ import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
|||||||
|
|
||||||
public class TransferablePolicyFileFilter extends FileFilter {
|
public class TransferablePolicyFileFilter extends FileFilter {
|
||||||
|
|
||||||
private TransferablePolicy transferablePolicy;
|
private final TransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public TransferablePolicyFileFilter(TransferablePolicy transferablePolicy) {
|
public TransferablePolicyFileFilter(TransferablePolicy transferablePolicy) {
|
||||||
|
@ -10,15 +10,16 @@ import java.util.logging.Logger;
|
|||||||
import javax.swing.TransferHandler;
|
import javax.swing.TransferHandler;
|
||||||
import javax.swing.TransferHandler.TransferSupport;
|
import javax.swing.TransferHandler.TransferSupport;
|
||||||
|
|
||||||
|
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public class TransferablePolicyImportHandler implements ImportHandler {
|
public class TransferablePolicyImportHandler implements ImportHandler {
|
||||||
|
|
||||||
private TransferablePolicySupport transferablePolicySupport;
|
private final TransferablePolicy transferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
public TransferablePolicyImportHandler(TransferablePolicySupport transferablePolicySupport) {
|
public TransferablePolicyImportHandler(TransferablePolicy transferablePolicy) {
|
||||||
this.transferablePolicySupport = transferablePolicySupport;
|
this.transferablePolicy = transferablePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canImportCache = false;
|
private boolean canImportCache = false;
|
||||||
@ -32,7 +33,7 @@ public class TransferablePolicyImportHandler implements ImportHandler {
|
|||||||
Transferable t = support.getTransferable();
|
Transferable t = support.getTransferable();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
canImportCache = transferablePolicySupport.getTransferablePolicy().accept(t);
|
canImportCache = transferablePolicy.accept(t);
|
||||||
} catch (InvalidDnDOperationException e) {
|
} catch (InvalidDnDOperationException e) {
|
||||||
// for some reason the last transferable has no drop current
|
// for some reason the last transferable has no drop current
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ public class TransferablePolicyImportHandler implements ImportHandler {
|
|||||||
Transferable t = support.getTransferable();
|
Transferable t = support.getTransferable();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
transferablePolicySupport.getTransferablePolicy().handleTransferable(t, add);
|
transferablePolicy.handleTransferable(t, add);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.filebot.ui.transfer;
|
|
||||||
|
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
|
||||||
|
|
||||||
|
|
||||||
public interface TransferablePolicySupport {
|
|
||||||
|
|
||||||
public TransferablePolicy getTransferablePolicy();
|
|
||||||
}
|
|
@ -85,7 +85,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class BackgroundWorker extends SwingWorker<Object, V> {
|
private class BackgroundWorker extends SwingWorker<Void, V> {
|
||||||
|
|
||||||
private final List<File> files;
|
private final List<File> files;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() {
|
protected Void doInBackground() {
|
||||||
load(files);
|
load(files);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -110,7 +110,7 @@ public abstract class FileTransferablePolicy implements TransferablePolicy {
|
|||||||
|
|
||||||
|
|
||||||
protected boolean accept(File file) {
|
protected boolean accept(File file) {
|
||||||
return false;
|
return file.isFile() || file.isDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -12,16 +12,18 @@ import javax.swing.ImageIcon;
|
|||||||
|
|
||||||
public abstract class EpisodeListClient {
|
public abstract class EpisodeListClient {
|
||||||
|
|
||||||
private static final List<EpisodeListClient> registry = new ArrayList<EpisodeListClient>();
|
private static List<EpisodeListClient> registry;
|
||||||
|
|
||||||
static {
|
|
||||||
registry.add(new TvdotcomClient());
|
|
||||||
registry.add(new AnidbClient());
|
|
||||||
registry.add(new TVRageClient());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static List<EpisodeListClient> getAvailableEpisodeListClients() {
|
public static synchronized List<EpisodeListClient> getAvailableEpisodeListClients() {
|
||||||
|
if (registry == null) {
|
||||||
|
registry = new ArrayList<EpisodeListClient>(3);
|
||||||
|
|
||||||
|
registry.add(new TvdotcomClient());
|
||||||
|
registry.add(new AnidbClient());
|
||||||
|
registry.add(new TVRageClient());
|
||||||
|
}
|
||||||
|
|
||||||
return Collections.unmodifiableList(registry);
|
return Collections.unmodifiableList(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,33 +2,20 @@
|
|||||||
package net.sourceforge.filebot.web;
|
package net.sourceforge.filebot.web;
|
||||||
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
|
|
||||||
public class MovieDescriptor {
|
public class MovieDescriptor {
|
||||||
|
|
||||||
private final String title;
|
private final String title;
|
||||||
private final Integer imdbId;
|
private final Integer imdbId;
|
||||||
|
|
||||||
private final Integer year;
|
|
||||||
private final URL imdbUrl;
|
|
||||||
|
|
||||||
|
public MovieDescriptor(String title) {
|
||||||
public MovieDescriptor(String description) {
|
this(title, null);
|
||||||
this(description, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public MovieDescriptor(String description, Integer imdbId) {
|
public MovieDescriptor(String title, Integer imdbId) {
|
||||||
this(description, imdbId, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MovieDescriptor(String title, Integer imdbId, Integer year, URL imdbUrl) {
|
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.imdbId = imdbId;
|
this.imdbId = imdbId;
|
||||||
this.year = year;
|
|
||||||
this.imdbUrl = imdbUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -42,21 +29,9 @@ public class MovieDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Integer getYear() {
|
|
||||||
return year;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public URL getImdbUrl() {
|
|
||||||
return imdbUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (year == null)
|
return title;
|
||||||
return title;
|
|
||||||
|
|
||||||
return String.format("%s (%d)", title, year);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,9 @@ public class OpenSubtitlesClient {
|
|||||||
* </tr>
|
* </tr>
|
||||||
* </table>
|
* </table>
|
||||||
*/
|
*/
|
||||||
private String url = "http://www.opensubtitles.org/xml-rpc";
|
private final String url = "http://www.opensubtitles.org/xml-rpc";
|
||||||
|
|
||||||
private String useragent;
|
private final String useragent;
|
||||||
|
|
||||||
private String token = null;
|
private String token = null;
|
||||||
|
|
||||||
@ -57,6 +57,13 @@ public class OpenSubtitlesClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login as user and use english as language
|
||||||
|
*
|
||||||
|
* @param username
|
||||||
|
* @param password
|
||||||
|
* @throws XmlRpcFault
|
||||||
|
*/
|
||||||
public void login(String username, String password) throws XmlRpcFault {
|
public void login(String username, String password) throws XmlRpcFault {
|
||||||
login(username, password, "en");
|
login(username, password, "en");
|
||||||
}
|
}
|
||||||
@ -85,19 +92,20 @@ public class OpenSubtitlesClient {
|
|||||||
/**
|
/**
|
||||||
* This will logout user (ends session id). Good call this function is before ending
|
* This will logout user (ends session id). Good call this function is before ending
|
||||||
* (closing) clients program.
|
* (closing) clients program.
|
||||||
|
*
|
||||||
|
* @throws XmlRpcFault
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public synchronized void logout() {
|
public synchronized void logout() throws XmlRpcFault {
|
||||||
|
|
||||||
// anonymous users will always get a 401 Unauthorized when trying to logout
|
|
||||||
try {
|
try {
|
||||||
Map<String, String> response = (Map<String, String>) invoke("LogOut", token);
|
invoke("LogOut", token);
|
||||||
checkStatus(response.get("status"));
|
|
||||||
} catch (Exception e) {
|
// anonymous users will always get a 401 Unauthorized when trying to logout
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, "Exception while deactivating session", e);
|
// do not check status for logout response
|
||||||
|
// checkStatus(response.get("status"));
|
||||||
|
} finally {
|
||||||
|
token = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
token = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import net.sourceforge.filebot.resources.ResourceManager;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client for the OpenSubtitles XML-RPC API.
|
* {@link SubtitleClient} for OpenSubtitles.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
||||||
@ -32,7 +32,7 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<MovieDescriptor> search(String query) throws Exception {
|
public List<MovieDescriptor> search(String query) throws Exception {
|
||||||
activate();
|
login();
|
||||||
|
|
||||||
return client.searchMoviesOnIMDB(query);
|
return client.searchMoviesOnIMDB(query);
|
||||||
}
|
}
|
||||||
@ -40,39 +40,45 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<OpenSubtitlesSubtitleDescriptor> getSubtitleList(MovieDescriptor descriptor) throws Exception {
|
public List<OpenSubtitlesSubtitleDescriptor> getSubtitleList(MovieDescriptor descriptor) throws Exception {
|
||||||
activate();
|
login();
|
||||||
|
|
||||||
return client.searchSubtitles(descriptor.getImdbId());
|
return client.searchSubtitles(descriptor.getImdbId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private synchronized void activate() {
|
private synchronized void login() throws Exception {
|
||||||
try {
|
if (!client.isLoggedOn()) {
|
||||||
if (!client.isLoggedOn()) {
|
client.loginAnonymous();
|
||||||
client.loginAnonymous();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logoutTimer.restart();
|
logoutTimer.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized void logout() {
|
||||||
|
logoutTimer.stop();
|
||||||
|
|
||||||
|
if (client.isLoggedOn()) {
|
||||||
|
try {
|
||||||
|
client.logout();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, "Exception while deactivating session", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final Runnable doLogout = new Runnable() {
|
private final Runnable doLogout = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logoutTimer.stop();
|
logout();
|
||||||
|
|
||||||
if (client.isLoggedOn()) {
|
|
||||||
client.logout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private class LogoutTimer {
|
private class LogoutTimer {
|
||||||
|
|
||||||
private static final int LOGOUT_DELAY = 15000; // 12 minutes
|
private final long LOGOUT_DELAY = 12 * 60 * 1000; // 12 minutes
|
||||||
|
|
||||||
private Timer daemon = null;
|
private Timer daemon = null;
|
||||||
private LogoutTimerTask currentTimerTask = null;
|
private LogoutTimerTask currentTimerTask = null;
|
||||||
@ -85,7 +91,6 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
|||||||
|
|
||||||
if (currentTimerTask != null) {
|
if (currentTimerTask != null) {
|
||||||
currentTimerTask.cancel();
|
currentTimerTask.cancel();
|
||||||
daemon.purge();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTimerTask = new LogoutTimerTask();
|
currentTimerTask = new LogoutTimerTask();
|
||||||
@ -109,7 +114,7 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
doLogout.run();
|
logout();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import java.util.logging.Logger;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import net.sourceforge.filebot.FileFormat;
|
||||||
import net.sourceforge.filebot.resources.ResourceManager;
|
import net.sourceforge.filebot.resources.ResourceManager;
|
||||||
import net.sourceforge.tuned.XPathUtil;
|
import net.sourceforge.tuned.XPathUtil;
|
||||||
|
|
||||||
@ -71,8 +72,7 @@ public class SubsceneSubtitleClient extends SubtitleClient {
|
|||||||
|
|
||||||
Document dom = HtmlUtil.getHtmlDocument(url);
|
Document dom = HtmlUtil.getHtmlDocument(url);
|
||||||
|
|
||||||
String downloadPath = XPathUtil.selectString("id('aspnetForm')/@action", dom);
|
Pattern hrefPattern = Pattern.compile("javascript:Subtitle\\((\\d+), '(\\w+)', '0', '(\\d+)'\\);");
|
||||||
String viewstate = XPathUtil.selectString("id('__VIEWSTATE')/@value", dom);
|
|
||||||
|
|
||||||
List<Node> nodes = XPathUtil.selectNodes("//TABLE[@class='filmSubtitleList']//A[@id]//ancestor::TR", dom);
|
List<Node> nodes = XPathUtil.selectNodes("//TABLE[@class='filmSubtitleList']//A[@id]//ancestor::TR", dom);
|
||||||
|
|
||||||
@ -88,15 +88,20 @@ public class SubsceneSubtitleClient extends SubtitleClient {
|
|||||||
String name = XPathUtil.selectString("./SPAN[2]", linkNode);
|
String name = XPathUtil.selectString("./SPAN[2]", linkNode);
|
||||||
|
|
||||||
int numberOfCDs = Integer.parseInt(XPathUtil.selectString("./TD[2]", node));
|
int numberOfCDs = Integer.parseInt(XPathUtil.selectString("./TD[2]", node));
|
||||||
boolean hearingImpaired = XPathUtil.selectFirstNode("./TD[3]/*[@id='imgEar']", node) != null;
|
boolean hearingImpaired = (XPathUtil.selectFirstNode("./TD[3]/*[@id='imgEar']", node) != null);
|
||||||
String author = XPathUtil.selectString("./TD[4]", node);
|
String author = XPathUtil.selectString("./TD[4]", node);
|
||||||
|
|
||||||
URL downloadUrl = new URL("http", host, downloadPath);
|
Matcher matcher = hrefPattern.matcher(href);
|
||||||
|
|
||||||
Map<String, String> downloadParameters = parseParameters(href);
|
if (!matcher.matches())
|
||||||
downloadParameters.put("__VIEWSTATE", viewstate);
|
throw new IllegalArgumentException("Cannot extract download parameters: " + href);
|
||||||
|
|
||||||
list.add(new SubsceneSubtitleDescriptor(name, lang, numberOfCDs, author, hearingImpaired, downloadUrl, downloadParameters));
|
String subtitleId = matcher.group(1);
|
||||||
|
String typeId = matcher.group(2);
|
||||||
|
|
||||||
|
URL downloadUrl = getDownloadUrl(url, subtitleId, typeId);
|
||||||
|
|
||||||
|
list.add(new SubsceneSubtitleDescriptor(name, lang, numberOfCDs, author, hearingImpaired, typeId, downloadUrl, url));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.WARNING, "Cannot parse subtitle node", e);
|
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.WARNING, "Cannot parse subtitle node", e);
|
||||||
}
|
}
|
||||||
@ -106,19 +111,11 @@ public class SubsceneSubtitleClient extends SubtitleClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> parseParameters(String href) {
|
private URL getDownloadUrl(URL referer, String subtitleId, String typeId) throws MalformedURLException {
|
||||||
Matcher matcher = Pattern.compile("javascript:Subtitle\\((\\d+), '(\\w+)', '0', '(\\d+)'\\);").matcher(href);
|
String basePath = FileFormat.getNameWithoutExtension(referer.getFile());
|
||||||
|
String path = String.format("%s-dlpath-%s/%s.zipx", basePath, subtitleId, typeId);
|
||||||
|
|
||||||
if (!matcher.matches())
|
return new URL(referer.getProtocol(), referer.getHost(), path);
|
||||||
throw new IllegalArgumentException("Cannot extract download parameters: " + href);
|
|
||||||
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
|
||||||
|
|
||||||
map.put("subtitleId", matcher.group(1));
|
|
||||||
map.put("typeId", matcher.group(2));
|
|
||||||
map.put("filmId", matcher.group(3));
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package net.sourceforge.filebot.web;
|
|||||||
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.sourceforge.tuned.DownloadTask;
|
import net.sourceforge.tuned.DownloadTask;
|
||||||
|
|
||||||
@ -16,19 +15,23 @@ public class SubsceneSubtitleDescriptor implements SubtitleDescriptor {
|
|||||||
private final String author;
|
private final String author;
|
||||||
private final boolean hearingImpaired;
|
private final boolean hearingImpaired;
|
||||||
|
|
||||||
private final Map<String, String> downloadParameters;
|
private final String typeId;
|
||||||
|
|
||||||
private final URL downloadUrl;
|
private final URL downloadUrl;
|
||||||
|
private final URL referer;
|
||||||
|
|
||||||
|
|
||||||
public SubsceneSubtitleDescriptor(String title, String language, int numberOfCDs, String author, boolean hearingImpaired, URL downloadUrl, Map<String, String> downloadParameters) {
|
public SubsceneSubtitleDescriptor(String title, String language, int numberOfCDs, String author, boolean hearingImpaired, String typeId, URL downloadUrl, URL referer) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
this.numberOfCDs = numberOfCDs;
|
this.numberOfCDs = numberOfCDs;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
this.hearingImpaired = hearingImpaired;
|
this.hearingImpaired = hearingImpaired;
|
||||||
|
|
||||||
|
this.typeId = typeId;
|
||||||
|
|
||||||
this.downloadUrl = downloadUrl;
|
this.downloadUrl = downloadUrl;
|
||||||
this.downloadParameters = downloadParameters;
|
this.referer = referer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -60,13 +63,16 @@ public class SubsceneSubtitleDescriptor implements SubtitleDescriptor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DownloadTask createDownloadTask() {
|
public DownloadTask createDownloadTask() {
|
||||||
return new DownloadTask(downloadUrl, downloadParameters);
|
DownloadTask downloadTask = new DownloadTask(downloadUrl);
|
||||||
|
downloadTask.setRequestHeader("Referer", referer.toString());
|
||||||
|
|
||||||
|
return downloadTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getArchiveType() {
|
public String getArchiveType() {
|
||||||
return downloadParameters.get("typeId");
|
return typeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,15 +11,17 @@ import javax.swing.ImageIcon;
|
|||||||
|
|
||||||
public abstract class SubtitleClient {
|
public abstract class SubtitleClient {
|
||||||
|
|
||||||
private static final List<SubtitleClient> registry = new ArrayList<SubtitleClient>();
|
private static List<SubtitleClient> registry;
|
||||||
|
|
||||||
static {
|
|
||||||
registry.add(new OpenSubtitlesSubtitleClient());
|
|
||||||
registry.add(new SubsceneSubtitleClient());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static List<SubtitleClient> getAvailableSubtitleClients() {
|
public static synchronized List<SubtitleClient> getAvailableSubtitleClients() {
|
||||||
|
if (registry == null) {
|
||||||
|
registry = new ArrayList<SubtitleClient>(2);
|
||||||
|
|
||||||
|
registry.add(new OpenSubtitlesSubtitleClient());
|
||||||
|
registry.add(new SubsceneSubtitleClient());
|
||||||
|
}
|
||||||
|
|
||||||
return Collections.unmodifiableList(registry);
|
return Collections.unmodifiableList(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -20,7 +22,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
|
||||||
|
|
||||||
public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
|
||||||
|
|
||||||
public static final String DOWNLOAD_STATE = "download state";
|
public static final String DOWNLOAD_STATE = "download state";
|
||||||
public static final String DOWNLOAD_PROGRESS = "download progress";
|
public static final String DOWNLOAD_PROGRESS = "download progress";
|
||||||
@ -30,32 +32,44 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||||||
PENDING,
|
PENDING,
|
||||||
CONNECTING,
|
CONNECTING,
|
||||||
DOWNLOADING,
|
DOWNLOADING,
|
||||||
DONE;
|
DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 4 * 1024;
|
private final int BUFFER_SIZE = 4 * 1024;
|
||||||
|
|
||||||
private URL url;
|
private URL url;
|
||||||
private ByteBuffer postdata = null;
|
private ByteBuffer postdata;
|
||||||
|
|
||||||
private long size = -1;
|
private long size = -1;
|
||||||
private long bytesRead = 0;
|
private long bytesRead = 0;
|
||||||
private DownloadState state = DownloadState.PENDING;
|
private DownloadState state = DownloadState.PENDING;
|
||||||
|
|
||||||
|
private final Map<String, String> requestHeaders = new HashMap<String, String>();
|
||||||
|
private final Map<String, String> responseHeaders = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
public DownloadTask(URL url) {
|
public DownloadTask(URL url) {
|
||||||
this.url = url;
|
this(url, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DownloadTask(URL url, ByteBuffer postdata) {
|
public DownloadTask(URL url, Map<String, String> postParameters) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.postdata = postdata;
|
|
||||||
|
if (postParameters != null) {
|
||||||
|
this.postdata = encodeParameters(postParameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DownloadTask(URL url, Map<String, String> postdata) {
|
protected HttpURLConnection createConnection() throws Exception {
|
||||||
this(url, encodeParameters(postdata));
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
for (String key : requestHeaders.keySet()) {
|
||||||
|
connection.addRequestProperty(key, requestHeaders.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +77,7 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||||||
protected ByteBuffer doInBackground() throws Exception {
|
protected ByteBuffer doInBackground() throws Exception {
|
||||||
setDownloadState(DownloadState.CONNECTING);
|
setDownloadState(DownloadState.CONNECTING);
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = createConnection();
|
||||||
|
|
||||||
if (postdata != null) {
|
if (postdata != null) {
|
||||||
connection.setRequestMethod("POST");
|
connection.setRequestMethod("POST");
|
||||||
@ -75,31 +89,39 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||||||
|
|
||||||
size = connection.getContentLength();
|
size = connection.getContentLength();
|
||||||
|
|
||||||
|
for (String key : connection.getHeaderFields().keySet()) {
|
||||||
|
responseHeaders.put(key, connection.getHeaderField(key));
|
||||||
|
}
|
||||||
|
|
||||||
setDownloadState(DownloadState.DOWNLOADING);
|
setDownloadState(DownloadState.DOWNLOADING);
|
||||||
|
|
||||||
InputStream in = connection.getInputStream();
|
InputStream in = connection.getInputStream();
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
|
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max((int) size, BUFFER_SIZE));
|
||||||
|
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (((len = in.read(buffer)) > 0) && !isCancelled()) {
|
while (((len = in.read(buffer)) >= 0) && !isCancelled()) {
|
||||||
out.write(buffer, 0, len);
|
out.write(buffer, 0, len);
|
||||||
|
|
||||||
bytesRead += len;
|
bytesRead += len;
|
||||||
getPropertyChangeSupport().firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
|
|
||||||
|
firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
|
||||||
|
|
||||||
|
if (isDownloadSizeKnown()) {
|
||||||
|
setProgress((int) ((bytesRead * 100) / size));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// IOException (Premature EOF) is always thrown when the size of
|
// IOException (Premature EOF) is always thrown when the size of
|
||||||
// the response body is not known in advance, so we ignore it
|
// the response body is not known in advance, so we ignore it
|
||||||
if (isSizeKnown())
|
if (isDownloadSizeKnown())
|
||||||
throw e;
|
throw e;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
in.close();
|
in.close();
|
||||||
out.close();
|
out.close();
|
||||||
connection.disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setDownloadState(DownloadState.DONE);
|
setDownloadState(DownloadState.DONE);
|
||||||
@ -107,9 +129,9 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setDownloadState(DownloadState state) {
|
protected void setDownloadState(DownloadState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
getPropertyChangeSupport().firePropertyChange(DOWNLOAD_STATE, null, state);
|
firePropertyChange(DOWNLOAD_STATE, null, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -118,22 +140,37 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public URL getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getBytesRead() {
|
public long getBytesRead() {
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isSizeKnown() {
|
public boolean isDownloadSizeKnown() {
|
||||||
return size >= 0;
|
return size >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getSize() {
|
public long getDownloadSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static ByteBuffer encodeParameters(Map<String, String> parameters) {
|
public void setRequestHeader(String name, String value) {
|
||||||
|
requestHeaders.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getResponseHeaders() {
|
||||||
|
return Collections.unmodifiableMap(responseHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected static ByteBuffer encodeParameters(Map<String, String> parameters) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -42,8 +42,6 @@ public class TemporaryFolder {
|
|||||||
for (TemporaryFolder folder : folders.values()) {
|
for (TemporaryFolder folder : folders.values()) {
|
||||||
folder.delete();
|
folder.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
folders.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -57,6 +55,13 @@ public class TemporaryFolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty file in this temporary folder
|
||||||
|
*
|
||||||
|
* @param name name of the file
|
||||||
|
* @return newly created file
|
||||||
|
* @throws IOException if an I/O error occurred
|
||||||
|
*/
|
||||||
public File createFile(String name) throws IOException {
|
public File createFile(String name) throws IOException {
|
||||||
if (!root.exists()) {
|
if (!root.exists()) {
|
||||||
root.mkdir();
|
root.mkdir();
|
||||||
@ -69,15 +74,37 @@ public class TemporaryFolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deleteFile(String name) {
|
/**
|
||||||
File file = new File(root, name);
|
* Creates an empty file in this temporary folder, using the given prefix and suffix to
|
||||||
|
* generate its name.
|
||||||
if (file.exists()) {
|
*
|
||||||
file.delete();
|
* @param prefix The prefix string to be used in generating the file's name; must be at
|
||||||
|
* least three characters long
|
||||||
|
* @param suffix The suffix string to be used in generating the file's name; may be null,
|
||||||
|
* in which case the suffix ".tmp" will be used
|
||||||
|
* @return An abstract pathname denoting a newly-created empty file
|
||||||
|
* @throws IOException If a file could not be created
|
||||||
|
* @see File#createTempFile(String, String)
|
||||||
|
*/
|
||||||
|
public File createFile(String prefix, String suffix) throws IOException {
|
||||||
|
if (!root.exists()) {
|
||||||
|
root.mkdir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return File.createTempFile(prefix, suffix, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean deleteFile(String name) {
|
||||||
|
return new File(root, name).delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the {@link File} object for this {@link TemporaryFolder}
|
||||||
|
*
|
||||||
|
* @return the {@link File} object for this {@link TemporaryFolder}
|
||||||
|
*/
|
||||||
public File getFolder() {
|
public File getFolder() {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
|
|
||||||
package net.sourceforge.tuned;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
|
|
||||||
public class TimeIntervalFormat {
|
|
||||||
|
|
||||||
private static TreeMap<Long, String> unitMap = new TreeMap<Long, String>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
unitMap.put(1L, "ms");
|
|
||||||
unitMap.put(1000L, "s");
|
|
||||||
unitMap.put(60 * 1000L, "m");
|
|
||||||
unitMap.put(60 * 60 * 1000L, "h");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String format(long millis, boolean zerounits) {
|
|
||||||
boolean negativ = false;
|
|
||||||
|
|
||||||
if (millis < 0) {
|
|
||||||
millis = Math.abs(millis);
|
|
||||||
negativ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (long unitBaseTime : unitMap.descendingKeySet()) {
|
|
||||||
int quotient = (int) (millis / unitBaseTime);
|
|
||||||
|
|
||||||
boolean isLastKey = (unitBaseTime == unitMap.firstKey());
|
|
||||||
|
|
||||||
if (zerounits || (quotient != 0) || isLastKey) {
|
|
||||||
sb.append(quotient + unitMap.get(unitBaseTime));
|
|
||||||
|
|
||||||
if (!isLastKey)
|
|
||||||
;
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
millis -= quotient * unitBaseTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negativ)
|
|
||||||
sb.insert(0, "-");
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +1,10 @@
|
|||||||
|
|
||||||
package net.sourceforge.tuned.ui;
|
package net.sourceforge.tuned.ui;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@ -26,14 +30,15 @@ public class ProgressIndicator extends JComponent {
|
|||||||
private int indeterminateShapeCount = 1;
|
private int indeterminateShapeCount = 1;
|
||||||
|
|
||||||
private float progressStrokeWidth = 4.5f;
|
private float progressStrokeWidth = 4.5f;
|
||||||
private float remainingStrokeWidth = 2.5f;
|
private float remainingStrokeWidth = 2f;
|
||||||
|
|
||||||
private Stroke progressStroke = new BasicStroke(progressStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
|
private Stroke progressStroke = new BasicStroke(progressStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
|
||||||
private Stroke remainingStroke = new BasicStroke(remainingStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
|
private Stroke remainingStroke = new BasicStroke(remainingStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
|
||||||
|
|
||||||
private Color progressColor = Color.orange;
|
private Color progressColor = Color.orange;
|
||||||
private Color remainingColor = new Color(0f, 0f, 0f, 0.25f);
|
private Color remainingColor = new Color(0f, 0f, 0f, 0.25f);
|
||||||
private Color textColor = new Color(42, 42, 42);
|
|
||||||
|
private Color textColor = new Color(0x5F5F5F);
|
||||||
|
|
||||||
private boolean paintText = true;
|
private boolean paintText = true;
|
||||||
private boolean paintBackground = false;
|
private boolean paintBackground = false;
|
||||||
@ -42,6 +47,8 @@ public class ProgressIndicator extends JComponent {
|
|||||||
private final Arc2D arc = new Arc2D.Double();
|
private final Arc2D arc = new Arc2D.Double();
|
||||||
private final Ellipse2D circle = new Ellipse2D.Double();
|
private final Ellipse2D circle = new Ellipse2D.Double();
|
||||||
|
|
||||||
|
private final Dimension baseSize = new Dimension(32, 32);
|
||||||
|
|
||||||
|
|
||||||
public ProgressIndicator() {
|
public ProgressIndicator() {
|
||||||
this(null);
|
this(null);
|
||||||
@ -53,7 +60,7 @@ public class ProgressIndicator extends JComponent {
|
|||||||
|
|
||||||
indeterminate = (model == null);
|
indeterminate = (model == null);
|
||||||
|
|
||||||
setFont(new Font(Font.DIALOG, Font.PLAIN, 8));
|
setFont(new Font(Font.DIALOG, Font.BOLD, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -69,20 +76,25 @@ public class ProgressIndicator extends JComponent {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint(Graphics g) {
|
public void paintComponent(Graphics g) {
|
||||||
Graphics2D g2d = (Graphics2D) g;
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
|
double a = Math.min(getWidth(), getHeight());
|
||||||
|
|
||||||
|
g2d.scale(a / baseSize.width, a / baseSize.height);
|
||||||
|
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
if (paintBackground) {
|
if (paintBackground) {
|
||||||
frame.setFrame(0, 0, getWidth(), getHeight());
|
frame.setFrame(0, 0, baseSize.width, baseSize.height);
|
||||||
|
|
||||||
g2d.setPaint(getBackground());
|
g2d.setPaint(getBackground());
|
||||||
circle.setFrame(frame);
|
circle.setFrame(frame);
|
||||||
g2d.fill(circle);
|
g2d.fill(circle);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.setFrame(progressStrokeWidth, progressStrokeWidth, getWidth() - progressStrokeWidth * 2 - 1, getHeight() - progressStrokeWidth * 2 - 1);
|
double inset = Math.max(Math.max(remainingStrokeWidth, progressStrokeWidth), indeterminateRadius);
|
||||||
|
frame.setFrame(inset, inset, baseSize.width - inset * 2 - 1, baseSize.height - inset * 2 - 1);
|
||||||
|
|
||||||
if (!indeterminate) {
|
if (!indeterminate) {
|
||||||
paintProgress(g2d);
|
paintProgress(g2d);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
package net.sourceforge.tuned.ui;
|
package net.sourceforge.tuned.ui;
|
||||||
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
|
Loading…
Reference in New Issue
Block a user