diff --git a/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/Info.plist b/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/Info.plist
new file mode 100644
index 00000000..09273694
--- /dev/null
+++ b/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/Info.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ AMFolderAction
+ AMAddingFolderItems
+
+
diff --git a/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/document.wflow b/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/document.wflow
new file mode 100644
index 00000000..c852b2aa
--- /dev/null
+++ b/installer/workflows/Folder Actions/Import Media Files with FileBot.workflow/Contents/document.wflow
@@ -0,0 +1,193 @@
+
+
+
+
+ AMApplicationBuild
+ 444.39
+ AMApplicationVersion
+ 2.9
+ AMDocumentVersion
+ 2
+ actions
+
+
+ action
+
+ AMAccepts
+
+ Container
+ List
+ Optional
+
+ Types
+
+ com.apple.cocoa.string
+
+
+ AMActionVersion
+ 2.0.3
+ AMApplication
+
+ Automator
+
+ AMParameterProperties
+
+ COMMAND_STRING
+
+ CheckedForUserDefaultShell
+
+ inputMethod
+
+ shell
+
+ source
+
+
+ AMProvides
+
+ Container
+ List
+ Types
+
+ com.apple.cocoa.string
+
+
+ ActionBundlePath
+ /System/Library/Automator/Run Shell Script.action
+ ActionName
+ Run Shell Script
+ ActionParameters
+
+ COMMAND_STRING
+ /usr/local/bin/filebot -script fn:amc --output "$HOME/Media" --action duplicate --conflict index -non-strict --log-file "$HOME/Media/.amc.log" --def excludeList=".amc.excludes" unsorted=y music=y artwork=y "$@" -exec open -R {f} +
+ CheckedForUserDefaultShell
+
+ inputMethod
+ 1
+ shell
+ /bin/bash
+ source
+
+
+ BundleIdentifier
+ com.apple.RunShellScript
+ CFBundleVersion
+ 2.0.3
+ CanShowSelectedItemsWhenRun
+
+ CanShowWhenRun
+
+ Category
+
+ AMCategoryUtilities
+
+ Class Name
+ RunShellScriptAction
+ InputUUID
+ 501F9637-7146-41E8-958D-E1FAB3C6DABC
+ Keywords
+
+ Shell
+ Script
+ Command
+ Run
+ Unix
+
+ OutputUUID
+ BE76312F-1956-431C-B21E-D5528ED97529
+ UUID
+ D7458846-B8ED-44A1-9E97-91736B192F85
+ UnlocalizedApplications
+
+ Automator
+
+ arguments
+
+ 0
+
+ default value
+ 0
+ name
+ inputMethod
+ required
+ 0
+ type
+ 0
+ uuid
+ 0
+
+ 1
+
+ default value
+
+ name
+ source
+ required
+ 0
+ type
+ 0
+ uuid
+ 1
+
+ 2
+
+ default value
+
+ name
+ CheckedForUserDefaultShell
+ required
+ 0
+ type
+ 0
+ uuid
+ 2
+
+ 3
+
+ default value
+
+ name
+ COMMAND_STRING
+ required
+ 0
+ type
+ 0
+ uuid
+ 3
+
+ 4
+
+ default value
+ /bin/sh
+ name
+ shell
+ required
+ 0
+ type
+ 0
+ uuid
+ 4
+
+
+ isViewVisible
+
+ location
+ 696.000000:252.000000
+ nibPath
+ /System/Library/Automator/Run Shell Script.action/Contents/Resources/Base.lproj/main.nib
+
+ isViewVisible
+
+
+
+ connectors
+
+ workflowMetaData
+
+ folderActionFolderPath
+ ~/Downloads
+ workflowTypeIdentifier
+ com.apple.Automator.folderAction
+
+
+
diff --git a/installer/workflows/Import Media Files with FileBot.workflow/Contents/Info.plist b/installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/Info.plist
similarity index 100%
rename from installer/workflows/Import Media Files with FileBot.workflow/Contents/Info.plist
rename to installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/Info.plist
diff --git a/installer/workflows/Import Media Files with FileBot.workflow/Contents/Resources/workflowCustomImage.icns b/installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/Resources/workflowCustomImage.icns
similarity index 100%
rename from installer/workflows/Import Media Files with FileBot.workflow/Contents/Resources/workflowCustomImage.icns
rename to installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/Resources/workflowCustomImage.icns
diff --git a/installer/workflows/Import Media Files with FileBot.workflow/Contents/document.wflow b/installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/document.wflow
similarity index 100%
rename from installer/workflows/Import Media Files with FileBot.workflow/Contents/document.wflow
rename to installer/workflows/Quick Actions/Import Media Files with FileBot.workflow/Contents/document.wflow
diff --git a/installer/workflows/Send to FileBot.workflow/Contents/Info.plist b/installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/Info.plist
similarity index 100%
rename from installer/workflows/Send to FileBot.workflow/Contents/Info.plist
rename to installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/Info.plist
diff --git a/installer/workflows/Send to FileBot.workflow/Contents/Resources/workflowCustomImage.icns b/installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/Resources/workflowCustomImage.icns
similarity index 100%
rename from installer/workflows/Send to FileBot.workflow/Contents/Resources/workflowCustomImage.icns
rename to installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/Resources/workflowCustomImage.icns
diff --git a/installer/workflows/Send to FileBot.workflow/Contents/document.wflow b/installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/document.wflow
similarity index 100%
rename from installer/workflows/Send to FileBot.workflow/Contents/document.wflow
rename to installer/workflows/Quick Actions/Send to FileBot.workflow/Contents/document.wflow
diff --git a/source/net/filebot/platform/mac/WorkflowMenu.java b/source/net/filebot/platform/mac/WorkflowMenu.java
new file mode 100644
index 00000000..bdbebe65
--- /dev/null
+++ b/source/net/filebot/platform/mac/WorkflowMenu.java
@@ -0,0 +1,64 @@
+package net.filebot.platform.mac;
+
+import static net.filebot.util.FileUtilities.*;
+import static net.filebot.util.ui.SwingUI.StandardFileAction.Verb.*;
+
+import java.io.File;
+import java.io.FileFilter;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+import net.filebot.util.FileUtilities.ExtensionFileFilter;
+import net.filebot.util.ui.SwingUI.DynamicMenu;
+import net.filebot.util.ui.SwingUI.StandardFileAction;
+
+public class WorkflowMenu extends DynamicMenu {
+
+ public static final FileFilter WORKFLOW = new ExtensionFileFilter("workflow");
+
+ public File templateFolder;
+ public File targetFolder;
+
+ public WorkflowMenu(String label, File templateFolder, File targetFolder) {
+ super(label);
+
+ this.templateFolder = templateFolder;
+ this.targetFolder = targetFolder;
+ }
+
+ @Override
+ protected void populate() {
+ for (File workflow : templateFolder.listFiles(WORKFLOW)) {
+ if (isInstalled(workflow)) {
+ add(createUninstallMenu(workflow));
+ } else {
+ add(createInstallMenu(workflow));
+ }
+ }
+ }
+
+ protected boolean isInstalled(File workflow) {
+ return new File(targetFolder, workflow.getName()).exists();
+ }
+
+ protected JMenuItem createInstallMenu(File workflow) {
+ JMenu menu = new JMenu(getNameWithoutExtension(workflow.getName()));
+
+ menu.add(new StandardFileAction("Install", workflow, OPEN));
+ menu.add(new StandardFileAction("Reveal", workflow, REVEAL));
+
+ return menu;
+ }
+
+ protected JMenuItem createUninstallMenu(File workflow) {
+ JMenu menu = new JMenu(getNameWithoutExtension(workflow.getName()));
+
+ menu.add(new StandardFileAction("Uninstall", workflow, TRASH));
+ menu.add(new StandardFileAction("Open", workflow, OPEN));
+ menu.add(new StandardFileAction("Reveal", workflow, REVEAL));
+
+ return menu;
+ }
+
+}
diff --git a/source/net/filebot/util/ui/SwingUI.java b/source/net/filebot/util/ui/SwingUI.java
index 3eefe662..ace025fc 100644
--- a/source/net/filebot/util/ui/SwingUI.java
+++ b/source/net/filebot/util/ui/SwingUI.java
@@ -26,6 +26,7 @@ import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
+import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
@@ -44,6 +45,7 @@ import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
+import javax.swing.JMenu;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
@@ -52,6 +54,8 @@ import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.text.JTextComponent;
@@ -410,6 +414,41 @@ public final class SwingUI {
}
}
+ public static class StandardFileAction extends AbstractAction {
+
+ public enum Verb {
+ OPEN, REVEAL, TRASH;
+ }
+
+ private File file;
+ private Verb verb;
+
+ public StandardFileAction(String label, File file, Verb verb) {
+ super(label);
+ this.file = file;
+ this.verb = verb;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent evt) {
+ try {
+ switch (verb) {
+ case OPEN:
+ Desktop.getDesktop().open(file);
+ break;
+ case REVEAL:
+ Desktop.getDesktop().browseFileDirectory(file);
+ break;
+ case TRASH:
+ Desktop.getDesktop().moveToTrash(file);
+ break;
+ }
+ } catch (Exception e) {
+ log.log(Level.SEVERE, e, cause(verb, e));
+ }
+ }
+ }
+
public static T onSecondaryLoop(BackgroundSupplier supplier) throws ExecutionException, InterruptedException {
// run spawn new EDT and block current EDT
SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
@@ -506,6 +545,32 @@ public final class SwingUI {
}
}
+ public static abstract class DynamicMenu extends JMenu implements MenuListener {
+
+ public DynamicMenu(String name) {
+ super(name);
+ addMenuListener(this);
+ }
+
+ protected abstract void populate();
+
+ @Override
+ public void menuSelected(MenuEvent e) {
+ removeAll();
+ populate();
+ }
+
+ @Override
+ public void menuDeselected(MenuEvent e) {
+
+ }
+
+ @Override
+ public void menuCanceled(MenuEvent e) {
+
+ }
+ }
+
/**
* When trying to drag a row of a multi-select JTable, it will start selecting rows instead of initiating a drag. This TableUI will give the JTable proper dnd behaviour.
*/