Experiment with artwork thumbnail support

This commit is contained in:
Reinhard Pointner 2019-05-04 19:15:56 +07:00
parent 04d8e94a3c
commit bb686b5a27
3 changed files with 49 additions and 5 deletions

View File

@ -10,9 +10,11 @@ import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.prefs.Preferences;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
@ -38,15 +40,19 @@ public class SelectDialog<T> extends JDialog {
private JList<T> list;
private String command = null;
private Map<T, Icon> icons;
public SelectDialog(Component parent, Collection<? extends T> options) {
this(parent, options, false, false, null);
this(parent, options, null, false, false, null);
}
public SelectDialog(Component parent, Collection<? extends T> options, boolean autoRepeatEnabled, boolean autoRepeatSelected, JComponent header) {
public SelectDialog(Component parent, Collection<? extends T> options, Map<T, Icon> icons, boolean autoRepeatEnabled, boolean autoRepeatSelected, JComponent header) {
super(getWindow(parent), "Select", ModalityType.DOCUMENT_MODAL);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// enable icons
this.icons = icons;
// initialize list
list = new JList(options.toArray());
@ -110,6 +116,10 @@ public class SelectDialog<T> extends JDialog {
} else {
render.setToolTipText(null);
}
if (icons != null) {
render.setIcon(icons.get(value));
}
}
protected String getTooltipText(SearchResult item) {

View File

@ -18,6 +18,7 @@ import java.awt.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
@ -34,6 +35,8 @@ import java.util.prefs.Preferences;
import java.util.regex.Pattern;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import net.filebot.Cache;
@ -46,6 +49,8 @@ import net.filebot.web.Episode;
import net.filebot.web.EpisodeListProvider;
import net.filebot.web.SearchResult;
import net.filebot.web.SortOrder;
import net.filebot.web.TheTVDBClient;
import net.filebot.web.ThumbnailProvider;
class EpisodeListMatcher implements AutoCompleteMatcher {
@ -228,13 +233,16 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
return probableMatches.get(0);
}
// prepare thumbnail images
Map<SearchResult, Icon> thumbnails = getThumbnails(options);
// show selection dialog on EDT
Callable<SearchResult> showSelectDialog = () -> {
JLabel header = new JLabel(getQueryInputMessage("Failed to identify some of the following files:", null, getFilesForQuery(files, query)));
header.setBorder(createCompoundBorder(createTitledBorder(""), createEmptyBorder(3, 3, 3, 3)));
// multiple results have been found, user must select one
SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(parent, options, true, false, header.getText().isEmpty() ? null : header);
SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(parent, options, thumbnails, true, false, header.getText().isEmpty() ? null : header);
selectDialog.setTitle(provider.getName());
selectDialog.getMessageLabel().setText("<html>Select best match for \"<b>" + escapeHTML(query) + "</b>\":</html>");
selectDialog.getCancelAction().putValue(Action.NAME, "Skip");
@ -283,6 +291,28 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
}
}
protected Map<SearchResult, Icon> getThumbnails(List<SearchResult> options) {
if (provider instanceof TheTVDBClient) {
try {
int[] ids = options.stream().mapToInt(SearchResult::getId).toArray();
byte[][] thumbnails = ThumbnailProvider.TheTVDB.getThumbnails(ids);
Map<SearchResult, Icon> icons = new HashMap<>(ids.length);
for (int i = 0; i < ids.length; i++) {
if (thumbnails[i].length > 0) {
icons.put(options.get(i), new ImageIcon(thumbnails[i]));
}
}
if (icons.size() > 0) {
return icons;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
protected Collection<File> getFilesForQuery(Collection<File> files, String query) {
Pattern pattern = Pattern.compile(query.isEmpty() ? ".+" : normalizePunctuation(query).replaceAll("\\W+", ".+"), Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CHARACTER_CLASS);
List<File> selection = files.stream().filter(f -> find(f.getPath(), pattern)).collect(toList());

View File

@ -38,6 +38,7 @@ import java.util.logging.Level;
import java.util.prefs.Preferences;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JLabel;
import net.filebot.similarity.Match;
@ -337,6 +338,9 @@ class MovieMatcher implements AutoCompleteMatcher {
return null;
}
// prepare thumbnail images
Map<Movie, Icon> thumbnails = null;
// show selection dialog on EDT
Callable<Movie> showSelectDialog = () -> {
String query = fileQuery.length() >= 2 || folderQuery.length() <= 2 ? fileQuery : folderQuery;
@ -344,7 +348,7 @@ class MovieMatcher implements AutoCompleteMatcher {
header.setBorder(createCompoundBorder(createTitledBorder(""), createEmptyBorder(3, 3, 3, 3)));
// multiple results have been found, user must select one
SelectDialog<Movie> selectDialog = new SelectDialog<Movie>(parent, options, true, false, header);
SelectDialog<Movie> selectDialog = new SelectDialog<Movie>(parent, options, thumbnails, true, false, header);
selectDialog.setTitle(service.getName());
selectDialog.getMessageLabel().setText("<html>Select best match for \"<b>" + escapeHTML(query) + "</b>\":</html>");