26#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
38#include <wx/wfstream.h>
41#include <unordered_map>
47enum { SAILDOCS, ZYGRIB };
48enum { GFS, COAMPS, RTOFS, HRRR, ICON, ECMWF };
50wxString toMailFormat(
int NEflag,
53 char c = NEflag == 1 ? a < 0 ?
'S' :
'N' : a < 0 ?
'W' :
'E';
55 s.Printf(
"%01d%c", abs(a), c);
70 m_boundingBoxCanvasIndex = -1;
73#if defined(__WXOSX__) || defined(__WXGTK3__)
75 m_displayScale = wxWindow::GetContentScaleFactor();
80 m_downloading =
false;
81 m_bTransferSuccess =
true;
84 auto bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)
85 .GetAsString(wxC2S_HTML_SYNTAX);
86 auto fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)
87 .GetAsString(wxC2S_HTML_SYNTAX);
88 m_htmlWinWorld->SetBorders(10);
89 m_htmlWinWorld->SetPage(
90 "<html><body bgcolor="
99 _(
"<h1>OpenCPN ECMWF forecast</h1>"
100 "<p>Free service based on ECMWF Open Data published under the terms of "
101 "Creative Commons CC-4.0-BY license</p>"
102 "<p>The IFS model GRIB files include information about surface "
104 "atmospheric pressure, wind strength, wind direction, wave height and "
105 "direction for the whole world on a 0.25 degree resolution "
107 "step in the first 144 hours and 6 hour step up to 10 days.</p>"
108 "The AIFS model contains data for wind, pressure and temperature on a "
109 "0.25 degree grid with 6 hour step for up to 15 days"
110 "<p>The data is updated twice a day as soon as the 00z and 12z model "
111 "runs finish and the "
112 "results are published by ECMWF, which usually means new forecast data "
113 "is available shortly after 8AM and 8PM UTC.</p>"
114 "<p>The grib downloaded covers the area of the primary chart "
116 "<p>The service is provided on best effort basis and comes with no "
117 "guarantees. The server is hosted by a volunteer and the service is "
118 "provided free of charge and without accepting any liability "
119 "whatsoever for its continuous availability, or for any loss or damage "
120 "arising from its use. If you find the service useful, please "
121 "consider making a donation to the OpenCPN project.</p>"
122 "<p>This service is based on data and products of the European Centre "
123 "for Medium-Range Weather Forecasts (ECMWF).</p>"
124 "<p>Source: www.ecmwf.int</p>"
125 "<p>Disclaimer: ECMWF does not accept any liability whatsoever for any "
126 "error or omission in the data, their availability, or for any loss or "
127 "damage arising from their use.</p>"
128 "</font></body></html>"));
129 m_htmlInfoWin->SetBorders(10);
130 m_htmlInfoWin->SetPage(
131 "<html><body bgcolor="
140 _(
"<h1>Grib weather forecasts</h1>"
141 "<p>Collection of local weather models from various sources available "
142 "for download over the internet.</p>"
143 "</font></body></html>"));
145 m_bLocal_source_selected =
false;
146 EnableDownloadButtons();
148 m_selectedAtmModelIndex = 0;
149 m_selectedWaveModelIndex = 0;
150 InitializeXygribDialog();
153GribRequestSetting::~GribRequestSetting() {
159 wxEVT_DOWNLOAD_EVENT,
160 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
167void GribRequestSetting::SaveConfig() {
170 pConf->SetPath(
"/PlugIns/GRIB");
172 pConf->Write(
"MailRequestConfig", m_RequestConfigBase);
173 pConf->Write(
"MailSenderAddress", m_pSenderAddress->GetValue());
174 pConf->Write(
"MailRequestAddresses", m_MailToAddresses);
175 pConf->Write(
"ZyGribLogin", m_pLogin->GetValue());
176 pConf->Write(
"ZyGribCode", m_pCode->GetValue());
177 pConf->Write(
"SendMailMethod", m_SendMethod);
178 pConf->Write(
"MovingGribSpeed", m_sMovingSpeed->GetValue());
179 pConf->Write(
"MovingGribCourse", m_sMovingCourse->GetValue());
187 pConf->Write(
"RequestZoneMaxLat",
m_spMaxLat->GetValue());
188 pConf->Write(
"RequestZoneMinLat",
m_spMinLat->GetValue());
189 pConf->Write(
"RequestZoneMaxLon",
m_spMaxLon->GetValue());
190 pConf->Write(
"RequestZoneMinLon",
m_spMinLon->GetValue());
194void GribRequestSetting::InitRequestConfig() {
198 pConf->SetPath(
"/PlugIns/GRIB");
201 pConf->Read(
"MailRequestConfig", &m_RequestConfigBase,
"000220XX........0");
202 pConf->Read(
"MailSenderAddress", &l,
"");
203 m_pSenderAddress->ChangeValue(l);
204 pConf->Read(
"MailRequestAddresses", &m_MailToAddresses,
205 "query@saildocs.com;gribauto@zygrib.org");
206 pConf->Read(
"ZyGribLogin", &l,
"");
207 m_pLogin->ChangeValue(l);
208 pConf->Read(
"ZyGribCode", &l,
"");
209 m_pCode->ChangeValue(l);
210 pConf->Read(
"SendMailMethod", &m_SendMethod, 0);
211 pConf->Read(
"MovingGribSpeed", &m, 0);
212 m_sMovingSpeed->SetValue(m);
213 pConf->Read(
"MovingGribCourse", &m, 0);
214 m_sMovingCourse->SetValue(m);
215 pConf->Read(
"ManualRequestZoneSizingMode", &m, 0);
217 pConf->Read(
"ManualRequestZoneSizing", &m, 0);
224 UpdateAreaSelectionState();
225 pConf->Read(
"RequestZoneMaxLat", &m, 0);
227 pConf->Read(
"RequestZoneMinLat", &m, 0);
229 pConf->Read(
"RequestZoneMaxLon", &m, 0);
231 pConf->Read(
"RequestZoneMinLon", &m, 0);
234 SetCoordinatesText();
237 if (m_RequestConfigBase.Len() != wxString(
"000220XX..............").Len())
238 m_RequestConfigBase =
"000220XX..............";
241 wxString s1[] = {
"GFS",
"COAMPS",
"RTOFS",
"HRRR",
"ICON",
"ECMWF"};
242 for (
unsigned int i = 0; i < (
sizeof(s1) /
sizeof(wxString)); i++)
243 m_pModel->Append(s1[i]);
244 wxString s2[] = {
"Saildocs",
"zyGrib"};
245 for (
unsigned int i = 0; i < (
sizeof(s2) /
sizeof(wxString)); i++)
246 m_pMailTo->Append(s2[i]);
247 wxString s3[] = {
"WW3-GLOBAL",
"WW3-MEDIT"};
248 for (
unsigned int i = 0; i < (
sizeof(s3) /
sizeof(wxString)); i++)
249 m_pWModel->Append(s3[i]);
252 m_tResUnit->SetLabel(wxString::Format(
"\u00B0"));
253 m_sCourseUnit->SetLabel(wxString::Format(
"\u00B0"));
257 GetTextExtent(
"-360", &w, &h,
nullptr,
nullptr,
261 m_sMovingSpeed->SetMinSize(wxSize(w, h));
262 m_sMovingCourse->SetMinSize(wxSize(w, h));
269 m_pSenderAddress->SetToolTip(
270 _(
"Address used to send request eMail. (Mandatory for LINUX)"));
271 m_pLogin->SetToolTip(_(
"This is your zyGrib's forum access Login"));
273 _(
"Get this Code in zyGrib's forum ( This is not your password! )"));
274 m_sMovingSpeed->SetToolTip(_(
"Enter your forescasted Speed (in Knots)"));
275 m_sMovingCourse->SetToolTip(_(
"Enter your forecasted Course"));
278 ((wxString)m_RequestConfigBase.GetChar(0)).ToLong(&i);
279 m_pMailTo->SetSelection(i);
280 ((wxString)m_RequestConfigBase.GetChar(1)).ToLong(&i);
281 m_pModel->SetSelection(i);
282 m_cMovingGribEnabled->SetValue(m_RequestConfigBase.GetChar(16) ==
284 ((wxString)m_RequestConfigBase.GetChar(2)).ToLong(&i);
285 ((wxString)m_RequestConfigBase.GetChar(3)).ToLong(&j);
286 ((wxString)m_RequestConfigBase.GetChar(4)).ToLong(&k, 16);
290 m_pSenderSizer->ShowItems(
false);
292 if (m_SendMethod == 0)
293 m_pSenderSizer->ShowItems(
false);
295 m_pSenderSizer->ShowItems(
299 m_tMouseEventTimer.Connect(
300 wxEVT_TIMER, wxTimerEventHandler(GribRequestSetting::OnMouseEventTimer),
305 ApplyRequestConfig(i, j, k);
307 ((wxString)m_RequestConfigBase.GetChar(5)).ToLong(&j);
308 m_pWModel->SetSelection(j);
310 m_pWind->Enable(
false);
311 m_pPress->Enable(
false);
316 m_MailImage->SetValue(WriteMail());
319wxWindow *GetGRIBCanvas();
320void GribRequestSetting::OnClose(wxCloseEvent &event) {
323 m_downloading =
false;
324 m_download_handle = 0;
328 wxEVT_DOWNLOAD_EVENT,
329 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
338 m_parent.m_highlight_latmax = 0;
339 m_parent.m_highlight_lonmax = 0;
340 m_parent.m_highlight_latmin = 0;
341 m_parent.m_highlight_lonmin = 0;
345void GribRequestSetting::SetRequestDialogSize() {
348 GetTextExtent(
"abc",
nullptr, &y,
nullptr,
nullptr,
OCPNGetFont(_(
"Dialog")));
349 m_MailImage->SetMinSize(
350 wxSize(-1, ((y * m_MailImage->GetNumberOfLines()) + 10)));
354 m_fgScrollSizer->Fit(m_sScrolledDialog);
357 SetMinSize(wxSize(0, 0));
360 wxWindow *frame = wxTheApp->GetTopWindow();
362 int w = frame->GetClientSize().x;
363 int h = frame->GetClientSize().y;
369 m_sScrolledDialog->SetMinSize(
370 wxSize(wxMin(w, scroll.x),
371 wxMin(h, scroll.y)));
376 wxSize sd = GetSize();
377 if (sd.y == GetClientSize().y) sd.y += 30;
378 SetSize(wxSize(sd.x, sd.y));
379 SetMinSize(wxSize(sd.x, sd.y));
387 if ((fabs(vp->
lat_max) < 90.) && (fabs(lonmax) < 360.)) {
388 if (lonmax < -180.) lonmax += 360.;
389 if (lonmax > 180.) lonmax -= 360.;
391 if ((fabs(vp->
lat_min) < 90.) && (fabs(lonmin) < 360.)) {
392 if (lonmin < -180.) lonmin += 360.;
393 if (lonmin > 180.) lonmin -= 360.;
396 bool bnew_val =
false;
398 if (
m_spMinLon->GetValue() != (
int)floor(lonmin)) bnew_val =
true;
400 if (
m_spMaxLon->GetValue() != (
int)ceil(lonmax)) bnew_val =
true;
408 SetCoordinatesText();
409 m_MailImage->SetValue(WriteMail());
414 if (!(event.ShiftDown() || m_bpManualSelection->GetValue())) {
419 if (event.LeftDown() && !event.Dragging()) {
434 int xm =
event.GetX() * m_displayScale;
435 int ym =
event.GetY() * m_displayScale;
437 if (event.LeftDown() && !event.Dragging()) {
438 m_parent.pParent->SetFocus();
451 SetCoordinatesText();
452 UpdateAreaSelectionState();
453 m_MailImage->SetValue(WriteMail());
456 UpdateGribSizeEstimate();
457 m_boundingBoxCanvasIndex = -1;
458 }
else if (event.Dragging()) {
473 if (!m_tMouseEventTimer.IsRunning())
474 m_tMouseEventTimer.Start(20, wxTIMER_ONE_SHOT);
479void GribRequestSetting::OnMouseEventTimer(wxTimerEvent &event) {
501void GribRequestSetting::SetCoordinatesText() {
502 m_stMaxLatNS->SetLabel(
m_spMaxLat->GetValue() < 0 ? _(
"S") : _(
"N"));
503 m_stMinLonEW->SetLabel(
m_spMinLon->GetValue() < 0 ? _(
"W") : _(
"E"));
504 m_stMaxLonEW->SetLabel(
m_spMaxLon->GetValue() < 0 ? _(
"W") : _(
"E"));
505 m_stMinLatNS->SetLabel(
m_spMinLat->GetValue() < 0 ? _(
"S") : _(
"N"));
508size_t LengthSelToHours(
int sel) {
520std::string GribRequestSetting::FormatPerLocale(T value) {
521 std::stringstream ss;
523 ss.imbue(std::locale(
""));
528wxString GribRequestSetting::GetDownloadProgressText(
long transferredBytes,
530 if (totalBytes > 0) {
531 return wxString::Format(_(
"Downloading... %s kB / %s kB (%li%%)"),
532 FormatPerLocale(transferredBytes / 1024).c_str(),
533 FormatPerLocale(totalBytes / 1024).c_str(),
534 (
int)((
double)transferredBytes / totalBytes * 100));
536 return wxString::Format(_(
"Downloading... %s kB / ???"),
537 FormatPerLocale(transferredBytes / 1024).c_str());
544 switch (ev.getDLEventCondition()) {
548 Disconnect(wxEVT_DOWNLOAD_EVENT,
552 m_downloading =
false;
553 m_download_handle = 0;
558 switch (m_downloadType) {
560 m_staticTextInfo->SetLabelText(
561 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
565 m_stLocalDownloadInfo->SetLabelText(
566 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
571 m_xygribPanel->m_progress_gauge->SetValue(
572 100 * ev.getTransferred() / ev.getTotal());
575 m_xygribPanel->m_status_text->SetLabel(
576 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
588void GribRequestSetting::OnWorldDownload(wxCommandEvent &event) {
591 m_downloading =
false;
592 m_download_handle = 0;
594 wxEVT_DOWNLOAD_EVENT,
595 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
597 m_btnDownloadWorld->SetLabelText(_(
"Download"));
598 m_staticTextInfo->SetLabelText(_(
"Download canceled"));
601 EnableDownloadButtons();
602 wxTheApp->ProcessPendingEvents();
607 m_downloading =
true;
609 EnableDownloadButtons();
610 m_btnDownloadWorld->SetLabelText(_(
"Cancel"));
611 m_staticTextInfo->SetLabelText(_(
"Preparing data on server..."));
614 switch (m_chECMWFResolution->GetSelection()) {
619 model =
"ecmwfaifs0p25";
625 std::ostringstream oss;
626 oss <<
"https://grib.bosun.io/grib?";
627 oss <<
"model=" << model;
632 oss <<
"&length=" << LengthSelToHours(m_chForecastLength->GetSelection());
634 wxString::Format(
"ocpn_%s_%li_%s.grb2", model.c_str(),
635 LengthSelToHours(m_chForecastLength->GetSelection()),
636 wxDateTime::Now().Format(
"%F-%H-%M"));
637 wxString path = m_parent.GetGribDir();
638 path.Append(wxFileName::GetPathSeparator());
639 path.Append(filename);
643 wxEVT_DOWNLOAD_EVENT,
644 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
647 while (m_downloading) {
648 wxTheApp->ProcessPendingEvents();
652 if (m_bTransferSuccess) {
653 m_staticTextInfo->SetLabelText(
654 wxString::Format(_(
"Download complete: %s"), path.c_str()));
661 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
663 m_parent.SetDialogsStyleSizePosition(
true);
667 m_staticTextInfo->SetLabelText(_(
"Download failed"));
670 m_btnDownloadWorld->SetLabelText(_(
"Download"));
672 EnableDownloadButtons();
675enum LocalSourceItem { SOURCE, AREA, GRIB };
677enum LocalGribDownloadType { DIRECT, MANIFEST, WEBPAGE };
680 GribCatalogInfo(LocalSourceItem type, wxString name, wxString description,
681 wxString url, wxString filename,
682 LocalGribDownloadType download_type,
double latmin,
683 double lonmin,
double latmax,
double lonmax)
686 description(description),
689 download_type(download_type),
694 LocalSourceItem type;
696 wxString description;
699 LocalGribDownloadType download_type;
706void GribRequestSetting::FillTreeCtrl(
wxJSONValue &data) {
707 m_SourcesTreeCtrl1->DeleteAllItems();
709 m_SourcesTreeCtrl1->AddRoot(_(
"Local high resolution forecasts"));
710 if (data.HasMember(
"sources") && data[
"sources"].IsArray()) {
711 for (
int i = 0; i < data[
"sources"].Size(); i++) {
714 LocalSourceItem::SOURCE, source[
"source"].AsString(),
715 source[
"description"].AsString(), source[
"url"].AsString(),
716 wxEmptyString, LocalGribDownloadType::WEBPAGE, 0, 0, 0, 0);
717 wxTreeItemId src_id = m_SourcesTreeCtrl1->AppendItem(
718 root, source[
"source"].AsString(), -1, -1, info);
719 if (source.
HasMember(
"areas") && source[
"areas"].IsArray()) {
720 for (
int j = 0; j < source[
"areas"].
Size(); j++) {
723 LocalSourceItem::AREA, area[
"name"].AsString(),
724 source[
"description"].AsString(), source[
"url"].AsString(),
725 wxEmptyString, LocalGribDownloadType::WEBPAGE,
726 area[
"boundary"][
"lat_min"].AsDouble(),
727 area[
"boundary"][
"lon_min"].AsDouble(),
728 area[
"boundary"][
"lat_max"].AsDouble(),
729 area[
"boundary"][
"lon_max"].AsDouble());
730 m_SourcesTreeCtrl1->AppendItem(src_id, area[
"name"].AsString(), -1,
732 if (area.
HasMember(
"gribs") && area[
"gribs"].IsArray()) {
733 for (
int k = 0; k < area[
"gribs"].
Size(); k++) {
736 LocalSourceItem::GRIB, grib[
"name"].AsString(),
737 source[
"description"].AsString(),
738 grib.
HasMember(
"url") ? grib[
"url"].AsString()
739 : grib[
"cat_url"].AsString(),
740 grib.HasMember(
"filename") ? grib[
"filename"].AsString() :
"",
741 grib.HasMember(
"url") ? LocalGribDownloadType::DIRECT
742 : LocalGribDownloadType::MANIFEST,
743 area[
"boundary"][
"lat_min"].AsDouble(),
744 area[
"boundary"][
"lon_min"].AsDouble(),
745 area[
"boundary"][
"lat_max"].AsDouble(),
746 area[
"boundary"][
"lon_max"].AsDouble());
747 m_SourcesTreeCtrl1->AppendItem(
748 m_SourcesTreeCtrl1->GetLastChild(src_id),
749 grib[
"name"].AsString(), -1, -1, inf_1);
754 m_SourcesTreeCtrl1->CollapseAllChildren(src_id);
757 m_SourcesTreeCtrl1->Expand(root);
760void GribRequestSetting::ReadLocalCatalog() {
762 wxFileInputStream str(m_parent.
pPlugIn->m_local_sources_catalog);
764 reader.
Parse(str, &root);
768void GribRequestSetting::HighlightArea(
double latmax,
double lonmax,
769 double latmin,
double lonmin) {
770 m_parent.m_highlight_latmax = latmax;
771 m_parent.m_highlight_lonmax = lonmax;
772 m_parent.m_highlight_latmin = latmin;
773 m_parent.m_highlight_lonmin = lonmin;
776void GribRequestSetting::OnLocalTreeSelChanged(wxTreeEvent &event) {
777 wxTreeItemId item = m_SourcesTreeCtrl1->GetSelection();
780 if (src->type == LocalSourceItem::GRIB) {
781 m_stLocalDownloadInfo->SetLabelText(_(
"Download grib..."));
782 m_bLocal_source_selected =
true;
783 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
785 m_stLocalDownloadInfo->SetLabelText(_(
"Select grib..."));
786 m_bLocal_source_selected =
false;
787 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
790 EnableDownloadButtons();
793void GribRequestSetting::OnUpdateLocalCatalog(wxCommandEvent &event) {
796 m_downloading =
false;
797 m_download_handle = 0;
799 wxEVT_DOWNLOAD_EVENT,
800 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
802 m_btnDownloadLocal->SetLabelText(_(
"Download"));
803 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
806 EnableDownloadButtons();
807 wxTheApp->ProcessPendingEvents();
812 m_downloading =
true;
814 EnableDownloadButtons();
815 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
816 m_staticTextInfo->SetLabelText(_(
"Downloading catalog update..."));
821 wxEVT_DOWNLOAD_EVENT,
822 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
825 m_parent.
pPlugIn->m_local_sources_catalog +
"new",
826 this, &m_download_handle);
827 while (m_downloading) {
828 wxTheApp->ProcessPendingEvents();
832 if (m_bTransferSuccess) {
833 wxRenameFile(m_parent.
pPlugIn->m_local_sources_catalog +
"new",
834 m_parent.
pPlugIn->m_local_sources_catalog,
true);
836 m_stLocalDownloadInfo->SetLabelText(_(
"Catalog update complete."));
838 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
841 m_btnDownloadLocal->SetLabelText(_(
"Download"));
843 EnableDownloadButtons();
846void GribRequestSetting::OnDownloadLocal(wxCommandEvent &event) {
849 m_downloading =
false;
850 m_download_handle = 0;
852 wxEVT_DOWNLOAD_EVENT,
853 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
855 m_btnDownloadLocal->SetLabelText(_(
"Download"));
856 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
859 EnableDownloadButtons();
860 wxTheApp->ProcessPendingEvents();
865 m_downloading =
true;
867 EnableDownloadButtons();
868 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
869 m_staticTextInfo->SetLabelText(_(
"Downloading grib..."));
872 m_SourcesTreeCtrl1->GetSelection()));
873 if (!src || src->type != LocalSourceItem::GRIB || src->url.IsEmpty()) {
874 m_downloading =
false;
875 m_stLocalDownloadInfo->SetLabelText(_(
"Download can't be started."));
876 m_btnDownloadWorld->SetLabelText(_(
"Download"));
878 EnableDownloadButtons();
884 wxEVT_DOWNLOAD_EVENT,
885 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
887 wxString url = src->url;
890 if (src->download_type == LocalGribDownloadType::MANIFEST) {
891 wxString path = m_parent.GetGribDir();
892 path.Append(wxFileName::GetPathSeparator());
893 path.Append(
"grib_manifest.json");
895 while (m_downloading) {
896 wxTheApp->ProcessPendingEvents();
901 if (!m_bTransferSuccess) {
903 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
907 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
911 wxFileInputStream str(path);
913 reader.
Parse(str, &root);
915 wxString parsed = root[
"url"].
AsString();
916 if (parsed.StartsWith(
"http")) {
919 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
926 m_downloading =
false;
927 m_download_handle = 0;
928 Disconnect(wxEVT_DOWNLOAD_EVENT,
932 m_btnDownloadLocal->SetLabelText(_(
"Download"));
933 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
936 EnableDownloadButtons();
937 wxTheApp->ProcessPendingEvents();
943 m_downloading =
true;
948 wxEVT_DOWNLOAD_EVENT,
949 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
952 if (!src->filename.IsEmpty()) {
953 filename = src->filename;
958 filename.Replace(
"?",
"_");
959 filename.Replace(
"&",
"_");
960 if (!(filename.Contains(
".grb2") || filename.Contains(
".grib2") ||
961 filename.Contains(
".grb") || filename.Contains(
".grib"))) {
962 filename.Append(
".grb");
966 wxString path = m_parent.GetGribDir();
967 path.Append(wxFileName::GetPathSeparator());
968 path.Append(filename);
970 while (m_downloading) {
971 wxTheApp->ProcessPendingEvents();
975 if (m_bTransferSuccess) {
976 m_stLocalDownloadInfo->SetLabelText(_(
"Grib download complete."));
977 m_stLocalDownloadInfo->SetLabelText(
978 wxString::Format(_(
"Download complete: %s"), path.c_str()));
986 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
988 m_parent.SetDialogsStyleSizePosition(
true);
992 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
995 m_btnDownloadWorld->SetLabelText(_(
"Download"));
997 EnableDownloadButtons();
1000void GribRequestSetting::EnableDownloadButtons() {
1001 switch (m_downloadType) {
1003 m_btnDownloadWorld->Enable(
true);
1004 m_btnDownloadLocal->Enable(
false);
1005 m_buttonUpdateCatalog->Enable(
false);
1009 m_btnDownloadWorld->Enable(
false);
1010 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1011 m_buttonUpdateCatalog->Enable(
false);
1014 m_xygribPanel->m_download_button->Enable(
true);
1017 m_btnDownloadWorld->Enable(
true);
1018 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1019 m_buttonUpdateCatalog->Enable(
true);
1020 m_xygribPanel->m_download_button->Enable(
true);
1025void GribRequestSetting::StopGraphicalZoneSelection() {
1045 if (!m_AllowSend)
return;
1051 UpdateGribSizeEstimate();
1054void GribRequestSetting::ApplyRequestConfig(
unsigned rs,
unsigned it,
1057 const wxString res[][RESOLUTIONS] = {
1058 {
"0.25",
"0.5",
"1.0",
"2.0"},
1059 {
"0.2",
"0.8",
"1.6", wxEmptyString},
1060 {
"0.08",
"0.24",
"1.0", wxEmptyString},
1061 {
"0.03",
"0.24",
"1.0", wxEmptyString},
1062 {
"0.0625",
"0.125", wxEmptyString, wxEmptyString},
1063 {
"0.4",
"1.0",
"2.0", wxEmptyString}
1066 IsZYGRIB = m_pMailTo->GetCurrentSelection() == ZYGRIB;
1068 m_pModel->SetSelection(GFS);
1069 IsGFS = m_pModel->GetCurrentSelection() == GFS;
1070 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1071 bool IsHRRR = m_pModel->GetCurrentSelection() == HRRR;
1072 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1073 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1076 m_pResolution->Clear();
1077 if (m_pModel->GetCurrentSelection() >= 0) {
1078 for (
int i = 0; i < RESOLUTIONS; i++) {
1079 if (res[m_pModel->GetCurrentSelection()][i] != wxEmptyString) {
1080 wxString s = res[m_pModel->GetCurrentSelection()][i];
1081 m_pResolution->Append(s);
1085 m_pResolution->SetSelection(rs);
1089 l = (IsGFS || IsRTOFS || IsICON || IsECMWF) ? 3 : IsHRRR ? 1 : 6;
1092 m = IsHRRR ? 2 : 25;
1094 m_pInterval->Clear();
1095 for (
unsigned i = l; i < m; i *= 2)
1096 m_pInterval->Append(wxString::Format(
"%d", i));
1097 m_pInterval->SetSelection(wxMin(it, m_pInterval->GetCount() - 1));
1107 m_pTimeRange->Clear();
1108 for (
unsigned i = 2; i < l + 1; i++)
1109 m_pTimeRange->Append(wxString::Format(
"%d", i));
1110 m_pTimeRange->SetSelection(wxMin(l - 2, tr));
1112 m_pModel->Enable(!IsZYGRIB);
1113 m_pWind->SetValue(!IsRTOFS);
1114 m_pPress->SetValue(!IsRTOFS);
1115 m_pWaves->SetValue(m_RequestConfigBase.GetChar(8) ==
'X' && IsGFS);
1116 m_pWaves->Enable(IsECMWF ||
1117 (IsGFS && m_pTimeRange->GetCurrentSelection() < 7));
1119 m_pRainfall->SetValue(m_RequestConfigBase.GetChar(9) ==
'X' &&
1121 m_pRainfall->Enable(IsGFS || IsHRRR);
1122 m_pCloudCover->SetValue(m_RequestConfigBase.GetChar(10) ==
'X' && IsGFS);
1123 m_pCloudCover->Enable(IsGFS);
1124 m_pAirTemp->SetValue(m_RequestConfigBase.GetChar(11) ==
'X' &&
1125 (IsGFS || IsHRRR || IsICON || IsECMWF));
1126 m_pAirTemp->Enable(IsGFS || IsHRRR || IsICON || IsECMWF);
1127 m_pSeaTemp->SetValue(m_RequestConfigBase.GetChar(12) ==
'X' &&
1128 ((!IsZYGRIB && IsGFS) || IsRTOFS || IsHRRR || IsICON));
1129 m_pSeaTemp->Enable(!IsZYGRIB && (IsGFS || IsHRRR || IsICON));
1130 m_pWindGust->SetValue(m_RequestConfigBase.GetChar(14) ==
'X' &&
1131 (IsGFS || IsHRRR || IsICON));
1132 m_pWindGust->Enable(IsGFS || IsHRRR || IsICON);
1133 m_pCAPE->SetValue(m_RequestConfigBase.GetChar(15) ==
'X' &&
1135 m_pCAPE->Enable(IsGFS || IsHRRR);
1136 m_pReflectivity->Enable(IsGFS || IsHRRR);
1138 m_pAltitudeData->SetValue(
1139 (IsGFS || IsICON || IsECMWF)
1140 ? m_RequestConfigBase.GetChar(17) ==
'X'
1142 m_pAltitudeData->Enable(IsGFS || IsICON || IsECMWF);
1143 m_p850hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(18) ==
'X'
1145 m_p850hpa->Enable(IsZYGRIB);
1146 m_p700hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(19) ==
'X'
1148 m_p700hpa->Enable(IsZYGRIB);
1149 m_p500hpa->SetValue((IsGFS || IsICON || IsECMWF)
1150 ? m_RequestConfigBase.GetChar(20) ==
'X'
1152 m_p500hpa->Enable(IsGFS || IsICON || IsECMWF);
1153 m_p300hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(21) ==
'X'
1155 m_p300hpa->Enable(IsZYGRIB);
1157 m_pCurrent->SetValue(IsRTOFS);
1158 m_pCurrent->Enable(
false);
1161 m_cMovingGribEnabled->Show(!IsZYGRIB);
1162 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1163 m_cMovingGribEnabled->IsShown());
1165 m_fgLog->ShowItems(IsZYGRIB);
1167 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1169 m_fgAltitudeData->ShowItems(
1170 m_pAltitudeData->IsChecked());
1173void GribRequestSetting::OnTopChange(wxCommandEvent &event) {
1175 if (m_pMailTo->GetCurrentSelection() == ZYGRIB) {
1176 m_pMailTo->SetSelection(0);
1179 _(
"Sorry...\nZyGrib momentary stopped providing this service...\nOnly "
1180 "Saildocs option is available"),
1181 _(
"Warning"), wxOK);
1183 ApplyRequestConfig(m_pResolution->GetCurrentSelection(),
1184 m_pInterval->GetCurrentSelection(),
1185 m_pTimeRange->GetCurrentSelection());
1187 m_cMovingGribEnabled->Show(m_pMailTo->GetCurrentSelection() == SAILDOCS);
1189 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1191 SetRequestDialogSize();
1194void GribRequestSetting::UpdateAreaSelectionState() {
1203void GribRequestSetting::OnZoneSelectionModeChange(wxCommandEvent &event) {
1204 StopGraphicalZoneSelection();
1213 }
else if (event.GetId() ==
MANSELECT) {
1219 m_cUseSavedZone->SetValue(
false);
1220 }
else if (event.GetId() ==
SAVEDZONE) {
1228 UpdateAreaSelectionState();
1229 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1231 SetRequestDialogSize();
1245 center.x = x + (zw / 2);
1246 center.y = y + (zh / 2);
1252 wxColour pen_color, back_color;
1253 GetGlobalColor(
"DASHR", &pen_color);
1254 GetGlobalColor(
"YELO1", &back_color);
1256 int label_offsetx = 5, label_offsety = 1;
1259 EstimateFileSize(&size);
1261 wxString label(_(
"Coord. "));
1262 label.Append(toMailFormat(1,
m_spMaxLat->GetValue()) +
" ");
1263 label.Append(toMailFormat(0,
m_spMinLon->GetValue()) +
" ");
1264 label.Append(toMailFormat(1,
m_spMinLat->GetValue()) +
" ");
1265 label.Append(toMailFormat(0,
m_spMaxLon->GetValue()) +
"\n");
1266 label.Append(
"Estim. Size ")
1267 .Append((wxString::Format(
"%1.2f ", size) + _(
"MB")));
1270 wxPen pen(pen_color);
1273 m_pdc->SetBrush(*wxTRANSPARENT_BRUSH);
1274 m_pdc->DrawRectangle(x, y, zw, zh);
1279 sdc.GetMultiLineTextExtent(label, &w, &h, &sl, font);
1281 m_pdc->GetMultiLineTextExtent(label, &w, &h, &sl, font);
1285 w += 2 * label_offsetx, h += 2 * label_offsety;
1286 x = center.x - (w / 2);
1287 y = center.y - (h / 2);
1289 h *= m_displayScale;
1290 w *= m_displayScale;
1297 mdc.SetBrush(back_color);
1298 mdc.SetPen(*wxTRANSPARENT_PEN);
1299 mdc.SetTextForeground(wxColor(0, 0, 0));
1300 mdc.DrawRectangle(0, 0, w, h);
1301 mdc.DrawLabel(label, wxRect(label_offsetx, label_offsety, w, h));
1303 wxImage im = bm.ConvertToImage();
1305 w = im.GetWidth(), h = im.GetHeight();
1306 for (
int j = 0; j < h; j++)
1307 for (
int i = 0; i < w; i++) im.SetAlpha(i, j, 155);
1309 m_pdc->DrawBitmap(im, x, y,
true);
1313#ifndef USE_ANDROID_GLES2
1320 m_oDC->SetPen(wxPen(pen_color, 3));
1323 outline[0] = wxPoint(x, y);
1324 outline[1] = wxPoint(x + zw, y);
1325 outline[2] = wxPoint(x + zw, y + zh);
1326 outline[3] = wxPoint(x, y + zh);
1327 outline[4] = wxPoint(x, y);
1328 m_oDC->DrawLines(5, outline);
1330 m_oDC->SetFont(*font);
1332 m_oDC->GetTextExtent(label, &w, &h);
1333 h *= m_displayScale;
1334 w *= m_displayScale;
1336 m_oDC->GetTextExtent(
"W", &ww, &hw);
1338 int label_offsetx_ = ww, label_offsety_ = 1;
1339 int x_ = center.x - w / 2;
1340 int y_ = center.y - h / 2;
1342 w += 2 * label_offsetx_, h += 2 * label_offsety_;
1344 m_oDC->SetBrush(wxBrush(back_color));
1345 m_oDC->DrawRoundedRectangle(x_, y_, w, h, 0);
1348 m_oDC->SetPen(wxPen(wxColour(0, 0, 0), 1));
1350 outline[0] = wxPoint(x_, y_);
1351 outline[1] = wxPoint(x_ + w, y_);
1352 outline[2] = wxPoint(x_ + w, y_ + h);
1353 outline[3] = wxPoint(x_, y_ + h);
1354 outline[4] = wxPoint(x_, y_);
1355 m_oDC->DrawLines(5, outline);
1357 m_oDC->DrawText(label, x_ + label_offsetx_, y_ + label_offsety_);
1377void GribRequestSetting::OnMovingClick(wxCommandEvent &event) {
1378 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1379 m_cMovingGribEnabled->IsShown());
1381 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1382 SetRequestDialogSize();
1387void GribRequestSetting::OnCoordinatesChange(wxSpinEvent &event) {
1388 SetCoordinatesText();
1390 StopGraphicalZoneSelection();
1392 if (!m_AllowSend)
return;
1394 m_MailImage->SetValue(WriteMail());
1397void GribRequestSetting::OnAnyChange(wxCommandEvent &event) {
1398 m_fgAltitudeData->ShowItems(m_pAltitudeData->IsChecked());
1400 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1402 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1404 SetRequestDialogSize();
1407void GribRequestSetting::OnTimeRangeChange(wxCommandEvent &event) {
1408 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1410 if (m_pModel->GetCurrentSelection() == 0) {
1411 if (m_pTimeRange->GetCurrentSelection() >
1413 m_pWaves->SetValue(0);
1414 m_pWaves->Enable(
false);
1417 _(
"You request a forecast for more than 8 days horizon.\nThis is "
1418 "conflicting with Wave data which will be removed from your "
1419 "request.\nDon't forget that beyond the first 8 days, the "
1420 "resolution will be only 2.5\u00B0x2.5\u00B0\nand the time "
1421 "intervall 12 hours."),
1424 m_pWaves->Enable(
true);
1427 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1429 SetRequestDialogSize();
1433 bool IsCOAMPS = m_pModel->GetCurrentSelection() == COAMPS;
1434 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1435 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1436 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1437 m_RequestConfigBase.SetChar(
1438 0, (
char)(m_pMailTo->GetCurrentSelection() +
'0'));
1439 m_cMovingGribEnabled->IsChecked()
1440 ? m_RequestConfigBase.SetChar(16,
'X')
1441 : m_RequestConfigBase.SetChar(16,
'.');
1444 m_RequestConfigBase.SetChar(
1445 1, (
char)(m_pModel->GetCurrentSelection() +
'0'));
1447 m_RequestConfigBase.SetChar(
1448 2, (
char)(m_pResolution->GetCurrentSelection() +
'0'));
1450 m_RequestConfigBase.SetChar(3,
1451 (
char)(m_pInterval->GetCurrentSelection() +
'0'));
1454 range.Printf(
"%x", m_pTimeRange->GetCurrentSelection() +
1456 m_RequestConfigBase.SetChar(4, range.GetChar(0));
1458 if (IsZYGRIB && m_pWModel->IsShown())
1459 m_RequestConfigBase.SetChar(
1460 5, (
char)(m_pWModel->GetCurrentSelection() +
'0'));
1462 m_RequestConfigBase.SetChar(
1464 m_RequestConfigBase.SetChar(
1467 if (!IsCOAMPS && !IsRTOFS) {
1468 m_pWindGust->IsChecked() ? m_RequestConfigBase.SetChar(14,
'X')
1469 : m_RequestConfigBase.SetChar(14,
'.');
1470 m_pWaves->IsChecked() ? m_RequestConfigBase.SetChar(8,
'X')
1471 : m_RequestConfigBase.SetChar(8,
'.');
1472 m_pRainfall->IsChecked() ? m_RequestConfigBase.SetChar(9,
'X')
1473 : m_RequestConfigBase.SetChar(9,
'.');
1474 m_pCloudCover->IsChecked() ? m_RequestConfigBase.SetChar(10,
'X')
1475 : m_RequestConfigBase.SetChar(10,
'.');
1476 m_pAirTemp->IsChecked() ? m_RequestConfigBase.SetChar(11,
'X')
1477 : m_RequestConfigBase.SetChar(11,
'.');
1478 m_pSeaTemp->IsChecked() ? m_RequestConfigBase.SetChar(12,
'X')
1479 : m_RequestConfigBase.SetChar(12,
'.');
1480 m_pCAPE->IsChecked() ? m_RequestConfigBase.SetChar(15,
'X')
1481 : m_RequestConfigBase.SetChar(15,
'.');
1484 m_pCurrent->IsChecked() ? m_RequestConfigBase.SetChar(13,
'X')
1485 : m_RequestConfigBase.SetChar(13,
'.');
1487 if (IsGFS || IsICON || IsECMWF) {
1488 m_pAltitudeData->IsChecked()
1489 ? m_RequestConfigBase.SetChar(17,
'X')
1490 : m_RequestConfigBase.SetChar(17,
'.');
1491 m_p500hpa->IsChecked() ? m_RequestConfigBase.SetChar(20,
'X')
1492 : m_RequestConfigBase.SetChar(20,
'.');
1495 m_p850hpa->IsChecked() ? m_RequestConfigBase.SetChar(18,
'X')
1496 : m_RequestConfigBase.SetChar(18,
'.');
1497 m_p700hpa->IsChecked() ? m_RequestConfigBase.SetChar(19,
'X')
1498 : m_RequestConfigBase.SetChar(19,
'.');
1499 m_p300hpa->IsChecked() ? m_RequestConfigBase.SetChar(21,
'X')
1500 : m_RequestConfigBase.SetChar(21,
'.');
1507wxString GribRequestSetting::WriteMail() {
1509 int limit = IsZYGRIB ? 2 : 0;
1513 const wxString s[] = {
",",
" "};
1514 const wxString p[][11] = {
1516 {
"APCP",
"TCDC",
"AIRTMP",
"HTSGW,WVPER,WVDIR",
"SEATMP",
"GUST",
"CAPE",
1517 wxEmptyString, wxEmptyString,
"WIND500,HGT500", wxEmptyString},
1522 {
"",
"",
"AIRTMP",
"",
"SFCTMP",
"GUST",
"",
"",
"",
"WIND500,HGT500",
1525 {
"",
"",
"TEMP",
"WAVES",
"",
"",
"",
"",
"",
"WIND500,HGT500",
""},
1527 {
"PRECIP",
"CLOUD",
"TEMP",
"WVSIG WVWIND", wxEmptyString,
"GUST",
"CAPE",
1528 "A850",
"A700",
"A500",
"A300"}};
1530 wxString r_topmess, r_parameters, r_zone;
1532 switch (m_pMailTo->GetCurrentSelection()) {
1534 r_zone = toMailFormat(1,
m_spMaxLat->GetValue()) +
"," +
1535 toMailFormat(1,
m_spMinLat->GetValue()) +
"," +
1536 toMailFormat(2,
m_spMinLon->GetValue()) +
"," +
1538 r_topmess =
"send ";
1539 r_topmess.Append(m_pModel->GetStringSelection() +
":");
1540 r_topmess.Append(r_zone +
"|");
1541 r_topmess.Append(m_pResolution->GetStringSelection())
1543 .Append(m_pResolution->GetStringSelection())
1546 m_pInterval->GetStringSelection().ToDouble(&v);
1547 r_topmess.Append(wxString::Format(
"0,%d,%d", (
int)v, (
int)v * 2));
1548 m_pTimeRange->GetStringSelection().ToDouble(&v);
1549 r_topmess.Append(wxString::Format(
"..%d", (
int)v * 24) +
"|=\n");
1556 r_zone = toMailFormat(1,
m_spMinLat->GetValue()) +
1557 toMailFormat(2,
m_spMinLon->GetValue()) +
" " +
1559 toMailFormat(2, maxlon);
1560 r_topmess =
"login : ";
1561 r_topmess.Append(m_pLogin->GetValue() +
"\n");
1562 r_topmess.Append(
"code :");
1563 r_topmess.Append(m_pCode->GetValue() +
"\n");
1564 r_topmess.Append(
"area : ");
1565 r_topmess.append(r_zone +
"\n");
1566 r_topmess.Append(
"resol : ");
1567 r_topmess.append(m_pResolution->GetStringSelection() +
"\n");
1568 r_topmess.Append(
"days : ");
1569 r_topmess.append(m_pTimeRange->GetStringSelection() +
"\n");
1570 r_topmess.Append(
"hours : ");
1571 r_topmess.append(m_pInterval->GetStringSelection() +
"\n");
1572 if (m_pWaves->IsChecked()) {
1573 r_topmess.Append(
"waves : ");
1574 r_topmess.append(m_pWModel->GetStringSelection() +
"\n");
1576 r_topmess.Append(
"meteo : ");
1577 r_topmess.append(m_pModel->GetStringSelection() +
"\n");
1578 if (m_pLogin->GetValue().IsEmpty() || m_pCode->GetValue().IsEmpty())
1583 int GFSZ = IsZYGRIB ? 6 : 0;
1584 switch (m_pModel->GetCurrentSelection()) {
1586 r_parameters =
"WIND" + s[m_pMailTo->GetCurrentSelection()] +
1588 if (m_pRainfall->IsChecked())
1589 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1591 if (m_pCloudCover->IsChecked())
1592 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1594 if (m_pAirTemp->IsChecked())
1595 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1597 if (m_pWaves->IsChecked())
1598 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1600 if (m_pSeaTemp->IsChecked())
1601 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1603 if (m_pWindGust->IsChecked())
1604 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1606 if (m_pCAPE->IsChecked())
1607 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1609 if (m_pAltitudeData->IsChecked()) {
1610 if (m_p850hpa->IsChecked())
1611 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1613 if (m_p700hpa->IsChecked())
1614 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1616 if (m_p500hpa->IsChecked())
1617 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1619 if (m_p300hpa->IsChecked())
1620 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1625 r_parameters =
"WIND,PRMSL";
1629 r_parameters =
"CUR,WTMP";
1632 r_parameters =
"WIND,PRMSL";
1634 if (m_pRainfall->IsChecked())
1635 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][0]);
1636 if (m_pAirTemp->IsChecked())
1637 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][2]);
1638 if (m_pSeaTemp->IsChecked())
1639 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][4]);
1640 if (m_pWindGust->IsChecked())
1641 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][5]);
1642 if (m_pCAPE->IsChecked())
1643 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][6]);
1646 r_parameters =
"WIND,PRMSL";
1648 if (m_pAirTemp->IsChecked())
1649 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][2]);
1650 if (m_pSeaTemp->IsChecked())
1651 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][4]);
1652 if (m_pWindGust->IsChecked())
1653 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][5]);
1654 if (m_pAltitudeData->IsChecked()) {
1655 if (m_p500hpa->IsChecked())
1656 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][9]);
1660 r_parameters =
"WIND,MSLP";
1662 if (m_pAirTemp->IsChecked())
1663 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][2]);
1664 if (m_pAltitudeData->IsChecked()) {
1665 if (m_p500hpa->IsChecked())
1666 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1669 if (m_pWaves->IsChecked())
1670 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][3]);
1673 if (!IsZYGRIB && m_cMovingGribEnabled->IsChecked())
1674 r_parameters.Append(wxString::Format(
"|%d,%d", m_sMovingSpeed->GetValue(),
1675 m_sMovingCourse->GetValue()));
1679 char c = m_pMailTo->GetCurrentSelection() == SAILDOCS ?
',' :
' ';
1680 for (
size_t i = 0; i < r_parameters.Len(); i++) {
1681 if (r_parameters.GetChar(i) ==
'|')
1683 if (r_parameters.GetChar(i) == c) j++;
1685 r_parameters.insert(
1686 i + 1, m_pMailTo->GetCurrentSelection() == SAILDOCS ?
"=\n" :
"\n");
1692 m_MailError_Nb += EstimateFileSize(&size);
1694 m_tFileSize->SetLabel(wxString::Format(
"%1.2f ", size) + _(
"MB"));
1697 m_tLimit->SetLabel(wxString(
"( ") + _(
"Max") +
1698 wxString::Format(
" %d ", limit) + _(
"MB") +
" )");
1699 if (size > limit) m_MailError_Nb += 2;
1701 m_tLimit->SetLabel(wxEmptyString);
1703 return wxString(r_topmess + r_parameters);
1706int GribRequestSetting::EstimateFileSize(
double *size) {
1707 if (!size)
return 0;
1711 double reso, time, inter;
1712 m_pResolution->GetStringSelection().ToDouble(&reso);
1713 m_pTimeRange->GetStringSelection().ToDouble(&time);
1714 m_pInterval->GetStringSelection().ToDouble(&inter);
1718 if (maxlat - minlat < 0)
return 3;
1719 double wlon = (maxlon > minlon ? 0 : 360) + maxlon - minlon;
1720 if (wlon > 180 || (maxlat - minlat > 180))
return 4;
1722 if (fabs(wlon) < 2 * reso || maxlat - minlat < 2 * reso)
1725 int npts = (int)(ceil(((
double)(maxlat - minlat) / reso)) *
1726 ceil(((
double)(wlon) / reso)));
1728 if (m_pModel->GetCurrentSelection() == COAMPS)
1729 npts = wxMin(npts, (
int)(ceil(40.0 / reso) * ceil(40.0 / reso)));
1732 int nbrec = (int)(time * 24 / inter) + 1;
1733 int nbPress = (m_pPress->IsChecked()) ? nbrec : 0;
1734 int nbWind = (m_pWind->IsChecked()) ? 2 * nbrec : 0;
1735 int nbwave = (m_pWaves->IsChecked()) ? 2 * nbrec : 0;
1736 int nbRain = (m_pRainfall->IsChecked()) ? nbrec - 1 : 0;
1737 int nbCloud = (m_pCloudCover->IsChecked()) ? nbrec - 1 : 0;
1738 int nbTemp = (m_pAirTemp->IsChecked()) ? nbrec : 0;
1739 int nbSTemp = (m_pSeaTemp->IsChecked()) ? nbrec : 0;
1740 int nbGUSTsfc = (m_pWindGust->IsChecked()) ? nbrec : 0;
1741 int nbCurrent = (m_pCurrent->IsChecked()) ? nbrec : 0;
1742 int nbCape = (m_pCAPE->IsChecked()) ? nbrec : 0;
1744 IsZYGRIB ? 5 * nbrec : 3 * nbrec;
1748 double estime = 0.0;
1752 estime += nbWind * (head + (nbits * npts) / 8 + 2);
1753 estime += nbCurrent * (head + (nbits * npts) / 8 + 2);
1756 estime += nbTemp * (head + (nbits * npts) / 8 + 2);
1757 estime += nbSTemp * (head + (nbits * npts) / 8 + 2);
1760 estime += nbRain * (head + (nbits * npts) / 8 + 2);
1763 estime += nbPress * (head + (nbits * npts) / 8 + 2);
1766 estime += nbCloud * (head + (nbits * npts) / 8 + 2);
1769 estime += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
1772 estime += nbCape * (head + (nbits * npts) / 8 + 2);
1775 estime += nbwave * (head + (nbits * npts) / 8 + 2);
1777 if (m_pAltitudeData->IsChecked()) {
1779 if (m_p850hpa->IsChecked()) nbalt++;
1780 if (m_p700hpa->IsChecked()) nbalt++;
1781 if (m_p500hpa->IsChecked()) nbalt++;
1782 if (m_p300hpa->IsChecked()) nbalt++;
1785 estime += nbAltitude * nbalt * (head + (nbits * npts) / 8 + 2);
1788 *size = estime / (1024. * 1024.);
1793const wxString EncodeURL(
const wxString &uri) {
1794 static std::unordered_map<int, wxString> sEncodeMap = {
1795 {(int)
'!',
"%21"}, {(int)
'#',
"%23"}, {(int)
'$',
"%24"},
1796 {(int)
'&',
"%26"}, {(int)
'\'',
"%27"}, {(int)
'(',
"%28"},
1797 {(int)
')',
"%29"}, {(int)
'*',
"%2A"}, {(int)
'+',
"%2B"},
1798 {(int)
',',
"%2C"}, {(int)
';',
"%3B"}, {(int)
'=',
"%3D"},
1799 {(int)
'?',
"%3F"}, {(int)
'@',
"%40"}, {(int)
'[',
"%5B"},
1800 {(int)
']',
"%5D"}, {(int)
' ',
"%20"}, {(int)
'|',
"%7C"},
1801 {(int)
':',
"%3A"}, {(int)
'\n',
"%0A"}};
1804 for (
size_t i = 0; i < uri.length(); ++i) {
1806 std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((
int)ch);
1807 if (iter != sEncodeMap.end()) {
1808 encoded << iter->second;
1817 StopGraphicalZoneSelection();
1824 m_MailImage->SetForegroundColour(
1828 m_MailImage->SetValue(WriteMail());
1829 SetRequestDialogSize();
1834 const wxString error[] = {
1836 _(
"Before sending an email to Zygrib you have to enter your Login and "
1837 "Code.\nPlease visit www.zygrib.org/ and follow instructions..."),
1838 _(
"Too big file! zyGrib limit is 2Mb!"),
1839 _(
"Error! Max Lat lower than Min Lat or Max Lon lower than Min Lon!"),
1840 _(
"Too large area! Each side must be less than 180\u00B0!"),
1841 _(
"Too small area for this resolution!")};
1843 ::wxBeginBusyCursor();
1845 m_MailImage->SetForegroundColour(wxColor(255, 0, 0));
1846 m_AllowSend =
false;
1848 if (m_MailError_Nb) {
1849 if (m_MailError_Nb > 7) {
1850 m_MailImage->SetValue(error[1] + error[0] + error[m_MailError_Nb - 6]);
1852 if (m_MailError_Nb == 6) m_MailError_Nb = 1;
1853 m_MailImage->SetValue(error[m_MailError_Nb]);
1857 SetRequestDialogSize();
1859 ::wxEndBusyCursor();
1864 std::string mailto =
1865 (m_pMailTo->GetCurrentSelection() == SAILDOCS
1866 ? m_MailToAddresses.BeforeFirst(
';')
1867 : m_MailToAddresses.AfterFirst(
';').BeforeFirst(
';'))
1869 std::string mailfrom = m_pSenderAddress->GetValue().ToStdString();
1871 std::regex mailregex(
"^([a-z0-9+_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$");
1873 if ((!mailto.empty() && !std::regex_match(mailto, mailregex)) ||
1874 (!mailfrom.empty() && !std::regex_match(mailfrom, mailregex))) {
1877 _(
"Sender or recipient e-mail address seems invalid.\nPlease correct "
1878 "it in the configuration file."),
1879 _(
"Error"), wxOK | wxICON_ERROR);
1889 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1893 EncodeURL(WriteMail()),
1897 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1906 if (mail.Send(*message, m_SendMethod)) {
1908 m_MailImage->SetValue(
1909 _(
"Your request is ready. An email is prepared in your email "
1910 "environment. \nYou have just to verify and send it...\nSave or "
1911 "Cancel to finish...or Continue..."));
1913 if (m_SendMethod == 0) {
1914 m_MailImage->SetValue(
1915 _(
"Your request is ready. An email is prepared in your email "
1916 "environment. \nYou have just to verify and send it...\nSave or "
1917 "Cancel to finish...or Continue..."));
1919 m_MailImage->SetValue(
1920 _(
"Your request was sent \n(if your system has an MTA configured and "
1921 "is able to send email).\nSave or Cancel to finish...or "
1926 m_MailImage->SetValue(
1927 _(
"Request can't be sent. Please verify your email systeme "
1928 "parameters.\nYou should also have a look at your log file.\nSave or "
1929 "Cancel to finish..."));
1933 SetRequestDialogSize();
1935 ::wxEndBusyCursor();
1940wxString GribRequestSetting::BuildXyGribUrl() {
1943 wxString::Format(
"http://grbsrv.opengribs.org/getmygribs2.php?");
1945 urlStr << wxString::Format(
"la1=%.0f", floor(
GetMinLat()));
1946 urlStr << wxString::Format(
"&la2=%.0f", ceil(
GetMaxLat()));
1947 urlStr << wxString::Format(
"&lo1=%.0f", floor(
GetMinLon()));
1948 urlStr << wxString::Format(
"&lo2=%.0f", ceil(
GetMaxLon()));
1951 urlStr << wxString::Format(
1953 xygribAtmModelList[m_selectedAtmModelIndex]
1954 ->reqName[m_xygribPanel->m_resolution_choice->GetSelection()]);
1956 urlStr << wxString::Format(
1958 xygribAtmModelList[m_selectedAtmModelIndex]
1959 ->interval[m_xygribPanel->m_interval_choice->GetSelection()]);
1961 urlStr << wxString::Format(
1962 "&days=%d", m_xygribPanel->m_duration_choice->GetSelection() + 1);
1966 wxString selStr = m_xygribPanel->m_run_choice->GetStringSelection();
1967 if (selStr.IsSameAs(
"18h",
false)) {
1968 urlStr <<
"&cyc=18";
1969 }
else if (selStr.IsSameAs(
"12h",
false)) {
1970 urlStr <<
"&cyc=12";
1971 }
else if (selStr.IsSameAs(
"6h",
false)) {
1972 urlStr <<
"&cyc=06";
1973 }
else if (selStr.IsSameAs(
"0h",
false)) {
1974 urlStr <<
"&cyc=00";
1976 urlStr <<
"&cyc=last";
1981 if (m_xygribPanel->m_wind_cbox->IsEnabled() &&
1982 m_xygribPanel->m_wind_cbox->IsChecked())
1984 if (m_xygribPanel->m_pressure_cbox->IsEnabled() &&
1985 m_xygribPanel->m_pressure_cbox->IsChecked()) {
1986 if (xygribAtmModelList[m_selectedAtmModelIndex]->altPressure) {
1992 if (m_xygribPanel->m_precipitation_cbox->IsEnabled() &&
1993 m_xygribPanel->m_precipitation_cbox->IsChecked())
1995 if (m_xygribPanel->m_cloudcover_cbox->IsEnabled() &&
1996 m_xygribPanel->m_cloudcover_cbox->IsChecked())
1998 if (m_xygribPanel->m_temperature_cbox->IsEnabled() &&
1999 m_xygribPanel->m_temperature_cbox->IsChecked())
2001 if (m_xygribPanel->m_cape_cbox->IsEnabled() &&
2002 m_xygribPanel->m_cape_cbox->IsChecked())
2004 if (m_xygribPanel->m_reflectivity_cbox->IsEnabled() &&
2005 m_xygribPanel->m_reflectivity_cbox->IsChecked())
2007 if (m_xygribPanel->m_gust_cbox->IsEnabled() &&
2008 m_xygribPanel->m_gust_cbox->IsChecked())
2012 if ((m_selectedWaveModelIndex >= 0) &&
2013 (xygribWaveModelList[m_selectedWaveModelIndex] !=
nullptr)) {
2014 wxString modelStr = wxString::Format(
2015 "&wmdl=%s", xygribWaveModelList[m_selectedWaveModelIndex]->reqName);
2016 wxString wParams =
"";
2017 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2020 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2021 wParams <<
"h;d;p;";
2023 if (wParams.length() > 0) {
2024 urlStr << wxString::Format(
"%s&wpar=%s", modelStr.c_str(),
2027 urlStr <<
"&wmdl=none";
2030 urlStr <<
"&wmdl=none";
2038wxString GribRequestSetting::BuildGribFileName() {
2039 wxString selStr = m_xygribPanel->m_resolution_choice->GetStringSelection();
2040 selStr.Replace(
".",
"P");
2043 if (m_selectedWaveModelIndex < 0) {
2044 fileName = wxString::Format(
2045 "XyGrib_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2046 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr);
2048 fileName = wxString::Format(
2049 "XyGrib_%s_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2050 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr,
2051 m_xygribPanel->m_wavemodel_choice->GetStringSelection());
2063void GribRequestSetting::OnXyGribDownloadButton(wxCommandEvent &event) {
2065 if (m_downloading) {
2069 m_downloading =
false;
2070 m_download_handle = 0;
2072 wxEVT_DOWNLOAD_EVENT,
2073 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2074 m_connected =
false;
2075 m_xygribPanel->m_progress_gauge->SetValue(0);
2076 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2077 m_xygribPanel->m_status_text->SetLabelText(_(
"Download cancelled"));
2080 EnableDownloadButtons();
2081 wxTheApp->ProcessPendingEvents();
2086 if (m_gribSizeEstimate > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB * 1024 * 1024) {
2087 m_xygribPanel->m_status_text->SetLabelText(
2088 wxString::Format(_(
"Can't download GRIB file bigger than %d MB"),
2089 (
int)XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB));
2095 MemorizeXyGribConfiguration();
2097 m_downloading =
true;
2099 EnableDownloadButtons();
2101 m_xygribPanel->m_download_button->SetLabelText(_(
"Cancel"));
2102 m_xygribPanel->m_status_text->SetLabelText(
2103 _(
"Preparing GRIB file on server..."));
2107 wxString requestUrl = BuildXyGribUrl();
2112 wxString filename = wxString::Format(
"ocpn_xygrib_%s.xml",
2113 wxDateTime::Now().Format(
"%F-%H-%M"));
2114 wxString path = m_parent.GetGribDir();
2115 path << wxFileName::GetPathSeparator();
2120 wxEVT_DOWNLOAD_EVENT,
2121 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2124 &m_download_handle);
2129 while (m_downloading) {
2130 wxTheApp->ProcessPendingEvents();
2134 if ((m_canceled) || (!m_bTransferSuccess)) {
2136 m_xygribPanel->m_status_text->SetLabelText(_(
"Grib request failed"));
2137 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2139 EnableDownloadButtons();
2147 bool readOk = xmlFile.Open(path);
2149 readOk &= xmlFile.ReadAll(&strXml);
2157 if (readOk && (((
int)strXml.find(
"\"status\":true") == wxNOT_FOUND))) {
2160 int errPos = strXml.find(
"\"message\":\"");
2161 int errEnd = strXml.find(
"\"}");
2162 if ((errPos != wxNOT_FOUND) && (errEnd != wxNOT_FOUND)) {
2164 errorStr = strXml.Mid(errPos, errEnd - errPos);
2166 errorStr =
"Unknown server error";
2169 m_xygribPanel->m_status_text->SetLabelText(
2170 wxString::Format(
"%s (%s)", _(
"Server Error"), errorStr));
2171 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2173 EnableDownloadButtons();
2178 int urlPos = strXml.find(
"\"url\":\"http:");
2179 int urlEnd = strXml.find(
".grb2\"");
2180 if ((urlPos != wxNOT_FOUND) && (urlEnd != wxNOT_FOUND)) {
2183 url = strXml.Mid(urlPos, urlEnd - urlPos);
2184 url.Replace(
"\\/",
"/");
2195 m_xygribPanel->m_status_text->SetLabelText(
2196 _(
"Error parsing XML file from server"));
2197 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2199 EnableDownloadButtons();
2203 m_xygribPanel->m_status_text->SetLabelText(_(
"Downloading GRIB file"));
2206 path = m_parent.GetGribDir();
2207 path << wxFileName::GetPathSeparator();
2208 path << BuildGribFileName();
2212 m_downloading =
true;
2216 wxEVT_DOWNLOAD_EVENT,
2217 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2223 while (m_downloading) {
2224 wxTheApp->ProcessPendingEvents();
2229 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2232 if (m_bTransferSuccess) {
2234 m_xygribPanel->m_status_text->SetLabelText(_(
"Download complete"));
2235 wxFileName fn(path);
2239 m_parent.OpenFile();
2241 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
2243 m_parent.SetDialogsStyleSizePosition(
true);
2248 m_xygribPanel->m_status_text->SetLabelText(_(
"Download failed"));
2252 EnableDownloadButtons();
2262 wxString atmModel = m_xygribPanel->m_atmmodel_choice->GetStringSelection();
2264 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2265 if (selectedAtmModel->name.IsSameAs(atmModel,
true)) {
2272 if (selectedAtmModel ==
nullptr) {
2273 selectedAtmModel = xygribAtmModelList[0];
2278 if (selectedAtmModel->wind)
2279 m_xygribPanel->m_wind_cbox->Enable();
2281 m_xygribPanel->m_wind_cbox->Disable();
2283 if (selectedAtmModel->gust)
2284 m_xygribPanel->m_gust_cbox->Enable();
2286 m_xygribPanel->m_gust_cbox->Disable();
2288 if (selectedAtmModel->pressure)
2289 m_xygribPanel->m_pressure_cbox->Enable();
2291 m_xygribPanel->m_pressure_cbox->Disable();
2293 if (selectedAtmModel->temperature)
2294 m_xygribPanel->m_temperature_cbox->Enable();
2296 m_xygribPanel->m_temperature_cbox->Disable();
2298 if (selectedAtmModel->cape)
2299 m_xygribPanel->m_cape_cbox->Enable();
2301 m_xygribPanel->m_cape_cbox->Disable();
2303 if (selectedAtmModel->reflectivity)
2304 m_xygribPanel->m_reflectivity_cbox->Enable();
2306 m_xygribPanel->m_reflectivity_cbox->Disable();
2308 if (selectedAtmModel->cloudCover)
2309 m_xygribPanel->m_cloudcover_cbox->Enable();
2311 m_xygribPanel->m_cloudcover_cbox->Disable();
2313 if (selectedAtmModel->precipitation)
2314 m_xygribPanel->m_precipitation_cbox->Enable();
2316 m_xygribPanel->m_precipitation_cbox->Disable();
2319 m_xygribPanel->m_resolution_choice->Clear();
2320 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2321 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2326 m_xygribPanel->m_duration_choice->Clear();
2327 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2328 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2332 m_xygribPanel->m_interval_choice->Clear();
2333 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2334 m_xygribPanel->m_interval_choice->Insert(
2335 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2339 m_xygribPanel->m_run_choice->Clear();
2340 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2341 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2342 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2343 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2345 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2346 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2347 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2348 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2349 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2352 if (modelIndex == m_parent.xyGribConfig.atmModelIndex) {
2353 ApplyXyGribConfiguration();
2355 m_selectedAtmModelIndex = modelIndex;
2356 m_xygribPanel->m_resolution_choice->SetSelection(0);
2357 m_xygribPanel->m_duration_choice->SetSelection(
2358 m_xygribPanel->m_duration_choice->GetCount() - 1);
2359 m_xygribPanel->m_interval_choice->SetSelection(0);
2360 m_xygribPanel->m_run_choice->SetSelection(
2361 m_xygribPanel->m_run_choice->GetCount() - 1);
2363 MemorizeXyGribConfiguration();
2373 wxString waveModel = m_xygribPanel->m_wavemodel_choice->GetStringSelection();
2375 while ((selectedModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2376 if (selectedModel->name.IsSameAs(waveModel,
true)) {
2383 if (selectedModel ==
nullptr) {
2385 m_selectedWaveModelIndex = -1;
2386 m_xygribPanel->m_waveheight_cbox->Disable();
2387 m_xygribPanel->m_windwave_cbox->Disable();
2388 MemorizeXyGribConfiguration();
2392 m_selectedWaveModelIndex = modelIndex;
2395 if (selectedModel->significantHeight) {
2396 m_xygribPanel->m_waveheight_cbox->Enable();
2398 m_xygribPanel->m_waveheight_cbox->Disable();
2401 if (selectedModel->windWaves) {
2402 m_xygribPanel->m_windwave_cbox->Enable();
2404 m_xygribPanel->m_windwave_cbox->Disable();
2406 MemorizeXyGribConfiguration();
2413 MemorizeXyGribConfiguration();
2417void GribRequestSetting::InitializeXygribDialog() {
2422 m_xygribPanel->m_atmmodel_choice->Clear();
2424 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2425 m_xygribPanel->m_atmmodel_choice->Insert(selectedAtmModel->name,
2430 m_selectedAtmModelIndex = m_parent.xyGribConfig.atmModelIndex;
2431 selectedAtmModel = xygribAtmModelList[m_selectedAtmModelIndex];
2434 m_xygribPanel->m_wavemodel_choice->Clear();
2436 while ((selectedWaveModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2437 m_xygribPanel->m_wavemodel_choice->Insert(selectedWaveModel->name,
2442 m_xygribPanel->m_wavemodel_choice->Insert(
"None", modelIndex);
2443 m_selectedWaveModelIndex = m_parent.xyGribConfig.waveModelIndex;
2444 selectedWaveModel = xygribWaveModelList[m_selectedWaveModelIndex];
2445 if (selectedWaveModel ==
nullptr) {
2446 m_selectedWaveModelIndex = -1;
2450 m_xygribPanel->m_resolution_choice->Clear();
2451 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2452 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2457 m_xygribPanel->m_duration_choice->Clear();
2458 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2459 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2463 m_xygribPanel->m_interval_choice->Clear();
2464 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2465 m_xygribPanel->m_interval_choice->Insert(
2466 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2470 m_xygribPanel->m_run_choice->Clear();
2471 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2472 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2473 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2474 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2476 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2477 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2478 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2479 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2480 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2483 if (selectedAtmModel->wind)
2484 m_xygribPanel->m_wind_cbox->Enable();
2486 m_xygribPanel->m_wind_cbox->Disable();
2488 if (selectedAtmModel->gust)
2489 m_xygribPanel->m_gust_cbox->Enable();
2491 m_xygribPanel->m_gust_cbox->Disable();
2493 if (selectedAtmModel->pressure)
2494 m_xygribPanel->m_pressure_cbox->Enable();
2496 m_xygribPanel->m_pressure_cbox->Disable();
2498 if (selectedAtmModel->temperature)
2499 m_xygribPanel->m_temperature_cbox->Enable();
2501 m_xygribPanel->m_temperature_cbox->Disable();
2503 if (selectedAtmModel->cape)
2504 m_xygribPanel->m_cape_cbox->Enable();
2506 m_xygribPanel->m_cape_cbox->Disable();
2508 if (selectedAtmModel->reflectivity)
2509 m_xygribPanel->m_reflectivity_cbox->Enable();
2511 m_xygribPanel->m_reflectivity_cbox->Disable();
2513 if (selectedAtmModel->cloudCover)
2514 m_xygribPanel->m_cloudcover_cbox->Enable();
2516 m_xygribPanel->m_cloudcover_cbox->Disable();
2518 if (selectedAtmModel->precipitation)
2519 m_xygribPanel->m_precipitation_cbox->Enable();
2521 m_xygribPanel->m_precipitation_cbox->Disable();
2523 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->significantHeight))
2524 m_xygribPanel->m_waveheight_cbox->Enable();
2526 m_xygribPanel->m_waveheight_cbox->Disable();
2528 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->windWaves))
2529 m_xygribPanel->m_windwave_cbox->Enable();
2531 m_xygribPanel->m_windwave_cbox->Disable();
2533 ApplyXyGribConfiguration();
2540void GribRequestSetting::ApplyXyGribConfiguration() {
2541 m_xygribPanel->m_atmmodel_choice->SetSelection(
2542 m_parent.xyGribConfig.atmModelIndex);
2543 m_xygribPanel->m_wavemodel_choice->SetSelection(
2544 m_parent.xyGribConfig.waveModelIndex);
2546 m_xygribPanel->m_wind_cbox->SetValue(m_parent.xyGribConfig.wind);
2547 m_xygribPanel->m_gust_cbox->SetValue(m_parent.xyGribConfig.gust);
2548 m_xygribPanel->m_pressure_cbox->SetValue(m_parent.xyGribConfig.pressure);
2549 m_xygribPanel->m_temperature_cbox->SetValue(
2550 m_parent.xyGribConfig.temperature);
2551 m_xygribPanel->m_cape_cbox->SetValue(m_parent.xyGribConfig.cape);
2552 m_xygribPanel->m_reflectivity_cbox->SetValue(
2553 m_parent.xyGribConfig.reflectivity);
2554 m_xygribPanel->m_cloudcover_cbox->SetValue(m_parent.xyGribConfig.cloudCover);
2555 m_xygribPanel->m_precipitation_cbox->SetValue(
2556 m_parent.xyGribConfig.precipitation);
2557 m_xygribPanel->m_waveheight_cbox->SetValue(m_parent.xyGribConfig.waveHeight);
2558 m_xygribPanel->m_windwave_cbox->SetValue(m_parent.xyGribConfig.windWaves);
2559 m_xygribPanel->m_resolution_choice->SetSelection(
2560 m_parent.xyGribConfig.resolutionIndex);
2561 m_xygribPanel->m_duration_choice->SetSelection(
2562 m_parent.xyGribConfig.durationIndex);
2563 m_xygribPanel->m_interval_choice->SetSelection(
2564 m_parent.xyGribConfig.intervalIndex);
2565 m_xygribPanel->m_run_choice->SetSelection(m_parent.xyGribConfig.runIndex);
2567 UpdateGribSizeEstimate();
2574void GribRequestSetting::MemorizeXyGribConfiguration() {
2575 m_parent.xyGribConfig.atmModelIndex =
2576 m_xygribPanel->m_atmmodel_choice->GetSelection();
2577 m_parent.xyGribConfig.waveModelIndex =
2578 m_xygribPanel->m_wavemodel_choice->GetSelection();
2580 m_parent.xyGribConfig.wind = m_xygribPanel->m_wind_cbox->IsChecked();
2581 m_parent.xyGribConfig.gust = m_xygribPanel->m_gust_cbox->IsChecked();
2582 m_parent.xyGribConfig.pressure = m_xygribPanel->m_pressure_cbox->IsChecked();
2583 m_parent.xyGribConfig.temperature =
2584 m_xygribPanel->m_temperature_cbox->IsChecked();
2585 m_parent.xyGribConfig.cape = m_xygribPanel->m_cape_cbox->IsChecked();
2586 m_parent.xyGribConfig.reflectivity =
2587 m_xygribPanel->m_reflectivity_cbox->IsChecked();
2588 m_parent.xyGribConfig.cloudCover =
2589 m_xygribPanel->m_cloudcover_cbox->IsChecked();
2590 m_parent.xyGribConfig.precipitation =
2591 m_xygribPanel->m_precipitation_cbox->IsChecked();
2592 m_parent.xyGribConfig.waveHeight =
2593 m_xygribPanel->m_waveheight_cbox->IsChecked();
2594 m_parent.xyGribConfig.windWaves = m_xygribPanel->m_windwave_cbox->IsChecked();
2596 m_parent.xyGribConfig.resolutionIndex =
2597 m_xygribPanel->m_resolution_choice->GetSelection();
2598 m_parent.xyGribConfig.durationIndex =
2599 m_xygribPanel->m_duration_choice->GetSelection();
2600 m_parent.xyGribConfig.intervalIndex =
2601 m_xygribPanel->m_interval_choice->GetSelection();
2602 m_parent.xyGribConfig.runIndex = m_xygribPanel->m_run_choice->GetSelection();
2604 UpdateGribSizeEstimate();
2610void GribRequestSetting::UpdateGribSizeEstimate() {
2615 if (!m_xygribPanel->m_resolution_choice->GetStringSelection().ToCDouble(
2617 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2620 if (!m_xygribPanel->m_duration_choice->GetStringSelection().ToCLong(&days)) {
2621 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2624 wxString intvStr = m_xygribPanel->m_interval_choice->GetStringSelection();
2625 intvStr.Replace(
"h",
"");
2626 if (!intvStr.ToCLong(&interval)) {
2627 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2632 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2641 int npts = (int)(ceil(fabs(xmax - xmin) / resolution) *
2642 ceil(fabs(ymax - ymin) / resolution));
2645 int nbrec = (int)days * 24 / interval + 1;
2647 int nbPress = (m_xygribPanel->m_pressure_cbox->IsChecked() &&
2648 m_xygribPanel->m_pressure_cbox->IsEnabled())
2651 int nbWind = (m_xygribPanel->m_wind_cbox->IsChecked() &&
2652 m_xygribPanel->m_wind_cbox->IsEnabled())
2655 int nbRain = (m_xygribPanel->m_precipitation_cbox->IsChecked() &&
2656 m_xygribPanel->m_precipitation_cbox->IsEnabled())
2659 int nbCloud = (m_xygribPanel->m_cloudcover_cbox->IsChecked() &&
2660 m_xygribPanel->m_cloudcover_cbox->IsEnabled())
2663 int nbTemp = (m_xygribPanel->m_temperature_cbox->IsChecked() &&
2664 m_xygribPanel->m_temperature_cbox->IsEnabled())
2668 int nbCAPEsfc = (m_xygribPanel->m_cape_cbox->IsChecked() &&
2669 m_xygribPanel->m_cape_cbox->IsEnabled())
2672 int nbReflectivity = (m_xygribPanel->m_reflectivity_cbox->IsChecked() &&
2673 m_xygribPanel->m_reflectivity_cbox->IsEnabled())
2676 int nbGUSTsfc = (m_xygribPanel->m_gust_cbox->IsChecked() &&
2677 m_xygribPanel->m_gust_cbox->IsEnabled())
2687 estimate += nbWind * (head + (nbits * npts) / 8 + 2);
2690 estimate += nbTemp * (head + (nbits * npts) / 8 + 2);
2696 estimate += nbRain * (head + 24 + (nbits * npts) / 8 + 2);
2699 estimate += nbPress * (head + (nbits * npts) / 8 + 2);
2702 estimate += nbCloud * (head + 24 + (nbits * npts) / 8 + 2);
2705 estimate += nbReflectivity * (head + (nbits * npts) / 8 + 2);
2708 estimate += nbCAPEsfc * (head + (nbits * npts) / 8 + 2);
2711 estimate += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
2715 int atmEstimate = estimate;
2719 if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2722 npts = (int)(ceil(fabs(xmax - xmin) / 0.5) * ceil(fabs(ymax - ymin) / 0.5));
2723 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2724 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2728 (int)(ceil(fabs(xmax - xmin) / 0.25) * ceil(fabs(ymax - ymin) / 0.25));
2729 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2730 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2734 (int)(ceil(fabs(xmax - xmin) / 0.05) * ceil(fabs(ymax - ymin) / 0.1));
2735 nbrec = (int)fmin(4, days) * 24 / interval + 1;
2741 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2743 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2746 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2748 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2750 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2752 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2755 int wavEstimate = estimate - atmEstimate;
2757 wavEstimate = wavEstimate * 0.6;
2759 estimate = atmEstimate + wavEstimate;
2762 estimate = estimate * 0.65;
2764 wxString warningStr =
"";
2765 if (estimate / (1024 * 1024) > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB) {
2766 warningStr = wxString::Format(
"(Warning GRIB exceeds %d MB limit)",
2767 XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB);
2770 m_xygribPanel->m_sizeestimate_text->SetLabel(
2771 wxString::Format(
"%d kB %s", estimate / 1024, warningStr));
2773 m_gribSizeEstimate = estimate;
void SetRequestButtonBitmap(int type)
Set the icon and tooltip for the download request button.
GribPi * pPlugIn
Plugin instance that owns this control bar.
wxString m_grib_dir
Directory containing GRIB files.
wxArrayString m_file_names
List of GRIB filenames being displayed.
Class GribRequestSettingBase.
wxButton * m_rButtonCancel
Button to Cancel a request to download, close the dialog without saving the configuration.
wxSpinCtrl * m_spMaxLon
A spinner for the max longitude of the bounding box for downloads.
wxSpinCtrl * m_spMaxLat
A spinner for the max latitude of the bounding box for downloads.
wxRadioButton * m_rbManualSelect
Radio button selected to indicate the download area is based on the area selected by the user.
wxRadioButton * m_rbCurrentView
Radio button selected to indicate the download area is based on the visible area of the chart in the ...
wxSpinCtrl * m_spMinLat
A spinner for the min latitude of the bounding box for downloads.
wxButton * m_rButtonApply
Button to Save the "download request" configuration.
wxButton * m_rButtonYes
Button to Send a download request through e-mail.
wxSpinCtrl * m_spMinLon
A spinner for the min longitude of the bounding box for downloads.
Manages GRIB file request configuration and downloads.
double m_StartLat
The latitude at the starting point of the bounding box.
void OnXyGribWaveModelChoice(wxCommandEvent &event) override
Handle action of changing wave model selection.
void OnSendMaiL(wxCommandEvent &event) override
Callback invoked when the user clicks the "Send" button in the "e-mail" tab.
double GetMinLat() const
Get the minimum latitude of the bounding box for the download request.
double GetMaxLat() const
Get the maximum latitude of the bounding box for the download request.
double m_Lat
The latitude at the mouse cursor while drawing a bounding box.
void OnVpUnderMouseChange(PlugIn_ViewPort *vp)
Callback invoked when the view port under mouse has changed.
bool RenderGlZoneOverlay()
Renders the GRIB area selection overlay using OpenGL.
bool RenderZoneOverlay(wxDC &dc)
Renders the GRIB area selection overlay using standard device context.
double m_Lon
The longitude at the mouse cursor while drawing a bounding box.
void OnXyGribAtmModelChoice(wxCommandEvent &event) override
Handle action of changing atmospheric model selection.
wxPoint m_StartPoint
Starting point of the bounding box in physical pixels.
bool DoRenderZoneOverlay()
Draws the GRIB area selection overlay on the chart.
bool MouseEventHook(wxMouseEvent &event)
Intercepts mouse events to handle GRIB area selection.
void OnVpWithFocusChange(PlugIn_ViewPort *vp)
Callback invoked when the focused view port has changed, such as in multi-chart mode when user switch...
PlugIn_ViewPort * m_VpMouse
The viewport under the mouse.
ZoneSelectionRenderState m_RenderSelectionZoneState
Current state of the bounding box overlay rendering.
void OnXyGribConfigChange(wxCommandEvent &event) override
Handle action of changing a GRIB configuration parameter.
double GetMaxLon() const
Get the maximum longitude of the bounding box for the download request.
PlugIn_ViewPort * m_VpFocus
The viewport currently in focus.
double m_StartLon
The longitude at the starting point of the bounding box.
double GetMinLon() const
Get the minimum longitude of the bounding box for the download request.
void OnOK(wxCommandEvent &event) override
Callback invoked when the user clicks the "OK" button in the "download" dialog.
Contains view parameters and status information for a chart display viewport.
double lon_max
Maximum longitude of the viewport.
double lat_max
Maximum latitude of the viewport.
double lon_min
Minimum longitude of the viewport.
double lat_min
Minimum latitude of the viewport.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
int Size() const
Return the size of the array or map stored in this value.
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
wxString AsString() const
Return the stored value as a wxWidget's string.
Email Request System for GRIB Data.
GRIB Data Visualization and Rendering Factory.
GRIB Weather Data Plugin for OpenCPN.
int m_SavedZoneSelMode
Persisted version of the GRIB area selection mode.
int m_ZoneSelMode
Tracks the current state of GRIB area selection for zone coordinates.
GRIB Weather Data Request and Download Management.
@ WORLD
Global forecast downloads (e.g., GFS)
@ XYGRIB
Downloads from XyGrib service.
@ NONE
No download source selected.
@ LOCAL_CATALOG
Downloads from configured catalogs.
@ LOCAL
Downloads from local sources.
@ AUTO_SELECTION
Area automatically set from current viewport bounds.
@ DRAW_SELECTION
Manual mode has been selected.
@ START_SELECTION
User has clicked Shift + Left click and is drawing the bounding box by dragging the mouse.
@ COMPLETE_SELECTION
Selection box completed in manual mode, coordinates have been captured after the user has released th...
@ SAVED_SELECTION
Area loaded from previously saved coordinates.
#define SAVEDZONE
Save zone.
#define MANSELECT
Manual selection mode.
#define AUTOSELECT
Automatic selection mode.
@ OCPN_DL_EVENT_TYPE_PROGRESS
Download progress update.
@ OCPN_DL_EVENT_TYPE_END
Download has completed.
@ OCPN_DL_NO_ERROR
Download completed successfully.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
wxFileConfig * GetOCPNConfigObject()
Gets OpenCPN's configuration object.
void GetCanvasPixLL(PlugIn_ViewPort *vp, wxPoint *pp, double lat, double lon)
Converts lat/lon to canvas physical pixel coordinates.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
int GetCanvasIndexUnderMouse()
Gets index of chart canvas under mouse cursor.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
void RequestRefresh(wxWindow *win)
Requests window refresh.
void GetCanvasLLPix(PlugIn_ViewPort *vp, wxPoint p, double *plat, double *plon)
Converts canvas physical pixel coordinates to lat/lon.
OpenGL Platform Abstraction Layer.
void OCPN_cancelDownloadFileBackground(long handle)
Cancels a background download.
int OCPNMessageBox_PlugIn(wxWindow *parent, const wxString &message, const wxString &caption, int style, int x, int y)
Shows a message box dialog.
_OCPN_DLStatus OCPN_downloadFileBackground(const wxString &url, const wxString &outputFile, wxEvtHandler *handler, long *handle)
Asynchronously downloads a file in the background.
XyGrib Model Configuration and Definitions.