Basic search, mostly functional

This commit is contained in:
Charles J. Cliffe 2016-12-26 21:56:19 -05:00
parent a02dbae7d3
commit d816dc220a
7 changed files with 369 additions and 24 deletions

View File

@ -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();

View File

@ -35,6 +35,7 @@ typedef std::vector<BookmarkEntry *> BookmarkList;
typedef std::map<std::string, BookmarkList > BookmarkMap;
typedef std::map<std::string, bool > BookmarkMapSorted;
typedef std::vector<std::string> BookmarkNames;
typedef std::map<std::string, bool> 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;
};

View File

@ -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 );

View File

@ -83,6 +83,185 @@
<property name="name">bSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_searchText</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxTE_PROCESS_ENTER</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">Search..</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown">onSearchTextFocus</event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnText">onSearchText</event>
<event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Clear Search</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_clearSearchButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onClearSearch</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>

View File

@ -10,14 +10,15 @@
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/treectrl.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/button.h>
#include <wx/treectrl.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/timer.h>
@ -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(); }

View File

@ -5,6 +5,7 @@
#include <wx/menu.h>
#include <wx/textdlg.h>
#include <algorithm>
#include <wchar.h>
#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<std::wstring> &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<std::string, bool> 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();
}

View File

@ -39,6 +39,7 @@ public:
void updateActiveList();
void updateBookmarks();
bool isKeywordMatch(std::wstring str, std::vector<std::wstring> &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<std::wstring> searchKeywords;
};