From d816dc220a7c2d4928ffac9ed83a818fe626ee46 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 26 Dec 2016 21:56:19 -0500 Subject: [PATCH] Basic search, mostly functional --- src/BookmarkMgr.cpp | 13 ++ src/BookmarkMgr.h | 8 +- src/forms/Bookmark/BookmarkPanel.cpp | 12 ++ src/forms/Bookmark/BookmarkPanel.fbp | 179 +++++++++++++++++++++++++++ src/forms/Bookmark/BookmarkPanel.h | 12 +- src/forms/Bookmark/BookmarkView.cpp | 162 +++++++++++++++++++++--- src/forms/Bookmark/BookmarkView.h | 7 ++ 7 files changed, 369 insertions(+), 24 deletions(-) diff --git a/src/BookmarkMgr.cpp b/src/BookmarkMgr.cpp index 986afe6..3e77818 100644 --- a/src/BookmarkMgr.cpp +++ b/src/BookmarkMgr.cpp @@ -236,6 +236,19 @@ void BookmarkMgr::getGroups(wxArrayString &arr) { } +void BookmarkMgr::setExpandState(std::string groupName, bool state) { + expandState[groupName] = state; +} + + +bool BookmarkMgr::getExpandState(std::string groupName) { + if (expandState.find(groupName) == expandState.end()) { + return true; + } + return expandState[groupName]; +} + + void BookmarkMgr::updateActiveList() { BookmarkView *bmv = wxGetApp().getAppFrame()->getBookmarkView(); diff --git a/src/BookmarkMgr.h b/src/BookmarkMgr.h index 910af0e..64fbae8 100644 --- a/src/BookmarkMgr.h +++ b/src/BookmarkMgr.h @@ -35,6 +35,7 @@ typedef std::vector BookmarkList; typedef std::map BookmarkMap; typedef std::map BookmarkMapSorted; typedef std::vector BookmarkNames; +typedef std::map BookmarkExpandState; class BookmarkMgr { public: @@ -53,7 +54,10 @@ public: BookmarkList getBookmarks(std::string group); void getGroups(BookmarkNames &arr); void getGroups(wxArrayString &arr); - + + void setExpandState(std::string groupName, bool state); + bool getExpandState(std::string groupName); + void updateActiveList(); void updateBookmarks(); void updateBookmarks(std::string group); @@ -78,4 +82,6 @@ protected: BookmarkMapSorted bmDataSorted; BookmarkList recents; std::mutex busy_lock; + + BookmarkExpandState expandState; }; diff --git a/src/forms/Bookmark/BookmarkPanel.cpp b/src/forms/Bookmark/BookmarkPanel.cpp index b5b79f7..8e0d6f1 100644 --- a/src/forms/Bookmark/BookmarkPanel.cpp +++ b/src/forms/Bookmark/BookmarkPanel.cpp @@ -14,6 +14,12 @@ BookmarkPanel::BookmarkPanel( wxWindow* parent, wxWindowID id, const wxPoint& po wxBoxSizer* bSizer1; bSizer1 = new wxBoxSizer( wxVERTICAL ); + m_searchText = new wxTextCtrl( this, wxID_ANY, wxT("Search.."), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + bSizer1->Add( m_searchText, 0, wxALL|wxEXPAND, 5 ); + + m_clearSearchButton = new wxButton( this, wxID_ANY, wxT("Clear Search"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1->Add( m_clearSearchButton, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + m_treeView = new wxTreeCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE|wxTR_EDIT_LABELS|wxTR_HAS_VARIABLE_ROW_HEIGHT|wxTR_HIDE_ROOT|wxTR_SINGLE ); bSizer1->Add( m_treeView, 1, wxEXPAND, 5 ); @@ -80,6 +86,9 @@ BookmarkPanel::BookmarkPanel( wxWindow* parent, wxWindowID id, const wxPoint& po this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( BookmarkPanel::onEnterWindow ) ); this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BookmarkPanel::onLeaveWindow ) ); this->Connect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ) ); + m_searchText->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( BookmarkPanel::onSearchTextFocus ), NULL, this ); + m_searchText->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BookmarkPanel::onSearchText ), NULL, this ); + m_clearSearchButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BookmarkPanel::onClearSearch ), NULL, this ); m_treeView->Connect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ), NULL, this ); m_treeView->Connect( wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeBeginDrag ), NULL, this ); m_treeView->Connect( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeBeginLabelEdit ), NULL, this ); @@ -104,6 +113,9 @@ BookmarkPanel::~BookmarkPanel() this->Disconnect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( BookmarkPanel::onEnterWindow ) ); this->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BookmarkPanel::onLeaveWindow ) ); this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ) ); + m_searchText->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( BookmarkPanel::onSearchTextFocus ), NULL, this ); + m_searchText->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BookmarkPanel::onSearchText ), NULL, this ); + m_clearSearchButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BookmarkPanel::onClearSearch ), NULL, this ); m_treeView->Disconnect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ), NULL, this ); m_treeView->Disconnect( wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeBeginDrag ), NULL, this ); m_treeView->Disconnect( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeBeginLabelEdit ), NULL, this ); diff --git a/src/forms/Bookmark/BookmarkPanel.fbp b/src/forms/Bookmark/BookmarkPanel.fbp index d7d6657..8214f9d 100644 --- a/src/forms/Bookmark/BookmarkPanel.fbp +++ b/src/forms/Bookmark/BookmarkPanel.fbp @@ -83,6 +83,185 @@ bSizer1 wxVERTICAL none + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_searchText + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_PROCESS_ENTER + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + Search.. + + + + + + + + + + + + onSearchTextFocus + + + + + + + + + + + + + + onSearchText + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Clear Search + + 0 + + + 0 + + 1 + m_clearSearchButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onClearSearch + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxEXPAND diff --git a/src/forms/Bookmark/BookmarkPanel.h b/src/forms/Bookmark/BookmarkPanel.h index 946faac..ecb09cb 100644 --- a/src/forms/Bookmark/BookmarkPanel.h +++ b/src/forms/Bookmark/BookmarkPanel.h @@ -10,14 +10,15 @@ #include #include -#include +#include +#include #include #include #include #include -#include +#include +#include #include -#include #include #include #include @@ -33,6 +34,8 @@ class BookmarkPanel : public wxPanel private: protected: + wxTextCtrl* m_searchText; + wxButton* m_clearSearchButton; wxTreeCtrl* m_treeView; wxPanel* m_propPanel; wxStaticText* m_labelLabel; @@ -50,6 +53,9 @@ class BookmarkPanel : public wxPanel virtual void onEnterWindow( wxMouseEvent& event ) { event.Skip(); } virtual void onLeaveWindow( wxMouseEvent& event ) { event.Skip(); } virtual void onMotion( wxMouseEvent& event ) { event.Skip(); } + virtual void onSearchTextFocus( wxMouseEvent& event ) { event.Skip(); } + virtual void onSearchText( wxCommandEvent& event ) { event.Skip(); } + virtual void onClearSearch( wxCommandEvent& event ) { event.Skip(); } virtual void onTreeBeginDrag( wxTreeEvent& event ) { event.Skip(); } virtual void onTreeBeginLabelEdit( wxTreeEvent& event ) { event.Skip(); } virtual void onTreeEndDrag( wxTreeEvent& event ) { event.Skip(); } diff --git a/src/forms/Bookmark/BookmarkView.cpp b/src/forms/Bookmark/BookmarkView.cpp index 933b9b6..9814e09 100644 --- a/src/forms/Bookmark/BookmarkView.cpp +++ b/src/forms/Bookmark/BookmarkView.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define wxCONTEXT_ADD_GROUP_ID 1000 @@ -83,6 +84,7 @@ BookmarkView::BookmarkView( wxWindow* parent, wxWindowID id, const wxPoint& pos, dragItemId = nullptr; editingLabel = false; + m_clearSearchButton->Hide(); hideProps(); m_updateTimer.Start(500); @@ -151,6 +153,19 @@ void BookmarkView::updateBookmarks(std::string group) { doUpdateBookmarks.store(true); } +bool BookmarkView::isKeywordMatch(std::wstring search_str, std::vector &keywords) { + wstring str = search_str; + std::transform(str.begin(), str.end(), str.begin(), towlower); + + for (auto k : keywords) { + if (str.find(k) != wstring::npos) { + return true; + } + } + + return false; +} + wxTreeItemId BookmarkView::refreshBookmarks() { TreeViewItem *prevSel = itemToTVI(m_treeView->GetSelection()); @@ -165,10 +180,7 @@ wxTreeItemId BookmarkView::refreshBookmarks() { wxTreeItemId bmSelFound = nullptr; std::map groupExpandState; - - for (auto g_i : groups) { - groupExpandState[g_i.first] = m_treeView->IsExpanded(g_i.second); - } + bool searchState = (searchKeywords.size() != 0); groups.erase(groups.begin(),groups.end()); m_treeView->DeleteChildren(bookmarkBranch); @@ -187,29 +199,41 @@ wxTreeItemId BookmarkView::refreshBookmarks() { } } - if (bmExpandState) { + if (searchState || bmExpandState) { m_treeView->Expand(bookmarkBranch); } for (auto gn_i : groupNames) { wxTreeItemId groupItem = groups[gn_i]; - bool groupExpanded = false; - - if (groupExpandState.find(gn_i) != groupExpandState.end()) { - groupExpanded = groupExpandState[gn_i]; - } else { // New - groupExpanded = true; - } + bool groupExpanded = searchState || wxGetApp().getBookmarkMgr().getExpandState(gn_i); BookmarkList bmList = wxGetApp().getBookmarkMgr().getBookmarks(gn_i); for (auto &bmEnt : bmList) { + std::wstring labelVal = BookmarkMgr::getBookmarkEntryDisplayName(bmEnt); + + if (searchState) { + + bool match = isKeywordMatch(labelVal, searchKeywords); + + std::string freqStr = frequencyToStr(bmEnt->frequency); + std::string bwStr = frequencyToStr(bmEnt->bandwidth); + + match = match || isKeywordMatch(bmEnt->userLabel, searchKeywords); + match = match || isKeywordMatch(std::to_wstring(bmEnt->frequency), searchKeywords); + match = match || isKeywordMatch(std::wstring(freqStr.begin(),freqStr.end()), searchKeywords); + match = match || isKeywordMatch(std::wstring(bwStr.begin(),bwStr.end()), searchKeywords); + match = match || isKeywordMatch(std::wstring(bmEnt->type.begin(),bmEnt->type.end()), searchKeywords); + + if (!match) { + continue; + } + } + TreeViewItem* tvi = new TreeViewItem(); tvi->type = TreeViewItem::TREEVIEW_ITEM_TYPE_BOOKMARK; tvi->bookmarkEnt = bmEnt; tvi->groupName = gn_i; - - std::wstring labelVal = BookmarkMgr::getBookmarkEntryDisplayName(bmEnt); wxTreeItemId itm = m_treeView->AppendItem(groupItem, labelVal); m_treeView->SetItemData(itm, tvi); @@ -244,6 +268,7 @@ void BookmarkView::doUpdateActiveList() { m_treeView->DeleteChildren(activeBranch); bool activeExpandState = expandState["active"]; + bool searchState = (searchKeywords.size() != 0); wxTreeItemId selItem = nullptr; for (auto demod_i : demods) { @@ -264,7 +289,7 @@ void BookmarkView::doUpdateActiveList() { } } - bool recentExpandState = expandState["recent"]; + bool recentExpandState = searchState || expandState["recent"]; // Recents BookmarkList bmRecents = wxGetApp().getBookmarkMgr().getRecents(); @@ -277,12 +302,29 @@ void BookmarkView::doUpdateActiveList() { std::wstring labelVal; bmr_i->node->child("user_label")->element()->get(labelVal); - + if (labelVal == "") { std::string wstr = frequencyToStr(bmr_i->frequency) + " " + bmr_i->type; labelVal = std::wstring(wstr.begin(),wstr.end()); } + if (searchKeywords.size()) { + + std::string freqStr = frequencyToStr(bmr_i->frequency); + std::string bwStr = frequencyToStr(bmr_i->bandwidth); + + bool match = isKeywordMatch(labelVal, searchKeywords); + match = match || isKeywordMatch(bmr_i->userLabel, searchKeywords); + match = match || isKeywordMatch(std::to_wstring(bmr_i->frequency), searchKeywords); + match = match || isKeywordMatch(std::wstring(freqStr.begin(),freqStr.end()), searchKeywords); + match = match || isKeywordMatch(std::wstring(bwStr.begin(),bwStr.end()), searchKeywords); + match = match || isKeywordMatch(std::wstring(bmr_i->type.begin(),tvi->bookmarkEnt->type.end()), searchKeywords); + + if (!match) { + continue; + } + } + wxTreeItemId itm = m_treeView->AppendItem(recentBranch, labelVal); m_treeView->SetItemData(itm, tvi); @@ -384,19 +426,39 @@ void BookmarkView::onTreeActivate( wxTreeEvent& event ) { void BookmarkView::onTreeCollapse( wxTreeEvent& event ) { + bool searchState = (searchKeywords.size() != 0); + + if (searchState) { + event.Skip(); + return; + } + if (event.GetItem() == activeBranch) { expandState["active"] = false; } else if (event.GetItem() == bookmarkBranch) { expandState["bookmark"] = false; } else if (event.GetItem() == recentBranch) { expandState["recent"] = false; - } + } else { + TreeViewItem *tvi = itemToTVI(event.GetItem()); + + if (tvi != nullptr) { + if (tvi->type == TreeViewItem::TREEVIEW_ITEM_TYPE_GROUP) { + wxGetApp().getBookmarkMgr().setExpandState(tvi->groupName,false); + } + } - event.Skip(); + } } void BookmarkView::onTreeExpanded( wxTreeEvent& event ) { + bool searchState = (searchKeywords.size() != 0); + + if (searchState) { + event.Skip(); + return; + } if (event.GetItem() == activeBranch) { expandState["active"] = true; @@ -404,9 +466,16 @@ void BookmarkView::onTreeExpanded( wxTreeEvent& event ) { expandState["bookmark"] = true; } else if (event.GetItem() == recentBranch) { expandState["recent"] = true; + } else { + TreeViewItem *tvi = itemToTVI(event.GetItem()); + + if (tvi != nullptr) { + if (tvi->type == TreeViewItem::TREEVIEW_ITEM_TYPE_GROUP) { + wxGetApp().getBookmarkMgr().setExpandState(tvi->groupName,true); + } + } + } - - event.Skip(); } @@ -1105,4 +1174,57 @@ TreeViewItem *BookmarkView::itemToTVI(wxTreeItemId item) { return tvi; } +void BookmarkView::onSearchTextFocus( wxMouseEvent& event ) { + if (!m_searchText->IsEmpty()) { + if (m_searchText->GetValue() == L"Search..") { + m_searchText->SetValue(L""); + } + } +} + + +void BookmarkView::onSearchText( wxCommandEvent& event ) { + wstring searchText = m_searchText->GetValue().Trim().Lower().ToStdWstring(); + + if (!searchKeywords.empty()) { + searchKeywords.erase(searchKeywords.begin(),searchKeywords.end()); + } + + if (searchText.length() != 0) { + std::wstringstream searchTextLo(searchText); + wstring tmp; + + while(std::getline(searchTextLo, tmp, L';')) { + if (tmp.length() != 0 && tmp.find(L"search.") == wstring::npos) { + searchKeywords.push_back(tmp); + std::wcout << L"Keyword: " << tmp << '\n'; + } + + } + } + + if (searchKeywords.size() != 0 && !m_clearSearchButton->IsShown()) { + m_clearSearchButton->Show(); + refreshLayout(); + } else if (searchKeywords.size() == 0 && m_clearSearchButton->IsShown()) { + m_clearSearchButton->Hide(); + refreshLayout(); + } + + wxGetApp().getBookmarkMgr().updateActiveList(); + wxGetApp().getBookmarkMgr().updateBookmarks(); +} + + +void BookmarkView::onClearSearch( wxCommandEvent& event ) { + m_searchText->SetValue(L"Search.."); + m_treeView->SetFocus(); + if (!searchKeywords.empty()) { + searchKeywords.erase(searchKeywords.begin(),searchKeywords.end()); + } + wxGetApp().getBookmarkMgr().updateActiveList(); + wxGetApp().getBookmarkMgr().updateBookmarks(); + m_clearSearchButton->Hide(); + refreshLayout(); +} diff --git a/src/forms/Bookmark/BookmarkView.h b/src/forms/Bookmark/BookmarkView.h index 3e3e912..b6264b7 100644 --- a/src/forms/Bookmark/BookmarkView.h +++ b/src/forms/Bookmark/BookmarkView.h @@ -39,6 +39,7 @@ public: void updateActiveList(); void updateBookmarks(); + bool isKeywordMatch(std::wstring str, std::vector &keywords); void updateBookmarks(std::string group); void activeSelection(DemodulatorInstance *dsel); void bookmarkSelection(BookmarkEntry *bmSel); @@ -82,6 +83,9 @@ protected: void onLeaveWindow( wxMouseEvent& event ); void onMotion( wxMouseEvent& event ); + void onSearchTextFocus( wxMouseEvent& event ); + void onSearchText( wxCommandEvent& event ); + void onClearSearch( wxCommandEvent& event ); void clearButtons(); void showButtons(); @@ -141,4 +145,7 @@ protected: // Focus BookmarkEntry *nextEnt; DemodulatorInstance *nextDemod; + + // Search + std::vector searchKeywords; };