mirror of
https://github.com/mitb-archive/filebot
synced 2024-11-04 16:35:08 -05:00
* added extra hints for when user input is required for movie/series identification
This commit is contained in:
parent
2cdd0ddc17
commit
02f789e1bf
@ -278,16 +278,16 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
|
|||||||
String parentPathHint = normalizePathSeparators(getRelativePathTail(files.get(0).getParentFile(), 2).getPath());
|
String parentPathHint = normalizePathSeparators(getRelativePathTail(files.get(0).getParentFile(), 2).getPath());
|
||||||
String suggestion = detectedSeriesNames.size() > 0 ? join(detectedSeriesNames, ", ") : parentPathHint;
|
String suggestion = detectedSeriesNames.size() > 0 ? join(detectedSeriesNames, ", ") : parentPathHint;
|
||||||
|
|
||||||
List<String> input = emptyList();
|
List<String> input;
|
||||||
synchronized (inputMemory) {
|
synchronized (inputMemory) {
|
||||||
input = inputMemory.get(suggestion);
|
input = inputMemory.get(suggestion);
|
||||||
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
||||||
input = showMultiValueInputDialog("Enter series name:", suggestion, parentPathHint, parent);
|
input = showMultiValueInputDialog(getQueryInputMessage(files), suggestion, parentPathHint, parent);
|
||||||
inputMemory.put(suggestion, input);
|
inputMemory.put(suggestion, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.size() > 0) {
|
if (input != null && input.size() > 0) {
|
||||||
// only allow one fetch session at a time so later requests can make use of cached results
|
// only allow one fetch session at a time so later requests can make use of cached results
|
||||||
synchronized (providerLock) {
|
synchronized (providerLock) {
|
||||||
episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap<String, SearchResult>(), parent);
|
episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap<String, SearchResult>(), parent);
|
||||||
@ -309,14 +309,39 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getQueryInputMessage(List<File> files) throws Exception {
|
||||||
|
StringBuilder html = new StringBuilder(512);
|
||||||
|
html.append("<html>");
|
||||||
|
html.append("Unable to identify the following files:").append("<br>");
|
||||||
|
|
||||||
|
for (File file : sortByUniquePath(files)) {
|
||||||
|
html.append("<nobr>");
|
||||||
|
html.append("• ");
|
||||||
|
|
||||||
|
File path = getStructurePathTail(file);
|
||||||
|
if (path == null) {
|
||||||
|
path = getRelativePathTail(file, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
new TextColorizer().colorizePath(html, path, true);
|
||||||
|
html.append("</nobr>");
|
||||||
|
html.append("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
html.append("<br>");
|
||||||
|
html.append("Please enter series name:");
|
||||||
|
html.append("</html>");
|
||||||
|
return html.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public List<Match<File, ?>> justFetchEpisodeList(final SortOrder sortOrder, final Locale locale, final Component parent) throws Exception {
|
public List<Match<File, ?>> justFetchEpisodeList(final SortOrder sortOrder, final Locale locale, final Component parent) throws Exception {
|
||||||
// require user input
|
// require user input
|
||||||
String input = showInputDialog("Enter series name:", "", "Fetch Episode List", parent);
|
List<String> input = showMultiValueInputDialog("Enter series name:", "", "Fetch Episode List", parent);
|
||||||
|
|
||||||
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
|
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
|
||||||
if (input != null && input.length() > 0) {
|
if (input.size() > 0) {
|
||||||
synchronized (providerLock) {
|
synchronized (providerLock) {
|
||||||
Set<Episode> episodes = fetchEpisodeSet(singleton(input), sortOrder, locale, new HashMap<String, SearchResult>(), parent);
|
Set<Episode> episodes = fetchEpisodeSet(input, sortOrder, locale, new HashMap<String, SearchResult>(), parent);
|
||||||
for (Episode it : episodes) {
|
for (Episode it : episodes) {
|
||||||
matches.add(new Match<File, Episode>(null, it));
|
matches.add(new Match<File, Episode>(null, it));
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
|||||||
String input = inputMemory.get(suggestion);
|
String input = inputMemory.get(suggestion);
|
||||||
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
if (input == null || suggestion == null || suggestion.isEmpty()) {
|
||||||
File movieFolder = guessMovieFolder(movieFile);
|
File movieFolder = guessMovieFolder(movieFile);
|
||||||
input = showInputDialog("Enter movie name:", suggestion != null && suggestion.length() > 0 ? suggestion : getName(movieFile), movieFolder == null ? movieFile.getName() : String.format("%s/%s", movieFolder.getName(), movieFile.getName()), parent);
|
input = showInputDialog(getQueryInputMessage(movieFile), suggestion != null && suggestion.length() > 0 ? suggestion : getName(movieFile), movieFolder == null ? movieFile.getName() : String.format("%s/%s", movieFolder.getName(), movieFile.getName()), parent);
|
||||||
inputMemory.put(suggestion, input);
|
inputMemory.put(suggestion, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,6 +292,28 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
|||||||
return options.isEmpty() ? null : selectMovie(movieFile, null, options, memory, parent);
|
return options.isEmpty() ? null : selectMovie(movieFile, null, options, memory, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getQueryInputMessage(File file) throws Exception {
|
||||||
|
File path = getStructurePathTail(file);
|
||||||
|
if (path == null) {
|
||||||
|
path = getRelativePathTail(file, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder html = new StringBuilder(512);
|
||||||
|
html.append("<html>");
|
||||||
|
html.append("Unable to identify the following files:").append("<br>");
|
||||||
|
|
||||||
|
html.append("<nobr>");
|
||||||
|
html.append("• ");
|
||||||
|
new TextColorizer().colorizePath(html, path, file.isFile());
|
||||||
|
html.append("</nobr>");
|
||||||
|
html.append("<br>");
|
||||||
|
|
||||||
|
html.append("<br>");
|
||||||
|
html.append("Please enter movie name:");
|
||||||
|
html.append("</html>");
|
||||||
|
return html.toString();
|
||||||
|
}
|
||||||
|
|
||||||
protected String checkedStripReleaseInfo(File file) throws Exception {
|
protected String checkedStripReleaseInfo(File file) throws Exception {
|
||||||
String name = stripReleaseInfo(getName(file));
|
String name = stripReleaseInfo(getName(file));
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ import java.awt.RenderingHints;
|
|||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
@ -44,8 +43,7 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer {
|
|||||||
private Color warningGradientBeginColor = Color.RED;
|
private Color warningGradientBeginColor = Color.RED;
|
||||||
private Color warningGradientEndColor = new Color(0xDC143C);
|
private Color warningGradientEndColor = new Color(0xDC143C);
|
||||||
|
|
||||||
private Color pathRainbowBeginColor = new Color(0xCC3300);
|
private TextColorizer textColorizer = new TextColorizer();
|
||||||
private Color pathRainbowEndColor = new Color(0x008080);
|
|
||||||
|
|
||||||
public RenameListCellRenderer(RenameModel renameModel) {
|
public RenameListCellRenderer(RenameModel renameModel) {
|
||||||
super(new Insets(4, 7, 4, 7));
|
super(new Insets(4, 7, 4, 7));
|
||||||
@ -164,29 +162,11 @@ class RenameListCellRenderer extends DefaultFancyListCellRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String colorizePath(File file, boolean hasExtension) {
|
protected String colorizePath(File file, boolean hasExtension) {
|
||||||
List<File> path = listPath(file);
|
|
||||||
StringBuilder html = new StringBuilder(512);
|
StringBuilder html = new StringBuilder(512);
|
||||||
html.append("<html><nobr>");
|
html.append("<html><nobr>");
|
||||||
|
textColorizer.colorizePath(html, file, hasExtension);
|
||||||
// colorize parent path
|
html.append("</nobr></html>");
|
||||||
for (int i = 0; i < path.size() - 1; i++) {
|
return html.toString();
|
||||||
float f = (path.size() <= 2) ? 1 : (float) i / (path.size() - 2);
|
|
||||||
Color c = interpolateHSB(pathRainbowBeginColor, pathRainbowEndColor, f);
|
|
||||||
html.append(String.format("<span style='color:rgb(%1$d, %2$d, %3$d)'>%4$s</span><span style='color:rgb(%1$d, %2$d, %3$d)'>/</span>", c.getRed(), c.getGreen(), c.getBlue(), escapeHTML(FileUtilities.getFolderName(path.get(i)))));
|
|
||||||
}
|
|
||||||
|
|
||||||
// only colorize extension
|
|
||||||
if (hasExtension) {
|
|
||||||
html.append(escapeHTML(FileUtilities.getName(file)));
|
|
||||||
String extension = FileUtilities.getExtension(file);
|
|
||||||
if (extension != null) {
|
|
||||||
html.append(String.format("<span style='color:#607080'>.%s</span>", escapeHTML(extension))); // highlight extension
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
html.append(file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return html.append("</nobr></html>").toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File resolveAbsolutePath(File targetDir, String path, String extension) {
|
protected File resolveAbsolutePath(File targetDir, String path, String extension) {
|
||||||
|
50
source/net/filebot/ui/rename/TextColorizer.java
Normal file
50
source/net/filebot/ui/rename/TextColorizer.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package net.filebot.ui.rename;
|
||||||
|
|
||||||
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
import static net.filebot.util.ui.TunedUtilities.*;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.filebot.util.FileUtilities;
|
||||||
|
|
||||||
|
public class TextColorizer {
|
||||||
|
|
||||||
|
private Color pathRainbowBeginColor;
|
||||||
|
private Color pathRainbowEndColor;
|
||||||
|
|
||||||
|
public TextColorizer() {
|
||||||
|
this(new Color(0xCC3300), new Color(0x008080));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextColorizer(Color pathRainbowBeginColor, Color pathRainbowEndColor) {
|
||||||
|
this.pathRainbowBeginColor = pathRainbowBeginColor;
|
||||||
|
this.pathRainbowEndColor = pathRainbowEndColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuilder colorizePath(StringBuilder html, File file, boolean hasExtension) {
|
||||||
|
List<File> path = listPath(file);
|
||||||
|
|
||||||
|
// colorize parent path
|
||||||
|
for (int i = 0; i < path.size() - 1; i++) {
|
||||||
|
float f = (path.size() <= 2) ? 1 : (float) i / (path.size() - 2);
|
||||||
|
Color c = interpolateHSB(pathRainbowBeginColor, pathRainbowEndColor, f);
|
||||||
|
html.append(String.format("<span style='color:rgb(%1$d, %2$d, %3$d)'>%4$s</span><span style='color:rgb(%1$d, %2$d, %3$d)'>/</span>", c.getRed(), c.getGreen(), c.getBlue(), escapeHTML(FileUtilities.getFolderName(path.get(i)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// only colorize extension
|
||||||
|
if (hasExtension) {
|
||||||
|
html.append(escapeHTML(FileUtilities.getName(file)));
|
||||||
|
String extension = FileUtilities.getExtension(file);
|
||||||
|
if (extension != null) {
|
||||||
|
html.append(String.format("<span style='color:#607080'>.%s</span>", escapeHTML(extension))); // highlight extension
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html.append(file.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -135,8 +135,8 @@ public final class TunedUtilities {
|
|||||||
return (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
return (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> showMultiValueInputDialog(final String text, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException {
|
public static List<String> showMultiValueInputDialog(final Object message, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException {
|
||||||
String input = showInputDialog(text, initialValue, title, parent);
|
String input = showInputDialog(message, initialValue, title, parent);
|
||||||
if (input == null || input.isEmpty()) {
|
if (input == null || input.isEmpty()) {
|
||||||
return emptyList();
|
return emptyList();
|
||||||
}
|
}
|
||||||
@ -161,14 +161,14 @@ public final class TunedUtilities {
|
|||||||
return singletonList(input);
|
return singletonList(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String showInputDialog(final String text, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException {
|
public static String showInputDialog(final Object message, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException {
|
||||||
final StringBuilder buffer = new StringBuilder();
|
final StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Object value = JOptionPane.showInputDialog(parent, text, title, PLAIN_MESSAGE, null, null, initialValue);
|
Object value = JOptionPane.showInputDialog(parent, message, title, PLAIN_MESSAGE, null, null, initialValue);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
buffer.append(value.toString().trim());
|
buffer.append(value.toString().trim());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user