From 20aef4e385c6a9a43e166bbf685381c233303ef1 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Sun, 29 Sep 2013 19:46:41 +0000 Subject: [PATCH] * more messages to help users know what to do next if they're just clicking around trying to figure out things work --- .../filebot/ui/rename/RenamePanel.java | 247 ++++++++---------- website/data/release-groups.txt | 2 + website/reviews.json | 5 + 3 files changed, 122 insertions(+), 132 deletions(-) diff --git a/source/net/sourceforge/filebot/ui/rename/RenamePanel.java b/source/net/sourceforge/filebot/ui/rename/RenamePanel.java index d029477b..8b241e90 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenamePanel.java +++ b/source/net/sourceforge/filebot/ui/rename/RenamePanel.java @@ -1,7 +1,5 @@ - package net.sourceforge.filebot.ui.rename; - import static javax.swing.JOptionPane.*; import static javax.swing.SwingUtilities.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; @@ -71,71 +69,69 @@ import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.ListSelection; import ca.odell.glazedlists.swing.EventSelectionModel; - public class RenamePanel extends JComponent { - + protected final RenameModel renameModel = new RenameModel(); - + protected final RenameList namesList = new RenameList(renameModel.names()); - + protected final RenameList filesList = new RenameList(renameModel.files()); - + protected final MatchAction matchAction = new MatchAction(renameModel); - + protected final RenameAction renameAction = new RenameAction(renameModel); - + 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 persistentPreferredLanguage = Settings.forPackage(RenamePanel.class).entry("rename.language").defaultValue("en"); private static final PreferencesEntry persistentPreferredEpisodeOrder = Settings.forPackage(RenamePanel.class).entry("rename.episode.order").defaultValue("Airdate"); - - + public RenamePanel() { namesList.setTitle("New Names"); namesList.setTransferablePolicy(new NamesListTransferablePolicy(renameModel.values())); - + 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 } - + try { // restore custom movie formatter renameModel.useFormatter(Movie.class, new ExpressionFormatter(persistentMovieFormat.getValue(), MovieFormat.NameYear, Movie.class)); } catch (Exception e) { // illegal format, ignore } - + RenameListCellRenderer cellrenderer = new RenameListCellRenderer(renameModel); - + namesList.getListComponent().setCellRenderer(cellrenderer); filesList.getListComponent().setCellRenderer(cellrenderer); - + EventSelectionModel> selectionModel = new EventSelectionModel>(renameModel.matches()); selectionModel.setSelectionMode(ListSelection.SINGLE_SELECTION); - + // use the same selection model for both lists to synchronize selection namesList.getListComponent().setSelectionModel(selectionModel); filesList.getListComponent().setSelectionModel(selectionModel); - + // synchronize viewports new ScrollPaneSynchronizer(namesList, filesList); - + // delete items from both lists Action removeAction = new AbstractAction("Remove") { - + @Override public void actionPerformed(ActionEvent e) { JList list = ((RenameList) e.getSource()).getListComponent(); @@ -161,28 +157,29 @@ public class RenamePanel extends JComponent { }; namesList.setRemoveAction(removeAction); filesList.setRemoveAction(removeAction); - + // create Match button JButton matchButton = new JButton(matchAction); matchButton.setVerticalTextPosition(SwingConstants.BOTTOM); matchButton.setHorizontalTextPosition(SwingConstants.CENTER); - + // create Rename button JButton renameButton = new JButton(renameAction); renameButton.setVerticalTextPosition(SwingConstants.BOTTOM); renameButton.setHorizontalTextPosition(SwingConstants.CENTER); - + // create fetch popup ActionPopup fetchPopup = createFetchPopup(); - + final Action fetchPopupAction = new ShowPopupAction("Fetch", ResourceManager.getIcon("action.fetch")); - JButton fetchButton = createImageButton(fetchPopupAction); + JButton fetchButton = new JButton(fetchPopupAction); + filesList.getListComponent().setComponentPopupMenu(fetchPopup); namesList.getListComponent().setComponentPopupMenu(fetchPopup); fetchButton.setComponentPopupMenu(fetchPopup); matchButton.setComponentPopupMenu(fetchPopup); namesList.getButtonPanel().add(fetchButton, "gap 0"); matchButton.addActionListener(new ActionListener() { - + @Override public void actionPerformed(ActionEvent e) { // show popup on actionPerformed only when names list is empty @@ -191,10 +188,10 @@ public class RenamePanel extends JComponent { } } }); - + namesList.getListComponent().setComponentPopupMenu(fetchPopup); fetchButton.setComponentPopupMenu(fetchPopup); - + // settings popup and button ActionPopup settingsPopup = createSettingsPopup(); final Action settingsPopupAction = new ShowPopupAction("Settings", ResourceManager.getIcon("action.settings")); @@ -202,14 +199,14 @@ public class RenamePanel extends JComponent { settingsButton.setComponentPopupMenu(settingsPopup); renameButton.setComponentPopupMenu(settingsPopup); namesList.getButtonPanel().add(settingsButton, "gap indent"); - + // open rename log button - filesList.getButtonPanel().add(createImageButton(clearFilesAction), "gap 0"); + filesList.getButtonPanel().add(new JButton(clearFilesAction), "gap 0"); filesList.getButtonPanel().add(createImageButton(openHistoryAction), "gap indent"); - + // reveal file location on double click filesList.getListComponent().addMouseListener(new MouseAdapter() { - + @Override public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() == 2) { @@ -228,10 +225,10 @@ public class RenamePanel extends JComponent { } } }); - + // reveal file location on double click namesList.getListComponent().addMouseListener(new MouseAdapter() { - + @Override public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() == 2) { @@ -257,85 +254,84 @@ public class RenamePanel extends JComponent { } } }); - + setLayout(new MigLayout("fill, insets dialog, gapx 10px", "[fill][align center, pref!][fill]", "align 33%")); add(filesList, "grow, sizegroupx list"); - + // make buttons larger matchButton.setMargin(new Insets(3, 14, 2, 14)); renameButton.setMargin(new Insets(6, 11, 2, 11)); - + add(matchButton, "split 2, flowy, sizegroupx button"); add(renameButton, "gapy 30px, sizegroupx button"); - + add(new LoadingOverlayPane(namesList, namesList, "32px", "30px"), "grow, sizegroupx list"); } - - + protected ActionPopup createFetchPopup() { final ActionPopup actionPopup = new ActionPopup("Series / Movie Data", ResourceManager.getIcon("action.fetch")); - + actionPopup.addDescription(new JLabel("Episode Mode:")); - + // create actions for match popup episode list completion for (EpisodeListProvider provider : WebServices.getEpisodeListProviders()) { actionPopup.add(new AutoCompleteAction(provider.getName(), provider.getIcon(), new EpisodeListMatcher(provider))); } - + actionPopup.addSeparator(); actionPopup.addDescription(new JLabel("Movie Mode:")); - + // create action for movie name completion for (MovieIdentificationService it : WebServices.getMovieIdentificationServices()) { actionPopup.add(new AutoCompleteAction(it.getName(), it.getIcon(), new MovieHashMatcher(it))); } - + actionPopup.addSeparator(); actionPopup.addDescription(new JLabel("Music Mode:")); actionPopup.add(new AutoCompleteAction(WebServices.AcoustID.getName(), WebServices.AcoustID.getIcon(), new AudioFingerprintMatcher(WebServices.AcoustID))); - + actionPopup.addSeparator(); actionPopup.addDescription(new JLabel("Options:")); - + actionPopup.add(new AbstractAction("Edit Format", ResourceManager.getIcon("action.format")) { - + @Override public void actionPerformed(ActionEvent evt) { FormatDialog dialog = new FormatDialog(getWindowAncestor(RenamePanel.this)); dialog.setLocation(getOffsetLocation(dialog.getOwner())); dialog.setVisible(true); - + if (dialog.submit()) { switch (dialog.getMode()) { - case Episode: - renameModel.useFormatter(Episode.class, new ExpressionFormatter(dialog.getFormat().getExpression(), EpisodeFormat.SeasonEpisode, Episode.class)); - persistentEpisodeFormat.setValue(dialog.getFormat().getExpression()); - break; - case Movie: - renameModel.useFormatter(Movie.class, new ExpressionFormatter(dialog.getFormat().getExpression(), MovieFormat.NameYear, Movie.class)); - persistentMovieFormat.setValue(dialog.getFormat().getExpression()); - break; - case Music: - renameModel.useFormatter(AudioTrack.class, new ExpressionFormatter(dialog.getFormat().getExpression(), new AudioTrackFormat(), AudioTrack.class)); - persistentMusicFormat.setValue(dialog.getFormat().getExpression()); - break; + case Episode: + renameModel.useFormatter(Episode.class, new ExpressionFormatter(dialog.getFormat().getExpression(), EpisodeFormat.SeasonEpisode, Episode.class)); + persistentEpisodeFormat.setValue(dialog.getFormat().getExpression()); + break; + case Movie: + renameModel.useFormatter(Movie.class, new ExpressionFormatter(dialog.getFormat().getExpression(), MovieFormat.NameYear, Movie.class)); + persistentMovieFormat.setValue(dialog.getFormat().getExpression()); + break; + case Music: + renameModel.useFormatter(AudioTrack.class, new ExpressionFormatter(dialog.getFormat().getExpression(), new AudioTrackFormat(), AudioTrack.class)); + persistentMusicFormat.setValue(dialog.getFormat().getExpression()); + break; } } } }); - + actionPopup.add(new AbstractAction("Preferences", ResourceManager.getIcon("action.preferences")) { - + @Override public void actionPerformed(ActionEvent evt) { List languages = new ArrayList(); languages.addAll(Language.preferredLanguages()); // add preferred languages first languages.addAll(Language.availableLanguages()); // then others - + JComboBox orderCombo = new JComboBox(SortOrder.values()); JList languageList = new JList(languages.toArray()); languageList.setCellRenderer(new DefaultListCellRenderer() { - + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); @@ -345,7 +341,7 @@ public class RenamePanel extends JComponent { return this; } }); - + // pre-select current preferences try { orderCombo.setSelectedItem(SortOrder.forName(persistentPreferredEpisodeOrder.getValue())); @@ -358,48 +354,47 @@ public class RenamePanel extends JComponent { break; } } - + JScrollPane spLanguageList = new JScrollPane(languageList); spLanguageList.setBorder(new CompoundBorder(new TitledBorder("Preferred Language"), spLanguageList.getBorder())); JScrollPane spOrderCombo = new JScrollPane(orderCombo, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); spOrderCombo.setBorder(new CompoundBorder(new TitledBorder("Preferred Episode Order"), spOrderCombo.getBorder())); - + JPanel message = new JPanel(new MigLayout("fill, flowy, insets 0")); message.add(spLanguageList, "grow"); message.add(spOrderCombo, "grow, hmin 24px"); JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, OK_CANCEL_OPTION); pane.createDialog(getWindowAncestor(RenamePanel.this), "Preferences").setVisible(true); - + if (pane.getValue() != null && pane.getValue().equals(OK_OPTION)) { persistentPreferredLanguage.setValue(((Language) languageList.getSelectedValue()).getCode()); persistentPreferredEpisodeOrder.setValue(((SortOrder) orderCombo.getSelectedItem()).name()); } } }); - + return actionPopup; } - - + protected ActionPopup createSettingsPopup() { ActionPopup actionPopup = new ActionPopup("Rename Options", ResourceManager.getIcon("action.settings")); - + actionPopup.addDescription(new JLabel("Extension:")); actionPopup.add(new SetRenameMode(false, "Preserve", ResourceManager.getIcon("action.extension.preserve"))); actionPopup.add(new SetRenameMode(true, "Override", ResourceManager.getIcon("action.extension.override"))); - + actionPopup.addSeparator(); - + actionPopup.addDescription(new JLabel("Action:")); for (StandardRenameAction action : EnumSet.of(StandardRenameAction.MOVE, StandardRenameAction.COPY, StandardRenameAction.KEEPLINK, StandardRenameAction.SYMLINK, StandardRenameAction.HARDLINK)) { actionPopup.add(new SetRenameAction(action, action.getDisplayName(), ResourceManager.getIcon("rename.action." + action.toString().toLowerCase()))); } - + return actionPopup; } - - protected final Action clearFilesAction = new AbstractAction("Clear Files", ResourceManager.getIcon("action.clear")) { - + + protected final Action clearFilesAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) { + @Override public void actionPerformed(ActionEvent evt) { if (isShiftOrAltDown(evt)) { @@ -409,18 +404,18 @@ public class RenamePanel extends JComponent { } } }; - + protected final Action openHistoryAction = new AbstractAction("Open History", ResourceManager.getIcon("action.report")) { - + @Override public void actionPerformed(ActionEvent evt) { try { History model = HistorySpooler.getInstance().getCompleteHistory(); - + HistoryDialog dialog = new HistoryDialog(getWindow(RenamePanel.this)); dialog.setLocationRelativeTo(RenamePanel.this); dialog.setModel(model); - + // show and block dialog.setVisible(true); } catch (Exception e) { @@ -428,15 +423,13 @@ public class RenamePanel extends JComponent { } } }; - - + protected static class ShowPopupAction extends AbstractAction { - + public ShowPopupAction(String name, Icon icon) { super(name, icon); } - - + @Override public void actionPerformed(ActionEvent e) { // display popup below component @@ -444,43 +437,37 @@ public class RenamePanel extends JComponent { source.getComponentPopupMenu().show(source, -3, source.getHeight() + 4); } }; - - + protected class SetRenameMode extends AbstractAction { - + private final boolean activate; - - + private SetRenameMode(boolean activate, String name, Icon icon) { super(name, icon); this.activate = activate; } - - + @Override public void actionPerformed(ActionEvent evt) { renameModel.setPreserveExtension(!activate); - + // use different file name formatter renameModel.useFormatter(File.class, new FileNameFormatter(renameModel.preserveExtension())); - + // display changed state filesList.repaint(); } } - - + protected class SetRenameAction extends AbstractAction { - + private final StandardRenameAction action; - - + public SetRenameAction(StandardRenameAction action, String name, Icon icon) { super(name, icon); this.action = action; } - - + @Override public void actionPerformed(ActionEvent evt) { if (action == StandardRenameAction.MOVE) { @@ -492,21 +479,19 @@ public class RenamePanel extends JComponent { } } } - - + protected class AutoCompleteAction extends AbstractAction { - + private final AutoCompleteMatcher matcher; - - + public AutoCompleteAction(String name, Icon icon, AutoCompleteMatcher matcher) { super(name, icon); - + this.matcher = matcher; - + // disable action while episode list matcher is working namesList.addPropertyChangeListener(LOADING_PROPERTY, new PropertyChangeListener() { - + @Override public void propertyChange(PropertyChangeEvent evt) { // disable action while loading is in progress @@ -514,50 +499,48 @@ public class RenamePanel extends JComponent { } }); } - - + @Override public void actionPerformed(final ActionEvent evt) { if (renameModel.files().isEmpty()) { + UILogger.info("Original Files is empty. Please add some files first."); return; } - + // clear names list renameModel.values().clear(); - + SwingWorker>, Void> worker = new SwingWorker>, Void>() { - + private final List remainingFiles = new LinkedList(renameModel.files()); private final SortOrder order = SortOrder.forName(persistentPreferredEpisodeOrder.getValue()); private final Locale locale = new Locale(persistentPreferredLanguage.getValue()); private final boolean autodetection = !isShiftOrAltDown(evt); // skip name auto-detection if SHIFT is pressed - - + @Override protected List> doInBackground() throws Exception { List> matches = matcher.match(remainingFiles, order, locale, autodetection, getWindow(RenamePanel.this)); - + // remove matched files for (Match match : matches) { remainingFiles.remove(match.getValue()); } - + return matches; } - - + @Override protected void done() { try { List> matches = new ArrayList>(); - + for (Match match : get()) { matches.add(new Match(match.getCandidate(), match.getValue())); } - + renameModel.clear(); renameModel.addAll(matches); - + // add remaining file entries renameModel.files().addAll(remainingFiles); } catch (Exception e) { @@ -568,12 +551,12 @@ public class RenamePanel extends JComponent { } } }; - + // auto-match in progress namesList.firePropertyChange(LOADING_PROPERTY, false, true); - + worker.execute(); } } - + } diff --git a/website/data/release-groups.txt b/website/data/release-groups.txt index 01c585d2..7de413fe 100644 --- a/website/data/release-groups.txt +++ b/website/data/release-groups.txt @@ -1120,6 +1120,7 @@ iNSECTS iNSOMNi iNSPiRED InSubs +iNT-TD IntelliQ iNTERNAL iNTiMiD @@ -2366,6 +2367,7 @@ zomg Zomg-Killerhurtalot Zorori-Project Zox +ZSiSO Zurako Zuzuu ZZGtv diff --git a/website/reviews.json b/website/reviews.json index 64618adb..82021f52 100644 --- a/website/reviews.json +++ b/website/reviews.json @@ -78,5 +78,10 @@ "user": "Raydan", "date": "2013-09-08", "text": "I can really recommend using filebot for sorting, moving, deleting, subtitle searching... I just started the script once... and it was quite mindblowing to be honest." + }, + { + "user": "Nitish Kumar", + "date": "2013-09-21", + "text": "FileBot is such an amazing piece of work. Been using it for TV Shows renaming but today tried over movies as well. Big time success!" } ] \ No newline at end of file