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