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