Feature #486 : Save/Load bookmarks into files

This commit is contained in:
vsonnier 2018-01-06 10:22:14 +01:00
parent ada56440fc
commit d4251b41fb
4 changed files with 134 additions and 18 deletions

View File

@ -417,6 +417,10 @@ AppFrame::AppFrame() :
menu->Append(wxID_SAVEAS, "Save Session &As.."); menu->Append(wxID_SAVEAS, "Save Session &As..");
menu->AppendSeparator(); menu->AppendSeparator();
menu->Append(wxID_RESET, "&Reset Session"); menu->Append(wxID_RESET, "&Reset Session");
menu->AppendSeparator();
menu->Append(wxID_OPEN_BOOKMARK, "Open Bookmark");
menu->Append(wxID_SAVE_BOOKMARK, "Save Bookmark");
menu->Append(wxID_SAVEAS_BOOKMARK, "Save Bookmark As..");
#ifndef __APPLE__ #ifndef __APPLE__
menu->AppendSeparator(); menu->AppendSeparator();
@ -1121,6 +1125,7 @@ bool AppFrame::actionOnMenuReset(wxCommandEvent& event) {
SetTitle(CUBICSDR_TITLE); SetTitle(CUBICSDR_TITLE);
currentSessionFile = ""; currentSessionFile = "";
currentBookmarkFile = "";
bookmarkSplitter->Unsplit(bookmarkView); bookmarkSplitter->Unsplit(bookmarkView);
bookmarkSplitter->SplitVertically(bookmarkView, mainVisSplitter, wxGetApp().getConfig()->getBookmarkSplit()); bookmarkSplitter->SplitVertically(bookmarkView, mainVisSplitter, wxGetApp().getConfig()->getBookmarkSplit());
hideBookmarksItem->Check(false); hideBookmarksItem->Check(false);
@ -1401,6 +1406,77 @@ bool AppFrame::actionOnMenuLoadSave(wxCommandEvent& event) {
return true; return true;
} }
//save mecanic for bookmark files
else if (event.GetId() == wxID_SAVE_BOOKMARK) {
if (!currentBookmarkFile.empty()) {
wxGetApp().getBookmarkMgr().saveToFile(currentBookmarkFile, false, true);
}
else {
wxFileDialog saveFileDialog(this, _("Save XML Bookmark file"), "", "", "XML files (*.xml)|*.xml", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (saveFileDialog.ShowModal() == wxID_CANCEL) {
return true;
}
// Make sure the file name actually ends in .xml
std::string fileName = saveFileDialog.GetPath().ToStdString();
std::string lcFileName = fileName;
std::transform(lcFileName.begin(), lcFileName.end(), lcFileName.begin(), ::tolower);
if (lcFileName.find_last_of(".xml") != lcFileName.length() - 1) {
fileName.append(".xml");
}
wxGetApp().getBookmarkMgr().saveToFile(fileName, false, true);
currentBookmarkFile = fileName;
}
return true;
}
else if (event.GetId() == wxID_OPEN_BOOKMARK) {
wxFileDialog openFileDialog(this, _("Open XML Bookmark file"), "", "", "XML files (*.xml)|*.xml", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (openFileDialog.ShowModal() == wxID_CANCEL) {
return true;
}
if (wxGetApp().getBookmarkMgr().loadFromFile(openFileDialog.GetPath().ToStdString(), false, true)) {
wxGetApp().getBookmarkMgr().updateBookmarks();
wxGetApp().getBookmarkMgr().updateActiveList();
currentBookmarkFile = openFileDialog.GetPath().ToStdString();
}
else {
//failure at loading.
currentBookmarkFile = "";
}
return true;
}
else if (event.GetId() == wxID_SAVEAS_BOOKMARK) {
wxFileDialog saveFileDialog(this, _("Save XML Bookmark file"), "", "", "XML files (*.xml)|*.xml", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (saveFileDialog.ShowModal() == wxID_CANCEL) {
return true;
}
// Make sure the file name actually ends in .xml
std::string fileName = saveFileDialog.GetPath().ToStdString();
std::string lcFileName = fileName;
std::transform(lcFileName.begin(), lcFileName.end(), lcFileName.begin(), ::tolower);
if (lcFileName.find_last_of(".xml") != lcFileName.length() - 1) {
fileName.append(".xml");
}
wxGetApp().getBookmarkMgr().saveToFile(fileName, false, true);
currentBookmarkFile = fileName;
return true;
}
return false; return false;
} }
@ -2153,6 +2229,11 @@ bool AppFrame::loadSession(std::string fileName) {
return false; return false;
} }
//Check if it is a session file, read the root node.
if (l.rootNode()->getName() != "cubicsdr_session") {
return false;
}
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr, false); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr, false);
wxGetApp().getDemodMgr().terminateAll(); wxGetApp().getDemodMgr().terminateAll();

View File

