From 74569a405f3e83bf26f925894f6b07da0463132d Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Fri, 4 Mar 2016 22:52:15 +0000 Subject: [PATCH] Support Query->SearchResult persistent memory in Episode mode --- source/ehcache.xml | 30 ++++++++++---- source/net/filebot/Cache.java | 3 +- source/net/filebot/ui/SelectDialog.java | 21 ++++++++++ .../filebot/ui/rename/EpisodeListMatcher.java | 41 ++++++++++++++----- .../filebot/ui/rename/MovieHashMatcher.java | 13 +----- 5 files changed, 77 insertions(+), 31 deletions(-) diff --git a/source/ehcache.xml b/source/ehcache.xml index 255e146c..e77d5595 100644 --- a/source/ehcache.xml +++ b/source/ehcache.xml @@ -3,7 +3,7 @@ Persistent disk store location --> - + @@ -31,7 +31,7 @@ diskPersistent="true" memoryStoreEvictionPolicy="LRU" /> - + @@ -45,7 +45,7 @@ diskPersistent="true" memoryStoreEvictionPolicy="LRU" /> - + @@ -59,7 +59,7 @@ diskPersistent="true" memoryStoreEvictionPolicy="LRU" /> - + @@ -73,11 +73,25 @@ diskPersistent="true" memoryStoreEvictionPolicy="LRU" /> - + + + + - - + diff --git a/source/net/filebot/Cache.java b/source/net/filebot/Cache.java index 3451b134..217eff40 100644 --- a/source/net/filebot/Cache.java +++ b/source/net/filebot/Cache.java @@ -10,7 +10,8 @@ import net.sf.ehcache.Element; public class Cache { - public static final String EPHEMERAL = "ephemeral"; + public static final String EPHEMERAL = "ephemeral-memory"; + public static final String PERSISTENT = "persistent-memory"; public static Cache getCache(String name) { return new Cache(CacheManager.getInstance().getCache(name)); diff --git a/source/net/filebot/ui/SelectDialog.java b/source/net/filebot/ui/SelectDialog.java index 179cdf19..98856025 100644 --- a/source/net/filebot/ui/SelectDialog.java +++ b/source/net/filebot/ui/SelectDialog.java @@ -1,5 +1,6 @@ package net.filebot.ui; +import static java.awt.Cursor.*; import static net.filebot.util.ui.SwingUI.*; import java.awt.Component; @@ -13,6 +14,7 @@ import java.util.Collection; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; @@ -30,12 +32,17 @@ import net.miginfocom.swing.MigLayout; public class SelectDialog extends JDialog { private JLabel headerLabel = new JLabel(); + private JCheckBox autoRepeatCheckBox = new JCheckBox(); private JList list; private Action selectedAction = null; public SelectDialog(Component parent, Collection options) { + this(parent, options, false, false); + } + + public SelectDialog(Component parent, Collection options, boolean autoRepeatEnabled, boolean autoRepeatSelected) { super(getWindow(parent), "Select", ModalityType.DOCUMENT_MODAL); setDefaultCloseOperation(DISPOSE_ON_CLOSE); @@ -70,6 +77,16 @@ public class SelectDialog extends JDialog { c.add(new JButton(selectAction), "align center, id select"); c.add(new JButton(cancelAction), "gap unrel, id cancel"); + // add repeat button + if (autoRepeatEnabled) { + autoRepeatCheckBox.setSelected(autoRepeatSelected); + autoRepeatCheckBox.setToolTipText("Remember"); + autoRepeatCheckBox.setCursor(getPredefinedCursor(HAND_CURSOR)); + autoRepeatCheckBox.setIcon(ResourceManager.getIcon("button.repeat")); + autoRepeatCheckBox.setSelectedIcon(ResourceManager.getIcon("button.repeat.selected")); + c.add(autoRepeatCheckBox, "pos 1al select.y n select.y2"); + } + // set default size and location setMinimumSize(new Dimension(220, 240)); setSize(new Dimension(240, 260)); @@ -86,6 +103,10 @@ public class SelectDialog extends JDialog { return headerLabel; } + public JCheckBox getAutoRepeatCheckBox() { + return autoRepeatCheckBox; + } + public Action getSelectedAction() { return selectedAction; } diff --git a/source/net/filebot/ui/rename/EpisodeListMatcher.java b/source/net/filebot/ui/rename/EpisodeListMatcher.java index 0d2ce491..bcf944e0 100644 --- a/source/net/filebot/ui/rename/EpisodeListMatcher.java +++ b/source/net/filebot/ui/rename/EpisodeListMatcher.java @@ -38,6 +38,7 @@ import java.util.concurrent.RunnableFuture; import javax.swing.Action; import javax.swing.SwingUtilities; +import net.filebot.Cache; import net.filebot.Settings; import net.filebot.similarity.CommonSequenceMatcher; import net.filebot.similarity.EpisodeMatcher; @@ -58,13 +59,16 @@ class EpisodeListMatcher implements AutoCompleteMatcher { // only allow one fetch session at a time so later requests can make use of cached results private final Object providerLock = new Object(); + // remember user selections + private final Cache persistentSelectionMemory = Cache.getCache(Cache.PERSISTENT); + public EpisodeListMatcher(EpisodeListProvider provider, boolean useSeriesIndex, boolean useAnimeIndex) { this.provider = provider; this.useSeriesIndex = useSeriesIndex; this.useAnimeIndex = useAnimeIndex; } - protected SearchResult selectSearchResult(final String query, final List searchResults, Map selectionMemory, final Component parent) throws Exception { + protected SearchResult selectSearchResult(final String query, final List searchResults, Map selectionMemory, boolean autodetection, final Component parent) throws Exception { if (searchResults.size() == 1) { return searchResults.get(0); } @@ -83,7 +87,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { @Override public SearchResult call() throws Exception { // multiple results have been found, user must select one - SelectDialog selectDialog = new SelectDialog(parent, searchResults); + SelectDialog selectDialog = new SelectDialog(parent, searchResults, true, false); selectDialog.getHeaderLabel().setText(String.format("Shows matching '%s':", query)); selectDialog.getCancelAction().putValue(Action.NAME, "Ignore"); @@ -107,6 +111,11 @@ class EpisodeListMatcher implements AutoCompleteMatcher { throw new CancellationException("Cancelled by user"); } + // remember if we should auto-repeat the chosen action in the future + if (selectDialog.getAutoRepeatCheckBox().isSelected() && selectDialog.getSelectedValue() != null) { + persistentSelectionMemory.put(query, selectDialog.getSelectedValue()); + } + // selected value or null if the dialog was canceled by the user return selectDialog.getSelectedValue(); } @@ -119,16 +128,26 @@ class EpisodeListMatcher implements AutoCompleteMatcher { return selectionMemory.get(query); } - SwingUtilities.invokeAndWait(showSelectDialog); + // check persistent memory + if (autodetection) { + SearchResult persistentSelection = persistentSelectionMemory.get(query, SearchResult.class); + if (persistentSelection != null) { + return persistentSelection; + } + } - // cache selected value - selectionMemory.put(query, showSelectDialog.get()); - return showSelectDialog.get(); + // ask user + SwingUtilities.invokeAndWait(showSelectDialog); + SearchResult userSelection = showSelectDialog.get(); + + // remember selected value + selectionMemory.put(query, userSelection); + return userSelection; } } } - protected Set fetchEpisodeSet(Collection seriesNames, final SortOrder sortOrder, final Locale locale, final Map selectionMemory, final Component parent) throws Exception { + protected Set fetchEpisodeSet(Collection seriesNames, final SortOrder sortOrder, final Locale locale, final Map selectionMemory, final boolean autodetection, final Component parent) throws Exception { List>> tasks = new ArrayList>>(); // detect series names and create episode list fetch tasks @@ -141,7 +160,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { // select search result if (results.size() > 0) { - SearchResult selectedSearchResult = selectSearchResult(query, results, selectionMemory, parent); + SearchResult selectedSearchResult = selectSearchResult(query, results, selectionMemory, autodetection, parent); if (selectedSearchResult != null) { return provider.getEpisodeList(selectedSearchResult, sortOrder, locale); @@ -278,7 +297,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { if (queries != null && queries.size() > 0) { // only allow one fetch session at a time so later requests can make use of cached results synchronized (providerLock) { - episodes = fetchEpisodeSet(queries, sortOrder, locale, selectionMemory, parent); + episodes = fetchEpisodeSet(queries, sortOrder, locale, selectionMemory, autodetection, parent); } } } @@ -301,7 +320,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { if (input != null && input.size() > 0) { // only allow one fetch session at a time so later requests can make use of cached results synchronized (providerLock) { - episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap(), parent); + episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap(), false, parent); } } } @@ -374,7 +393,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { List> matches = new ArrayList>(); if (input.size() > 0) { synchronized (providerLock) { - Set episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap(), parent); + Set episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap(), false, parent); for (Episode it : episodes) { matches.add(new Match(null, it)); } diff --git a/source/net/filebot/ui/rename/MovieHashMatcher.java b/source/net/filebot/ui/rename/MovieHashMatcher.java index d48bc81a..2be6973c 100644 --- a/source/net/filebot/ui/rename/MovieHashMatcher.java +++ b/source/net/filebot/ui/rename/MovieHashMatcher.java @@ -404,21 +404,12 @@ class MovieHashMatcher implements AutoCompleteMatcher { @Override public Movie call() throws Exception { // multiple results have been found, user must select one - SelectDialog selectDialog = new SelectDialog(parent, options); + SelectDialog selectDialog = new SelectDialog(parent, options, true, false); selectDialog.setTitle(folderQuery.isEmpty() ? fileQuery : String.format("%s / %s", folderQuery, fileQuery)); selectDialog.getHeaderLabel().setText(String.format("Movies matching '%s':", fileQuery.length() >= 2 || folderQuery.length() <= 2 ? fileQuery : folderQuery)); selectDialog.getCancelAction().putValue(Action.NAME, "Ignore"); - // add repeat button - JCheckBox checkBox = new JCheckBox(); - checkBox.setToolTipText("Select / Ignore for all"); - checkBox.setCursor(getPredefinedCursor(HAND_CURSOR)); - checkBox.setIcon(ResourceManager.getIcon("button.repeat")); - checkBox.setSelectedIcon(ResourceManager.getIcon("button.repeat.selected")); - JComponent c = (JComponent) selectDialog.getContentPane(); - c.add(checkBox, "pos 1al select.y n select.y2"); - // restore original dialog size Settings prefs = Settings.forPackage(MovieHashMatcher.class); int w = Integer.parseInt(prefs.get("dialog.select.w", "280")); @@ -435,7 +426,7 @@ class MovieHashMatcher implements AutoCompleteMatcher { prefs.put("dialog.select.h", Integer.toString(selectDialog.getHeight())); // remember if we should auto-repeat the chosen action in the future - if (checkBox.isSelected() || selectDialog.getSelectedAction() == null) { + if (selectDialog.getAutoRepeatCheckBox().isSelected() || selectDialog.getSelectedAction() == null) { memory.put("repeat", selectDialog.getSelectedValue() != null ? "select" : "ignore"); }