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
41#include "catalog_handler.h"
42#include "catalog_mgr.h"
43#include "downloader.h"
44#include "ocpn_utils.h"
45#include "OCPNPlatform.h"
46#include "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
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
154protected:
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);
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
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 {
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();
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();
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
452class CatalogLoad : public wxPanel, public Helpers {
453public:
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}
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.
Datatypes and a single method to parse ocpn-plugins.xml XML data.
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.