OpenCPN Partial API docs
Loading...
Searching...
No Matches
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
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
49extern OCPNPlatform* g_Platform;
50
52wxDEFINE_EVENT(CHANNELS_DL_DONE, wxCommandEvent);
53wxDEFINE_EVENT(CHANNELS_PARSE_DONE, wxCommandEvent);
54wxDEFINE_EVENT(CATALOG_DL_DONE, wxCommandEvent);
55wxDEFINE_EVENT(CATALOG_PARSE_DONE, wxCommandEvent);
56
58wxDEFINE_EVENT(CATALOG_DLG_CLOSE, wxCommandEvent);
59
60#ifdef _WIN32
61static const std::string SEP("\\");
62#else
63static const std::string SEP("/");
64#endif
65
66namespace catalog_mgr {
67
68class Helpers {
69public:
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
80private:
81 wxWindow* parent;
82};
83
85class CatalogUpdate : public wxDialog, Helpers {
86protected:
87 struct UrlEdit; // forward
88 struct ActiveCatalogGrid; // forward
89
90public:
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 HIDE = "<span foreground=\'blue\'>";
98 HIDE += _("Hide");
99 HIDE += " &lt;&lt;&lt;</span>";
100 ADVANCED = "<span foreground=\'blue\'>";
101 ADVANCED += _("Ultra advanced");
102 ADVANCED += " &gt;&gt;&gt;</span>";
103
104 auto sizer = new wxBoxSizer(wxVERTICAL);
105 auto flags = wxSizerFlags().Expand().Border();
106
107 m_catalog_grid = new ActiveCatalogGrid(this);
108 sizer->Add(new UrlStatus(this), flags);
109 sizer->Add(new UrlChannel(this, m_catalog_grid), flags);
110 sizer->Add(new wxStaticLine(this), flags);
111
112 sizer->Add(m_catalog_grid, flags);
113 sizer->Add(new wxStaticLine(this), flags);
114
115 m_advanced = new wxStaticText(this, wxID_ANY, "");
116 m_advanced->Bind(wxEVT_LEFT_DOWN,
117 [=](wxMouseEvent& e) { toggleUrlEdit(); });
118 sizer->Add(m_advanced, flags);
119
120 m_url_box = new wxBoxSizer(wxVERTICAL);
121 m_url_edit = new UrlEdit(this);
122 m_url_box->Add(m_url_edit, flags);
123 m_url_box->Add(new Buttons(this, m_catalog_grid),
124 wxSizerFlags().Border().Right());
125 sizer->Add(m_url_box, flags);
126 sizer->Add(new wxStaticLine(this), flags);
127
128 auto done = makeButton(_("Done"));
129 sizer->Add(done, wxSizerFlags().Border().Right());
130 done->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [=](wxCommandEvent e) {
131 EndModal(wxID_OK);
132 wxCommandEvent evt(CATALOG_DLG_CLOSE);
133 wxPostEvent(GetParent(), evt);
134 e.Skip();
135 });
136 toggleUrlEdit();
137
138 Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent& e) {
139 EndModal(wxID_OK);
140 wxCommandEvent cmd_evt(CATALOG_DLG_CLOSE);
141 wxPostEvent(GetParent(), cmd_evt);
142 e.Skip();
143 });
144
145 SetSizer(sizer);
146 auto size = getWindowSize();
147 size.SetHeight(1);
148 SetMinClientSize(size);
149 Fit();
150 ShowModal();
151 }
152
153protected:
154 wxString HIDE, ADVANCED;
155
156 wxBoxSizer* m_url_box;
157 ActiveCatalogGrid* m_catalog_grid;
158 UrlEdit* m_url_edit;
159 wxStaticText* m_advanced;
160 bool m_show_edit;
161
167 wxSize getWindowSize() {
168 auto uri = CatalogHandler::getInstance()->GetDefaultUrl();
169 auto size = GetTextExtent(uri);
170 size.SetWidth(size.GetWidth() * 120 / 100);
171 size.SetHeight(size.GetHeight() * 130 / 100);
172 return size;
173 }
174
175 void toggleUrlEdit() {
176 m_show_edit = !m_show_edit;
177 m_url_box->GetItem((size_t)0)->GetWindow()->Show(m_show_edit);
178 m_url_box->GetItem((size_t)1)->GetWindow()->Show(m_show_edit);
179 m_advanced->SetLabelMarkup(m_show_edit ? HIDE : ADVANCED);
180 Fit();
181 }
182
184 struct UrlStatus : public wxPanel, public Helpers {
185 UrlStatus(wxWindow* parent) : wxPanel(parent), Helpers(this) {
186 auto sizer = new wxBoxSizer(wxHORIZONTAL);
187 auto flags =
188 wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
189 sizer->Add(staticText(_("Catalog URL status: ")), flags);
190 auto catalog = CatalogHandler::getInstance();
191 int channels = catalog->GetChannels().size();
192 auto text = staticText(channels > 0 ? _("OK") : _("Error"));
193 sizer->Add(text, flags);
194
195 SetSizer(sizer);
196 Fit();
197 Show();
198 }
199 };
200
205 struct ActiveCatalogGrid : public wxPanel, public Helpers {
206 ActiveCatalogGrid(wxWindow* parent) : wxPanel(parent), Helpers(this) {
207 using CmdEvt = wxCommandEvent;
208
209 auto grid = new wxFlexGridSizer(4, 0, 0);
210 auto plugin_handler = PluginHandler::getInstance();
211 grid->AddGrowableCol(0);
212 grid->AddGrowableCol(1);
213 grid->AddGrowableCol(2);
214 grid->AddGrowableCol(3);
215 auto flags = wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL);
216 flags = flags.DoubleBorder();
217
218 /* Cell 0..3 */
219 CatalogData catalog_data =
220 CatalogHandler::getInstance()->UserCatalogData();
221 grid->Add(staticText(_("Current active plugin catalog")), flags);
222 grid->Add(staticText(""), flags);
223 grid->Add(staticText(""), flags);
224 grid->Add(staticText(""), flags);
225
226 /* Cell 4..7 */
227 catalog_data = CatalogHandler::getInstance()->DefaultCatalogData();
228 grid->Add(staticText(_("Default catalog")), flags);
229 grid->Add(staticText(""), flags);
230 grid->Add(staticText(""), flags);
231 auto use_default = makeButton(_("Use as active catalog"));
232 grid->Add(use_default, wxSizerFlags().Border());
233 use_default->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
234 [=](CmdEvt& e) { useDefaultCatalog(); });
235
236 /* Cell 8..11 */
237 catalog_data = CatalogHandler::getInstance()->LatestCatalogData();
238 grid->Add(staticText(_("Latest available catalog:")), flags);
239 grid->Add(staticText(""), flags);
240 grid->Add(staticText(""), flags);
241 auto use_latest = makeButton(_("Use as active catalog"));
242 use_latest->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
243 [=](CmdEvt& e) { UseLatestCatalog(); });
244
245 grid->Add(use_latest, wxSizerFlags().Border());
246
247 SetSizer(grid);
249 Fit();
250 Show();
251 }
252
253 void UpdateVersion(wxSizer* grid, CatalogData data, size_t ix) {
254 auto version =
255 dynamic_cast<wxStaticText*>(grid->GetItem(ix)->GetWindow());
256 version->SetLabel(data.version);
257 auto date =
258 dynamic_cast<wxStaticText*>(grid->GetItem(ix + 1)->GetWindow());
259 date->SetLabel(data.date);
260 }
261
267 CatalogData data = CatalogHandler::getInstance()->UserCatalogData();
268 auto grid = dynamic_cast<wxSizer*>(GetSizer());
269 UpdateVersion(grid, data, 1);
270 data = CatalogHandler::getInstance()->DefaultCatalogData();
271 UpdateVersion(grid, data, 5);
272 data = CatalogHandler::getInstance()->LatestCatalogData();
273 UpdateVersion(grid, data, 9);
274 Refresh(true);
275 Update();
276 }
277
278 std::string GetDefaultCatalogPath() {
279 std::string path = g_Platform->GetSharedDataDir().ToStdString();
280 path += SEP;
281 path += "ocpn-plugins.xml";
282 return path;
283 }
284
285 void ReloadAvailableVersion() {
286 auto handler = CatalogHandler::getInstance();
287 std::ostringstream xml;
288 auto status = handler->DownloadCatalog(&xml);
289 std::string message;
290 if (status != CatalogHandler::ServerStatus::OK) {
291 message = _("Cannot download data from url");
292 }
293 status = handler->ParseCatalog(xml.str(), true);
294 if (status != CatalogHandler::ServerStatus::OK) {
295 message = _("Cannot parse downloaded data");
296 }
297 if (message != "") {
298 wxMessageBox(message, _("Catalog update problem"), wxICON_ERROR);
299 } else {
301 }
302 }
303
304 std::string GetPrivateCatalogPath() {
305 auto plugin_handler = PluginHandler::getInstance();
306 std::string path = g_Platform->GetPrivateDataDir().ToStdString();
307 path += SEP + "ocpn-plugins.xml";
308 return path;
309 }
310
311 void useDefaultCatalog() {
312 auto src = GetDefaultCatalogPath();
313 auto dest = GetPrivateCatalogPath();
314 ocpn::copy_file(src, dest);
315 CatalogHandler::getInstance()->ClearCatalogData();
317 }
318
319 void UseLatestCatalog() {
320 auto catalog = CatalogHandler::getInstance();
321 std::ofstream dest(GetPrivateCatalogPath());
322 catalog->DownloadCatalog(&dest);
323 dest.close();
324 catalog->ClearCatalogData();
326 }
327 };
328
330 struct Buttons : public wxPanel, public Helpers {
331 Buttons(wxWindow* parent, ActiveCatalogGrid* catalog_grid)
332 : wxPanel(parent),
333 Helpers(this),
334 m_catalog_grid(catalog_grid),
335 m_parent(dynamic_cast<CatalogUpdate*>(GetParent())) {
336 auto sizer = new wxBoxSizer(wxHORIZONTAL);
337 auto flags = wxSizerFlags().Right().Bottom().Border();
338
339 auto clear = makeButton(_("Clear"));
340 clear->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
341 [=](wxCommandEvent& ev) { clearUrl(); });
342 sizer->Add(clear, flags);
343
344 auto use_default = makeButton(_("Use default location"));
345 use_default->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
346 [=](wxCommandEvent& ev) { useDefaultUrl(); });
347 sizer->Add(use_default, flags);
348
349 auto update = makeButton(_("Save"));
350 sizer->Add(update, flags);
351 update->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
352 [=](wxCommandEvent& ev) { updateUrl(); });
353
354 SetSizer(sizer);
355 Fit();
356 Show();
357 }
358
359 void useDefaultUrl() {
360 auto url = CatalogHandler::getInstance()->GetDefaultUrl();
361 m_parent->m_url_edit->setText(url);
362 }
363
364 void clearUrl() { m_parent->m_url_edit->clear(); }
365
366 void updateUrl() {
367 auto text = m_parent->m_url_edit->getText();
368 CatalogHandler::getInstance()->SetCustomUrl(text.c_str());
369 m_catalog_grid->ReloadAvailableVersion();
370 }
371
372 ActiveCatalogGrid* m_catalog_grid;
373 CatalogUpdate* m_parent;
374 };
375
377 struct UrlChannel : public wxPanel, public Helpers {
378 UrlChannel(wxWindow* parent, ActiveCatalogGrid* catalog_grid)
379 : wxPanel(parent), Helpers(this), m_catalog_grid(catalog_grid) {
380 auto sizer = new wxBoxSizer(wxHORIZONTAL);
381 auto flags =
382 wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
383 sizer->Add(staticText(_("Catalog channel: ")), flags);
384 auto catalog = CatalogHandler::getInstance();
385 wxArrayString channel_list;
386 for (auto channel : catalog->GetChannels()) {
387 channel_list.Add(channel.c_str());
388 }
389 auto channels = new wxChoice(this, wxID_ANY, wxDefaultPosition,
390 wxDefaultSize, channel_list);
391 auto current = CatalogHandler::getInstance()->GetActiveChannel();
392 int ix = channels->FindString(current.c_str());
393 channels->SetSelection(ix != wxNOT_FOUND ? ix : 0);
394 channels->Bind(wxEVT_CHOICE,
395 [=](wxCommandEvent& e) { onChannelChange(e); });
396 sizer->Add(channels, flags);
397 SetSizer(sizer);
398 Fit();
399 Show();
400 }
401
402 void onChannelChange(wxCommandEvent& ev) {
403 CatalogHandler::getInstance()->SetActiveChannel(ev.GetString());
404 m_catalog_grid->ReloadAvailableVersion();
405 };
406
407 std::string m_active_channel;
408 ActiveCatalogGrid* m_catalog_grid;
409 };
410
412 struct UrlEdit : public wxPanel, public Helpers {
413 UrlEdit(wxWindow* parent) : wxPanel(parent), Helpers(this) {
414 auto sizer = new wxBoxSizer(wxVERTICAL);
415 auto url_location = new wxBoxSizer(wxHORIZONTAL);
416 auto flags = wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL);
417 url_location->Add(staticText(_("Custom catalog URL: ")), flags);
418 flags = wxSizerFlags().Expand().Border();
419 sizer->Add(url_location, flags);
420
421 auto url_edit = new wxBoxSizer(wxHORIZONTAL);
422 auto uri = CatalogHandler::getInstance()->GetCustomUrl();
423 m_url_ctrl = new wxTextCtrl(this, wxID_ANY, uri);
424 auto the_parent = dynamic_cast<CatalogUpdate*>(GetParent());
425 m_url_ctrl->SetMinClientSize(the_parent->getWindowSize());
426 url_edit->Add(m_url_ctrl, wxSizerFlags().Expand());
427
428 sizer->Add(url_edit, flags);
429 SetSizer(sizer);
430 Fit();
431 Show();
432 }
433
434 void setText(std::string text) {
435 m_url_ctrl->Clear();
436 *m_url_ctrl << text;
437 m_url_ctrl->Refresh();
438 }
439
440 void clear() { m_url_ctrl->Clear(); }
441
442 std::string getText() {
443 return std::string(m_url_ctrl->GetLineText(0).ToStdString());
444 }
445
446 wxTextCtrl* m_url_ctrl;
447 };
448};
449
451class CatalogLoad : public wxPanel, public Helpers {
452public:
453 struct DialogGrid; // forward
454
455 CatalogLoad(wxWindow* parent, bool use_latest = false)
456 : wxPanel(parent), Helpers(this), m_simple(use_latest) {
457 auto sizer = new wxBoxSizer(wxVERTICAL);
458 auto flags = wxSizerFlags().Expand().Border();
459 m_grid = new DialogGrid(this);
460 sizer->Add(m_grid, flags);
461 sizer->Add(1, 1, 1, wxEXPAND); // Expanding spacer
462 if (m_simple) {
463 m_buttons = new Buttons(this);
464 sizer->Add(m_buttons, flags.Bottom().Right());
465 }
466 auto size = GetTextExtent(_("Check latest release..."));
467 size.SetHeight(size.GetHeight() * 10);
468 size.SetWidth(size.GetWidth() * 5 / 2);
469 SetMinClientSize(size);
470 std::thread worker([=]() { Worker(); });
471 worker.detach();
472
473 SetSizer(sizer);
474 Fit();
475 Show();
476
477 Bind(CHANNELS_DL_DONE,
478 [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 1); });
479 Bind(CHANNELS_PARSE_DONE,
480 [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 3); });
481 Bind(CATALOG_DL_DONE, [=](wxCommandEvent& ev) { m_grid->CellDone(ev, 5); });
482 Bind(CATALOG_PARSE_DONE, [=](wxCommandEvent& ev) { workerDone(ev); });
483 }
484
485 void PostEvent(int evt_id, catalog_status status, std::string message) {
486 wxCommandEvent evt(evt_id);
487 evt.SetInt(static_cast<int>(status));
488 evt.SetString(message);
489 wxPostEvent(this, evt);
490 }
491
493 void workerDone(wxCommandEvent& ev) {
494 m_grid->CellDone(ev, 5);
495 if (m_simple) {
496 std::string message = _("Catalog updated").ToStdString();
497 std::string path = g_Platform->GetPrivateDataDir().ToStdString();
498 path += SEP;
499 path += "ocpn-plugins.xml";
500 std::ofstream stream;
501 stream.open(path, std::ios::out);
502 if (stream.is_open()) {
503 stream << m_xml.str();
504 stream.close();
505 ev.SetString("Catalog updated");
506 ev.SetInt(static_cast<int>(catalog_status::OK_MSG));
507 } else {
508 ev.SetString("Update error (cannot writé to file)");
509 ev.SetInt(static_cast<int>(catalog_status::OS_ERROR));
510 wxLogMessage("Update error: Cannot write to %s", path.c_str());
511 }
512 m_grid->CellDone(ev, 6);
513 m_buttons->ActivateOk();
514 } else {
515 CatalogData catalog_data;
516 auto handler = CatalogHandler::getInstance();
517 catalog_data = handler->LatestCatalogData();
518 Hide();
519 Refresh(true);
520 Update();
521 new CatalogUpdate(this);
522 }
523 }
524
526 void Worker() {
527 auto catalog = CatalogHandler::getInstance();
528 std::ostringstream json;
529
530 auto status = catalog->LoadChannels(&json);
531 PostEvent(CHANNELS_DL_DONE, status, catalog->LastErrorMsg());
532
533 status = catalog->LoadChannels(json.str());
534 PostEvent(CHANNELS_PARSE_DONE, status, catalog->LastErrorMsg());
535
536 if (status == catalog_status::OK) {
537 auto channel = catalog->GetActiveChannel();
538 status = catalog_status::OK_MSG;
539 PostEvent(CHANNELS_PARSE_DONE, status, channel);
540 }
541 m_xml.clear();
542 status = catalog->DownloadCatalog(&m_xml);
543 PostEvent(CATALOG_DL_DONE, status, catalog->LastErrorMsg());
544
545 status = catalog->ParseCatalog(m_xml.str(), true);
546 if (status == catalog_status::OK) {
547 PostEvent(CATALOG_PARSE_DONE, catalog_status::OK_MSG,
548 catalog->LatestCatalogData().version);
549 } else {
550 PostEvent(CATALOG_PARSE_DONE, status, catalog->LastErrorMsg());
551 }
552 }
553
555 struct DialogGrid : public wxPanel, public Helpers {
556 DialogGrid(wxWindow* parent) : wxPanel(parent), Helpers(this) {
557 auto grid = new wxFlexGridSizer(2, 0, 0);
558 auto flags =
559 wxSizerFlags().Expand().Border().Align(wxALIGN_CENTER_VERTICAL);
560 grid->Add(staticText(_("Server is reachable...")), flags);
561 grid->Add(staticText(""), flags);
562 grid->Add(staticText(_("Check channel...")), flags);
563 grid->Add(staticText(""), flags);
564 grid->Add(staticText(_("Check latest release...")), flags);
565 grid->Add(staticText(""), flags);
566 grid->Add(staticText(""), flags);
567 grid->Add(staticText(""), flags);
568 auto url = CatalogHandler::getInstance()->GetCustomUrl();
569 if (url != "") {
570 grid->Add(staticText(_("Custom URL")), flags);
571 grid->Add(staticText(url.c_str()), flags);
572 }
573 SetSizer(grid);
574 Fit();
575 Show();
576 }
577
578 /* Update status values in grid. */
579 void CellDone(const wxCommandEvent& event, size_t index) {
580 // wxLogMessage("CellDone: event %d", event.GetInt());
581 auto cell = GetSizer()->GetItem(index)->GetWindow();
582 auto code = static_cast<catalog_status>(event.GetInt());
583 if (code == catalog_status::OK) {
584 cell->SetLabel(_("OK"));
585 } else if (code == catalog_status::OK_MSG) {
586 cell->SetLabel(event.GetString().ToStdString());
587 } else {
588 auto msg = std::string(_("Fail: ")) + event.GetString().ToStdString();
589 cell->SetLabel(msg.c_str());
590 }
591 Fit();
592 }
593 };
594
596 struct Buttons : public wxPanel {
597 Buttons(wxWindow* parent) : wxPanel(parent) {
598 using CmdEvt = wxCommandEvent;
599
600 auto sizer = new wxBoxSizer(wxHORIZONTAL);
601 auto flags = wxSizerFlags().Right().Bottom().Border();
602 sizer->Add(1, 1, 100, wxEXPAND); // Expanding spacer
603 auto cancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
604 sizer->Add(cancel, flags);
605 m_ok = new wxButton(this, wxID_OK, _("OK"));
606 m_ok->Enable(false);
607 sizer->Add(m_ok, flags);
608 SetSizer(sizer);
609 Fit();
610 SetFocus();
611 Show();
612 }
613
614 void ActivateOk() { m_ok->Enable(true); }
615
616 wxButton* m_ok;
617 };
618
619 std::ostringstream m_xml;
620 DialogGrid* m_grid;
621 Buttons* m_buttons;
622 const bool m_simple; // Simple means just install, no advanced dialog
623};
624
625} // namespace catalog_mgr
626
629 : wxFrame(parent, wxID_ANY, _("Catalog Manager"), wxDefaultPosition,
630 wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER) {
631 auto vbox = new wxBoxSizer(wxHORIZONTAL);
632 vbox->Add(new catalog_mgr::CatalogLoad(this, false),
633 wxSizerFlags(1).Expand());
634 Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent&) {
635 wxCommandEvent evt(EVT_PLUGINS_RELOAD);
636 wxPostEvent(GetParent(), evt);
637 Destroy();
638 });
639 Bind(CATALOG_DLG_CLOSE, [this](wxCommandEvent&) {
640 wxCommandEvent evt(EVT_PLUGINS_RELOAD);
641 wxPostEvent(GetParent(), evt);
642 Destroy();
643 });
644 SetSizer(vbox);
645
646 Fit();
647 Center();
648 Raise();
649 SetFocus();
650 Show();
651}
652
654 : wxDialog(parent, wxID_ANY, _("Catalog Manager"), wxDefaultPosition,
655 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
656 auto vbox = new wxBoxSizer(wxHORIZONTAL);
657 vbox->Add(new catalog_mgr::CatalogLoad(this, true), wxSizerFlags(1).Expand());
658 Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& e) { EndModal(wxID_OK); });
659 Bind(CATALOG_DLG_CLOSE, [&](wxCommandEvent& ev) { EndModal(wxID_OK); });
660 SetSizer(vbox);
661
662 Fit();
663 ShowModal();
664 Destroy();
665}
Plugin catalog management: Build the runtime catalog, handling downloads as required.
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()
Get the custom url set by SetCustomUrl.
bool SetActiveChannel(const char *channel)
Set the active channel used when downloading catalog.
Provides platform-specific support utilities for OpenCPN.
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.
wxSize getWindowSize()
The window width is determined by the normally hidden custom url text control.
Overall metadata for the set of plugins used.
OK/Cancel buttons for the download progress window.
Grid with Server is Reachable..., Check channel... etc.
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.