OpenCPN Partial API docs
Loading...
Searching...
No Matches
filter_dlg.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2025 Alec Leamas *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
25#include <functional>
26#include <memory>
27#include <string>
28
29#include <wx/app.h>
30#include <wx/arrstr.h>
31#include <wx/button.h>
32#include <wx/checkbox.h>
33#include <wx/checklst.h>
34#include <wx/choicdlg.h>
35#include <wx/frame.h>
36#include <wx/log.h>
37#include <wx/msgdlg.h>
38#include <wx/panel.h>
39#include <wx/radiobox.h>
40#include <wx/radiobut.h>
41#include <wx/sizer.h>
42#include <wx/statline.h>
43#include <wx/stattext.h>
44#include <wx/textdlg.h>
45#include <wx/wrapsizer.h>
46
47#ifndef ocpnUSE_wxBitmapBundle
48#include <wx/sstream.h>
49#include <wxSVG/svg.h>
50#endif
51
55#include "filter_dlg.h"
56#include "std_filesystem.h"
57#include "svg_icons.h"
58#include "edit_button.h"
59
60// Make _() return const char* instead of wxString;
61#undef _
62#if wxCHECK_VERSION(3, 2, 0)
63#define _(s) wxGetTranslation(wxASCII_STR(s)).ToStdString().c_str()
64#else
65#define _(s) wxGetTranslation((s)).ToStdString().c_str()
66#endif
67
68static const std::string kEditFilterFrameName("EditFilterFrame::");
69
70static const char* const kFilterExists =
71 R"( Filter already exists. Please use Edit to update
72or Remove to delete it prior to create.)";
73
74static const std::unordered_map<NavmsgStatus::Direction, std::string>
75 kStringByDirection = {{NavmsgStatus::Direction::kInput, "Input"},
76 {NavmsgStatus::Direction::kReceived, "Received"},
77 {NavmsgStatus::Direction::kOutput, "Output"},
78 {NavmsgStatus::Direction::kInternal, "Internal"}};
79
81template <typename T>
82T* GetWindowById(int id) {
83 return dynamic_cast<T*>(wxWindow::FindWindowById(id));
84};
85
86static NavmsgStatus::Direction StringToDirection(const std::string& s) {
87 for (const auto& it : kStringByDirection)
88 if (it.second == s) return it.first;
89 return NavmsgStatus::Direction::kNone;
90}
91
92static wxArrayString GetUserFilters() {
93 auto std_filters = filters_on_disk::List(false);
94 wxArrayString wx_filters;
95 for (auto& f : std_filters) wx_filters.Add(f);
96 return wx_filters;
97}
98
100static std::vector<std::string> GetActiveMessages() {
101 auto v = NavMsgBus::GetInstance().GetActiveMessages();
102 std::vector<std::string> result;
103 for (const auto& m : NavMsgBus::GetInstance().GetActiveMessages()) {
104 size_t pos = m.find("::");
105 if (pos == std::string::npos) {
106 result.push_back(m);
107 } else {
108 result.push_back(m.substr(pos + 2));
109 }
110 }
111 return result;
112}
113
114class NewFilterDlg : public wxTextEntryDialog {
115public:
116 NewFilterDlg(wxWindow*)
117 : wxTextEntryDialog(wxTheApp->GetTopWindow(), _("New filter name")) {}
118};
119
120class DeleteFilterDlg : public wxSingleChoiceDialog {
121public:
122 DeleteFilterDlg(wxWindow*)
123 : wxSingleChoiceDialog(wxTheApp->GetTopWindow(),
124 _("Remove filter (name):"), _("Remove filter"),
125 GetUserFilters()) {}
126};
127
128class SelectFilterDlg : public wxSingleChoiceDialog {
129public:
130 SelectFilterDlg(wxWindow*)
131 : wxSingleChoiceDialog(wxTheApp->GetTopWindow(), _("Edit filter (name):"),
132 _("Edit filter"), GetUserFilters()) {}
133};
134
135class BadFilterNameDlg : public wxMessageDialog {
136public:
137 BadFilterNameDlg(wxWindow* parent)
138 : wxMessageDialog(parent, _(kFilterExists)) {}
139};
140
145class MsgTypePanel : public wxPanel {
146public:
147 MsgTypePanel(wxWindow* parent, NavmsgFilter& filter,
148 std::function<void()> on_update)
149 : wxPanel(parent, wxID_ANY),
150 m_filter(filter),
151 m_on_update(std::move(on_update)),
152 kIncludeBtnId(wxWindow::NewControlId()),
153 kExcludeBtnId(wxWindow::NewControlId()),
154 kEditBtnId(wxWindow::NewControlId()),
155 kListboxId(wxWindow::NewControlId()),
156 kSummaryId(wxWindow::NewControlId()),
157 kSetBtnId(wxWindow::NewControlId()),
158 kClearBtnId(wxWindow::NewControlId()) {
159 auto flags = wxSizerFlags(0).Border();
160 auto vbox = new wxStaticBoxSizer(wxVERTICAL, this, _("Message Types"));
161 auto hbox = new wxBoxSizer(wxHORIZONTAL);
162
163 auto radiobox = new wxBoxSizer(wxVERTICAL);
164 radiobox->Add(new wxRadioButton(this, kIncludeBtnId, _("Include messages"),
165 wxDefaultPosition, wxDefaultSize,
166 wxRB_GROUP));
167 radiobox->Add(
168 new wxRadioButton(this, kExcludeBtnId, _("Exclude messages")));
169 radiobox->Add(1, 1, 1); // Expanding space, align buttons to bottom
170 radiobox->Add(new wxButton(this, kSetBtnId, _("Check all")), flags);
171 radiobox->Add(new wxButton(this, kClearBtnId, _("Clear all")), flags);
172 hbox->Add(radiobox, flags.Expand());
173
174 hbox->Add(1, 1, 1); // Expanding space, keep button/summary right aligned
175 wxArrayString choices;
176 auto msg_types = GetActiveMessages();
177 for (const auto& msg_type : msg_types) choices.Add(msg_type);
178 auto listbox = new wxCheckListBox(this, kListboxId, wxDefaultPosition,
179 wxDefaultSize, choices, 1);
180 hbox->Add(new wxStaticText(this, kSummaryId, ""), flags);
181 hbox->Add(listbox, flags);
182
183 auto edit_box = new wxBoxSizer(wxVERTICAL);
184 auto edit_btn = new EditButton(this, kEditBtnId, [&] { OnEditClick(); });
185 edit_box->Add(edit_btn, wxSizerFlags());
186 hbox->Add(edit_box, flags.Expand());
187
188 wxWindow* btn = GetWindowById<wxWindow>(kSetBtnId);
189 btn->Hide();
190 btn->Bind(wxEVT_BUTTON, [&](wxCommandEvent&) { SetAllItems(true); });
191 btn = GetWindowById<wxWindow>(kClearBtnId);
192 btn->Hide();
193 btn->Bind(wxEVT_BUTTON, [&](wxCommandEvent&) { SetAllItems(false); });
194
195 vbox->Add(hbox, flags.Expand());
196 SetSizer(vbox);
197 ImportFromFilter();
198 listbox->Hide();
199 GetWindowById<wxStaticText>(kSummaryId)->SetLabel(GetSummary());
200 Fit();
201
202 listbox->Bind(wxEVT_CHECKLISTBOX,
203 [&](wxCommandEvent& ev) { OnItemCheck(ev.GetInt()); });
204 }
205
206private:
207 std::string GetListboxItem(wxCheckListBox* listbox, unsigned i) const {
208 return listbox->GetString(i).ToStdString();
209 }
210
211 void SetAllItems(bool value) {
212 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
213 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
214 listbox->Check(i, value);
215 }
216 ExportToFilter();
217 }
218
219 std::string GetSummary() {
220 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
221
222 if (m_filter.exclude_msg.empty() && m_filter.include_msg.empty())
223 return _("All");
224 bool excluded = !m_filter.exclude_msg.empty();
225 size_t checked =
226 excluded ? m_filter.exclude_msg.size() : m_filter.include_msg.size();
227 size_t all = listbox->GetCount();
228 if (all == checked) return _("All");
229
230 std::stringstream ss;
231 ss << "[" << checked << _(" of ") << all << "]";
232 return ss.str();
233 }
234
239 void OnEditClick() {
240 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
241 auto summary = GetWindowById<wxStaticText>(kSummaryId);
242 auto edit_button = GetWindowById<EditButton>(kEditBtnId);
243 bool is_editing = listbox->IsShown();
244 listbox->Show(!is_editing);
245 summary->Show(is_editing);
246 summary->SetLabel(GetSummary());
247 edit_button->SetIcon(!is_editing);
248 GetWindowById<wxWindow>(kSetBtnId)->Show(!is_editing);
249 GetWindowById<wxWindow>(kClearBtnId)->Show(!is_editing);
250 GetParent()->Fit();
251 ExportToFilter();
252 }
253
258 void OnItemCheck(int ix) {
259 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
260 int checked = 0;
261 for (unsigned i = 0; i < listbox->GetCount(); i += 1)
262 if (listbox->IsChecked(i)) checked += 1;
263 if (checked == 0) {
264 // Refuse to create a filter with no interfaces.
265 listbox->Check(ix);
266 return;
267 }
268 ExportToFilter();
269 }
270
272 void ImportFromFilter() {
273 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
274 auto exclude_btn = GetWindowById<wxRadioButton>(kExcludeBtnId);
275 auto include_btn = GetWindowById<wxRadioButton>(kIncludeBtnId);
276
277 exclude_btn->SetValue(m_filter.exclude_msg.size() > 0);
278 if (include_btn->GetValue()) {
279 if (m_filter.include_msg.empty()) {
280 for (unsigned i = 0; i < listbox->GetCount(); i++) listbox->Check(i);
281 } else {
282 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
283 std::string item = GetListboxItem(listbox, i);
284 if (m_filter.include_msg.count(item)) listbox->Check(i);
285 }
286 }
287 } else {
288 if (m_filter.exclude_msg.empty()) {
289 for (unsigned i = 0; i < listbox->GetCount(); i++) listbox->Check(i);
290 } else {
291 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
292 std::string item = GetListboxItem(listbox, i);
293 if (m_filter.exclude_msg.count(item)) listbox->Check(i);
294 }
295 }
296 }
297 }
298
300 void ExportToFilter() {
301 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
302 auto include_btn = GetWindowById<wxRadioButton>(kIncludeBtnId);
303 m_filter.include_msg.clear();
304 m_filter.exclude_msg.clear();
305 auto& the_set =
306 include_btn->GetValue() ? m_filter.include_msg : m_filter.exclude_msg;
307 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
308 if (!listbox->IsChecked(i)) continue;
309 std::string item = GetListboxItem(listbox, i);
310 the_set.insert(item);
311 }
312 if (the_set.size() == listbox->GetCount()) {
313 m_filter.include_msg.clear();
314 m_filter.exclude_msg.clear();
315 }
316 m_on_update();
317 }
318
319 NavmsgFilter& m_filter;
320 std::function<void()> m_on_update;
321 const int kIncludeBtnId;
322 const int kExcludeBtnId;
323 const int kEditBtnId;
324 const int kListboxId;
325 const int kSummaryId;
326 const int kSetBtnId;
327 const int kClearBtnId;
328};
329
338template <typename T>
339class SetPanel : public wxPanel {
340public:
341 SetPanel(wxWindow* parent, std::set<T>& set, std::function<void()> on_update,
342 const std::string& label, std::function<wxArrayString()> get_choices)
343 : wxPanel(),
344 m_set(set),
345 m_on_update(std::move(on_update)),
346 kEditBtnId(wxWindow::NewControlId()),
347 kListboxId(wxWindow::NewControlId()),
348 kListLabelId(wxWindow::NewControlId()) {
349 wxPanel::Create(parent, wxID_ANY);
350 auto flags = wxSizerFlags(0).Border();
351 auto vbox = new wxBoxSizer(wxVERTICAL);
352 auto hbox = new wxBoxSizer(wxHORIZONTAL);
353 hbox->Add(new wxStaticText(this, wxID_ANY, label), flags);
354
355 hbox->Add(1, 1, 1);
356 auto listbox = new wxCheckListBox(this, kListboxId, wxDefaultPosition,
357 wxDefaultSize, get_choices());
358 hbox->Add(listbox, flags);
359 auto list_label = new wxStaticText(this, kListLabelId, "");
360 hbox->Add(list_label, flags);
361 auto edit_btn = new EditButton(this, kEditBtnId, [&] { OnEditClick(); });
362 hbox->Add(edit_btn, flags);
363 vbox->Add(hbox, flags.Expand());
364 SetSizer(vbox);
365
366 ImportFromFilter();
367 list_label->SetLabel(GetListLabel());
368
369 listbox->Hide();
370 list_label->Show();
371 Layout();
372
373 listbox->Bind(wxEVT_CHECKLISTBOX,
374 [&](wxCommandEvent& ev) { OnItemCheck(ev.GetInt()); });
375 }
376
377private:
379 T GetListboxItem(wxCheckListBox* listbox, unsigned i) const {
380 if constexpr (std::is_same<T, std::string>::value)
381 return listbox->GetString(i).ToStdString();
382 else if constexpr (std::is_same<T, NavAddr::Bus>::value)
383 return NavAddr::StringToBus(listbox->GetString(i).ToStdString());
384 else if constexpr (std::is_same<T, NavmsgStatus::Direction>::value)
385 return StringToDirection(listbox->GetString(i).ToStdString());
386 else if constexpr (std::is_same<T, NavmsgStatus::Accepted>::value)
388 listbox->GetString(i).ToStdString());
389 else
390 assert(false && "bad type...");
391 }
392
394 std::string GetListLabel() {
395 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
396 if (m_set.empty() || m_set.size() == listbox->GetCount()) return _("All");
397 std::stringstream ss;
398 ss << "[" << m_set.size() << _(" of ") << listbox->GetCount() << "]";
399 return ss.str();
400 }
401
406 void OnEditClick() {
407 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
408 auto list_label = GetWindowById<wxStaticText>(kListLabelId);
409 auto edit_button = GetWindowById<EditButton>(kEditBtnId);
410 bool is_editing = listbox->IsShown();
411 listbox->Show(!is_editing);
412 list_label->Show(is_editing);
413 list_label->SetLabel(GetListLabel());
414 edit_button->SetIcon(!is_editing);
415 GetParent()->Fit();
416 }
417
422 void OnItemCheck(int ix) {
423 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
424 auto list_label = GetWindowById<wxStaticText>(kListLabelId);
425 int checked = 0;
426 for (unsigned i = 0; i < listbox->GetCount(); i += 1)
427 if (listbox->IsChecked(i)) checked += 1;
428 if (checked == 0) {
429 listbox->Check(ix);
430 return;
431 }
432 list_label->SetLabel(GetListLabel());
433 ExportToFilter();
434 }
435
437 void ImportFromFilter() {
438 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
439 if (m_set.empty()) {
440 for (unsigned i = 0; i < listbox->GetCount(); i++) listbox->Check(i);
441 } else {
442 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
443 T item = GetListboxItem(listbox, i);
444 if (m_set.count(item) > 0) listbox->Check(i);
445 }
446 }
447 }
448
450 void ExportToFilter() {
451 auto listbox = GetWindowById<wxCheckListBox>(kListboxId);
452 m_set.clear();
453 for (unsigned i = 0; i < listbox->GetCount(); i += 1) {
454 if (!listbox->IsChecked(i)) continue;
455 T item = GetListboxItem(listbox, i);
456 m_set.insert(item);
457 }
458 if (m_set.size() == listbox->GetCount()) m_set.clear();
459 m_on_update();
460 }
461
462 std::set<T>& m_set;
463 std::function<void()> m_on_update;
464 const int kEditBtnId;
465 const int kListboxId;
466 const int kListLabelId;
467};
468
470class IfacePanel : public SetPanel<std::string> {
471public:
472 IfacePanel(wxWindow* parent, NavmsgFilter& filter,
473 std::function<void()> on_update)
474 : SetPanel<std::string>(parent, filter.interfaces, std::move(on_update),
475 _("Use interfaces"),
476 [&]() { return IfacePanel::GetChoices(); }) {}
477
478private:
479 wxArrayString GetChoices() const {
480 wxArrayString choices;
481 for (auto& driver : CommDriverRegistry::GetInstance().GetDrivers())
482 choices.Add(driver->iface);
483 choices.Add("Internal");
484 return choices;
485 }
486};
487
492class BusPanel : public SetPanel<NavAddr::Bus> {
493public:
494 BusPanel(wxWindow* parent, NavmsgFilter& filter,
495 std::function<void()> on_update)
496 : SetPanel<NavAddr::Bus>(parent, filter.buses, std::move(on_update),
497 _("Use message buses"),
498 [&]() { return BusPanel::GetChoices(); }) {}
499
500private:
501 wxArrayString GetChoices() const {
502 static const char* choices[] = {"nmea0183", "nmea2000", "SignalK", "Onenet",
503 "Plugin"};
504 return {5, choices};
505 }
506};
507
512class DirectionPanel : public SetPanel<NavmsgStatus::Direction> {
513public:
514 DirectionPanel(wxWindow* parent, NavmsgFilter& filter,
515 std::function<void()> on_update)
517 parent, filter.directions, std::move(on_update),
518 _("Use directions"), [&] { return DirectionPanel::GetChoices(); }) {
519 }
520
521private:
522 wxArrayString GetChoices() const {
523 static const char* choices[] = {"Input", "Received", "Output", "Internal"};
524 return {4, choices};
525 }
526};
527
528class AcceptedPanel : public SetPanel<NavmsgStatus::Accepted> {
529public:
530 AcceptedPanel(wxWindow* parent, NavmsgFilter& filter,
531 std::function<void()> on_update)
533 parent, filter.accepted, std::move(on_update),
534 _("Use Accepted states"),
535 [&]() { return AcceptedPanel::GetChoices(); }) {}
536
537private:
538 wxArrayString GetChoices() const {
539 static const char* choices[] = {"Ok", "FilteredNoOutput",
540 "FilteredDropped"};
541 return {3, choices};
542 }
543};
544
545class EditFilterFrame : public wxFrame {
546 class Buttons : public wxPanel {
547 public:
548 Buttons(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
549 auto vbox = new wxBoxSizer(wxVERTICAL);
550 auto buttons = new wxStdDialogButtonSizer();
551 buttons->AddButton(new wxButton(this, wxID_CLOSE));
552 buttons->AddButton(new wxButton(this, wxID_APPLY));
553 vbox->Add(buttons, wxSizerFlags().Expand());
554 buttons->Realize();
555 SetSizer(vbox);
556 Layout();
557 }
558 };
559
560public:
561 EditFilterFrame(wxWindow* parent, const std::string& name,
562 std::function<void(const std::string&)> on_update,
563 std::function<void(const std::string&)> on_apply)
564 : wxFrame(parent, wxID_ANY,
565 [name] { return _("Edit filter: ") + name; }()),
566 m_on_update(std::move(on_update)),
567 m_on_apply(std::move(on_apply)),
568 m_name(name) {
569 SetName(kEditFilterFrameName + name);
570 m_filter = filters_on_disk::Read(m_name);
571
572 auto flags = wxSizerFlags().Border().Expand();
573 auto vbox = new wxBoxSizer(wxVERTICAL);
574 SetSizer(vbox);
575 vbox->Add(new IfacePanel(this, m_filter, [&] { Update(); }), flags);
576 vbox->Add(new wxStaticLine(this), flags.Expand());
577 vbox->Add(new BusPanel(this, m_filter, [&] { Update(); }), flags);
578 vbox->Add(new wxStaticLine(this), flags.Expand());
579 vbox->Add(new DirectionPanel(this, m_filter, [&] { Update(); }), flags);
580 vbox->Add(new wxStaticLine(this), flags.Expand());
581 vbox->Add(new AcceptedPanel(this, m_filter, [&] { Update(); }), flags);
582 vbox->Add(new MsgTypePanel(this, m_filter, [&] { Update(); }), flags);
583 vbox->Add(new Buttons(this), flags);
584 Fit();
585 Hide();
586
587 Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent&) { Destroy(); });
588 Bind(wxEVT_BUTTON, [&](wxCommandEvent& evt) { OnButtonEvent(evt); });
589 }
590
591private:
592 void Update() {
593 filters_on_disk::Write(m_filter, m_name);
594 m_on_update(m_name);
595 }
596
597 void OnButtonEvent(wxCommandEvent& evt) {
598 if (evt.GetId() == wxID_CLOSE) {
599 Destroy();
600 evt.Skip();
601 } else if (evt.GetId() == wxID_APPLY) {
602 m_on_apply(m_name);
603 evt.Skip();
604 }
605 }
606
607 std::function<void(const std::string&)> m_on_update;
608 std::function<void(const std::string&)> m_on_apply;
609 std::string m_name;
610 NavmsgFilter m_filter;
611};
612
613void CreateFilterDlg(wxWindow* parent) {
614 NewFilterDlg dlg(parent);
615 dlg.ShowModal();
616 auto name = dlg.GetValue().ToStdString();
617 if (name.empty()) {
618 wxMessageDialog dlg(wxTheApp->GetTopWindow(), _("Illegal name"));
619 dlg.ShowModal();
620 return;
621 }
622 if (filters_on_disk::Exists(name)) {
623 BadFilterNameDlg(wxTheApp->GetTopWindow()).ShowModal();
624 return;
625 }
626 NavmsgFilter filter;
627 filter.m_name = name;
628 filters_on_disk::Write(filter, name);
629 FilterEvents::GetInstance().filter_list_change.Notify();
630}
631
632void RemoveFilterDlg(wxWindow* parent) {
633 if (GetUserFilters().empty()) {
634 wxMessageDialog dlg(wxTheApp->GetTopWindow(), _("No filters created"));
635 dlg.ShowModal();
636 return;
637 }
638 DeleteFilterDlg dlg(parent);
639 int sts = dlg.ShowModal();
640 if (sts != wxID_OK) return;
641
642 fs::path path(dlg.GetStringSelection().ToStdString());
643 if (filters_on_disk::Remove(path.stem().string())) {
644 FilterEvents::GetInstance().filter_list_change.Notify();
645 wxMessageDialog dlg(wxTheApp->GetTopWindow(), _("Filter removed"));
646 dlg.ShowModal();
647 } else {
648 wxMessageDialog dlg(wxTheApp->GetTopWindow(), _("Cannot remove filter"));
649 dlg.ShowModal();
650 }
651}
652
653void EditOneFilterDlg(wxWindow* parent, const std::string& filter) {
654 std::string window_name = kEditFilterFrameName + filter;
655 wxWindow* frame = wxWindow::FindWindowByName(window_name);
656 if (frame) {
657 frame->Raise();
658 return;
659 }
660 auto on_update = [](const std::string& _name) {
661 FilterEvents::GetInstance().filter_update.Notify(_name);
662 };
663 auto on_apply = [](const std::string& _name) {
664 FilterEvents::GetInstance().filter_apply.Notify(_name);
665 };
666 new EditFilterFrame(parent, filter, on_update, on_apply);
667 frame = wxWindow::FindWindowByName(window_name);
668 assert(frame && "Cannot create EditFilter frame");
669 frame->Show();
670}
671
672void EditFilterDlg(wxWindow* parent) {
673 if (GetUserFilters().empty()) {
674 wxMessageDialog dlg(wxTheApp->GetTopWindow(), _("No filters created"));
675 dlg.ShowModal();
676 return;
677 }
678 SelectFilterDlg dlg(parent);
679 int sts = dlg.ShowModal();
680 if (sts != wxID_OK) return;
681
682 EditOneFilterDlg(parent, dlg.GetStringSelection().ToStdString());
683};
The bus panel, filter w r t message types (nmea2000, nmea1083, etc.).
const std::vector< DriverPtr > & GetDrivers() const
Direction panel, set up filter w r t direction (input, output, etc..) Bound to filter....
Two state button showing either an edit.
Definition edit_button.h:16
const void Notify()
Notify all listeners, no data supplied.
EventVar filter_update
Notified with filter name when filter is updated on disk.
Definition filter_dlg.h:47
EventVar filter_list_change
Notified without data when user creates or removes a filter.
Definition filter_dlg.h:44
EventVar filter_apply
Notified with filter name when applied by user.
Definition filter_dlg.h:50
Interfaces filtering panel, bound to filter.interfaces.
Message type filter setup GUI bound to filter.include_msg and filter.exclude_msg.
The raw message layer, a singleton.
const std::set< std::string > & GetActiveMessages()
Return list of message types sent or received.
static Accepted StringToAccepted(const std::string &s)
Return Accepted value corresponding to argument s.
Common base for displaying a filter set bound to the set ctor parameter.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
T * GetWindowById(int id)
Return window with given id (which must exist) casted to T*.
Dialogs handing user defined filters.
std::vector< std::string > List(bool include_system)
Return list of filters, possibly including also the system ones.
bool Write(const NavmsgFilter &filter, const std::string &name)
Write contents for given filter to disk.
Filter storage routines.