* use String (language name) instead of Locale in all SubtitleProviders
* get languages (name, code) from xml file * implemented LanguageComboBox (model, renderer, persistence) * rename language icons * removed various prototype classes that will never be used
|
@ -26,8 +26,8 @@
|
|||
<manifest>
|
||||
<attribute name="Built-By" value="${user.name}" />
|
||||
<attribute name="Built-Date" value="${today}" />
|
||||
<attribute name="Implementation-Title" value="${title}" />
|
||||
<attribute name="Implementation-Version" value="${version}" />
|
||||
<attribute name="Application-Name" value="${title}" />
|
||||
<attribute name="Application-Version" value="${version}" />
|
||||
<attribute name="Class-Path" value="args4j.jar miglayout.jar glazedlists.jar nekohtml.jar xercesImpl.jar ehcache.jar simmetrics.jar xmlrpc-client.jar" />
|
||||
<attribute name="Main-Class" value="net.sourceforge.filebot.Main" />
|
||||
</manifest>
|
||||
|
|
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 551 B |
Before Width: | Height: | Size: 526 B |
After Width: | Height: | Size: 503 B |
Before Width: | Height: | Size: 594 B |
Before Width: | Height: | Size: 616 B |
Before Width: | Height: | Size: 517 B |
After Width: | Height: | Size: 571 B |
After Width: | Height: | Size: 479 B |
After Width: | Height: | Size: 386 B |
|
@ -2,29 +2,35 @@
|
|||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import net.sourceforge.filebot.ResourceManager;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
|
||||
class Language implements Comparable<Language> {
|
||||
class Language {
|
||||
|
||||
private final String name;
|
||||
private final Locale locale;
|
||||
@XmlAttribute(name = "name")
|
||||
private String name;
|
||||
|
||||
private final String code;
|
||||
private final Icon icon;
|
||||
@XmlAttribute(name = "code")
|
||||
private String code;
|
||||
|
||||
|
||||
public Language(String languageName) {
|
||||
this.name = languageName;
|
||||
this.locale = LanguageResolver.getDefault().getLocale(name);
|
||||
|
||||
this.code = (locale != null ? locale.getLanguage() : null);
|
||||
|
||||
this.icon = ResourceManager.getFlagIcon(code);
|
||||
protected Language() {
|
||||
// used by JAXB
|
||||
}
|
||||
|
||||
|
||||
public Language(String name, String code) {
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,37 +44,62 @@ class Language implements Comparable<Language> {
|
|||
}
|
||||
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
|
||||
public Icon getIcon() {
|
||||
return icon;
|
||||
@Override
|
||||
public Language clone() {
|
||||
return new Language(name, code);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
public static Language getLanguage(String languageCode) {
|
||||
for (Language language : Languages.getInstance().elements()) {
|
||||
if (language.getCode().equalsIgnoreCase(languageCode))
|
||||
return language;
|
||||
}
|
||||
|
||||
if (obj instanceof Language)
|
||||
return getName().equalsIgnoreCase(((Language) obj).getName());
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Language language) {
|
||||
return getName().compareToIgnoreCase(language.getName());
|
||||
public static List<Language> availableLanguages() {
|
||||
return Collections.unmodifiableList(Arrays.asList(Languages.getInstance().elements()));
|
||||
}
|
||||
|
||||
|
||||
@XmlRootElement(name = "languages")
|
||||
private static class Languages {
|
||||
|
||||
@XmlElement(name = "language")
|
||||
private Language[] elements;
|
||||
|
||||
// keep singleton instance of all available languages
|
||||
private static Languages instance;
|
||||
|
||||
|
||||
public static Languages getInstance() {
|
||||
if (instance == null) {
|
||||
try {
|
||||
Unmarshaller unmarshaller = JAXBContext.newInstance(Languages.class).createUnmarshaller();
|
||||
|
||||
// load languages from xml files
|
||||
return (Languages) unmarshaller.unmarshal(Language.class.getResource("languages.xml"));
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public Language[] elements() {
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import ca.odell.glazedlists.matchers.Matcher;
|
||||
|
||||
|
||||
class LanguageMatcher implements Matcher<SubtitlePackage> {
|
||||
|
||||
private final Set<Language> languages;
|
||||
|
||||
|
||||
public LanguageMatcher(Collection<Language> languages) {
|
||||
this.languages = new TreeSet<Language>(languages);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(SubtitlePackage item) {
|
||||
return languages.contains(item.getLanguage());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
public class LanguageResolver {
|
||||
|
||||
private static final LanguageResolver defaultInstance = new LanguageResolver();
|
||||
|
||||
|
||||
public static LanguageResolver getDefault() {
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
private final ConcurrentMap<String, Locale> cache = new ConcurrentHashMap<String, Locale>();
|
||||
|
||||
|
||||
/**
|
||||
* Get the {@link Locale} for a given language name (e.g. "german").
|
||||
*
|
||||
* @param languageName english name of the language
|
||||
* @return the locale for this language or null if no locale for this language exists
|
||||
*/
|
||||
public Locale getLocale(String languageName) {
|
||||
// case insensitive
|
||||
String key = languageName.toLowerCase();
|
||||
|
||||
Locale locale = cache.get(key);
|
||||
|
||||
if (locale == null) {
|
||||
locale = findLocale(languageName);
|
||||
cache.put(key, locale);
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the ISO 639 language code for a language.
|
||||
*
|
||||
* @param languageName english name of the language
|
||||
* @return lowercase ISO 639 language code
|
||||
* @see Locale#getLanguage()
|
||||
*/
|
||||
public String getLanguageCode(String languageName) {
|
||||
Locale locale = getLocale(languageName);
|
||||
|
||||
if (locale != null)
|
||||
return locale.getLanguage();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the {@link Locale} for a given language name.
|
||||
*
|
||||
* @param languageName language name
|
||||
* @return {@link Locale} for the given language, or null if no matching {@link Locale} is
|
||||
* available
|
||||
*/
|
||||
protected Locale findLocale(String languageName) {
|
||||
for (Locale locale : Locale.getAvailableLocales()) {
|
||||
if (locale.getDisplayLanguage(Locale.ENGLISH).equalsIgnoreCase(languageName))
|
||||
return locale;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.FilteredImageSource;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import net.sourceforge.tuned.ui.ColorTintImageFilter;
|
||||
import net.sourceforge.tuned.ui.IconViewCellRenderer;
|
||||
import net.sourceforge.tuned.ui.TunedUtilities;
|
||||
|
||||
|
||||
public class SubtitleCellRenderer extends IconViewCellRenderer {
|
||||
|
||||
//TODO rename info to e.g. language
|
||||
private final JLabel info1 = new JLabel();
|
||||
private final JLabel info2 = new JLabel();
|
||||
|
||||
private Color infoForegroundDeselected = new Color(0x808080);
|
||||
|
||||
// TODO gscheid machn
|
||||
private Icon icon;
|
||||
|
||||
|
||||
public SubtitleCellRenderer() {
|
||||
info1.setBorder(null);
|
||||
info2.setBorder(null);
|
||||
|
||||
info1.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
|
||||
getContentPane().add(info1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
SubtitlePackage subtitle = (SubtitlePackage) value;
|
||||
|
||||
setText(subtitle.getName());
|
||||
|
||||
info1.setText(subtitle.getLanguage().getName());
|
||||
|
||||
icon = subtitle.getLanguage().getIcon();
|
||||
|
||||
info1.setIcon(icon);
|
||||
|
||||
Icon icon = subtitle.getArchiveIcon();
|
||||
|
||||
if (isSelected) {
|
||||
setIcon(new ImageIcon(createImage(new FilteredImageSource(TunedUtilities.getImage(icon).getSource(), new ColorTintImageFilter(list.getSelectionBackground(), 0.5f)))));
|
||||
|
||||
info1.setForeground(list.getSelectionForeground());
|
||||
info2.setForeground(list.getSelectionForeground());
|
||||
} else {
|
||||
setIcon(icon);
|
||||
|
||||
info1.setForeground(infoForegroundDeselected);
|
||||
info2.setForeground(infoForegroundDeselected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
//TODO gscheid machn
|
||||
g.translate(36, 43);
|
||||
// icon.paintIcon(this, g, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
|
||||
public class SubtitleDownloadPanel extends JComponent {
|
||||
|
||||
private final SubtitlePackagePanel packagePanel = new SubtitlePackagePanel();
|
||||
|
||||
|
||||
public SubtitleDownloadPanel() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(packagePanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
|
||||
public SubtitlePackagePanel getPackagePanel() {
|
||||
return packagePanel;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,15 +17,12 @@ public class SubtitlePackage {
|
|||
|
||||
private final Icon archiveIcon;
|
||||
|
||||
private final Language language;
|
||||
|
||||
private final DownloadTask downloadTask;
|
||||
|
||||
|
||||
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
|
||||
this.subtitleDescriptor = subtitleDescriptor;
|
||||
|
||||
language = new Language(subtitleDescriptor.getLanguageName());
|
||||
downloadTask = subtitleDescriptor.createDownloadTask();
|
||||
|
||||
archiveType = ArchiveType.forName(subtitleDescriptor.getArchiveType());
|
||||
|
@ -43,8 +40,8 @@ public class SubtitlePackage {
|
|||
}
|
||||
|
||||
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
public String getLanguageName() {
|
||||
return subtitleDescriptor.getLanguageName();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
|
||||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||
import net.sourceforge.tuned.DownloadTask;
|
||||
import ca.odell.glazedlists.BasicEventList;
|
||||
import ca.odell.glazedlists.EventList;
|
||||
import ca.odell.glazedlists.ObservableElementList;
|
||||
import ca.odell.glazedlists.swing.EventListModel;
|
||||
|
||||
|
||||
public class SubtitlePackagePanel extends JComponent {
|
||||
|
||||
private final EventList<SubtitlePackage> model = new BasicEventList<SubtitlePackage>();
|
||||
|
||||
|
||||
public SubtitlePackagePanel() {
|
||||
setLayout(new BorderLayout());
|
||||
add(createList(), BorderLayout.CENTER);
|
||||
model.add(new SubtitlePackage(new SubtitleDescriptor() {
|
||||
|
||||
@Override
|
||||
public DownloadTask createDownloadTask() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getArchiveType() {
|
||||
return ArchiveType.ZIP.getExtension();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getLanguageName() {
|
||||
return "english";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Firefly 1x01 The Train Job.srt";
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public EventList<SubtitlePackage> getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
protected JComponent createList() {
|
||||
ObservableElementList<SubtitlePackage> observableList = new ObservableElementList<SubtitlePackage>(model, new SubtitlePackageConnector());
|
||||
|
||||
JList list = new JList(new EventListModel<SubtitlePackage>(observableList));
|
||||
|
||||
list.setCellRenderer(new SubtitleCellRenderer());
|
||||
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
|
||||
list.setVisibleRowCount(-1);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static class SubtitlePackageConnector implements ObservableElementList.Connector<SubtitlePackage> {
|
||||
|
||||
/**
|
||||
* The list which contains the elements being observed via this {@link ObservableElementList.Connector}.
|
||||
*/
|
||||
private ObservableElementList<SubtitlePackage> list = null;
|
||||
|
||||
|
||||
public EventListener installListener(final SubtitlePackage element) {
|
||||
PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
list.elementChanged(element);
|
||||
}
|
||||
};
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
|
||||
public void uninstallListener(SubtitlePackage element, EventListener listener) {
|
||||
element.getDownloadTask().removePropertyChangeListener((PropertyChangeListener) listener);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setObservableElementList(ObservableElementList<? extends SubtitlePackage> list) {
|
||||
this.list = (ObservableElementList<SubtitlePackage>) list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,18 @@ package net.sourceforge.filebot.ui.panel.subtitle;
|
|||
|
||||
|
||||
import static net.sourceforge.filebot.Settings.*;
|
||||
import static net.sourceforge.filebot.ui.panel.subtitle.LanguageComboBoxModel.*;
|
||||
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
import net.sourceforge.filebot.Settings;
|
||||
import net.sourceforge.filebot.ui.AbstractSearchPanel;
|
||||
|
@ -21,15 +25,57 @@ import net.sourceforge.filebot.web.SubsceneSubtitleClient;
|
|||
import net.sourceforge.filebot.web.SubtitleDescriptor;
|
||||
import net.sourceforge.filebot.web.SubtitleProvider;
|
||||
import net.sourceforge.filebot.web.SubtitleSourceClient;
|
||||
import net.sourceforge.tuned.PreferencesMap.AbstractAdapter;
|
||||
import net.sourceforge.tuned.PreferencesMap.PreferencesEntry;
|
||||
import net.sourceforge.tuned.ui.LabelProvider;
|
||||
import net.sourceforge.tuned.ui.SimpleLabelProvider;
|
||||
|
||||
|
||||
public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, SubtitlePackage> {
|
||||
|
||||
private final LanguageComboBoxModel languageModel = new LanguageComboBoxModel();
|
||||
|
||||
|
||||
public SubtitlePanel() {
|
||||
historyPanel.setColumnHeader(0, "Show / Movie");
|
||||
historyPanel.setColumnHeader(1, "Number of Subtitles");
|
||||
|
||||
JComboBox languageComboBox = new JComboBox(languageModel);
|
||||
|
||||
languageComboBox.setRenderer(new LanguageComboBoxCellRenderer());
|
||||
|
||||
// restore state
|
||||
languageModel.setSelectedItem(persistentSelectedLanguage.getValue());
|
||||
languageModel.favorites().addAll(persistentFavorites.getValue());
|
||||
|
||||
// guess favorite languages
|
||||
if (languageModel.favorites().isEmpty()) {
|
||||
for (Locale locale : new Locale[] { Locale.getDefault(), Locale.ENGLISH }) {
|
||||
Language language = Language.getLanguage(locale.getLanguage());
|
||||
|
||||
if (language != null) {
|
||||
languageModel.favorites().add(language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update favorites on change
|
||||
languageComboBox.addPopupMenuListener(new PopupSelectionListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
Language language = (Language) e.getItem();
|
||||
|
||||
if (languageModel.favorites().add(language)) {
|
||||
persistentFavorites.setValue(languageModel.favorites());
|
||||
}
|
||||
|
||||
persistentSelectedLanguage.setValue(language);
|
||||
}
|
||||
});
|
||||
|
||||
// add after text field
|
||||
add(languageComboBox, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,24 +107,26 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
protected SubtitleRequestProcessor createRequestProcessor() {
|
||||
SubtitleProvider provider = searchTextField.getSelectButton().getSelectedValue();
|
||||
String text = searchTextField.getText().trim();
|
||||
Language language = languageModel.getSelectedItem();
|
||||
|
||||
//TODO language selection combobox
|
||||
Locale language = Locale.ENGLISH;
|
||||
// null or proper language name
|
||||
String languageName = (language == ALL_LANGUAGES ? null : language.getName());
|
||||
|
||||
return new SubtitleRequestProcessor(new SubtitleRequest(provider, text, language));
|
||||
return new SubtitleRequestProcessor(new SubtitleRequest(provider, text, languageName));
|
||||
}
|
||||
|
||||
|
||||
protected static class SubtitleRequest extends Request {
|
||||
|
||||
private final SubtitleProvider provider;
|
||||
private final Locale language;
|
||||
private final String languageName;
|
||||
|
||||
|
||||
public SubtitleRequest(SubtitleProvider provider, String searchText, Locale language) {
|
||||
public SubtitleRequest(SubtitleProvider provider, String searchText, String languageName) {
|
||||
super(searchText);
|
||||
|
||||
this.provider = provider;
|
||||
this.language = language;
|
||||
this.languageName = languageName;
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,8 +135,8 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
}
|
||||
|
||||
|
||||
public Locale getLanguage() {
|
||||
return language;
|
||||
public String getLanguageName() {
|
||||
return languageName;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -97,7 +145,7 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
protected static class SubtitleRequestProcessor extends RequestProcessor<SubtitleRequest, SubtitlePackage> {
|
||||
|
||||
public SubtitleRequestProcessor(SubtitleRequest request) {
|
||||
super(request, new SubtitleDownloadPanel());
|
||||
super(request, new SubtitleListComponent());
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,9 +157,9 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
|
||||
@Override
|
||||
public Collection<SubtitlePackage> fetch() throws Exception {
|
||||
List<SubtitlePackage> packages = new ArrayList<SubtitlePackage>(20);
|
||||
List<SubtitlePackage> packages = new ArrayList<SubtitlePackage>();
|
||||
|
||||
for (SubtitleDescriptor subtitle : request.getProvider().getSubtitleList(getSearchResult(), request.getLanguage())) {
|
||||
for (SubtitleDescriptor subtitle : request.getProvider().getSubtitleList(getSearchResult(), request.getLanguageName())) {
|
||||
packages.add(new SubtitlePackage(subtitle));
|
||||
}
|
||||
|
||||
|
@ -121,19 +169,20 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
|
||||
@Override
|
||||
public URI getLink() {
|
||||
return request.getProvider().getSubtitleListLink(getSearchResult(), request.getLanguage());
|
||||
return request.getProvider().getSubtitleListLink(getSearchResult(), request.getLanguageName());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void process(Collection<SubtitlePackage> subtitles) {
|
||||
getComponent().getPackagePanel().getModel().addAll(subtitles);
|
||||
getComponent().setLanguageVisible(request.getLanguageName() == null);
|
||||
getComponent().getModel().addAll(subtitles);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SubtitleDownloadPanel getComponent() {
|
||||
return (SubtitleDownloadPanel) super.getComponent();
|
||||
public SubtitleListComponent getComponent() {
|
||||
return (SubtitleListComponent) super.getComponent();
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,4 +206,48 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
|
||||
}
|
||||
|
||||
private final PreferencesEntry<Language> persistentSelectedLanguage = getSettings().entry("language.selected", new AbstractAdapter<Language>() {
|
||||
|
||||
@Override
|
||||
public Language get(Preferences prefs, String key) {
|
||||
return Language.getLanguage(prefs.get(key, ""));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void put(Preferences prefs, String key, Language value) {
|
||||
prefs.put(key, value == null ? "undefined" : value.getCode());
|
||||
}
|
||||
});
|
||||
|
||||
private final PreferencesEntry<List<Language>> persistentFavorites = getSettings().entry("language.favorites", new AbstractAdapter<List<Language>>() {
|
||||
|
||||
@Override
|
||||
public List<Language> get(Preferences prefs, String key) {
|
||||
List<Language> languages = new ArrayList<Language>();
|
||||
|
||||
for (String languageCode : prefs.get(key, "").split("\\W+")) {
|
||||
languages.add(Language.getLanguage(languageCode));
|
||||
}
|
||||
|
||||
return languages;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void put(Preferences prefs, String key, List<Language> languages) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < languages.size(); i++) {
|
||||
sb.append(languages.get(i).getCode());
|
||||
|
||||
if (i < languages.size() - 1) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
prefs.put(key, sb.toString());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class Unrar {
|
||||
|
||||
private static final Command command = getCommand();
|
||||
|
||||
private static final int timeout = 5000;
|
||||
private static final int sleepInterval = 50;
|
||||
|
||||
|
||||
public static void extractFiles(File archiveFile, File destinationFolder) throws Exception {
|
||||
if (command == null) {
|
||||
throw new IllegalStateException("Unrar could not be initialized");
|
||||
}
|
||||
|
||||
Process process = command.execute(archiveFile, destinationFolder);
|
||||
|
||||
int counter = 0;
|
||||
|
||||
while (isRunning(process)) {
|
||||
Thread.sleep(sleepInterval);
|
||||
counter += sleepInterval;
|
||||
|
||||
if (counter > timeout) {
|
||||
process.destroy();
|
||||
throw new TimeoutException(String.format("%s timed out", command.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
if (process.exitValue() != 0) {
|
||||
throw new Exception(String.format("%s returned with exit value %d", command.getName(), process.exitValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean isRunning(Process process) {
|
||||
try {
|
||||
// will throw exception if process is still running
|
||||
process.exitValue();
|
||||
|
||||
// process has terminated
|
||||
return false;
|
||||
} catch (IllegalThreadStateException e) {
|
||||
// process is still running
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Command getCommand() {
|
||||
try {
|
||||
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
File programFiles = new File(System.getenv("PROGRAMFILES"));
|
||||
|
||||
for (File folder : programFiles.listFiles(FOLDERS_ONLY)) {
|
||||
String name = folder.getName().toLowerCase();
|
||||
|
||||
if (name.contains("rar") || name.contains("zip")) {
|
||||
for (File file : folder.listFiles(FILES_ONLY)) {
|
||||
String filename = file.getName();
|
||||
|
||||
if (filename.equalsIgnoreCase("unrar.exe") || filename.equalsIgnoreCase("7z.exe")) {
|
||||
return new Command(filename, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("External program not found");
|
||||
} else {
|
||||
// linux, bsd, mac, ...
|
||||
String command = "unrar";
|
||||
|
||||
// will throw an exception if command cannot be executed
|
||||
Runtime.getRuntime().exec(command);
|
||||
|
||||
return new Command(command);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.getLogger(Unrar.class.getName()).log(Level.WARNING, "Cannot initialize unrar facility: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static class Command {
|
||||
|
||||
private final String name;
|
||||
private final String executable;
|
||||
|
||||
|
||||
public Command(String command) {
|
||||
this.name = command;
|
||||
this.executable = command;
|
||||
}
|
||||
|
||||
|
||||
public Command(String name, File executable) {
|
||||
this.name = name;
|
||||
this.executable = executable.getAbsolutePath();
|
||||
}
|
||||
|
||||
|
||||
public Process execute(File archive, File workingDirectory) throws IOException {
|
||||
ProcessBuilder builder = new ProcessBuilder(executable, "x", "-y", archive.getAbsolutePath());
|
||||
builder.directory(workingDirectory);
|
||||
|
||||
Process process = builder.start();
|
||||
|
||||
// if output stream is open, but not read, the subprocess may block due to limited buffer size,
|
||||
// so we close all streams just in case
|
||||
process.getInputStream().close();
|
||||
process.getOutputStream().close();
|
||||
process.getErrorStream().close();
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final FileFilter FOLDERS_ONLY = new FileFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
return file.isDirectory();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static final FileFilter FILES_ONLY = new FileFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
return file.isFile();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -12,7 +12,6 @@ import java.net.URL;
|
|||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -99,7 +98,7 @@ public class AnidbClient implements EpisodeListProvider {
|
|||
|
||||
protected String selectTitle(Document animePage) {
|
||||
// prefer official english title
|
||||
String title = selectOfficialTitle(animePage, Locale.ENGLISH);
|
||||
String title = selectOfficialTitle(animePage, "english");
|
||||
|
||||
if (title.isEmpty()) {
|
||||
// fallback: extract name from header (e.g. "Anime: Naruto")
|
||||
|
@ -110,11 +109,11 @@ public class AnidbClient implements EpisodeListProvider {
|
|||
}
|
||||
|
||||
|
||||
protected String selectOfficialTitle(Document animePage, Locale language) {
|
||||
protected String selectOfficialTitle(Document animePage, String languageName) {
|
||||
// create xpath query for official title of the given language
|
||||
// e.g. //*[@class='data']//*[contains(@class, 'official') and .//*[contains(@title, 'english')]]//LABEL
|
||||
|
||||
String condition = String.format(".//*[contains(@title, '%s')]", language.getDisplayLanguage(Locale.ENGLISH).toLowerCase());
|
||||
String condition = String.format(".//*[contains(@title, '%s')]", languageName.toLowerCase());
|
||||
String xpath = String.format("//*[@class='data']//*[contains(@class, 'official') and %s]//LABEL", condition);
|
||||
|
||||
return selectString(xpath, animePage);
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -141,14 +140,14 @@ public class OpenSubtitlesClient {
|
|||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(int imdbid, Locale language) throws XmlRpcFault {
|
||||
public List<OpenSubtitlesSubtitleDescriptor> searchSubtitles(int imdbid, String languageName) throws XmlRpcFault {
|
||||
|
||||
Map<String, String> searchListEntry = new HashMap<String, String>(2);
|
||||
|
||||
// pad imdbId with zeros
|
||||
//TODO needed???
|
||||
searchListEntry.put("imdbid", String.format("%07d", imdbid));
|
||||
searchListEntry.put("sublanguageid", getSubLanguageID(language));
|
||||
searchListEntry.put("sublanguageid", getSubLanguageID(languageName));
|
||||
|
||||
List<Map<String, String>> searchList = Collections.singletonList(searchListEntry);
|
||||
|
||||
|
@ -169,9 +168,9 @@ public class OpenSubtitlesClient {
|
|||
}
|
||||
|
||||
|
||||
private String getSubLanguageID(Locale locale) {
|
||||
private String getSubLanguageID(String languageName) {
|
||||
//TODO test if sublanguageid is really ISO3 language code
|
||||
return locale.getISO3Language();
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ package net.sourceforge.filebot.web;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -51,15 +50,15 @@ public class OpenSubtitlesSubtitleClient implements SubtitleProvider {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, Locale language) throws Exception {
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception {
|
||||
login();
|
||||
|
||||
return (List) client.searchSubtitles(((MovieDescriptor) searchResult).getImdbId(), language);
|
||||
return (List) client.searchSubtitles(((MovieDescriptor) searchResult).getImdbId(), languageName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URI getSubtitleListLink(SearchResult searchResult, Locale language) {
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
|
||||
//TODO provide link
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.net.URLEncoder;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -96,11 +95,9 @@ public class SubsceneSubtitleClient implements SubtitleProvider {
|
|||
|
||||
|
||||
@Override
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, Locale language) throws Exception {
|
||||
URL subtitleListUrl = getSubtitleListLink(searchResult, language).toURL();
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception {
|
||||
URL subtitleListUrl = getSubtitleListLink(searchResult, languageName).toURL();
|
||||
|
||||
// english language name or null
|
||||
String languageName = (language == null || language.equals(Locale.ROOT) ? null : language.getDisplayLanguage(Locale.ENGLISH));
|
||||
Integer languageFilter = null;
|
||||
|
||||
if (languageName != null) {
|
||||
|
@ -206,7 +203,7 @@ public class SubsceneSubtitleClient implements SubtitleProvider {
|
|||
|
||||
|
||||
@Override
|
||||
public URI getSubtitleListLink(SearchResult searchResult, Locale locale) {
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
|
||||
return ((HyperLink) searchResult).toURI();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ package net.sourceforge.filebot.web;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
|
@ -14,10 +13,10 @@ public interface SubtitleProvider {
|
|||
public List<SearchResult> search(String query) throws Exception;
|
||||
|
||||
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, Locale language) throws Exception;
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception;
|
||||
|
||||
|
||||
public URI getSubtitleListLink(SearchResult searchResult, Locale language);
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName);
|
||||
|
||||
|
||||
public String getName();
|
||||
|
|
|
@ -6,13 +6,11 @@ import static net.sourceforge.filebot.web.WebRequest.*;
|
|||
import static net.sourceforge.tuned.XPathUtilities.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
@ -71,14 +69,11 @@ public class SubtitleSourceClient implements SubtitleProvider {
|
|||
|
||||
|
||||
@Override
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, Locale language) throws Exception {
|
||||
// english language name or null
|
||||
String languageFilter = (language == null || language == Locale.ROOT) ? null : language.getDisplayLanguage(Locale.ENGLISH);
|
||||
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception {
|
||||
List<SubtitleDescriptor> subtitles = new ArrayList<SubtitleDescriptor>();
|
||||
|
||||
for (SubtitleDescriptor subtitle : getSubtitleList(searchResult)) {
|
||||
if (languageFilter == null || languageFilter.equalsIgnoreCase(subtitle.getLanguageName())) {
|
||||
if (languageName == null || languageName.equalsIgnoreCase(subtitle.getLanguageName())) {
|
||||
subtitles.add(subtitle);
|
||||
}
|
||||
}
|
||||
|
@ -133,14 +128,10 @@ public class SubtitleSourceClient implements SubtitleProvider {
|
|||
|
||||
|
||||
@Override
|
||||
public URI getSubtitleListLink(SearchResult searchResult, Locale language) {
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName) {
|
||||
int imdb = ((MovieDescriptor) searchResult).getImdbId();
|
||||
|
||||
try {
|
||||
return new URI("http://" + host + "/title/" + String.format("tt%07d", imdb));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return URI.create("http://" + host + "/title/" + String.format("tt%07d", imdb));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,11 +44,6 @@ public final class XPathUtilities {
|
|||
}
|
||||
|
||||
|
||||
public static boolean exists(String xpath, Object node) {
|
||||
return selectNode(xpath, node) != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nodeName search for nodes with this name
|
||||
* @param parentNode search in the child nodes of this nodes
|
||||
|
|
|
@ -7,7 +7,6 @@ import static org.junit.Assert.*;
|
|||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
@ -135,7 +134,7 @@ public class AnidbClientTest {
|
|||
|
||||
@Test
|
||||
public void selectJapaneseTitle() throws Exception {
|
||||
assertEquals("十二国記", anidb.selectOfficialTitle(getHtmlDocument(twelvekingdomsSearchResult.getURL()), Locale.JAPANESE));
|
||||
assertEquals("十二国記", anidb.selectOfficialTitle(getHtmlDocument(twelvekingdomsSearchResult.getURL()), "Japanese"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,11 +6,8 @@ import static org.junit.Assert.*;
|
|||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.filebot.ui.panel.subtitle.LanguageResolver;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -63,7 +60,7 @@ public class SubsceneSubtitleClientTest {
|
|||
|
||||
@Test
|
||||
public void getSubtitleListSearchResult() throws Exception {
|
||||
List<SubtitleDescriptor> subtitleList = subscene.getSubtitleList(twinpeaksSearchResult, Locale.ITALIAN);
|
||||
List<SubtitleDescriptor> subtitleList = subscene.getSubtitleList(twinpeaksSearchResult, "Italian");
|
||||
|
||||
assertEquals(1, subtitleList.size());
|
||||
|
||||
|
@ -77,7 +74,7 @@ public class SubsceneSubtitleClientTest {
|
|||
|
||||
@Test
|
||||
public void getSubtitleListSearchResultMany() throws Exception {
|
||||
List<SubtitleDescriptor> subtitleList = subscene.getSubtitleList(lostSearchResult, LanguageResolver.getDefault().getLocale("Japanese"));
|
||||
List<SubtitleDescriptor> subtitleList = subscene.getSubtitleList(lostSearchResult, "Japanese");
|
||||
|
||||
// lots of subtitles, but only a few Japanese ones
|
||||
assertEquals(16, subtitleList.size());
|
||||
|
|
|
@ -5,7 +5,6 @@ package net.sourceforge.filebot.web;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -32,7 +31,7 @@ public class SubtitleSourceClientTest {
|
|||
|
||||
@Test
|
||||
public void getSubtitleListAll() throws Exception {
|
||||
List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Buffy", 118276), Locale.ENGLISH);
|
||||
List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Buffy", 118276), "English");
|
||||
|
||||
SubtitleDescriptor sample = list.get(0);
|
||||
|
||||
|
|