* support simple File regex/replace renaming in GUI

* support loading of metadata from xattr (instead of online sources)
This commit is contained in:
Reinhard Pointner 2014-06-28 06:09:11 +00:00
parent 07568068c5
commit 7799f25a3a
4 changed files with 75 additions and 23 deletions

View File

@ -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;
}

View File

@ -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<String> 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();
}
}

View File

@ -3,6 +3,8 @@ help.url = http://www.filebot.net/naming.html
episode.syntax: <html><b>{</b> <b>}</b> \u2026 expression, <b>n</b> \u2026 name, <b>s</b> \u2026 season, <b>e</b> \u2026 episode, <b>t</b> \u2026 title</html>
movie.syntax: <html><b>{</b> <b>}</b> \u2026 expression, <b>n</b> \u2026 name, <b>y</b> \u2026 year</html>
music.syntax: <html><b>{</b> <b>}</b> \u2026 expression, <b>n</b> \u2026 album artist, <b>t</b> \u2026 title, <b>album</b> \u2026 album, <b>pi</b> \u2026 track</html>
file.syntax: <html><b>{</b> <b>}</b> \u2026 expression, <b>n</b> \u2026 name</html>
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('-')}

View File

@ -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<String> persistentEpisodeFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.episode");
private static final PreferencesEntry<String> persistentMovieFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.movie");
private static final PreferencesEntry<String> persistentMusicFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.music");
private static final PreferencesEntry<String> persistentFileFormat = Settings.forPackage(RenamePanel.class).entry("rename.format.file");
private static final PreferencesEntry<String> persistentLastFormatState = Settings.forPackage(RenamePanel.class).entry("rename.last.format.state");
private static final PreferencesEntry<String> 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<File> files = new ArrayList<File>(renameModel.files());
ArrayList<Object> objects = new ArrayList<Object>(files.size());
String forcedName = showInputDialog("Enter Name:", generatedName, "Enter Name", RenamePanel.this);
if (forcedName != null && forcedName.length() > 0) {
renameModel.matches().set(index, new Match<Object, File>(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<Object, File>(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());
}