OpenCPN Partial API docs
connections_dialog.cpp
1 /******************************************************************************
2  *
3  * Project: OpenCPN
4  * Purpose:
5  * Author: David Register
6  *
7  ***************************************************************************
8  * Copyright (C) 2024 by David S. Register *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the *
22  * Free Software Foundation, Inc., *
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24  ***************************************************************************
25  *
26  *
27  */
28 
29 #include <wx/wxprec.h>
30 
31 #ifndef WX_PRECOMP
32 #include <wx/wx.h>
33 #endif // precompiled headers
34 
35 #include <wx/statline.h>
36 
37 #include "model/comm_drv_factory.h"
38 #include "model/config_vars.h"
39 #include "model/sys_events.h"
40 
41 #include "connections_dialog.h"
42 #include "conn_params_panel.h"
43 #include "NMEALogWindow.h"
44 #include "OCPNPlatform.h"
45 #include "options.h"
46 #include "priority_gui.h"
47 #include "connection_edit.h"
48 
49 extern bool g_bfilter_cogsog;
50 extern int g_COGFilterSec;
51 extern int g_SOGFilterSec;
52 
53 
54 //------------------------------------------------------------------------------
55 // ConnectionsDialog Implementation
56 //------------------------------------------------------------------------------
57 
58 // Define constructors
59 ConnectionsDialog::ConnectionsDialog() {}
60 
61 ConnectionsDialog::ConnectionsDialog(wxScrolledWindow* container,
62  options* parent) {
63  m_container = container;
64  m_parent = parent;
65 
66  Init();
67 }
68 
69 ConnectionsDialog::~ConnectionsDialog() {}
70 
71 void ConnectionsDialog::SetInitialSettings(void) {
72 
73  m_cbNMEADebug->SetValue(false);
74  if (NMEALogWindow::GetInstance().GetTTYWindow()) {
75  if (NMEALogWindow::GetInstance().GetTTYWindow()->IsShown()) {
76  m_cbNMEADebug->SetValue(true);
77  }
78  }
79 
80  FillSourceList();
81 
82  // Reset the touch flag...
83  SetSelectedConnectionPanel(nullptr);
84 }
85 
86 
87 void ::ConnectionsDialog::OnSize(wxSizeEvent &ev){
88  if (m_sbSizerLB)
89  m_sbSizerLB->Layout();
90 }
91 
92 void ConnectionsDialog::Init() {
93  // Setup some initial values
94  mSelectedConnection = NULL;
95 
96  // Create the UI
97 
98  // Try to detect smaller displays, and adjust dialog layout accordingly
99  // Looking for small devices in landscape mode.
100  bool bcompact = false;
101  wxSize displaySize = wxGetDisplaySize();
102  if ((displaySize.y < 500) && (displaySize.x > displaySize.y))
103  bcompact = true;
104 
105  wxBoxSizer* bSizer4 = new wxBoxSizer(wxVERTICAL);
106  m_container->SetSizer(bSizer4);
107  m_container->SetVirtualSize(m_container->GetParent()->GetSize());
108 
109  // In compact mode, we scroll the entire dialog
110  // Otherwise, we scroll only the connection list
111  if (bcompact)
112  m_container->SetScrollRate(1, 1);
113  else
114  m_container->SetScrollRate(0, 0);
115 
116 
117  m_bSizerOuterContainer = new wxBoxSizer(wxVERTICAL);
118  bSizer4->Add(m_bSizerOuterContainer, 1, wxEXPAND, 5);
119 
120  wxStaticBoxSizer* sbSizerGeneral;
121  sbSizerGeneral = new wxStaticBoxSizer(
122  new wxStaticBox(m_container, wxID_ANY, _("General")), wxVERTICAL);
123  m_bSizerOuterContainer->Add(sbSizerGeneral, 0, wxRIGHT | wxEXPAND, 5);
124 
125  wxBoxSizer* bSizer151;
126  bSizer151 = new wxBoxSizer(wxVERTICAL);
127 
128  wxBoxSizer* bSizer161;
129  bSizer161 = new wxBoxSizer(wxVERTICAL);
130 
131  wxBoxSizer* bSizer171;
132  bSizer171 = new wxBoxSizer(wxHORIZONTAL);
133 
134  m_cbFilterSogCog = new wxCheckBox(m_container, wxID_ANY,
135  _("Filter NMEA Course and Speed data"),
136  wxDefaultPosition, wxDefaultSize, 0);
137  m_cbFilterSogCog->SetValue(g_bfilter_cogsog);
138  bSizer171->Add(m_cbFilterSogCog, 0, wxALL, 5);
139 
140  m_stFilterSec =
141  new wxStaticText(m_container, wxID_ANY, _("Filter period (sec)"),
142  wxDefaultPosition, wxDefaultSize, 0);
143  m_stFilterSec->Wrap(-1);
144 
145  int nspace = 5;
146 #ifdef __WXGTK__
147  nspace = 9;
148 #endif
149  bSizer171->Add(m_stFilterSec, 0, wxALL, nspace);
150 
151  m_tFilterSec = new wxTextCtrl(m_container, wxID_ANY, wxEmptyString,
152  wxDefaultPosition,
153  wxSize(50, 3 * m_container->GetCharWidth()), 0);
154  wxString sfilt;
155  sfilt.Printf("%d", g_COGFilterSec);
156  m_tFilterSec->SetValue(sfilt);
157  bSizer171->Add(m_tFilterSec, 0, wxALL, 4);
158  bSizer161->Add(bSizer171, 0, wxEXPAND, 5);
159 
160  int cb_space = 1;
161 
162  // On smaller displays, squeeze the dialog slightly
163  if (bcompact){
164  wxFlexGridSizer *GenProps = new wxFlexGridSizer(0, 2, 0, 0);
165  bSizer161->Add(GenProps, 0, wxALL, cb_space);
166 
167  m_cbNMEADebug =
168  new wxCheckBox(m_container, wxID_ANY, _("Show NMEA Debug Window"),
169  wxDefaultPosition, wxDefaultSize, 0);
170  m_cbNMEADebug->SetValue(NMEALogWindow::GetInstance().Active());
171  GenProps->Add(m_cbNMEADebug, 0, wxALL, cb_space);
172 
173  m_cbFurunoGP3X = new wxCheckBox(m_container, wxID_ANY,
174  _("Format uploads for Furuno GP3X"),
175  wxDefaultPosition, wxDefaultSize, 0);
176  m_cbFurunoGP3X->SetValue(g_GPS_Ident == "FurunoGP3X");
177  GenProps->Add(m_cbFurunoGP3X, 0, wxALL, cb_space);
178 
179  m_cbGarminUploadHost = new wxCheckBox(
180  m_container, wxID_ANY, _("Use Garmin GRMN (Host) mode for uploads"),
181  wxDefaultPosition, wxDefaultSize, 0);
182  m_cbGarminUploadHost->SetValue(g_bGarminHostUpload);
183  GenProps->Add(m_cbGarminUploadHost, 0, wxALL, cb_space);
184 
185  m_cbAPBMagnetic =
186  new wxCheckBox(m_container, wxID_ANY,
187  _("Use magnetic bearings in output sentence APB"),
188  wxDefaultPosition, wxDefaultSize, 0);
189  m_cbAPBMagnetic->SetValue(g_bMagneticAPB);
190  GenProps->Add(m_cbAPBMagnetic, 0, wxALL, cb_space);
191 
192  wxSizer *talkerSizer = new wxBoxSizer(wxHORIZONTAL);
193  bSizer161->Add(talkerSizer, 0, wxALL, 1);
194 
195  m_ButtonPriorityDialog = new wxButton(m_container, wxID_ANY,
196  _("Adjust communication priorities..."),
197  wxDefaultPosition, wxDefaultSize, 0);
198  talkerSizer->Add(m_ButtonPriorityDialog, 0, wxALL, cb_space);
199 
200  talkerSizer->AddSpacer(12 * m_container->GetCharWidth());
201 
202  m_stTalkerIdText = new wxStaticText(
203  m_container, wxID_ANY,
204  wxString::Format("%s", _("NMEA0183 Talker ID")),
205  wxDefaultPosition, wxDefaultSize, 0);
206  m_stTalkerIdText->Wrap(-1);
207  talkerSizer->Add(m_stTalkerIdText, 0, wxALL, 2);
208 
209  talkerSizer->AddSpacer(2 * m_container->GetCharWidth());
210 
211  m_TalkerIdText = new wxTextCtrl(m_container, -1, "", wxDefaultPosition,
212  wxSize(50, 3 * m_container->GetCharWidth()), 0);
213  m_TalkerIdText->SetMaxLength(2);
214  m_TalkerIdText->SetValue(g_TalkerIdText.MakeUpper());
215  talkerSizer->Add(m_TalkerIdText, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
216  }
217  else {
218  cb_space = 2;
219  m_cbNMEADebug =
220  new wxCheckBox(m_container, wxID_ANY, _("Show NMEA Debug Window"),
221  wxDefaultPosition, wxDefaultSize, 0);
222  m_cbNMEADebug->SetValue(NMEALogWindow::GetInstance().Active());
223  bSizer161->Add(m_cbNMEADebug, 0, wxALL, cb_space);
224 
225  m_cbFurunoGP3X = new wxCheckBox(m_container, wxID_ANY,
226  _("Format uploads for Furuno GP3X"),
227  wxDefaultPosition, wxDefaultSize, 0);
228  m_cbFurunoGP3X->SetValue(g_GPS_Ident == "FurunoGP3X");
229  bSizer161->Add(m_cbFurunoGP3X, 0, wxALL, cb_space);
230 
231  m_cbGarminUploadHost = new wxCheckBox(
232  m_container, wxID_ANY, _("Use Garmin GRMN (Host) mode for uploads"),
233  wxDefaultPosition, wxDefaultSize, 0);
234  m_cbGarminUploadHost->SetValue(g_bGarminHostUpload);
235  bSizer161->Add(m_cbGarminUploadHost, 0, wxALL, cb_space);
236 
237  m_cbAPBMagnetic =
238  new wxCheckBox(m_container, wxID_ANY,
239  _("Use magnetic bearings in output sentence APB"),
240  wxDefaultPosition, wxDefaultSize, 0);
241  m_cbAPBMagnetic->SetValue(g_bMagneticAPB);
242  bSizer161->Add(m_cbAPBMagnetic, 0, wxALL, cb_space);
243 
244  wxSizer* talkerSizer = new wxBoxSizer(wxHORIZONTAL);
245  bSizer161->Add(talkerSizer, 0, wxALL, 1);
246 
247  talkerSizer->AddSpacer(3 * m_container->GetCharWidth());
248 
249  m_stTalkerIdText = new wxStaticText(
250  m_container, wxID_ANY, wxString::Format("%s", _("NMEA0183 Talker ID")),
251  wxDefaultPosition, wxDefaultSize, 0);
252  m_stTalkerIdText->Wrap(-1);
253  talkerSizer->Add(m_stTalkerIdText, 0, wxALL, 2);
254 
255  talkerSizer->AddSpacer(2 * m_container->GetCharWidth());
256 
257  m_TalkerIdText =
258  new wxTextCtrl(m_container, -1, "", wxDefaultPosition,
259  wxSize(50, 3 * m_container->GetCharWidth()), 0);
260  m_TalkerIdText->SetMaxLength(2);
261  m_TalkerIdText->SetValue(g_TalkerIdText.MakeUpper());
262  talkerSizer->Add(m_TalkerIdText, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
263 
264  m_ButtonPriorityDialog = new wxButton(
265  m_container, wxID_ANY, _("Adjust communication priorities..."),
266  wxDefaultPosition, wxDefaultSize, 0);
267  bSizer161->Add(m_ButtonPriorityDialog, 0, wxALL, cb_space);
268  }
269 
270  bSizer151->Add(bSizer161, 0, wxEXPAND, 5);
271  sbSizerGeneral->Add(bSizer151, 0, wxEXPAND, 5);
272 
273  // Connections listbox, etc
274  m_sbSizerLB = new wxStaticBoxSizer(
275  new wxStaticBox(m_container, wxID_ANY, _("Data Connections")),
276  wxVERTICAL);
277  m_bSizerOuterContainer->Add(m_sbSizerLB, 1, wxEXPAND | wxRIGHT, 5);
278 
279  // Add/Remove/Edit Buttons
280  wxBoxSizer* bSizer18;
281  bSizer18 = new wxBoxSizer(wxHORIZONTAL);
282  m_sbSizerLB->Add(bSizer18, 0, wxEXPAND, 5);
283 
284  m_buttonAdd = new wxButton(m_container, wxID_ANY, _("Add Connection..."),
285  wxDefaultPosition, wxDefaultSize, 0);
286  bSizer18->Add(m_buttonAdd, 0, wxALL, 5);
287 
288  m_buttonEdit = new wxButton(m_container, wxID_ANY, _("Edit Connection..."),
289  wxDefaultPosition, wxDefaultSize, 0);
290  m_buttonEdit->Enable(FALSE);
291  bSizer18->Add(m_buttonEdit, 0, wxALL, 5);
292 
293  m_buttonRemove = new wxButton(m_container, wxID_ANY, _("Remove Connection"),
294  wxDefaultPosition, wxDefaultSize, 0);
295  m_buttonRemove->Enable(FALSE);
296  bSizer18->Add(m_buttonRemove, 0, wxALL, 5);
297 
298  wxStaticLine *staticline5 = new wxStaticLine(m_container, wxID_ANY, wxDefaultPosition,
299  wxDefaultSize, wxLI_HORIZONTAL);
300  m_sbSizerLB->Add(staticline5, 0, wxEXPAND | wxALL, 5);
301 
302 
303  //m_cPanel =
304  // new wxPanel(m_container, wxID_ANY, wxDefaultPosition,
305  // wxDLG_UNIT(m_parent, wxSize(-1, -1)));
306  //sbSizerLB->Add(m_cPanel, 0, wxALL | wxEXPAND, 0);
307 
308 
309  //wxBoxSizer* boxSizercPanel = new wxBoxSizer(wxVERTICAL);
310  //m_cPanel->SetSizer(boxSizercPanel);
311 
312 #ifdef __ANDROID__
313  m_scrollWinConnections =
314  new wxPanel(m_container, wxID_ANY, wxDefaultPosition, wxDefaultSize,
315  wxBORDER_RAISED | wxBG_STYLE_ERASE);
316 #else
317  m_scrollWinConnections = new wxScrolledWindow(
318  m_container, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(m_parent, wxSize(-1, -1)),
319  wxBORDER_RAISED | wxVSCROLL | wxBG_STYLE_ERASE);
320 
321  // In compact mode, we scroll the entire dialog
322  // Otherwise, we scroll only the connection list
323  if (bcompact)
324  m_scrollWinConnections->SetScrollRate(0, 0);
325  else
326  m_scrollWinConnections->SetScrollRate(5, 5);
327 
328 #endif
329 
330  m_sbSizerLB->Add(m_scrollWinConnections, 1, wxRIGHT | wxEXPAND, 5);
331 
332  boxSizerConnections = new wxBoxSizer(wxVERTICAL);
333  m_scrollWinConnections->SetSizer(boxSizerConnections);
334 
335  // Connect controls
336  m_buttonAdd->Connect(
337  wxEVT_COMMAND_BUTTON_CLICKED,
338  wxCommandEventHandler(ConnectionsDialog::OnAddDatasourceClick), NULL,
339  this);
340  m_buttonEdit->Connect(
341  wxEVT_COMMAND_BUTTON_CLICKED,
342  wxCommandEventHandler(ConnectionsDialog::OnEditDatasourceClick), NULL,
343  this);
344  m_buttonRemove->Connect(
345  wxEVT_COMMAND_BUTTON_CLICKED,
346  wxCommandEventHandler(ConnectionsDialog::OnRemoveDatasourceClick), NULL,
347  this);
348 
349  m_cbNMEADebug->Connect(
350  wxEVT_COMMAND_CHECKBOX_CLICKED,
351  wxCommandEventHandler(ConnectionsDialog::OnShowGpsWindowCheckboxClick),
352  NULL, this);
353  //m_cbFilterSogCog->Connect(
354  // wxEVT_COMMAND_CHECKBOX_CLICKED,
355  // wxCommandEventHandler(ConnectionsDialog::OnValChange), NULL, this);
356  //m_tFilterSec->Connect(wxEVT_COMMAND_TEXT_UPDATED,
357  // wxCommandEventHandler(ConnectionsDialog::OnValChange),
358  // NULL, this);
359  //m_cbAPBMagnetic->Connect(
360  // wxEVT_COMMAND_CHECKBOX_CLICKED,
361  // wxCommandEventHandler(ConnectionsDialog::OnValChange), NULL, this);
362 
363  m_ButtonPriorityDialog->Connect(
364  wxEVT_COMMAND_BUTTON_CLICKED,
365  wxCommandEventHandler(ConnectionsDialog::OnPriorityDialog), NULL, this);
366 
367  // Catch SizeEvents to force a layout honoring proportions
368  m_container->Connect(wxEVT_SIZE, wxSizeEventHandler(ConnectionsDialog::OnSize), NULL, this);
369 
370 }
371 
372 void ConnectionsDialog::SetSelectedConnectionPanel(
373  ConnectionParamsPanel* panel) {
374  // Only one panel can be selected at any time
375  // Clear any selections
376 
377  if (mSelectedConnection && mSelectedConnection->m_optionsPanel)
378  mSelectedConnection->m_optionsPanel->SetSelected(false);
379 
380  if (panel) {
381  mSelectedConnection = panel->m_pConnectionParams;
382  panel->SetSelected(true);
383  m_buttonRemove->Enable();
384  m_buttonRemove->Show();
385  m_buttonEdit->Enable();
386  m_buttonEdit->Show();
387  m_buttonAdd->Disable();
388 
389  } else {
390  mSelectedConnection = NULL;
391  m_buttonRemove->Disable();
392  m_buttonAdd->Enable();
393  m_buttonAdd->Show();
394  m_buttonEdit->Disable();
395  }
396 
397  m_container->FitInside();
398  // Scroll the panel to allow the user to see more of the NMEA parameter
399  // settings area
400  wxPoint buttonPosition = m_buttonAdd->GetPosition();
401  m_container->Scroll(-1, buttonPosition.y / m_parent->GetScrollRate());
402 }
403 
404 void ConnectionsDialog::EnableConnection(ConnectionParams* conn, bool value) {
405  if (conn) {
406  conn->bEnabled = value;
407  // trigger a rebuild/takedown of the connection on "APPLY"
408  conn->b_IsSetup = FALSE; // trigger a rebuild/takedown of the connection
409  }
410 }
411 
412 bool ConnectionsDialog::SortSourceList(void) {
413  if (TheConnectionParams()->Count() < 2) return false;
414 
415  std::vector<int> ivec;
416  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) ivec.push_back(i);
417 
418  bool did_sort = false;
419  bool did_swap = true;
420  while (did_swap) {
421  did_swap = false;
422  for (size_t j = 1; j < ivec.size(); j++) {
423  ConnectionParams* c1 = TheConnectionParams()->Item(ivec[j]);
424  ConnectionParams* c2 = TheConnectionParams()->Item(ivec[j - 1]);
425 
426  if (c1->Priority < c2->Priority) {
427  int t = ivec[j - 1];
428  ivec[j - 1] = ivec[j];
429  ivec[j] = t;
430  did_swap = true;
431  did_sort = true;
432  }
433  }
434  }
435 
436  // if(did_sort)
437  {
438  boxSizerConnections = new wxBoxSizer(wxVERTICAL);
439  m_scrollWinConnections->SetSizer(boxSizerConnections);
440 
441  for (size_t i = 0; i < ivec.size(); i++) {
442  ConnectionParamsPanel* pPanel =
443  TheConnectionParams()->Item(ivec[i])->m_optionsPanel;
444  boxSizerConnections->Add(pPanel, 0, wxEXPAND | wxRIGHT, 10);
445  }
446  }
447 
448  return did_sort;
449 }
450 
451 void ConnectionsDialog::FillSourceList(void) {
452  m_buttonRemove->Enable(FALSE);
453 
454  // Add new panels as necessary
455  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
456  ConnectionParams *cp = TheConnectionParams()->Item(i);
457  if (!cp->m_optionsPanel) {
459  m_scrollWinConnections, wxID_ANY, wxDefaultPosition, wxDefaultSize,
460  cp, this);
461  pPanel->SetSelected(false);
462  boxSizerConnections->Add(pPanel, 0, wxEXPAND | wxRIGHT, 10);
463  cp->m_optionsPanel = pPanel;
464  } else {
465  cp->m_optionsPanel->Update(cp);
466  }
467  }
468  SortSourceList();
469 
470  mSelectedConnection = NULL;
471  mSelectedConnection = NULL;
472  m_buttonAdd->Enable(true);
473  m_buttonAdd->Show();
474 }
475 
476 void ConnectionsDialog::UpdateSourceList(bool bResort) {
477  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
478  ConnectionParams* cp = TheConnectionParams()->Item(i);
479  ConnectionParamsPanel* panel = cp->m_optionsPanel;
480  if (panel) panel->Update(TheConnectionParams()->Item(i));
481  }
482 
483  if (bResort) {
484  SortSourceList();
485  }
486 
487  m_scrollWinConnections->Layout();
488 }
489 
490 void ConnectionsDialog::OnAddDatasourceClick(wxCommandEvent& event) {
491  // Unselect all panels
492  for (size_t i = 0; i < TheConnectionParams()->Count(); i++)
493  TheConnectionParams()->Item(i)->m_optionsPanel->SetSelected(false);
494 
495  ConnectionEditDialog dialog(m_parent, this);
496  dialog.SetSize(wxSize(m_parent->GetSize().x, m_parent->GetSize().y * 8/10));
497  dialog.SetPropsLabel(_("Configure new connection"));
498  dialog.SetDefaultConnectionParams();
499 
500  auto rv = dialog.ShowModal();
501  if (rv == wxID_OK) {
502  ConnectionParams* cp = dialog.GetParamsFromControls();
503  if (cp) {
504  cp->b_IsSetup = false; // Trigger new stream
505  TheConnectionParams()->Add(cp);
506  FillSourceList();
507  }
508  UpdateDatastreams();
509  m_sbSizerLB->Layout();
510  }
511 }
512 
513 void ConnectionsDialog::OnRemoveDatasourceClick(wxCommandEvent& event) {
514  if (mSelectedConnection) {
515  // Find the index
516  int index = -1;
517  ConnectionParams* cp = NULL;
518  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
519  cp = TheConnectionParams()->Item(i);
520  if (mSelectedConnection == cp) {
521  index = i;
522  break;
523  }
524  }
525 
526  if ((index >= 0) && (cp)) {
527  delete TheConnectionParams()->Item(index)->m_optionsPanel;
528  TheConnectionParams()->RemoveAt(index);
529  StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
530  mSelectedConnection = NULL;
531 
532  FillSourceList();
533  }
534  m_buttonEdit->Disable();
535  m_buttonRemove->Disable();
536 
537  m_sbSizerLB->Layout();
538  }
539 }
540 
541 void ConnectionsDialog::OnEditDatasourceClick(wxCommandEvent& event) {
542  if (mSelectedConnection) {
543  // Find the index
544  int index = -1;
545  ConnectionParams* cp = NULL;
546  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
547  cp = TheConnectionParams()->Item(i);
548  if (mSelectedConnection == cp) {
549  index = i;
550  break;
551  }
552  }
553 
554  if ((index >= 0) && (cp)) {
555  ConnectionEditDialog dialog(m_parent, this);
556  dialog.SetSize(wxSize(m_parent->GetSize().x, m_parent->GetSize().y * 8/10));
557  dialog.SetPropsLabel(_("Edit Selected Connection"));
558  // Preload the dialog contents
559  dialog.PreloadControls(cp);
560 
561  auto rv = dialog.ShowModal();
562  if (rv == wxID_OK){
563  ConnectionParams* cp_edited = dialog.GetParamsFromControls();
564  delete cp->m_optionsPanel;
565  StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
566 
567  TheConnectionParams()->Item(index) = cp_edited;
568  cp_edited->b_IsSetup = false; // Trigger new stream
569  FillSourceList();
570  UpdateDatastreams();
571  m_sbSizerLB->Layout();
572  }
573  }
574  }
575 }
576 
577 
578 
579 void ConnectionsDialog::OnShowGpsWindowCheckboxClick(wxCommandEvent& event) {
580  if (!m_cbNMEADebug->GetValue()) {
581  NMEALogWindow::GetInstance().DestroyWindow();
582  } else {
583  NMEALogWindow::GetInstance().Create((wxWindow*)(m_parent->pParent), 35);
584 
585  // Try to ensure that the log window is a least a little bit visible
586  wxRect logRect(NMEALogWindow::GetInstance().GetPosX(),
587  NMEALogWindow::GetInstance().GetPosY(),
588  NMEALogWindow::GetInstance().GetSizeW(),
589  NMEALogWindow::GetInstance().GetSizeH());
590 
591  if (m_container->GetRect().Contains(logRect)) {
592  NMEALogWindow::GetInstance().SetPos(
593  m_container->GetRect().x / 2,
594  (m_container->GetRect().y +
595  (m_container->GetRect().height - logRect.height) / 2));
596  NMEALogWindow::GetInstance().Move();
597  }
598 
599  m_parent->Raise();
600  }
601 }
602 
603 void ConnectionsDialog::ApplySettings() {
604  g_bfilter_cogsog = m_cbFilterSogCog->GetValue();
605 
606  long filter_val = 1;
607  m_tFilterSec->GetValue().ToLong(&filter_val);
608  g_COGFilterSec =
609  wxMin(static_cast<int>(filter_val),
610  60 /*MAX_COGSOG_FILTER_SECONDS*/); // FIXME (dave) should be
611  g_COGFilterSec = wxMax(g_COGFilterSec, 1);
612  g_SOGFilterSec = g_COGFilterSec;
613 
614  g_bMagneticAPB = m_cbAPBMagnetic->GetValue();
615  g_TalkerIdText = m_TalkerIdText->GetValue();
616 
617  g_bGarminHostUpload = m_cbGarminUploadHost->GetValue();
618  g_GPS_Ident = m_cbFurunoGP3X->GetValue() ? "FurunoGP3X" : "Generic";
619 
620  UpdateDatastreams();
621 }
622 
623 void ConnectionsDialog::UpdateDatastreams() {
624  // Recreate datastreams that are new, or have been edited
625  std::vector<std::string>enabled_conns;
626 
627  for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
628  ConnectionParams* cp = TheConnectionParams()->Item(i);
629 
630  // Connection already setup?
631  if (cp->b_IsSetup){
632  if(cp->bEnabled){
633  enabled_conns.push_back(cp->GetStrippedDSPort());
634  }
635  continue;
636  }
637 
638  // Check to see if this connection port has been
639  // already enabled in this loop.
640  // If so, then leave this connection alone.
641  // This will handle multiple connections with same port,
642  // but possibly different filters
643  // Also protect against some user config errors
644  if ( std::find(enabled_conns.begin(), enabled_conns.end(),
645  cp->GetStrippedDSPort()) != enabled_conns.end()) {
646  continue;
647  }
648 
649  // Terminate and remove any existing driver, if present in registry
650  StopAndRemoveCommDriver(cp->GetStrippedDSPort(), cp->GetCommProtocol());
651 
652  // Stop and remove "previous" port, in case other params have changed.
653  StopAndRemoveCommDriver(cp->GetLastDSPort(), cp->GetLastCommProtocol());
654 
655  // Internal BlueTooth driver stacks commonly need a time delay to purge
656  // their buffers, etc. before restating with new parameters...
657  if (cp->Type == INTERNAL_BT) wxSleep(1);
658 
659  // Connection has been disabled
660  if (!cp->bEnabled) continue;
661 
662  // Make any new or re-enabled drivers
663  MakeCommDriver(cp);
664  cp->b_IsSetup = TRUE;
665  enabled_conns.push_back(cp->GetStrippedDSPort());
666  }
667 }
668 
669 void ConnectionsDialog::OnPriorityDialog(wxCommandEvent& event) {
670  PriorityDlg* pdlg = new PriorityDlg(m_parent);
671  pdlg->ShowModal();
672  delete pdlg;
673 }