39#include <unordered_map>
47#if defined(__linux__) && !defined(__ANDROID__)
53#include <wx/filename.h>
54#include <wx/aui/aui.h>
55#include <wx/platinfo.h>
56#include <wx/popupwin.h>
57#include <wx/progdlg.h>
58#include <wx/statline.h>
59#include <wx/tokenzr.h>
60#include <wx/tooltip.h>
62#include <wx/hashset.h>
63#include <wx/hashmap.h>
64#include <wx/jsonval.h>
65#include <wx/jsonreader.h>
67#include <wx/zipstrm.h>
68#include <wx/zstream.h>
69#include <wx/tarstrm.h>
70#include <wx/textwrapper.h>
77#include <archive_entry.h>
78typedef __LA_INT64_T la_int64_t;
88#include "model/ais_target_data.h"
92#include "model/comm_drv_n2k.h"
95#include "model/comm_vars.h"
96#include "model/config_vars.h"
97#include "model/downloader.h"
98#include "model/georef.h"
99#include "model/json_event.h"
101#include "model/multiplexer.h"
102#include "model/nav_object_database.h"
103#include "model/navutil_base.h"
104#include "model/ocpn_utils.h"
105#include "model/plugin_cache.h"
107#include "model/plugin_handler.h"
108#include "model/plugin_loader.h"
109#include "model/plugin_paths.h"
110#include "model/route.h"
111#include "model/routeman.h"
112#include "model/safe_mode.h"
113#include "model/select.h"
114#include "model/semantic_vers.h"
115#include "model/track.h"
118#include "canvasMenu.h"
119#include "cat_settings.h"
120#include "chartbase.h"
125#include "download_mgr.h"
129#include "model/ais_decoder.h"
132#include "observable_confvar.h"
133#include "observable_globvar.h"
135#include "OCPN_AUIManager.h"
137#include "ocpn_frame.h"
138#include "ocpn_pixel.h"
139#include "OCPNPlatform.h"
140#include "OCPNRegion.h"
143#include "pluginmanager.h"
144#include "routemanagerdialog.h"
145#include "routeman_gui.h"
148#include "SoundFactory.h"
150#include "svg_utils.h"
151#include "SystemCmdSound.h"
153#include "update_mgr.h"
154#include "waypointman_gui.h"
158#include "androidUTIL.h"
162#include "glChartCanvas.h"
167#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
168extern wxLocale* plocale_def_lang;
177extern bool g_bShowChartBar;
181extern RouteList* pRouteList;
182extern std::vector<Track*> g_TrackList;
184extern s52plib* ps52plib;
185extern wxString ChartListFileName;
187extern ColorScheme global_color_scheme;
188extern wxArrayString g_locale_catalog_array;
189extern int g_GUIScaleFactor;
190extern int g_ChartScaleFactor;
191extern wxString g_locale;
194extern int g_chart_zoom_modifier_raster;
195extern int g_chart_zoom_modifier_vector;
196extern double g_display_size_mm;
197extern bool g_bopengl;
199extern ChartGroupArray* g_pGroupArray;
200extern unsigned int g_canvasConfig;
202extern wxString g_CmdSoundString;
204extern unsigned int gs_plib_flags;
207extern bool g_bquiting;
209WX_DEFINE_ARRAY_PTR(
ChartCanvas*, arrayofCanvasPtr);
210extern arrayofCanvasPtr g_canvasArray;
212void NotifySetupOptionsPlugin(
const PlugInData* pic);
214enum { CurlThreadId = wxID_HIGHEST + 1 };
216#include <wx/listimpl.cpp>
217WX_DEFINE_LIST(Plugin_WaypointList);
218WX_DEFINE_LIST(Plugin_HyperlinkList);
223static void SendAisJsonMessage(std::shared_ptr<const AisTargetData> pTarget) {
225 if (!GetJSONMessageTargetCount())
return;
230 wxLongLong t = ::wxGetLocalTimeMillis();
232 jMsg[wxS(
"Source")] = wxS(
"AisDecoder");
233 jMsg[wxT(
"Type")] = wxT(
"Information");
234 jMsg[wxT(
"Msg")] = wxS(
"AIS Target");
235 jMsg[wxT(
"MsgId")] = t.GetValue();
236 jMsg[wxS(
"lat")] = pTarget->Lat;
237 jMsg[wxS(
"lon")] = pTarget->Lon;
238 jMsg[wxS(
"sog")] = pTarget->SOG;
239 jMsg[wxS(
"cog")] = pTarget->COG;
240 jMsg[wxS(
"hdg")] = pTarget->HDG;
241 jMsg[wxS(
"mmsi")] = pTarget->MMSI;
242 jMsg[wxS(
"class")] = pTarget->Class;
243 jMsg[wxS(
"ownship")] = pTarget->b_OwnShip;
244 jMsg[wxS(
"active")] = pTarget->b_active;
245 jMsg[wxS(
"lost")] = pTarget->b_lost;
246 wxString l_ShipName = wxString::FromUTF8(pTarget->ShipName);
247 for (
size_t i = 0; i < l_ShipName.Len(); i++) {
248 if (l_ShipName.GetChar(i) ==
'@') l_ShipName.SetChar(i,
'\n');
250 jMsg[wxS(
"shipname")] = l_ShipName;
251 wxString l_CallSign = wxString::FromUTF8(pTarget->CallSign);
252 for (
size_t i = 0; i < l_CallSign.Len(); i++) {
253 if (l_CallSign.GetChar(i) ==
'@') l_CallSign.SetChar(i,
'\n');
255 jMsg[wxS(
"callsign")] = l_CallSign;
256 jMsg[wxS(
"removed")] = pTarget->b_removed;
257 SendJSONMessageToAllPlugins(wxT(
"AIS"), jMsg);
261 return (*p1)->Key().compare((*p2)->Key());
265 auto version = metadata.version;
267 if (version[0] ==
'v') version = version.substr(1);
272 auto imported_version = ParseVersion(metadata);
273 for (
auto& md :
PluginHandler::getInstance()->getAvailable()) {
274 if (md.name != metadata.name)
continue;
275 if (md.is_imported)
continue;
276 if (!PluginHandler::getInstance()->isCompatible(md))
continue;
277 if (ParseVersion(md) >= imported_version)
return true;
288 void message(
const std::string& message) {
290 m_deferred_messages.push_back(message);
295 void show_deferred_messages() {
296 for (
auto m : m_deferred_messages) show_msg(m);
303 void show_msg(wxString msg) {
304 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
305 wxICON_INFORMATION | wxOK, 10);
309 std::vector<wxString> m_deferred_messages;
316 Wrap(win, text, widthMax);
318 wxString
const& GetWrapped()
const {
return m_wrapped; }
319 int const GetLineCount()
const {
return m_lineCount; }
320 wxArrayString GetLineArray() {
return m_array; }
323 virtual void OnOutputLine(
const wxString& line) {
327 virtual void OnNewLine() {
335 wxArrayString m_array;
339 template <
typename T>
340 std::size_t operator()(T t)
const {
341 return static_cast<std::size_t
>(t);
345wxString message_by_status(PluginStatus stat) {
347 case PluginStatus::System:
348 return _(
"Plugin is a standard system plugin");
349 case PluginStatus::Managed:
350 return _(
"Plugin is managed by OpenCPN");
351 case PluginStatus::Unmanaged:
352 return _(
"Plugin is not managed by OpenCPN");
353 case PluginStatus::Ghost:
355 case PluginStatus::Unknown:
356 return _(
"Plugin status unknown");
357 case PluginStatus::LegacyUpdateAvailable:
358 return _(
"Update to managed Plugin is available");
359 case PluginStatus::ManagedInstallAvailable:
360 return _(
"New managed Plugin installation available");
361 case PluginStatus::ManagedInstalledUpdateAvailable:
362 return _(
"Update to installed Plugin is available");
363 case PluginStatus::ManagedInstalledCurrentVersion:
364 return _(
"Plugin is latest available");
365 case PluginStatus::Imported:
366 return _(
"Plugin is imported");
367 case PluginStatus::ManagedInstalledDowngradeAvailable:
369 case PluginStatus::PendingListRemoval:
376static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
378 {{PluginStatus::System,
"emblem-default.svg"},
379 {PluginStatus::Managed,
"emblem-default.svg"},
380 {PluginStatus::Unmanaged,
"emblem-unmanaged.svg"},
381 {PluginStatus::Ghost,
"ghost.svg"},
382 {PluginStatus::Unknown,
"emblem-unmanaged.svg"},
383 {PluginStatus::LegacyUpdateAvailable,
"emblem-legacy-update.svg"},
384 {PluginStatus::ManagedInstallAvailable,
"emblem-download.svg"},
385 {PluginStatus::ManagedInstalledUpdateAvailable,
386 "emblem-legacy-update.svg"},
387 {PluginStatus::ManagedInstalledCurrentVersion,
"emblem-default.svg"},
388 {PluginStatus::ManagedInstalledDowngradeAvailable,
389 "emblem-default.svg"},
390 {PluginStatus::PendingListRemoval,
"emblem-default.svg"},
391 {PluginStatus::Imported,
"emblem-default.svg"}});
393static const std::unordered_map<PluginStatus, const char*, EnumClassHash>
394 literalstatus_by_status(
395 {{PluginStatus::System,
"System"},
396 {PluginStatus::Managed,
"Managed"},
397 {PluginStatus::Unmanaged,
"Unmanaged"},
398 {PluginStatus::Ghost,
"Ghost"},
399 {PluginStatus::Unknown,
"Unknown"},
400 {PluginStatus::LegacyUpdateAvailable,
"LegacyUpdateAvailable"},
401 {PluginStatus::ManagedInstallAvailable,
"ManagedInstallAvailable"},
402 {PluginStatus::ManagedInstalledUpdateAvailable,
403 "ManagedInstalledUpdateAvailable"},
404 {PluginStatus::ManagedInstalledCurrentVersion,
405 "ManagedInstalledCurrentVersion"},
406 {PluginStatus::ManagedInstalledDowngradeAvailable,
407 "ManagedInstalledDowngradeAvailable"},
408 {PluginStatus::PendingListRemoval,
"PendingListRemoval"},
409 {PluginStatus::Imported,
"Imported"}
417static std::vector<PluginMetadata> getCompatiblePlugins() {
419 struct metadata_compare {
422 return lhs.key() < rhs.key();
426 std::vector<PluginMetadata> returnArray;
428 std::set<PluginMetadata, metadata_compare> unique_plugins;
429 for (
auto plugin :
PluginHandler::getInstance()->getAvailable()) {
430 unique_plugins.insert(plugin);
432 for (
auto plugin : unique_plugins) {
434 returnArray.push_back(plugin);
451 std::string installed;
453 if (path ==
"" || !wxFileName::IsFileReadable(path)) {
456 std::ifstream stream;
457 stream.open(path, std::ifstream::in);
466static std::vector<PluginMetadata> getUpdates(
const char* name) {
467 auto updates = getCompatiblePlugins();
469 std::remove_if(updates.begin(), updates.end(),
473 auto inst_vers = getInstalledVersion(name);
474 if (inst_vers.major == -1) {
479 updates.erase(std::remove_if(updates.begin(), updates.end(),
481 return metadata_version(m) == inst_vers;
488static void gui_uninstall(
const PlugInData* pic,
const char* plugin) {
489 g_Platform->ShowBusySpinner();
490 PluginLoader::getInstance()->DeactivatePlugIn(*pic);
492 PluginLoader::getInstance()->UpdatePlugIns();
494 wxLogMessage(
"Uninstalling %s", plugin);
495 PluginHandler::getInstance()->
uninstall(plugin);
496 PluginLoader::getInstance()->UpdatePlugIns();
497 g_Platform->HideBusySpinner();
500static bool LoadAllPlugIns(
bool load_enabled,
bool keep_orphans =
false) {
501 g_Platform->ShowBusySpinner();
503 PluginLoader::getInstance()->
LoadAllPlugIns(load_enabled, keep_orphans);
504 g_Platform->HideBusySpinner();
509static void UninstallPlugin(
const std::string& name) {
510 auto handler = PluginHandler::getInstance();
511 auto loader = PluginLoader::getInstance();
512 auto finder = [name](
const PluginMetadata pm) {
return pm.name == name; };
513 const auto& installed = handler->getInstalled();
514 auto found = std::find_if(installed.begin(), installed.end(), finder);
515 if (found != installed.end()) {
516 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
517 auto const& item = loader->GetPlugInArray()->Item(i);
518 if (item->m_common_name.ToStdString() == name) {
519 DEBUG_LOG <<
"Unloading plugin: " << name;
520 loader->UnLoadPlugIn(i);
524 handler->uninstall(found->name);
525 DEBUG_LOG <<
"Uninstalling: " << found->name;
530 bool uninstall,
const char* name = 0,
531 bool b_forceEnable =
false) {
533 const char* plugin = name == 0 ? pic->
m_common_name.mb_str().data() : name;
534 auto updates = getUpdates(plugin);
535 auto parent_dlg =
dynamic_cast<wxScrolledWindow*
>(parent);
536 wxASSERT(parent_dlg != 0);
538 auto status = dialog.ShowModal();
539 status = dialog.GetReturnCode();
540 if (status != wxID_OK) {
544 auto update = dialog.GetUpdate();
545 if (!g_pi_manager->CheckBlacklistedPlugin(update)) {
549 wxLogMessage(
"Installing %s", update.name.c_str());
551 auto pluginHandler = PluginHandler::getInstance();
553 if (uninstall && path !=
"") {
554 gui_uninstall(pic, update.name.c_str());
556 bool cacheResult = pluginHandler->installPluginFromCache(update);
559 g_Platform->ShowBusySpinner();
563 std::string tempTarballPath = downloader->run(parent_dlg, uninstall);
565 if (!tempTarballPath.size())
571 if (!isRegularFile(manifestPath.c_str())) {
572 wxLogMessage(
"Installation of %s failed", update.name.c_str());
573 PluginHandler::cleanupFiles(manifestPath, update.name);
579 wxLogMessage(
"Installation of %s successful", update.name.c_str());
580 wxURI uri(wxString(update.tarball_url.c_str()));
581 wxFileName fn(uri.GetPath());
582 std::string basename = fn.GetFullName().ToStdString();
585 wxLogDebug(
"Copied %s to local cache at %s", tempTarballPath.c_str(),
587 remove(tempTarballPath.c_str());
595 wxString pispec = _T(
"_pi.dll");
596#elif defined(__WXOSX__)
597 wxString pispec = _T(
"_pi.dylib");
599 wxString pispec = _T(
"_pi.so");
603 wxTextFile manifest_file(manifestPath);
605 if (manifest_file.Open()) {
607 for (wxString str = manifest_file.GetFirstLine(); !manifest_file.Eof();
608 str = manifest_file.GetNextLine()) {
609 if (str.Contains(pispec)) {
610 if (getenv(
"OCPN_KEEP_PLUGINS")) {
614 auto loader = PluginLoader::getInstance();
615 if (!loader->CheckPluginCompatibility(str)) {
617 _(
"The plugin is not compatible with this version of OpenCPN, "
618 "and will be uninstalled.");
619 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
620 wxICON_INFORMATION | wxOK, 10);
622 PluginHandler::cleanupFiles(manifestPath, update.name);
631 if (b_forceEnable && pluginFile.Length()) {
632 wxString config_section = (_T (
"/PlugIns/" ));
633 wxFileName fn(pluginFile);
634 config_section += fn.GetFullName();
635 pConfig->SetPath(config_section);
636 pConfig->Write(_T (
"bEnabled" ),
true);
641 auto handler = PluginHandler::getInstance();
642 std::remove(handler->ImportedMetadataPath(update.name).c_str());
645 LoadAllPlugIns(
false);
655 pivp.clat = tvp.
clat;
656 pivp.clon = tvp.
clon;
658 pivp.skew = tvp.
skew;
663 pivp.rv_rect = tvp.rv_rect;
664 pivp.b_quilt = tvp.b_quilt;
665 pivp.m_projection_type = tvp.m_projection_type;
667 pivp.lat_min = tvp.GetBBox().GetMinLat();
668 pivp.lat_max = tvp.GetBBox().GetMaxLat();
669 pivp.lon_min = tvp.GetBBox().GetMinLon();
670 pivp.lon_max = tvp.GetBBox().GetMaxLon();
672 pivp.bValid = tvp.IsValid();
689 vp.rv_rect = pivp.rv_rect;
690 vp.b_quilt = pivp.b_quilt;
691 vp.m_projection_type = pivp.m_projection_type;
693 if (gFrame->GetPrimaryCanvas())
694 vp.
ref_scale = gFrame->GetPrimaryCanvas()->GetVP().ref_scale;
709 void OnPluginUtilAction(wxCommandEvent& event);
711 DECLARE_EVENT_TABLE()
715EVT_BUTTON(ID_CMD_BUTTON_PERFORM_ACTION, pluginUtilHandler::OnPluginUtilAction)
720void pluginUtilHandler::OnPluginUtilAction(wxCommandEvent& event) {
721 auto panel =
static_cast<PluginPanel*
>(
event.GetClientData());
724 wxASSERT(plugin_list_panel != 0);
726 auto actionPIC = panel->GetPlugin();
727 wxString name = actionPIC->m_common_name;
730 switch (panel->GetAction()) {
731 case ActionVerb::UPGRADE_TO_MANAGED_VERSION: {
732 auto loader = PluginLoader::getInstance();
735 std::string pluginName = actionPIC->m_managed_metadata.name;
737 wxLogMessage(
"Installing managed plugin: %s", pluginName.c_str());
739 new GuiDownloader(plugin_list_panel, actionPIC->m_managed_metadata);
740 downloader->run(plugin_list_panel,
false);
744 if (isRegularFile(manifestPath.c_str())) {
746 for (
unsigned i = 0; i < loader->GetPlugInArray()->GetCount(); i += 1) {
747 if (actionPIC->m_managed_metadata.name ==
748 loader->GetPlugInArray()->Item(i)->m_common_name.ToStdString()) {
749 loader->UnLoadPlugIn(i);
755 LoadAllPlugIns(
false);
757 PluginHandler::cleanupFiles(manifestPath,
758 actionPIC->m_managed_metadata.name);
761 plugin_list_panel->SelectByName(name);
766 case ActionVerb::UPDATE_IMPORTED_VERSION:
767 case ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION:
768 case ActionVerb::REINSTALL_MANAGED_VERSION:
769 case ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION: {
771 auto metaSave = actionPIC->m_managed_metadata;
772 run_update_dialog(plugin_list_panel, actionPIC,
true,
773 metaSave.name.c_str());
777 case ActionVerb::INSTALL_MANAGED_VERSION: {
778 wxLogMessage(
"Installing new managed plugin.");
779 run_update_dialog(plugin_list_panel, actionPIC,
false);
783 case ActionVerb::UNINSTALL_MANAGED_VERSION: {
784 PluginLoader::getInstance()->DeactivatePlugIn(*actionPIC);
788 message.Printf(
"%s %s\n", actionPIC->m_managed_metadata.name.c_str(),
789 actionPIC->m_managed_metadata.version.c_str());
790 message += _(
"successfully un-installed");
792 wxLogMessage(
"Uninstalling %s",
793 actionPIC->m_managed_metadata.name.c_str());
796 actionPIC->m_managed_metadata.name);
799 auto loader = PluginLoader::getInstance();
800 LoadAllPlugIns(
false);
803 OCPNMessageBox(gFrame, message, _(
"Un-Installation complete"),
804 wxICON_INFORMATION | wxOK);
809 case ActionVerb::NOP:
820const wxEventType wxEVT_OCPN_MSG = wxNewEventType();
822OCPN_MsgEvent::OCPN_MsgEvent(wxEventType commandType,
int id)
823 : wxEvent(id, commandType) {}
825OCPN_MsgEvent::~OCPN_MsgEvent() {}
827wxEvent* OCPN_MsgEvent::Clone()
const {
829 newevent->m_MessageID =
832 newevent->m_MessageText = this->m_MessageText.c_str();
841PlugInToolbarToolContainer::PlugInToolbarToolContainer() {
845 bitmap_Rollover_day = NULL;
846 bitmap_Rollover_dusk = NULL;
847 bitmap_Rollover_night = NULL;
850PlugInToolbarToolContainer::~PlugInToolbarToolContainer() {
854 delete bitmap_Rollover_day;
855 delete bitmap_Rollover_dusk;
856 delete bitmap_Rollover_night;
867#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
868EVT_CURL_END_PERFORM(CurlThreadId, PlugInManager::OnEndPerformCurlDownload)
869EVT_CURL_DOWNLOAD(CurlThreadId, PlugInManager::OnCurlDownload)
873static
void event_message_box(const wxString& msg) {
874 OCPNMessageBox(NULL, msg, wxString(_(
"OpenCPN Info")),
875 wxICON_INFORMATION | wxOK, 0);
881 if (!pic->m_toolbox_panel) NotifySetupOptionsPlugin(pic);
886PlugInManager::PlugInManager(
MyFrame* parent) {
887#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
888 m_pCurlThread = NULL;
894 MyFrame* pFrame = GetParentFrame();
896 m_plugin_menu_item_id_next = CanvasMenuHandler::GetNextContextMenuId();
897 m_plugin_tool_id_next = pFrame->GetNextToolbarToolId();
910 new wxRadioBox(pFrame, -1, _T(
""), wxPoint(0, 0), wxSize(-1, -1), as);
916#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
918 m_last_online =
false;
919 m_last_online_chk = -1;
924 m_blacklist = blacklist_factory();
925 m_blacklist_ui = std::unique_ptr<BlacklistUI>(
new BlacklistUI());
927 wxDEFINE_EVENT(EVT_JSON_TO_ALL_PLUGINS,
ObservedEvt);
928 evt_json_to_all_plugins_listener.
Listen(g_pRouteMan->
json_msg,
this,
929 EVT_JSON_TO_ALL_PLUGINS);
930 Bind(EVT_JSON_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
931 auto json = std::static_pointer_cast<const wxJSONValue>(ev.GetSharedPtr());
932 SendJSONMessageToAllPlugins(ev.GetString(), *json);
935 wxDEFINE_EVENT(EVT_LEGINFO_TO_ALL_PLUGINS,
ObservedEvt);
937 EVT_LEGINFO_TO_ALL_PLUGINS);
938 Bind(EVT_LEGINFO_TO_ALL_PLUGINS, [&](
ObservedEvt& ev) {
939 auto ptr = UnpackEvtPointer<ActiveLegDat>(ev);
940 SendActiveLegInfoToAllPlugIns(ptr.get());
943 HandlePluginLoaderEvents();
950PlugInManager::~PlugInManager() {
951#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
952 wxCurlBase::Shutdown();
954 delete m_utilHandler;
957void PlugInManager::InitCommListeners(
void) {
961 auto& msgbus = NavMsgBus::GetInstance();
966 auto ptr = ev.GetSharedPtr();
967 auto n0183_msg = std::static_pointer_cast<const Nmea0183Msg>(ptr);
972 m_listener_SignalK.
Listen(sk_msg,
this, EVT_SIGNALK);
980 std::string s = n0183_msg->payload;
981 wxString sentence(s.c_str());
984 const auto& drivers = CommDriverRegistry::GetInstance().
GetDrivers();
985 auto& target_driver =
FindDriver(drivers, n0183_msg->source->iface);
987 bool bpass_input_filter =
true;
993 params = drv_serial->GetParams();
997 params = drv_net->GetParams();
1002 bpass_input_filter = params.SentencePassesFilter(sentence, FILTER_INPUT);
1005 }
else if (s[0] ==
'!') {
1007 SendAISSentenceToAllPlugIns(sentence);
1012 g_ownshipMMSI_SK = sK_msg->context_self;
1017 std::string msgTerminated = sK_msg->raw_message;
1020 int errors = jsonReader.
Parse(msgTerminated, &root);
1021 if (errors == 0) SendJSONMessageToAllPlugins(wxT(
"OCPN_CORE_SIGNALK"), root);
1030wxDEFINE_EVENT(EVT_PLUGMGR_ROUTEMAN_MSG,
ObservedEvt);
1031wxDEFINE_EVENT(EVT_BLACKLISTED_PLUGIN, wxCommandEvent);
1032wxDEFINE_EVENT(EVT_LOAD_DIRECTORY, wxCommandEvent);
1033wxDEFINE_EVENT(EVT_LOAD_PLUGIN, wxCommandEvent);
1034wxDEFINE_EVENT(EVT_PLUGIN_UNLOAD, wxCommandEvent);
1035wxDEFINE_EVENT(EVT_PLUGLIST_CHANGE, wxCommandEvent);
1036wxDEFINE_EVENT(EVT_UPDATE_CHART_TYPES, wxCommandEvent);
1037wxDEFINE_EVENT(EVT_PLUGIN_LOADALL_FINALIZE, wxCommandEvent);
1039void PlugInManager::HandlePluginLoaderEvents() {
1040 auto loader = PluginLoader::getInstance();
1042 evt_blacklisted_plugin_listener.
Listen(loader->evt_blacklisted_plugin,
this,
1043 EVT_BLACKLISTED_PLUGIN);
1044 Bind(EVT_BLACKLISTED_PLUGIN, [&](wxCommandEvent& ev) {
1045 m_blacklist_ui->message(ev.GetString().ToStdString());
1048 loader->SetOnDeactivateCb(
1050 evt_pluglist_change_listener.
Listen(loader->evt_pluglist_change,
this,
1051 EVT_PLUGLIST_CHANGE);
1052 Bind(EVT_PLUGLIST_CHANGE, [&](wxCommandEvent&) {
1054 if (g_options) g_options->itemBoxSizerPanelPlugins->Layout();
1057 evt_load_directory_listener.
Listen(loader->evt_load_directory,
this,
1058 EVT_LOAD_DIRECTORY);
1059 Bind(EVT_LOAD_DIRECTORY, [&](wxCommandEvent&) {
1060 pConfig->SetPath(
"/PlugIns/");
1061 SetPluginOrder(pConfig->Read(
"PluginOrder", wxEmptyString));
1064 evt_load_plugin_listener.
Listen(loader->evt_load_plugin,
this,
1066 Bind(EVT_LOAD_PLUGIN, [&](wxCommandEvent& ev) {
1071 evt_update_chart_types_listener.
Listen(loader->evt_update_chart_types,
this,
1072 EVT_UPDATE_CHART_TYPES);
1073 Bind(EVT_UPDATE_CHART_TYPES,
1074 [&](wxCommandEvent& ev) { UpDateChartDataTypes(); });
1076 evt_plugin_loadall_finalize_listener.
Listen(
1077 loader->evt_plugin_loadall_finalize,
this, EVT_PLUGIN_LOADALL_FINALIZE);
1078 Bind(EVT_PLUGIN_LOADALL_FINALIZE,
1079 [&](wxCommandEvent& ev) { FinalizePluginLoadall(); });
1081 evt_ais_json_listener.
Listen(g_pAIS->
plugin_msg,
this, EVT_PLUGMGR_AIS_MSG);
1083 EVT_PLUGMGR_ROUTEMAN_MSG);
1085 auto pTarget = UnpackEvtPointer<AisTargetData>(ev);
1086 SendAisJsonMessage(pTarget);
1088 Bind(EVT_PLUGMGR_ROUTEMAN_MSG, [&](
ObservedEvt& ev) {
1089 auto msg = UnpackEvtPointer<wxJSONValue>(ev);
1090 SendJSONMessageToAllPlugins(ev.GetString(), *msg);
1098wxDEFINE_EVENT(EVT_DOWNLOAD_FAILED, wxCommandEvent);
1099wxDEFINE_EVENT(EVT_DOWNLOAD_OK, wxCommandEvent);
1101void PlugInManager::HandlePluginHandlerEvents() {
1102 auto loader = PluginLoader::getInstance();
1104 evt_download_failed_listener.
Listen(loader->evt_update_chart_types,
this,
1105 EVT_DOWNLOAD_FAILED);
1106 Bind(EVT_DOWNLOAD_FAILED, [&](wxCommandEvent& ev) {
1107 wxString message = _(
"Please check system log for more info.");
1108 OCPNMessageBox(gFrame, message, _(
"Installation error"),
1109 wxICON_ERROR | wxOK | wxCENTRE);
1112 evt_download_ok_listener.
Listen(loader->evt_update_chart_types,
this,
1114 Bind(EVT_DOWNLOAD_OK, [&](wxCommandEvent& ev) {
1115 wxString message(ev.GetString());
1116 message += _(
" successfully installed from cache");
1117 OCPNMessageBox(gFrame, message, _(
"Installation complete"),
1118 wxICON_INFORMATION | wxOK | wxCENTRE);
1122bool PlugInManager::CallLateInit(
void) {
1125 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1126 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1129 switch (pic->m_api_version) {
1140 ProcessLateInit(pic);
1150 wxString msg(
"PlugInManager: Calling LateInit PlugIn: ");
1155 if (ppi) ppi->LateInit();
1163 ChartData->PurgeCachePlugins();
1164 gFrame->InvalidateAllQuilts();
1167 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1170 if (pttc->m_pplugin == pic->m_pplugin) {
1171 m_PlugInToolbarTools.Remove(pttc);
1177 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1179 if (pimis->m_pplugin == pic->m_pplugin) {
1180 m_PlugInMenuItems.Remove(pimis);
1186bool PlugInManager::IsAnyPlugInChartEnabled() {
1189 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1190 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1192 if (pic->m_enabled && pic->m_init_state) {
1201void PlugInManager::UpdateManagedPlugins() {
1202 PluginLoader::getInstance()->UpdateManagedPlugins(
false);
1203 PluginLoader::getInstance()->
SortPlugins(ComparePlugins);
1206 g_options->itemBoxSizerPanelPlugins->Layout();
1209bool PlugInManager::UpDateChartDataTypes() {
1211 if (NULL == ChartData)
return bret;
1213 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1214 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1217 if (pic->m_init_state) {
1224 if (bret) ChartData->UpdateChartClassDescriptorArray();
1229void PlugInManager::FinalizePluginLoadall() {
1233 SetColorSchemeForAllPlugIns(global_color_scheme);
1236 SendBaseConfigToAllPlugIns();
1237 SendS52ConfigToAllPlugIns(
true);
1238 SendSKConfigToAllPlugIns();
1243 if (gFrame->GetPrimaryCanvas()->GetglCanvas())
1244 gFrame->GetPrimaryCanvas()->GetglCanvas()->SendJSONConfigMessage();
1252void PlugInManager::SetPluginOrder(wxString serialized_names) {
1253 m_plugin_order.Empty();
1254 wxStringTokenizer tokenizer(serialized_names,
";");
1255 while (tokenizer.HasMoreTokens()) {
1256 m_plugin_order.Add(tokenizer.GetNextToken());
1260wxString PlugInManager::GetPluginOrder() {
1261 wxString plugins = wxEmptyString;
1262 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1263 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1264 plugins.Append(plugin_array->Item(i)->m_common_name);
1265 if (i < plugin_array->GetCount() - 1) plugins.Append(
';');
1270bool PlugInManager::UpdateConfig() {
1274 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1275 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1279 wxString config_section = (_T (
"/PlugIns/" ));
1281 pConfig->SetPath(config_section);
1282 pConfig->Write(_T (
"bEnabled" ), pic->m_enabled);
1289void PlugInManager::ShowDeferredBlacklistMessages() {
1290 m_blacklist_ui->show_deferred_messages();
1293bool PlugInManager::CheckBlacklistedPlugin(
const PluginMetadata plugin) {
1295 return CheckBlacklistedPlugin(wxString(plugin.name), v.major, v.minor);
1298bool PlugInManager::CheckBlacklistedPlugin(
opencpn_plugin* plugin) {
1299 int major = plugin->GetPlugInVersionMajor();
1300 int minor = plugin->GetPlugInVersionMinor();
1303 wxString name = wxString::FromAscii(
typeid(*plugin).name());
1304 name.Replace(
"class ", wxEmptyString);
1306 const std::type_info& ti =
typeid(*plugin);
1308 char* realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
1309 wxString name = wxString::FromAscii(realname);
1312 return CheckBlacklistedPlugin(name, major, minor);
1315bool PlugInManager::CheckBlacklistedPlugin(wxString name,
int major,
1317 auto block_status = m_blacklist->get_status(name.ToStdString(), major, minor);
1318 if (block_status == plug_status::unblocked)
return true;
1319 plug_data data(name.ToStdString(), major, minor);
1320 auto msg = m_blacklist->get_message(block_status, data);
1321 m_blacklist_ui->message(msg);
1325bool PlugInManager::RenderAllCanvasOverlayPlugIns(
ocpnDC& dc,
1329 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1330 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1332 if (pic->m_enabled && pic->m_init_state) {
1336 wxDC* pdc = dc.GetDC();
1339 switch (pic->m_api_version) {
1341 if (priority > 0)
break;
1344 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1348 if (priority > 0)
break;
1351 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1362 if (priority > 0)
break;
1365 if (ppi) ppi->RenderOverlay(*pdc, &pivp);
1370 if (priority > 0)
break;
1374 ppi->RenderOverlay(*pdc, &pivp);
1379 ppi116->RenderOverlayMultiCanvas(*pdc, &pivp, canvasIndex);
1384 if (priority <= 0) {
1388 ppi->RenderOverlay(*pdc, &pivp);
1404 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK)
continue;
1406 if ((m_cached_overlay_bm.GetWidth() != vp.
pix_width) ||
1407 (m_cached_overlay_bm.GetHeight() != vp.
pix_height))
1411 mdc.SelectObject(m_cached_overlay_bm);
1412 mdc.SetBackground(*wxBLACK_BRUSH);
1415 bool b_rendered =
false;
1417 switch (pic->m_api_version) {
1419 if (priority > 0)
break;
1422 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1426 if (priority > 0)
break;
1429 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1440 if (priority > 0)
break;
1443 if (ppi) b_rendered = ppi->RenderOverlay(mdc, &pivp);
1448 if (priority > 0)
break;
1452 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1457 b_rendered = ppi116->RenderOverlayMultiCanvas(mdc, &pivp,
1463 if (priority <= 0) {
1467 b_rendered = ppi->RenderOverlay(mdc, &pivp);
1474 mdc, &pivp, g_canvasConfig, priority);
1478 b_rendered = pic->m_pplugin->RenderOverlay(&mdc, &pivp);
1483 mdc.SelectObject(wxNullBitmap);
1486 wxMask* p_msk =
new wxMask(m_cached_overlay_bm, wxColour(0, 0, 0));
1487 m_cached_overlay_bm.SetMask(p_msk);
1489 dc.DrawBitmap(m_cached_overlay_bm, 0, 0,
true);
1492 }
else if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1500bool PlugInManager::RenderAllGLCanvasOverlayPlugIns(wxGLContext* pcontext,
1504 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1505 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1507 if (pic->m_enabled && pic->m_init_state) {
1508 if (pic->
m_cap_flag & WANTS_OPENGL_OVERLAY_CALLBACK) {
1511 switch (pic->m_api_version) {
1513 if (priority > 0)
break;
1516 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1528 if (priority > 0)
break;
1531 if (ppi) ppi->RenderGLOverlay(pcontext, &pivp);
1536 if (priority > 0)
break;
1540 ppi->RenderGLOverlay(pcontext, &pivp);
1545 ppi116->RenderGLOverlayMultiCanvas(pcontext, &pivp, canvasIndex);
1551 if (priority <= 0) {
1555 ppi->RenderGLOverlay(pcontext, &pivp);
1576void PlugInManager::SendViewPortToRequestingPlugIns(
ViewPort& vp) {
1577 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1578 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1580 if (pic->m_enabled && pic->m_init_state) {
1583 if (pic->m_pplugin) pic->m_pplugin->SetCurrentViewPort(pivp);
1589void NotifySetupOptionsPlugin(
const PlugInData* pd) {
1590 PluginLoader::getInstance()->NotifySetupOptionsPlugin(pd);
1593void PlugInManager::NotifySetupOptions() {
1594 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1595 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1597 NotifySetupOptionsPlugin(pic);
1602 int ok_apply_cancel) {
1603 if (pic->m_enabled && pic->m_init_state) {
1605 pic->m_pplugin->OnCloseToolboxPanel(0, ok_apply_cancel);
1606 auto loader = PluginLoader::getInstance();
1613void PlugInManager::CloseAllPlugInPanels(
int ok_apply_cancel) {
1614 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1615 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1618 ClosePlugInPanel(pic, ok_apply_cancel);
1623int PlugInManager::AddCanvasContextMenuItem(wxMenuItem* pitem,
1627 pmic->pmenu_item = pitem;
1628 pmic->m_pplugin = pplugin;
1629 pmic->id = pitem->GetId() == wxID_SEPARATOR ? wxID_SEPARATOR
1630 : m_plugin_menu_item_id_next;
1632 pmic->b_grey =
false;
1633 pmic->m_in_menu = name;
1635 m_PlugInMenuItems.Add(pmic);
1637 m_plugin_menu_item_id_next++;
1642void PlugInManager::RemoveCanvasContextMenuItem(
int item,
const char* name) {
1643 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1646 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1647 m_PlugInMenuItems.Remove(pimis);
1655void PlugInManager::SetCanvasContextMenuItemViz(
int item,
bool viz,
1657 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1660 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1668void PlugInManager::SetCanvasContextMenuItemGrey(
int item,
bool grey,
1670 for (
unsigned int i = 0; i < m_PlugInMenuItems.GetCount(); i++) {
1673 if (pimis->id == item && !strcmp(name, pimis->m_in_menu)) {
1674 pimis->b_grey = grey;
1681void PlugInManager::SendResizeEventToAllPlugIns(
int x,
int y) {
1682 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1683 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1685 if (pic->m_enabled && pic->m_init_state)
1686 pic->m_pplugin->ProcessParentResize(x, y);
1690void PlugInManager::SetColorSchemeForAllPlugIns(ColorScheme cs) {
1691 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1692 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1694 if (pic->m_enabled && pic->m_init_state)
1695 pic->m_pplugin->SetColorScheme((PI_ColorScheme)cs);
1699void PlugInManager::PrepareAllPluginContextMenus() {
1700 int canvasIndex = gFrame->GetCanvasIndexUnderMouse();
1701 if (canvasIndex < 0)
return;
1703 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1704 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1706 if (pic->m_enabled && pic->m_init_state) {
1708 switch (pic->m_api_version) {
1715 if (ppi) ppi->PrepareContextMenu(canvasIndex);
1726void PlugInManager::SendSKConfigToAllPlugIns() {
1729 v[_T(
"self")] = g_ownshipMMSI_SK;
1733 SendMessageToAllPlugins(wxString(_T(
"OCPN_CORE_SIGNALK")), out);
1736void PlugInManager::SendBaseConfigToAllPlugIns() {
1739 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1740 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1741 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1742 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1743 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1746 if (g_MainToolbar) {
1747 v[_T(
"OpenCPN Toolbar Width")] = g_MainToolbar->GetToolbarRect().width;
1748 v[_T(
"OpenCPN Toolbar Height")] = g_MainToolbar->GetToolbarRect().height;
1749 v[_T(
"OpenCPN Toolbar PosnX")] = g_MainToolbar->GetToolbarRect().x;
1750 v[_T(
"OpenCPN Toolbar PosnY")] = g_MainToolbar->GetToolbarRect().y;
1754 v[_T(
"OpenCPN Zoom Mod Vector")] = g_chart_zoom_modifier_vector;
1755 v[_T(
"OpenCPN Zoom Mod Other")] = g_chart_zoom_modifier_raster;
1756 v[_T(
"OpenCPN Scale Factor Exp")] =
1757 g_Platform->GetChartScaleFactorExp(g_ChartScaleFactor);
1758 v[_T(
"OpenCPN Display Width")] = (int)g_display_size_mm;
1759 v[_T(
"OpenCPN Content Scale Factor")] = OCPN_GetDisplayContentScaleFactor();
1760 v[_T(
"OpenCPN Display DIP Scale Factor")] = OCPN_GetWinDIPScaleFactor();
1765 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1768void PlugInManager::SendS52ConfigToAllPlugIns(
bool bReconfig) {
1771 v[_T(
"OpenCPN Version Major")] = VERSION_MAJOR;
1772 v[_T(
"OpenCPN Version Minor")] = VERSION_MINOR;
1773 v[_T(
"OpenCPN Version Patch")] = VERSION_PATCH;
1774 v[_T(
"OpenCPN Version Date")] = VERSION_DATE;
1775 v[_T(
"OpenCPN Version Full")] = VERSION_FULL;
1783 v[_T(
"OpenCPN S52PLIB ShowAnchorConditions")] = ps52plib->GetAnchorOn();
1784 v[_T(
"OpenCPN S52PLIB ShowQualityOfData")] = ps52plib->GetQualityOfData();
1789 v[_T(
"OpenCPN S52PLIB MetaDisplay")] = ps52plib->m_bShowMeta;
1790 v[_T(
"OpenCPN S52PLIB DeclutterText")] = ps52plib->m_bDeClutterText;
1791 v[_T(
"OpenCPN S52PLIB ShowNationalText")] = ps52plib->m_bShowNationalTexts;
1792 v[_T(
"OpenCPN S52PLIB ShowImportantTextOnly")] =
1793 ps52plib->m_bShowS57ImportantTextOnly;
1794 v[_T(
"OpenCPN S52PLIB UseSCAMIN")] = ps52plib->m_bUseSCAMIN;
1795 v[_T(
"OpenCPN S52PLIB UseSUPER_SCAMIN")] = ps52plib->m_bUseSUPER_SCAMIN;
1796 v[_T(
"OpenCPN S52PLIB SymbolStyle")] = ps52plib->m_nSymbolStyle;
1797 v[_T(
"OpenCPN S52PLIB BoundaryStyle")] = ps52plib->m_nBoundaryStyle;
1798 v[_T(
"OpenCPN S52PLIB ColorShades")] =
1799 S52_getMarinerParam(S52_MAR_TWO_SHADES);
1800 v[_T(
"OpenCPN S52PLIB Safety Depth")] =
1801 (double)S52_getMarinerParam(S52_MAR_SAFETY_DEPTH);
1802 v[_T(
"OpenCPN S52PLIB Shallow Contour")] =
1803 (double)S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR);
1804 v[_T(
"OpenCPN S52PLIB Deep Contour")] =
1805 (double)S52_getMarinerParam(S52_MAR_DEEP_CONTOUR);
1809 v[_T(
"OpenCPN S52PLIB GlobalReconfig")] = bReconfig;
1814 SendMessageToAllPlugins(wxString(_T(
"OpenCPN Config")), out);
1817void PlugInManager::NotifyAuiPlugIns(
void) {
1818 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
1819 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
1821 if (pic->m_enabled && pic->m_init_state &&
1823 pic->m_pplugin->UpdateAuiStatus();
1827int PlugInManager::AddToolbarTool(wxString label, wxBitmap* bitmap,
1828 wxBitmap* bmpRollover, wxItemKind kind,
1829 wxString shortHelp, wxString longHelp,
1830 wxObject* clientData,
int position,
1833 pttc->label = label;
1835 if (!bitmap->IsOk()) {
1837 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1840 pttc->bitmap_day =
new wxBitmap(*bitmap);
1841 pttc->bitmap_day->UnShare();
1844 if (!bmpRollover->IsOk()) {
1846 pttc->bitmap_Rollover_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1849 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1850 pttc->bitmap_Rollover_day->UnShare();
1853 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1854 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1855 pttc->bitmap_Rollover_dusk =
1856 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1857 pttc->bitmap_Rollover_night =
1858 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1861 pttc->shortHelp = shortHelp;
1862 pttc->longHelp = longHelp;
1863 pttc->clientData = clientData;
1864 pttc->position = position;
1865 pttc->m_pplugin = pplugin;
1866 pttc->tool_sel = tool_sel;
1868 pttc->b_toggle =
false;
1869 pttc->id = m_plugin_tool_id_next;
1871 m_PlugInToolbarTools.Add(pttc);
1873 m_plugin_tool_id_next++;
1878int PlugInManager::AddToolbarTool(wxString label, wxString SVGfile,
1879 wxString SVGRolloverfile,
1880 wxString SVGToggledfile, wxItemKind kind,
1881 wxString shortHelp, wxString longHelp,
1882 wxObject* clientData,
int position,
1885 pttc->label = label;
1887 pttc->pluginNormalIconSVG = SVGfile;
1888 pttc->pluginRolloverIconSVG = SVGRolloverfile;
1889 pttc->pluginToggledIconSVG = SVGToggledfile;
1894 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1895 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1896 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1897 pttc->bitmap_Rollover_day =
new wxBitmap(*pttc->bitmap_day);
1898 pttc->bitmap_Rollover_dusk =
1899 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 128);
1900 pttc->bitmap_Rollover_night =
1901 BuildDimmedToolBitmap(pttc->bitmap_Rollover_day, 32);
1904 pttc->shortHelp = shortHelp;
1905 pttc->longHelp = longHelp;
1906 pttc->clientData = clientData;
1907 pttc->position = position;
1908 pttc->m_pplugin = pplugin;
1909 pttc->tool_sel = tool_sel;
1911 pttc->b_toggle =
false;
1912 pttc->id = m_plugin_tool_id_next;
1914 m_PlugInToolbarTools.Add(pttc);
1916 m_plugin_tool_id_next++;
1921void PlugInManager::RemoveToolbarTool(
int tool_id) {
1922 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1925 if (pttc->id == tool_id) {
1926 m_PlugInToolbarTools.Remove(pttc);
1932 pParent->RequestNewToolbars();
1935void PlugInManager::SetToolbarToolViz(
int item,
bool viz) {
1936 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1939 if (pttc->id == item) {
1941 pParent->RequestNewToolbars();
1948void PlugInManager::SetToolbarItemState(
int item,
bool toggle) {
1949 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1952 if (pttc->id == item) {
1953 pttc->b_toggle = toggle;
1954 pParent->SetMasterToolbarItemState(item, toggle);
1961void PlugInManager::SetToolbarItemBitmaps(
int item, wxBitmap* bitmap,
1962 wxBitmap* bmpRollover) {
1963 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
1966 if (pttc->id == item) {
1967 delete pttc->bitmap_day;
1968 delete pttc->bitmap_dusk;
1969 delete pttc->bitmap_night;
1970 delete pttc->bitmap_Rollover_day;
1972 if (!bitmap->IsOk()) {
1974 pttc->bitmap_day =
new wxBitmap(style->GetIcon(_T(
"default_pi")));
1977 pttc->bitmap_day =
new wxBitmap(*bitmap);
1978 pttc->bitmap_day->UnShare();
1981 if (!bmpRollover->IsOk()) {
1983 pttc->bitmap_Rollover_day =
1984 new wxBitmap(style->GetIcon(_T(
"default_pi")));
1987 pttc->bitmap_Rollover_day =
new wxBitmap(*bmpRollover);
1988 pttc->bitmap_Rollover_day->UnShare();
1991 pttc->bitmap_dusk = BuildDimmedToolBitmap(pttc->bitmap_day, 128);
1992 pttc->bitmap_night = BuildDimmedToolBitmap(pttc->bitmap_day, 32);
1994 pParent->SetToolbarItemBitmaps(item, pttc->bitmap_day,
1995 pttc->bitmap_Rollover_day);
2002void PlugInManager::SetToolbarItemBitmaps(
int item, wxString SVGfile,
2003 wxString SVGfileRollover,
2004 wxString SVGfileToggled) {
2005 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2008 if (pttc->id == item) {
2009 pttc->pluginNormalIconSVG = SVGfile;
2010 pttc->pluginRolloverIconSVG = SVGfileRollover;
2011 pttc->pluginToggledIconSVG = SVGfileToggled;
2012 pParent->SetToolbarItemSVG(item, pttc->pluginNormalIconSVG,
2013 pttc->pluginRolloverIconSVG,
2014 pttc->pluginToggledIconSVG);
2022 for (
unsigned int i = 0; i < m_PlugInToolbarTools.GetCount(); i++) {
2024 if (
id == pc->id)
return pc->m_pplugin;
2030wxString PlugInManager::GetToolOwnerCommonName(
const int id) {
2033 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2034 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2036 if (pic && (pic->m_pplugin == ppi))
return pic->
m_common_name;
2040 return wxEmptyString;
2043wxString PlugInManager::GetLastError() {
return m_last_error_string; }
2045wxBitmap* PlugInManager::BuildDimmedToolBitmap(wxBitmap* pbmp_normal,
2046 unsigned char dim_ratio) {
2047 wxImage img_dup = pbmp_normal->ConvertToImage();
2049 if (!img_dup.IsOk())
return NULL;
2051 if (dim_ratio < 200) {
2053 int gimg_width = img_dup.GetWidth();
2054 int gimg_height = img_dup.GetHeight();
2056 double factor = (double)(dim_ratio) / 256.0;
2058 for (
int iy = 0; iy < gimg_height; iy++) {
2059 for (
int ix = 0; ix < gimg_width; ix++) {
2060 if (!img_dup.IsTransparent(ix, iy)) {
2061 wxImage::RGBValue rgb(img_dup.GetRed(ix, iy),
2062 img_dup.GetGreen(ix, iy),
2063 img_dup.GetBlue(ix, iy));
2064 wxImage::HSVValue hsv = wxImage::RGBtoHSV(rgb);
2065 hsv.value = hsv.value * factor;
2066 wxImage::RGBValue nrgb = wxImage::HSVtoRGB(hsv);
2067 img_dup.SetRGB(ix, iy, nrgb.red, nrgb.green, nrgb.blue);
2073 wxBitmap* ptoolBarBitmap;
2076 wxBitmap tbmp(img_dup.GetWidth(), img_dup.GetHeight(), -1);
2078 dwxdc.SelectObject(tbmp);
2080 ptoolBarBitmap =
new wxBitmap(img_dup, (wxDC&)dwxdc);
2082 ptoolBarBitmap =
new wxBitmap(img_dup);
2086 return ptoolBarBitmap;
2089wxArrayString PlugInManager::GetPlugInChartClassNameArray(
void) {
2090 wxArrayString array;
2091 auto plugin_array = PluginLoader::getInstance()->GetPlugInArray();
2092 for (
unsigned int i = 0; i < plugin_array->GetCount(); i++) {
2094 if (pic && pic->m_enabled && pic->m_init_state &&
2097 wxArrayString carray = pic->m_pplugin->GetDynamicChartClassNameArray();
2099 for (
unsigned int j = 0; j < carray.GetCount(); j++) {
2100 array.Add(carray[j]);
2108 while (j < array.GetCount()) {
2109 wxString test = array[j];
2110 unsigned int k = j + 1;
2111 while (k < array.GetCount()) {
2112 if (test == array[k]) {
2130#define DISABLED_SETTINGS_MSG \
2131 _("These settings might destabilize OpenCPN and are by default disabled." \
2132 " To despite the dangers enable them manually add a CatalogExpert=1" \
2133 " line in the [PlugIns] section in the configuration file.")
2138CatalogMgrPanel::CatalogMgrPanel(wxWindow* parent)
2139 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize),
2141 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2144 topSizer->Add(
new wxStaticLine(
this), 0, wxGROW | wxLEFT | wxRIGHT, 4);
2146 wxStaticBox* itemStaticBoxSizer4Static =
2147 new wxStaticBox(
this, wxID_ANY, _(
"Plugin Catalog"));
2148 wxStaticBoxSizer* itemStaticBoxSizer4 =
2149 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
2150 topSizer->Add(itemStaticBoxSizer4, 1, wxEXPAND | wxALL, 2);
2154 m_catalogText =
new wxStaticText(
this, wxID_STATIC, _T(
""));
2155 itemStaticBoxSizer4->Add(m_catalogText,
2156 wxSizerFlags().Border().Proportion(1));
2157 m_catalogText->SetLabel(GetCatalogText(
false));
2160 wxBoxSizer* rowSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2161 itemStaticBoxSizer4->Add(rowSizer2,
2162 wxSizerFlags().Expand().Border().Proportion(1));
2164 m_updateButton =
new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog"),
2165 wxDefaultPosition, wxDefaultSize, 0);
2166 rowSizer2->Add(m_updateButton, 0, wxALIGN_LEFT);
2167 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2168 &CatalogMgrPanel::OnUpdateButton,
this);
2169 rowSizer2->AddSpacer(4 * GetCharWidth());
2170 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2171 wxDefaultPosition, wxDefaultSize, 0);
2172 rowSizer2->Add(m_tarballButton, 0, wxALIGN_LEFT | wxLEFT, 2 * GetCharWidth());
2173 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2174 &CatalogMgrPanel::OnTarballButton,
this);
2176 rowSizer2->AddSpacer(4 * GetCharWidth());
2177 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2178 wxDefaultPosition, wxDefaultSize, 0);
2180 if (expert.Get(
false)) {
2181 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2182 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2184 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
2185 wxMessageBox(DISABLED_SETTINGS_MSG, _(
"Disabled"));
2188 rowSizer2->AddSpacer(4 * GetCharWidth());
2189 rowSizer2->Add(m_adv_button, 0, wxALIGN_LEFT);
2191 SetUpdateButtonLabel();
2194 wxBoxSizer* rowSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2195 itemStaticBoxSizer4->Add(rowSizer3, 0, wxEXPAND | wxALL, 4);
2197 SetMinSize(wxSize(m_parent->GetClientSize().x - (4 * GetCharWidth()), -1));
2201 wxDEFINE_EVENT(EVT_CATALOG_CHANGE, wxCommandEvent);
2202 catalog_listener.Listen(catalog,
this, EVT_CATALOG_CHANGE);
2203 Bind(EVT_CATALOG_CHANGE, [&](wxCommandEvent&) { SetUpdateButtonLabel(); });
2206 SetBackgroundColour(wxColour(0x7c, 0xb0, 0xe9));
2208 if (!expert.Get(
false)) {
2210 new wxButton(
this, wxID_ANY, _(
"Update Plugin Catalog: master"),
2211 wxDefaultPosition, wxDefaultSize, 0);
2212 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT);
2213 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2214 &CatalogMgrPanel::OnUpdateButton,
this);
2215 SetUpdateButtonLabel();
2216 m_tarballButton = NULL;
2217 m_adv_button = NULL;
2220 m_catalogText =
new wxStaticText(
this, wxID_STATIC, GetCatalogText(
false));
2221 itemStaticBoxSizer4->Add(m_catalogText,
2222 wxSizerFlags().Border(wxALL, 5).Proportion(1));
2225 m_updateButton =
new wxButton(
2226 this, wxID_ANY,
"Update Plugin Catalog:master ",
2227 wxDefaultPosition, wxDefaultSize, 0);
2228 itemStaticBoxSizer4->Add(m_updateButton, 0, wxALIGN_LEFT | wxTOP, 5);
2229 m_updateButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2230 &CatalogMgrPanel::OnUpdateButton,
this);
2231 SetUpdateButtonLabel();
2234 m_adv_button =
new wxButton(
this, wxID_ANY, _(
"Settings..."),
2235 wxDefaultPosition, wxDefaultSize, 0);
2236 itemStaticBoxSizer4->Add(m_adv_button, 0, wxALIGN_LEFT | wxTOP,
2238 m_adv_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2239 &CatalogMgrPanel::OnPluginSettingsButton,
this);
2242 m_tarballButton =
new wxButton(
this, wxID_ANY, _(
"Import plugin..."),
2243 wxDefaultPosition, wxDefaultSize, 0);
2244 itemStaticBoxSizer4->Add(m_tarballButton, 0, wxALIGN_LEFT | wxALL,
2245 2 * GetCharWidth());
2246 m_tarballButton->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
2247 &CatalogMgrPanel::OnTarballButton,
this);
2253CatalogMgrPanel::~CatalogMgrPanel() {
2254 m_updateButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2255 &CatalogMgrPanel::OnUpdateButton,
this);
2256 if (m_tarballButton)
2257 m_tarballButton->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
2258 &CatalogMgrPanel::OnTarballButton,
this);
2261static const char*
const DOWNLOAD_REPO_PROTO =
2262 "https://raw.githubusercontent.com/OpenCPN/plugins/@branch@/"
2265void CatalogMgrPanel::OnUpdateButton(wxCommandEvent& event) {
2267 std::string catalog(g_catalog_channel ==
"" ?
"master" : g_catalog_channel);
2268 std::string url(g_catalog_custom_url);
2269 if (catalog !=
"custom") {
2270 url = std::string(DOWNLOAD_REPO_PROTO);
2271 ocpn::replace(url,
"@branch@", catalog);
2274 std::string filePath =
2275 wxFileName::CreateTempFileName(
"ocpn_dl").ToStdString();
2277 auto catalogHdlr = CatalogHandler::getInstance();
2279 g_Platform->ShowBusySpinner();
2280 auto status = catalogHdlr->DownloadCatalog(filePath, url);
2281 g_Platform->HideBusySpinner();
2283 std::string message;
2284 if (status != CatalogHandler::ServerStatus::OK) {
2285 message = _(
"Cannot download data from url");
2286 OCPNMessageBox(
this, message, _(
"OpenCPN Catalog update"),
2287 wxICON_ERROR | wxOK);
2293 if (!AndroidSecureCopyFile(wxString(filePath.c_str()),
2295 wxFileName::GetPathSeparator() +
2296 _T(
"ocpn-plugins.xml"))) {
2297 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2298 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2303 if (!wxCopyFile(wxString(filePath.c_str()),
2305 wxFileName::GetPathSeparator() +
2306 _T(
"ocpn-plugins.xml"))) {
2307 OCPNMessageBox(
this, _(
"Unable to copy catalog file"),
2308 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2314 if (catalog ==
"master") {
2316 OCPNMessageBox(
this, _(
"Unable to copy catalog file to cache"),
2317 _(
"OpenCPN Catalog update"), wxICON_ERROR | wxOK);
2323 pConfig->SetPath(_T(
"/PlugIns/"));
2324 pConfig->Write(
"LatestCatalogDownloaded", catalog.c_str());
2330 auto pluginHandler = PluginHandler::getInstance();
2331 pluginHandler->setMetadata(
"");
2335 auto cataloghdlr = CatalogHandler::getInstance();
2336 cataloghdlr->ClearCatalogData();
2339 LoadAllPlugIns(
false);
2343 m_catalogText->SetLabel(GetCatalogText(
true));
2346 OCPNMessageBox(
this, _(
"Catalog update successful"),
2347 _(
"OpenCPN Catalog update"), wxICON_INFORMATION | wxOK);
2350void CatalogMgrPanel::OnPluginSettingsButton(wxCommandEvent& event) {
2354 androidDisableRotation();
2357 dialog->ShowModal();
2360 androidEnableRotation();
2364void CatalogMgrPanel::OnTarballButton(wxCommandEvent& event) {
2367 int response = g_Platform->DoFileSelectorDialog(
2368 this, &path, _(
"Select tarball file"), GetImportInitDir(),
"",
2369 "tar files (*.tar.gz)|*.tar.gz|All Files (*.*)|*.*");
2371 if (response != wxID_OK) {
2374 auto handler = PluginHandler::getInstance();
2376 bool ok = handler->ExtractMetadata(path.ToStdString(), metadata);
2380 _(
"Error extracting metadata from tarball (missing metadata.xml?)"),
2381 _(
"OpenCPN Plugin Import Error"));
2385 OCPNMessageBox(
this, _(
"Incompatible import plugin detected."),
2386 _(
"OpenCPN Plugin Import Error"));
2387 handler->uninstall(metadata.name);
2390 UninstallPlugin(metadata.name);
2391 ok = handler->installPlugin(metadata, path.ToStdString());
2393 OCPNMessageBox(
this, _(
"Error extracting import plugin tarball."),
2394 _(
"OpenCPN Plugin Import Error"));
2397 metadata.is_imported =
true;
2399 std::ofstream file(metadata_path);
2402 WARNING_LOG <<
"Error saving metadata file: " << metadata_path
2403 <<
" for imported plugin: " << metadata.name;
2405 LoadAllPlugIns(
false,
true);
2408 wxString ws(_(
"Plugin"));
2409 ws += metadata.name + _(
" successfully imported");
2410 OCPNMessageBox(gFrame, ws, _(
"Installation complete"),
2411 wxICON_INFORMATION | wxOK | wxCENTRE);
2414wxString CatalogMgrPanel::GetCatalogText(
bool updated) {
2416 catalog = updated ? _(
"Active Catalog") : _(
"Last Catalog");
2417 catalog += _T(
": ");
2420 pConfig->SetPath(_T(
"/PlugIns/"));
2421 wxString latestCatalog =
2422 pConfig->Read(_T(
"LatestCatalogDownloaded"), _T(
"default"));
2423 catalog += latestCatalog;
2428 auto pluginHandler = PluginHandler::getInstance();
2429 std::string date = pluginHandler->GetCatalogData()->date;
2431 catalog += wxString(
" ") + _(
"Last change: ") +
" " + date;
2432 if (!updated) catalog += _T(
" : ") + _(
"Please Update Plugin Catalog.");
2438void CatalogMgrPanel::SetUpdateButtonLabel() {
2439 wxString label = _(
"Update Plugin Catalog");
2441 label += g_catalog_channel ==
"" ?
"master" : g_catalog_channel;
2442 m_updateButton->SetLabel(label);
2446wxString CatalogMgrPanel::GetImportInitDir() {
2448 pConfig->SetPath(_T(
"/PlugIns/"));
2449 wxString lastImportDir;
2450 lastImportDir = pConfig->Read(_T(
"LatestImportDir"),
2451 g_Platform->GetWritableDocumentsDir());
2452 if (wxDirExists(lastImportDir)) {
2453 return lastImportDir;
2455 return (g_Platform->GetWritableDocumentsDir());
2464 const wxPoint& pos, const wxSize& size)
2465 : wxScrolledWindow(parent,
id, pos, size, wxTAB_TRAVERSAL | wxVSCROLL),
2466 m_PluginSelected(0) {
2467 m_is_loading.clear();
2468 SetSizer(
new wxBoxSizer(wxVERTICAL));
2469 ReloadPluginPanels();
2472void PluginListPanel::SelectByName(wxString& name) {
2473 for (
auto it = GetChildren().GetFirst(); it; it = it->GetNext()) {
2474 auto pluginPanel =
dynamic_cast<PluginPanel*
>(it->GetData());
2476 if (pluginPanel->GetPluginPtr()->m_common_name.IsSameAs(name)) {
2477 pluginPanel->SetSelected(
true);
2478 pluginPanel->Layout();
2479 SelectPlugin(pluginPanel);
2487std::vector<const PlugInData*> GetInstalled() {
2488 std::vector<const PlugInData*> result;
2489 auto loader = PluginLoader::getInstance();
2490 for (
size_t i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
2491 auto const item = loader->GetPlugInArray()->Item(i);
2492 if (item->m_managed_metadata.name.empty()) {
2493 const auto name = item->m_common_name.ToStdString();
2497 result.push_back(item);
2500 std::string slhs, srhs;
2501 for (
auto& cl : lhs->Key()) slhs += toupper(cl);
2502 for (
auto& cr : rhs->Key()) srhs += toupper(cr);
2503 return slhs.compare(srhs) < 0;
2505 std::sort(result.begin(), result.end(), compare);
2510static bool IsPluginLoaded(
const std::string& name) {
2511 if (safe_mode::get_mode()) {
2514 std::find(installed.begin(), installed.end(), ocpn::tolower(name));
2515 return found != installed.end();
2517 auto loaded = PluginLoader::getInstance()->GetPlugInArray();
2518 for (
size_t i = 0; i < loaded->GetCount(); i++) {
2519 if (loaded->Item(i)->m_common_name.ToStdString() == name)
return true;
2526 if (m_is_loading.test_and_set()) {
2528 DEBUG_LOG <<
"LoadAllPlugins: recursive invocation";
2532 auto plugins = PluginLoader::getInstance()->GetPlugInArray();
2533 m_PluginItems.Clear();
2535 wxWindowList kids = GetChildren();
2536 for (
unsigned int i = 0; i < kids.GetCount(); i++) {
2537 wxWindowListNode* node = kids.Item(i);
2538 wxWindow* win = node->GetData();
2540 if (pp) win->Destroy();
2542 GetSizer()->Clear();
2545 m_PluginSelected = 0;
2547 if (safe_mode::get_mode()) {
2550 for (
const auto& name : installed) AddPlugin(name);
2553 auto available = getCompatiblePlugins();
2557 return IsPluginLoaded(md.name);
2559 auto end = std::remove_if(available.begin(), available.end(), predicate);
2560 available.erase(end, available.end());
2566 std::string slhs, srhs;
2567 for (
auto& cl : lhs.name) slhs += toupper(cl);
2568 for (
auto& cr : rhs.name) srhs += toupper(cr);
2569 return slhs.compare(srhs) < 0;
2573 std::set<PluginMetadata, CompSort> unique_sorted_entries(comp_sort);
2574 for (
const auto& p : available) unique_sorted_entries.insert(p);
2579 for (
const auto& p : GetInstalled())
2580 if (p->m_enabled) AddPlugin(*p);
2583 for (
const auto& p : GetInstalled())
2584 if (!p->m_enabled) AddPlugin(*p);
2587 for (
const auto& p : unique_sorted_entries) AddPlugin(
PlugInData(p));
2595 m_is_loading.clear();
2598void PluginListPanel::AddPlugin(
const std::string& name) {
2601 panel->SetSelected(
false);
2602 GetSizer()->Add(panel, 0, wxEXPAND);
2603 m_PluginItems.Add(panel);
2604 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2605 GetSizer()->AddSpacer(m_pluginSpacer);
2608void PluginListPanel::AddPlugin(
const PlugInData& pic) {
2610 new PluginPanel(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, pic);
2611 pPluginPanel->SetSelected(
false);
2612 GetSizer()->Add(pPluginPanel, 0, wxEXPAND);
2613 m_PluginItems.Add(pPluginPanel);
2615 m_pluginSpacer = g_Platform->GetDisplayDPmm() * 1.0;
2616 GetSizer()->AddSpacer(m_pluginSpacer);
2629int PluginListPanel::ComputePluginSpace(ArrayOfPluginPanel plugins,
2630 wxBoxSizer* sizer) {
2632 for (
size_t i = 0; i < plugins.GetCount(); i++) {
2633 auto panel = plugins.Item(i);
2634 bool was_selected = panel->GetSelected();
2635 panel->SetSelected(
false);
2637 wxSize unselected = panel->GetSize();
2639 panel->SetSelected(
true);
2641 wxSize selected = panel->GetSize();
2643 int dy = selected.GetHeight() - unselected.GetHeight();
2644 max_dy = wxMax(max_dy, dy);
2645 panel->SetSelected(was_selected);
2650PluginListPanel::~PluginListPanel() {}
2652void PluginListPanel::UpdateSelections() {
2653 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2656 pPluginPanel->SetSelected(pPluginPanel->GetSelected());
2661void PluginListPanel::SelectPlugin(
PluginPanel* pi) {
2663 GetViewStart(&xs, &ys);
2666 if (m_PluginSelected) {
2667 m_PluginSelected->SetSelected(
false);
2668 m_PluginSelected->Layout();
2671 if (pi == NULL) m_PluginSelected->SetSelected(
false);
2673 m_PluginSelected = pi;
2675 GetSizer()->Layout();
2677 wxSize size = GetBestVirtualSize();
2678 SetVirtualSize(size);
2683 for (
unsigned int i = 0; i < m_PluginItems.GetCount(); i++) {
2685 int yd = pPluginPanel->GetSize().y;
2687 htop += m_pluginSpacer;
2688 if (pPluginPanel == pi) {
2689 int piBottom = htop - (ys * g_options->GetScrollRate());
2690 if (piBottom > GetClientSize().y) {
2691 ys += (piBottom - GetClientSize().y) / g_options->GetScrollRate();
2701 int pos = m_PluginItems.Index(pi);
2704 m_PluginItems.RemoveAt(pos);
2707 m_PluginItems.Insert(pi, pos - 1);
2708 wxStaticLine* itemStaticLine =
new wxStaticLine(
2709 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2714 m_PluginSelected = pi;
2716 GetSizer()->Layout();
2722 int pos = m_PluginItems.Index(pi);
2723 if (pos == (
int)m_PluginItems.Count() -
2726 m_PluginItems.RemoveAt(pos);
2729 m_PluginItems.Insert(pi, pos + 1);
2730 wxStaticLine* itemStaticLine =
new wxStaticLine(
2731 this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
2736 m_PluginSelected = pi;
2738 GetSizer()->Layout();
2743static bool canUninstall(std::string name) {
2744 PluginHandler* pluginHandler = PluginHandler::getInstance();
2747 for (
auto plugin : pluginHandler->getInstalled()) {
2748 if (plugin.name == name) {
2749 if (safe_mode::get_mode())
2752 return !plugin.readonly;
2759 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
2761 m_is_safe_panel(true) {
2763 wxASSERT(m_PluginListPanel != 0);
2764 wxBoxSizer* top_sizer =
new wxBoxSizer(wxVERTICAL);
2765 SetSizer(top_sizer);
2766 wxBoxSizer* top_horizontal =
new wxBoxSizer(wxHORIZONTAL);
2767 top_sizer->Add(top_horizontal, 0, wxEXPAND);
2769 double iconSize = GetCharWidth() * 4;
2771 int icon_scale = iconSize * dpi_mult;
2773 wxBitmap bitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2774 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2775 top_horizontal->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2777 m_pName =
new wxStaticText(
this, wxID_ANY, name);
2778 top_horizontal->Add(m_pName, wxID_ANY, wxALIGN_CENTER_VERTICAL);
2779 m_pVersion =
new wxStaticText(
this, wxID_ANY,
"");
2780 top_horizontal->Add(m_pVersion);
2783 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2784 top_horizontal->Add(m_pButtons);
2785 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2786 top_horizontal->Add(m_info_btn);
2787 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2788 wxDefaultPosition, wxDefaultSize, 0);
2789 top_horizontal->Add(m_pButtonUninstall, 0, wxALIGN_CENTER_VERTICAL | wxALL,
2791 auto uninstall = [&](wxCommandEvent ev) {
2792 auto n = m_pName->GetLabel().ToStdString();
2794 OCPNMessageBox(gFrame, std::string(_(
"Uninstall plugin ")) + n +
"?",
2795 _(
"Un-Installation"), wxICON_QUESTION | wxOK | wxCANCEL);
2796 if (result != wxID_OK)
return;
2800 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED, uninstall);
2804EVT_PAINT(PluginPanel::OnPaint)
2809 : wxPanel(parent,
id, pos, size, wxBORDER_NONE),
2811 m_is_safe_panel(false) {
2814 wxASSERT(m_PluginListPanel != 0);
2816 m_bSelected =
false;
2817 m_penWidthUnselected = g_Platform->GetDisplayDPmm() * .25;
2818 m_penWidthSelected = g_Platform->GetDisplayDPmm() * .5;
2820 wxBoxSizer* topSizer =
new wxBoxSizer(wxVERTICAL);
2823 wxBoxSizer* itemBoxSizer01 =
new wxBoxSizer(wxHORIZONTAL);
2824 topSizer->Add(itemBoxSizer01, 0, wxEXPAND);
2825 Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2826 Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2828 double iconSize = GetCharWidth() * 4;
2830 int icon_scale = iconSize * dpi_mult;
2832 wxImage plugin_icon;
2834 if (m_plugin.m_bitmap.IsOk()) {
2835 plugin_icon = m_plugin.m_bitmap.ConvertToImage();
2838 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2839 wxFileName path(g_Platform->GetSharedDataDir(),
"packageBox.svg");
2840 path.AppendDir(
"uidata");
2841 path.AppendDir(
"traditional");
2842 bitmap = LoadSVG(path.GetFullPath(), icon_scale, icon_scale);
2843 }
else if (plugin_icon.IsOk()) {
2844 int nowSize = plugin_icon.GetWidth();
2845 plugin_icon.Rescale(icon_scale, icon_scale, wxIMAGE_QUALITY_HIGH);
2846 bitmap = wxBitmap(plugin_icon);
2848 bitmap = wxBitmap(style->GetIcon(
"default_pi", icon_scale, icon_scale));
2850 m_itemStaticBitmap =
new wxStaticBitmap(
this, wxID_ANY, bitmap);
2852 itemBoxSizer01->Add(m_itemStaticBitmap, 0, wxEXPAND | wxALL, 10);
2853 m_itemStaticBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
2855 m_itemStaticBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
2858 wxBoxSizer* itemBoxSizer02 =
new wxBoxSizer(wxVERTICAL);
2859 itemBoxSizer01->Add(itemBoxSizer02, 1, wxEXPAND | wxALL, 0);
2862 int nChars = g_options->GetSize().x / GetCharWidth();
2863 bool bCompact =
false;
2869 wxString nameString = m_plugin.m_common_name;
2873 dc.GetTextExtent(m_plugin.m_common_name, &nameWidth, NULL);
2874 if (nameWidth > maxWidth) {
2875 nameString = wxControl::Ellipsize(m_plugin.m_common_name, dc,
2876 wxELLIPSIZE_END, maxWidth);
2878 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2879 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2880 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2881 itemBoxSizer02->Add(m_pName, 0, wxALL, 5);
2883 wxFlexGridSizer* sl1 =
new wxFlexGridSizer(2, 0, 0);
2884 sl1->AddGrowableCol(1);
2885 itemBoxSizer02->Add(sl1, 0, wxEXPAND);
2887 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2888 sl1->Add(m_pVersion, 0, wxALL, 5);
2889 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
2892 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2893 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2895 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2896 sl1->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 5);
2897 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2900 wxString descriptionString = m_plugin.m_short_description;
2901 int maxDescriptionWidth = g_Platform->
getDisplaySize().x - (iconSize * 4);
2902 int descriptionWidth;
2903 dc.GetTextExtent(m_plugin.m_short_description, &descriptionWidth, NULL);
2904 if (descriptionWidth > maxDescriptionWidth)
2906 wxControl::Ellipsize(m_plugin.m_short_description, dc,
2907 wxELLIPSIZE_END, maxDescriptionWidth);
2912 new wxStaticText(
this, wxID_ANY, descriptionString, wxDefaultPosition,
2913 wxSize(maxDescriptionWidth, -1), wxST_NO_AUTORESIZE);
2914 itemBoxSizer02->Add(m_pDescription, 0, wxEXPAND | wxALL, 5);
2915 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2916 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2919 wxFlexGridSizer* itemBoxSizer03 =
new wxFlexGridSizer(4, 0, 0);
2920 itemBoxSizer03->AddGrowableCol(2);
2921 itemBoxSizer02->Add(itemBoxSizer03, 0, wxEXPAND);
2923 wxString nameString = m_plugin.m_common_name;
2924 m_pName =
new wxStaticText(
this, wxID_ANY, nameString);
2925 m_pName->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2926 m_pName->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2930 wxFont font = GetFont();
2931 font.SetWeight(wxFONTWEIGHT_BOLD);
2932 m_pName->SetFont(font);
2935 itemBoxSizer03->Add(m_pName, 0, wxALL, 10);
2937 m_pVersion =
new wxStaticText(
this, wxID_ANY, _T(
"X.YY.ZZ.AA"));
2938 itemBoxSizer03->Add(m_pVersion, 0, wxALL, 10);
2939 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable ||
2940 m_plugin.m_status == PluginStatus::System ||
2941 (m_plugin.m_status == PluginStatus::Unmanaged &&
2942 !m_plugin.m_managed_metadata.is_orphan)) {
2945 m_pVersion->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2946 m_pVersion->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2948 m_cbEnable =
new wxCheckBox(
this, wxID_ANY, _(
"Enabled"));
2949 itemBoxSizer03->Add(m_cbEnable, 1, wxALIGN_RIGHT | wxTOP, 10);
2950 m_cbEnable->Bind(wxEVT_CHECKBOX, &PluginPanel::OnPluginEnableToggle,
this);
2952 itemBoxSizer03->Add(5 * GetCharWidth(), 1, 0, wxALIGN_RIGHT | wxTOP, 10);
2954 m_pDescription =
new wxStaticText(
2955 this, wxID_ANY, m_plugin.m_short_description, wxDefaultPosition,
2957 itemBoxSizer02->Add(m_pDescription, 1, wxEXPAND | wxALL, 5);
2958 m_pDescription->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
2959 m_pDescription->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
this);
2963 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2965 itemBoxSizer02->Add(m_info_btn, 0);
2967 m_pButtons =
new wxBoxSizer(wxHORIZONTAL);
2968 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2969 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2970 wxDefaultPosition, wxDefaultSize, 0);
2971 m_pButtons->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 2);
2973 m_pButtons->AddSpacer(3 * GetCharWidth());
2976 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
2977 wxDefaultPosition, wxDefaultSize, 0);
2978 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
2980 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
2981 wxDefaultPosition, wxDefaultSize, 0);
2982 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
2984 m_pButtons =
new wxBoxSizer(wxVERTICAL);
2985 itemBoxSizer02->Add(m_pButtons, 0, wxALL, 0);
2987 wxBoxSizer* tline =
new wxBoxSizer(wxHORIZONTAL);
2988 m_pButtons->Add(tline, 0, wxALL, 2);
2990 m_pButtonPreferences =
new wxButton(
this, wxID_ANY, _(
"Preferences"),
2991 wxDefaultPosition, wxDefaultSize, 0);
2992 tline->Add(m_pButtonPreferences, 0, wxALIGN_LEFT | wxALL, 0);
2994 tline->AddSpacer(3 * GetCharWidth());
2996 m_info_btn =
new WebsiteButton(
this,
"https:\\opencpn.org");
2998 tline->Add(m_info_btn, 0);
3001 new wxButton(
this, wxID_ANY,
"Upgrade to Version XX.XX.XX",
3002 wxDefaultPosition, wxDefaultSize);
3003 m_pButtons->Add(m_pButtonAction, 0, wxALIGN_LEFT | wxALL, 2);
3005 m_pButtonUninstall =
new wxButton(
this, wxID_ANY, _(
"Uninstall"),
3006 wxDefaultPosition, wxDefaultSize, 0);
3007 m_pButtons->Add(m_pButtonUninstall, 0, wxALIGN_LEFT | wxALL, 2);
3010 wxBitmap statusBitmap;
3011 const auto stat = m_plugin.m_status;
3012 auto icon_name = icon_by_status.at(stat);
3013 if (stat == PluginStatus::Imported &&
3014 IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3016 icon_by_status.at(PluginStatus::ManagedInstalledUpdateAvailable);
3019 wxFileName path(g_Platform->GetSharedDataDir(), icon_name);
3020 path.AppendDir(
"uidata");
3021 path.AppendDir(
"traditional");
3023 int bmsize = GetCharWidth() * 3 * dpi_mult;
3024 if (path.IsFileReadable()) {
3025 statusBitmap = LoadSVG(path.GetFullPath(), bmsize, bmsize);
3026 ok = statusBitmap.IsOk();
3029 auto style = g_StyleManager->GetCurrentStyle();
3030 statusBitmap = wxBitmap(style->GetIcon(_T(
"default_pi"), bmsize, bmsize));
3031 wxLogMessage(
"Icon: %s not found.", path.GetFullPath());
3034 m_itemStatusIconBitmap =
new wxStaticBitmap(
this, wxID_ANY, statusBitmap);
3035 m_itemStatusIconBitmap->SetToolTip(message_by_status(stat));
3036 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3038 m_itemStatusIconBitmap->Bind(wxEVT_LEFT_UP, &PluginPanel::OnPluginSelectedUp,
3041 itemBoxSizer01->Add(m_itemStatusIconBitmap, 0, wxEXPAND | wxALL, 20);
3043 itemBoxSizer02->AddSpacer(GetCharWidth());
3045 m_pButtonPreferences->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3046 &PluginPanel::OnPluginPreferences,
this);
3047 m_pButtonUninstall->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3048 &PluginPanel::OnPluginUninstall,
this);
3049 m_pButtonAction->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3050 &PluginPanel::OnPluginAction,
this);
3052 SetSelected(m_bSelected);
3053 SetAutoLayout(
true);
3061PluginPanel::~PluginPanel() {
3062 Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3063 if (m_is_safe_panel)
return;
3064 m_itemStaticBitmap->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
3066 m_pName->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3067 m_pVersion->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3068 m_pDescription->Unbind(wxEVT_LEFT_DOWN, &PluginPanel::OnPluginSelected,
this);
3069 if (m_pButtonAction) {
3070 m_pButtonAction->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3071 &PluginPanel::OnPluginAction,
this);
3073 m_pButtonPreferences->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3074 &PluginPanel::OnPluginPreferences,
this);
3075 m_cbEnable->Unbind(wxEVT_COMMAND_BUTTON_CLICKED,
3076 &PluginPanel::OnPluginEnableToggle,
this);
3079void PluginPanel::SetActionLabel(wxString& label) {
3080 m_pButtonAction->SetLabel(label);
3084static wxStopWatch swclick;
3085static int downx, downy;
3087void PluginPanel::OnPluginSelected(wxMouseEvent& event) {
3090 event.GetPosition(&downx, &downy);
3096void PluginPanel::OnPluginSelectedUp(wxMouseEvent& event) {
3098 qDebug() << swclick.Time();
3099 if (swclick.Time() < 200) {
3101 event.GetPosition(&upx, &upy);
3102 if ((fabs(upx - downx) < GetCharWidth()) &&
3103 (fabs(upy - downy) < GetCharWidth())) {
3111void PluginPanel::DoPluginSelect() {
3112 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable) {
3118 run_update_dialog(m_PluginListPanel, &m_plugin,
false, 0,
true);
3119 }
else if (m_bSelected) {
3121 m_PluginListPanel->SelectPlugin(NULL);
3124 m_PluginListPanel->SelectPlugin(
this);
3132static PluginMetadata GetMetadataByName(
const std::string& name) {
3133 auto plugins = PluginHandler::getInstance()->
getInstalled();
3134 auto predicate = [name](
const PluginMetadata& pm) {
return pm.name == name; };
3135 auto found = std::find_if(plugins.begin(), plugins.end(), predicate);
3136 if (found == plugins.end()) {
3137 wxLogDebug(
"Cannot find metadata for %s", name.c_str());
3142void PluginPanel::SetSelected(
bool selected) {
3143 m_bSelected = selected;
3145 m_pVersion->SetLabel(
3148 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3149 m_pButtons->Show(
true);
3150 bool unInstallPossible = canUninstall(m_plugin.
m_common_name.ToStdString());
3153 if (m_plugin.m_status == PluginStatus::LegacyUpdateAvailable ||
3154 m_plugin.m_status == PluginStatus::Unmanaged ||
3155 m_plugin.m_status == PluginStatus::System)
3156 unInstallPossible =
false;
3159 if (m_plugin.m_managed_metadata.is_orphan) unInstallPossible =
true;
3161 m_pButtonUninstall->Show(unInstallPossible);
3163 if (m_plugin.m_managed_metadata.info_url.size()) {
3164 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3168 m_cbEnable->Show(
true);
3173 switch (m_plugin.m_status) {
3174 case PluginStatus::LegacyUpdateAvailable:
3175 label = _(
"Upgrade to Version ");
3176 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3177 m_action = ActionVerb::UPGRADE_TO_MANAGED_VERSION;
3178 m_pButtonAction->Enable();
3181 case PluginStatus::ManagedInstallAvailable:
3182 label = _(
"Install...");
3183 m_action = ActionVerb::INSTALL_MANAGED_VERSION;
3184 m_pButtonAction->Enable();
3187 case PluginStatus::ManagedInstalledUpdateAvailable:
3188 label = _(
"Update to ");
3189 label += wxString(m_plugin.m_managed_metadata.version.c_str());
3190 m_action = ActionVerb::UPGRADE_INSTALLED_MANAGED_VERSION;
3191 m_pButtonAction->Enable();
3194 case PluginStatus::ManagedInstalledCurrentVersion:
3195 label = _(
"Reinstall");
3196 m_action = ActionVerb::REINSTALL_MANAGED_VERSION;
3197 m_pButtonAction->Enable();
3200 case PluginStatus::ManagedInstalledDowngradeAvailable:
3201 label = _(
"Downgrade");
3202 m_action = ActionVerb::DOWNGRADE_INSTALLED_MANAGED_VERSION;
3203 m_pButtonAction->Enable();
3206 case PluginStatus::Imported:
3207 if (IsUpdateAvailable(m_plugin.m_managed_metadata)) {
3208 label = _(
"Update");
3209 m_action = ActionVerb::UPDATE_IMPORTED_VERSION;
3211 m_pButtonAction->Hide();
3212 m_action = ActionVerb::NOP;
3216 case PluginStatus::Unmanaged:
3217 m_action = ActionVerb::NOP;
3218 m_pButtonAction->Hide();
3221 case PluginStatus::System:
3222 m_action = ActionVerb::NOP;
3223 m_pButtonAction->Hide();
3228 m_action = ActionVerb::NOP;
3231 SetActionLabel(label);
3234 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3243 m_pButtons->Show(
false);
3246 if (m_plugin.m_status == PluginStatus::ManagedInstallAvailable)
3247 m_cbEnable->Show(
false);
3263 SetBackgroundColour(GetDialogColor(DLG_SELECTED_BACKGROUND));
3265 SetBackgroundColour(GetDialogColor(DLG_UNSELECTED_BACKGROUND));
3268 SetEnabled(m_plugin.m_enabled);
3283void PluginPanel::OnPaint(wxPaintEvent& event) {
3286 int penWidth = m_penWidthUnselected;
3287 wxColour color = GetDialogColor(DLG_UNSELECTED_BACKGROUND);
3288 wxColour border = GetDialogColor(DLG_UNSELECTED_ACCENT);
3291 penWidth = m_penWidthSelected;
3292 color = GetDialogColor(DLG_SELECTED_BACKGROUND);
3293 border = GetDialogColor(DLG_SELECTED_ACCENT);
3296 wxBrush b(color, wxBRUSHSTYLE_SOLID);
3298 dc.SetPen(wxPen(border, penWidth));
3300 dc.DrawRoundedRectangle(5, 5, GetSize().x - 10, GetSize().y - 10, 5);
3303void PluginPanel::OnPluginPreferences(wxCommandEvent& event) {
3304 if (m_plugin.m_enabled && m_plugin.m_init_state &&
3307 androidDisableRotation();
3318void PluginPanel::OnPluginEnableToggle(wxCommandEvent& event) {
3319 SetEnabled(event.IsChecked());
3320 m_pVersion->SetLabel(
3322 if (m_plugin.m_status == PluginStatus::System) {
3325 PluginLoader::getInstance()->evt_pluglist_change.
Notify();
3329void PluginPanel::OnPluginUninstall(wxCommandEvent& event) {
3330 m_action = ActionVerb::UNINSTALL_MANAGED_VERSION;
3333 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3334 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3335 actionEvent.SetClientData(
this);
3336 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3339void PluginPanel::OnPluginAction(wxCommandEvent& event) {
3341 wxCommandEvent actionEvent(wxEVT_COMMAND_BUTTON_CLICKED);
3342 actionEvent.SetId(ID_CMD_BUTTON_PERFORM_ACTION);
3343 actionEvent.SetClientData(
this);
3344 g_pi_manager->GetUtilHandler()->AddPendingEvent(actionEvent);
3349static void SetWindowFontStyle(wxWindow* window, wxFontStyle style) {
3350 auto font = window->GetFont();
3351 font.SetStyle(style);
3352 window->SetFont(font);
3355void PluginPanel::SetEnabled(
bool enabled) {
3356 if (m_is_safe_panel)
return;
3358 PluginLoader::getInstance()->UpdatePlugIns();
3359 NotifySetupOptionsPlugin(&m_plugin);
3360 if (!enabled && !m_bSelected) {
3361 SetWindowFontStyle(m_pName, wxFONTSTYLE_ITALIC);
3362 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_ITALIC);
3363 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_ITALIC);
3366 m_pVersion->Disable();
3367 m_pDescription->Disable();
3370 SetWindowFontStyle(m_pName, wxFONTSTYLE_NORMAL);
3371 SetWindowFontStyle(m_pVersion, wxFONTSTYLE_NORMAL);
3372 SetWindowFontStyle(m_pDescription, wxFONTSTYLE_NORMAL);
3375 m_pVersion->Enable();
3376 m_pDescription->Enable();
3381 m_pName->Enable(enabled || m_bSelected);
3382 m_pVersion->Enable(enabled || m_bSelected);
3383 m_pDescription->Enable(enabled || m_bSelected);
3387 wxString description = m_plugin.m_long_description;
3388 if (description.IsEmpty())
3389 description = wxString(m_plugin.m_managed_metadata.description.c_str());
3392 g_options->GetSize().x * 7 / 10);
3393 m_pDescription->SetLabel(wrapper.GetWrapped());
3394 if (m_plugin.m_managed_metadata.info_url.size()) {
3395 m_info_btn->SetURL(m_plugin.m_managed_metadata.info_url.c_str());
3399 wxString description = m_plugin.m_short_description;
3400 if (description.IsEmpty())
3401 description = wxString(m_plugin.m_managed_metadata.summary.c_str());
3403 g_options->GetSize().x * 7 / 10);
3404 m_pDescription->SetLabel(wrapper.GetWrapped());
3407 m_pButtonPreferences->Enable(enabled &&
3409 m_cbEnable->SetValue(enabled);
3412void PluginPanel::OnPluginUp(wxCommandEvent& event) {
3413 m_PluginListPanel->MoveUp(
this);
3416void PluginPanel::OnPluginDown(wxCommandEvent& event) {
3417 m_PluginListPanel->MoveDown(
this);
3422 : wxPanel(parent), m_url(url) {
3423 auto vbox =
new wxBoxSizer(wxVERTICAL);
3424 auto button =
new wxButton(
this, wxID_ANY, _(
"Website"));
3425 button->Enable(strlen(url) > 0);
3428 Bind(wxEVT_COMMAND_BUTTON_CLICKED,
3429 [=](wxCommandEvent&) { wxLaunchDefaultBrowser(m_url); });
3437PlugInChartBase::PlugInChartBase() { m_Chart_Error_Factor = 0.; }
3439PlugInChartBase::~PlugInChartBase() {}
3441wxString PlugInChartBase::GetFileSearchMask(
void) {
return _T(
""); }
3443int PlugInChartBase::Init(
const wxString& name,
int init_flags) {
return 0; }
3447double PlugInChartBase::GetNormalScaleMin(
double canvas_scale_factor,
3448 bool b_allow_overzoom) {
3452double PlugInChartBase::GetNormalScaleMax(
double canvas_scale_factor,
3457bool PlugInChartBase::GetChartExtent(
ExtentPI* pext) {
return false; }
3459wxBitmap& PlugInChartBase::RenderRegionView(
const PlugIn_ViewPort& VPoint,
3460 const wxRegion& Region) {
3461 return wxNullBitmap;
3469void PlugInChartBase::GetValidCanvasRegion(
const PlugIn_ViewPort& VPoint,
3470 wxRegion* pValidRegion) {}
3472void PlugInChartBase::SetColorScheme(
int cs,
bool bApplyImmediate) {}
3474double PlugInChartBase::GetNearestPreferredScalePPM(
double target_scale_ppm) {
3478wxBitmap* PlugInChartBase::GetThumbnail(
int tnx,
int tny,
int cs) {
3482void PlugInChartBase::ComputeSourceRectangle(
const PlugIn_ViewPort& vp,
3483 wxRect* pSourceRect) {}
3485double PlugInChartBase::GetRasterScaleFactor() {
return 1.0; }
3487bool PlugInChartBase::GetChartBits(wxRect& source,
unsigned char* pPix,
3492int PlugInChartBase::GetSize_X() {
return 1; }
3494int PlugInChartBase::GetSize_Y() {
return 1; }
3496void PlugInChartBase::latlong_to_chartpix(
double lat,
double lon,
double& pixx,
3499void PlugInChartBase::chartpix_to_latlong(
double pixx,
double pixy,
3500 double* plat,
double* plon) {}
3507PlugInChartBaseGL::PlugInChartBaseGL() {}
3509PlugInChartBaseGL::~PlugInChartBaseGL() {}
3511int PlugInChartBaseGL::RenderRegionViewOnGL(
const wxGLContext& glc,
3513 const wxRegion& Region,
3514 bool b_use_stencil) {
3518ListOfPI_S57Obj* PlugInChartBaseGL::GetObjRuleListAtLatLon(
3523wxString PlugInChartBaseGL::CreateObjDescriptions(ListOfPI_S57Obj* obj_list) {
3527int PlugInChartBaseGL::GetNoCOVREntries() {
return 0; }
3529int PlugInChartBaseGL::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3531int PlugInChartBaseGL::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3533float* PlugInChartBaseGL::GetNoCOVRTableHead(
int iTable) {
return 0; }
3540PlugInChartBaseExtended::PlugInChartBaseExtended() {}
3542PlugInChartBaseExtended::~PlugInChartBaseExtended() {}
3544int PlugInChartBaseExtended::RenderRegionViewOnGL(
const wxGLContext& glc,
3546 const wxRegion& Region,
3547 bool b_use_stencil) {
3551int PlugInChartBaseExtended::RenderRegionViewOnGLNoText(
3553 const wxRegion& Region,
bool b_use_stencil) {
3557int PlugInChartBaseExtended::RenderRegionViewOnGLTextOnly(
3559 const wxRegion& Region,
bool b_use_stencil) {
3563wxBitmap& PlugInChartBaseExtended::RenderRegionViewOnDCNoText(
3565 return wxNullBitmap;
3568bool PlugInChartBaseExtended::RenderRegionViewOnDCTextOnly(
3569 wxMemoryDC& dc,
const PlugIn_ViewPort& VPoint,
const wxRegion& Region) {
3573ListOfPI_S57Obj* PlugInChartBaseExtended::GetObjRuleListAtLatLon(
3578wxString PlugInChartBaseExtended::CreateObjDescriptions(
3579 ListOfPI_S57Obj* obj_list) {
3583int PlugInChartBaseExtended::GetNoCOVREntries() {
return 0; }
3585int PlugInChartBaseExtended::GetNoCOVRTablePoints(
int iTable) {
return 0; }
3587int PlugInChartBaseExtended::GetNoCOVRTablenPoints(
int iTable) {
return 0; }
3589float* PlugInChartBaseExtended::GetNoCOVRTableHead(
int iTable) {
return 0; }
3591void PlugInChartBaseExtended::ClearPLIBTextList() {}
3598PlugInChartBaseExtendedPlus2::PlugInChartBaseExtendedPlus2() {}
3600PlugInChartBaseExtendedPlus2::~PlugInChartBaseExtendedPlus2() {}
3603PlugInChartBaseExtendedPlus2::GetLightsObjRuleListVisibleAtLatLon(
3613PlugInChartBaseGLPlus2::PlugInChartBaseGLPlus2() {}
3615PlugInChartBaseGLPlus2::~PlugInChartBaseGLPlus2() {}
3617ListOfPI_S57Obj* PlugInChartBaseGLPlus2::GetLightsObjRuleListVisibleAtLatLon(
3627ChartPlugInWrapper::ChartPlugInWrapper() {}
3629ChartPlugInWrapper::ChartPlugInWrapper(
const wxString& chart_class) {
3630 m_ppo = ::wxCreateDynamicObject(chart_class);
3634ChartPlugInWrapper::~ChartPlugInWrapper() {
3635 if (m_ppicb)
delete m_ppicb;
3638wxString ChartPlugInWrapper::GetFileSearchMask(
void) {
3640 return m_ppicb->GetFileSearchMask();
3645InitReturn ChartPlugInWrapper::Init(
const wxString& name,
3646 ChartInitFlag init_flags) {
3648 wxWindow* pa = wxWindow::FindFocus();
3650 InitReturn ret_val = (InitReturn)m_ppicb->Init(name, (
int)init_flags);
3654 if (ret_val == INIT_OK) {
3655 m_FullPath = m_ppicb->GetFullPath();
3656 m_ChartType = (ChartTypeEnum)m_ppicb->GetChartType();
3657 m_ChartFamily = (ChartFamilyEnum)m_ppicb->GetChartFamily();
3658 m_projection = (OcpnProjType)m_ppicb->GetChartProjection();
3659 m_EdDate = m_ppicb->GetEditionDate();
3660 m_Name = m_ppicb->GetName();
3661 m_ID = m_ppicb->GetID();
3662 m_DepthUnits = m_ppicb->GetDepthUnits();
3663 m_SoundingsDatum = m_ppicb->GetSoundingsDatum();
3664 m_datum_str = m_ppicb->GetDatumString();
3665 m_SE = m_ppicb->GetSE();
3666 m_EdDate = m_ppicb->GetEditionDate();
3667 m_ExtraInfo = m_ppicb->GetExtraInfo();
3668 Chart_Error_Factor = m_ppicb->GetChartErrorFactor();
3669 m_depth_unit_id = (ChartDepthUnitType)m_ppicb->GetDepthUnitId();
3670 m_Chart_Skew = m_ppicb->GetChartSkew();
3671 m_Chart_Scale = m_ppicb->GetNativeScale();
3676 m_ppm_avg = 10000. / m_ppicb->GetNativeScale();
3679 if ((fabs(m_Chart_Skew) < .01) &&
3680 (CHART_FAMILY_RASTER == m_ChartFamily)) {
3682 if (GetChartExtent(&extent)) {
3683 double lon_range = extent.ELON - extent.WLON;
3684 if ((lon_range > 0) &&
3686 m_ppm_avg = GetSize_X() / (lon_range * 1852 * 60);
3690 m_overlayENC =
false;
3691 if (m_ChartFamily == (ChartFamilyEnum)PI_CHART_FAMILY_VECTOR) {
3692 wxCharBuffer buf = m_FullPath.ToUTF8();
3693 m_overlayENC = s57chart::IsCellOverlayType(buf.data());
3696 bReadyToRender = m_ppicb->IsReadyToRender();
3699 m_ChartType = CHART_TYPE_UNKNOWN;
3700 m_ChartFamily = CHART_FAMILY_UNKNOWN;
3706 if (pc) pc->SetFocus();
3710 return INIT_FAIL_REMOVE;
3714int ChartPlugInWrapper::GetCOVREntries() {
3716 return m_ppicb->GetCOVREntries();
3721int ChartPlugInWrapper::GetCOVRTablePoints(
int iTable) {
3723 return m_ppicb->GetCOVRTablePoints(iTable);
3728int ChartPlugInWrapper::GetCOVRTablenPoints(
int iTable) {
3730 return m_ppicb->GetCOVRTablenPoints(iTable);
3735float* ChartPlugInWrapper::GetCOVRTableHead(
int iTable) {
3737 return m_ppicb->GetCOVRTableHead(iTable);
3747int ChartPlugInWrapper::GetNoCOVREntries() {
3751 return ppicbgl->GetNoCOVREntries();
3757int ChartPlugInWrapper::GetNoCOVRTablePoints(
int iTable) {
3761 return ppicbgl->GetNoCOVRTablePoints(iTable);
3767int ChartPlugInWrapper::GetNoCOVRTablenPoints(
int iTable) {
3771 return ppicbgl->GetNoCOVRTablenPoints(iTable);
3777float* ChartPlugInWrapper::GetNoCOVRTableHead(
int iTable) {
3781 return ppicbgl->GetNoCOVRTableHead(iTable);
3787bool ChartPlugInWrapper::GetChartExtent(
Extent* pext) {
3790 if (m_ppicb->GetChartExtent(&xpi)) {
3791 pext->NLAT = xpi.NLAT;
3792 pext->SLAT = xpi.SLAT;
3793 pext->ELON = xpi.ELON;
3794 pext->WLON = xpi.WLON;
3803ThumbData* ChartPlugInWrapper::GetThumbData(
int tnx,
int tny,
float lat,
3808 if (!pThumbData->pDIBThumb) {
3809 wxBitmap* pBMPOwnedByChart =
3810 m_ppicb->GetThumbnail(tnx, tny, m_global_color_scheme);
3811 if (pBMPOwnedByChart) {
3812 wxImage img = pBMPOwnedByChart->ConvertToImage();
3813 pThumbData->pDIBThumb =
new wxBitmap(img);
3815 pThumbData->pDIBThumb = NULL;
3818 pThumbData->Thumb_Size_X = tnx;
3819 pThumbData->Thumb_Size_Y = tny;
3846 pThumbData->ShipX = 0;
3847 pThumbData->ShipY = 0;
3854ThumbData* ChartPlugInWrapper::GetThumbData() {
return pThumbData; }
3856bool ChartPlugInWrapper::UpdateThumbData(
double lat,
double lon) {
3860double ChartPlugInWrapper::GetNormalScaleMin(
double canvas_scale_factor,
3861 bool b_allow_overzoom) {
3863 return m_ppicb->GetNormalScaleMin(canvas_scale_factor, b_allow_overzoom);
3868double ChartPlugInWrapper::GetNormalScaleMax(
double canvas_scale_factor,
3871 return m_ppicb->GetNormalScaleMax(canvas_scale_factor, canvas_width);
3890void RenderRotateToViewPort(
const ViewPort& VPoint) {
3891#ifndef USE_ANDROID_GLES2
3893 glTranslatef(xt, yt, 0);
3894 glRotatef(VPoint.
rotation * 180. / PI, 0, 0, 1);
3895 glTranslatef(-xt, -yt, 0);
3899void UndoRenderRotateToViewPort(
const ViewPort& VPoint) {
3900#ifndef USE_ANDROID_GLES2
3902 glTranslatef(xt, yt, 0);
3903 glRotatef(-VPoint.
rotation * 180. / PI, 0, 0, 1);
3904 glTranslatef(-xt, -yt, 0);
3908bool ChartPlugInWrapper::RenderRegionViewOnGL(
const wxGLContext& glc,
3911 const LLRegion& Region) {
3920 if (!Region.Empty() && (ppicb_gl || ppicb_x)) {
3921 wxRegion* r = RectRegion.GetNew_wxRegion();
3924 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
3925 chart_region.Intersect(Region);
3927 if (!chart_region.Empty()) {
3928 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
3930 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
3934#ifndef USE_ANDROID_GLES2
3937 RenderRotateToViewPort(VPoint);
3941 ppicb_x->RenderRegionViewOnGL(glc, pivp, *r,
3942 glChartCanvas::s_b_useStencil);
3944 ppicb_gl->RenderRegionViewOnGL(glc, pivp, *r,
3945 glChartCanvas::s_b_useStencil);
3946 UndoRenderRotateToViewPort(VPoint);
3948#ifndef USE_ANDROID_GLES2
3951 glChartCanvas::DisableClipRegion();
3965bool ChartPlugInWrapper::RenderRegionViewOnGLNoText(
3966 const wxGLContext& glc,
const ViewPort& VPoint,
3967 const OCPNRegion& RectRegion,
const LLRegion& Region) {
3976 if (!Region.Empty() && ppicb_x) {
3978 glChartCanvas::SetClipRect(VPoint, VPoint.rv_rect,
false);
3979 glChartCanvas::DisableClipRegion();
3982 RenderRotateToViewPort(VPoint);
3985 wxRegion* r = RectRegion.GetNew_wxRegion();
3987 ppicb_x->RenderRegionViewOnGLNoText(glc, pivp, *r,
3988 glChartCanvas::s_b_useStencil);
3991 UndoRenderRotateToViewPort(VPoint);
3996 else if (!Region.Empty() &&
4000 wxRegion* r = RectRegion.GetNew_wxRegion();
4003 LLRegion chart_region = vp.GetLLRegion(upd.GetRect());
4004 chart_region.Intersect(Region);
4006 if (!chart_region.Empty()) {
4007 ViewPort cvp = glChartCanvas::ClippedViewport(VPoint, chart_region);
4009 glChartCanvas::SetClipRect(cvp, upd.GetRect(),
false);
4011 RenderRotateToViewPort(VPoint);
4014 ppicb->RenderRegionViewOnGL(glc, pivp, *r,
4015 glChartCanvas::s_b_useStencil);
4018 UndoRenderRotateToViewPort(VPoint);
4020 glChartCanvas::DisableClipRegion();
4033bool ChartPlugInWrapper::RenderRegionViewOnGLTextOnly(
4040 if (!Region.Empty() && ppicb_x) {
4041 wxRegion* r = Region.GetNew_wxRegion();
4043#ifndef USE_ANDROID_GLES2
4046 RenderRotateToViewPort(VPoint);
4049 ppicb_x->RenderRegionViewOnGLTextOnly(glc, pivp, *r,
4050 glChartCanvas::s_b_useStencil);
4051 UndoRenderRotateToViewPort(VPoint);
4053#ifndef USE_ANDROID_GLES2
4066bool ChartPlugInWrapper::RenderRegionViewOnDC(wxMemoryDC& dc,
4072 if (Region.IsOk()) {
4073 wxRegion* r = Region.GetNew_wxRegion();
4075 dc.SelectObject(m_ppicb->RenderRegionView(pivp, *r));
4077 wxBitmap& obmp = m_ppicb->RenderRegionView(pivp, *r);
4080 wxColour nodat = GetGlobalColor(_T (
"NODTA" ));
4081 wxColour nodat_sub = nodat;
4083#ifdef ocpnUSE_ocpnBitmap
4084 nodat_sub = wxColour(nodat.Blue(), nodat.Green(), nodat.Red());
4086 m_pMask =
new wxMask(obmp, nodat_sub);
4087 obmp.SetMask(m_pMask);
4089 dc.SelectObject(obmp);
4100bool ChartPlugInWrapper::RenderRegionViewOnDCNoText(wxMemoryDC& dc,
4111 if (Region.IsOk() && (pCBx || ppicb)) {
4112 wxRegion* r = Region.GetNew_wxRegion();
4115 dc.SelectObject(pCBx->RenderRegionViewOnDCNoText(pivp, *r));
4117 dc.SelectObject(ppicb->RenderRegionView(pivp, *r));
4127bool ChartPlugInWrapper::RenderRegionViewOnDCTextOnly(
4130 bool ret_val =
false;
4133 if (Region.IsOk()) {
4134 wxRegion* r = Region.GetNew_wxRegion();
4138 if (pCBx) ret_val = pCBx->RenderRegionViewOnDCTextOnly(dc, pivp, *r);
4148void ChartPlugInWrapper::ClearPLIBTextList() {
4152 if (pCBx) pCBx->ClearPLIBTextList();
4156bool ChartPlugInWrapper::AdjustVP(
ViewPort& vp_last,
ViewPort& vp_proposed) {
4160 return m_ppicb->AdjustVP(pivp_last, pivp_proposed);
4165void ChartPlugInWrapper::GetValidCanvasRegion(
const ViewPort& VPoint,
4173 m_ppicb->GetValidCanvasRegion(pivp, ®ion);
4180void ChartPlugInWrapper::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
4182 m_ppicb->SetColorScheme(cs, bApplyImmediate);
4184 m_global_color_scheme = cs;
4186 if (pThumbData) pThumbData->pDIBThumb = NULL;
4190 double target_scale_ppm) {
4192 return m_ppicb->GetNearestPreferredScalePPM(target_scale_ppm);
4197void ChartPlugInWrapper::ComputeSourceRectangle(
const ViewPort& VPoint,
4198 wxRect* pSourceRect) {
4201 m_ppicb->ComputeSourceRectangle(pivp, pSourceRect);
4205double ChartPlugInWrapper::GetRasterScaleFactor(
const ViewPort& vp) {
4207 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
4212bool ChartPlugInWrapper::GetChartBits(wxRect& source,
unsigned char* pPix,
4214 wxCriticalSectionLocker locker(m_critSect);
4218 return m_ppicb->GetChartBits(source, pPix, sub_samp);
4223int ChartPlugInWrapper::GetSize_X() {
4225 return m_ppicb->GetSize_X();
4230int ChartPlugInWrapper::GetSize_Y() {
4232 return m_ppicb->GetSize_Y();
4237void ChartPlugInWrapper::latlong_to_chartpix(
double lat,
double lon,
4238 double& pixx,
double& pixy) {
4239 if (m_ppicb) m_ppicb->latlong_to_chartpix(lat, lon, pixx, pixy);
4242void ChartPlugInWrapper::chartpix_to_latlong(
double pixx,
double pixy,
4243 double* plat,
double* plon) {
4244 if (m_ppicb) m_ppicb->chartpix_to_latlong(pixx, pixy, plat, plon);
4257wxString toSDMM_PlugIn(
int NEflag,
double a,
bool hi_precision) {
4258 return toSDMM(NEflag, a, hi_precision);
4261wxColour GetBaseGlobalColor(wxString colorName) {
4262 return GetGlobalColor(colorName);
4265int OCPNMessageBox_PlugIn(wxWindow* parent,
const wxString& message,
4266 const wxString& caption,
int style,
int x,
int y) {
4267 return OCPNMessageBox(parent, message, caption, style, 100, x, y);
4270wxString GetOCPN_ExePath(
void) {
return g_Platform->GetExePath(); }
4272wxString* GetpPlugInLocation() {
return g_Platform->GetPluginDirPtr(); }
4274wxString GetWritableDocumentsDir(
void) {
4275 return g_Platform->GetWritableDocumentsDir();
4280 auto loader = PluginLoader::getInstance();
4281 for (
unsigned int i = 0; i < loader->GetPlugInArray()->GetCount(); i++) {
4283 if (pic->m_pplugin == pplugin) {
4293ListOfPI_S57Obj* PlugInManager::GetPlugInObjRuleListAtLatLon(
4296 ListOfPI_S57Obj* list = NULL;
4302 list = picbgl->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4310 list = picbx->GetObjRuleListAtLatLon(zlat, zlon, SelectRadius, &pi_vp);
4320 ListOfPI_S57Obj* rule_list) {
4326 ret_str = picbgl->CreateObjDescriptions(rule_list);
4331 ret_str = picbx->CreateObjDescriptions(rule_list);
4339wxString PI_GetPLIBColorScheme() {
4343int PI_GetPLIBDepthUnitInt() {
4345 return ps52plib->m_nDepthUnitDisplay;
4350int PI_GetPLIBSymbolStyle() {
4352 return ps52plib->m_nSymbolStyle;
4357int PI_GetPLIBBoundaryStyle() {
4359 return ps52plib->m_nBoundaryStyle;
4369 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4371 ViewPort cvp = CreateCompatibleViewport(*vp);
4376 ObjRazRules rzRules;
4377 rzRules.obj = &cobj;
4378 rzRules.LUP = pContext->LUP;
4379 rzRules.sm_transform_parms = 0;
4380 rzRules.child = NULL;
4381 rzRules.next = NULL;
4383 if (pContext->LUP) {
4384 ps52plib->SetVPointCompat(
4385 cvp.pix_width, cvp.pix_height, cvp.view_scale_ppm, cvp.rotation,
4386 cvp.clat, cvp.clon, cvp.chart_scale, cvp.rv_rect, cvp.GetBBox(),
4387 cvp.ref_scale, GetOCPNCanvasWindow()->GetContentScaleFactor());
4388 ps52plib->PrepareForRender();
4390 return ps52plib->ObjectRenderCheck(&rzRules);
4397int PI_GetPLIBStateHash() {
4399 return ps52plib->GetStateHash();
4404void CreateCompatibleS57Object(
PI_S57Obj* pObj, S57Obj* cobj,
4405 chart_context* pctx) {
4406 strncpy(cobj->FeatureName, pObj->FeatureName, 8);
4407 cobj->Primitive_type = (GeoPrim_t)pObj->Primitive_type;
4408 cobj->att_array = pObj->att_array;
4409 cobj->attVal = pObj->attVal;
4410 cobj->n_attr = pObj->n_attr;
4415 cobj->npt = pObj->npt;
4417 cobj->iOBJL = pObj->iOBJL;
4418 cobj->Index = pObj->Index;
4420 cobj->geoPt = (pt*)pObj->geoPt;
4421 cobj->geoPtz = pObj->geoPtz;
4422 cobj->geoPtMulti = pObj->geoPtMulti;
4424 cobj->m_lat = pObj->m_lat;
4425 cobj->m_lon = pObj->m_lon;
4427 cobj->m_DisplayCat = (DisCat)pObj->m_DisplayCat;
4428 cobj->x_rate = pObj->x_rate;
4429 cobj->y_rate = pObj->y_rate;
4430 cobj->x_origin = pObj->x_origin;
4431 cobj->y_origin = pObj->y_origin;
4433 cobj->Scamin = pObj->Scamin;
4434 cobj->nRef = pObj->nRef;
4435 cobj->bIsAton = pObj->bIsAton;
4436 cobj->bIsAssociable = pObj->bIsAssociable;
4438 cobj->m_n_lsindex = pObj->m_n_lsindex;
4439 cobj->m_lsindex_array = pObj->m_lsindex_array;
4440 cobj->m_n_edge_max_points = pObj->m_n_edge_max_points;
4442 if (gs_plib_flags & PLIB_CAPS_OBJSEGLIST) {
4443 cobj->m_ls_list_legacy =
4447 cobj->m_ls_list_legacy = 0;
4448 cobj->m_ls_list = 0;
4450 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE)
4451 cobj->m_bcategory_mutable = pObj->m_bcategory_mutable;
4453 cobj->m_bcategory_mutable =
true;
4456 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE) {
4457 if (pObj->m_DPRI == -1) {
4459 if (pCtx->LUP) cobj->m_DPRI = pCtx->LUP->DPRI -
'0';
4461 cobj->m_DPRI = pObj->m_DPRI;
4464 cobj->pPolyTessGeo = (PolyTessGeo*)pObj->pPolyTessGeo;
4465 cobj->m_chart_context = (chart_context*)pObj->m_chart_context;
4467 if (pObj->auxParm3 != 1234) {
4468 pObj->auxParm3 = 1234;
4469 pObj->auxParm0 = -99;
4472 cobj->auxParm0 = pObj->auxParm0;
4479 if (pContext->bBBObj_valid)
4481 cobj->BBObj.Set(pContext->BBObj.GetMinY(), pContext->BBObj.GetMinX(),
4482 pContext->BBObj.GetMaxY(), pContext->BBObj.GetMaxX());
4484 cobj->CSrules = pContext->CSrules;
4485 cobj->bCS_Added = pContext->bCS_Added;
4487 cobj->FText = pContext->FText;
4488 cobj->bFText_Added = pContext->bFText_Added;
4489 cobj->rText = pContext->rText;
4491 cobj->bIsClone =
true;
4494 cobj->m_chart_context = pctx;
4495 chart_context* ppctx = (chart_context*)pObj->m_chart_context;
4498 cobj->m_chart_context->m_pvc_hash = ppctx->m_pvc_hash;
4499 cobj->m_chart_context->m_pve_hash = ppctx->m_pve_hash;
4500 cobj->m_chart_context->ref_lat = ppctx->ref_lat;
4501 cobj->m_chart_context->ref_lon = ppctx->ref_lon;
4502 cobj->m_chart_context->pFloatingATONArray = ppctx->pFloatingATONArray;
4503 cobj->m_chart_context->pRigidATONArray = ppctx->pRigidATONArray;
4504 cobj->m_chart_context->safety_contour = ppctx->safety_contour;
4505 cobj->m_chart_context->vertex_buffer = ppctx->vertex_buffer;
4507 cobj->m_chart_context->chart =
4509 cobj->m_chart_context->chart_type = S52_CHART_TYPE_PLUGIN;
4513bool PI_PLIBSetContext(
PI_S57Obj* pObj) {
4515 if (!pObj->S52_Context) {
4517 pObj->S52_Context = ctx;
4523 CreateCompatibleS57Object(pObj, &cobj, NULL);
4525 LUPname LUP_Name = PAPER_CHART;
4528 ctx->CSrules = NULL;
4529 ctx->bCS_Added =
false;
4532 if (ctx->bFText_Added) {
4533 ctx->bFText_Added =
false;
4539 ctx->bBBObj_valid =
true;
4540 ctx->BBObj.SetMin(pObj->lon_min, pObj->lat_min);
4541 ctx->BBObj.SetMax(pObj->lon_max, pObj->lat_max);
4544 switch (cobj.Primitive_type) {
4549 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
4550 LUP_Name = PAPER_CHART;
4552 LUP_Name = SIMPLIFIED;
4561 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
4562 LUP_Name = PLAIN_BOUNDARIES;
4564 LUP_Name = SYMBOLIZED_BOUNDARIES;
4569 LUPrec* lup = ps52plib->S52_LUPLookup(LUP_Name, cobj.FeatureName, &cobj);
4573 ps52plib->_LUP2rules(lup, &cobj);
4575 ctx->MPSRulesList = NULL;
4583 pContext->bBBObj_valid =
true;
4584 pContext->BBObj.SetMin(pObj->lon_min, pObj->lat_min);
4585 pContext->BBObj.SetMax(pObj->lon_max, pObj->lat_max);
4589void UpdatePIObjectPlibContext(
PI_S57Obj* pObj, S57Obj* cobj,
4590 ObjRazRules* rzRules) {
4594 pContext->CSrules = cobj->CSrules;
4595 pContext->bCS_Added = cobj->bCS_Added;
4597 pContext->FText = cobj->FText;
4598 pContext->bFText_Added = cobj->bFText_Added;
4599 pContext->rText = cobj->rText;
4601 if (cobj->BBObj.GetValid()) {
4604 BoundingBox(cobj->BBObj.GetMinLon(), cobj->BBObj.GetMinLat(),
4605 cobj->BBObj.GetMaxLon(), cobj->BBObj.GetMaxLat());
4606 pContext->bBBObj_valid =
true;
4611 pObj->m_DisplayCat = (PI_DisCat)cobj->m_DisplayCat;
4613 if (gs_plib_flags & PLIB_CAPS_OBJCATMUTATE) pObj->m_DPRI = cobj->m_DPRI;
4615 pContext->ChildRazRules = rzRules->child;
4616 pContext->MPSRulesList = rzRules->mps;
4618 pObj->auxParm0 = cobj->auxParm0;
4621bool PI_GetObjectRenderBox(
PI_S57Obj* pObj,
double* lat_min,
double* lat_max,
4622 double* lon_min,
double* lon_max) {
4625 if (lat_min) *lat_min = pContext->BBObj.GetMinY();
4626 if (lat_max) *lat_max = pContext->BBObj.GetMaxY();
4627 if (lon_min) *lon_min = pContext->BBObj.GetMinX();
4628 if (lon_max) *lon_max = pContext->BBObj.GetMaxX();
4629 return pContext->bBBObj_valid;
4634PI_LUPname PI_GetObjectLUPName(
PI_S57Obj* pObj) {
4637 LUPrec* lup = pContext->LUP;
4638 if (lup)
return (PI_LUPname)(lup->TNAM);
4640 return (PI_LUPname)(-1);
4643PI_DisPrio PI_GetObjectDisplayPriority(
PI_S57Obj* pObj) {
4646 LUPrec* lup = pContext->LUP;
4647 if (lup)
return (PI_DisPrio)(lup->DPRI);
4650 return (PI_DisPrio)(-1);
4653PI_DisCat PI_GetObjectDisplayCategory(
PI_S57Obj* pObj) {
4656 LUPrec* lup = pContext->LUP;
4657 if (lup)
return (PI_DisCat)(lup->DISC);
4659 return (PI_DisCat)(-1);
4661double PI_GetPLIBMarinerSafetyContour() {
4662 return S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
4665void PI_PLIBSetLineFeaturePriority(
PI_S57Obj* pObj,
int prio) {
4669 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4674 ObjRazRules rzRules;
4675 rzRules.obj = &cobj;
4676 rzRules.LUP = pContext->LUP;
4677 rzRules.sm_transform_parms = 0;
4678 rzRules.child = NULL;
4679 rzRules.next = NULL;
4680 rzRules.mps = pContext->MPSRulesList;
4682 if (pContext->LUP) {
4683 ps52plib->SetLineFeaturePriority(&rzRules, prio);
4686 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4690void PI_PLIBPrepareForNewRender(
void) {
4692 ps52plib->PrepareForRender();
4693 ps52plib->ClearTextList();
4695 if (gs_plib_flags & PLIB_CAPS_LINE_BUFFER)
4696 ps52plib->EnableGLLS(
true);
4698 ps52plib->EnableGLLS(
false);
4702void PI_PLIBSetRenderCaps(
unsigned int flags) { gs_plib_flags = flags; }
4704void PI_PLIBFreeContext(
void* pContext) {
4707 if (pctx->ChildRazRules) {
4708 ObjRazRules* ctop = pctx->ChildRazRules;
4712 if (ps52plib) ps52plib->DestroyLUP(ctop->LUP);
4714 ObjRazRules* cnxx = ctop->next;
4720 if (pctx->MPSRulesList) {
4721 if (ps52plib && pctx->MPSRulesList->cs_rules) {
4722 for (
unsigned int i = 0; i < pctx->MPSRulesList->cs_rules->GetCount();
4724 Rules* top = pctx->MPSRulesList->cs_rules->Item(i);
4725 ps52plib->DestroyRulesChain(top);
4727 delete pctx->MPSRulesList->cs_rules;
4729 free(pctx->MPSRulesList);
4741 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4747 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
4748 &transform.easting_vp_center, &transform.northing_vp_center);
4751 ObjRazRules rzRules;
4752 rzRules.obj = &cobj;
4753 rzRules.LUP = pContext->LUP;
4754 rzRules.sm_transform_parms = &transform;
4755 rzRules.child = pContext->ChildRazRules;
4756 rzRules.next = NULL;
4757 rzRules.mps = pContext->MPSRulesList;
4759 if (pContext->LUP) {
4760 ViewPort cvp = CreateCompatibleViewport(*vp);
4766 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4767 GetOCPNCanvasWindow()->GetContentScaleFactor());
4768 ps52plib->PrepareForRender();
4770 ps52plib->RenderObjectToDC(pdc, &rzRules);
4773 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4780 wxRect rect,
unsigned char* pixbuf) {
4782 render_canvas_parms pb_spec;
4784 pb_spec.depth = BPP;
4785 pb_spec.pb_pitch = ((rect.width * pb_spec.depth / 8));
4786 pb_spec.lclip = rect.x;
4787 pb_spec.rclip = rect.x + rect.width - 1;
4788 pb_spec.pix_buff = pixbuf;
4789 pb_spec.width = rect.width;
4790 pb_spec.height = rect.height;
4793#ifdef ocpnUSE_ocpnBitmap
4794 pb_spec.b_revrgb =
true;
4796 pb_spec.b_revrgb =
false;
4799 pb_spec.b_revrgb =
false;
4804 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4810 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
4811 &transform.easting_vp_center, &transform.northing_vp_center);
4814 ObjRazRules rzRules;
4815 rzRules.obj = &cobj;
4816 rzRules.LUP = pContext->LUP;
4817 rzRules.sm_transform_parms = &transform;
4818 rzRules.child = pContext->ChildRazRules;
4819 rzRules.next = NULL;
4820 rzRules.mps = pContext->MPSRulesList;
4822 ViewPort cvp = CreateCompatibleViewport(*vp);
4826 if (!(gs_plib_flags & PLIB_CAPS_SINGLEGEO_BUFFER)) {
4827 if (!pObj->geoPtMulti) {
4828 PolyTessGeo* tess = (PolyTessGeo*)pObj->pPolyTessGeo;
4830 if (!tess)
return 1;
4832 PolyTriGroup* ptg =
new PolyTriGroup;
4833 ptg->tri_prim_head =
4834 tess->Get_PolyTriGroup_head()->tri_prim_head;
4835 ptg->bsingle_alloc =
false;
4836 ptg->data_type = DATA_TYPE_DOUBLE;
4837 tess->Set_PolyTriGroup_head(ptg);
4839 double* pd = (
double*)malloc(
sizeof(
double));
4840 pObj->geoPtMulti = pd;
4844 if (pContext->LUP) {
4849 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4850 GetOCPNCanvasWindow()->GetContentScaleFactor());
4851 ps52plib->PrepareForRender();
4853 ps52plib->RenderAreaToDC(pdc, &rzRules, &pb_spec);
4856 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4862int PI_PLIBRenderAreaToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4868 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4875 if (!(gs_plib_flags & PLIB_CAPS_SINGLEGEO_BUFFER)) {
4876 if (!pObj->geoPtMulti) {
4877 PolyTessGeo* tess = (PolyTessGeo*)pObj->pPolyTessGeo;
4879 if (!tess)
return 1;
4883 ptg->tri_prim_head = tess->Get_PolyTriGroup_head()->tri_prim_head;
4884 ptg->bsingle_alloc =
false;
4885 ptg->data_type = DATA_TYPE_DOUBLE;
4886 tess->Set_PolyTriGroup_head(ptg);
4890 double* pd = (
double*)malloc(
sizeof(
double));
4891 pObj->geoPtMulti = pd;
4897 if (pObj->auxParm0 < 1)
4906 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
4907 &transform.easting_vp_center, &transform.northing_vp_center);
4910 ObjRazRules rzRules;
4911 rzRules.obj = &cobj;
4912 rzRules.LUP = pContext->LUP;
4913 rzRules.sm_transform_parms = &transform;
4914 rzRules.child = pContext->ChildRazRules;
4915 rzRules.next = NULL;
4916 rzRules.mps = pContext->MPSRulesList;
4918 if (pContext->LUP) {
4919 ViewPort cvp = CreateCompatibleViewport(*vp);
4925 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4926 GetOCPNCanvasWindow()->GetContentScaleFactor());
4927 ps52plib->PrepareForRender();
4929 ps52plib->RenderAreaToGL(glcc, &rzRules);
4932 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4939int PI_PLIBRenderObjectToGL(
const wxGLContext& glcc,
PI_S57Obj* pObj,
4944 CreateCompatibleS57Object(pObj, &cobj, &ctx);
4950 toSM(vp->clat, vp->clon, pObj->chart_ref_lat, pObj->chart_ref_lon,
4951 &transform.easting_vp_center, &transform.northing_vp_center);
4954 ObjRazRules rzRules;
4955 rzRules.obj = &cobj;
4956 rzRules.LUP = pContext->LUP;
4957 rzRules.sm_transform_parms = &transform;
4958 rzRules.child = pContext->ChildRazRules;
4959 rzRules.next = NULL;
4960 rzRules.mps = pContext->MPSRulesList;
4962 if (pContext->LUP) {
4963 ViewPort cvp = CreateCompatibleViewport(*vp);
4969 cvp.rv_rect, cvp.GetBBox(), cvp.
ref_scale,
4970 GetOCPNCanvasWindow()->GetContentScaleFactor());
4971 ps52plib->PrepareForRender();
4973 ps52plib->RenderObjectToGL(glcc, &rzRules);
4976 UpdatePIObjectPlibContext(pObj, &cobj, &rzRules);
4986OCPN_downloadEvent::OCPN_downloadEvent(wxEventType commandType,
int id)
4987 : wxEvent(id, commandType) {
4988 m_stat = OCPN_DL_UNKNOWN;
4989 m_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
4990 m_b_complete =
false;
4994OCPN_downloadEvent::~OCPN_downloadEvent() {}
4996wxEvent* OCPN_downloadEvent::Clone()
const {
4998 newevent->m_stat = this->m_stat;
4999 newevent->m_condition = this->m_condition;
5001 newevent->m_totalBytes = this->m_totalBytes;
5002 newevent->m_sofarBytes = this->m_sofarBytes;
5003 newevent->m_b_complete = this->m_b_complete;
5009DECL_EXP wxEventType wxEVT_DOWNLOAD_EVENT = wxNewEventType();
5011_OCPN_DLStatus g_download_status;
5012_OCPN_DLCondition g_download_condition;
5014#define DL_EVENT_TIMER 4388
5022 void setBackgroundMode(
long ID, wxEvtHandler* handler);
5023 void clearBackgroundMode();
5024 void onTimerEvent(wxTimerEvent& event);
5027 wxTimer m_eventTimer;
5028 wxEvtHandler* m_download_evHandler;
5034PI_DLEvtHandler::PI_DLEvtHandler() {
5035 g_download_status = OCPN_DL_UNKNOWN;
5036 g_download_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
5038 m_download_evHandler = NULL;
5044PI_DLEvtHandler::~PI_DLEvtHandler() {
5045 m_eventTimer.Stop();
5048 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5055 g_download_status =
event.getDLEventStatus();
5056 g_download_condition =
event.getDLEventCondition();
5059 if (m_download_evHandler &&
5060 (OCPN_DL_EVENT_TYPE_END == event.getDLEventCondition())) {
5062 ev.setComplete(
true);
5063 ev.setTransferred(m_sofarBytes);
5064 ev.setTotal(m_totalBytes);
5066 ev.setDLEventStatus(event.getDLEventStatus());
5067 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
5069 m_download_evHandler->AddPendingEvent(ev);
5070 m_eventTimer.Stop();
5072 finishAndroidFileDownload();
5079void PI_DLEvtHandler::setBackgroundMode(
long ID, wxEvtHandler* handler) {
5081 m_download_evHandler = handler;
5083 m_eventTimer.SetOwner(
this, DL_EVENT_TIMER);
5087 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onTimerEvent);
5088 m_eventTimer.Start(1000, wxTIMER_CONTINUOUS);
5091void PI_DLEvtHandler::clearBackgroundMode() {
5092 m_download_evHandler = NULL;
5093 m_eventTimer.Stop();
5096void PI_DLEvtHandler::onTimerEvent(wxTimerEvent& event) {
5102 int stat = queryAndroidFileDownload(m_id, &sstat);
5105 long sofarBytes = 0;
5106 long totalBytes = -1;
5110 qDebug() <<
"Error on queryAndroidFileDownload, ending download";
5111 ev.setComplete(
true);
5112 ev.setTransferred(sofarBytes);
5113 ev.setTotal(totalBytes);
5115 ev.setDLEventStatus(OCPN_DL_FAILED);
5116 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
5118 wxStringTokenizer tk(sstat, _T(
";"));
5119 if (tk.HasMoreTokens()) {
5120 wxString token = tk.GetNextToken();
5121 token.ToLong(&state);
5122 token = tk.GetNextToken();
5123 token.ToLong(&sofarBytes);
5124 token = tk.GetNextToken();
5125 token.ToLong(&totalBytes);
5128 qDebug() << state << sofarBytes << totalBytes;
5130 m_sofarBytes = sofarBytes;
5131 m_totalBytes = totalBytes;
5133 ev.setTransferred(sofarBytes);
5134 ev.setTotal(totalBytes);
5137 qDebug() <<
"Event OCPN_DL_FAILED/OCPN_DL_EVENT_TYPE_END";
5138 ev.setComplete(
true);
5139 ev.setDLEventStatus(OCPN_DL_FAILED);
5140 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
5141 }
else if (state == 8) {
5142 qDebug() <<
"Event OCPN_DL_NO_ERROR/OCPN_DL_EVENT_TYPE_END";
5143 ev.setComplete(
true);
5144 ev.setDLEventStatus(OCPN_DL_NO_ERROR);
5145 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
5147 ev.setComplete(
false);
5148 ev.setDLEventStatus(OCPN_DL_UNKNOWN);
5149 ev.setDLEventCondition(OCPN_DL_EVENT_TYPE_PROGRESS);
5155 if (m_download_evHandler) {
5157 m_download_evHandler->AddPendingEvent(ev);
5161 if (OCPN_DL_EVENT_TYPE_END == ev.getDLEventCondition()) {
5162 m_eventTimer.Stop();
5163 finishAndroidFileDownload();
5172_OCPN_DLStatus OCPN_downloadFile(
const wxString& url,
5173 const wxString& outputFile,
5174 const wxString& title,
const wxString& message,
5175 const wxBitmap& bitmap, wxWindow* parent,
5176 long style,
int timeout_secs) {
5179 wxString msg = _T(
"Downloading file synchronously: ");
5186 int vres = validateAndroidWriteLocation(outputFile);
5188 return OCPN_DL_ABORTED;
5194 g_download_status = OCPN_DL_UNKNOWN;
5195 g_download_condition = OCPN_DL_EVENT_TYPE_UNKNOWN;
5198 g_piEventHandler->Connect(
5199 wxEVT_DOWNLOAD_EVENT,
5200 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5205 wxString fURI = outputFile;
5206 if (!fURI.StartsWith(_T(
"file://"))) {
5207 fURI.Prepend(_T(
"file://"));
5210 int res = startAndroidFileDownload(url, fURI, g_piEventHandler, &dl_ID);
5213 finishAndroidFileDownload();
5214 g_piEventHandler->Disconnect(
5215 wxEVT_DOWNLOAD_EVENT,
5216 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5218 return OCPN_DL_FAILED;
5221 wxDateTime dl_start_time = wxDateTime::Now();
5225 wxTimeSpan dt = wxDateTime::Now() - dl_start_time;
5226 qDebug() <<
"Spin.." << dt.GetSeconds().GetLo();
5228 if (dt.GetSeconds() > timeout_secs) {
5229 qDebug() <<
"USER_TIMOUT";
5230 finishAndroidFileDownload();
5231 g_piEventHandler->Disconnect(
5232 wxEVT_DOWNLOAD_EVENT,
5233 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5235 return (OCPN_DL_USER_TIMEOUT);
5238 if (g_download_condition != OCPN_DL_EVENT_TYPE_UNKNOWN) {
5239 if (OCPN_DL_EVENT_TYPE_END == g_download_condition) {
5240 _OCPN_DLStatus ss = g_download_status;
5241 finishAndroidFileDownload();
5242 g_piEventHandler->Disconnect(
5243 wxEVT_DOWNLOAD_EVENT,
5247 qDebug() <<
"RETURN DL_END" << (int)ss;
5253 int stat = queryAndroidFileDownload(dl_ID, &sstat);
5255 qDebug() <<
"Error on queryAndroidFileDownload";
5256 finishAndroidFileDownload();
5257 g_piEventHandler->Disconnect(
5258 wxEVT_DOWNLOAD_EVENT,
5259 (wxObjectEventFunction)(wxEventFunction)&PI_DLEvtHandler::onDLEvent);
5262 return OCPN_DL_FAILED;
5269#elif defined(OCPN_USE_CURL)
5270 wxFileName tfn = wxFileName::CreateTempFileName(outputFile);
5271 wxFileOutputStream output(tfn.GetFullPath());
5273 wxCurlDownloadDialog ddlg(url, &output, title, message + url, bitmap, parent,
5275 wxCurlDialogReturnFlag ret = ddlg.RunModal();
5278 _OCPN_DLStatus result = OCPN_DL_UNKNOWN;
5281 case wxCDRF_SUCCESS: {
5282 if (wxCopyFile(tfn.GetFullPath(), outputFile))
5283 result = OCPN_DL_NO_ERROR;
5285 result = OCPN_DL_FAILED;
5288 case wxCDRF_FAILED: {
5289 result = OCPN_DL_FAILED;
5292 case wxCDRF_USER_ABORTED: {
5293 result = OCPN_DL_ABORTED;
5300 if (wxFileExists(tfn.GetFullPath())) wxRemoveFile(tfn.GetFullPath());
5304 return OCPN_DL_FAILED;
5309_OCPN_DLStatus OCPN_downloadFileBackground(
const wxString& url,
5310 const wxString& outputFile,
5311 wxEvtHandler* handler,
5314 wxString msg = _T(
"Downloading file asynchronously: ");
5326 int res = startAndroidFileDownload(url, outputFile, NULL ,
5330 finishAndroidFileDownload();
5331 return OCPN_DL_FAILED;
5335 g_piEventHandler->setBackgroundMode(dl_ID, handler);
5337 if (handle) *handle = dl_ID;
5339 return OCPN_DL_STARTED;
5341#elif defined(OCPN_USE_CURL)
5342 if (g_pi_manager->m_pCurlThread)
5345 return OCPN_DL_FAILED;
5346 g_pi_manager->m_pCurlThread =
5347 new wxCurlDownloadThread(g_pi_manager, CurlThreadId);
5348 bool http = (url.StartsWith(wxS(
"http:")) || url.StartsWith(wxS(
"https:")));
5350 if (http && g_pi_manager->m_pCurl &&
5351 dynamic_cast<wxCurlHTTP*
>(g_pi_manager->m_pCurl.get())) {
5355 g_pi_manager->m_pCurl = 0;
5358 bool failed =
false;
5359 if (!g_pi_manager->HandleCurlThreadError(
5360 g_pi_manager->m_pCurlThread->SetURL(url, g_pi_manager->m_pCurl),
5361 g_pi_manager->m_pCurlThread, url))
5364 g_pi_manager->m_pCurl = g_pi_manager->m_pCurlThread->GetCurlSharedPtr();
5365 if (!g_pi_manager->HandleCurlThreadError(
5366 g_pi_manager->m_pCurlThread->SetOutputStream(
5367 new wxFileOutputStream(outputFile)),
5368 g_pi_manager->m_pCurlThread))
5372 g_pi_manager->m_download_evHandler = handler;
5373 g_pi_manager->m_downloadHandle = handle;
5375 wxCurlThreadError err = g_pi_manager->m_pCurlThread->Download();
5376 if (err != wxCTE_NO_ERROR) {
5377 g_pi_manager->HandleCurlThreadError(
5378 err, g_pi_manager->m_pCurlThread);
5379 g_pi_manager->m_pCurlThread->Abort();
5384 if (!failed)
return OCPN_DL_STARTED;
5386 if (g_pi_manager->m_pCurlThread) {
5387 if (g_pi_manager->m_pCurlThread->IsAlive())
5388 g_pi_manager->m_pCurlThread->Abort();
5389 if (g_pi_manager->m_pCurlThread->GetOutputStream())
5390 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5391 wxDELETE(g_pi_manager->m_pCurlThread);
5392 g_pi_manager->m_download_evHandler = NULL;
5393 g_pi_manager->m_downloadHandle = NULL;
5394 return OCPN_DL_STARTED;
5396 g_pi_manager->m_pCurl = 0;
5397 return OCPN_DL_FAILED;
5400 return OCPN_DL_FAILED;
5404void OCPN_cancelDownloadFileBackground(
long handle) {
5408 cancelAndroidFileDownload(handle);
5409 finishAndroidFileDownload();
5410 if (g_piEventHandler) g_piEventHandler->clearBackgroundMode();
5412 if (g_pi_manager->m_pCurlThread) {
5413 g_pi_manager->m_pCurlThread->Abort();
5414 delete (g_pi_manager->m_pCurlThread->GetOutputStream());
5415 wxDELETE(g_pi_manager->m_pCurlThread);
5416 g_pi_manager->m_download_evHandler = NULL;
5417 g_pi_manager->m_downloadHandle = NULL;
5419 g_pi_manager->m_pCurl = 0;
5424_OCPN_DLStatus OCPN_postDataHttp(
const wxString& url,
5425 const wxString& parameters, wxString& result,
5428 wxString lparms = parameters;
5429 wxString postResult = doAndroidPOST(url, lparms, timeout_secs * 1000);
5430 if (postResult.IsSameAs(_T(
"NOK")))
return OCPN_DL_FAILED;
5432 result = postResult;
5433 return OCPN_DL_NO_ERROR;
5435#elif defined(OCPN_USE_CURL)
5437 post.SetOpt(CURLOPT_TIMEOUT, timeout_secs);
5438 size_t res = post.Post(parameters.ToAscii(), parameters.Len(), url);
5441 result = wxString(post.GetResponseBody().c_str(), wxConvUTF8);
5442 return OCPN_DL_NO_ERROR;
5444 result = wxEmptyString;
5446 return OCPN_DL_FAILED;
5449 return OCPN_DL_FAILED;
5453bool OCPN_isOnline() {
5455 return androidCheckOnline();
5458#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5459 if (wxDateTime::GetTimeNow() >
5460 g_pi_manager->m_last_online_chk + ONLINE_CHECK_RETRY) {
5462 get.Head(_T(
"http://yahoo.com/"));
5463 g_pi_manager->m_last_online = get.GetResponseCode() > 0;
5465 g_pi_manager->m_last_online_chk = wxDateTime::GetTimeNow();
5467 return g_pi_manager->m_last_online;
5473#if !defined(__ANDROID__) && defined(OCPN_USE_CURL)
5474void PlugInManager::OnEndPerformCurlDownload(wxCurlEndPerformEvent& ev) {
5476 if (ev.IsSuccessful()) {
5477 event.setDLEventStatus(OCPN_DL_NO_ERROR);
5479 g_pi_manager->m_pCurl = 0;
5480 event.setDLEventStatus(OCPN_DL_FAILED);
5482 event.setDLEventCondition(OCPN_DL_EVENT_TYPE_END);
5483 event.setComplete(
true);
5485 if (m_download_evHandler) {
5486 m_download_evHandler->AddPendingEvent(event);
5487 m_download_evHandler = NULL;
5488 m_downloadHandle = NULL;
5491 if (m_pCurlThread) {
5492 m_pCurlThread->Wait();
5493 if (!m_pCurlThread->IsAborting()) {
5494 delete (m_pCurlThread->GetOutputStream());
5495 wxDELETE(m_pCurlThread);
5500void PlugInManager::OnCurlDownload(wxCurlDownloadEvent& ev) {
5502 event.setDLEventStatus(OCPN_DL_UNKNOWN);
5503 event.setDLEventCondition(OCPN_DL_EVENT_TYPE_PROGRESS);
5504 event.setTotal(ev.GetTotalBytes());
5505 event.setTransferred(ev.GetDownloadedBytes());
5506 event.setComplete(
false);
5508 if (m_download_evHandler) {
5509 m_download_evHandler->AddPendingEvent(event);
5513bool PlugInManager::HandleCurlThreadError(wxCurlThreadError err,
5514 wxCurlBaseThread* p,
5515 const wxString& url) {
5517 case wxCTE_NO_ERROR:
5520 case wxCTE_NO_RESOURCE:
5522 wxS(
"Insufficient resources for correct execution of the program."));
5525 case wxCTE_ALREADY_RUNNING:
5529 case wxCTE_INVALID_PROTOCOL:
5530 wxLogError(wxS(
"The URL '%s' uses an unsupported protocol."),
5534 case wxCTE_NO_VALID_STREAM:
5541 case wxCTE_CURL_ERROR: {
5542 wxString ws = wxS(
"unknown");
5543 if (p->GetCurlSession())
5545 wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
5546 wxLogError(wxS(
"Network error: %s"), ws.c_str());
5551 if (p->IsAlive()) p->Abort();
Plugin catalog management: Build the runtime catalog, handling downloads as required.
EventVar plugin_msg
A JSON message should be sent.
Handle messages for blacklisted plugins.
Modal dialog for plugin catalog settings.
Manages the chart database and provides access to chart data.
Wrapper class for plugin-based charts.
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Find the nearest preferred viewport scale (in pixels/meter) for this chart.
const std::vector< DriverPtr > & GetDrivers() const
Wrapper for configuration variables which lives in a wxBaseConfig object.
const void Notify()
Notify all listeners, no data supplied.
Wrapper for global variable, supports notification events when value changes.
Downloader with progress and final message dialogs.
static std::string MessageKey(const char *type="ALL")
Return key which should be used to listen to given message type.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
void Init(const KeyProvider &kp, std::function< void(ObservedEvt &ev)> action)
Initiate an object yet not listening.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Adds a std::shared<void> element to wxCommandEvent.
Data for a loaded plugin, including dl-loaded library.
Basic data for a loaded plugin, trivially copyable.
wxString m_plugin_filename
The short file path.
wxString m_plugin_file
The full file path.
int m_cap_flag
PlugIn Capabilities descriptor.
wxString m_common_name
A common name string for the plugin.
void HandleN0183(std::shared_ptr< const Nmea0183Msg > n0183_msg)
Process incoming NMEA 0183 messages from the message bus.
void HandleSignalK(std::shared_ptr< const SignalkMsg > sK_msg)
Process incoming SignalK messages from the message bus.
const std::vector< PluginMetadata > getInstalled()
Return list of all installed and loaded plugins.
static std::string ImportedMetadataPath(std::string name)
Return path to imported metadata for given plugin.
std::vector< std::string > GetInstalldataPlugins()
Return list of installed plugins lower case names, not necessarily loaded.
static std::string fileListPath(std::string name)
Return path to installation manifest for given plugin.
static std::string versionPath(std::string name)
Return path to file containing version for given plugin.
bool uninstall(const std::string plugin)
Uninstall an installed and loaded plugin.
bool ClearInstallData(const std::string plugin_name)
Remove installation data for not loaded plugin.
void SetInstalledMetadata(const PluginMetadata &pm)
Set metadata for an installed plugin.
static bool isCompatible(const PluginMetadata &metadata, const char *os=PKG_TARGET, const char *os_version=PKG_TARGET_VERSION)
Return true if given plugin is loadable on given os/version.
void ReloadPluginPanels()
Complete reload from plugins array.
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
static std::string GetPluginVersion(const PlugInData pd, std::function< const PluginMetadata(const std::string &)> get_metadata)
Return version string for a plugin, possibly with an "Imported" suffix.
void SortPlugins(int(*cmp_func)(PlugInContainer **, PlugInContainer **))
Sort GetPluginArray().
static void UpdatePlugin(PlugInContainer *plugin, const PluginMetadata &md)
Update PlugInContainer status using data from PluginMetadata and manifest.
void SetEnabled(const wxString &common_name, bool enabled)
Update enabled/disabled state for plugin with given name.
static PluginMetadata MetadataByName(const std::string &name)
Find metadata for given plugin.
void ShowPreferencesDialog(const PlugInData &pd, wxWindow *parent)
Display the preferences dialog for a plugin.
PluginPanel(wxPanel *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, const PlugInData plugin)
An entry in the list of plugins presented by Options | Plugins.
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
A parsed SignalK message over ipv4.
Modal dialog, displays available updates (possibly just one) and lets user select and eventually conf...
Represents the view port for chart display in OpenCPN.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
double ref_scale
The nominal scale of the "reference chart" for this view.
int pix_height
Height of the viewport in physical pixels.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Device context class that can use either wxDC or OpenGL for drawing.
virtual bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex, int priority)
Render plugin overlay over chart canvas in OpenGL mode.
virtual bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvas_ix, int priority)
Render plugin overlay over chart canvas in non-OpenGL mode.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
The JSON document writer.
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
DriverPtr & FindDriver(const std::vector< DriverPtr > &drivers, const std::string &iface, const NavAddr::Bus _bus)
Search list of drivers for a driver with given interface string.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
Enhanced logging interface on top of wx/log.h.
std::string lookup_tarball(const char *uri)
Get path to tarball in cache for given filename.
bool store_metadata(const char *path)
Store metadata in metadata cache, return success/fail.
bool store_tarball(const char *path, const char *basename)
Store a tarball in tarball cache, return success/fail.
#define INSTALLS_PLUGIN_CHART
Plugin provides new chart type for standard (non-GL) view.
#define INSTALLS_CONTEXTMENU_ITEMS
Plugin will add items to chart context menu.
#define WANTS_LATE_INIT
Delay full plugin initialization until system is ready.
#define INSTALLS_TOOLBOX_PAGE
Plugin will add pages to the toolbox/settings dialog.
#define USES_AUI_MANAGER
Plugin uses wxAuiManager for window management.
#define INSTALLS_PLUGIN_CHART_GL
Plugin provides new chart type for OpenGL view.
#define WANTS_ONPAINT_VIEWPORT
Receive callbacks during chart viewport painting.
#define WANTS_PREFERENCES
Plugin will add page(s) to global preferences dialog.
#define WANTS_OVERLAY_CALLBACK
Receive callbacks to render custom overlay graphics on the chart.
void SendNMEASentenceToAllPlugIns(const wxString &sentence)
Distribute a NMEA 0183 sentence to all plugins that have registered interest by setting the WANTS_NME...
Tools to send data to plugins.
Versions uses a modified semantic versioning scheme: major.minor.revision.post-tag+build.
static SemanticVersion parse(std::string s)
Parse a version string, sets major == -1 on errors.