diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs new file mode 100644 index 000000000..7806debe1 --- /dev/null +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -0,0 +1,30 @@ +using Flow.Launcher.Plugin; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Flow.Launcher.ViewModel +{ + public class CustomExplorerViewModel : BaseModel + { + public string Name { get; set; } + public string Path { get; set; } + public string FileArgument { get; set; } = "\"%d\""; + public string DirectoryArgument { get; set; } = "\"%d\""; + public bool Editable { get; init; } = true; + + public CustomExplorerViewModel Copy() + { + return new CustomExplorerViewModel + { + Name = Name, + Path = Path, + FileArgument = FileArgument, + DirectoryArgument = DirectoryArgument, + Editable = Editable + }; + } + } +} diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index d0351af51..1cb65fb85 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Text.Json.Serialization; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.Infrastructure.UserSettings { @@ -37,6 +39,49 @@ namespace Flow.Launcher.Infrastructure.UserSettings public string ResultFontStretch { get; set; } public bool UseGlyphIcons { get; set; } = true; + public int CustomExplorerIndex { get; set; } = 0; + + [JsonIgnore] + public CustomExplorerViewModel CustomExplorer + { + get => CustomExplorerList[CustomExplorerIndex < CustomExplorerList.Count ? CustomExplorerIndex : 0]; + set => CustomExplorerList[CustomExplorerIndex] = value; + } + + public List CustomExplorerList { get; set; } = new() + { + new() + { + Name = "Explorer", + Path = "explorer", + DirectoryArgument = "\"%d\"", + FileArgument = "/select, \"%f\"", + Editable = false + }, + new() + { + Name = "Total Commander", + Path = @"C:\Program Files\totalcmd\TOTALCMD64.exe", + DirectoryArgument = "/O /A /S /T \"%d\"", + FileArgument = "/O /A /S /T \"%f\"" + }, + new() + { + Name = "Directory Opus", + Path = @"C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe", + DirectoryArgument = "/cmd Go \"%d\" NEW", + FileArgument = "/cmd Go \"%f\" NEW" + + }, + new() + { + Name = "Files", + Path = "Files", + DirectoryArgument = "-select \"%d\"", + FileArgument = "-select \"%f\"" + } + }; + public bool UseAnimation { get; set; } = true; public bool UseSound { get; set; } = false; diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 974eafa96..3abdaf01f 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -190,5 +190,12 @@ namespace Flow.Launcher.Plugin /// Type for Serialization /// void SaveSettingJsonStorage() where T : new(); + + /// + /// Open directory in an explorer configured by user via Flow's Settings. The default is Windows Explorer + /// + /// Directory Path to open + /// Extra FileName Info + public void OpenDirectory(string DirectoryPath, string FileName = null); } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 416773c54..d9775d8b1 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -34,6 +34,8 @@ Maximum results shown Ignore hotkeys in fullscreen mode Disable Flow Launcher activation when a full screen application is active (Recommended for games). + Default File Manager + Select the file manager to use when opening the folder. Python Directory Auto Update Select @@ -138,6 +140,16 @@ Release Notes Usage Tips: + + Select File Manager + Please specify the file location of the file manager you using and add arguments if necessary. The default arguments is "%d", and a path is entered at that location. For example, If a command is required such as "totalcmd.exe /A c:\windows", argument is /A "%d". + "%f" is an argument that represent the file path. It is used to emphasize the file/folder name when opening a specific file location in 3rd party file manager. This argument is only available in the "Arg for File" item. If the file manager does not have that function, you can use "%d". + File Manager + Profile Name + File Manager Path + Arg For Folder + Arg For File + Change Priority Greater the number, the higher the result will be ranked. Try setting it as 5. If you want the results to be lower than any other plugin's, provide a negative number diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 71f6f1be4..e90a53fc3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -22,6 +22,8 @@ using System.Runtime.CompilerServices; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using System.Collections.Concurrent; +using Flow.Launcher.Plugin.SharedCommands; +using System.Diagnostics; namespace Flow.Launcher { @@ -158,7 +160,7 @@ namespace Flow.Launcher if (!_pluginJsonStorages.ContainsKey(type)) _pluginJsonStorages[type] = new PluginJsonStorage(); - return ((PluginJsonStorage) _pluginJsonStorages[type]).Load(); + return ((PluginJsonStorage)_pluginJsonStorages[type]).Load(); } public void SaveSettingJsonStorage() where T : new() @@ -167,7 +169,7 @@ namespace Flow.Launcher if (!_pluginJsonStorages.ContainsKey(type)) _pluginJsonStorages[type] = new PluginJsonStorage(); - ((PluginJsonStorage) _pluginJsonStorages[type]).Save(); + ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } public void SaveJsonStorage(T settings) where T : new() @@ -175,7 +177,22 @@ namespace Flow.Launcher var type = typeof(T); _pluginJsonStorages[type] = new PluginJsonStorage(settings); - ((PluginJsonStorage) _pluginJsonStorages[type]).Save(); + ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); + } + + public void OpenDirectory(string DirectoryPath, string FileName = null) + { + using Process explorer = new Process(); + var explorerInfo = _settingsVM.Settings.CustomExplorer; + explorer.StartInfo = new ProcessStartInfo + { + FileName = explorerInfo.Path, + Arguments = FileName is null ? + explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) : + explorerInfo.FileArgument.Replace("%d", DirectoryPath).Replace("%f", + Path.IsPathRooted(FileName) ? FileName : Path.Combine(DirectoryPath, FileName)) + }; + explorer.Start(); } public event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent; @@ -188,7 +205,7 @@ namespace Flow.Launcher { if (GlobalKeyboardEvent != null) { - return GlobalKeyboardEvent((int) keyevent, vkcode, state); + return GlobalKeyboardEvent((int)keyevent, vkcode, state); } return true; diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml b/Flow.Launcher/SelectFileManagerWindow.xaml new file mode 100644 index 000000000..eba794c96 --- /dev/null +++ b/Flow.Launcher/SelectFileManagerWindow.xaml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml.cs b/Flow.Launcher/SelectFileManagerWindow.xaml.cs new file mode 100644 index 000000000..4f6fb3439 --- /dev/null +++ b/Flow.Launcher/SelectFileManagerWindow.xaml.cs @@ -0,0 +1,88 @@ +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.ViewModel; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Flow.Launcher +{ + public partial class SelectFileManagerWindow : Window, INotifyPropertyChanged + { + private int selectedCustomExplorerIndex; + + public event PropertyChangedEventHandler PropertyChanged; + + public Settings Settings { get; } + + public int SelectedCustomExplorerIndex + { + get => selectedCustomExplorerIndex; set + { + selectedCustomExplorerIndex = value; + PropertyChanged?.Invoke(this, new(nameof(CustomExplorer))); + } + } + public ObservableCollection CustomExplorers { get; set; } + + public CustomExplorerViewModel CustomExplorer => CustomExplorers[SelectedCustomExplorerIndex]; + public SelectFileManagerWindow(Settings settings) + { + Settings = settings; + CustomExplorers = new ObservableCollection(Settings.CustomExplorerList.Select(x => x.Copy())); + SelectedCustomExplorerIndex = Settings.CustomExplorerIndex; + InitializeComponent(); + } + + private void btnCancel_Click(object sender, RoutedEventArgs e) + { + Close(); + } + + private void btnDone_Click(object sender, RoutedEventArgs e) + { + Settings.CustomExplorerList = CustomExplorers.ToList(); + Settings.CustomExplorerIndex = SelectedCustomExplorerIndex; + Close(); + } + + private void btnAdd_Click(object sender, RoutedEventArgs e) + { + CustomExplorers.Add(new() + { + Name = "New Profile" + }); + SelectedCustomExplorerIndex = CustomExplorers.Count - 1; + } + + private void btnDelete_Click(object sender, RoutedEventArgs e) + { + CustomExplorers.RemoveAt(SelectedCustomExplorerIndex--); + } + + private void btnBrowseFile_Click(object sender, RoutedEventArgs e) + { + Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); + Nullable result = dlg.ShowDialog(); + + if (result == true) + { + TextBox path = (TextBox)(((FrameworkElement)sender).Parent as FrameworkElement).FindName("PathTextBox"); + path.Text = dlg.FileName; + path.Focus(); + ((Button)sender).Focus(); + } + } + } +} diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 550b3e85d..fe68650d0 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -688,6 +688,35 @@ + + + + + + + +