diff --git a/source/net/sourceforge/filebot/cli/CmdlineOperations.java b/source/net/sourceforge/filebot/cli/CmdlineOperations.java index f55613e9..b8731622 100644 --- a/source/net/sourceforge/filebot/cli/CmdlineOperations.java +++ b/source/net/sourceforge/filebot/cli/CmdlineOperations.java @@ -46,7 +46,6 @@ import net.sourceforge.filebot.hash.VerificationFileWriter; import net.sourceforge.filebot.similarity.EpisodeMetrics; import net.sourceforge.filebot.similarity.Match; import net.sourceforge.filebot.similarity.Matcher; -import net.sourceforge.filebot.similarity.MetricCascade; import net.sourceforge.filebot.similarity.NameSimilarityMetric; import net.sourceforge.filebot.similarity.SeriesNameMatcher; import net.sourceforge.filebot.similarity.SimilarityMetric; @@ -384,7 +383,7 @@ public class CmdlineOperations implements CmdlineInterface { try { CLILogger.fine("Looking up subtitles by filehash via " + service.getName()); collector.addAll(service.getName(), lookupSubtitleByHash(service, language, collector.remainingVideos())); - } catch (RuntimeException e) { + } catch (Exception e) { CLILogger.warning(format("Lookup by hash failed: " + e.getMessage())); } } @@ -402,7 +401,7 @@ public class CmdlineOperations implements CmdlineInterface { try { CLILogger.fine(format("Searching for %s at [%s]", querySet.toString(), service.getName())); collector.addAll(service.getName(), lookupSubtitleByFileName(service, querySet, language, collector.remainingVideos())); - } catch (RuntimeException e) { + } catch (Exception e) { CLILogger.warning(format("Search for [%s] failed: %s", querySet, e.getMessage())); } } @@ -499,7 +498,7 @@ public class CmdlineOperations implements CmdlineInterface { if (subtitles.size() > 0) { // first match everything as best as possible, then filter possibly bad matches Matcher matcher = new Matcher(videoFiles, subtitles, false, EpisodeMetrics.defaultSequence(true)); - SimilarityMetric sanity = new MetricCascade(StrictEpisodeMetrics.defaultSequence(true)); + SimilarityMetric sanity = EpisodeMetrics.verificationMetric(); for (Match it : matcher.match()) { if (sanity.getSimilarity(it.getValue(), it.getCandidate()) >= 1) { diff --git a/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java b/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java index a2054b18..4ba46964 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java @@ -2,6 +2,9 @@ package net.sourceforge.filebot.ui.rename; +import static net.sourceforge.filebot.similarity.EpisodeMetrics.*; +import static net.sourceforge.tuned.ui.TunedUtilities.*; + import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics; @@ -19,7 +22,9 @@ import javax.swing.border.EmptyBorder; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; +import net.sourceforge.filebot.similarity.Match; import net.sourceforge.filebot.ui.rename.RenameModel.FormattedFuture; +import net.sourceforge.filebot.web.Episode; import net.sourceforge.tuned.FileUtilities; import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer; import net.sourceforge.tuned.ui.GradientStyle; @@ -34,16 +39,18 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer { private final Color noMatchGradientBeginColor = new Color(0xB7B7B7); private final Color noMatchGradientEndColor = new Color(0x9A9A9A); + private final Color warningGradientBeginColor = Color.RED; + private final Color warningGradientEndColor = new Color(0xDC143C); + public RenameListCellRenderer(RenameModel renameModel) { super(new Insets(4, 7, 4, 7)); this.renameModel = renameModel; - setHighlightingEnabled(false); setLayout(new MigLayout("insets 0, fill", "align left", "align center")); - add(typeRenderer, "gap rel:push, hidemode 3"); + this.add(typeRenderer, "gap rel:push, hidemode 3"); } @@ -51,7 +58,8 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer { public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - // reset decoration + // reset decoration / highlighting + setOpaque(false); setIcon(null); typeRenderer.setVisible(false); typeRenderer.setAlpha(1.0f); @@ -80,6 +88,7 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer { } else if (value instanceof FormattedFuture) { // display progress icon FormattedFuture formattedFuture = (FormattedFuture) value; + setText(formattedFuture.isDone() && !formattedFuture.isCancelled() ? formattedFuture.toString() : formattedFuture.preview()); switch (formattedFuture.getState()) { case PENDING: @@ -89,10 +98,45 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer { setIcon(ResourceManager.getIcon("worker.started")); break; } + + if (renameModel.hasComplement(index)) { + float matchProbablity = getMatchProbablity(formattedFuture.getMatch()); + setOpaque(true); // enable paint background + setBackground(derive(warningGradientBeginColor, (1 - matchProbablity) * 0.5f)); // alpha indicates match probability + + if (matchProbablity < 1) { + if (isSelected) { + setGradientColors(warningGradientBeginColor, warningGradientEndColor); + setIcon(ResourceManager.getIcon("status.warning")); + + if (formattedFuture.isComplexFormat()) { + typeRenderer.setVisible(true); + typeRenderer.setAlpha(1.0f); + typeRenderer.setText(formattedFuture.preview()); + } + } + + } + } } } + protected float getMatchProbablity(Match match) { + if (match.getValue() instanceof Episode) { + float f = verificationMetric().getSimilarity(match.getValue(), match.getCandidate()); + return (f + 1) / 2; // normalize -1..1 to 0..1 + } + + float f = EpisodeIdentifier.getSimilarity(match.getValue(), match.getCandidate()); + if (f != 0) { + return (Math.max(f, 0)); // normalize -1..1 and boost by 0.25 (because file <-> file matches are not necessarily about Episodes) + } + + return 1; // assume match is OK + } + + protected String getType(File file) { if (file.isDirectory()) return "Folder"; diff --git a/source/net/sourceforge/filebot/ui/rename/RenameModel.java b/source/net/sourceforge/filebot/ui/rename/RenameModel.java index ce150522..6317b4fe 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenameModel.java +++ b/source/net/sourceforge/filebot/ui/rename/RenameModel.java @@ -32,7 +32,7 @@ import net.sourceforge.tuned.ui.TunedUtilities; public class RenameModel extends MatchModel { - private final FormattedFutureEventList names = new FormattedFutureEventList(); + private final FormattedFutureEventList names = new FormattedFutureEventList(this.values()); private final Map formatters = new LinkedHashMap(); @@ -151,10 +151,9 @@ public class RenameModel extends MatchModel { private final Executor backgroundFormatter = new ThreadPoolExecutor(0, 1, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue()); - public FormattedFutureEventList() { - super(values()); - - source.addListEventListener(this); + public FormattedFutureEventList(EventList source) { + super(source); + this.source.addListEventListener(this); } @@ -317,6 +316,11 @@ public class RenameModel extends MatchModel { } + public boolean isComplexFormat() { + return formatter instanceof ExpressionFormatter; + } + + public Match getMatch() { return match; } diff --git a/source/net/sourceforge/filebot/ui/subtitle/VideoHashSubtitleDownloadDialog.java b/source/net/sourceforge/filebot/ui/subtitle/VideoHashSubtitleDownloadDialog.java index b0ec3ba9..5c940376 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/VideoHashSubtitleDownloadDialog.java +++ b/source/net/sourceforge/filebot/ui/subtitle/VideoHashSubtitleDownloadDialog.java @@ -4,7 +4,6 @@ package net.sourceforge.filebot.ui.subtitle; import static javax.swing.BorderFactory.*; import static javax.swing.JOptionPane.*; -import static net.sourceforge.filebot.similarity.EpisodeMetrics.*; import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*; import static net.sourceforge.tuned.FileUtilities.*; @@ -60,10 +59,8 @@ import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.similarity.EpisodeMetrics; import net.sourceforge.filebot.similarity.Match; import net.sourceforge.filebot.similarity.Matcher; -import net.sourceforge.filebot.similarity.MetricCascade; import net.sourceforge.filebot.similarity.SeriesNameMatcher; import net.sourceforge.filebot.similarity.SimilarityMetric; -import net.sourceforge.filebot.similarity.StrictEpisodeMetrics; import net.sourceforge.filebot.ui.Language; import net.sourceforge.filebot.vfs.MemoryFile; import net.sourceforge.filebot.web.SubtitleDescriptor; @@ -927,7 +924,7 @@ class VideoHashSubtitleDownloadDialog extends JDialog { // first match everything as best as possible, then filter possibly bad matches Matcher matcher = new Matcher(files, subtitles, false, EpisodeMetrics.defaultSequence(true)); - SimilarityMetric sanity = new MetricCascade(StrictEpisodeMetrics.defaultSequence(true)); + SimilarityMetric sanity = EpisodeMetrics.verificationMetric(); for (Match it : matcher.match()) { if (sanity.getSimilarity(it.getValue(), it.getCandidate()) >= 1) { @@ -936,13 +933,12 @@ class VideoHashSubtitleDownloadDialog extends JDialog { } // add other possible matches to the options - SimilarityMetric matchMetric = new MetricCascade(FileName, EpisodeIdentifier, Title, Name); - float matchSimilarity = 0.6f; + float minMatchSimilarity = 0.6f; for (File file : files) { // add matching subtitles for (SubtitleDescriptor it : subtitles) { - if (matchMetric.getSimilarity(file, it) >= matchSimilarity && !subtitlesByFile.get(file).contains(it)) { + if (!subtitlesByFile.get(file).contains(it) && sanity.getSimilarity(file, it) >= minMatchSimilarity) { subtitlesByFile.get(file).add(it); } } diff --git a/source/net/sourceforge/tuned/ui/DefaultFancyListCellRenderer.java b/source/net/sourceforge/tuned/ui/DefaultFancyListCellRenderer.java index ff3c8eb9..7a23af99 100644 --- a/source/net/sourceforge/tuned/ui/DefaultFancyListCellRenderer.java +++ b/source/net/sourceforge/tuned/ui/DefaultFancyListCellRenderer.java @@ -15,20 +15,23 @@ public class DefaultFancyListCellRenderer extends AbstractFancyListCellRenderer private final JLabel label = new DefaultListCellRenderer(); - + public DefaultFancyListCellRenderer() { add(label); } + public DefaultFancyListCellRenderer(int padding) { super(new Insets(padding, padding, padding, padding)); add(label); } + public DefaultFancyListCellRenderer(Insets padding) { super(padding); add(label); } + protected DefaultFancyListCellRenderer(int padding, int margin, Color selectedBorderColor) { super(new Insets(padding, padding, padding, padding), new Insets(margin, margin, margin, margin), selectedBorderColor); @@ -39,9 +42,7 @@ public class DefaultFancyListCellRenderer extends AbstractFancyListCellRenderer @Override protected void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - label.setOpaque(false); - setText(String.valueOf(value)); }