@ -43,6 +43,10 @@
#define wxID_SET_DB_OFFSET 2012 #define wxID_SET_DB_OFFSET 2012
#define wxID_ABOUT_CUBICSDR 2013 #define wxID_ABOUT_CUBICSDR 2013
#define wxID_OPEN_BOOKMARK 2020
#define wxID_SAVE_BOOKMARK 2021
#define wxID_SAVEAS_BOOKMARK 2022
#define wxID_MAIN_SPLITTER 2050 #define wxID_MAIN_SPLITTER 2050
#define wxID_VIS_SPLITTER 2051 #define wxID_VIS_SPLITTER 2051
#define wxID_BM_SPLITTER 2052 #define wxID_BM_SPLITTER 2052
@ -229,6 +233,7 @@ private:
std::string currentTXantennaName; std::string currentTXantennaName;
std::string currentSessionFile; std::string currentSessionFile;
std::string currentBookmarkFile;
FFTVisualDataThread *waterfallDataThread; FFTVisualDataThread *waterfallDataThread;

View File

@ -18,7 +18,8 @@ BookmarkMgr::BookmarkMgr() {
//represents an empty BookMarkList that is returned by reference by some functions. //represents an empty BookMarkList that is returned by reference by some functions.
const BookmarkList BookmarkMgr::emptyResults; const BookmarkList BookmarkMgr::emptyResults;
void BookmarkMgr::saveToFile(std::string bookmarkFn, bool backup) { void BookmarkMgr::saveToFile(std::string bookmarkFn, bool backup, bool useFullpath) {
DataTree s("cubicsdr_bookmarks"); DataTree s("cubicsdr_bookmarks");
DataNode *header = s.rootNode()->newChild("header"); DataNode *header = s.rootNode()->newChild("header");
header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring()); header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring());
@ -62,8 +63,17 @@ void BookmarkMgr::saveToFile(std::string bookmarkFn, bool backup) {
recent_modems->newChildCloneFrom("modem", r_i->node); recent_modems->newChildCloneFrom("modem", r_i->node);
} }
wxFileName saveFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn); wxFileName saveFile;
wxFileName saveFileBackup(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup"); wxFileName saveFileBackup;
if (useFullpath) {
saveFile.Assign(bookmarkFn);
saveFileBackup.Assign(bookmarkFn + ".backup");
}
else {
saveFile.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn);
saveFileBackup.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup");
}
if (saveFile.IsDirWritable()) { if (saveFile.IsDirWritable()) {
// Hopefully leave at least a readable backup in case of failure.. // Hopefully leave at least a readable backup in case of failure..
@ -74,21 +84,29 @@ void BookmarkMgr::saveToFile(std::string bookmarkFn, bool backup) {
} }
} }
bool BookmarkMgr::loadFromFile(std::string bookmarkFn, bool backup) { bool BookmarkMgr::loadFromFile(std::string bookmarkFn, bool backup, bool useFullpath) {
wxFileName loadFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn);
wxFileName failFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".failedload"); wxFileName loadFile;
wxFileName lastLoaded(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".lastloaded"); wxFileName failFile;
wxFileName backupFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup"); wxFileName lastLoaded;
wxFileName backupFile;
if (useFullpath) {
loadFile.Assign(bookmarkFn);
failFile.Assign(bookmarkFn + ".failedload");
lastLoaded.Assign(bookmarkFn + ".lastloaded");
backupFile.Assign(bookmarkFn + ".backup");
}
else {
loadFile.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn);
failFile.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".failedload");
lastLoaded.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".lastloaded");
backupFile.Assign(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup");
}
DataTree s; DataTree s;
bool loadStatusOk = true; bool loadStatusOk = true;
// Clear any active data
bmData.clear();
clearRecents();
clearRanges();
bmDataSorted.clear();
// File exists but is not readable // File exists but is not readable
if (loadFile.FileExists() && !loadFile.IsFileReadable()) { if (loadFile.FileExists() && !loadFile.IsFileReadable()) {
return false; return false;
@ -105,6 +123,17 @@ bool BookmarkMgr::loadFromFile(std::string bookmarkFn, bool backup) {
return false; return false;
} }
//Check if it is a bookmark file, read the root node.
if (s.rootNode()->getName() != "cubicsdr_bookmarks") {
return false;
}
// Clear any active data
bmData.clear();
clearRecents();
clearRanges();
bmDataSorted.clear();
if (s.rootNode()->hasAnother("branches")) { if (s.rootNode()->hasAnother("branches")) {
DataNode *branches = s.rootNode()->getNext("branches"); DataNode *branches = s.rootNode()->getNext("branches");
int bActive = 1, bRange = 0, bBookmark = 1, bRecent = 1; int bActive = 1, bRange = 0, bBookmark = 1, bRecent = 1;

View File

@ -78,9 +78,10 @@ typedef std::map<std::string, bool> BookmarkExpandState;
class BookmarkMgr { class BookmarkMgr {
public: public:
BookmarkMgr(); BookmarkMgr();
//if useFullpath = false, use the application config dir.
void saveToFile(std::string bookmarkFn, bool backup = true); //else assume bookmarkFn is a full path and use it for location.
bool loadFromFile(std::string bookmarkFn, bool backup = true); void saveToFile(std::string bookmarkFn, bool backup = true, bool useFullpath = false);
bool loadFromFile(std::string bookmarkFn, bool backup = true, bool useFullpath = false);
bool hasLastLoad(std::string bookmarkFn); bool hasLastLoad(std::string bookmarkFn);
bool hasBackup(std::string bookmarkFn); bool hasBackup(std::string bookmarkFn);