OpenCPN Partial API docs
Loading...
Searching...
No Matches
connection_edit.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2022 by David S. Register *
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, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24#include <memory>
25#include <set>
26#include <string>
27#include <vector>
28
29#include "gl_headers.h" // Must come before anything using GL stuff
30
31#include <wx/wxprec.h>
32
33#ifndef WX_PRECOMP
34#include <wx/wx.h>
35#endif
36
37#include "config.h"
38
39#include <wx/tokenzr.h>
40#include <wx/regex.h>
41
42#if defined(__linux__) && !defined(__ANDROID__)
43#include <linux/can.h>
44#include <linux/can/raw.h>
45#include <net/if.h>
46#include <serial/serial.h>
47#include <sys/ioctl.h>
48#include <sys/socket.h>
49#include "dnet.h"
50#endif
51
52#ifdef __ANDROID__
53#include "androidUTIL.h"
54#include "qdebug.h"
55#endif
56
57#include "connection_edit.h"
58
60#include "model/config_vars.h"
61#include "model/ocpn_utils.h"
62#include "model/ser_ports.h"
63#include "model/sys_events.h"
64
65#include "conn_params_panel.h"
66#include "gui_lib.h"
67#include "nmea0183.h"
68#include "ocpn_platform.h"
69#include "ocpn_plugin.h" // FIXME for GetOCPNScaledFont_PlugIn
70#include "options.h"
71#include "priority_gui.h"
72#include "udev_rule_mgr.h"
73
74static wxString StringArrayToString(const wxArrayString& arr) {
75 wxString ret = wxEmptyString;
76 for (size_t i = 0; i < arr.Count(); i++) {
77 if (i > 0) ret.Append(",");
78 ret.Append(arr[i]);
79 }
80 return ret;
81}
82
83// Check available SocketCAN interfaces
84#if defined(__linux__) && !defined(__ANDROID__)
85static intf_t* intf;
86std::vector<std::string> can_if_candidates;
87static int print_intf(const struct intf_entry* entry, void* arg) {
88 std::string iface = entry->intf_name;
89 if (entry->intf_type == 1 && iface.find("can") != std::string::npos) {
90 can_if_candidates.push_back(entry->intf_name);
91 }
92 return 0;
93}
94#endif
95
96static wxArrayString GetAvailableSocketCANInterfaces() {
97 wxArrayString rv;
98
99#if defined(__linux__) && !defined(__ANDROID__)
100 struct intf_entry* entry;
101
102 can_if_candidates.clear();
103
104 if ((intf = intf_open()) == NULL) {
105 wxLogWarning("Error opening interface list");
106 }
107
108 if (intf_loop(intf, print_intf, NULL) < 0) {
109 wxLogWarning("Error looping over interface list");
110 }
111 intf_close(intf);
112
113 for (const auto& iface : can_if_candidates) {
114 int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
115 if (sock < 0) {
116 continue;
117 }
118
119 // Get the interface index
120 struct ifreq if_request;
121 strcpy(if_request.ifr_name, iface.c_str());
122 if (ioctl(sock, SIOCGIFINDEX, &if_request) < 0) {
123 continue;
124 }
125
126 // Check if interface is UP
127 struct sockaddr_can can_address;
128 can_address.can_family = AF_CAN;
129 can_address.can_ifindex = if_request.ifr_ifindex;
130 if (ioctl(sock, SIOCGIFFLAGS, &if_request) < 0) {
131 continue;
132 }
133 if (if_request.ifr_flags & IFF_UP) {
134 rv.Add(iface);
135 } else {
136 continue;
137 }
138 }
139#endif
140 return rv;
141}
142
143static void LoadSerialPorts(wxComboBox* box) {
145 class PortSorter {
146 private:
147 std::string GetKey(const std::string& s) const {
148 if (s.find("->") == std::string::npos) return s;
149 return ocpn::trim(ocpn::split(s, "->")[1]) + " link";
150 }
151
152 public:
153 bool operator()(const std::string& lhs, const std::string& rhs) const {
154 return GetKey(lhs) < GetKey(rhs);
155 }
156 } port_sorter;
157
158 std::set<std::string, PortSorter> sorted_ports(port_sorter);
159 std::unique_ptr<wxArrayString> ports(EnumerateSerialPorts());
160 for (size_t i = 0; i < ports->GetCount(); i++)
161 sorted_ports.insert((*ports)[i].ToStdString());
162
163 auto value = box->GetValue();
164 box->Clear();
165 for (auto& p : sorted_ports) box->Append(p);
166 if (!value.empty()) box->SetValue(value);
167}
168
169//------------------------------------------------------------------------------
170// ConnectionEditDialog Implementation
171//------------------------------------------------------------------------------
172
173// Define constructors
174ConnectionEditDialog::ConnectionEditDialog() {}
175
176ConnectionEditDialog::ConnectionEditDialog(
177 wxWindow* parent,
178 std::function<void(ConnectionParams* p, bool editing, bool ok_cancel)>
179 _on_edit_click)
180 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), 0,
181 "conn_edit"),
182 m_on_edit_click(_on_edit_click) {
183 m_parent = parent;
184
185 Init();
186}
187
188ConnectionEditDialog::~ConnectionEditDialog() {}
189
190void ConnectionEditDialog::SetInitialSettings() {
191 LoadSerialPorts(m_comboPort);
192}
193
194void ConnectionEditDialog::AddOKCancelButtons() {
195#ifndef ANDROID
196 if (!m_btnSizer) {
197 m_btnSizer = new wxStdDialogButtonSizer();
198 m_btnOK = new wxButton(this, wxID_OK);
199 m_btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
200 m_btnSizer->AddButton(m_btnOK);
201 m_btnSizer->AddButton(m_btnCancel);
202 m_btnSizer->Realize();
203 GetSizer()->Add(m_btnSizer, 0, wxALL | wxEXPAND, 5);
204 m_btnSizer->Show(true);
205 }
206#else
207 if (!m_btnSizerBox) {
208 m_btnSizerBox = new wxBoxSizer(wxHORIZONTAL);
209 m_btnOK = new wxButton(this, wxID_OK);
210 m_btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
211 m_btnSizerBox->AddSpacer(wxWindow::GetCharWidth());
212 m_btnSizerBox->Add(m_btnOK, 0, wxALL, 5);
213 m_btnSizerBox->Add(m_btnCancel, 0, wxALL, 5);
214 GetSizer()->Add(m_btnSizerBox, 0, wxALL | wxEXPAND, 5);
215 }
216#endif
217
218 m_btnOK->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
219 [&](wxCommandEvent& ev) { OnOKClick(); });
220 m_btnCancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
221 [&](wxCommandEvent& ev) { OnCancelClick(); });
222}
223
224void ConnectionEditDialog::OnOKClick() {
225 m_on_edit_click(m_cp_original, new_mode, true);
226}
227
228void ConnectionEditDialog::OnCancelClick() {
229 m_on_edit_click(nullptr, false, false);
230}
231
232void ConnectionEditDialog::Init() {
233 wxFont* qFont = GetOCPNScaledFont(_("Dialog"));
234 SetFont(*qFont);
235
236 m_btnSizer = nullptr;
237 m_btnSizerBox = nullptr;
238
239 // Setup some inital values
240 m_buttonScanBT = 0;
241 m_stBTPairs = 0;
242 m_choiceBTDataSources = 0;
243
244 m_BTScanTimer.SetOwner(this, ID_BT_SCANTIMER);
245 m_BTscanning = 0;
246 wxSize displaySize = wxGetDisplaySize();
247
248 // Create the UI
249
250 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
251 SetSizer(mainSizer);
252
253#if 0
254 wxBoxSizer* boxSizer02 = new wxBoxSizer(wxVERTICAL);
255 mainSizer->Add(boxSizer02, 1, wxEXPAND | wxALL, 2);
256#endif
257
258#if 0
259 m_scrolledwin =
260 new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1),
261 wxVSCROLL | wxHSCROLL);
262 m_scrolledwin->ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_NEVER);
263 m_scrolledwin->SetScrollRate(1, 1);
264#ifdef ANDROID
265 //m_scrolledwin->SetFont(*qFont);
266 //m_scrolledwin->GetHandle()->setStyleSheet(getWideScrollBarsStyleSheet());
267 QString qtStyleSheetFont = "font: bold;background-color: red;font-size: 48px;";
268 //GetHandle()->setStyleSheet(qtStyleSheetFont);
269 //GetHandle()->setStyleSheet(getWideScrollBarsStyleSheet());
270
271#endif
272 boxSizer02->Add(m_scrolledwin, 1, wxALL | wxEXPAND, 3);
273
274 auto boxSizerSWin = new wxBoxSizer(wxVERTICAL);
275 m_scrolledwin->SetSizer(boxSizerSWin);
276 boxSizerSWin->SetSizeHints(m_scrolledwin);
277#endif
278
279 int group_item_spacing = 2;
280
281 wxFont* dFont = GetOCPNScaledFont_PlugIn(_("Dialog"));
282 double font_size = dFont->GetPointSize() * 17 / 16;
283 wxFont* bFont = wxTheFontList->FindOrCreateFont(
284 font_size, dFont->GetFamily(), dFont->GetStyle(), wxFONTWEIGHT_BOLD);
285
286 //
287 // m_stEditCon = new wxStaticText(m_pNMEAForm, wxID_ANY, _("Edit Selected
288 // Connection")); m_stEditCon->SetFont(*bFont); bSizer19->Add(m_stEditCon,
289 // 0, wxALL | wxEXPAND | wxALIGN_CENTER_HORIZONTAL, 5);
290 //
291
292 // Connections Properties
293 m_sbConnEdit = new wxStaticBox(this, wxID_ANY, _("Edit Selected Connection"));
294 m_sbConnEdit->SetFont(*bFont);
295
296 sbSizerConnectionProps = new wxStaticBoxSizer(m_sbConnEdit, wxVERTICAL);
297 GetSizer()->Add(sbSizerConnectionProps, 1, wxALL | wxEXPAND, 5);
298
299 wxBoxSizer* bSizer15;
300 bSizer15 = new wxBoxSizer(wxHORIZONTAL);
301
302 sbSizerConnectionProps->Add(bSizer15, 0, wxTOP | wxEXPAND, 5);
303
304 m_rbTypeSerial =
305 new wxRadioButton(this, wxID_ANY, _("Serial"), wxDefaultPosition,
306 wxDefaultSize, wxRB_GROUP);
307 m_rbTypeSerial->SetValue(TRUE);
308 bSizer15->Add(m_rbTypeSerial, 0, wxALL, 5);
309
310 m_rbTypeNet = new wxRadioButton(this, wxID_ANY, _("Network"),
311 wxDefaultPosition, wxDefaultSize, 0);
312 bSizer15->Add(m_rbTypeNet, 0, wxALL, 5);
313
314 m_rbTypeCAN = new wxRadioButton(this, wxID_ANY, "socketCAN",
315 wxDefaultPosition, wxDefaultSize, 0);
316#if defined(__linux__) && !defined(__ANDROID__) && !defined(__WXOSX__)
317 bSizer15->Add(m_rbTypeCAN, 0, wxALL, 5);
318#else
319 m_rbTypeCAN->Hide();
320#endif
321
322 wxBoxSizer* bSizer15a = new wxBoxSizer(wxHORIZONTAL);
323 sbSizerConnectionProps->Add(bSizer15a, 0, wxEXPAND, 5);
324
325 if (OCPNPlatform::hasInternalGPS()) {
326 m_rbTypeInternalGPS = new wxRadioButton(
327 this, wxID_ANY, _("Built-in GPS"), wxDefaultPosition, wxDefaultSize, 0);
328 bSizer15a->Add(m_rbTypeInternalGPS, 0, wxALL, 5);
329 } else
330 m_rbTypeInternalGPS = NULL;
331
332 // has built-in Bluetooth
333 if (OCPNPlatform::hasInternalBT()) {
334 m_rbTypeInternalBT =
335 new wxRadioButton(this, wxID_ANY, _("Built-in Bluetooth SPP"),
336 wxDefaultPosition, wxDefaultSize, 0);
337 bSizer15a->Add(m_rbTypeInternalBT, 0, wxALL, 5);
338
339 m_buttonScanBT = new wxButton(this, wxID_ANY, _("BT Scan") + " ",
340 wxDefaultPosition, wxDefaultSize);
341 m_buttonScanBT->Hide();
342
343 sbSizerConnectionProps->Add(m_buttonScanBT, 0, wxALL, 25);
344
345 m_stBTPairs = new wxStaticText(this, wxID_ANY, _("Bluetooth Data Sources"),
346 wxDefaultPosition, wxDefaultSize, 0);
347 m_stBTPairs->Wrap(-1);
348 m_stBTPairs->Hide();
349 sbSizerConnectionProps->Add(m_stBTPairs, 0, wxALL, 5);
350
351 wxArrayString mt;
352 mt.Add("unscanned");
353
354 int ref_size = this->GetCharWidth();
355 m_choiceBTDataSources =
356 new wxChoice(this, wxID_ANY, wxDefaultPosition,
357 wxSize(40 * ref_size, 2 * ref_size), mt);
358 m_choiceBTDataSources->SetSelection(0);
359 m_choiceBTDataSources->Hide();
360 sbSizerConnectionProps->Add(m_choiceBTDataSources, 1, wxEXPAND | wxTOP, 25);
361
362 } else
363 m_rbTypeInternalBT = NULL;
364
365 gSizerNetProps = new wxFlexGridSizer(0, 2, 0, 0);
366
367 sbSizerConnectionProps->Add(gSizerNetProps, 0, wxEXPAND, 5);
368
369 m_stNetProto = new wxStaticText(this, wxID_ANY, _("Network Protocol"),
370 wxDefaultPosition, wxDefaultSize, 0);
371 m_stNetProto->Wrap(-1);
372 gSizerNetProps->Add(m_stNetProto, 0, wxALL, 5);
373
374 wxBoxSizer* bSizer16;
375 bSizer16 = new wxBoxSizer(wxHORIZONTAL);
376 gSizerNetProps->Add(bSizer16, 1, wxEXPAND, 5);
377 gSizerNetProps->AddSpacer(1);
378 gSizerNetProps->AddSpacer(1);
379
380 m_rbNetProtoTCP = new wxRadioButton(
381 this, wxID_ANY, _("TCP"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
382 m_rbNetProtoTCP->Enable(TRUE);
383 m_rbNetProtoTCP->SetValue(TRUE);
384
385 bSizer16->Add(m_rbNetProtoTCP, 0, wxALL, 5);
386
387 m_rbNetProtoUDP = new wxRadioButton(this, wxID_ANY, _("UDP"),
388 wxDefaultPosition, wxDefaultSize, 0);
389 m_rbNetProtoUDP->Enable(TRUE);
390
391 bSizer16->Add(m_rbNetProtoUDP, 0, wxALL, 5);
392
393 // Optimize for Portrait mode handheld devices
394 if (displaySize.x < displaySize.y) {
395 wxBoxSizer* bSizer16a;
396 bSizer16a = new wxBoxSizer(wxHORIZONTAL);
397 gSizerNetProps->AddSpacer(1);
398 gSizerNetProps->Add(bSizer16a, 1, wxEXPAND, 5);
399 gSizerNetProps->AddSpacer(1);
400 gSizerNetProps->AddSpacer(1);
401 m_rbNetProtoGPSD = new wxRadioButton(this, wxID_ANY, _("GPSD"),
402 wxDefaultPosition, wxDefaultSize, 0);
403 m_rbNetProtoGPSD->Enable(TRUE);
404 bSizer16a->Add(m_rbNetProtoGPSD, 0, wxALL, 5);
405
406 m_rbNetProtoSignalK = new wxRadioButton(
407 this, wxID_ANY, _("Signal K"), wxDefaultPosition, wxDefaultSize, 0);
408 m_rbNetProtoSignalK->Enable(TRUE);
409 bSizer16a->Add(m_rbNetProtoSignalK, 0, wxALL, 5);
410 } else {
411 m_rbNetProtoGPSD = new wxRadioButton(this, wxID_ANY, _("GPSD"),
412 wxDefaultPosition, wxDefaultSize, 0);
413 m_rbNetProtoGPSD->Enable(TRUE);
414 bSizer16->Add(m_rbNetProtoGPSD, 0, wxALL, 5);
415
416 m_rbNetProtoSignalK = new wxRadioButton(
417 this, wxID_ANY, _("Signal K"), wxDefaultPosition, wxDefaultSize, 0);
418 m_rbNetProtoSignalK->Enable(TRUE);
419 bSizer16->Add(m_rbNetProtoSignalK, 0, wxALL, 5);
420 }
421
422 m_stNetDataProtocol = new wxStaticText(this, wxID_ANY, _("Data Protocol"),
423 wxDefaultPosition, wxDefaultSize, 0);
424 m_stNetDataProtocol->Wrap(-1);
425
426 gSizerNetProps->Add(m_stNetDataProtocol, 0, wxALL, 5);
427
428 wxString m_choiceNetProtocolChoices[] = {_("NMEA 0183"), _("NMEA 2000")};
429 int m_choiceNetProtocolNChoices =
430 sizeof(m_choiceNetProtocolChoices) / sizeof(wxString);
431 m_choiceNetDataProtocol =
432 new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
433 m_choiceNetProtocolNChoices, m_choiceNetProtocolChoices, 0);
434 // m_choiceNetDataProtocol->Bind(wxEVT_MOUSEWHEEL,
435 // &ConnectionEditDialog::OnWheelChoice, this);
436 m_choiceNetDataProtocol->SetSelection(0);
437 m_choiceNetDataProtocol->Enable(TRUE);
438
439 gSizerNetProps->Add(m_choiceNetDataProtocol, 1, wxEXPAND | wxTOP, 5);
440 gSizerNetProps->AddSpacer(1);
441 gSizerNetProps->AddSpacer(1);
442
443 m_stNetAddr = new wxStaticText(this, wxID_ANY, _("Address"),
444 wxDefaultPosition, wxDefaultSize, 0);
445 m_stNetAddr->Wrap(-1);
446 int column1width = 16 * m_stNetProto->GetCharWidth();
447 m_stNetAddr->SetMinSize(wxSize(column1width, -1));
448 gSizerNetProps->Add(m_stNetAddr, 0, wxALL, 5);
449
450 m_tNetAddress = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
451 wxDefaultPosition, wxDefaultSize, 0);
452 int column2width = 40 * this->GetCharWidth();
453 m_tNetAddress->SetMaxSize(wxSize(column2width, -1));
454 m_tNetAddress->SetMinSize(wxSize(column2width, -1));
455
456 gSizerNetProps->Add(m_tNetAddress, 0, wxEXPAND | wxTOP, 5);
457 gSizerNetProps->AddSpacer(1);
458 gSizerNetProps->AddSpacer(1);
459
460 m_stNetPort = new wxStaticText(this, wxID_ANY, _("DataPort"),
461 wxDefaultPosition, wxDefaultSize, 0);
462 m_stNetPort->Wrap(-1);
463 gSizerNetProps->Add(m_stNetPort, 0, wxALL, 5);
464
465 m_tNetPort = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
466 wxDefaultSize, 0);
467 gSizerNetProps->Add(m_tNetPort, 1, wxEXPAND | wxTOP, 5);
468 gSizerNetProps->AddSpacer(1);
469 gSizerNetProps->AddSpacer(1);
470
471 gSizerCanProps = new wxGridSizer(0, 1, 0, 0);
472
473 wxFlexGridSizer* fgSizer1C;
474 fgSizer1C = new wxFlexGridSizer(0, 2, 0, 0);
475 // fgSizer1C->SetFlexibleDirection(wxBOTH);
476 // fgSizer1C->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
477
478 m_stCANSource = new wxStaticText(this, wxID_ANY, _("socketCAN Source"),
479 wxDefaultPosition, wxDefaultSize, 0);
480 m_stCANSource->Wrap(-1);
481 m_stCANSource->SetMinSize(wxSize(column1width, -1));
482 fgSizer1C->Add(m_stCANSource, 0, wxALL, 5);
483
484 wxArrayString choices = GetAvailableSocketCANInterfaces();
485 m_choiceCANSource =
486 new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices);
487
488 m_choiceCANSource->SetSelection(0);
489 m_choiceCANSource->Enable(TRUE);
490 m_choiceCANSource->SetMaxSize(wxSize(column2width, -1));
491 m_choiceCANSource->SetMinSize(wxSize(column2width, -1));
492 fgSizer1C->Add(m_choiceCANSource, 1, wxEXPAND | wxTOP, 5);
493
494 gSizerCanProps->Add(fgSizer1C, 0, wxEXPAND, 5);
495
496 sbSizerConnectionProps->Add(gSizerCanProps, 0, wxEXPAND, 5);
497
498 gSizerSerProps = new wxGridSizer(0, 1, 0, 0);
499 sbSizerConnectionProps->Add(gSizerSerProps, 0, wxEXPAND, 5);
500
501 wxFlexGridSizer* fgSizer1;
502 fgSizer1 = new wxFlexGridSizer(0, 4, 0, 0);
503 fgSizer1->SetFlexibleDirection(wxBOTH);
504 fgSizer1->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
505
506 m_stSerPort =
507 new wxStaticText(this, wxID_ANY, _("Data port"), wxDefaultPosition,
508 wxDefaultSize, wxST_ELLIPSIZE_END);
509 m_stSerPort->SetMinSize(wxSize(column1width, -1));
510 m_stSerPort->Wrap(-1);
511
512 fgSizer1->Add(m_stSerPort, 0, wxALL, 5);
513
514 m_comboPort = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
515 wxDefaultSize, 0, NULL, 0);
516
517 m_comboPort->SetMaxSize(wxSize(column2width, -1));
518 m_comboPort->SetMinSize(wxSize(column2width, -1));
519
520 fgSizer1->Add(m_comboPort, 0, wxEXPAND | wxTOP, 5);
521
522 m_stSerBaudrate = new wxStaticText(this, wxID_ANY, _("Baudrate"),
523 wxDefaultPosition, wxDefaultSize, 0);
524 m_stSerBaudrate->Wrap(-1);
525 fgSizer1->AddSpacer(1);
526 fgSizer1->AddSpacer(1);
527 fgSizer1->Add(m_stSerBaudrate, 0, wxALL, 5);
528
529 wxString m_choiceBaudRateChoices[] = {
530 _("150"), _("300"), _("600"), _("1200"), _("2400"),
531 _("4800"), _("9600"), _("19200"), _("38400"), _("57600"),
532 _("115200"), _("230400"), _("460800"), _("921600")};
533 int m_choiceBaudRateNChoices =
534 sizeof(m_choiceBaudRateChoices) / sizeof(wxString);
535 m_choiceBaudRate =
536 new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
537 m_choiceBaudRateNChoices, m_choiceBaudRateChoices, 0);
538 // m_choiceBaudRate->Bind(wxEVT_MOUSEWHEEL,
539 // &ConnectionEditDialog::OnWheelChoice, this);
540
541 m_choiceBaudRate->SetSelection(0);
542
543 fgSizer1->Add(m_choiceBaudRate, 1, wxEXPAND | wxTOP, 5);
544 fgSizer1->AddSpacer(1);
545 fgSizer1->AddSpacer(1);
546
547 m_stSerProtocol = new wxStaticText(this, wxID_ANY, _("Protocol"),
548 wxDefaultPosition, wxDefaultSize, 0);
549 m_stSerProtocol->Wrap(-1);
550 fgSizer1->Add(m_stSerProtocol, 0, wxALL, 5);
551
552 wxString m_choiceSerialProtocolChoices[] = {_("NMEA 0183"), _("NMEA 2000")};
553 int m_choiceSerialProtocolNChoices =
554 sizeof(m_choiceSerialProtocolChoices) / sizeof(wxString);
555 m_choiceSerialProtocol = new wxChoice(
556 this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
557 m_choiceSerialProtocolNChoices, m_choiceSerialProtocolChoices, 0);
558 // m_choiceSerialProtocol->Bind(wxEVT_MOUSEWHEEL,
559 // &ConnectionEditDialog::OnWheelChoice, this);
560
561 m_choiceSerialProtocol->SetSelection(0);
562 m_choiceSerialProtocol->Enable(TRUE);
563 fgSizer1->Add(m_choiceSerialProtocol, 1, wxEXPAND | wxTOP, 5);
564
565 gSizerSerProps->Add(fgSizer1, 0, wxEXPAND, 5);
566
567 // User Comments
568
569 wxFlexGridSizer* commentSizer = new wxFlexGridSizer(0, 2, 0, 0);
570 // sbSizerConnectionProps->Add(commentSizer, 0, wxEXPAND, 5);
571
572 // Net User Comments
573 m_stNetComment = new wxStaticText(this, wxID_ANY, _("Description"),
574 wxDefaultPosition, wxDefaultSize, 0);
575 m_stNetComment->Wrap(-1);
576 m_stNetComment->SetMinSize(wxSize(column1width, -1));
577 commentSizer->Add(m_stNetComment, 0, wxALL, 5);
578
579 m_tNetComment = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
580 wxDefaultPosition, wxDefaultSize, 0);
581 m_tNetComment->SetMaxSize(wxSize(column2width, -1));
582 m_tNetComment->SetMinSize(wxSize(column2width, -1));
583
584 commentSizer->Add(m_tNetComment, 1, wxEXPAND | wxTOP, 5);
585
586 // Serial User Comments
587 m_stSerialComment = new wxStaticText(this, wxID_ANY, _("User Comment"),
588 wxDefaultPosition, wxDefaultSize, 0);
589 m_stSerialComment->Wrap(-1);
590 m_stSerialComment->SetMinSize(wxSize(column1width, -1));
591 commentSizer->Add(m_stSerialComment, 0, wxALL, 5);
592
593 m_tSerialComment = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
594 wxDefaultPosition, wxDefaultSize, 0);
595 m_tSerialComment->SetMaxSize(wxSize(column2width, -1));
596 m_tSerialComment->SetMinSize(wxSize(column2width, -1));
597
598 commentSizer->Add(m_tSerialComment, 1, wxTOP, 5);
599
600 sbSizerConnectionProps->Add(commentSizer, 0, wxEXPAND, 5);
601
602 wxFlexGridSizer* fgSizer5;
603 fgSizer5 = new wxFlexGridSizer(0, 2, 0, 0);
604 fgSizer5->SetFlexibleDirection(wxBOTH);
605 fgSizer5->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
606 sbSizerConnectionProps->Add(fgSizer5, 0, wxEXPAND, 5);
607
608 m_cbInput = new wxCheckBox(this, wxID_ANY, _("Receive Input on this Port"),
609 wxDefaultPosition, wxDefaultSize, 0);
610 fgSizer5->Add(m_cbInput, 0, wxALL, 2);
611 fgSizer5->AddSpacer(1);
612
613 m_cbOutput =
614 new wxCheckBox(this, wxID_ANY,
615 wxString::Format("%s (%s)", _("Output on this port"),
616 _("as autopilot or NMEA repeater")),
617 wxDefaultPosition, wxDefaultSize, 0);
618 fgSizer5->Add(m_cbOutput, 0, wxALL, 2);
619 fgSizer5->AddSpacer(1);
620
621 // Authentication token
622
623 auto flags = wxSizerFlags().Border();
624 m_collapse_box = new wxBoxSizer(wxHORIZONTAL);
625
626 m_collapse_box->Add(new wxStaticText(this, wxID_ANY, _("Advanced: ")), flags);
627 m_collapse_box->Add(
628 new ExpandableIcon(this,
629 [&](bool collapsed) { OnCollapsedToggle(collapsed); }),
630 flags);
631 fgSizer5->Add(m_collapse_box, wxSizerFlags());
632 fgSizer5->Add(new wxStaticText(this, wxID_ANY, ""));
633
634 m_stAuthToken = new wxStaticText(this, wxID_ANY, _("Auth Token"),
635 wxDefaultPosition, wxDefaultSize, 0);
636 m_stAuthToken->SetMinSize(wxSize(column1width, -1));
637 m_stAuthToken->Wrap(-1);
638 fgSizer5->Add(m_stAuthToken, 0, wxALL, 5);
639 m_stAuthToken->Hide();
640
641 m_tAuthToken = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
642 wxDefaultPosition, wxDefaultSize, 0);
643 m_tAuthToken->SetMinSize(wxSize(column2width, -1));
644 fgSizer5->Add(m_tAuthToken, 1, wxEXPAND | wxTOP, 5);
645
646 m_tAuthToken->Hide();
647
648 m_cbGarminHost =
649 new wxCheckBox(this, wxID_ANY, _("Use Garmin (GRMN) mode for input"),
650 wxDefaultPosition, wxDefaultSize, 0);
651 m_cbGarminHost->SetValue(FALSE);
652 fgSizer5->Add(m_cbGarminHost, 0, wxALL, 2);
653 fgSizer5->AddSpacer(1);
654
655#ifndef USE_GARMINHOST
656 m_cbGarminHost->Hide();
657#endif
658
659 m_cbMultiCast = new wxCheckBox(this, wxID_ANY, _(" UDP Multicast"),
660 wxDefaultPosition, wxDefaultSize, 0);
661 m_cbMultiCast->SetValue(FALSE);
662 // m_cbMultiCast->SetToolTip(_("Advanced Use Only. Enable UDP Multicast."));
663
664 fgSizer5->Add(m_cbMultiCast, 0, wxALL, 2);
665 fgSizer5->AddSpacer(1);
666
667 m_stPrecision = new wxStaticText(this, wxID_ANY, _("APB bearing precision"),
668 wxDefaultPosition, wxDefaultSize, 0);
669
670 m_stPrecision->Wrap(-1);
671 fgSizer5->Add(m_stPrecision, 0, wxALL, 2);
672
673 wxString m_choicePrecisionChoices[] = {_("x"), _("x.x"), _("x.xx"),
674 _("x.xxx"), _("x.xxxx")};
675 int m_choicePrecisionNChoices =
676 sizeof(m_choicePrecisionChoices) / sizeof(wxString);
677 m_choicePrecision =
678 new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
679 m_choicePrecisionNChoices, m_choicePrecisionChoices, 0);
680 // m_choicePrecision->Bind(wxEVT_MOUSEWHEEL,
681 // &ConnectionEditDialog::OnWheelChoice, this);
682
683 m_choicePrecision->SetSelection(g_NMEAAPBPrecision);
684 fgSizer5->Add(m_choicePrecision, 0, wxALL, 2);
685
686 // signalK discovery enable
687 m_cbCheckSKDiscover =
688 new wxCheckBox(this, wxID_ANY, _("Automatic server discovery"),
689 wxDefaultPosition, wxDefaultSize, 0);
690 m_cbCheckSKDiscover->SetValue(TRUE);
691 m_cbCheckSKDiscover->SetToolTip(
692 _("If checked, signal K server will be discovered automatically"));
693
694 fgSizer5->Add(m_cbCheckSKDiscover, 0, wxALL, 2);
695
696 // signal K "Discover now" button
697 m_ButtonSKDiscover = new wxButton(this, wxID_ANY, _("Discover now..."),
698 wxDefaultPosition, wxDefaultSize, 0);
699 m_ButtonSKDiscover->Hide();
700 fgSizer5->Add(m_ButtonSKDiscover, 0, wxALL, 2);
701
702 // signalK Server Status
703 m_StaticTextSKServerStatus =
704 new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0);
705 fgSizer5->Add(m_StaticTextSKServerStatus, 0, wxALL, 2);
706
707 sbSizerInFilter = new wxStaticBoxSizer(
708 new wxStaticBox(this, wxID_ANY, _("Input filtering")), wxVERTICAL);
709 sbSizerConnectionProps->Add(sbSizerInFilter,
710 wxSizerFlags().Expand().Border());
711
712 wxBoxSizer* bSizer9;
713 bSizer9 = new wxBoxSizer(wxHORIZONTAL);
714
715 m_rbIAccept = new wxRadioButton(this, wxID_ANY, _("Accept only sentences"),
716 wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
717 bSizer9->Add(m_rbIAccept, 0, wxALL, 5);
718
719 m_rbIIgnore = new wxRadioButton(this, wxID_ANY, _("Ignore sentences"),
720 wxDefaultPosition, wxDefaultSize, 0);
721 bSizer9->Add(m_rbIIgnore, 0, wxALL, 5);
722
723 sbSizerInFilter->Add(bSizer9, 0, wxEXPAND, 5);
724
725 wxBoxSizer* bSizer11;
726 bSizer11 = new wxBoxSizer(wxHORIZONTAL);
727 sbSizerInFilter->Add(bSizer11, 0, wxEXPAND, 5);
728
729 m_tcInputStc =
730 new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
731 wxDefaultSize, wxTE_READONLY);
732 bSizer11->Add(m_tcInputStc, 1, wxALL | wxEXPAND, 5);
733
734 m_btnInputStcList = new wxButton(this, wxID_ANY, "...", wxDefaultPosition,
735 wxDefaultSize, wxBU_EXACTFIT);
736 bSizer11->Add(m_btnInputStcList, 0, wxALL, 5);
737
738 bSizer11->AddSpacer(GetCharWidth() * 5);
739
740 sbSizerOutFilter = new wxStaticBoxSizer(
741 new wxStaticBox(this, wxID_ANY, _("Output filtering")), wxVERTICAL);
742 sbSizerConnectionProps->Add(sbSizerOutFilter, 0, wxEXPAND, 5);
743
744 wxBoxSizer* bSizer10;
745 bSizer10 = new wxBoxSizer(wxHORIZONTAL);
746
747 m_rbOAccept = new wxRadioButton(this, wxID_ANY, _("Transmit sentences"),
748 wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
749 bSizer10->Add(m_rbOAccept, 0, wxALL, 5);
750
751 m_rbOIgnore = new wxRadioButton(this, wxID_ANY, _("Drop sentences"),
752 wxDefaultPosition, wxDefaultSize, 0);
753 bSizer10->Add(m_rbOIgnore, 0, wxALL, 5);
754
755 sbSizerOutFilter->Add(bSizer10, 0, wxEXPAND, 5);
756
757 wxBoxSizer* bSizer12;
758 bSizer12 = new wxBoxSizer(wxHORIZONTAL);
759 sbSizerOutFilter->Add(bSizer12, 0, wxEXPAND, 5);
760
761 m_tcOutputStc =
762 new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
763 wxDefaultSize, wxTE_READONLY);
764 bSizer12->Add(m_tcOutputStc, 1, wxALL | wxEXPAND, 5);
765
766 m_btnOutputStcList = new wxButton(this, wxID_ANY, "...", wxDefaultPosition,
767 wxDefaultSize, wxBU_EXACTFIT);
768 bSizer12->Add(m_btnOutputStcList, 0, wxALL, 5);
769
770 bSizer12->AddSpacer(GetCharWidth() * 5);
771
772 sbSizerConnectionProps->AddSpacer(20);
773
774 ConnectControls();
775
776 SetInitialSettings();
777
778 ShowTypeCommon();
779
780 ShowNMEACommon(true);
781 ShowNMEASerial(true);
782 ShowNMEANet(false);
783 ShowNMEACAN(false);
784 connectionsaved = TRUE;
785
786 GetSizer()->Fit(this);
787
788 new_device_listener.Init(SystemEvents::GetInstance().evt_dev_change,
789 [&](ObservedEvt&) { LoadSerialPorts(m_comboPort); });
790}
791
792// void ConnectionEditDialog::OnWheelChoice(wxMouseEvent& event) {
793// return;
794// }
795
796void ConnectionEditDialog::SetSelectedConnectionPanel(
797 ConnectionParamsPanel* panel) {
798 // Only one panel can be selected at any time
799 // Clear any selections
800
801 if (mSelectedConnection && mSelectedConnection->m_optionsPanel)
802 mSelectedConnection->m_optionsPanel->SetSelected(false);
803
804 if (panel) {
805 mSelectedConnection = panel->m_pConnectionParams;
806 panel->SetSelected(true);
807 SetConnectionParams(mSelectedConnection);
808 m_buttonRemove->Enable();
809 m_buttonRemove->Show();
810 m_buttonAdd->Disable();
811 m_sbConnEdit->SetLabel(_("Edit Selected Connection"));
812
813 } else {
814 mSelectedConnection = NULL;
815 m_buttonRemove->Disable();
816 m_buttonAdd->Enable();
817 m_buttonAdd->Show();
818 m_sbConnEdit->SetLabel("");
819 ClearNMEAForm();
820 }
821
822 // Scroll the panel to allow the user to see more of the NMEA parameter
823 // settings area
824 // wxPoint buttonPosition = m_buttonAdd->GetPosition();
825 // this->Scroll(-1, buttonPosition.y / m_parent->GetScrollRate());
826}
827
828void ConnectionEditDialog::SetPropsLabel(wxString label) {
829 m_sbConnEdit->SetLabel(label);
830}
831
832void ConnectionEditDialog::EnableConnection(ConnectionParams* conn,
833 bool value) {
834 if (conn) {
835 // conn->bEnabled = value;
836 conn->b_IsSetup = FALSE; // trigger a rebuild/takedown of the connection
837 m_connection_enabled = conn->bEnabled;
838 }
839}
840
841#if 1
842void ConnectionEditDialog::OnValChange(wxCommandEvent& event) { event.Skip(); }
843
844void ConnectionEditDialog::OnScanBTClick(wxCommandEvent& event) {
845 if (m_BTscanning)
846 StopBTScan();
847 else {
848 m_btNoChangeCounter = 0;
849 m_btlastResultCount = 0;
850
851 Bind(wxEVT_TIMER, &ConnectionEditDialog::onBTScanTimer, this,
852 ID_BT_SCANTIMER);
853 m_BTScanTimer.Start(1000, wxTIMER_CONTINUOUS);
854 g_Platform->startBluetoothScan();
855 m_BTscanning = 1;
856 if (m_buttonScanBT) {
857 m_buttonScanBT->SetLabel(_("Stop Scan"));
858 }
859 }
860}
861
862void ConnectionEditDialog::onBTScanTimer(wxTimerEvent& event) {
863 if (m_BTscanning) {
864 m_BTscanning++;
865
866 m_BTscan_results = g_Platform->getBluetoothScanResults();
867
868 m_choiceBTDataSources->Clear();
869 m_choiceBTDataSources->Append(m_BTscan_results[0]); // scan status
870
871 unsigned int i = 1;
872 while ((i + 1) < m_BTscan_results.GetCount()) {
873 wxString item1 = m_BTscan_results[i] + ";";
874 wxString item2 = m_BTscan_results.Item(i + 1);
875 m_choiceBTDataSources->Append(item1 + item2);
876
877 i += 2;
878 }
879
880 if (m_BTscan_results.GetCount() > 1) {
881 m_choiceBTDataSources->SetSelection(1);
882 }
883
884 // Watch for changes. When no changes occur after n seconds, stop the scan
885 if (m_btNoChangeCounter > 5) StopBTScan();
886
887 if ((int)m_BTscan_results.GetCount() == m_btlastResultCount)
888 m_btNoChangeCounter++;
889 else
890 m_btNoChangeCounter = 0;
891
892 m_btlastResultCount = m_BTscan_results.GetCount();
893
894 // Absolute fallback
895 if (m_BTscanning >= 15) {
896 StopBTScan();
897 }
898 } else {
899 }
900 return;
901}
902
903void ConnectionEditDialog::StopBTScan() {
904 m_BTScanTimer.Stop();
905
906 g_Platform->stopBluetoothScan();
907
908 m_BTscanning = 0;
909
910 if (m_buttonScanBT) {
911 m_buttonScanBT->SetLabel(_("BT Scan"));
912 m_buttonScanBT->Enable();
913 }
914}
915
916void ConnectionEditDialog::OnConnValChange(wxCommandEvent& event) {
917 connectionsaved = FALSE;
918 event.Skip();
919}
920
921void ConnectionEditDialog::OnTypeSerialSelected(wxCommandEvent& event) {
922 OnConnValChange(event);
923 SetNMEAFormToSerial();
924}
925
926void ConnectionEditDialog::OnTypeNetSelected(wxCommandEvent& event) {
927 OnConnValChange(event);
928 SetNMEAFormToNet();
929}
930
931void ConnectionEditDialog::OnTypeCANSelected(wxCommandEvent& event) {
932 OnConnValChange(event);
933 SetNMEAFormToCAN();
934}
935
936void ConnectionEditDialog::OnTypeGPSSelected(wxCommandEvent& event) {
937 OnConnValChange(event);
938 SetNMEAFormToGPS();
939}
940
941void ConnectionEditDialog::OnTypeBTSelected(wxCommandEvent& event) {
942 OnConnValChange(event);
943 SetNMEAFormToBT();
944}
945
946void ConnectionEditDialog::OnUploadFormatChange(wxCommandEvent& event) {
947 if (event.GetEventObject() == m_cbGarminUploadHost && event.IsChecked())
948 m_cbFurunoGP3X->SetValue(FALSE);
949 else if (event.GetEventObject() == m_cbFurunoGP3X && event.IsChecked())
950 m_cbGarminUploadHost->SetValue(FALSE);
951
952 OnConnValChange(event);
953 event.Skip();
954}
955#endif
956
957void ConnectionEditDialog::ShowTypeCommon(bool visible) {
958 m_rbTypeSerial->Show(visible);
959 m_rbTypeNet->Show(visible);
960#if defined(__linux__) && !defined(__ANDROID__) && !defined(__WXOSX__)
961 m_rbTypeCAN->Show(visible);
962#endif
963 if (m_rbTypeInternalGPS) m_rbTypeInternalGPS->Show(visible);
964 if (m_rbTypeInternalBT) m_rbTypeInternalBT->Show(visible);
965}
966
967void ConnectionEditDialog::ShowNMEACommon(bool visible) {
968 bool advanced = m_advanced;
969 m_cbInput->Show(visible);
970 m_cbOutput->Show(visible);
971 m_stPrecision->Show(visible && advanced);
972 m_choicePrecision->Show(visible && advanced);
973 m_stPrecision->Show(visible && advanced);
974 m_stAuthToken->Show(visible && advanced);
975 m_tAuthToken->Show(visible && advanced);
976 if (visible) {
977 const bool bout_enable = (m_cbOutput->IsChecked() && advanced);
978 m_stPrecision->Enable(bout_enable);
979 m_choicePrecision->Enable(bout_enable);
980 } else {
981 sbSizerOutFilter->SetDimension(0, 0, 0, 0);
982 sbSizerInFilter->SetDimension(0, 0, 0, 0);
983 sbSizerConnectionProps->SetDimension(0, 0, 0, 0);
984 m_sbConnEdit->SetLabel("");
985 }
986
987 m_cbCheckSKDiscover->Hide(); // Provisional
988 m_ButtonSKDiscover->Hide();
989
990 const bool bin_enable = (m_cbInput->IsChecked() && advanced);
991 ShowInFilter(visible && bin_enable);
992 const bool bout_enable = (m_cbOutput->IsChecked() && advanced);
993 ShowOutFilter(visible && bout_enable);
994
995 m_bNMEAParams_shown = visible;
996}
997
998void ConnectionEditDialog::ShowNMEANet(bool visible) {
999 bool advanced = m_advanced;
1000 m_stNetAddr->Show(visible);
1001 m_tNetAddress->Show(visible);
1002 m_stNetDataProtocol->Show(visible);
1003 m_stNetPort->Show(visible);
1004 m_choiceNetDataProtocol->Show(visible);
1005 m_tNetPort->Show(visible);
1006 m_stNetProto->Show(visible);
1007 m_rbNetProtoSignalK->Show(visible);
1008 m_rbNetProtoGPSD->Show(visible);
1009 m_rbNetProtoTCP->Show(visible);
1010 m_rbNetProtoUDP->Show(visible);
1011 m_stNetComment->Show(visible);
1012 m_tNetComment->Show(visible);
1013 m_stAuthToken->Show(visible);
1014 m_tAuthToken->Show(visible);
1015 m_cbGarminHost->Hide();
1016}
1017
1018void ConnectionEditDialog::ShowNMEASerial(bool visible) {
1019 bool advanced = m_advanced;
1020 m_stSerBaudrate->Show(visible);
1021 m_choiceBaudRate->Show(visible);
1022 m_stSerPort->Show(visible);
1023 m_comboPort->Show(visible);
1024 m_stSerProtocol->Show(visible);
1025 m_choiceSerialProtocol->Show(visible);
1026 m_cbGarminHost->Show(visible && advanced);
1027 m_stSerialComment->Show(visible);
1028 m_tSerialComment->Show(visible);
1029}
1030
1031void ConnectionEditDialog::ShowNMEAGPS(bool visible) {
1032 m_cbCheckSKDiscover->Hide();
1033 m_ButtonSKDiscover->Hide();
1034 m_stAuthToken->Hide();
1035 m_tAuthToken->Hide();
1036 m_cbOutput->Hide();
1037}
1038
1039void ConnectionEditDialog::ShowNMEACAN(bool visible) {
1040 m_stCANSource->Show(visible);
1041 m_choiceCANSource->Show(visible);
1042}
1043
1044void ConnectionEditDialog::ShowNMEABT(bool visible) {
1045 if (visible) {
1046 if (m_buttonScanBT) m_buttonScanBT->Show();
1047 if (m_stBTPairs) m_stBTPairs->Show();
1048 if (m_choiceBTDataSources) {
1049 if (m_choiceBTDataSources->GetCount() > 1)
1050 m_choiceBTDataSources->SetSelection(1);
1051 m_choiceBTDataSources->Show();
1052 }
1053 } else {
1054 if (m_buttonScanBT) m_buttonScanBT->Hide();
1055 if (m_stBTPairs) m_stBTPairs->Hide();
1056 if (m_choiceBTDataSources) m_choiceBTDataSources->Hide();
1057 }
1058 m_cbCheckSKDiscover->Hide();
1059 m_stAuthToken->Hide();
1060 m_tAuthToken->Hide();
1061 m_cbCheckSKDiscover->Hide(); // Provisional
1062 m_ButtonSKDiscover->Hide();
1063 m_tcOutputStc->Show(visible);
1064 m_btnOutputStcList->Show(visible);
1065 m_cbOutput->Show(visible);
1066}
1067
1068void ConnectionEditDialog::SetNMEAFormToSerial() {
1069 bool advanced = m_advanced;
1070 ShowNMEACommon(TRUE);
1071 ShowNMEANet(FALSE);
1072 ShowNMEAGPS(FALSE);
1073 ShowNMEABT(FALSE);
1074 ShowNMEASerial(TRUE);
1075 ShowNMEACAN(FALSE);
1076 SetDSFormRWStates();
1077 LayoutDialog();
1078}
1079
1080void ConnectionEditDialog::SetNMEAFormToNet() {
1081 bool advanced = m_advanced;
1082 ShowNMEACommon(TRUE);
1083 ShowNMEANet(TRUE);
1084 ShowNMEAGPS(FALSE);
1085 ShowNMEABT(FALSE);
1086 ShowNMEASerial(FALSE);
1087 ShowNMEACAN(FALSE);
1088 SetUDPNetAddressVisiblity();
1089 SetDSFormRWStates();
1090
1091 LayoutDialog();
1092}
1093
1094void ConnectionEditDialog::SetNMEAFormToCAN() {
1095 bool advanced = m_advanced;
1096 ShowNMEACommon(FALSE);
1097 ShowNMEANet(FALSE);
1098 ShowNMEAGPS(FALSE);
1099 ShowNMEABT(FALSE);
1100 ShowNMEASerial(FALSE);
1101 ShowNMEACAN(TRUE);
1102 sbSizerInFilter->Show(false);
1103 sbSizerOutFilter->Show(false);
1104 SetDSFormRWStates();
1105
1106 LayoutDialog();
1107}
1108
1109void ConnectionEditDialog::SetNMEAFormToGPS() {
1110 ShowNMEACommon(TRUE);
1111 ShowNMEANet(FALSE);
1112 ShowNMEAGPS(TRUE);
1113 ShowNMEABT(FALSE);
1114 ShowNMEASerial(FALSE);
1115 ShowNMEACAN(FALSE);
1116
1117 // m_container->FitInside();
1118 // Fit();
1119 SetDSFormRWStates();
1120 LayoutDialog();
1121}
1122
1123void ConnectionEditDialog::SetNMEAFormToBT() {
1124 m_rbNetProtoUDP->SetValue(true);
1125 ShowNMEACommon(TRUE);
1126 ShowNMEANet(FALSE);
1127 ShowNMEAGPS(FALSE);
1128 ShowNMEABT(TRUE);
1129 ShowNMEASerial(FALSE);
1130 ShowNMEACAN(FALSE);
1131
1132 // m_container->FitInside();
1133 // Fit();
1134 SetDSFormRWStates();
1135 LayoutDialog();
1136}
1137
1138void ConnectionEditDialog::ClearNMEAForm() {
1139 ShowNMEACommon(FALSE);
1140 ShowNMEANet(FALSE);
1141 ShowNMEAGPS(FALSE);
1142 ShowNMEABT(FALSE);
1143 ShowNMEASerial(FALSE);
1144 ShowNMEACAN(FALSE);
1145
1146 // m_container->FitInside();
1147 // Fit();
1148}
1149
1150void ConnectionEditDialog::SetDSFormOptionVizStates() {
1151 bool advanced = m_advanced;
1152 m_collapse_box->ShowItems(true);
1153 m_cbInput->Show();
1154 m_cbOutput->Show();
1155 m_stPrecision->Show(true);
1156 m_choicePrecision->Show(true);
1157
1158 ShowInFilter(advanced);
1159 ShowOutFilter(advanced);
1160 // Discovery hidden until it works.
1161 // m_cbCheckSKDiscover->Show();
1162 m_stAuthToken->Show(advanced);
1163 m_tAuthToken->Show(advanced);
1164 // m_ButtonSKDiscover->Show();
1165 m_StaticTextSKServerStatus->Show(advanced);
1166
1167 if (m_rbTypeSerial->GetValue()) {
1168 m_cbMultiCast->Hide();
1169 m_cbCheckSKDiscover->Hide();
1170 m_stAuthToken->Hide();
1171 m_tAuthToken->Hide();
1172 m_ButtonSKDiscover->Hide();
1173 m_StaticTextSKServerStatus->Hide();
1174 bool n0183ctlenabled =
1175 (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1176 DataProtocol::PROTO_NMEA0183;
1177 bool n2kctlenabled = (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1178 DataProtocol::PROTO_NMEA2000;
1179 if (!n0183ctlenabled) {
1180 if (n2kctlenabled) {
1181 m_cbInput->Show();
1182 m_cbOutput->Show();
1183 } else {
1184 m_cbInput->Hide();
1185 m_cbOutput->Hide();
1186 }
1187 ShowOutFilter(false);
1188 ShowInFilter(false);
1189 m_stPrecision->Hide();
1190 m_choicePrecision->Hide();
1191 m_stNetDataProtocol->Hide();
1192 m_choiceNetDataProtocol->Hide();
1193 } else {
1194 m_cbInput->Show();
1195 m_cbInput->Enable();
1196
1197 ShowInFilter(m_cbInput->IsChecked() && advanced);
1198 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1199
1200 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1201 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1202
1203 m_cbGarminHost->Show(m_cbInput->IsChecked() && advanced);
1204 }
1205 }
1206
1207 if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue()) {
1208 m_cbMultiCast->Hide();
1209 m_cbCheckSKDiscover->Hide();
1210 m_stAuthToken->Hide();
1211 m_tAuthToken->Hide();
1212 m_ButtonSKDiscover->Hide();
1213 m_StaticTextSKServerStatus->Hide();
1214 m_cbOutput->Hide();
1215 m_cbInput->Hide();
1216 ShowOutFilter(false);
1217 ShowInFilter(false);
1218 m_stPrecision->Hide();
1219 m_choicePrecision->Hide();
1220 m_cbGarminHost->Hide();
1221 m_collapse_box->ShowItems(false);
1222 }
1223
1224 if (m_rbTypeInternalBT && m_rbTypeInternalBT->GetValue()) {
1225 m_cbMultiCast->Hide();
1226 m_cbCheckSKDiscover->Hide();
1227 m_stAuthToken->Hide();
1228 m_tAuthToken->Hide();
1229 m_ButtonSKDiscover->Hide();
1230 m_StaticTextSKServerStatus->Hide();
1231
1232 ShowInFilter(m_cbInput->IsChecked() && advanced);
1233 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1234
1235 m_stPrecision->Show(m_cbOutput->IsChecked() && advanced);
1236 m_choicePrecision->Show(m_cbOutput->IsChecked() && advanced);
1237 }
1238
1239 if (m_rbTypeCAN->GetValue()) {
1240 m_cbMultiCast->Hide();
1241 m_cbCheckSKDiscover->Hide();
1242 m_stAuthToken->Hide();
1243 m_tAuthToken->Hide();
1244 m_ButtonSKDiscover->Hide();
1245 m_StaticTextSKServerStatus->Hide();
1246 m_cbGarminHost->Hide();
1247 m_cbInput->Hide();
1248 m_cbOutput->Hide();
1249
1250 ShowInFilter(false);
1251 ShowOutFilter(false);
1252
1253 m_stPrecision->Hide();
1254 m_choicePrecision->Hide();
1255
1256 m_stNetDataProtocol->Hide();
1257 m_choiceNetDataProtocol->Hide();
1258 m_collapse_box->Show(false);
1259 }
1260
1261 if (m_rbTypeNet->GetValue()) {
1262 if (m_rbNetProtoGPSD->GetValue()) {
1263 m_cbMultiCast->Hide();
1264 m_cbCheckSKDiscover->Hide();
1265 m_cbInput->Hide();
1266 m_cbOutput->Hide();
1267 ShowInFilter(true);
1268 ShowOutFilter(false);
1269 m_stPrecision->Hide();
1270 m_choicePrecision->Hide();
1271 m_ButtonSKDiscover->Hide();
1272 m_StaticTextSKServerStatus->Hide();
1273 m_stAuthToken->Hide();
1274 m_tAuthToken->Hide();
1275 m_stNetDataProtocol->Hide();
1276 m_choiceNetDataProtocol->Hide();
1277 m_cbGarminHost->Hide();
1278 m_collapse_box->Show(false);
1279
1280 } else if (m_rbNetProtoSignalK->GetValue()) {
1281 m_cbMultiCast->Hide();
1282 m_cbInput->Hide();
1283 m_cbOutput->Hide();
1284 ShowInFilter(false);
1285 ShowOutFilter(false);
1286 m_stPrecision->Hide();
1287 m_choicePrecision->Hide();
1288 m_stNetDataProtocol->Hide();
1289 m_choiceNetDataProtocol->Hide();
1290 m_cbGarminHost->Hide();
1291
1292 } else { // tcp or udp
1293 m_stAuthToken->Hide();
1294 m_tAuthToken->Hide();
1295 m_cbCheckSKDiscover->Hide();
1296 m_ButtonSKDiscover->Hide();
1297 m_StaticTextSKServerStatus->Hide();
1298 m_stNetDataProtocol->Show();
1299 m_choiceNetDataProtocol->Show();
1300 m_cbGarminHost->Hide();
1301
1302 // if (m_rbNetProtoUDP->GetValue()) m_cbMultiCast->Show(advanced);
1303
1304 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1305 DataProtocol::PROTO_NMEA2000) {
1306 m_stPrecision->Hide();
1307 m_choicePrecision->Hide();
1308
1309 ShowInFilter(false);
1310 ShowOutFilter(false);
1311 if (m_rbNetProtoTCP->GetValue()) m_collapse_box->ShowItems(false);
1312 }
1313 if ((DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1314 DataProtocol::PROTO_NMEA0183) {
1315 m_stPrecision->Show(advanced);
1316 m_choicePrecision->Show(advanced);
1317 m_stPrecision->Enable(m_cbOutput->IsChecked() && advanced);
1318 m_choicePrecision->Enable(m_cbOutput->IsChecked() && advanced);
1319
1320 ShowInFilter(m_cbInput->IsChecked() && advanced);
1321 ShowOutFilter(m_cbOutput->IsChecked() && advanced);
1322 }
1323 }
1324 }
1325}
1326
1327void ConnectionEditDialog::SetDSFormRWStates() {
1328 if (m_rbTypeSerial->GetValue()) {
1329 m_cbInput->Enable(TRUE);
1330 m_cbOutput->Enable(TRUE);
1331 ShowInFilter();
1332 ShowOutFilter(m_cbOutput->IsChecked());
1333 } else if (m_rbNetProtoGPSD->GetValue()) {
1334 if (m_tNetPort->GetValue() == wxEmptyString)
1335 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1336 m_cbInput->SetValue(TRUE);
1337 m_cbInput->Enable(FALSE);
1338 // m_cbOutput->SetValue(FALSE);
1339 m_cbOutput->Enable(FALSE);
1340 m_rbOAccept->Enable(FALSE);
1341 m_rbOIgnore->Enable(FALSE);
1342 m_btnOutputStcList->Enable(FALSE);
1343 } else if (m_rbNetProtoSignalK->GetValue()) {
1344 if (m_tNetPort->GetValue() == wxEmptyString)
1345 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1346 m_cbInput->SetValue(TRUE);
1347 m_cbInput->Enable(FALSE);
1348 // m_cbOutput->SetValue(FALSE);
1349 m_cbOutput->Enable(FALSE);
1350 m_rbOAccept->Enable(FALSE);
1351 m_rbOIgnore->Enable(FALSE);
1352 UpdateDiscoverStatus(wxEmptyString);
1353 } else {
1354 if (m_tNetPort->GetValue() == wxEmptyString) {
1355 if (m_rbNetProtoTCP->GetValue()) {
1356 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1357 } else {
1358 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1359 }
1360 }
1361 m_cbInput->Enable(TRUE);
1362 m_cbOutput->Enable(TRUE);
1363 m_rbOAccept->Enable(TRUE);
1364 m_rbOIgnore->Enable(TRUE);
1365 m_btnOutputStcList->Enable(TRUE);
1366 }
1367
1368 SetDSFormOptionVizStates();
1369 // m_container->FitInside();
1370}
1371
1372void ConnectionEditDialog::ShowInFilter(bool bshow) {
1373 sbSizerInFilter->GetStaticBox()->Show(bshow);
1374 m_rbIAccept->Show(bshow);
1375 m_rbIIgnore->Show(bshow);
1376 m_tcInputStc->Show(bshow);
1377 m_btnInputStcList->Show(bshow);
1378}
1379
1380void ConnectionEditDialog::ShowOutFilter(bool bshow) {
1381 sbSizerOutFilter->GetStaticBox()->Show(bshow);
1382 m_rbOAccept->Show(bshow);
1383 m_rbOIgnore->Show(bshow);
1384 m_tcOutputStc->Show(bshow);
1385 m_btnOutputStcList->Show(bshow);
1386}
1387
1388void ConnectionEditDialog::PreloadControls(ConnectionParams* cp) {
1389 m_cp_original = cp;
1390 SetConnectionParams(cp);
1391}
1392
1393void ConnectionEditDialog::SetConnectionParams(ConnectionParams* cp) {
1394 if (wxNOT_FOUND == m_comboPort->FindString(cp->Port))
1395 m_comboPort->Append(cp->Port);
1396
1397 m_comboPort->Select(m_comboPort->FindString(cp->Port));
1398
1399 m_cbGarminHost->SetValue(cp->Garmin);
1400 m_cbInput->SetValue(cp->IOSelect != DS_TYPE_OUTPUT);
1401 m_cbOutput->SetValue(cp->IOSelect != DS_TYPE_INPUT);
1402 m_cbCheckSKDiscover->SetValue(cp->AutoSKDiscover);
1403
1404 if (cp->InputSentenceListType == WHITELIST)
1405 m_rbIAccept->SetValue(TRUE);
1406 else
1407 m_rbIIgnore->SetValue(TRUE);
1408 if (cp->OutputSentenceListType == WHITELIST)
1409 m_rbOAccept->SetValue(TRUE);
1410 else
1411 m_rbOIgnore->SetValue(TRUE);
1412 m_tcInputStc->SetValue(StringArrayToString(cp->InputSentenceList));
1413 m_tcOutputStc->SetValue(StringArrayToString(cp->OutputSentenceList));
1414 m_choiceBaudRate->Select(
1415 m_choiceBaudRate->FindString(wxString::Format("%d", cp->Baudrate)));
1416 m_choiceSerialProtocol->Select(cp->Protocol); // TODO
1417 m_tNetAddress->SetValue(cp->NetworkAddress);
1418
1419 m_choiceNetDataProtocol->Select(cp->Protocol); // TODO
1420
1421 m_cbMultiCast->SetValue(IsAddressMultiCast(m_tNetAddress->GetValue()));
1422
1423 if (cp->NetworkPort == 0)
1424 m_tNetPort->SetValue(wxEmptyString);
1425 else
1426 m_tNetPort->SetValue(wxString::Format("%i", cp->NetworkPort));
1427
1428 if (cp->NetProtocol == TCP)
1429 m_rbNetProtoTCP->SetValue(TRUE);
1430 else if (cp->NetProtocol == UDP)
1431 m_rbNetProtoUDP->SetValue(TRUE);
1432 else if (cp->NetProtocol == GPSD)
1433 m_rbNetProtoGPSD->SetValue(TRUE);
1434 else if (cp->NetProtocol == SIGNALK)
1435 m_rbNetProtoSignalK->SetValue(TRUE);
1436 else
1437 m_rbNetProtoGPSD->SetValue(TRUE);
1438
1439 if (cp->Type == SERIAL) {
1440 m_rbTypeSerial->SetValue(TRUE);
1441 SetNMEAFormToSerial();
1442 SetNMEAFormForSerialProtocol();
1443 } else if (cp->Type == NETWORK) {
1444 m_rbTypeNet->SetValue(TRUE);
1445 SetNMEAFormToNet();
1446 } else if (cp->Type == SOCKETCAN) {
1447 m_rbTypeCAN->SetValue(TRUE);
1448 SetNMEAFormToCAN();
1449
1450 } else if (cp->Type == INTERNAL_GPS) {
1451 if (m_rbTypeInternalGPS) m_rbTypeInternalGPS->SetValue(TRUE);
1452 SetNMEAFormToGPS();
1453 } else if (cp->Type == INTERNAL_BT) {
1454 if (m_rbTypeInternalBT) m_rbTypeInternalBT->SetValue(TRUE);
1455 SetNMEAFormToBT();
1456
1457 // Preset the source selector
1458 wxString bts = cp->NetworkAddress + ";" + cp->GetPortStr();
1459 m_choiceBTDataSources->Clear();
1460 m_choiceBTDataSources->Append(bts);
1461 m_choiceBTDataSources->SetSelection(0);
1462 } else
1463 ClearNMEAForm();
1464
1465 if (cp->Type == SERIAL)
1466 m_tSerialComment->SetValue(cp->UserComment);
1467 else if (cp->Type == NETWORK)
1468 m_tNetComment->SetValue(cp->UserComment);
1469
1470 m_tAuthToken->SetValue(cp->AuthToken);
1471
1472 m_connection_enabled = cp->bEnabled;
1473
1474 // Reset touch flag
1475 connectionsaved = true;
1476}
1477
1478void ConnectionEditDialog::SetUDPNetAddressVisiblity() {
1479 if (m_rbNetProtoUDP->GetValue() && !m_cbMultiCast->IsChecked() &&
1480 !m_cbOutput->IsChecked()) {
1481 // m_stNetAddr->Show(FALSE);
1482 // m_tNetAddress->Show(FALSE);
1483 m_tNetAddress->Enable(TRUE);
1484 } else {
1485 m_stNetAddr->Show(TRUE);
1486 m_tNetAddress->Show(TRUE);
1487 m_tNetAddress->Enable(TRUE);
1488 }
1489 if (!m_rbNetProtoUDP->GetValue()) {
1490 m_stNetAddr->Show(TRUE);
1491 m_tNetAddress->Show(TRUE);
1492 m_tNetAddress->Enable(TRUE);
1493 }
1494 if (m_rbNetProtoUDP->GetValue() && m_advanced) {
1495 // m_cbMultiCast->Show();
1496 } else
1497 m_cbMultiCast->Hide();
1498}
1499
1500void ConnectionEditDialog::SetDefaultConnectionParams() {
1501 if (m_comboPort && !m_comboPort->IsListEmpty()) {
1502 m_comboPort->Select(0);
1503 m_comboPort->SetValue(wxEmptyString); // These two broke it
1504 }
1505 m_cbGarminHost->SetValue(FALSE);
1506 m_cbInput->SetValue(TRUE);
1507 m_cbOutput->SetValue(FALSE);
1508 m_rbIAccept->SetValue(TRUE);
1509 m_rbOAccept->SetValue(TRUE);
1510 m_tcInputStc->SetValue(wxEmptyString);
1511 m_tcOutputStc->SetValue(wxEmptyString);
1512 m_choiceBaudRate->Select(m_choiceBaudRate->FindString("4800"));
1513 // m_choiceSerialProtocol->Select( cp->Protocol ); // TODO
1514
1515 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1516
1517 m_tNetComment->SetValue(wxEmptyString);
1518 m_tSerialComment->SetValue(wxEmptyString);
1519 m_tAuthToken->SetValue(wxEmptyString);
1520
1521 bool bserial = TRUE;
1522#ifdef __WXGTK__
1523 bserial = FALSE;
1524#endif
1525
1526#ifdef __WXOSX__
1527 bserial = FALSE;
1528#endif
1529
1530#ifdef __ANDROID__
1531 if (m_rbTypeInternalGPS) {
1532 m_rbTypeInternalGPS->SetValue(true);
1533 SetNMEAFormToGPS();
1534 } else {
1535 m_rbTypeNet->SetValue(true);
1536 SetNMEAFormToNet();
1537 }
1538
1539#else
1540 m_rbTypeSerial->SetValue(bserial);
1541 m_rbTypeNet->SetValue(!bserial);
1542 bserial ? SetNMEAFormToSerial() : SetNMEAFormToNet();
1543 m_rbTypeCAN->SetValue(FALSE);
1544#endif
1545
1546 m_connection_enabled = TRUE;
1547
1548 // Reset touch flag
1549 connectionsaved = false;
1550}
1551
1552void ConnectionEditDialog::LayoutDialog() {
1553 gSizerNetProps->Layout();
1554 gSizerSerProps->Layout();
1555 this->Layout();
1556 this->Fit();
1557 GetSizer()->Layout();
1558}
1559
1560void ConnectionEditDialog::UpdateSourceList(bool bResort) {
1561 for (auto* cp : TheConnectionParams()) {
1562 ConnectionParamsPanel* panel = cp->m_optionsPanel;
1563 if (panel) panel->Update(cp);
1564 }
1565
1566 m_scrollWinConnections->Layout();
1567}
1568
1569void ConnectionEditDialog::OnSelectDatasource(wxListEvent& event) {
1570 SetConnectionParams(TheConnectionParams()[event.GetData()]);
1571 m_buttonRemove->Enable();
1572 m_buttonRemove->Show();
1573 event.Skip();
1574}
1575
1576void ConnectionEditDialog::OnDiscoverButton(wxCommandEvent& event) {
1577#if 0 // FIXME (dave)
1578 wxString ip;
1579 int port;
1580 std::string serviceIdent =
1581 std::string("_signalk-ws._tcp.local."); // Works for node.js server
1582
1583 g_Platform->ShowBusySpinner();
1584
1585 if (SignalKDataStream::DiscoverSKServer(serviceIdent, ip, port,
1586 1)) // 1 second scan
1587 {
1588 m_tNetAddress->SetValue(ip);
1589 m_tNetPort->SetValue(wxString::Format("%i", port));
1590 UpdateDiscoverStatus(_("Signal K server available."));
1591 } else {
1592 UpdateDiscoverStatus(_("Signal K server not found."));
1593 }
1594 g_Platform->HideBusySpinner();
1595#endif
1596 event.Skip();
1597}
1598
1599void ConnectionEditDialog::UpdateDiscoverStatus(wxString stat) {
1600 m_StaticTextSKServerStatus->SetLabel(stat);
1601}
1602
1603void ConnectionEditDialog::OnBtnIStcs(wxCommandEvent& event) {
1604 const ListType type = m_rbIAccept->GetValue() ? WHITELIST : BLACKLIST;
1605 const wxArrayString list = wxStringTokenize(m_tcInputStc->GetValue(), ",");
1606 SentenceListDlg dlg(m_parent, FILTER_INPUT, type, list);
1607
1608 if (dlg.ShowModal() == wxID_OK) m_tcInputStc->SetValue(dlg.GetSentences());
1609}
1610
1611void ConnectionEditDialog::OnBtnOStcs(wxCommandEvent& event) {
1612 const ListType type = m_rbOAccept->GetValue() ? WHITELIST : BLACKLIST;
1613 const wxArrayString list = wxStringTokenize(m_tcOutputStc->GetValue(), ",");
1614 SentenceListDlg dlg(m_parent, FILTER_OUTPUT, type, list);
1615
1616 if (dlg.ShowModal() == wxID_OK) m_tcOutputStc->SetValue(dlg.GetSentences());
1617}
1618
1619void ConnectionEditDialog::OnNetProtocolSelected(wxCommandEvent& event) {
1620 if (m_rbNetProtoGPSD->GetValue()) {
1621 if (IsDefaultPort(m_tNetPort->GetValue())) {
1622 m_tNetPort->SetValue(DEFAULT_GPSD_PORT);
1623 }
1624 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1625 } else if (m_rbNetProtoUDP->GetValue()) {
1626 if (IsDefaultPort(m_tNetPort->GetValue())) {
1627 m_tNetPort->SetValue(DEFAULT_UDP_PORT);
1628 }
1629 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1630 if (m_cbInput->GetValue() && !m_cbMultiCast->GetValue() &&
1631 m_rbNetProtoUDP->GetValue())
1632 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1633 else if (m_cbOutput->GetValue() && !m_cbMultiCast->GetValue())
1634 m_tNetPort->SetValue(DEFAULT_UDP_OUT_ADDRESS);
1635
1636 if (m_cbInput->GetValue() && m_cbOutput->GetValue())
1637 m_cbOutput->SetValue(false);
1638
1639 } else if (m_rbNetProtoSignalK->GetValue()) {
1640 if (IsDefaultPort(m_tNetPort->GetValue())) {
1641 m_tNetPort->SetValue(DEFAULT_SIGNALK_PORT);
1642 }
1643 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1644 } else if (m_rbNetProtoTCP->GetValue()) {
1645 if (IsDefaultPort(m_tNetPort->GetValue())) {
1646 m_tNetPort->SetValue(DEFAULT_TCP_PORT);
1647 }
1648 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1649 }
1650
1651 SetUDPNetAddressVisiblity();
1652 SetDSFormRWStates();
1653 LayoutDialog();
1654 OnConnValChange(event);
1655}
1656
1657void ConnectionEditDialog::OnRbAcceptInput(wxCommandEvent& event) {
1658 OnConnValChange(event);
1659}
1660void ConnectionEditDialog::OnRbIgnoreInput(wxCommandEvent& event) {
1661 OnConnValChange(event);
1662}
1663
1664void ConnectionEditDialog::OnRbOutput(wxCommandEvent& event) {
1665 OnConnValChange(event);
1666}
1667
1668void ConnectionEditDialog::OnCbInput(wxCommandEvent& event) {
1669 const bool checked = m_cbInput->IsChecked();
1670 ShowInFilter(checked);
1671 if (checked && m_rbNetProtoUDP->GetValue() && m_rbTypeNet->GetValue()) {
1672 m_cbOutput->SetValue(FALSE);
1673
1674 if (!m_cbMultiCast->GetValue()) m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS);
1675 }
1676 SetDSFormRWStates();
1677 LayoutDialog();
1678 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1679 OnConnValChange(event);
1680}
1681
1682void ConnectionEditDialog::OnCbOutput(wxCommandEvent& event) {
1683 OnConnValChange(event);
1684 const bool checked = m_cbOutput->IsChecked();
1685 m_stPrecision->Enable(checked);
1686 m_choicePrecision->Enable(checked);
1687 ShowOutFilter(checked);
1688
1689 if (!m_cbMultiCast->IsChecked() && m_rbNetProtoUDP->GetValue()) {
1690 if (checked) {
1691 m_tNetAddress->SetValue(
1692 DEFAULT_UDP_OUT_ADDRESS); // IP address for output
1693 // Check for a UDP input connection on the same port
1694 NetworkProtocol proto = UDP;
1695 for (auto* cp : TheConnectionParams()) {
1696 if (cp->NetProtocol == proto &&
1697 cp->NetworkPort == wxAtoi(m_tNetPort->GetValue()) &&
1698 cp->IOSelect == DS_TYPE_INPUT) {
1699 // More: View the filter handler
1700 m_advanced = true;
1701 SetNMEAFormForNetProtocol();
1702 LayoutDialog();
1703
1704 wxString mes;
1705 bool warn = false;
1706 if (cp->bEnabled) {
1707 mes =
1708 _("There is an enabled UDP input connection that uses the "
1709 "same data port.");
1710 mes << "\n"
1711 << _("Please apply a filter on both connections to avoid a "
1712 "feedback loop.");
1713 warn = true;
1714 } else {
1715 mes =
1716 _("There is a disabled UDP Input connection that uses the "
1717 "same Dataport.");
1718 mes << "\n"
1719 << _("If you enable that input please apply a filter on both "
1720 "connections to avoid a feedback loop.");
1721 }
1722 mes << "\n"
1723 << _("Or consider using a different data port for one of them");
1724 if (warn)
1725 OCPNMessageBox(this, mes, _("OpenCPN Warning"),
1726 wxOK | wxICON_EXCLAMATION, 60);
1727 else
1728 OCPNMessageBox(this, mes, _("OpenCPN info"),
1729 wxOK | wxICON_INFORMATION, 60);
1730 break;
1731 }
1732 }
1733 } else {
1734 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1735 }
1736 }
1737
1738 if (checked && m_rbNetProtoUDP->GetValue()) {
1739 m_cbInput->SetValue(FALSE);
1740 }
1741
1742 if (m_rbTypeNet->GetValue()) SetUDPNetAddressVisiblity();
1743 SetDSFormRWStates();
1744 LayoutDialog();
1745}
1746
1747void ConnectionEditDialog::OnCbMultiCast(wxCommandEvent& event) {
1748 const bool checked = m_cbMultiCast->IsChecked();
1749 if (checked) {
1750 if (!IsAddressMultiCast(m_tNetAddress->GetValue())) {
1751 m_tNetAddress->SetValue("224.0.2.21");
1752 }
1753 } else if (m_cbOutput->IsChecked()) {
1754 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for output
1755 } else {
1756 m_tNetAddress->SetValue(DEFAULT_IP_ADDRESS); // IP address for input
1757 }
1758
1759 SetUDPNetAddressVisiblity();
1760 LayoutDialog();
1761}
1762
1763void ConnectionEditDialog::OnCollapsedToggle(bool collapsed) {
1764 m_advanced = !collapsed;
1765 if (m_rbTypeNet->GetValue())
1766 SetNMEAFormForNetProtocol();
1767 else
1768 SetNMEAFormForSerialProtocol();
1769 LayoutDialog();
1770}
1771
1772void ConnectionEditDialog::OnCbAdvanced(wxCommandEvent& event) {
1773 if (m_rbTypeNet->GetValue())
1774 SetNMEAFormForNetProtocol();
1775 else
1776 SetNMEAFormForSerialProtocol();
1777 LayoutDialog();
1778}
1779
1780void ConnectionEditDialog::OnShowGpsWindowCheckboxClick(wxCommandEvent& event) {
1781 // if (!m_cbNMEADebug->GetValue()) {
1782 // NMEALogWindow::GetInstance().DestroyWindow();
1783 // } else {
1784 // NMEALogWindow::GetInstance().Create((wxWindow*)(m_parent->GetParent()),
1785 // 35);
1786 //
1787 // // Try to ensure that the log window is at least a little bit visible
1788 // wxRect logRect(NMEALogWindow::GetInstance().GetPosX(),
1789 // NMEALogWindow::GetInstance().GetPosY(),
1790 // NMEALogWindow::GetInstance().GetSizeW(),
1791 // NMEALogWindow::GetInstance().GetSizeH());
1792 // FIXME (leamas)
1793
1794#if 0
1795 if (m_container->GetRect().Contains(logRect)) {
1796 NMEALogWindow::Get().SetPos(
1797 m_container->GetRect().x / 2,
1798 (m_container->GetRect().y +
1799 (m_container->GetRect().height - logRect.height) / 2));
1800 NMEALogWindow::Get().Move();
1801 }
1802#endif
1803 m_parent->Raise();
1804 // }
1805}
1806void ConnectionEditDialog::SetNMEAFormForSerialProtocol() {
1807 bool n0183ctlenabled = (DataProtocol)m_choiceSerialProtocol->GetSelection() ==
1808 DataProtocol::PROTO_NMEA0183;
1809 bool advanced = m_advanced;
1810 ShowNMEACommon(n0183ctlenabled && advanced);
1811 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1812
1813 SetDSFormRWStates();
1814 LayoutDialog();
1815}
1816
1817void ConnectionEditDialog::SetNMEAFormForNetProtocol() {
1818 bool n0183ctlenabled =
1819 (DataProtocol)m_choiceNetDataProtocol->GetSelection() ==
1820 DataProtocol::PROTO_NMEA0183;
1821 bool advanced = m_advanced;
1822 ShowNMEACommon(n0183ctlenabled && advanced);
1823 m_cbGarminHost->Show(n0183ctlenabled && advanced);
1824
1825 SetDSFormRWStates();
1826
1827 LayoutDialog();
1828}
1829
1830void ConnectionEditDialog::OnProtocolChoice(wxCommandEvent& event) {
1831 if (m_rbTypeNet->GetValue())
1832 SetNMEAFormForNetProtocol();
1833 else
1834 SetNMEAFormForSerialProtocol();
1835
1836 OnConnValChange(event);
1837}
1838
1839void ConnectionEditDialog::ApplySettings() {
1840#if 0
1841 g_bfilter_cogsog = m_cbFilterSogCog->GetValue();
1842
1843 long filter_val = 1;
1844 m_tFilterSec->GetValue().ToLong(&filter_val);
1845 g_COGFilterSec =
1846 wxMin(static_cast<int>(filter_val),
1847 60 /*MAX_COGSOG_FILTER_SECONDS*/); // FIXME (dave) should be
1848 g_COGFilterSec = wxMax(g_COGFilterSec, 1);
1849 g_SOGFilterSec = g_COGFilterSec;
1850
1851 g_bMagneticAPB = m_cbAPBMagnetic->GetValue();
1852 g_NMEAAPBPrecision = m_choicePrecision->GetCurrentSelection();
1853
1854 // NMEA Source
1855 // If the stream selected exists, capture some of its existing parameters
1856 // to facility identification and allow stop and restart of the stream
1857 wxString lastAddr;
1858 int lastPort = 0;
1859 NetworkProtocol lastNetProtocol = PROTO_UNDEFINED;
1860 DataProtocol lastDataProtocol = PROTO_NMEA0183;
1861
1862 if (mSelectedConnection) {
1863 ConnectionParams* cpo = mSelectedConnection;
1864 lastAddr = cpo->NetworkAddress;
1865 lastPort = cpo->NetworkPort;
1866 lastNetProtocol = cpo->NetProtocol;
1867 lastDataProtocol = cpo->Protocol;
1868 }
1869
1870 if (!connectionsaved) {
1871 size_t nCurrentPanelCount = TheConnectionParams()->GetCount();
1872 ConnectionParams* cp = NULL;
1873 int old_priority = -1;
1874 {
1875 if (mSelectedConnection) {
1876 cp = mSelectedConnection;
1877 old_priority = cp->Priority;
1878 UpdateConnectionParamsFromControls(cp);
1879 cp->b_IsSetup = false;
1880 // cp->bEnabled = false;
1881 // if (cp->m_optionsPanel)
1882 // cp->m_optionsPanel->SetEnableCheckbox(false);
1883
1884 // delete TheConnectionParams()->Item(itemIndex)->m_optionsPanel;
1885 // old_priority = TheConnectionParams()->Item(itemIndex)->Priority;
1886 // TheConnectionParams()->RemoveAt(itemIndex);
1887 // TheConnectionParams()->Insert(cp, itemIndex);
1888 // mSelectedConnection = cp;
1889 // cp->m_optionsPanel->SetSelected( true );
1890 } else {
1891 cp = CreateConnectionParamsFromSelectedItem();
1892 if (cp) TheConnectionParams()->Add(cp);
1893 }
1894
1895 // Record the previous parameters, if any
1896 if (cp) {
1897 cp->LastNetProtocol = lastNetProtocol;
1898 cp->LastNetworkAddress = lastAddr;
1899 cp->LastNetworkPort = lastPort;
1900 cp->LastDataProtocol = lastDataProtocol;
1901 }
1902
1903 if (TheConnectionParams()->GetCount() != nCurrentPanelCount)
1904 FillSourceList();
1905 else if (old_priority >= 0) {
1906 if (old_priority != cp->Priority) // need resort
1907 UpdateSourceList(true);
1908 else
1909 UpdateSourceList(false);
1910 }
1911
1912 connectionsaved = TRUE;
1913 }
1914 // else {
1915 // ::wxEndBusyCursor();
1916 // if (m_bNMEAParams_shown) event.SetInt(wxID_STOP);
1917 // }
1918
1919 SetSelectedConnectionPanel(nullptr);
1920 }
1921
1922 // Recreate datastreams that are new, or have been edited
1923 for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
1924 ConnectionParams* cp = TheConnectionParams()->Item(i);
1925
1926 if (cp->b_IsSetup) continue;
1927
1928 // Connection is new, or edited, or disabled
1929
1930 // Terminate and remove any existing driver, if present in registry
1931 StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
1932
1933 // Stop and remove "previous" port, in case other params have changed.
1934 StopAndRemoveCommDriver(cp->GetLastDSPort(), cp->GetLastCommProtocol());
1935
1936 // Internal BlueTooth driver stacks commonly need a time delay to purge
1937 // their buffers, etc. before restating with new parameters...
1938 if (cp->Type == INTERNAL_BT) wxSleep(1);
1939
1940 // Connection has been disabled
1941 if (!cp->bEnabled) continue;
1942
1943 // Make any new or re-enabled drivers
1944 MakeCommDriver(cp);
1945 cp->b_IsSetup = TRUE;
1946 }
1947
1948 g_bGarminHostUpload = m_cbGarminUploadHost->GetValue();
1949 g_GPS_Ident =
1950 m_cbFurunoGP3X->GetValue() ? "FurunoGP3X" : "Generic";
1951#endif
1952}
1953
1955ConnectionEditDialog::CreateConnectionParamsFromSelectedItem() {
1956#if 0
1957 // FIXME (dave) How could this happen?
1958 // if (!m_bNMEAParams_shown) return NULL;
1959
1960 // Special encoding for deleted connection
1961 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == "Deleted")
1962 return NULL;
1963
1964 // We check some values here for consistency.
1965 // If necessary, set defaults so user will see some result, however wrong...
1966
1967 // DataStreams should be Input, Output, or Both
1968 if (!(m_cbInput->GetValue() || m_cbOutput->GetValue())) {
1969 m_cbInput->SetValue(true);
1970 }
1971
1972 if (m_rbTypeSerial->GetValue() && m_comboPort->GetValue() == wxEmptyString) {
1973 m_comboPort->Select(0);
1974 }
1975 // TCP, GPSD and UDP require port field to be set.
1976 // TCP clients, GPSD and UDP output sockets require an address
1977 else if (m_rbTypeNet->GetValue()) {
1978 if (wxAtoi(m_tNetPort->GetValue()) == 0) {
1979 m_tNetPort->SetValue("10110"); // reset to default
1980 }
1981 if (m_tNetAddress->GetValue() == wxEmptyString) {
1982 m_tNetAddress->SetValue("0.0.0.0");
1983 }
1984 } else if (m_rbTypeCAN->GetValue()) {
1985 }
1986
1987 ConnectionParams* pConnectionParams = new ConnectionParams();
1988
1989 UpdateConnectionParamsFromSelectedItem(pConnectionParams);
1990
1992 m_scrollWinConnections, wxID_ANY, wxDefaultPosition, wxDefaultSize,
1993 pConnectionParams, this);
1994 pPanel->SetSelected(false);
1995 boxSizerConnections->Add(pPanel, 0, wxEXPAND | wxALL, 0);
1996 pConnectionParams->m_optionsPanel = pPanel;
1997
1998 return pConnectionParams;
1999#endif
2000 return NULL;
2001}
2002
2003ConnectionParams* ConnectionEditDialog::GetParamsFromControls() {
2004 ConnectionParams* pConnectionParams = new ConnectionParams();
2005 UpdateConnectionParamsFromControls(pConnectionParams);
2006 return pConnectionParams;
2007}
2008
2009ConnectionParams* ConnectionEditDialog::UpdateConnectionParamsFromControls(
2010 ConnectionParams* pConnectionParams) {
2011 pConnectionParams->Valid = TRUE;
2012 if (m_rbTypeSerial->GetValue())
2013 pConnectionParams->Type = SERIAL;
2014 else if (m_rbTypeNet->GetValue())
2015 pConnectionParams->Type = NETWORK;
2016 else if (m_rbTypeInternalGPS && m_rbTypeInternalGPS->GetValue())
2017 pConnectionParams->Type = INTERNAL_GPS;
2018 else if (m_rbTypeInternalBT && m_rbTypeInternalBT->GetValue())
2019 pConnectionParams->Type = INTERNAL_BT;
2020 else if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2021 pConnectionParams->Type = SOCKETCAN;
2022
2023 if (m_rbTypeNet->GetValue()) {
2024 // Save the existing addr/port to allow closing of existing port
2025 pConnectionParams->LastNetworkAddress = pConnectionParams->NetworkAddress;
2026 pConnectionParams->LastNetworkPort = pConnectionParams->NetworkPort;
2027 pConnectionParams->LastNetProtocol = pConnectionParams->NetProtocol;
2028 pConnectionParams->LastDataProtocol = pConnectionParams->Protocol;
2029
2030 pConnectionParams->NetworkAddress =
2031 m_tNetAddress->GetValue().Trim(false).Trim(true);
2032 pConnectionParams->NetworkPort =
2033 wxAtoi(m_tNetPort->GetValue().Trim(false).Trim(true));
2034 if (m_rbNetProtoTCP->GetValue()) {
2035 pConnectionParams->NetProtocol = TCP;
2036 pConnectionParams->Protocol =
2037 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2038 } else if (m_rbNetProtoUDP->GetValue()) {
2039 pConnectionParams->NetProtocol = UDP;
2040 pConnectionParams->Protocol =
2041 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2042 } else if (m_rbNetProtoGPSD->GetValue())
2043 pConnectionParams->NetProtocol = GPSD;
2044 else if (m_rbNetProtoSignalK->GetValue())
2045 pConnectionParams->NetProtocol = SIGNALK;
2046 else
2047 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2048 }
2049
2050 if (m_rbTypeSerial->GetValue())
2051 pConnectionParams->Protocol =
2052 (DataProtocol)m_choiceSerialProtocol->GetSelection();
2053 else if (m_rbTypeNet->GetValue())
2054 pConnectionParams->Protocol =
2055 (DataProtocol)m_choiceNetDataProtocol->GetSelection();
2056
2057 pConnectionParams->Baudrate = wxAtoi(m_choiceBaudRate->GetStringSelection());
2058 pConnectionParams->ChecksumCheck = true;
2059 pConnectionParams->AutoSKDiscover = m_cbCheckSKDiscover->GetValue();
2060 pConnectionParams->Garmin = m_cbGarminHost->GetValue();
2061 pConnectionParams->InputSentenceList =
2062 wxStringTokenize(m_tcInputStc->GetValue(), ",");
2063 if (m_rbIAccept->GetValue())
2064 pConnectionParams->InputSentenceListType = WHITELIST;
2065 else
2066 pConnectionParams->InputSentenceListType = BLACKLIST;
2067 if (m_cbInput->GetValue()) {
2068 if (m_cbOutput->GetValue()) {
2069 pConnectionParams->IOSelect = DS_TYPE_INPUT_OUTPUT;
2070 } else {
2071 pConnectionParams->IOSelect = DS_TYPE_INPUT;
2072 }
2073 } else
2074 pConnectionParams->IOSelect = DS_TYPE_OUTPUT;
2075
2076 pConnectionParams->OutputSentenceList =
2077 wxStringTokenize(m_tcOutputStc->GetValue(), ",");
2078 if (m_rbOAccept->GetValue())
2079 pConnectionParams->OutputSentenceListType = WHITELIST;
2080 else
2081 pConnectionParams->OutputSentenceListType = BLACKLIST;
2082 pConnectionParams->Port = m_comboPort->GetValue().BeforeFirst(' ');
2083#if defined(__linux__) && !defined(__ANDROID__)
2084 if (pConnectionParams->Type == SERIAL)
2085 CheckSerialAccess(m_parent, pConnectionParams->Port.ToStdString());
2086#endif
2087
2088 if (m_rbTypeCAN && m_rbTypeCAN->GetValue())
2089 pConnectionParams->Protocol = PROTO_NMEA2000;
2090
2091 pConnectionParams->bEnabled = m_connection_enabled;
2092 pConnectionParams->b_IsSetup = FALSE;
2093
2094 if (pConnectionParams->Type == INTERNAL_GPS) {
2095 pConnectionParams->NetworkAddress = "";
2096 pConnectionParams->NetworkPort = 0;
2097 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2098 pConnectionParams->Baudrate = 0;
2099 pConnectionParams->Port = "Internal GPS";
2100 }
2101
2102 if (pConnectionParams->Type == INTERNAL_BT) {
2103 wxString parms = m_choiceBTDataSources->GetStringSelection();
2104 wxStringTokenizer tkz(parms, ";");
2105 wxString name = tkz.GetNextToken();
2106 wxString mac = tkz.GetNextToken();
2107
2108 pConnectionParams->NetworkAddress = name;
2109 pConnectionParams->Port = mac;
2110 pConnectionParams->NetworkPort = 0;
2111 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2112 pConnectionParams->Baudrate = 0;
2113 // pConnectionParams->SetAuxParameterStr(m_choiceBTDataSources->GetStringSelection());
2114 }
2115
2116 if (pConnectionParams->Type == SOCKETCAN) {
2117 pConnectionParams->NetworkAddress = "";
2118 pConnectionParams->NetworkPort = 0;
2119 pConnectionParams->NetProtocol = PROTO_UNDEFINED;
2120 pConnectionParams->Baudrate = 0;
2121 pConnectionParams->socketCAN_port =
2122 m_choiceCANSource->GetString(m_choiceCANSource->GetSelection());
2123 }
2124
2125 if (pConnectionParams->Type == SERIAL) {
2126 pConnectionParams->UserComment = m_tSerialComment->GetValue();
2127 } else if (pConnectionParams->Type == NETWORK) {
2128 pConnectionParams->UserComment = m_tNetComment->GetValue();
2129 }
2130 pConnectionParams->AuthToken = m_tAuthToken->GetValue();
2131
2132 return pConnectionParams;
2133}
2134
2135void ConnectionEditDialog::OnPriorityDialog(wxCommandEvent& event) {
2136 PriorityDlg* pdlg = new PriorityDlg(m_parent);
2137 pdlg->ShowModal();
2138 delete pdlg;
2139}
2140void ConnectionEditDialog::ConnectControls() {
2141 // Connect controls
2142 m_rbTypeSerial->Connect(
2143 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2144 wxCommandEventHandler(ConnectionEditDialog::OnTypeSerialSelected), NULL,
2145 this);
2146 m_rbTypeNet->Connect(
2147 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2148 wxCommandEventHandler(ConnectionEditDialog::OnTypeNetSelected), NULL,
2149 this);
2150
2151 m_rbTypeCAN->Connect(
2152 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2153 wxCommandEventHandler(ConnectionEditDialog::OnTypeCANSelected), NULL,
2154 this);
2155
2156 if (m_rbTypeInternalGPS)
2157 m_rbTypeInternalGPS->Connect(
2158 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2159 wxCommandEventHandler(ConnectionEditDialog::OnTypeGPSSelected), NULL,
2160 this);
2161 if (m_rbTypeInternalBT)
2162 m_rbTypeInternalBT->Connect(
2163 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2164 wxCommandEventHandler(ConnectionEditDialog::OnTypeBTSelected), NULL,
2165 this);
2166
2167 // Network connection
2168 m_rbNetProtoTCP->Connect(
2169 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2170 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2171 this);
2172 m_rbNetProtoUDP->Connect(
2173 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2174 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2175 this);
2176 m_rbNetProtoGPSD->Connect(
2177 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2178 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2179 this);
2180 m_rbNetProtoSignalK->Connect(
2181 wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2182 wxCommandEventHandler(ConnectionEditDialog::OnNetProtocolSelected), NULL,
2183 this);
2184 m_choiceNetDataProtocol->Connect(
2185 wxEVT_COMMAND_CHOICE_SELECTED,
2186 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2187 this);
2188 m_choiceSerialProtocol->Connect(
2189 wxEVT_COMMAND_CHOICE_SELECTED,
2190 wxCommandEventHandler(ConnectionEditDialog::OnProtocolChoice), NULL,
2191 this);
2192 m_cbMultiCast->Connect(
2193 wxEVT_COMMAND_CHECKBOX_CLICKED,
2194 wxCommandEventHandler(ConnectionEditDialog::OnCbMultiCast), NULL, this);
2195
2196 // input/output control
2197 m_cbInput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2198 wxCommandEventHandler(ConnectionEditDialog::OnCbInput),
2199 NULL, this);
2200 m_cbOutput->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2201 wxCommandEventHandler(ConnectionEditDialog::OnCbOutput),
2202 NULL, this);
2203
2204 if (m_buttonScanBT)
2205 m_buttonScanBT->Connect(
2206 wxEVT_COMMAND_BUTTON_CLICKED,
2207 wxCommandEventHandler(ConnectionEditDialog::OnScanBTClick), NULL, this);
2208
2209 // Input filtering
2210 // m_rbIAccept->Connect(
2211 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2212 // wxCommandEventHandler(ConnectionEditDialog::OnRbAcceptInput), NULL,
2213 // this);
2214 // m_rbIIgnore->Connect(
2215 // wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2216 // wxCommandEventHandler(ConnectionEditDialog::OnRbIgnoreInput), NULL,
2217 // this);
2218 // m_tcInputStc->Connect(
2219 // wxEVT_COMMAND_TEXT_UPDATED,
2220 // wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL,
2221 // this);
2222 m_btnInputStcList->Connect(
2223 wxEVT_COMMAND_BUTTON_CLICKED,
2224 wxCommandEventHandler(ConnectionEditDialog::OnBtnIStcs), NULL, this);
2225
2226 // output filtering
2227 m_btnOutputStcList->Connect(
2228 wxEVT_COMMAND_BUTTON_CLICKED,
2229 wxCommandEventHandler(ConnectionEditDialog::OnBtnOStcs), NULL, this);
2230
2231#if 0
2232 m_tNetAddress->Connect(
2233 wxEVT_COMMAND_TEXT_UPDATED,
2234 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2235 m_tNetPort->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2236 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange),
2237 NULL, this);
2238 m_comboPort->Connect(
2239 wxEVT_COMMAND_COMBOBOX_SELECTED,
2240 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2241 m_comboPort->Connect(
2242 wxEVT_COMMAND_TEXT_UPDATED,
2243 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2244 m_choiceBaudRate->Connect(
2245 wxEVT_COMMAND_CHOICE_SELECTED,
2246 wxCommandEventHandler(ConnectionEditDialog::OnBaudrateChoice), NULL, this);
2247 m_choicePriority->Connect(
2248 wxEVT_COMMAND_CHOICE_SELECTED,
2249 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2250 m_choiceCANSource->Connect(
2251 wxEVT_COMMAND_CHOICE_SELECTED,
2252 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2253 m_cbCheckCRC->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
2254 wxCommandEventHandler(ConnectionEditDialog::OnCrcCheck),
2255 NULL, this);
2256 m_cbGarminHost->Connect(
2257 wxEVT_COMMAND_CHECKBOX_CLICKED,
2258 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2259 this);
2260 m_cbGarminUploadHost->Connect(
2261 wxEVT_COMMAND_CHECKBOX_CLICKED,
2262 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2263 this);
2264 m_cbFurunoGP3X->Connect(
2265 wxEVT_COMMAND_CHECKBOX_CLICKED,
2266 wxCommandEventHandler(ConnectionEditDialog::OnUploadFormatChange), NULL,
2267 this);
2268 m_cbCheckSKDiscover->Connect(
2269 wxEVT_COMMAND_CHECKBOX_CLICKED,
2270 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2271 m_ButtonSKDiscover->Connect(
2272 wxEVT_COMMAND_BUTTON_CLICKED,
2273 wxCommandEventHandler(ConnectionEditDialog::OnDiscoverButton), NULL, this);
2274
2275 m_rbOAccept->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2276 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2277 NULL, this);
2278 m_rbOIgnore->Connect(wxEVT_COMMAND_RADIOBUTTON_SELECTED,
2279 wxCommandEventHandler(ConnectionEditDialog::OnRbOutput),
2280 NULL, this);
2281 m_tcOutputStc->Connect(
2282 wxEVT_COMMAND_TEXT_UPDATED,
2283 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2284 m_cbCheckCRC->Connect(
2285 wxEVT_COMMAND_CHECKBOX_CLICKED,
2286 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2287
2288 m_cbNMEADebug->Connect(
2289 wxEVT_COMMAND_CHECKBOX_CLICKED,
2290 wxCommandEventHandler(ConnectionEditDialog::OnShowGpsWindowCheckboxClick),
2291 NULL, this);
2292 m_cbFilterSogCog->Connect(
2293 wxEVT_COMMAND_CHECKBOX_CLICKED,
2294 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2295 m_tFilterSec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
2296 wxCommandEventHandler(ConnectionEditDialog::OnValChange),
2297 NULL, this);
2298 m_cbAPBMagnetic->Connect(
2299 wxEVT_COMMAND_CHECKBOX_CLICKED,
2300 wxCommandEventHandler(ConnectionEditDialog::OnValChange), NULL, this);
2301
2302 m_ButtonPriorityDialog->Connect(
2303 wxEVT_COMMAND_BUTTON_CLICKED,
2304 wxCommandEventHandler(ConnectionEditDialog::OnPriorityDialog), NULL, this);
2305
2306 m_tNetComment->Connect(
2307 wxEVT_COMMAND_TEXT_UPDATED,
2308 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2309 m_tSerialComment->Connect(
2310 wxEVT_COMMAND_TEXT_UPDATED,
2311 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2312 m_tAuthToken->Connect(
2313 wxEVT_COMMAND_TEXT_UPDATED,
2314 wxCommandEventHandler(ConnectionEditDialog::OnConnValChange), NULL, this);
2315
2316 if (m_buttonScanBT)
2317 m_buttonScanBT->Connect(
2318 wxEVT_COMMAND_BUTTON_CLICKED,
2319 wxCommandEventHandler(ConnectionEditDialog::OnScanBTClick), NULL, this);
2320#endif
2321}
2322
2323bool ConnectionEditDialog::IsAddressMultiCast(wxString ip) {
2324 wxArrayString bytes = wxSplit(ip, '.');
2325 if (bytes.size() != 4) {
2326 return false;
2327 }
2328 unsigned long ipNum = (wxAtoi(bytes[0]) << 24) + (wxAtoi(bytes[1]) << 16) +
2329 (wxAtoi(bytes[2]) << 8) + wxAtoi(bytes[3]);
2330 unsigned long multicastStart = (224 << 24);
2331 unsigned long multicastEnd = (239 << 24) + (255 << 16) + (255 << 8) + 255;
2332 return ipNum >= multicastStart && ipNum <= multicastEnd;
2333}
2334
2335bool ConnectionEditDialog::IsDefaultPort(wxString address) {
2336 return (address == DEFAULT_TCP_PORT) || (address == DEFAULT_UDP_PORT) ||
2337 (address == DEFAULT_SIGNALK_PORT) || (address == DEFAULT_GPSD_PORT);
2338}
2339
2340bool ConnectionEditDialog::IsAddressBroadcast(wxString ip) {
2341 wxArrayString bytes = wxSplit(ip, '.');
2342 if (bytes.size() != 4) {
2343 std::cerr << "Invalid IP format." << std::endl;
2344 return false;
2345 }
2346 return wxAtoi(bytes[3]) == 255;
2347}
2348
2349SentenceListDlg::SentenceListDlg(wxWindow* parent, FilterDirection dir,
2350 ListType type, const wxArrayString& list)
2351 : wxDialog(parent, wxID_ANY, _("Sentence Filter"), wxDefaultPosition,
2352 wxSize(280, 420)),
2353 m_type(type),
2354 m_dir(dir),
2355 m_sentences(NMEA0183().GetRecognizedArray()) {
2356 m_sentences.Sort();
2357 wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
2358 wxBoxSizer* secondSizer = new wxBoxSizer(wxHORIZONTAL);
2359 wxStaticBox* pclbBox = new wxStaticBox(this, wxID_ANY, GetBoxLabel());
2360 wxStaticBoxSizer* stcSizer = new wxStaticBoxSizer(pclbBox, wxVERTICAL);
2361 m_clbSentences = new wxCheckListBox(this, wxID_ANY, wxDefaultPosition,
2362 wxDefaultSize, m_sentences);
2363 wxBoxSizer* btnEntrySizer = new wxBoxSizer(wxVERTICAL);
2364 wxButton* btnCheckAll = new wxButton(this, wxID_ANY, _("Select All"));
2365 wxButton* btnClearAll = new wxButton(this, wxID_ANY, _("Clear All"));
2366 wxButton* btnAdd = new wxButton(this, wxID_ANY, _("Add"));
2367 m_btnDel = new wxButton(this, wxID_ANY, _("Delete"));
2368 m_btnDel->Disable();
2369 wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
2370 wxButton* btnOK = new wxButton(this, wxID_OK);
2371 wxButton* btnCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
2372
2373 secondSizer->Add(stcSizer, 1, wxALL | wxEXPAND, 5);
2374 stcSizer->Add(m_clbSentences, 1, wxALL | wxEXPAND, 5);
2375 btnEntrySizer->Add(btnCheckAll, 0, wxALL, 5);
2376 btnEntrySizer->Add(btnClearAll, 0, wxALL, 5);
2377 btnEntrySizer->AddSpacer(1);
2378 btnEntrySizer->Add(btnAdd, 0, wxALL, 5);
2379 btnEntrySizer->Add(m_btnDel, 0, wxALL, 5);
2380 secondSizer->Add(btnEntrySizer, 0, wxALL | wxEXPAND, 5);
2381 mainSizer->Add(secondSizer, 1, wxEXPAND, 5);
2382 btnSizer->AddButton(btnOK);
2383 btnSizer->AddButton(btnCancel);
2384 btnSizer->Realize();
2385 mainSizer->Add(btnSizer, 0, wxALL | wxEXPAND, 5);
2386
2387 SetSizer(mainSizer);
2388 mainSizer->SetSizeHints(this);
2389 Centre();
2390
2391 // Connect Events
2392 btnAdd->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2393 wxCommandEventHandler(SentenceListDlg::OnAddClick), NULL,
2394 this);
2395 m_btnDel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2396 wxCommandEventHandler(SentenceListDlg::OnDeleteClick), NULL,
2397 this);
2398 m_clbSentences->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
2399 wxCommandEventHandler(SentenceListDlg::OnCLBSelect),
2400 NULL, this);
2401 btnCheckAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2402 wxCommandEventHandler(SentenceListDlg::OnCheckAllClick),
2403 NULL, this);
2404 btnClearAll->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
2405 wxCommandEventHandler(SentenceListDlg::OnClearAllClick),
2406 NULL, this);
2407
2408 Populate(list);
2409}
2410
2411wxString SentenceListDlg::GetBoxLabel() const {
2412 if (m_dir == FILTER_OUTPUT)
2413 return m_type == WHITELIST ? _("Transmit sentences") : _("Drop sentences");
2414 else
2415 return m_type == WHITELIST ? _("Accept only sentences")
2416 : _("Ignore sentences");
2417}
2418
2419void SentenceListDlg::Populate(const wxArrayString& list) {
2420 if (m_dir == FILTER_OUTPUT) {
2421 wxString s;
2422 m_sentences.Add(g_TalkerIdText + wxString("RMB"));
2423 m_sentences.Add(g_TalkerIdText + wxString("RMC"));
2424 m_sentences.Add(g_TalkerIdText + wxString("APB"));
2425 m_sentences.Add(g_TalkerIdText + wxString("XTE"));
2426 }
2427 m_sentences.Add("AIVDM");
2428 m_sentences.Add("AIVDO");
2429 m_sentences.Add("FRPOS");
2430 m_sentences.Add(g_TalkerIdText);
2431 m_sentences.Add("CD");
2432 m_sentences.Sort();
2433 m_clbSentences->Clear();
2434 m_clbSentences->InsertItems(m_sentences, 0);
2435
2436 wxArrayString new_strings;
2437
2438 if (list.Count() == 0) {
2439 for (size_t i = 0; i < m_clbSentences->GetCount(); ++i)
2440 m_clbSentences->Check(i, m_type == WHITELIST);
2441 } else {
2442 for (size_t i = 0; i < list.Count(); ++i) {
2443 int item = m_clbSentences->FindString(list[i]);
2444 if (item != wxNOT_FOUND)
2445 m_clbSentences->Check(item);
2446 else
2447 new_strings.Add(list[i]);
2448 }
2449 if (new_strings.GetCount()) {
2450 m_clbSentences->InsertItems(new_strings, m_clbSentences->GetCount());
2451 for (size_t i = 0; i < new_strings.GetCount(); ++i) {
2452 int item = m_clbSentences->FindString(new_strings[i]);
2453 if (item != wxNOT_FOUND) m_clbSentences->Check(item);
2454 }
2455 }
2456 }
2457}
2458
2459wxString SentenceListDlg::GetSentences() {
2460 wxArrayString retString;
2461 for (size_t i = 0; i < m_clbSentences->GetCount(); i++) {
2462 if (m_clbSentences->IsChecked(i))
2463 retString.Add(m_clbSentences->GetString(i));
2464 }
2465 return StringArrayToString(retString);
2466}
2467
2468void SentenceListDlg::OnCLBSelect(wxCommandEvent& e) {
2469 // Only activate the "Delete" button if the selection is not in the standard
2470 // list
2471 m_btnDel->Enable(m_sentences.Index(e.GetString()) == wxNOT_FOUND);
2472}
2473
2474void SentenceListDlg::OnAddClick(wxCommandEvent& event) {
2475#ifdef __ANDROID__
2476 androidDisableRotation();
2477#endif
2478
2479 wxTextEntryDialog textdlg(
2480 this,
2481 _("Enter the NMEA sentence (2, 3 or 5 characters)\n or a valid REGEX "
2482 "expression (6 characters or longer)"),
2483 _("Enter the NMEA sentence"));
2484
2485 textdlg.SetTextValidator(wxFILTER_ASCII);
2486 int result = textdlg.ShowModal();
2487
2488#ifdef __ANDROID__
2489 androidEnableRotation();
2490#endif
2491
2492 if (result == wxID_CANCEL) return;
2493 wxString stc = textdlg.GetValue();
2494
2495 if (stc.Length() == 2 || stc.Length() == 3 || stc.Length() == 5) {
2496 m_clbSentences->Append(stc);
2497 m_clbSentences->Check(m_clbSentences->FindString(stc));
2498 return;
2499 } else if (stc.Length() < 2) {
2500 OCPNMessageBox(
2501 this,
2502 _("An NMEA sentence is generally 3 characters long (like RMC, GGA etc.)\n \
2503 It can also have a two letter prefix identifying the source, or TALKER, of the message.\n \
2504 The whole sentences then looks like GPGGA or AITXT.\n \
2505 You may filter out all the sentences with certain TALKER prefix (like GP, AI etc.).\n \
2506 The filter also accepts Regular Expressions (REGEX) with 6 or more characters. \n\n"),
2507 _("OpenCPN Info"));
2508 return;
2509 }
2510
2511 else {
2512 // Verify that a longer text entry is a valid RegEx
2513 wxRegEx r(stc);
2514 if (r.IsValid()) {
2515 m_clbSentences->Append(stc);
2516 m_clbSentences->Check(m_clbSentences->FindString(stc));
2517 return;
2518 } else {
2519 OCPNMessageBox(this, _("REGEX syntax error: \n") + stc,
2520 _("OpenCPN Info"));
2521 return;
2522 }
2523 }
2524}
2525
2526void SentenceListDlg::OnDeleteClick(wxCommandEvent& event) {
2527 m_clbSentences->Delete(m_clbSentences->GetSelection());
2528}
2529
2530void SentenceListDlg::OnClearAllClick(wxCommandEvent& event) {
2531 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2532 m_clbSentences->Check(i, FALSE);
2533}
2534
2535void SentenceListDlg::OnCheckAllClick(wxCommandEvent& event) {
2536 for (size_t i = 0; i < m_clbSentences->GetCount(); i++)
2537 m_clbSentences->Check(i, TRUE);
2538}
Panel for displaying and editing connection parameters.
Simple panel showing either an "expand" or "collapse" icon, state switches when clicked.
Definition expand_icon.h:35
void Init(const KeyProvider &kp, const std::function< void(ObservedEvt &ev)> &action)
Initiate an object yet not listening.
Definition observable.h:295
Custom event class for OpenCPN's notification system.
void MakeCommDriver(const ConnectionParams *params)
Create and register a driver for given connection.
Communication drivers factory and support.
Global variables stored in configuration file.
Panel for editing a connection.
Dialog and support code for editing a connection.
Platform independent GL includes.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
Definition gui_lib.cpp:61
General purpose GUI support.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
std::string trim(std::string s)
Strip possibly trailing and/or leading space characters in s.
OpenCPN Platform specific support utilities.
PlugIn Object Definition/API.
Miscellaneous utilities, many of which string related.
Options dialog.
Input priorities management dialog.
Serial ports support, notably enumeration.
wxArrayString * EnumerateSerialPorts(void)
Enumerate all serial ports.
Suspend/resume and new devices events exchange point.
bool CheckSerialAccess(wxWindow *parent, const std::string device)
Run checks and possible dialogs to ensure device is accessible.
Access checks for comm devices and dongle.