OpenCPN Partial API docs
catalog_mgr.cpp
1 /******************************************************************************
2  *
3  * Project: OpenCPN
4  *
5  ***************************************************************************
6  * Copyright (C) 2019 Alec Leamas *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the *
20  * Free Software Foundation, Inc., *
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22  ***************************************************************************
23  */
24 
25 #include "config.h"
26 
27 #include <fstream>
28 #include <sstream>
29 #include <thread>
30 
31 #include <wx/button.h>
32 #include <wx/debug.h>
33 #include <wx/filename.h>
34 #include <wx/log.h>
35 #include <wx/msgdlg.h>
36 #include <wx/panel.h>
37 #include <wx/progdlg.h>
38 #include <wx/sizer.h>
39 #include <wx/statline.h>
40 
41 #include "model/catalog_handler.h"
42 #include "catalog_mgr.h"
43 #include "model/downloader.h"
44 #include "model/ocpn_utils.h"
45 #include "OCPNPlatform.h"
46 #include "model/plugin_handler.h"
47 #include "download_mgr.h"
48 
49 extern OCPNPlatform* g_Platform;
50 
52 wxDEFINE_EVENT(CHANNELS_DL_DONE, wxCommandEvent);
53 wxDEFINE_EVENT(CHANNELS_PARSE_DONE, wxCommandEvent);
54 wxDEFINE_EVENT(CATALOG_DL_DONE, wxCommandEvent);
55 wxDEFINE_EVENT(CATALOG_PARSE_DONE, wxCommandEvent);
56 
58 wxDEFINE_EVENT(CATALOG_DLG_CLOSE, wxCommandEvent);
59 
60 #ifdef _WIN32
61 static const std::string SEP("\\");
62 #else
63 static const std::string SEP("/");
64 #endif
65 
66 namespace catalog_mgr {
67 
68 class Helpers {
69 public:
70  Helpers(wxWindow* _parent) : parent(_parent) {}
71 
72  wxStaticText* staticText(const char* text) {
73  return new wxStaticText(parent, wxID_ANY, text);
74  }
75 
76  wxButton* makeButton(const char* label, int id = wxID_ANY) {
77  return new wxButton(parent, wxID_ANY, label);
78  }
79 
80 private:
81  wxWindow* parent;
82 };
83 
85 class CatalogUpdate : public wxDialog, Helpers {
86 protected:
87  struct UrlEdit; // forward
88  struct ActiveCatalogGrid; // forward
89 
90 public:
91  CatalogUpdate(wxWindow* parent)
92  : wxDialog(parent, wxID_ANY, _("Manage Plugin Catalog"),
93  wxDefaultPosition, wxDefaultSize,
94  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxSTAY_ON_TOP),
95  Helpers(this),
96  m_show_edit(true) {
97 
98  HIDE = "<span foreground=\'blue\'>";
99  HIDE += _("Hide");
100  HIDE += " &lt;&lt;&lt;</span>";
101  ADVANCED = "<span foreground=\'blue\'>";
102  ADVANCED += _("Ultra advanced");
103  ADVANCED += " &gt;&gt;&gt;</span>";
104 
105  auto sizer = new wxBoxSizer(wxVERTICAL);
106  auto flags = wxSizerFlags().Expand().Border();
107 
108  m_catalog_grid = new ActiveCatalogGrid(this);
109  sizer->Add(new UrlStatus(this), flags);
110  sizer->Add(new UrlChannel(this, m_catalog_grid), flags);
111  sizer->Add(new wxStaticLine(this), flags);
112 
113  sizer->Add(m_catalog_grid, flags);
114  sizer->Add(new wxStaticLine(this), flags);
115 
116  m_advanced = new wxStaticText(this, wxID_ANY, "");
117  m_advanced->Bind(wxEVT_LEFT_DOWN,
118  [=](wxMouseEvent& e) { toggleUrlEdit(); });
119  sizer->Add(m_advanced, flags);
120 
121  m_url_box = new wxBoxSizer(wxVERTICAL);
122  m_url_edit = new UrlEdit(this);
123  m_url_box->Add(m_url_edit, flags);
124  m_url_box->Add(new Buttons(this, m_catalog_grid),
125  wxSizerFlags().Border().Right());
126  sizer->Add(m_url_box, flags);
127  sizer->Add(new wxStaticLine(this), flags);
128 
129  auto done = makeButton(_("Done"));
130  sizer->Add(done, wxSizerFlags().Border().Right());
131  done->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent e) {
132  EndModal(wxID_OK);
133  wxCommandEvent evt(CATALOG_DLG_CLOSE);
134  wxPostEvent(GetParent(), evt);
135  e.Skip();
136  });
137  toggleUrlEdit();
138 
139  Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent& e) {
140  EndModal(wxID_OK);
141  wxCommandEvent cmd_evt(CATALOG_DLG_CLOSE);
142  wxPostEvent(GetParent(), cmd_evt);
143  e.Skip();
144  });
145 
146  SetSizer(sizer);
147  auto size = getWindowSize();
148  size.SetHeight(1);
149  SetMinClientSize(size);
150  Fit();
151  ShowModal();
152  }
153 
154 protected:
155  wxString HIDE, ADVANCED;
156 
157  wxBoxSizer* m_url_box;
158  ActiveCatalogGrid* m_catalog_grid;
159  UrlEdit* m_url_edit;
160  wxStaticText* m_advanced;
161  bool m_show_edit;
162 
168  wxSize getWindowSize() {
169  auto uri = CatalogHandler::getInstance()->GetDefaultUrl();
170  auto size = GetTextExtent(uri);
171  size.SetWidth(size.GetWidth() * 120 / 100);
172  size.SetHeight(size.GetHeight() * 130 / 100);
173  return size;
174  }
175 
176  void toggleUrlEdit() {
177  m_show_edit = !m_show_edit;
178  m_url_box->GetItem((size_t)0)->GetWindow()->Show(m_show_edit);
179  m_url_box->GetItem((size_t)1)->GetWindow()->Show(m_show_edit);
180  m_advanced->SetLabelMarkup(m_show_edit ? HIDE : ADVANCED);
181  Fit();
182  }
183 
185  struct UrlStatus : public wxPanel, public Helpers {
186  UrlStatus(wxWindow* parent) : wxPanel(parent), Helpers(this) {
187  auto sizer = new wxBoxSizer(wxHORIZONTAL);
188  auto flags =
189  wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
190  sizer->Add(staticText(_("Catalog URL status: ")), flags);
191  auto catalog = CatalogHandler::getInstance();
192  int channels = catalog->GetChannels().size();
193  auto text = staticText(channels > 0 ? _("OK") : _("Error"));
194  sizer->Add(text, flags);
195 
196  SetSizer(sizer);
197  Fit();
198  Show();
199  }
200  };
201 
206  struct ActiveCatalogGrid : public wxPanel, public Helpers {
207  ActiveCatalogGrid(wxWindow* parent) : wxPanel(parent), Helpers(this) {
208  using CmdEvt = wxCommandEvent;
209 
210  auto grid = new wxFlexGridSizer(4, 0, 0);
211  auto plugin_handler = PluginHandler::getInstance();
212  grid->AddGrowableCol(0);
213  grid->AddGrowableCol(1);
214  grid->AddGrowableCol(2);
215  grid->AddGrowableCol(3);
216  auto flags = wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL);
217  flags = flags.DoubleBorder();
218 
219  /* Cell 0..3 */
220  CatalogData catalog_data =
221  CatalogHandler::getInstance()->UserCatalogData();
222  grid->Add(staticText(_("Current active plugin catalog")), flags);
223  grid->Add(staticText(""), flags);
224  grid->Add(staticText(""), flags);
225  grid->Add(staticText(""), flags);
226 
227  /* Cell 4..7 */
228  catalog_data = CatalogHandler::getInstance()->DefaultCatalogData();
229  grid->Add(staticText(_("Default catalog")), flags);
230  grid->Add(staticText(""), flags);
231  grid->Add(staticText(""), flags);
232  auto use_default = makeButton(_("Use as active catalog"));
233  grid->Add(use_default, wxSizerFlags().Border());
234  use_default->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
235  [=](CmdEvt& e) { useDefaultCatalog(); });
236 
237  /* Cell 8..11 */
238  catalog_data = CatalogHandler::getInstance()->LatestCatalogData();
239  grid->Add(staticText(_("Latest available catalog:")), flags);
240  grid->Add(staticText(""), flags);
241  grid->Add(staticText(""), flags);
242  auto use_latest = makeButton(_("Use as active catalog"));
243  use_latest->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
244  [=](CmdEvt& e) { UseLatestCatalog(); });
245 
246  grid->Add(use_latest, wxSizerFlags().Border());
247 
248  SetSizer(grid);
249  UpdateVersions();
250  Fit();
251  Show();
252  }
253 
254  void UpdateVersion(wxSizer* grid, CatalogData data, size_t ix) {
255  auto version =
256  dynamic_cast<wxStaticText*>(grid->GetItem(ix)->GetWindow());
257  version->SetLabel(data.version);
258  auto date =
259  dynamic_cast<wxStaticText*>(grid->GetItem(ix + 1)->GetWindow());
260  date->SetLabel(data.date);
261  }
262 
267  void UpdateVersions() {
268  CatalogData data = CatalogHandler::getInstance()->UserCatalogData();
269  auto grid = dynamic_cast<wxSizer*>(GetSizer());
270  UpdateVersion(grid, data, 1);
271  data = CatalogHandler::getInstance()->DefaultCatalogData();
272  UpdateVersion(grid, data, 5);
273  data = CatalogHandler::getInstance()->LatestCatalogData();
274  UpdateVersion(grid, data, 9);
275  Refresh(true);
276  Update();
277  }
278 
279  std::string GetDefaultCatalogPath() {
280  std::string path = g_Platform->GetSharedDataDir().ToStdString();
281  path += SEP;
282  path += "ocpn-plugins.xml";
283  return path;
284  }
285 
286  void ReloadAvailableVersion() {
287  auto handler = CatalogHandler::getInstance();
288  std::ostringstream xml;
289  auto status = handler->DownloadCatalog(&xml);
290  std::string message;
291  if (status != CatalogHandler::ServerStatus::OK) {
292  message = _("Cannot download data from url");
293  }
294  status = handler->ParseCatalog(xml.str(), true);
295  if (status != CatalogHandler::ServerStatus::OK) {
296  message = _("Cannot parse downloaded data");
297  }
298  if (message != "") {
299  wxMessageBox(message, _("Catalog update problem"), wxICON_ERROR);
300  } else {
301  UpdateVersions();
302  }
303  }
304 
305  std::string GetPrivateCatalogPath() {
306  auto plugin_handler = PluginHandler::getInstance();
307  std::string path = g_Platform->GetPrivateDataDir().ToStdString();
308  path += SEP + "ocpn-plugins.xml";
309  return path;
310  }
311 
312  void useDefaultCatalog() {
313  auto src = GetDefaultCatalogPath();
314  auto dest = GetPrivateCatalogPath();
315  ocpn::copy_file(src, dest);
316  CatalogHandler::getInstance()->ClearCatalogData();
317  UpdateVersions();
318  }
319 
320  void UseLatestCatalog() {
321  auto catalog = CatalogHandler::getInstance();
322  std::ofstream dest(GetPrivateCatalogPath());
323  catalog->DownloadCatalog(&dest);
324  dest.close();
325  catalog->ClearCatalogData();
326  UpdateVersions();
327  }
328  };
329 
331  struct Buttons : public wxPanel, public Helpers {
332  Buttons(wxWindow* parent, ActiveCatalogGrid* catalog_grid)
333  : wxPanel(parent),
334  Helpers(this),
335  m_catalog_grid(catalog_grid),
336  m_parent(dynamic_cast<CatalogUpdate*>(GetParent())) {
337  auto sizer = new wxBoxSizer(wxHORIZONTAL);
338  auto flags = wxSizerFlags().Right().Bottom().Border();
339 
340  auto clear = makeButton(_("Clear"));
341  clear->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
342  [=](wxCommandEvent& ev) { clearUrl(); });
343  sizer->Add(clear, flags);
344 
345  auto use_default = makeButton(_("Use default location"));
346  use_default->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
347  [=](wxCommandEvent& ev) { useDefaultUrl(); });
348  sizer->Add(use_default, flags);
349 
350  auto update = makeButton(_("Save"));
351  sizer->Add(update, flags);
352  update->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
353  [=](wxCommandEvent& ev) { updateUrl(); });
354 
355  SetSizer(sizer);
356  Fit();
357  Show();
358  }
359 
360  void useDefaultUrl() {
361  auto url = CatalogHandler::getInstance()->GetDefaultUrl();
362  m_parent->m_url_edit->setText(url);
363  }
364 
365  void clearUrl() { m_parent->m_url_edit->clear(); }
366 
367  void updateUrl() {
368  auto text = m_parent->m_url_edit->getText();
369  CatalogHandler::getInstance()->SetCustomUrl(text.c_str());
370  m_catalog_grid->ReloadAvailableVersion();
371  }
372 
373  ActiveCatalogGrid* m_catalog_grid;
374  CatalogUpdate* m_parent;
375  };
376 
378  struct UrlChannel : public wxPanel, public Helpers {
379  UrlChannel(wxWindow* parent, ActiveCatalogGrid* catalog_grid)
380  : wxPanel(parent), Helpers(this), m_catalog_grid(catalog_grid) {
381  auto sizer = new wxBoxSizer(wxHORIZONTAL);
382  auto flags =
383  wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
384  sizer->Add(staticText(_("Catalog channel: ")), flags);
385  auto catalog = CatalogHandler::getInstance();
386  wxArrayString channel_list;
387  for (auto channel : catalog->GetChannels()) {
388  channel_list.Add(channel.c_str());
389  }
390  auto channels = new wxChoice(this, wxID_ANY, wxDefaultPosition,
391  wxDefaultSize, channel_list);
392  auto current = CatalogHandler::getInstance()->GetActiveChannel();
393  int ix = channels->FindString(current.c_str());
394  channels->SetSelection(ix != wxNOT_FOUND ? ix : 0);
395  channels->Bind(wxEVT_CHOICE,
396  [=](wxCommandEvent& e) { onChannelChange(e); });
397  sizer->Add(channels, flags);
398  SetSizer(sizer);
399  Fit();
400  Show();
401  }
402 
403  void onChannelChange(wxCommandEvent& ev) {
404  CatalogHandler::getInstance()->SetActiveChannel(ev.GetString());
405  m_catalog_grid->ReloadAvailableVersion();
406  };
407 
408  std::string m_active_channel;
409  ActiveCatalogGrid* m_catalog_grid;
410  };
411 
413  struct UrlEdit : public wxPanel, public Helpers {
414  UrlEdit(wxWindow* parent) : wxPanel(parent), Helpers(this) {
415  auto sizer = new wxBoxSizer(wxVERTICAL);
416  auto url_location = new wxBoxSizer(wxHORIZONTAL);
417  auto flags = wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL);
418  url_location->Add(staticText(_("Custom catalog URL: ")), flags);
419  flags = wxSizerFlags().Expand().Border();
420  sizer->Add(url_location, flags);
421 
422  auto url_edit = new wxBoxSizer(wxHORIZONTAL);
423  auto uri = CatalogHandler::getInstance()->GetCustomUrl();
424  m_url_ctrl = new wxTextCtrl(this, wxID_ANY, uri);
425  auto the_parent = dynamic_cast<CatalogUpdate*>(GetParent());
426  m_url_ctrl->SetMinClientSize(the_parent->getWindowSize());
427  url_edit->Add(m_url_ctrl, wxSizerFlags().Expand());
428 
429  sizer->Add(url_edit, flags);
430  SetSizer(sizer);
431  Fit();
432  Show();
433  }
434 
435  void setText(std::string text) {
436  m_url_ctrl->Clear();
437  *m_url_ctrl << text;
438  m_url_ctrl->Refresh();
439  }
440 
441  void clear() { m_url_ctrl->Clear(); }
442 
443  std::string getText() {
444  return std::string(m_url_ctrl->GetLineText(0).ToStdString());
445  }
446 
447  wxTextCtrl* m_url_ctrl;
448  };
449 };
450 
452 class CatalogLoad : public wxPanel, public Helpers {
453 public:
454  struct DialogGrid; // forward
455 
456  CatalogLoad(wxWindow* parent, bool use_latest = false)
457  : wxPanel(parent), Helpers(this), m_simple(use_latest) {
458  auto sizer = new wxBoxSizer(wxVERTICAL);
459  auto flags = wxSizerFlags().Expand().Border();
460  m_grid = new DialogGrid(this);
461  sizer->Add(m_grid, flags);
462  sizer->Add(1, 1, 1, wxEXPAND); // Expanding spacer
463  if (m_simple) {
464  m_buttons = new Buttons(this);
465  sizer->Add(m_buttons, flags.Bottom().Right());
466  }
467  auto size = GetTextExtent(_("Check latest release..."));
468  size.SetHeight(size.GetHeight() * 10);
469  size.SetWidth(size.GetWidth() * 5 / 2);
470  SetMinClientSize(size);
471  std::thread worker([=]() { Worker(); });
472  worker.detach();
473 
474  SetSizer(sizer);
475  Fit();
476  Show();
477 
478  Bind(CHANNELS_DL_DONE,
479  [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 1); });
480  Bind(CHANNELS_PARSE_DONE,
481  [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 3); });
482  Bind(CATALOG_DL_DONE, [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 5); });
483  Bind(CATALOG_PARSE_DONE, [=](wxCommandEvent& ev) { workerDone(ev); });
484  }
485 
486  void PostEvent(int evt_id, catalog_status status, std::string message) {
487  wxCommandEvent evt(evt_id);
488  evt.SetInt(static_cast<int>(status));
489  evt.SetString(message);
490  wxPostEvent(this, evt);
491  }
492 
494  void workerDone(wxCommandEvent& ev) {
495  m_grid->CellDone(ev, 5);
496  if (m_simple) {
497  std::string message = _("Catalog updated").ToStdString();
498  std::string path = g_Platform->GetPrivateDataDir().ToStdString();
499  path += SEP;
500  path += "ocpn-plugins.xml";
501  std::ofstream stream;
502  stream.open(path, std::ios::out);
503  if (stream.is_open()) {
504  stream << m_xml.str();
505  stream.close();
506  ev.SetString("Catalog updated");
507  ev.SetInt(static_cast<int>(catalog_status::OK_MSG));
508  } else {
509  ev.SetString("Update error (cannot writé to file)");
510  ev.SetInt(static_cast<int>(catalog_status::OS_ERROR));
511  wxLogMessage("Update error: Cannot write to %s", path.c_str());
512  }
513  m_grid->CellDone(ev, 6);
514  m_buttons->ActivateOk();
515  } else {
516  CatalogData catalog_data;
517  auto handler = CatalogHandler::getInstance();
518  catalog_data = handler->LatestCatalogData();
519  Hide();
520  Refresh(true);
521  Update();
522  new CatalogUpdate(this);
523  }
524  }
525 
527  void Worker() {
528  auto catalog = CatalogHandler::getInstance();
529  std::ostringstream json;
530 
531  auto status = catalog->LoadChannels(&json);
532  PostEvent(CHANNELS_DL_DONE, status, catalog->LastErrorMsg());
533 
534  status = catalog->LoadChannels(json.str());
535  PostEvent(CHANNELS_PARSE_DONE, status, catalog->LastErrorMsg());
536 
537  if (status == catalog_status::OK) {
538  auto channel = catalog->GetActiveChannel();
539  status = catalog_status::OK_MSG;
540  PostEvent(CHANNELS_PARSE_DONE, status, channel);
541  }
542  m_xml.clear();
543  status = catalog->DownloadCatalog(&m_xml);
544  PostEvent(CATALOG_DL_DONE, status, catalog->LastErrorMsg());
545 
546  status = catalog->ParseCatalog(m_xml.str(), true);
547  if (status == catalog_status::OK) {
548  PostEvent(CATALOG_PARSE_DONE, catalog_status::OK_MSG,
549  catalog->LatestCatalogData().version);
550  } else {
551  PostEvent(CATALOG_PARSE_DONE, status, catalog->LastErrorMsg());
552  }
553  }
554 
556  struct DialogGrid : public wxPanel, public Helpers {
557  DialogGrid(wxWindow* parent) : wxPanel(parent), Helpers(this) {
558  auto grid = new wxFlexGridSizer(2, 0, 0);
559  auto flags =
560  wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
561  grid->Add(staticText(_("Server is reachable...")), flags);
562  grid->Add(staticText(""), flags);
563  grid->Add(staticText(_("Check channel...")), flags);
564  grid->Add(staticText(""), flags);
565  grid->Add(staticText(_("Check latest release...")), flags);
566  grid->Add(staticText(""), flags);
567  grid->Add(staticText(""), flags);
568  grid->Add(staticText(""), flags);
569  auto url = CatalogHandler::getInstance()->GetCustomUrl();
570  if (url != "") {
571  grid->Add(staticText(_("Custom URL")), flags);
572  grid->Add(staticText(url.c_str()), flags);
573  }
574  SetSizer(grid);
575  Fit();
576  Show();
577  }
578 
579  /* Update status values in grid. */
580  void CellDone(const wxCommandEvent& event, size_t index) {
581  // wxLogMessage("CellDone: event %d", event.GetInt());
582  auto cell = GetSizer()->GetItem(index)->GetWindow();
583  auto code = static_cast<catalog_status>(event.GetInt());
584  if (code == catalog_status::OK) {
585  cell->SetLabel(_("OK"));
586  } else if (code == catalog_status::OK_MSG) {
587  cell->SetLabel(event.GetString().ToStdString());
588  } else {
589  auto msg = std::string(_("Fail: ")) + event.GetString().ToStdString();
590  cell->SetLabel(msg.c_str());
591  }
592  Fit();
593  }
594  };
595 
597  struct Buttons : public wxPanel {
598  Buttons(wxWindow* parent) : wxPanel(parent) {
599  using CmdEvt = wxCommandEvent;
600 
601  auto sizer = new wxBoxSizer(wxHORIZONTAL);
602  auto flags = wxSizerFlags().Right().Bottom().Border();
603  sizer->Add(1, 1, 100, wxEXPAND); // Expanding spacer
604  auto cancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
605  sizer->Add(cancel, flags);
606  m_ok = new wxButton(this, wxID_OK, _("OK"));
607  m_ok->Enable(false);
608  sizer->Add(m_ok, flags);
609  SetSizer(sizer);
610  Fit();
611  SetFocus();
612  Show();
613  }
614 
615  void ActivateOk() { m_ok->Enable(true); }
616 
617  wxButton* m_ok;
618  };
619 
620  std::ostringstream m_xml;
621  DialogGrid* m_grid;
622  Buttons* m_buttons;
623  const bool m_simple; // Simple means just install, no advanced dialog
624 };
625 
626 } // namespace catalog_mgr
627 
630  : wxFrame(parent, wxID_ANY, _("Catalog Manager"), wxDefaultPosition,
631  wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER) {
632  auto vbox = new wxBoxSizer(wxHORIZONTAL);
633  vbox->Add(new catalog_mgr::CatalogLoad(this, false),
634  wxSizerFlags(1).Expand());
635  Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent&) {
636  wxCommandEvent evt(EVT_PLUGINS_RELOAD);
637  wxPostEvent(GetParent(), evt);
638  Destroy();
639  });
640  Bind(CATALOG_DLG_CLOSE, [this](wxCommandEvent&) {
641  wxCommandEvent evt(EVT_PLUGINS_RELOAD);
642  wxPostEvent(GetParent(), evt);
643  Destroy();
644  });
645  SetSizer(vbox);
646 
647  Fit();
648  Center();
649  Raise();
650  SetFocus();
651  Show();
652 }
653 
655  : wxDialog(parent, wxID_ANY, _("Catalog Manager"), wxDefaultPosition,
656  wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
657  auto vbox = new wxBoxSizer(wxHORIZONTAL);
658  vbox->Add(new catalog_mgr::CatalogLoad(this, true), wxSizerFlags(1).Expand());
659  Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& e) { EndModal(wxID_OK); });
660  Bind(CATALOG_DLG_CLOSE, [&](wxCommandEvent& ev) { EndModal(wxID_OK); });
661  SetSizer(vbox);
662 
663  Fit();
664  ShowModal();
665  Destroy();
666 }
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
AdvancedCatalogDialog(wxWindow *parent)
Invoke the advanced catalog dialog after a status check.
CatalogData DefaultCatalogData()
Data for default version, installed with main opencpn.
std::string GetDefaultUrl()
Get the default URL, with actual channel included.
CatalogData LatestCatalogData()
Data for latest parsed data marked as latest.
CatalogData UserCatalogData()
Data for user catalog which overrides the default one.
std::string GetActiveChannel()
Get the branch (a.
void SetCustomUrl(const char *url)
Set a custom url, overrides also channel settings.
void ClearCatalogData()
Invalidate *CatalogData caches.
std::string GetCustomUrl()
Set a custom url, overrides also channel settings.
bool SetActiveChannel(const char *channel)
Set the active channel used when downloading catalog.
SimpleCatalogDialog(wxWindow *parent)
Perform a simple catalog update without options.
Download status/progress window, always shown at start-up.
void Worker()
Runs in separate, detached thread, started from ctor.
void workerDone(wxCommandEvent &ev)
Last part of initial Worker() call, in main thread.
The advanced dialog showing channels, possible updates, rollback etc.
Definition: catalog_mgr.cpp:85
wxSize getWindowSize()
The window width is determined by the normally hidden custom url text control.
wxDEFINE_EVENT(REST_IO_EVT, ObservedEvt)
Event from IO thread to main.
Datatypes and methods to parse ocpn-plugins.xml XML data, either complete catalog or a single plugin.
OK/Cancel buttons for the download progress window.
Grid with Server is Reachable..., Check channel...
Active catalog: The current active, the default and latest downloaded + buttons to use default or lat...
void UpdateVersions()
Update version and date for default, latest and active catalog.
The buttons below custom url: Use Default and Update.
Combobox where user selects active catalog channel.
Custom url edit control, a text line.
The Url Status line at top.