diff --git a/build.xml b/build.xml index e11177db..64e14ff4 100644 --- a/build.xml +++ b/build.xml @@ -195,7 +195,7 @@ - + diff --git a/source/net/sourceforge/filebot/Main.java b/source/net/sourceforge/filebot/Main.java index ad56a1c7..3c426ba6 100644 --- a/source/net/sourceforge/filebot/Main.java +++ b/source/net/sourceforge/filebot/Main.java @@ -3,8 +3,8 @@ package net.sourceforge.filebot; import static javax.swing.JFrame.*; +import static net.sourceforge.tuned.ui.TunedUtilities.*; -import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.security.CodeSource; @@ -96,16 +96,19 @@ public class Main { } - private static void restoreWindowBounds(Window window, final Settings settings) { + private static void restoreWindowBounds(final JFrame window, final Settings settings) { // store bounds on close window.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - settings.put("window.x", String.valueOf(e.getWindow().getX())); - settings.put("window.y", String.valueOf(e.getWindow().getY())); - settings.put("window.width", String.valueOf(e.getWindow().getWidth())); - settings.put("window.height", String.valueOf(e.getWindow().getHeight())); + // don't save window bounds if window is maximized + if (!isMaximized(window)) { + settings.put("window.x", String.valueOf(window.getX())); + settings.put("window.y", String.valueOf(window.getY())); + settings.put("window.width", String.valueOf(window.getWidth())); + settings.put("window.height", String.valueOf(window.getHeight())); + } } }); diff --git a/source/net/sourceforge/filebot/ui/panel/rename/MovieFormatter.java b/source/net/sourceforge/filebot/ui/panel/rename/MovieFormatter.java index e9f718df..0a2c37dd 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/MovieFormatter.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/MovieFormatter.java @@ -2,15 +2,16 @@ package net.sourceforge.filebot.ui.panel.rename; +import java.util.Formatter; + import net.sourceforge.filebot.similarity.Match; -import net.sourceforge.filebot.web.MovieDescriptor; class MovieFormatter implements MatchFormatter { @Override public boolean canFormat(Match match) { - return match.getValue() instanceof MovieDescriptor; + return match.getValue() instanceof MoviePart; } @@ -22,8 +23,15 @@ class MovieFormatter implements MatchFormatter { @Override public String format(Match match) { - // use default format for the time being - return match.getValue().toString(); + MoviePart video = (MoviePart) match.getValue(); + Formatter name = new Formatter(new StringBuilder()); + + // format as single-file or multi-part movie + name.format("%s (%d)", video.getMovie().getName(), video.getMovie().getYear()); + + if (video.getPartCount() > 1) + name.format(" CD%d", video.getPartIndex() + 1); + + return name.out().toString(); } - } diff --git a/source/net/sourceforge/filebot/ui/panel/rename/MovieHashMatcher.java b/source/net/sourceforge/filebot/ui/panel/rename/MovieHashMatcher.java index c1ede12a..01e750e6 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/MovieHashMatcher.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/MovieHashMatcher.java @@ -11,10 +11,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Scanner; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.Map.Entry; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import java.util.concurrent.RunnableFuture; @@ -44,18 +49,44 @@ class MovieHashMatcher implements AutoCompleteMatcher { File[] movieFiles = filter(files, VIDEO_FILES).toArray(new File[0]); MovieDescriptor[] movieDescriptors = service.getMovieDescriptors(movieFiles); + // map movies to (possibly multiple) files (in natural order) + Map> filesByMovie = new HashMap>(); + + // map all files by movie + for (int i = 0; i < movieFiles.length; i++) { + MovieDescriptor movie = movieDescriptors[i]; + + // unknown hash, try via imdb id from nfo file + if (movie == null) { + movie = determineMovie(movieFiles[i]); + } + + // check if we managed to lookup the movie descriptor + if (movie != null) { + // get file list for movie + SortedSet movieParts = filesByMovie.get(movie); + + if (movieParts == null) { + movieParts = new TreeSet(); + filesByMovie.put(movie, movieParts); + } + + movieParts.add(movieFiles[i]); + } + } + + // collect all File/MoviePart matches List> matches = new ArrayList>(); - for (int i = 0; i < movieDescriptors.length; i++) { - if (movieDescriptors[i] != null) { - matches.add(new Match(movieFiles[i], movieDescriptors[i])); - } else { - // unknown hash, try via imdb id from nfo file - MovieDescriptor movie = determineMovie(movieFiles[i]); - - if (movie != null) { - matches.add(new Match(movieFiles[i], movie)); - } + for (Entry> entry : filesByMovie.entrySet()) { + MovieDescriptor movie = entry.getKey(); + + int partIndex = 0; + int partCount = entry.getValue().size(); + + // add all movie parts + for (File file : entry.getValue()) { + matches.add(new Match(file, new MoviePart(movie, partIndex++, partCount))); } } diff --git a/source/net/sourceforge/filebot/ui/panel/rename/MoviePart.java b/source/net/sourceforge/filebot/ui/panel/rename/MoviePart.java new file mode 100644 index 00000000..e4455d5e --- /dev/null +++ b/source/net/sourceforge/filebot/ui/panel/rename/MoviePart.java @@ -0,0 +1,45 @@ + +package net.sourceforge.filebot.ui.panel.rename; + + +import net.sourceforge.filebot.web.MovieDescriptor; + + +class MoviePart { + + private final MovieDescriptor movie; + + private final int partIndex; + private final int partCount; + + + public MoviePart(MovieDescriptor movie) { + this(movie, 0, 1); + } + + + public MoviePart(MovieDescriptor movie, int partIndex, int partCount) { + if (partCount < 1 || partIndex >= partCount) + throw new IllegalArgumentException("Illegal part: " + partIndex + "/" + partCount); + + this.movie = movie; + this.partIndex = partIndex; + this.partCount = partCount; + } + + + public MovieDescriptor getMovie() { + return movie; + } + + + public int getPartIndex() { + return partIndex; + } + + + public int getPartCount() { + return partCount; + } + +} diff --git a/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java b/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java index 1692dc3a..ffc95c24 100644 --- a/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java +++ b/source/net/sourceforge/filebot/ui/panel/rename/RenamePanel.java @@ -41,6 +41,7 @@ import net.sourceforge.filebot.web.Episode; import net.sourceforge.filebot.web.EpisodeListProvider; import net.sourceforge.filebot.web.IMDbClient; import net.sourceforge.filebot.web.MovieDescriptor; +import net.sourceforge.filebot.web.OpenSubtitlesClient; import net.sourceforge.filebot.web.TMDbClient; import net.sourceforge.filebot.web.TVDotComClient; import net.sourceforge.filebot.web.TVRageClient; @@ -152,6 +153,9 @@ public class RenamePanel extends JComponent { actionPopup.addDescription(new JLabel("Movie Mode:")); // create action for movie name completion + OpenSubtitlesClient osdb = new OpenSubtitlesClient(String.format("%s %s", getApplicationName(), getApplicationVersion())); + actionPopup.add(new AutoCompleteAction(osdb.getName(), osdb.getIcon(), new MovieHashMatcher(osdb))); + TMDbClient tmdb = new TMDbClient(getApplicationProperty("themoviedb.apikey")); actionPopup.add(new AutoCompleteAction(tmdb.getName(), tmdb.getIcon(), new MovieHashMatcher(tmdb))); diff --git a/source/net/sourceforge/tuned/ui/TunedUtilities.java b/source/net/sourceforge/tuned/ui/TunedUtilities.java index 0b66ce2a..bc6a4386 100644 --- a/source/net/sourceforge/tuned/ui/TunedUtilities.java +++ b/source/net/sourceforge/tuned/ui/TunedUtilities.java @@ -5,6 +5,7 @@ package net.sourceforge.tuned.ui; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Frame; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; @@ -98,6 +99,11 @@ public final class TunedUtilities { } + public static boolean isMaximized(Frame frame) { + return (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0; + } + + public static Window getWindow(Object component) { if (component instanceof Window) return (Window) component; diff --git a/test/net/sourceforge/filebot/web/TheTVDBClientTest.java b/test/net/sourceforge/filebot/web/TheTVDBClientTest.java index 65b3cd60..e4ab5ffd 100644 --- a/test/net/sourceforge/filebot/web/TheTVDBClientTest.java +++ b/test/net/sourceforge/filebot/web/TheTVDBClientTest.java @@ -44,8 +44,7 @@ public class TheTVDBClientTest { TheTVDBSearchResult first = (TheTVDBSearchResult) results.get(0); - // test encoding (umlauts) - assertEquals("Buffy - Im Bann der Dämonen", first.getName()); + assertEquals("Buffy", first.getName()); assertEquals(70327, first.getSeriesId()); TheTVDBSearchResult second = (TheTVDBSearchResult) results.get(1);