From 7799f25a3ad49ccac1aa312c7c67534b1a33b33f Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Sat, 28 Jun 2014 06:09:11 +0000 Subject: [PATCH] * support simple File regex/replace renaming in GUI * support loading of metadata from xattr (instead of online sources) --- .../net/filebot/format/MediaBindingBean.java | 2 + .../net/filebot/ui/rename/FormatDialog.java | 21 ++++-- .../filebot/ui/rename/FormatDialog.properties | 11 ++++ source/net/filebot/ui/rename/RenamePanel.java | 64 ++++++++++++++----- 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index 06f62d2a..005f2b5a 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -83,6 +83,8 @@ public class MediaBindingBean { return getMovie().getName(); if (infoObject instanceof AudioTrack) return getAlbumArtist() != null ? getAlbumArtist() : getArtist(); + if (infoObject instanceof File) + return FileUtilities.getName((File) infoObject); return null; } diff --git a/source/net/filebot/ui/rename/FormatDialog.java b/source/net/filebot/ui/rename/FormatDialog.java index 881eebd2..42dc5045 100644 --- a/source/net/filebot/ui/rename/FormatDialog.java +++ b/source/net/filebot/ui/rename/FormatDialog.java @@ -58,7 +58,6 @@ import javax.swing.event.PopupMenuListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; -import net.miginfocom.swing.MigLayout; import net.filebot.ResourceManager; import net.filebot.Settings; import net.filebot.format.BindingException; @@ -78,6 +77,7 @@ import net.filebot.util.ui.notification.SeparatorBorder.Position; import net.filebot.web.AudioTrackFormat; import net.filebot.web.EpisodeFormat; import net.filebot.web.MovieFormat; +import net.miginfocom.swing.MigLayout; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; @@ -111,13 +111,18 @@ public class FormatDialog extends JDialog { private static final PreferencesEntry persistentSampleFile = Settings.forPackage(FormatDialog.class).entry("format.sample.file"); public enum Mode { - Episode, Movie, Music; + Episode, Movie, Music, File; public Mode next() { - if (ordinal() < values().length - 1) - return values()[ordinal() + 1]; - - return values()[0]; + // cycle through Episode -> Movie -> Music (but ignore generic File mode) + switch (this) { + case Episode: + return Movie; + case Movie: + return Music; + default: + return Episode; + } } public String key() { @@ -130,8 +135,10 @@ public class FormatDialog extends JDialog { return new EpisodeFormat(true, true); case Movie: // case Movie return new MovieFormat(true, true, false); - default: + case Music: return new AudioTrackFormat(); + default: + return new FileFormat(); } } diff --git a/source/net/filebot/ui/rename/FormatDialog.properties b/source/net/filebot/ui/rename/FormatDialog.properties index 27149046..3090f859 100644 --- a/source/net/filebot/ui/rename/FormatDialog.properties +++ b/source/net/filebot/ui/rename/FormatDialog.properties @@ -3,6 +3,8 @@ help.url = http://www.filebot.net/naming.html episode.syntax: { } \u2026 expression, n \u2026 name, s \u2026 season, e \u2026 episode, t \u2026 title movie.syntax: { } \u2026 expression, n \u2026 name, y \u2026 year music.syntax: { } \u2026 expression, n \u2026 album artist, t \u2026 title, album \u2026 album, pi \u2026 track +file.syntax: { } \u2026 expression, n \u2026 name + episode.sample: {"@type":"net.filebot.web.Episode","seriesName":"Firefly","seriesStartDate":{"year":2002,"month":9,"day":20},"season":1,"episode":1,"title":"Serenity","absolute":1,"special":null,"airdate":{"year":2002,"month":12,"day":20},"series":{"@type":"net.filebot.web.TheTVDBSearchResult","seriesId":78874,"name":"Firefly","aliasNames":[]}} movie.sample: {"@type":"net.filebot.web.MoviePart","partIndex":1,"partCount":2,"year":2009,"imdbId":-1,"tmdbId":19995,"name":"Avatar","aliasNames":[]} @@ -40,3 +42,12 @@ music.example[2]: {n} - {t} {[audio.SamplingRateString]} music.example[3]: {pi.pad(2)} {n} - {t} {[af, audio.BitRate]} # organize folder structure music.example[4]: {n}/{"$album/"}{"${pi.pad(2)}. "} {t} + +# simple filename without extension +file.example[0]: {n} +# simple filename regex-replace +file.example[1]: {n.replaceAll(/\\d+/, '')} +# simple filename regex-replace +file.example[2]: {n.replaceAll(/\\p{Punct}+/, ' ')} +# simple filter +file.example[3]: {n.after('-')} diff --git a/source/net/filebot/ui/rename/RenamePanel.java b/source/net/filebot/ui/rename/RenamePanel.java index 7f02a577..826ef0ea 100644 --- a/source/net/filebot/ui/rename/RenamePanel.java +++ b/source/net/filebot/ui/rename/RenamePanel.java @@ -46,7 +46,6 @@ import javax.swing.SwingWorker; import javax.swing.border.CompoundBorder; import javax.swing.border.TitledBorder; -import net.miginfocom.swing.MigLayout; import net.filebot.History; import net.filebot.HistorySpooler; import net.filebot.Language; @@ -55,6 +54,7 @@ import net.filebot.Settings; import net.filebot.StandardRenameAction; import net.filebot.WebServices; import net.filebot.format.MediaBindingBean; +import net.filebot.media.MediaDetection; import net.filebot.similarity.Match; import net.filebot.ui.rename.FormatDialog.Mode; import net.filebot.ui.rename.RenameModel.FormattedFuture; @@ -71,6 +71,7 @@ import net.filebot.web.MovieFormat; import net.filebot.web.MovieIdentificationService; import net.filebot.web.MusicIdentificationService; import net.filebot.web.SortOrder; +import net.miginfocom.swing.MigLayout; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.ListSelection; import ca.odell.glazedlists.swing.EventSelectionModel; @@ -90,6 +91,7 @@ public class RenamePanel extends JComponent { private static final PreferencesEntry persistentEpisodeFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.episode"); private static final PreferencesEntry persistentMovieFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.movie"); private static final PreferencesEntry persistentMusicFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.music"); + private static final PreferencesEntry persistentFileFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.file"); private static final PreferencesEntry persistentLastFormatState = Settings.forPackage(RenamePanel.class).entry("rename.last.format.state"); private static final PreferencesEntry persistentPreferredLanguage = Settings.forPackage(RenamePanel.class).entry("rename.language").defaultValue("en"); @@ -102,24 +104,34 @@ public class RenamePanel extends JComponent { filesList.setTitle("Original Files"); filesList.setTransferablePolicy(new FilesListTransferablePolicy(renameModel.files())); - // filename formatter - renameModel.useFormatter(File.class, new FileNameFormatter(renameModel.preserveExtension())); - - // movie formatter - renameModel.useFormatter(Movie.class, new MovieFormatter()); - try { // restore custom episode formatter renameModel.useFormatter(Episode.class, new ExpressionFormatter(persistentEpisodeFormat.getValue(), EpisodeFormat.SeasonEpisode, Episode.class)); } catch (Exception e) { - // illegal format, ignore + // use default formatter } try { // restore custom movie formatter renameModel.useFormatter(Movie.class, new ExpressionFormatter(persistentMovieFormat.getValue(), MovieFormat.NameYear, Movie.class)); } catch (Exception e) { - // illegal format, ignore + // use default movie formatter + renameModel.useFormatter(Movie.class, new MovieFormatter()); + } + + try { + // restore custom music formatter + renameModel.useFormatter(AudioTrack.class, new ExpressionFormatter(persistentMusicFormat.getValue(), new AudioTrackFormat(), AudioTrack.class)); + } catch (Exception e) { + // use default formatter + } + + try { + // restore custom music formatter + renameModel.useFormatter(File.class, new ExpressionFormatter(persistentFileFormat.getValue(), new FileFormat(), File.class)); + } catch (Exception e) { + // use default filename formatter + renameModel.useFormatter(File.class, new FileNameFormatter(renameModel.preserveExtension())); } RenameListCellRenderer cellrenderer = new RenameListCellRenderer(renameModel); @@ -292,13 +304,26 @@ public class RenamePanel extends JComponent { @Override public void actionPerformed(ActionEvent evt) { try { - int index = namesList.getListComponent().getSelectedIndex(); - File file = (File) filesList.getListComponent().getModel().getElementAt(index); - String generatedName = namesList.getListComponent().getModel().getElementAt(index).toString(); + if (namesList.getModel().isEmpty()) { + ArrayList files = new ArrayList(renameModel.files()); + ArrayList objects = new ArrayList(files.size()); - String forcedName = showInputDialog("Enter Name:", generatedName, "Enter Name", RenamePanel.this); - if (forcedName != null && forcedName.length() > 0) { - renameModel.matches().set(index, new Match(forcedName, file)); + for (File file : files) { + Object metaObject = MediaDetection.readMetaInfo(file); + objects.add(metaObject != null ? metaObject : file); + } + + renameModel.clear(); + renameModel.addAll(objects, files); + } else { + int index = namesList.getListComponent().getSelectedIndex(); + File file = (File) filesList.getListComponent().getModel().getElementAt(index); + String generatedName = namesList.getListComponent().getModel().getElementAt(index).toString(); + + String forcedName = showInputDialog("Enter Name:", generatedName, "Enter Name", RenamePanel.this); + if (forcedName != null && forcedName.length() > 0) { + renameModel.matches().set(index, new Match(forcedName, file)); + } } } catch (Exception e) { Logger.getLogger(RenamePanel.class.getName()).log(Level.WARNING, e.getMessage()); @@ -427,8 +452,10 @@ public class RenamePanel extends JComponent { initMode = Mode.Movie; } else if (lockOnBinding.getInfoObject() instanceof AudioTrack) { initMode = Mode.Music; + } else if (lockOnBinding.getInfoObject() instanceof File) { + initMode = Mode.File; } else { - // illegal info object => ignore + // ignore objects that cannot be formatted return; } } else { @@ -458,7 +485,12 @@ public class RenamePanel extends JComponent { renameModel.useFormatter(AudioTrack.class, new ExpressionFormatter(dialog.getFormat().getExpression(), new AudioTrackFormat(), AudioTrack.class)); persistentMusicFormat.setValue(dialog.getFormat().getExpression()); break; + case File: + renameModel.useFormatter(File.class, new ExpressionFormatter(dialog.getFormat().getExpression(), new FileFormat(), File.class)); + persistentFileFormat.setValue(dialog.getFormat().getExpression()); + break; } + if (lockOnBinding == null) { persistentLastFormatState.setValue(dialog.getMode().name()); }