| @@ -81,6 +81,8 @@ extern float frameRateLimit; | |||
| /** Interval between autosaves in seconds. */ | |||
| extern float autosaveInterval; | |||
| extern bool skipLoadOnLaunch; | |||
| extern std::string lastPatchDirectory; | |||
| extern std::string lastSelectionDirectory; | |||
| extern std::list<std::string> recentPatchPaths; | |||
| extern std::vector<NVGcolor> cableColors; | |||
| extern std::vector<std::string> cableLabels; | |||
| @@ -1094,25 +1094,33 @@ void RackWidget::loadSelection(std::string path) { | |||
| } | |||
| void RackWidget::loadSelectionDialog() { | |||
| std::string selectionDir = asset::user("selections"); | |||
| system::createDirectories(selectionDir); | |||
| std::string dir = settings::lastSelectionDirectory; | |||
| // Use fallback <Rack user dir>/selections | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("selections"); | |||
| system::createDirectory(dir); | |||
| } | |||
| osdialog_filters* filters = osdialog_filters_parse(SELECTION_FILTERS); | |||
| DEFER({osdialog_filters_free(filters);}); | |||
| char* pathC = osdialog_file(OSDIALOG_OPEN, selectionDir.c_str(), NULL, filters); | |||
| char* pathC = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, filters); | |||
| if (!pathC) { | |||
| // No path selected | |||
| // Cancel silently | |||
| return; | |||
| } | |||
| DEFER({std::free(pathC);}); | |||
| std::string path = pathC; | |||
| std::free(pathC); | |||
| try { | |||
| loadSelection(pathC); | |||
| loadSelection(path); | |||
| } | |||
| catch (Exception& e) { | |||
| osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, e.what()); | |||
| } | |||
| settings::lastSelectionDirectory = system::getDirectory(path); | |||
| } | |||
| void RackWidget::saveSelection(std::string path) { | |||
| @@ -1136,25 +1144,32 @@ void RackWidget::saveSelection(std::string path) { | |||
| } | |||
| void RackWidget::saveSelectionDialog() { | |||
| std::string selectionDir = asset::user("selections"); | |||
| system::createDirectories(selectionDir); | |||
| std::string dir = settings::lastSelectionDirectory; | |||
| // Use fallback <Rack user dir>/selections | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("selections"); | |||
| system::createDirectory(dir); | |||
| } | |||
| osdialog_filters* filters = osdialog_filters_parse(SELECTION_FILTERS); | |||
| DEFER({osdialog_filters_free(filters);}); | |||
| char* pathC = osdialog_file(OSDIALOG_SAVE, selectionDir.c_str(), "Untitled.vcvs", filters); | |||
| char* pathC = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcvs", filters); | |||
| if (!pathC) { | |||
| // No path selected | |||
| return; | |||
| } | |||
| DEFER({std::free(pathC);}); | |||
| std::string path = pathC; | |||
| std::free(pathC); | |||
| // Automatically append .vcvs extension | |||
| if (system::getExtension(path) != ".vcvs") | |||
| path += ".vcvs"; | |||
| saveSelection(path); | |||
| settings::lastSelectionDirectory = system::getDirectory(path); | |||
| } | |||
| void RackWidget::copyClipboardSelection() { | |||
| @@ -167,12 +167,18 @@ void Manager::saveAsDialog(bool setPath) { | |||
| filename = system::getFilename(this->path); | |||
| } | |||
| // Default to <Rack user dir>/patches | |||
| // Use fallback lastPatchDirectory | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("patches"); | |||
| system::createDirectories(dir); | |||
| dir = settings::lastPatchDirectory; | |||
| // Use fallback <Rack user dir>/patches | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("patches"); | |||
| system::createDirectory(dir); | |||
| } | |||
| } | |||
| // Use fallback filename | |||
| if (filename == "") { | |||
| filename = "Untitled.vcv"; | |||
| } | |||
| @@ -185,19 +191,14 @@ void Manager::saveAsDialog(bool setPath) { | |||
| // Cancel silently | |||
| return; | |||
| } | |||
| DEFER({std::free(pathC);}); | |||
| std::string path = pathC; | |||
| std::free(pathC); | |||
| // Automatically append .vcv extension | |||
| std::string path = pathC; | |||
| if (system::getExtension(path) != ".vcv") { | |||
| path += ".vcv"; | |||
| } | |||
| APP->history->setSaved(); | |||
| if (setPath) { | |||
| this->path = path; | |||
| } | |||
| try { | |||
| save(path); | |||
| } | |||
| @@ -207,7 +208,13 @@ void Manager::saveAsDialog(bool setPath) { | |||
| return; | |||
| } | |||
| pushRecentPath(path); | |||
| // Commit patch path | |||
| APP->history->setSaved(); | |||
| if (setPath) { | |||
| this->path = path; | |||
| settings::lastPatchDirectory = system::getDirectory(path); | |||
| pushRecentPath(path); | |||
| } | |||
| } | |||
| @@ -400,10 +407,15 @@ void Manager::loadDialog() { | |||
| dir = system::getDirectory(this->path); | |||
| } | |||
| // Default to <Rack user dir>/patches | |||
| // Use fallback lastPatchDirectory | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("patches"); | |||
| system::createDirectory(dir); | |||
| dir = settings::lastPatchDirectory; | |||
| // Use fallback <Rack user dir>/patches | |||
| if (dir == "" || !system::isDirectory(dir)) { | |||
| dir = asset::user("patches"); | |||
| system::createDirectory(dir); | |||
| } | |||
| } | |||
| osdialog_filters* filters = osdialog_filters_parse(PATCH_FILTERS); | |||
| @@ -411,7 +423,7 @@ void Manager::loadDialog() { | |||
| char* pathC = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, filters); | |||
| if (!pathC) { | |||
| // Fail silently | |||
| // Cancel silently | |||
| return; | |||
| } | |||
| std::string path = pathC; | |||
| @@ -55,6 +55,8 @@ bool preferDarkPanels = false; | |||
| #endif | |||
| float autosaveInterval = 15.0; | |||
| bool skipLoadOnLaunch = false; | |||
| std::string lastPatchDirectory; | |||
| std::string lastSelectionDirectory; | |||
| std::list<std::string> recentPatchPaths; | |||
| bool cableAutoRotate = true; | |||
| std::vector<NVGcolor> cableColors; | |||
| @@ -190,6 +192,10 @@ json_t* toJson() { | |||
| if (skipLoadOnLaunch) | |||
| json_object_set_new(rootJ, "skipLoadOnLaunch", json_boolean(true)); | |||
| json_object_set_new(rootJ, "lastPatchDirectory", json_stringn(lastPatchDirectory.c_str(), lastPatchDirectory.size())); | |||
| json_object_set_new(rootJ, "lastSelectionDirectory", json_stringn(lastSelectionDirectory.c_str(), lastSelectionDirectory.size())); | |||
| json_t* recentPatchPathsJ = json_array(); | |||
| for (const std::string& path : recentPatchPaths) { | |||
| json_array_append_new(recentPatchPathsJ, json_string(path.c_str())); | |||
| @@ -421,6 +427,14 @@ void fromJson(json_t* rootJ) { | |||
| if (skipLoadOnLaunchJ) | |||
| skipLoadOnLaunch = json_boolean_value(skipLoadOnLaunchJ); | |||
| json_t* lastPatchDirectoryJ = json_object_get(rootJ, "lastPatchDirectory"); | |||
| if (lastPatchDirectoryJ) | |||
| lastPatchDirectory = json_string_value(lastPatchDirectoryJ); | |||
| json_t* lastSelectionDirectoryJ = json_object_get(rootJ, "lastSelectionDirectory"); | |||
| if (lastSelectionDirectoryJ) | |||
| lastSelectionDirectory = json_string_value(lastSelectionDirectoryJ); | |||
| recentPatchPaths.clear(); | |||
| json_t* recentPatchPathsJ = json_object_get(rootJ, "recentPatchPaths"); | |||
| if (recentPatchPathsJ) { | |||