diff --git a/src/BookmarkMgr.cpp b/src/BookmarkMgr.cpp index 4b4f172..0fedc23 100644 --- a/src/BookmarkMgr.cpp +++ b/src/BookmarkMgr.cpp @@ -14,16 +14,11 @@ void BookmarkMgr::loadFromFile(std::string bookmarkFn) { } -void BookmarkMgr::addBookmark(std::string group, DemodulatorInstance *demod, std::string folder) { + +void BookmarkMgr::addBookmark(std::string group, DemodulatorInstance *demod) { std::lock_guard < std::mutex > lock(busy_lock); - BookmarkEntry *be = new BookmarkEntry; - - be->bandwidth = demod->getBandwidth(); - be->type = demod->getDemodulatorType(); - be->label = demod->getLabel(); - be->frequency = demod->getFrequency(); - be->folder = folder; + BookmarkEntry *be = demodToBookmarkEntry(demod); wxGetApp().getDemodMgr().saveInstance(be->node, demod); @@ -38,22 +33,13 @@ void BookmarkMgr::removeBookmark(std::string group, BookmarkEntry *be) { } -BookmarkList BookmarkMgr::getBookmarks(std::string group, std::string folder) { +BookmarkList BookmarkMgr::getBookmarks(std::string group) { std::lock_guard < std::mutex > lock(busy_lock); BookmarkList results; - if (folder != "") { - for (auto be_i : bmData[group]) { - results.push_back(be_i); - } - } else { - for (auto be_i : bmData[group]) { - if (be_i->folder != folder) { - continue; - } - results.push_back(be_i); - } + for (auto be_i : bmData[group]) { + results.push_back(be_i); } return results; @@ -78,4 +64,33 @@ void BookmarkMgr::updateActiveList() { if (bmv) { bmv->updateActiveList(); } -} \ No newline at end of file +} + +void BookmarkMgr::addRecent(DemodulatorInstance *demod) { + std::lock_guard < std::mutex > lock(busy_lock); + recents.push_back(demodToBookmarkEntry(demod)); + if (recents.size() > 10) { + delete *(recents.begin()); + recents.erase(recents.begin(), recents.begin()+1); + } +} + + +BookmarkList BookmarkMgr::getRecents() { + return recents; +} + + +BookmarkEntry *BookmarkMgr::demodToBookmarkEntry(DemodulatorInstance *demod) { + BookmarkEntry *be = new BookmarkEntry; + + be->bandwidth = demod->getBandwidth(); + be->type = demod->getDemodulatorType(); + be->label = demod->getLabel(); + be->frequency = demod->getFrequency(); + + be->node = new DataNode; + wxGetApp().getDemodMgr().saveInstance(be->node, demod); + + return be; +} diff --git a/src/BookmarkMgr.h b/src/BookmarkMgr.h index b88160b..4b65e05 100644 --- a/src/BookmarkMgr.h +++ b/src/BookmarkMgr.h @@ -11,7 +11,6 @@ class BookmarkEntry { public: std::mutex busy_lock; - std::string folder; std::string type; std::string label; @@ -40,15 +39,25 @@ public: void saveToFile(std::string bookmarkFn); void loadFromFile(std::string bookmarkFn); - void addBookmark(std::string group, DemodulatorInstance *demod, std::string folder = ""); + void addBookmark(std::string group, DemodulatorInstance *demod); void removeBookmark(std::string group, BookmarkEntry *be); - BookmarkList getBookmarks(std::string group, std::string folder = ""); + + BookmarkList getBookmarks(std::string group); + BookmarkGroup getGroup(std::string group); BookmarkNames getGroups(); + void updateActiveList(); + + void addRecent(DemodulatorInstance *demod); + BookmarkList getRecents(); + protected: + BookmarkEntry *demodToBookmarkEntry(DemodulatorInstance *demod); + BookmarkMap bmData; + BookmarkList recents; std::mutex busy_lock; }; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index 5aa2da9..5801102 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -132,6 +132,8 @@ DemodulatorInstance *DemodulatorMgr::getFirstDemodulator() { void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { std::lock_guard < std::recursive_mutex > lock(demods_busy); + + wxGetApp().getBookmarkMgr().addRecent(demod); std::vector::iterator i; @@ -409,6 +411,8 @@ void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) { DemodulatorInstance *DemodulatorMgr::loadInstance(DataNode *node) { DemodulatorInstance *newDemod = nullptr; + node->rewindAll(); + long bandwidth = *node->getNext("bandwidth"); long long freq = *node->getNext("frequency"); float squelch_level = node->hasAnother("squelch_level") ? (float) *node->getNext("squelch_level") : 0; diff --git a/src/forms/Bookmark/BookmarkView.cpp b/src/forms/Bookmark/BookmarkView.cpp index 5b4fcc2..a6d2d00 100644 --- a/src/forms/Bookmark/BookmarkView.cpp +++ b/src/forms/Bookmark/BookmarkView.cpp @@ -2,14 +2,20 @@ #include "CubicSDR.h" BookmarkView::BookmarkView( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : BookmarkPanel(parent, id, pos, size, style) { + rootBranch = m_treeView->AddRoot("Root"); activeBranch = m_treeView->AppendItem(rootBranch, "Active"); bookmarkBranch = m_treeView->AppendItem(rootBranch, "Bookmarks"); + recentBranch = m_treeView->AppendItem(rootBranch, "Recents"); + doUpdateActive = false; activeSel = nullptr; - m_updateTimer.Start(500); + recentSel = nullptr; + hideProps(); m_propPanel->Hide(); + + m_updateTimer.Start(500); } void BookmarkView::onUpdateTimer( wxTimerEvent& event ) { @@ -56,6 +62,7 @@ void BookmarkView::doUpdateActiveList() { DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); // DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + // Actives activeItems.erase(activeItems.begin(),activeItems.end()); m_treeView->DeleteChildren(activeBranch); @@ -73,10 +80,24 @@ void BookmarkView::doUpdateActiveList() { selItem = itm; } } + + // Recents + BookmarkList bmRecents = wxGetApp().getBookmarkMgr().getRecents(); + recentItems.erase(recentItems.begin(),recentItems.end()); + m_treeView->DeleteChildren(recentBranch); + + for (auto bmr_i: bmRecents) { + wxTreeItemId itm = m_treeView->AppendItem(recentBranch, bmr_i->label); + recentItems[itm] = bmr_i; + if (recentSel == bmr_i) { + selItem = itm; + } + } + if (selItem != nullptr) { m_treeView->SelectItem(selItem); } - + m_treeView->Enable(); m_treeView->ExpandAll(); } @@ -90,7 +111,9 @@ void BookmarkView::onTreeEndLabelEdit( wxTreeEvent& event ) { } void BookmarkView::onTreeActivate( wxTreeEvent& event ) { - event.Skip(); + if (recentSel) { + activateBookmark(recentSel); + } } void BookmarkView::onTreeCollapse( wxTreeEvent& event ) { @@ -121,6 +144,7 @@ void BookmarkView::hideProps() { void BookmarkView::activeSelection(DemodulatorInstance *dsel) { activeSel = dsel; + recentSel = nullptr; m_frequencyVal->SetLabelText(frequencyToStr(dsel->getFrequency())); m_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth())); @@ -147,21 +171,100 @@ void BookmarkView::activeSelection(DemodulatorInstance *dsel) { this->Layout(); } +void BookmarkView::activateBookmark(BookmarkEntry *bmEnt) { + DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node); + newDemod->run(); + newDemod->setActive(true); + wxGetApp().bindDemodulator(newDemod); + if (bmEnt == recentSel) { + activeSel = newDemod; + recentSel = nullptr; + } + doUpdateActiveList(); +} + +void BookmarkView::bookmarkSelection(BookmarkEntry *bmSel) { + bookmarkSel = bmSel; + recentSel = nullptr; + activeSel = nullptr; + + m_frequencyVal->SetLabelText(frequencyToStr(bmSel->frequency)); + m_bandwidthVal->SetLabelText(frequencyToStr(bmSel->bandwidth)); + m_modulationVal->SetLabelText(bmSel->type); + m_labelText->SetValue(bmSel->label); + + hideProps(); + + m_frequencyVal->Show(); + m_frequencyLabel->Show(); + + m_bandwidthVal->Show(); + m_bandwidthLabel->Show(); + + m_modulationVal->Show(); + m_modulationLabel->Show(); + + m_labelText->Show(); + m_labelLabel->Show(); + + m_activateButton->Show(); + m_bookmarkButton->Show(); + m_removeButton->Show(); + + this->Layout(); +} + + +void BookmarkView::recentSelection(BookmarkEntry *bmSel) { + recentSel = bmSel; + activeSel = nullptr; + bookmarkSel = nullptr; + + m_frequencyVal->SetLabelText(frequencyToStr(bmSel->frequency)); + m_bandwidthVal->SetLabelText(frequencyToStr(bmSel->bandwidth)); + m_modulationVal->SetLabelText(bmSel->type); + m_labelText->SetValue(bmSel->label); + + hideProps(); + + m_frequencyVal->Show(); + m_frequencyLabel->Show(); + + m_bandwidthVal->Show(); + m_bandwidthLabel->Show(); + + m_modulationVal->Show(); + m_modulationLabel->Show(); + + m_labelText->Show(); + m_labelLabel->Show(); + + m_activateButton->Show(); + m_bookmarkButton->Show(); + m_removeButton->Hide(); + + this->Layout(); +} + void BookmarkView::onTreeSelect( wxTreeEvent& event ) { if (activeItems.find(event.GetItem()) != activeItems.end()) { DemodulatorInstance *dsel = activeItems[event.GetItem()]; m_propPanel->Show(); activeSelection(dsel); wxGetApp().getDemodMgr().setActiveDemodulator(activeSel, false); + } else if (recentItems.find(event.GetItem()) != recentItems.end()) { + recentSel = recentItems[event.GetItem()]; + m_propPanel->Show(); + recentSelection(recentSel); } else { activeSel = nullptr; + recentSel = nullptr; m_propPanel->Hide(); hideProps(); this->Layout(); wxGetApp().getDemodMgr().setActiveDemodulator(activeSel, false); - event.Skip(); } } @@ -177,8 +280,6 @@ void BookmarkView::onDoubleClickFreq( wxMouseEvent& event ) { if (activeSel) { wxGetApp().getDemodMgr().setActiveDemodulator(activeSel, false); wxGetApp().showFrequencyInput(FrequencyDialog::FrequencyDialogTarget::FDIALOG_TARGET_DEFAULT); - } else { - event.Skip(); } } @@ -186,8 +287,6 @@ void BookmarkView::onDoubleClickBandwidth( wxMouseEvent& event ) { if (activeSel) { wxGetApp().getDemodMgr().setActiveDemodulator(activeSel, false); wxGetApp().showFrequencyInput(FrequencyDialog::FrequencyDialogTarget::FDIALOG_TARGET_BANDWIDTH); - } else { - event.Skip(); } } @@ -196,7 +295,9 @@ void BookmarkView::onBookmark( wxCommandEvent& event ) { } void BookmarkView::onActivate( wxCommandEvent& event ) { - event.Skip(); + if (recentSel) { + activateBookmark(recentSel); + } } void BookmarkView::onRemove( wxCommandEvent& event ) { @@ -205,8 +306,6 @@ void BookmarkView::onRemove( wxCommandEvent& event ) { wxGetApp().removeDemodulator(activeSel); wxGetApp().getDemodMgr().deleteThread(activeSel); activeSel = nullptr; - } else { - event.Skip(); } } diff --git a/src/forms/Bookmark/BookmarkView.h b/src/forms/Bookmark/BookmarkView.h index 567c46c..a6cd5b0 100644 --- a/src/forms/Bookmark/BookmarkView.h +++ b/src/forms/Bookmark/BookmarkView.h @@ -10,6 +10,9 @@ public: void updateActiveList(); void activeSelection(DemodulatorInstance *dsel); + void bookmarkSelection(BookmarkEntry *bmSel); + void activateBookmark(BookmarkEntry *bmEnt); + void recentSelection(BookmarkEntry *bmSel); void updateTheme(); protected: @@ -34,9 +37,13 @@ protected: void onRemove( wxCommandEvent& event ); bool doUpdateActive; - wxTreeItemId rootBranch, activeBranch, bookmarkBranch; + wxTreeItemId rootBranch, activeBranch, bookmarkBranch, recentBranch; std::map groups; std::map activeItems; + std::map recentItems; DemodulatorInstance *activeSel; + BookmarkEntry *recentSel; + BookmarkEntry *bookmarkSel; + }; \ No newline at end of file diff --git a/src/util/DataTree.cpp b/src/util/DataTree.cpp index 3c1d1ce..ee3d469 100755 --- a/src/util/DataTree.cpp +++ b/src/util/DataTree.cpp @@ -565,6 +565,7 @@ DataNode *DataNode::getNext(const char *name_in) { void DataNode::rewind() { ptr = 0; + childmap_ptr.erase(childmap_ptr.begin(),childmap_ptr.end()); } void DataNode::rewind(const char *name_in) { @@ -1342,6 +1343,38 @@ long DataTree::getSerializedSize(DataElement &de_node_names, bool debug) /* get return total_size; } +void DataNode::rewindAll() { + stack dn_stack; + + /* start at the root */ + dn_stack.push(this); + + while (!dn_stack.empty()) { + dn_stack.top()->rewind(); + + /* if it has children, traverse into them */ + if (dn_stack.top()->hasAnother()) { + dn_stack.push(dn_stack.top()->getNext()); + dn_stack.top()->rewind(); + } else { + /* no more children, back out until we have children, then add next child to the top */ + while (!dn_stack.empty()) { + if (!dn_stack.top()->hasAnother()) { + dn_stack.top()->rewind(); + dn_stack.pop(); + } else + break; + } + + if (!dn_stack.empty()) { + dn_stack.push(dn_stack.top()->getNext()); + dn_stack.top()->rewind(); + } + } + } + +} + void DataNode::findAll(const char *name_in, vector &node_list_out) { stack dn_stack; diff --git a/src/util/DataTree.h b/src/util/DataTree.h index 5baa6e5..dad6947 100755 --- a/src/util/DataTree.h +++ b/src/util/DataTree.h @@ -260,7 +260,8 @@ public: DataNode *getNext(); /* get next child */ void rewind(const char *name_in); /* rewind specific */ void rewind(); /* rewind generic */ - + void rewindAll(); + void findAll(const char *name_in, vector &node_list_out); // operator string () { string s; element()->get(s); return s; } @@ -316,7 +317,6 @@ public: bool operator() () { return hasAnother(); } DataNode *operator ^(const char *name_in) { return newChild(name_in); } - };