From 7ccee1a8655c3f68dd8ec2bd9ffe966bebb05bbf Mon Sep 17 00:00:00 2001 From: VKamyshniy Date: Wed, 8 Apr 2015 00:20:30 +0300 Subject: [PATCH] [Summary] Introducing save file dialog with custom file filters. Saving templates with the save dialog, which uses "*.template" filter. On Windows, fixing many little mistakes to make the open/save dialogs better complied with Windows conventions. [Review required] YPozdnyakov --- gtk2_ardour/ardour_ui.cc | 4 +- gtk2_ardour/open_file_dialog.h | 16 ++-- gtk2_ardour/open_file_dialog.mm | 110 ++++++++++++++++-------- gtk2_ardour/open_file_dialog_nix.cc | 6 ++ gtk2_ardour/open_file_dialog_windows.cc | 89 +++++++++++++++---- 5 files changed, 164 insertions(+), 61 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 761206a425..15b8088674 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -2618,7 +2619,8 @@ ARDOUR_UI::save_template () return; } - std::string template_path = ARDOUR::save_file_dialog(Config->get_default_session_parent_dir(),_("Save Template")); + std::string template_path = ARDOUR::save_file_dialog(boost::assign::list_of (ARDOUR::template_suffix + 1), + Config->get_default_session_parent_dir(),_("Save Template")); if (!template_path.empty()) { bool add_suffix = true; std::string basename = Glib::path_get_basename (template_path); diff --git a/gtk2_ardour/open_file_dialog.h b/gtk2_ardour/open_file_dialog.h index e7b6a904e6..947684a2c9 100644 --- a/gtk2_ardour/open_file_dialog.h +++ b/gtk2_ardour/open_file_dialog.h @@ -25,11 +25,17 @@ namespace ARDOUR { - std::string save_file_dialog (std::string initial_path = "", std::string title = _("Save")); - std::string save_as_file_dialog (std::string, std::string title, bool &); - std::string open_file_dialog (std::string initial_path = "", std::string title = _("Open")); - std::vector open_file_dialog (std::vector extensions, bool multi_selection, std::string initial_path = "", std::string title = _("Open")); - std::string choose_folder_dialog (std::string initial_path = "", std::string title = _("Choose Folder")); + std::string save_file_dialog (std::string initial_path = "", std::string title = _("Save")); + std::string save_file_dialog (std::vector extensions, + std::string initial_path = "", + std::string title = _("Save")); + std::string save_as_file_dialog (std::string, std::string title, bool &); + std::string open_file_dialog (std::string initial_path = "", std::string title = _("Open")); + std::vector open_file_dialog (std::vector extensions, + bool multi_selection, + std::string initial_path = "", + std::string title = _("Open")); + std::string choose_folder_dialog (std::string initial_path = "", std::string title = _("Choose Folder")); } #endif /* __gtk_ardour_open_file_dialog_h__ */ diff --git a/gtk2_ardour/open_file_dialog.mm b/gtk2_ardour/open_file_dialog.mm index 6c2055c6bc..8b6c21ae39 100644 --- a/gtk2_ardour/open_file_dialog.mm +++ b/gtk2_ardour/open_file_dialog.mm @@ -37,21 +37,21 @@ using namespace std; /* ====== "trampoline" functions to invoke Objective-C method ====== */ + std::string ARDOUR::open_file_dialog (std::string initial_path, std::string title) { - NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; + NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; - //NP: we should find some gentle way to do this - NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; - // Call the Objective-C method using Objective-C syntax - NSString *nsPath = [FileDialog class_open_file_dialog:nsTitle withArg2:nsDefaultPath]; - std::string stdPath = [nsPath UTF8String]; - - return stdPath; + //NP: we should find some gentle way to do this + NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; + // Call the Objective-C method using Objective-C syntax + NSString *nsPath = [FileDialog class_open_file_dialog:nsTitle withArg2:nsDefaultPath]; + std::string stdPath = [nsPath UTF8String]; + + return stdPath; } - std::vector ARDOUR::open_file_dialog (std::vector extensions, bool multi_selection, std::string initial_path, std::string title) { @@ -83,18 +83,44 @@ ARDOUR::open_file_dialog (std::vector extensions, bool multi_select } +std::string +ARDOUR::save_file_dialog (std::vector extensions, + std::string initial_path, + std::string title) +{ + NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; + + //NP: we should find some gentle way to do this + NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; + + id fileTypesArray = [NSMutableArray new]; + + for (std::vector::iterator it = extensions.begin(); it != extensions.end(); ++it) { + id nsstr = [NSString stringWithUTF8String:(*it).c_str()]; + [fileTypesArray addObject:nsstr]; + } + + // Call the Objective-C method using Objective-C syntax + NSString *nsPath = [FileDialog class_save_file_dialog:nsTitle withArg2:nsDefaultPath withArg3:fileTypesArray]; + std::string stdPath = [nsPath UTF8String]; + + return stdPath; +} + std::string ARDOUR::save_file_dialog (std::string initial_path, std::string title) { - NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; - - //NP: we should find some gentle way to do this - NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; - // Call the Objective-C method using Objective-C syntax - NSString *nsPath = [FileDialog class_save_file_dialog:nsTitle withArg2:nsDefaultPath]; - std::string stdPath = [nsPath UTF8String]; - - return stdPath; + NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; + + id fileTypesArray = [NSMutableArray new]; + + //NP: we should find some gentle way to do this + NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; + // Call the Objective-C method using Objective-C syntax + NSString *nsPath = [FileDialog class_save_file_dialog:nsTitle withArg2:nsDefaultPath withArg3:fileTypesArray]; + + std::string stdPath = [nsPath UTF8String]; + return stdPath; } std::string @@ -115,17 +141,18 @@ ARDOUR::save_as_file_dialog (std::string initial_path, std::string title, bool& std::string ARDOUR::choose_folder_dialog(std::string initial_path, std::string title) { - NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; - - //NP: we should find some gentle way to do this - NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; - // Call the Objective-C method using Objective-C syntax - NSString *nsPath = [FileDialog class_choose_folder_dialog:nsTitle withArg2:nsDefaultPath]; + NSString *nsTitle = [NSString stringWithUTF8String:title.c_str()]; + + //NP: we should find some gentle way to do this + NSString *nsDefaultPath = [NSString stringWithUTF8String:initial_path.c_str()]; + + // Call the Objective-C method using Objective-C syntax + NSString *nsPath = [FileDialog class_choose_folder_dialog:nsTitle withArg2:nsDefaultPath]; - std::string stdPath = [nsPath UTF8String]; + std::string stdPath = [nsPath UTF8String]; - return stdPath; - } + return stdPath; +} /* ====== Objective-C functions called from C++ functions ====== */ @@ -171,7 +198,10 @@ ARDOUR::choose_folder_dialog(std::string initial_path, std::string title) } /* On choose many files */ -+ (NSArray*) class_open_file_dialog:(NSString *)title withArg2:(NSString *)initial_path withArg3:(NSArray*) fileTypesArray withArg4:(bool) multiSelection ++ (NSArray*) class_open_file_dialog:(NSString *)title + withArg2:(NSString *)initial_path + withArg3:(NSArray*) fileTypesArray + withArg4:(bool) multiSelection { // Create a File Open Dialog class. NSOpenPanel* openDlg = [NSOpenPanel openPanel]; @@ -180,14 +210,15 @@ ARDOUR::choose_folder_dialog(std::string initial_path, std::string title) [openDlg setAllowedFileTypes:fileTypesArray]; [openDlg setAllowsMultipleSelection:multiSelection]; [openDlg setTitle:title]; - - NSFileManager *fm = [[NSFileManager alloc] init]; + + NSFileManager *fm = [[NSFileManager alloc] init]; BOOL isDir; BOOL exists = [fm fileExistsAtPath:initial_path isDirectory:&isDir]; - if(!exists) + if(!exists) { initial_path = NSHomeDirectory(); - + } + [openDlg setDirectoryURL : [NSURL fileURLWithPath:initial_path]]; // Display the dialog box. If the OK pressed, @@ -204,20 +235,27 @@ ARDOUR::choose_folder_dialog(std::string initial_path, std::string title) } /* On create new session */ -+ (NSString*) class_save_file_dialog:(NSString *)title withArg2:(NSString *)initial_path -{ ++ (NSString*) class_save_file_dialog:(NSString *)title + withArg2:(NSString *)initial_path + withArg3:(NSArray*) fileTypesArray +{ // Create a File Open Dialog class. NSSavePanel* saveDlg = [NSSavePanel savePanel]; [saveDlg setTitle:title]; [saveDlg setCanCreateDirectories:YES]; + + if ([fileTypesArray count]) { + [saveDlg setAllowedFileTypes:fileTypesArray]; + } NSFileManager *fm = [[NSFileManager alloc] init]; BOOL isDir; BOOL exists = [fm fileExistsAtPath:initial_path isDirectory:&isDir]; - if(!exists) + if(!exists) { initial_path = NSHomeDirectory(); - + } + [saveDlg setDirectoryURL : [NSURL fileURLWithPath:initial_path]]; // Display the dialog box. If the OK pressed, diff --git a/gtk2_ardour/open_file_dialog_nix.cc b/gtk2_ardour/open_file_dialog_nix.cc index 7d20de0a95..c457fd3fd2 100644 --- a/gtk2_ardour/open_file_dialog_nix.cc +++ b/gtk2_ardour/open_file_dialog_nix.cc @@ -41,6 +41,12 @@ ARDOUR::save_file_dialog (string /*initial_path*/, string title) return string(); } +std::string +ARDOUR::save_file_dialog (std::vector /* extensions */, std::string /* initial_path */, std::string /* title */) +{ + return string(); +} + string ARDOUR::open_file_dialog (string /*initial_path*/, string /*title*/) { diff --git a/gtk2_ardour/open_file_dialog_windows.cc b/gtk2_ardour/open_file_dialog_windows.cc index 309367f56b..9db7a4ca3d 100644 --- a/gtk2_ardour/open_file_dialog_windows.cc +++ b/gtk2_ardour/open_file_dialog_windows.cc @@ -41,12 +41,63 @@ ARDOUR::save_file_dialog (std::string initial_path, std::string title) ofn.lpstrFile = szFilePathName; // This will hold the file name ofn.nMaxFile = _MAX_PATH; ofn.lpstrTitle = title.c_str(); - ofn.Flags = OFN_OVERWRITEPROMPT; + ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER; // Check on valid path WIN32_FIND_DATA FindFileData; HANDLE handle = FindFirstFile(initial_path.c_str(), &FindFileData) ; - int found = (handle != INVALID_HANDLE_VALUE); + int found = (handle != INVALID_HANDLE_VALUE); + + // if path is valid + if (found) { + ofn.lpstrInitialDir = initial_path.c_str(); + } else { + initial_path = Glib::get_home_dir(); + ofn.lpstrInitialDir = initial_path.c_str(); + } + + // Run dialog + if (GetSaveFileName(&ofn)) { + return ofn.lpstrFile; + } + + return string(); +} + +std::string +ARDOUR::save_file_dialog (std::vector extensions, std::string initial_path, std::string title) +{ + TCHAR szFilePathName[_MAX_PATH] = ""; + OPENFILENAME ofn = {0}; + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.lpstrFile = szFilePathName; // This will hold the file name + ofn.nMaxFile = _MAX_PATH; + ofn.lpstrTitle = title.c_str(); + ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER; + + + // Create filter for required file types + std::string filter; + for (int i = 0; i < extensions.size(); ++i) { + filter += "*."+extensions[i]+";"; + } + + char c_filter[1 + filter.size() + 2]; + c_filter[0] = 0; + strcpy (c_filter + 1, filter.c_str ()); + c_filter[1 + filter.size() + 1] = '\0'; + + ofn.lpstrFilter = c_filter; + + if (!extensions.empty()) { + ofn.lpstrDefExt = extensions[0].c_str (); + } + + // Check on valid path + WIN32_FIND_DATA FindFileData; + HANDLE handle = FindFirstFile(initial_path.c_str(), &FindFileData) ; + int found = (handle != INVALID_HANDLE_VALUE); // if path is valid if (found) { @@ -73,13 +124,13 @@ ARDOUR::open_file_dialog (std::string initial_path, std::string title) ofn.lpstrFile = szFilePathName; // This will hold the file name ofn.nMaxFile = _MAX_PATH; ofn.lpstrTitle = title.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER; ofn.lpstrFilter = " \0*.ardour\0"; - + ofn.lpstrDefExt = "ardour"; // Check on valid path WIN32_FIND_DATA FindFileData; HANDLE handle = FindFirstFile(initial_path.c_str(), &FindFileData) ; - int found = (handle != INVALID_HANDLE_VALUE); + int found = (handle != INVALID_HANDLE_VALUE); // if path is valid if (found) { @@ -99,13 +150,15 @@ ARDOUR::open_file_dialog (std::string initial_path, std::string title) std::vector ARDOUR::open_file_dialog (std::vector extensions, bool multi_selection, std::string initial_path, std::string title) { - TCHAR szFilePathName[_MAX_PATH] = ""; + TCHAR szFilePathName[_MAX_PATH*100] = ""; OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(OPENFILENAME); ofn.lpstrFile = szFilePathName; // This will hold the file name - ofn.nMaxFile = _MAX_PATH; + ofn.nMaxFile = sizeof (szFilePathName); ofn.lpstrTitle = title.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER; + if (multi_selection) { ofn.Flags |= OFN_ALLOWMULTISELECT; } @@ -116,18 +169,21 @@ ARDOUR::open_file_dialog (std::vector extensions, bool multi_select filter += "*."+extensions[i]+";"; } - char c_filter[2+filter.size()+2]; - c_filter[0] = ' '; - c_filter[1] = '\0'; - strcpy (c_filter+2, filter.c_str ()); - c_filter[filter.size()+3] = '\0'; + char c_filter[1 + filter.size() + 2]; + c_filter[0] = 0; + strcpy (c_filter + 1, filter.c_str ()); + c_filter[1 + filter.size() + 1] = '\0'; ofn.lpstrFilter = c_filter; + if (!extensions.empty()) { + ofn.lpstrDefExt = extensions[0].c_str (); + } + // Check on valid path WIN32_FIND_DATA FindFileData; HANDLE handle = FindFirstFile(initial_path.c_str(), &FindFileData) ; - int found = (handle != INVALID_HANDLE_VALUE); + int found = (handle != INVALID_HANDLE_VALUE); // if path is valid if (found) { @@ -140,13 +196,10 @@ ARDOUR::open_file_dialog (std::vector extensions, bool multi_select std::vector file_pathes; if (GetOpenFileName(&ofn)) { - std::string directory_path = ofn.lpstrFile; std::string path; char* ptr = ofn.lpstrFile; - bool many_files = (ofn.lpstrFile [strlen (ofn.lpstrFile) + 1] != 0); - if (ofn.lpstrFile [strlen (ofn.lpstrFile) + 1] != 0) { // Many files for (char *current_name = ofn.lpstrFile + strlen (ofn.lpstrFile) + 1; *current_name; @@ -159,8 +212,6 @@ ARDOUR::open_file_dialog (std::vector extensions, bool multi_select } else { file_pathes.push_back (ofn.lpstrFile); // single file selected } - - return file_pathes; } return file_pathes;