diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index 8c63e45a..df363963 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -77,7 +77,7 @@ public class MediaBindingBean { private MediaInfo mediaInfo; public MediaBindingBean(Object infoObject, File mediaFile) { - this(infoObject, mediaFile, singletonMap(mediaFile, infoObject)); + this(infoObject, mediaFile, null); } public MediaBindingBean(Object infoObject, File mediaFile, Map context) { @@ -949,13 +949,18 @@ public class MediaBindingBean { } @Define("i") - public Integer getModelIndex() { + public Number getModelIndex() { return 1 + identityIndexOf(context.values(), getInfoObject()); } @Define("di") - public Integer getDuplicateIndex() { - return 1 + identityIndexOf(context.values().stream().filter(it -> getInfoObject().equals(it)).collect(toList()), getInfoObject()); + public Number getDuplicateIndex() { + return 1 + identityIndexOf(context.values().stream().filter(getInfoObject()::equals).collect(toList()), getInfoObject()); + } + + @Define("dc") + public Number getDuplicateCount() { + return context.values().stream().filter(getInfoObject()::equals).count(); } @Define("plex") diff --git a/source/net/filebot/ui/rename/BindingDialog.java b/source/net/filebot/ui/rename/BindingDialog.java index d675474d..2dc45135 100644 --- a/source/net/filebot/ui/rename/BindingDialog.java +++ b/source/net/filebot/ui/rename/BindingDialog.java @@ -42,7 +42,6 @@ import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.RowFilter; import javax.swing.SwingWorker; -import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; @@ -67,6 +66,8 @@ class BindingDialog extends JDialog { private final Format infoObjectFormat; private final BindingTableModel bindingModel = new BindingTableModel(); + private MediaBindingBean sample = null; + private boolean submit = false; public BindingDialog(Window owner, String title, Format infoObjectFormat, boolean editable) { @@ -106,10 +107,11 @@ class BindingDialog extends JDialog { // update preview on change DocumentListener changeListener = new LazyDocumentListener(1000, evt -> { // ignore lazy events that come in after the window has been closed - if (bindingModel.executor.isShutdown()) + if (sample == null || bindingModel.executor.isShutdown()) { return; + } - bindingModel.setModel(getSampleExpressions(), new MediaBindingBean(getInfoObject(), getMediaFile())); + bindingModel.setModel(getSampleExpressions(), sample); }); // update example bindings on change @@ -121,23 +123,9 @@ class BindingDialog extends JDialog { mediaInfoAction.setEnabled(false); // disable media info action if media file is invalid - mediaFileTextField.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void changedUpdate(DocumentEvent e) { - mediaInfoAction.setEnabled(getMediaFile() != null && getMediaFile().isFile()); - } - - @Override - public void removeUpdate(DocumentEvent e) { - changedUpdate(e); - } - - @Override - public void insertUpdate(DocumentEvent e) { - changedUpdate(e); - } - }); + mediaFileTextField.getDocument().addDocumentListener(new LazyDocumentListener(0, evt -> { + mediaInfoAction.setEnabled(getMediaFile() != null && getMediaFile().isFile()); + })); // finish dialog and close window manually addWindowListener(windowClosed(evt -> finish(false))); @@ -216,31 +204,25 @@ class BindingDialog extends JDialog { dispose(); } - public void setInfoObject(Object info) { - infoTextField.putClientProperty("model", info); + public void setSample(MediaBindingBean sample) { + this.sample = sample; - infoTextField.setText(info == null ? "" : infoObjectFormat.format(info)); - infoTextField.setToolTipText(info == null ? "null" : "
" + escapeHTML(json(info, true)) + "
"); + infoTextField.setText(getInfoObject() == null ? "" : infoObjectFormat.format(getInfoObject())); + infoTextField.setToolTipText(getInfoObject() == null ? "null" : "
" + escapeHTML(json(getInfoObject(), true)) + "
"); + + mediaFileTextField.setText(getMediaFile() == null ? "" : getMediaFile().getAbsolutePath()); + } + + public MediaBindingBean getSample() { + return sample; } public Object getInfoObject() { - return infoTextField.getClientProperty("model"); - } - - public void setMediaFile(File mediaFile) { - mediaFileTextField.setText(mediaFile == null ? "" : mediaFile.getAbsolutePath()); + return sample == null ? null : sample.getInfoObject(); } public File getMediaFile() { - // allow only absolute paths - String path = mediaFileTextField.getText().trim(); - if (path.length() > 0) { - File file = new File(mediaFileTextField.getText()); - if (file.isAbsolute()) { - return file; - } - } - return null; + return sample == null ? null : sample.getFileObject(); } protected final Action mediaInfoAction = new AbstractAction("Open MediaInfo", ResourceManager.getIcon("action.properties")) { @@ -315,17 +297,18 @@ class BindingDialog extends JDialog { @Override public void actionPerformed(ActionEvent evt) { ExtensionFileFilter mediaFiles = combineFilter(VIDEO_FILES, AUDIO_FILES, SUBTITLE_FILES); - List file = showLoadDialogSelectFiles(false, false, getMediaFile(), mediaFiles, (String) getValue(NAME), evt); + List selection = showLoadDialogSelectFiles(false, false, getMediaFile(), mediaFiles, (String) getValue(NAME), evt); - if (file.size() > 0) { + if (selection.size() > 0) { // update text field - mediaFileTextField.setText(file.get(0).getAbsolutePath()); + File file = selection.get(0).getAbsoluteFile(); + Object info = xattr.getMetaInfo(file); - // set info object from xattr if possible - Object object = xattr.getMetaInfo(file.get(0)); - if (object != null && infoObjectFormat.format(object) != null) { - setInfoObject(object); + if (info == null || infoObjectFormat.format(info) == null) { + info = getInfoObject(); } + + setSample(new MediaBindingBean(info, file)); } } }; diff --git a/source/net/filebot/ui/rename/BindingDialog.properties b/source/net/filebot/ui/rename/BindingDialog.properties index 3994eb23..062049b6 100644 --- a/source/net/filebot/ui/rename/BindingDialog.properties +++ b/source/net/filebot/ui/rename/BindingDialog.properties @@ -2,4 +2,4 @@ parameter.exclude: ^StreamKind|^UniqueID|^StreamOrder|^ID|Count$ # preview expressions (keys are tagged so they can be sorted alphabetically) -expressions: n, y, s, e, sxe, s00e00, t, d, startdate, absolute, es, e00, sy, sc, age, special, episode, series, primaryTitle, alias, movie, tmdbid, imdbid, pi, pn, lang, subt, plex, az, type, anime, regular, music, album, artist, albumArtist, actors, director, collection, genre, genres, languages, runtime, certification, rating, votes, vc, ac, cf, vf, hpi, af, channels, resolution, dim, bitdepth, ws, sdhd, source, tags, s3d, group, original, info, info.network, info.status, info.productionCompanies, info.productionCountries, info.certifications, info.certifications.DE, omdb.rating, omdb.votes, localize.German.name, localize.German.title, fn, ext, mediaType, mediaPath, file, file.name, folder, folder.name, mediaTitle, audioLanguages, textLanguages, duration, seconds, minutes, bytes, megabytes, gigabytes, crc32, media, media.overallBitRateString, video[0], video[0].codecID, video[0].frameRate, video[0].displayAspectRatioString, video[0].scanType, audio[0], audio[0].bitRateString, audio[0].language, audio, audio.language, text[0], text[0].codecInfo, text[0].language, text, text.language +expressions: n, y, s, e, sxe, s00e00, t, d, startdate, absolute, es, e00, sy, sc, di, dc, age, special, episode, series, primaryTitle, alias, movie, tmdbid, imdbid, pi, pn, lang, subt, plex, az, type, anime, regular, music, album, artist, albumArtist, actors, director, collection, genre, genres, languages, runtime, certification, rating, votes, vc, ac, cf, vf, hpi, af, channels, resolution, dim, bitdepth, ws, sdhd, source, tags, s3d, group, original, info, info.network, info.status, info.productionCompanies, info.productionCountries, info.certifications, info.certifications.DE, omdb.rating, omdb.votes, localize.German.name, localize.German.title, fn, ext, mediaType, mediaPath, file, file.name, folder, folder.name, mediaTitle, audioLanguages, textLanguages, duration, seconds, minutes, bytes, megabytes, gigabytes, crc32, media, media.overallBitRateString, video[0], video[0].codecID, video[0].frameRate, video[0].displayAspectRatioString, video[0].scanType, audio[0], audio[0].bitRateString, audio[0].language, audio, audio.language, text[0], text[0].codecInfo, text[0].language, text, text.language diff --git a/source/net/filebot/ui/rename/FormatDialog.java b/source/net/filebot/ui/rename/FormatDialog.java index d10ed94f..70b9c302 100644 --- a/source/net/filebot/ui/rename/FormatDialog.java +++ b/source/net/filebot/ui/rename/FormatDialog.java @@ -592,9 +592,7 @@ public class FormatDialog extends JDialog { @Override public void actionPerformed(ActionEvent evt) { BindingDialog dialog = new BindingDialog(getWindow(evt.getSource()), String.format("%s Bindings", mode), mode.getFormat(), !locked); - - dialog.setInfoObject(sample.getInfoObject()); - dialog.setMediaFile(sample.getFileObject()); + dialog.setSample(sample); // open dialog dialog.setLocationRelativeTo((Component) evt.getSource()); diff --git a/source/net/filebot/ui/rename/PresetEditor.java b/source/net/filebot/ui/rename/PresetEditor.java index 1e06cf41..038ffa31 100644 --- a/source/net/filebot/ui/rename/PresetEditor.java +++ b/source/net/filebot/ui/rename/PresetEditor.java @@ -344,8 +344,7 @@ public class PresetEditor extends JDialog { popup.add(newAction(f.getPath(), e -> { BindingDialog dialog = new BindingDialog(getWindow(evt.getSource()), "File Bindings", FormatDialog.Mode.File.getFormat(), false); dialog.setLocation(getOffsetLocation(getWindow(evt.getSource()))); - dialog.setInfoObject(f); - dialog.setMediaFile(f); + dialog.setSample(new MediaBindingBean(f, f)); dialog.setVisible(true); })); }