25#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
37#include <wx/wfstream.h>
40#include <unordered_map>
46enum { SAILDOCS, ZYGRIB };
47enum { GFS, COAMPS, RTOFS, HRRR, ICON, ECMWF };
49wxString toMailFormat(
int NEflag,
52 char c = NEflag == 1 ? a < 0 ?
'S' :
'N' : a < 0 ?
'W' :
'E';
54 s.Printf(_T (
"%01d%c" ), abs(a), c);
69 m_boundingBoxCanvasIndex = -1;
72#if defined(__WXOSX__) || defined(__WXGTK3__)
74 m_displayScale = GetContentScaleFactor();
79 m_downloading =
false;
80 m_bTransferSuccess =
true;
83 auto bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)
84 .GetAsString(wxC2S_HTML_SYNTAX);
85 auto fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)
86 .GetAsString(wxC2S_HTML_SYNTAX);
87 m_htmlWinWorld->SetBorders(10);
88 m_htmlWinWorld->SetPage(
89 "<html><body bgcolor="
98 _(
"<h1>OpenCPN ECMWF forecast</h1>"
99 "<p>Free service based on ECMWF Open Data published under the terms of "
100 "Creative Commons CC-4.0-BY license</p>"
101 "<p>The IFS model GRIB files include information about surface "
103 "atmospheric pressure, wind strength, wind direction, wave height and "
104 "direction for the whole world on a 0.25 degree resolution "
106 "step in the first 144 hours and 6 hour step up to 10 days.</p>"
107 "The AIFS model contains data for wind, pressure and temperature on a "
108 "0.25 degree grid with 6 hour step for up to 15 days"
109 "<p>The data is updated twice a day as soon as the 00z and 12z model "
110 "runs finish and the "
111 "results are published by ECMWF, which usually means new forecast data "
112 "is available shortly after 8AM and 8PM UTC.</p>"
113 "<p>The grib downloaded covers the area of the primary chart "
115 "<p>The service is provided on best effort basis and comes with no "
116 "guarantees. The server is hosted by a volunteer and the service is "
117 "provided free of charge and without accepting any liability "
118 "whatsoever for its continuous availability, or for any loss or damage "
119 "arising from its use. If you find the service useful, please "
120 "consider making a donation to the OpenCPN project.</p>"
121 "<p>This service is based on data and products of the European Centre "
122 "for Medium-Range Weather Forecasts (ECMWF).</p>"
123 "<p>Source: www.ecmwf.int</p>"
124 "<p>Disclaimer: ECMWF does not accept any liability whatsoever for any "
125 "error or omission in the data, their availability, or for any loss or "
126 "damage arising from their use.</p>"
127 "</font></body></html>"));
128 m_htmlInfoWin->SetBorders(10);
129 m_htmlInfoWin->SetPage(
130 "<html><body bgcolor="
139 _(
"<h1>Grib weather forecasts</h1>"
140 "<p>Collection of local weather models from various sources available "
141 "for download over the internet.</p>"
142 "</font></body></html>"));
144 m_bLocal_source_selected =
false;
145 EnableDownloadButtons();
147 m_selectedAtmModelIndex = 0;
148 m_selectedWaveModelIndex = 0;
149 InitializeXygribDialog();
152GribRequestSetting::~GribRequestSetting() {
158 wxEVT_DOWNLOAD_EVENT,
159 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
168void GribRequestSetting::SaveConfig() {
171 pConf->SetPath(_T(
"/PlugIns/GRIB" ));
173 pConf->Write(_T (
"MailRequestConfig" ), m_RequestConfigBase);
174 pConf->Write(_T(
"MailSenderAddress" ), m_pSenderAddress->GetValue());
175 pConf->Write(_T(
"MailRequestAddresses" ), m_MailToAddresses);
176 pConf->Write(_T(
"ZyGribLogin" ), m_pLogin->GetValue());
177 pConf->Write(_T(
"ZyGribCode" ), m_pCode->GetValue());
178 pConf->Write(_T(
"SendMailMethod" ), m_SendMethod);
179 pConf->Write(_T(
"MovingGribSpeed" ), m_sMovingSpeed->GetValue());
180 pConf->Write(_T(
"MovingGribCourse" ), m_sMovingCourse->GetValue());
185 pConf->Write(_T(
"ManualRequestZoneSizingMode" ),
m_ZoneSelMode);
188 pConf->Write(_T(
"RequestZoneMaxLat" ),
m_spMaxLat->GetValue());
189 pConf->Write(_T(
"RequestZoneMinLat" ),
m_spMinLat->GetValue());
190 pConf->Write(_T(
"RequestZoneMaxLon" ),
m_spMaxLon->GetValue());
191 pConf->Write(_T(
"RequestZoneMinLon" ),
m_spMinLon->GetValue());
195void GribRequestSetting::InitRequestConfig() {
199 pConf->SetPath(_T(
"/PlugIns/GRIB" ));
202 pConf->Read(_T(
"MailRequestConfig" ), &m_RequestConfigBase,
203 _T(
"000220XX........0" ));
204 pConf->Read(_T(
"MailSenderAddress" ), &l, _T(
""));
205 m_pSenderAddress->ChangeValue(l);
206 pConf->Read(_T(
"MailRequestAddresses" ), &m_MailToAddresses,
207 _T(
"query@saildocs.com;gribauto@zygrib.org"));
208 pConf->Read(_T(
"ZyGribLogin" ), &l, _T(
""));
209 m_pLogin->ChangeValue(l);
210 pConf->Read(_T(
"ZyGribCode" ), &l, _T(
""));
211 m_pCode->ChangeValue(l);
212 pConf->Read(_T(
"SendMailMethod" ), &m_SendMethod, 0);
213 pConf->Read(_T(
"MovingGribSpeed" ), &m, 0);
214 m_sMovingSpeed->SetValue(m);
215 pConf->Read(_T(
"MovingGribCourse" ), &m, 0);
216 m_sMovingCourse->SetValue(m);
217 pConf->Read(_T(
"ManualRequestZoneSizingMode" ), &m, 0);
219 pConf->Read(_T(
"ManualRequestZoneSizing" ), &m, 0);
226 UpdateAreaSelectionState();
227 pConf->Read(_T(
"RequestZoneMaxLat" ), &m, 0);
229 pConf->Read(_T(
"RequestZoneMinLat" ), &m, 0);
231 pConf->Read(_T(
"RequestZoneMaxLon" ), &m, 0);
233 pConf->Read(_T(
"RequestZoneMinLon" ), &m, 0);
236 SetCoordinatesText();
239 if (m_RequestConfigBase.Len() !=
240 wxString(_T(
"000220XX.............." )).Len())
241 m_RequestConfigBase = _T(
"000220XX.............." );
244 wxString s1[] = {_T(
"GFS"), _T(
"COAMPS"), _T(
"RTOFS"),
245 _T(
"HRRR"), _T(
"ICON"), _T(
"ECMWF")};
246 for (
unsigned int i = 0; i < (
sizeof(s1) /
sizeof(wxString)); i++)
247 m_pModel->Append(s1[i]);
248 wxString s2[] = {_T(
"Saildocs"), _T(
"zyGrib")};
249 for (
unsigned int i = 0; i < (
sizeof(s2) /
sizeof(wxString)); i++)
250 m_pMailTo->Append(s2[i]);
251 wxString s3[] = {_T(
"WW3-GLOBAL"), _T(
"WW3-MEDIT")};
252 for (
unsigned int i = 0; i < (
sizeof(s3) /
sizeof(wxString)); i++)
253 m_pWModel->Append(s3[i]);
256 m_tResUnit->SetLabel(wxString::Format(_T(
"\u00B0")));
257 m_sCourseUnit->SetLabel(wxString::Format(_T(
"\u00B0")));
261 GetTextExtent(_T(
"-360"), &w, &h, 0, 0,
265 m_sMovingSpeed->SetMinSize(wxSize(w, h));
266 m_sMovingCourse->SetMinSize(wxSize(w, h));
273 m_pSenderAddress->SetToolTip(
274 _(
"Address used to send request eMail. (Mandatory for LINUX)"));
275 m_pLogin->SetToolTip(_(
"This is your zyGrib's forum access Login"));
277 _(
"Get this Code in zyGrib's forum ( This is not your password! )"));
278 m_sMovingSpeed->SetToolTip(_(
"Enter your forescasted Speed (in Knots)"));
279 m_sMovingCourse->SetToolTip(_(
"Enter your forecasted Course"));
282 ((wxString)m_RequestConfigBase.GetChar(0)).ToLong(&i);
283 m_pMailTo->SetSelection(i);
284 ((wxString)m_RequestConfigBase.GetChar(1)).ToLong(&i);
285 m_pModel->SetSelection(i);
286 m_cMovingGribEnabled->SetValue(m_RequestConfigBase.GetChar(16) ==
288 ((wxString)m_RequestConfigBase.GetChar(2)).ToLong(&i);
289 ((wxString)m_RequestConfigBase.GetChar(3)).ToLong(&j);
290 ((wxString)m_RequestConfigBase.GetChar(4)).ToLong(&k, 16);
294 m_pSenderSizer->ShowItems(
false);
296 if (m_SendMethod == 0)
297 m_pSenderSizer->ShowItems(
false);
299 m_pSenderSizer->ShowItems(
303 m_tMouseEventTimer.Connect(
304 wxEVT_TIMER, wxTimerEventHandler(GribRequestSetting::OnMouseEventTimer),
309 ApplyRequestConfig(i, j, k);
311 ((wxString)m_RequestConfigBase.GetChar(5)).ToLong(&j);
312 m_pWModel->SetSelection(j);
314 m_pWind->Enable(
false);
315 m_pPress->Enable(
false);
320 m_MailImage->SetValue(WriteMail());
323wxWindow *GetGRIBCanvas();
324void GribRequestSetting::OnClose(wxCloseEvent &event) {
327 m_downloading =
false;
328 m_download_handle = 0;
332 wxEVT_DOWNLOAD_EVENT,
333 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
342 m_parent.m_highlight_latmax = 0;
343 m_parent.m_highlight_lonmax = 0;
344 m_parent.m_highlight_latmin = 0;
345 m_parent.m_highlight_lonmin = 0;
349void GribRequestSetting::SetRequestDialogSize() {
352 GetTextExtent(_T(
"abc"),
nullptr, &y, 0, 0,
OCPNGetFont(_(
"Dialog")));
353 m_MailImage->SetMinSize(
354 wxSize(-1, ((y * m_MailImage->GetNumberOfLines()) + 10)));
358 m_fgScrollSizer->Fit(m_sScrolledDialog);
361 SetMinSize(wxSize(0, 0));
364 wxWindow *frame = wxTheApp->GetTopWindow();
366 int w = frame->GetClientSize().x;
367 int h = frame->GetClientSize().y;
373 m_sScrolledDialog->SetMinSize(
374 wxSize(wxMin(w, scroll.x),
375 wxMin(h, scroll.y)));
380 wxSize sd = GetSize();
381 if (sd.y == GetClientSize().y) sd.y += 30;
382 SetSize(wxSize(sd.x, sd.y));
383 SetMinSize(wxSize(sd.x, sd.y));
391 if ((fabs(vp->
lat_max) < 90.) && (fabs(lonmax) < 360.)) {
392 if (lonmax < -180.) lonmax += 360.;
393 if (lonmax > 180.) lonmax -= 360.;
395 if ((fabs(vp->
lat_min) < 90.) && (fabs(lonmin) < 360.)) {
396 if (lonmin < -180.) lonmin += 360.;
397 if (lonmin > 180.) lonmin -= 360.;
400 bool bnew_val =
false;
402 if (
m_spMinLon->GetValue() != (
int)floor(lonmin)) bnew_val =
true;
404 if (
m_spMaxLon->GetValue() != (
int)ceil(lonmax)) bnew_val =
true;
412 SetCoordinatesText();
413 m_MailImage->SetValue(WriteMail());
418 if (!(event.ShiftDown() || m_bpManualSelection->GetValue())) {
423 if (event.LeftDown() && !event.Dragging()) {
438 int xm =
event.GetX() * m_displayScale;
439 int ym =
event.GetY() * m_displayScale;
441 if (event.LeftDown() && !event.Dragging()) {
442 m_parent.pParent->SetFocus();
455 SetCoordinatesText();
456 UpdateAreaSelectionState();
457 m_MailImage->SetValue(WriteMail());
460 UpdateGribSizeEstimate();
461 m_boundingBoxCanvasIndex = -1;
462 }
else if (event.Dragging()) {
477 if (!m_tMouseEventTimer.IsRunning())
478 m_tMouseEventTimer.Start(20, wxTIMER_ONE_SHOT);
483void GribRequestSetting::OnMouseEventTimer(wxTimerEvent &event) {
505void GribRequestSetting::SetCoordinatesText() {
506 m_stMaxLatNS->SetLabel(
m_spMaxLat->GetValue() < 0 ? _(
"S") : _(
"N"));
507 m_stMinLonEW->SetLabel(
m_spMinLon->GetValue() < 0 ? _(
"W") : _(
"E"));
508 m_stMaxLonEW->SetLabel(
m_spMaxLon->GetValue() < 0 ? _(
"W") : _(
"E"));
509 m_stMinLatNS->SetLabel(
m_spMinLat->GetValue() < 0 ? _(
"S") : _(
"N"));
512size_t LengthSelToHours(
int sel) {
524std::string GribRequestSetting::FormatPerLocale(T value) {
525 std::stringstream ss;
527 ss.imbue(std::locale(
""));
532wxString GribRequestSetting::GetDownloadProgressText(
long transferredBytes,
534 if (totalBytes > 0) {
535 return wxString::Format(_(
"Downloading... %s kB / %s kB (%li%%)"),
536 FormatPerLocale(transferredBytes / 1024).c_str(),
537 FormatPerLocale(totalBytes / 1024).c_str(),
538 (
int)((
double)transferredBytes / totalBytes * 100));
540 return wxString::Format(_(
"Downloading... %s kB / ???"),
541 FormatPerLocale(transferredBytes / 1024).c_str());
548 switch (ev.getDLEventCondition()) {
552 Disconnect(wxEVT_DOWNLOAD_EVENT,
556 m_downloading =
false;
557 m_download_handle = 0;
562 switch (m_downloadType) {
564 m_staticTextInfo->SetLabelText(
565 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
569 m_stLocalDownloadInfo->SetLabelText(
570 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
575 m_xygribPanel->m_progress_gauge->SetValue(
576 100 * ev.getTransferred() / ev.getTotal());
579 m_xygribPanel->m_status_text->SetLabel(
580 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
592void GribRequestSetting::OnWorldDownload(wxCommandEvent &event) {
595 m_downloading =
false;
596 m_download_handle = 0;
598 wxEVT_DOWNLOAD_EVENT,
599 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
601 m_btnDownloadWorld->SetLabelText(_(
"Download"));
602 m_staticTextInfo->SetLabelText(_(
"Download canceled"));
605 EnableDownloadButtons();
606 wxTheApp->ProcessPendingEvents();
611 m_downloading =
true;
613 EnableDownloadButtons();
614 m_btnDownloadWorld->SetLabelText(_(
"Cancel"));
615 m_staticTextInfo->SetLabelText(_(
"Preparing data on server..."));
618 switch (m_chECMWFResolution->GetSelection()) {
623 model =
"ecmwfaifs0p25";
629 std::ostringstream oss;
630 oss <<
"https://grib.bosun.io/grib?";
631 oss <<
"model=" << model;
636 oss <<
"&length=" << LengthSelToHours(m_chForecastLength->GetSelection());
638 wxString::Format(
"ocpn_%s_%li_%s.grb2", model.c_str(),
639 LengthSelToHours(m_chForecastLength->GetSelection()),
640 wxDateTime::Now().Format(
"%F-%H-%M"));
641 wxString path = m_parent.GetGribDir();
642 path.Append(wxFileName::GetPathSeparator());
643 path.Append(filename);
647 wxEVT_DOWNLOAD_EVENT,
648 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
652 while (m_downloading) {
653 wxTheApp->ProcessPendingEvents();
657 if (m_bTransferSuccess) {
658 m_staticTextInfo->SetLabelText(
659 wxString::Format(_(
"Download complete: %s"), path.c_str()));
666 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
668 m_parent.SetDialogsStyleSizePosition(
true);
672 m_staticTextInfo->SetLabelText(_(
"Download failed"));
675 m_btnDownloadWorld->SetLabelText(_(
"Download"));
677 EnableDownloadButtons();
680enum LocalSourceItem { SOURCE, AREA, GRIB };
682enum LocalGribDownloadType { DIRECT, MANIFEST, WEBPAGE };
685 GribCatalogInfo(LocalSourceItem type, wxString name, wxString description,
686 wxString url, wxString filename,
687 LocalGribDownloadType download_type,
double latmin,
688 double lonmin,
double latmax,
double lonmax)
691 description(description),
694 download_type(download_type),
699 LocalSourceItem type;
701 wxString description;
704 LocalGribDownloadType download_type;
711void GribRequestSetting::FillTreeCtrl(
wxJSONValue &data) {
712 m_SourcesTreeCtrl1->DeleteAllItems();
714 m_SourcesTreeCtrl1->AddRoot(_(
"Local high resolution forecasts"));
715 if (data.HasMember(
"sources") && data[
"sources"].IsArray()) {
716 for (
int i = 0; i < data[
"sources"].Size(); i++) {
719 LocalSourceItem::SOURCE, source[
"source"].AsString(),
720 source[
"description"].AsString(), source[
"url"].AsString(),
721 wxEmptyString, LocalGribDownloadType::WEBPAGE, 0, 0, 0, 0);
722 wxTreeItemId src_id = m_SourcesTreeCtrl1->AppendItem(
723 root, source[
"source"].AsString(), -1, -1, info);
724 if (source.
HasMember(
"areas") && source[
"areas"].IsArray()) {
725 for (
int j = 0; j < source[_T(
"areas")].
Size(); j++) {
728 LocalSourceItem::AREA, area[
"name"].AsString(),
729 source[
"description"].AsString(), source[
"url"].AsString(),
730 wxEmptyString, LocalGribDownloadType::WEBPAGE,
731 area[
"boundary"][
"lat_min"].AsDouble(),
732 area[
"boundary"][
"lon_min"].AsDouble(),
733 area[
"boundary"][
"lat_max"].AsDouble(),
734 area[
"boundary"][
"lon_max"].AsDouble());
735 m_SourcesTreeCtrl1->AppendItem(src_id, area[
"name"].AsString(), -1,
737 if (area.
HasMember(
"gribs") && area[
"gribs"].IsArray()) {
738 for (
int k = 0; k < area[
"gribs"].
Size(); k++) {
741 LocalSourceItem::GRIB, grib[
"name"].AsString(),
742 source[
"description"].AsString(),
743 grib.
HasMember(
"url") ? grib[
"url"].AsString()
744 : grib[
"cat_url"].AsString(),
745 grib.HasMember(
"filename") ? grib[
"filename"].AsString() :
"",
746 grib.HasMember(
"url") ? LocalGribDownloadType::DIRECT
747 : LocalGribDownloadType::MANIFEST,
748 area[
"boundary"][
"lat_min"].AsDouble(),
749 area[
"boundary"][
"lon_min"].AsDouble(),
750 area[
"boundary"][
"lat_max"].AsDouble(),
751 area[
"boundary"][
"lon_max"].AsDouble());
752 m_SourcesTreeCtrl1->AppendItem(
753 m_SourcesTreeCtrl1->GetLastChild(src_id),
754 grib[_T(
"name")].AsString(), -1, -1, info);
759 m_SourcesTreeCtrl1->CollapseAllChildren(src_id);
762 m_SourcesTreeCtrl1->Expand(root);
765void GribRequestSetting::ReadLocalCatalog() {
767 wxFileInputStream str(m_parent.
pPlugIn->m_local_sources_catalog);
769 reader.
Parse(str, &root);
773void GribRequestSetting::HighlightArea(
double latmax,
double lonmax,
774 double latmin,
double lonmin) {
775 m_parent.m_highlight_latmax = latmax;
776 m_parent.m_highlight_lonmax = lonmax;
777 m_parent.m_highlight_latmin = latmin;
778 m_parent.m_highlight_lonmin = lonmin;
781void GribRequestSetting::OnLocalTreeSelChanged(wxTreeEvent &event) {
782 wxTreeItemId item = m_SourcesTreeCtrl1->GetSelection();
785 if (src->type == LocalSourceItem::GRIB) {
786 m_stLocalDownloadInfo->SetLabelText(_(
"Download grib..."));
787 m_bLocal_source_selected =
true;
788 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
790 m_stLocalDownloadInfo->SetLabelText(_(
"Select grib..."));
791 m_bLocal_source_selected =
false;
792 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
795 EnableDownloadButtons();
798void GribRequestSetting::OnUpdateLocalCatalog(wxCommandEvent &event) {
801 m_downloading =
false;
802 m_download_handle = 0;
804 wxEVT_DOWNLOAD_EVENT,
805 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
807 m_btnDownloadLocal->SetLabelText(_(
"Download"));
808 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
811 EnableDownloadButtons();
812 wxTheApp->ProcessPendingEvents();
817 m_downloading =
true;
819 EnableDownloadButtons();
820 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
821 m_staticTextInfo->SetLabelText(_(
"Downloading catalog update..."));
826 wxEVT_DOWNLOAD_EVENT,
827 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
830 CATALOG_URL, m_parent.
pPlugIn->m_local_sources_catalog +
"new",
this,
832 while (m_downloading) {
833 wxTheApp->ProcessPendingEvents();
837 if (m_bTransferSuccess) {
838 wxRenameFile(m_parent.
pPlugIn->m_local_sources_catalog +
"new",
839 m_parent.
pPlugIn->m_local_sources_catalog,
true);
841 m_stLocalDownloadInfo->SetLabelText(_(
"Catalog update complete."));
843 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
846 m_btnDownloadLocal->SetLabelText(_(
"Download"));
848 EnableDownloadButtons();
851void GribRequestSetting::OnDownloadLocal(wxCommandEvent &event) {
854 m_downloading =
false;
855 m_download_handle = 0;
857 wxEVT_DOWNLOAD_EVENT,
858 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
860 m_btnDownloadLocal->SetLabelText(_(
"Download"));
861 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
864 EnableDownloadButtons();
865 wxTheApp->ProcessPendingEvents();
870 m_downloading =
true;
872 EnableDownloadButtons();
873 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
874 m_staticTextInfo->SetLabelText(_(
"Downloading grib..."));
877 m_SourcesTreeCtrl1->GetSelection()));
878 if (!src || src->type != LocalSourceItem::GRIB || src->url.IsEmpty()) {
879 m_downloading =
false;
880 m_stLocalDownloadInfo->SetLabelText(_(
"Download can't be started."));
881 m_btnDownloadWorld->SetLabelText(_(
"Download"));
883 EnableDownloadButtons();
889 wxEVT_DOWNLOAD_EVENT,
890 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
892 wxString url = src->url;
895 if (src->download_type == LocalGribDownloadType::MANIFEST) {
896 wxString path = m_parent.GetGribDir();
897 path.Append(wxFileName::GetPathSeparator());
898 path.Append(
"grib_manifest.json");
900 while (m_downloading) {
901 wxTheApp->ProcessPendingEvents();
906 if (!m_bTransferSuccess) {
908 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
912 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
916 wxFileInputStream str(path);
918 reader.
Parse(str, &root);
920 wxString parsed = root[
"url"].
AsString();
921 if (parsed.StartsWith(
"http")) {
924 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
931 m_downloading =
false;
932 m_download_handle = 0;
933 Disconnect(wxEVT_DOWNLOAD_EVENT,
937 m_btnDownloadLocal->SetLabelText(_(
"Download"));
938 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
941 EnableDownloadButtons();
942 wxTheApp->ProcessPendingEvents();
948 m_downloading =
true;
953 wxEVT_DOWNLOAD_EVENT,
954 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
957 if (!src->filename.IsEmpty()) {
958 filename = src->filename;
963 filename.Replace(
"?",
"_");
964 filename.Replace(
"&",
"_");
965 if (!(filename.Contains(
".grb2") || filename.Contains(
".grib2") ||
966 filename.Contains(
".grb") || filename.Contains(
".grib"))) {
967 filename.Append(
".grb");
971 wxString path = m_parent.GetGribDir();
972 path.Append(wxFileName::GetPathSeparator());
973 path.Append(filename);
975 while (m_downloading) {
976 wxTheApp->ProcessPendingEvents();
980 if (m_bTransferSuccess) {
981 m_stLocalDownloadInfo->SetLabelText(_(
"Grib download complete."));
982 m_stLocalDownloadInfo->SetLabelText(
983 wxString::Format(_(
"Download complete: %s"), path.c_str()));
991 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
993 m_parent.SetDialogsStyleSizePosition(
true);
997 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
1000 m_btnDownloadWorld->SetLabelText(_(
"Download"));
1002 EnableDownloadButtons();
1005void GribRequestSetting::EnableDownloadButtons() {
1006 switch (m_downloadType) {
1008 m_btnDownloadWorld->Enable(
true);
1009 m_btnDownloadLocal->Enable(
false);
1010 m_buttonUpdateCatalog->Enable(
false);
1014 m_btnDownloadWorld->Enable(
false);
1015 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1016 m_buttonUpdateCatalog->Enable(
false);
1019 m_xygribPanel->m_download_button->Enable(
true);
1022 m_btnDownloadWorld->Enable(
true);
1023 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1024 m_buttonUpdateCatalog->Enable(
true);
1025 m_xygribPanel->m_download_button->Enable(
true);
1030void GribRequestSetting::StopGraphicalZoneSelection() {
1050 if (!m_AllowSend)
return;
1056 UpdateGribSizeEstimate();
1059void GribRequestSetting::ApplyRequestConfig(
unsigned rs,
unsigned it,
1062 const wxString res[][RESOLUTIONS] = {
1063 {_T(
"0.25"), _T(
"0.5"), _T(
"1.0"), _T(
"2.0")},
1064 {_T(
"0.2"), _T(
"0.8"), _T(
"1.6"), wxEmptyString},
1065 {_T(
"0.08"), _T(
"0.24"), _T(
"1.0"), wxEmptyString},
1066 {_T(
"0.03"), _T(
"0.24"), _T(
"1.0"), wxEmptyString},
1067 {_T(
"0.0625"), _T(
"0.125"), wxEmptyString, wxEmptyString},
1068 {_T(
"0.4"), _T(
"1.0"), _T(
"2.0"), wxEmptyString}
1071 IsZYGRIB = m_pMailTo->GetCurrentSelection() == ZYGRIB;
1073 m_pModel->SetSelection(GFS);
1074 IsGFS = m_pModel->GetCurrentSelection() == GFS;
1075 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1076 bool IsHRRR = m_pModel->GetCurrentSelection() == HRRR;
1077 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1078 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1081 m_pResolution->Clear();
1082 if (m_pModel->GetCurrentSelection() >= 0) {
1083 for (
int i = 0; i < RESOLUTIONS; i++) {
1084 if (res[m_pModel->GetCurrentSelection()][i] != wxEmptyString) {
1085 wxString s = res[m_pModel->GetCurrentSelection()][i];
1086 m_pResolution->Append(s);
1090 m_pResolution->SetSelection(rs);
1094 l = (IsGFS || IsRTOFS || IsICON || IsECMWF) ? 3 : IsHRRR ? 1 : 6;
1097 m = IsHRRR ? 2 : 25;
1099 m_pInterval->Clear();
1100 for (
unsigned i = l; i < m; i *= 2)
1101 m_pInterval->Append(wxString::Format(_T(
"%d"), i));
1102 m_pInterval->SetSelection(wxMin(it, m_pInterval->GetCount() - 1));
1112 m_pTimeRange->Clear();
1113 for (
unsigned i = 2; i < l + 1; i++)
1114 m_pTimeRange->Append(wxString::Format(_T(
"%d"), i));
1115 m_pTimeRange->SetSelection(wxMin(l - 2, tr));
1117 m_pModel->Enable(!IsZYGRIB);
1118 m_pWind->SetValue(!IsRTOFS);
1119 m_pPress->SetValue(!IsRTOFS);
1120 m_pWaves->SetValue(m_RequestConfigBase.GetChar(8) ==
'X' && IsGFS);
1121 m_pWaves->Enable(IsECMWF ||
1122 (IsGFS && m_pTimeRange->GetCurrentSelection() < 7));
1124 m_pRainfall->SetValue(m_RequestConfigBase.GetChar(9) ==
'X' &&
1126 m_pRainfall->Enable(IsGFS || IsHRRR);
1127 m_pCloudCover->SetValue(m_RequestConfigBase.GetChar(10) ==
'X' && IsGFS);
1128 m_pCloudCover->Enable(IsGFS);
1129 m_pAirTemp->SetValue(m_RequestConfigBase.GetChar(11) ==
'X' &&
1130 (IsGFS || IsHRRR || IsICON || IsECMWF));
1131 m_pAirTemp->Enable(IsGFS || IsHRRR || IsICON || IsECMWF);
1132 m_pSeaTemp->SetValue(m_RequestConfigBase.GetChar(12) ==
'X' &&
1133 ((!IsZYGRIB && IsGFS) || IsRTOFS || IsHRRR || IsICON));
1134 m_pSeaTemp->Enable(!IsZYGRIB && (IsGFS || IsHRRR || IsICON));
1135 m_pWindGust->SetValue(m_RequestConfigBase.GetChar(14) ==
'X' &&
1136 (IsGFS || IsHRRR || IsICON));
1137 m_pWindGust->Enable(IsGFS || IsHRRR || IsICON);
1138 m_pCAPE->SetValue(m_RequestConfigBase.GetChar(15) ==
'X' &&
1140 m_pCAPE->Enable(IsGFS || IsHRRR);
1141 m_pReflectivity->Enable(IsGFS || IsHRRR);
1143 m_pAltitudeData->SetValue(
1144 (IsGFS || IsICON || IsECMWF)
1145 ? m_RequestConfigBase.GetChar(17) ==
'X'
1147 m_pAltitudeData->Enable(IsGFS || IsICON || IsECMWF);
1148 m_p850hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(18) ==
'X'
1150 m_p850hpa->Enable(IsZYGRIB);
1151 m_p700hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(19) ==
'X'
1153 m_p700hpa->Enable(IsZYGRIB);
1154 m_p500hpa->SetValue((IsGFS || IsICON || IsECMWF)
1155 ? m_RequestConfigBase.GetChar(20) ==
'X'
1157 m_p500hpa->Enable(IsGFS || IsICON || IsECMWF);
1158 m_p300hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(21) ==
'X'
1160 m_p300hpa->Enable(IsZYGRIB);
1162 m_pCurrent->SetValue(IsRTOFS);
1163 m_pCurrent->Enable(
false);
1166 m_cMovingGribEnabled->Show(!IsZYGRIB);
1167 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1168 m_cMovingGribEnabled->IsShown());
1170 m_fgLog->ShowItems(IsZYGRIB);
1172 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1174 m_fgAltitudeData->ShowItems(
1175 m_pAltitudeData->IsChecked());
1178void GribRequestSetting::OnTopChange(wxCommandEvent &event) {
1180 if (m_pMailTo->GetCurrentSelection() == ZYGRIB) {
1181 m_pMailTo->SetSelection(0);
1184 _(
"Sorry...\nZyGrib momentary stopped providing this service...\nOnly "
1185 "Saildocs option is available"),
1186 _(
"Warning"), wxOK);
1188 ApplyRequestConfig(m_pResolution->GetCurrentSelection(),
1189 m_pInterval->GetCurrentSelection(),
1190 m_pTimeRange->GetCurrentSelection());
1192 m_cMovingGribEnabled->Show(m_pMailTo->GetCurrentSelection() == SAILDOCS);
1194 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1196 SetRequestDialogSize();
1199void GribRequestSetting::UpdateAreaSelectionState() {
1208void GribRequestSetting::OnZoneSelectionModeChange(wxCommandEvent &event) {
1209 StopGraphicalZoneSelection();
1218 }
else if (event.GetId() ==
MANSELECT) {
1224 m_cUseSavedZone->SetValue(
false);
1225 }
else if (event.GetId() ==
SAVEDZONE) {
1233 UpdateAreaSelectionState();
1234 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1236 SetRequestDialogSize();
1250 center.x = x + (zw / 2);
1251 center.y = y + (zh / 2);
1257 wxColour pen_color, back_color;
1258 GetGlobalColor(_T (
"DASHR" ), &pen_color);
1259 GetGlobalColor(_T (
"YELO1" ), &back_color);
1261 int label_offsetx = 5, label_offsety = 1;
1264 EstimateFileSize(&size);
1266 wxString label(_(
"Coord. "));
1267 label.Append(toMailFormat(1,
m_spMaxLat->GetValue()) + _T(
" "));
1268 label.Append(toMailFormat(0,
m_spMinLon->GetValue()) + _T(
" "));
1269 label.Append(toMailFormat(1,
m_spMinLat->GetValue()) + _T(
" "));
1270 label.Append(toMailFormat(0,
m_spMaxLon->GetValue()) + _T(
"\n"));
1271 label.Append(_T(
"Estim. Size "))
1272 .Append((wxString::Format(_T(
"%1.2f " ), size) + _(
"MB")));
1275 wxPen pen(pen_color);
1278 m_pdc->SetBrush(*wxTRANSPARENT_BRUSH);
1279 m_pdc->DrawRectangle(x, y, zw, zh);
1284 sdc.GetMultiLineTextExtent(label, &w, &h, &sl, font);
1286 m_pdc->GetMultiLineTextExtent(label, &w, &h, &sl, font);
1290 w += 2 * label_offsetx, h += 2 * label_offsety;
1291 x = center.x - (w / 2);
1292 y = center.y - (h / 2);
1294 h *= m_displayScale;
1295 w *= m_displayScale;
1302 mdc.SetBrush(back_color);
1303 mdc.SetPen(*wxTRANSPARENT_PEN);
1304 mdc.SetTextForeground(wxColor(0, 0, 0));
1305 mdc.DrawRectangle(0, 0, w, h);
1306 mdc.DrawLabel(label, wxRect(label_offsetx, label_offsety, w, h));
1308 wxImage im = bm.ConvertToImage();
1310 w = im.GetWidth(), h = im.GetHeight();
1311 for (
int j = 0; j < h; j++)
1312 for (
int i = 0; i < w; i++) im.SetAlpha(i, j, 155);
1314 m_pdc->DrawBitmap(im, x, y,
true);
1318#ifndef USE_ANDROID_GLES2
1325 m_oDC->SetPen(wxPen(pen_color, 3));
1328 outline[0] = wxPoint(x, y);
1329 outline[1] = wxPoint(x + zw, y);
1330 outline[2] = wxPoint(x + zw, y + zh);
1331 outline[3] = wxPoint(x, y + zh);
1332 outline[4] = wxPoint(x, y);
1333 m_oDC->DrawLines(5, outline);
1335 m_oDC->SetFont(*font);
1337 m_oDC->GetTextExtent(label, &w, &h);
1338 h *= m_displayScale;
1339 w *= m_displayScale;
1341 m_oDC->GetTextExtent(
"W", &ww, &hw);
1343 int label_offsetx = ww, label_offsety = 1;
1344 int x = center.x - w / 2;
1345 int y = center.y - h / 2;
1347 w += 2 * label_offsetx, h += 2 * label_offsety;
1349 m_oDC->SetBrush(wxBrush(back_color));
1350 m_oDC->DrawRoundedRectangle(x, y, w, h, 0);
1353 m_oDC->SetPen(wxPen(wxColour(0, 0, 0), 1));
1355 outline[0] = wxPoint(x, y);
1356 outline[1] = wxPoint(x + w, y);
1357 outline[2] = wxPoint(x + w, y + h);
1358 outline[3] = wxPoint(x, y + h);
1359 outline[4] = wxPoint(x, y);
1360 m_oDC->DrawLines(5, outline);
1362 m_oDC->DrawText(label, x + label_offsetx, y + label_offsety);
1382void GribRequestSetting::OnMovingClick(wxCommandEvent &event) {
1383 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1384 m_cMovingGribEnabled->IsShown());
1386 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1387 SetRequestDialogSize();
1392void GribRequestSetting::OnCoordinatesChange(wxSpinEvent &event) {
1393 SetCoordinatesText();
1395 StopGraphicalZoneSelection();
1397 if (!m_AllowSend)
return;
1399 m_MailImage->SetValue(WriteMail());
1402void GribRequestSetting::OnAnyChange(wxCommandEvent &event) {
1403 m_fgAltitudeData->ShowItems(m_pAltitudeData->IsChecked());
1405 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1407 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1409 SetRequestDialogSize();
1412void GribRequestSetting::OnTimeRangeChange(wxCommandEvent &event) {
1413 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1415 if (m_pModel->GetCurrentSelection() == 0) {
1416 if (m_pTimeRange->GetCurrentSelection() >
1418 m_pWaves->SetValue(0);
1419 m_pWaves->Enable(
false);
1422 _(
"You request a forecast for more than 8 days horizon.\nThis is "
1423 "conflicting with Wave data which will be removed from your "
1424 "request.\nDon't forget that beyond the first 8 days, the "
1425 "resolution will be only 2.5\u00B0x2.5\u00B0\nand the time "
1426 "intervall 12 hours."),
1429 m_pWaves->Enable(
true);
1432 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1434 SetRequestDialogSize();
1437void GribRequestSetting::OnOK(wxCommandEvent &event) {
1438 bool IsCOAMPS = m_pModel->GetCurrentSelection() == COAMPS;
1439 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1440 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1441 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1442 m_RequestConfigBase.SetChar(
1443 0, (
char)(m_pMailTo->GetCurrentSelection() +
'0'));
1444 m_cMovingGribEnabled->IsChecked()
1445 ? m_RequestConfigBase.SetChar(16,
'X')
1446 : m_RequestConfigBase.SetChar(16,
'.');
1449 m_RequestConfigBase.SetChar(
1450 1, (
char)(m_pModel->GetCurrentSelection() +
'0'));
1452 m_RequestConfigBase.SetChar(
1453 2, (
char)(m_pResolution->GetCurrentSelection() +
'0'));
1455 m_RequestConfigBase.SetChar(3,
1456 (
char)(m_pInterval->GetCurrentSelection() +
'0'));
1459 range.Printf(_T(
"%x"), m_pTimeRange->GetCurrentSelection() +
1461 m_RequestConfigBase.SetChar(4, range.GetChar(0));
1463 if (IsZYGRIB && m_pWModel->IsShown())
1464 m_RequestConfigBase.SetChar(
1465 5, (
char)(m_pWModel->GetCurrentSelection() +
'0'));
1467 m_RequestConfigBase.SetChar(
1469 m_RequestConfigBase.SetChar(
1472 if (!IsCOAMPS && !IsRTOFS) {
1473 m_pWindGust->IsChecked() ? m_RequestConfigBase.SetChar(14,
'X')
1474 : m_RequestConfigBase.SetChar(14,
'.');
1475 m_pWaves->IsChecked() ? m_RequestConfigBase.SetChar(8,
'X')
1476 : m_RequestConfigBase.SetChar(8,
'.');
1477 m_pRainfall->IsChecked() ? m_RequestConfigBase.SetChar(9,
'X')
1478 : m_RequestConfigBase.SetChar(9,
'.');
1479 m_pCloudCover->IsChecked() ? m_RequestConfigBase.SetChar(10,
'X')
1480 : m_RequestConfigBase.SetChar(10,
'.');
1481 m_pAirTemp->IsChecked() ? m_RequestConfigBase.SetChar(11,
'X')
1482 : m_RequestConfigBase.SetChar(11,
'.');
1483 m_pSeaTemp->IsChecked() ? m_RequestConfigBase.SetChar(12,
'X')
1484 : m_RequestConfigBase.SetChar(12,
'.');
1485 m_pCAPE->IsChecked() ? m_RequestConfigBase.SetChar(15,
'X')
1486 : m_RequestConfigBase.SetChar(15,
'.');
1489 m_pCurrent->IsChecked() ? m_RequestConfigBase.SetChar(13,
'X')
1490 : m_RequestConfigBase.SetChar(13,
'.');
1492 if (IsGFS || IsICON || IsECMWF) {
1493 m_pAltitudeData->IsChecked()
1494 ? m_RequestConfigBase.SetChar(17,
'X')
1495 : m_RequestConfigBase.SetChar(17,
'.');
1496 m_p500hpa->IsChecked() ? m_RequestConfigBase.SetChar(20,
'X')
1497 : m_RequestConfigBase.SetChar(20,
'.');
1500 m_p850hpa->IsChecked() ? m_RequestConfigBase.SetChar(18,
'X')
1501 : m_RequestConfigBase.SetChar(18,
'.');
1502 m_p700hpa->IsChecked() ? m_RequestConfigBase.SetChar(19,
'X')
1503 : m_RequestConfigBase.SetChar(19,
'.');
1504 m_p300hpa->IsChecked() ? m_RequestConfigBase.SetChar(21,
'X')
1505 : m_RequestConfigBase.SetChar(21,
'.');
1512wxString GribRequestSetting::WriteMail() {
1514 int limit = IsZYGRIB ? 2 : 0;
1518 const wxString s[] = {_T(
","), _T(
" ")};
1519 const wxString p[][11] = {
1521 {_T(
"APCP"), _T(
"TCDC"), _T(
"AIRTMP"), _T(
"HTSGW,WVPER,WVDIR"),
1522 _T(
"SEATMP"), _T(
"GUST"), _T(
"CAPE"), wxEmptyString, wxEmptyString,
1523 _T(
"WIND500,HGT500"), wxEmptyString},
1528 {_T(
""), _T(
""), _T(
"AIRTMP"), _T(
""), _T(
"SFCTMP"), _T(
"GUST"), _T(
""),
1529 _T(
""), _T(
""), _T(
"WIND500,HGT500"), _T(
"")},
1531 {_T(
""), _T(
""), _T(
"TEMP"), _T(
"WAVES"), _T(
""), _T(
""), _T(
""), _T(
""),
1532 _T(
""), _T(
"WIND500,HGT500"), _T(
"")},
1534 {_T(
"PRECIP"), _T(
"CLOUD"), _T(
"TEMP"), _T(
"WVSIG WVWIND"), wxEmptyString,
1535 _T(
"GUST"), _T(
"CAPE"), _T(
"A850"), _T(
"A700"), _T(
"A500"), _T(
"A300")}};
1537 wxString r_topmess, r_parameters, r_zone;
1539 switch (m_pMailTo->GetCurrentSelection()) {
1541 r_zone = toMailFormat(1,
m_spMaxLat->GetValue()) + _T(
",") +
1542 toMailFormat(1,
m_spMinLat->GetValue()) + _T(
",") +
1543 toMailFormat(2,
m_spMinLon->GetValue()) + _T(
",") +
1545 r_topmess = wxT(
"send ");
1546 r_topmess.Append(m_pModel->GetStringSelection() + _T(
":"));
1547 r_topmess.Append(r_zone + _T(
"|"));
1548 r_topmess.Append(m_pResolution->GetStringSelection())
1550 .Append(m_pResolution->GetStringSelection())
1553 m_pInterval->GetStringSelection().ToDouble(&v);
1554 r_topmess.Append(wxString::Format(_T(
"0,%d,%d"), (
int)v, (
int)v * 2));
1555 m_pTimeRange->GetStringSelection().ToDouble(&v);
1556 r_topmess.Append(wxString::Format(_T(
"..%d"), (
int)v * 24) + _T(
"|=\n"));
1563 r_zone = toMailFormat(1,
m_spMinLat->GetValue()) +
1564 toMailFormat(2,
m_spMinLon->GetValue()) + _T(
" ") +
1566 toMailFormat(2, maxlon);
1567 r_topmess = wxT(
"login : ");
1568 r_topmess.Append(m_pLogin->GetValue() + _T(
"\n"));
1569 r_topmess.Append(wxT(
"code :"));
1570 r_topmess.Append(m_pCode->GetValue() + _T(
"\n"));
1571 r_topmess.Append(wxT(
"area : "));
1572 r_topmess.append(r_zone + _T(
"\n"));
1573 r_topmess.Append(wxT(
"resol : "));
1574 r_topmess.append(m_pResolution->GetStringSelection() + _T(
"\n"));
1575 r_topmess.Append(wxT(
"days : "));
1576 r_topmess.append(m_pTimeRange->GetStringSelection() + _T(
"\n"));
1577 r_topmess.Append(wxT(
"hours : "));
1578 r_topmess.append(m_pInterval->GetStringSelection() + _T(
"\n"));
1579 if (m_pWaves->IsChecked()) {
1580 r_topmess.Append(wxT(
"waves : "));
1581 r_topmess.append(m_pWModel->GetStringSelection() + _T(
"\n"));
1583 r_topmess.Append(wxT(
"meteo : "));
1584 r_topmess.append(m_pModel->GetStringSelection() + _T(
"\n"));
1585 if (m_pLogin->GetValue().IsEmpty() || m_pCode->GetValue().IsEmpty())
1590 int GFSZ = IsZYGRIB ? 6 : 0;
1591 switch (m_pModel->GetCurrentSelection()) {
1593 r_parameters = wxT(
"WIND") + s[m_pMailTo->GetCurrentSelection()] +
1595 if (m_pRainfall->IsChecked())
1596 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1598 if (m_pCloudCover->IsChecked())
1599 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1601 if (m_pAirTemp->IsChecked())
1602 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1604 if (m_pWaves->IsChecked())
1605 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1607 if (m_pSeaTemp->IsChecked())
1608 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1610 if (m_pWindGust->IsChecked())
1611 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1613 if (m_pCAPE->IsChecked())
1614 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1616 if (m_pAltitudeData->IsChecked()) {
1617 if (m_p850hpa->IsChecked())
1618 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1620 if (m_p700hpa->IsChecked())
1621 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1623 if (m_p500hpa->IsChecked())
1624 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1626 if (m_p300hpa->IsChecked())
1627 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1632 r_parameters = wxT(
"WIND,PRMSL");
1636 r_parameters = wxT(
"CUR,WTMP");
1639 r_parameters = wxT(
"WIND,PRMSL");
1641 if (m_pRainfall->IsChecked())
1642 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][0]);
1643 if (m_pAirTemp->IsChecked())
1644 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][2]);
1645 if (m_pSeaTemp->IsChecked())
1646 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][4]);
1647 if (m_pWindGust->IsChecked())
1648 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][5]);
1649 if (m_pCAPE->IsChecked())
1650 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][6]);
1653 r_parameters = wxT(
"WIND,PRMSL");
1655 if (m_pAirTemp->IsChecked())
1656 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][2]);
1657 if (m_pSeaTemp->IsChecked())
1658 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][4]);
1659 if (m_pWindGust->IsChecked())
1660 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][5]);
1661 if (m_pAltitudeData->IsChecked()) {
1662 if (m_p500hpa->IsChecked())
1663 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][9]);
1667 r_parameters = wxT(
"WIND,MSLP");
1669 if (m_pAirTemp->IsChecked())
1670 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][2]);
1671 if (m_pAltitudeData->IsChecked()) {
1672 if (m_p500hpa->IsChecked())
1673 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1676 if (m_pWaves->IsChecked())
1677 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][3]);
1680 if (!IsZYGRIB && m_cMovingGribEnabled->IsChecked())
1681 r_parameters.Append(wxString::Format(
1682 _T(
"|%d,%d"), m_sMovingSpeed->GetValue(), m_sMovingCourse->GetValue()));
1686 char c = m_pMailTo->GetCurrentSelection() == SAILDOCS ?
',' :
' ';
1687 for (
size_t i = 0; i < r_parameters.Len(); i++) {
1688 if (r_parameters.GetChar(i) ==
'|')
1690 if (r_parameters.GetChar(i) == c) j++;
1692 r_parameters.insert(i + 1, m_pMailTo->GetCurrentSelection() == SAILDOCS
1700 m_MailError_Nb += EstimateFileSize(&size);
1702 m_tFileSize->SetLabel(wxString::Format(_T(
"%1.2f " ), size) + _(
"MB"));
1705 m_tLimit->SetLabel(wxString(_T(
"( ")) + _(
"Max") +
1706 wxString::Format(_T(
" %d "), limit) + _(
"MB") +
1708 if (size > limit) m_MailError_Nb += 2;
1710 m_tLimit->SetLabel(wxEmptyString);
1712 return wxString(r_topmess + r_parameters);
1715int GribRequestSetting::EstimateFileSize(
double *size) {
1716 if (!size)
return 0;
1720 double reso, time, inter;
1721 m_pResolution->GetStringSelection().ToDouble(&reso);
1722 m_pTimeRange->GetStringSelection().ToDouble(&time);
1723 m_pInterval->GetStringSelection().ToDouble(&inter);
1727 if (maxlat - minlat < 0)
return 3;
1728 double wlon = (maxlon > minlon ? 0 : 360) + maxlon - minlon;
1729 if (wlon > 180 || (maxlat - minlat > 180))
return 4;
1731 if (fabs(wlon) < 2 * reso || maxlat - minlat < 2 * reso)
1734 int npts = (int)(ceil(((
double)(maxlat - minlat) / reso)) *
1735 ceil(((
double)(wlon) / reso)));
1737 if (m_pModel->GetCurrentSelection() == COAMPS)
1738 npts = wxMin(npts, (
int)(ceil(40.0 / reso) * ceil(40.0 / reso)));
1741 int nbrec = (int)(time * 24 / inter) + 1;
1742 int nbPress = (m_pPress->IsChecked()) ? nbrec : 0;
1743 int nbWind = (m_pWind->IsChecked()) ? 2 * nbrec : 0;
1744 int nbwave = (m_pWaves->IsChecked()) ? 2 * nbrec : 0;
1745 int nbRain = (m_pRainfall->IsChecked()) ? nbrec - 1 : 0;
1746 int nbCloud = (m_pCloudCover->IsChecked()) ? nbrec - 1 : 0;
1747 int nbTemp = (m_pAirTemp->IsChecked()) ? nbrec : 0;
1748 int nbSTemp = (m_pSeaTemp->IsChecked()) ? nbrec : 0;
1749 int nbGUSTsfc = (m_pWindGust->IsChecked()) ? nbrec : 0;
1750 int nbCurrent = (m_pCurrent->IsChecked()) ? nbrec : 0;
1751 int nbCape = (m_pCAPE->IsChecked()) ? nbrec : 0;
1753 IsZYGRIB ? 5 * nbrec : 3 * nbrec;
1757 double estime = 0.0;
1761 estime += nbWind * (head + (nbits * npts) / 8 + 2);
1762 estime += nbCurrent * (head + (nbits * npts) / 8 + 2);
1765 estime += nbTemp * (head + (nbits * npts) / 8 + 2);
1766 estime += nbSTemp * (head + (nbits * npts) / 8 + 2);
1769 estime += nbRain * (head + (nbits * npts) / 8 + 2);
1772 estime += nbPress * (head + (nbits * npts) / 8 + 2);
1775 estime += nbCloud * (head + (nbits * npts) / 8 + 2);
1778 estime += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
1781 estime += nbCape * (head + (nbits * npts) / 8 + 2);
1784 estime += nbwave * (head + (nbits * npts) / 8 + 2);
1786 if (m_pAltitudeData->IsChecked()) {
1788 if (m_p850hpa->IsChecked()) nbalt++;
1789 if (m_p700hpa->IsChecked()) nbalt++;
1790 if (m_p500hpa->IsChecked()) nbalt++;
1791 if (m_p300hpa->IsChecked()) nbalt++;
1794 estime += nbAltitude * nbalt * (head + (nbits * npts) / 8 + 2);
1797 *size = estime / (1024. * 1024.);
1802const wxString EncodeURL(
const wxString &uri) {
1803 static std::unordered_map<int, wxString> sEncodeMap = {
1804 {(int)
'!',
"%21"}, {(int)
'#',
"%23"}, {(int)
'$',
"%24"},
1805 {(int)
'&',
"%26"}, {(int)
'\'',
"%27"}, {(int)
'(',
"%28"},
1806 {(int)
')',
"%29"}, {(int)
'*',
"%2A"}, {(int)
'+',
"%2B"},
1807 {(int)
',',
"%2C"}, {(int)
';',
"%3B"}, {(int)
'=',
"%3D"},
1808 {(int)
'?',
"%3F"}, {(int)
'@',
"%40"}, {(int)
'[',
"%5B"},
1809 {(int)
']',
"%5D"}, {(int)
' ',
"%20"}, {(int)
'|',
"%7C"},
1810 {(int)
':',
"%3A"}, {(int)
'\n',
"%0A"}};
1813 for (
size_t i = 0; i < uri.length(); ++i) {
1815 std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((
int)ch);
1816 if (iter != sEncodeMap.end()) {
1817 encoded << iter->second;
1825void GribRequestSetting::OnSendMaiL(wxCommandEvent &event) {
1826 StopGraphicalZoneSelection();
1833 m_MailImage->SetForegroundColour(
1837 m_MailImage->SetValue(WriteMail());
1838 SetRequestDialogSize();
1843 const wxString error[] = {
1845 _(
"Before sending an email to Zygrib you have to enter your Login and "
1846 "Code.\nPlease visit www.zygrib.org/ and follow instructions..."),
1847 _(
"Too big file! zyGrib limit is 2Mb!"),
1848 _(
"Error! Max Lat lower than Min Lat or Max Lon lower than Min Lon!"),
1849 _(
"Too large area! Each side must be less than 180\u00B0!"),
1850 _(
"Too small area for this resolution!")};
1852 ::wxBeginBusyCursor();
1854 m_MailImage->SetForegroundColour(wxColor(255, 0, 0));
1855 m_AllowSend =
false;
1857 if (m_MailError_Nb) {
1858 if (m_MailError_Nb > 7) {
1859 m_MailImage->SetValue(error[1] + error[0] + error[m_MailError_Nb - 6]);
1861 if (m_MailError_Nb == 6) m_MailError_Nb = 1;
1862 m_MailImage->SetValue(error[m_MailError_Nb]);
1866 SetRequestDialogSize();
1868 ::wxEndBusyCursor();
1873 std::string mailto =
1874 (m_pMailTo->GetCurrentSelection() == SAILDOCS
1875 ? m_MailToAddresses.BeforeFirst(_T(
';'))
1876 : m_MailToAddresses.AfterFirst(_T(
';')).BeforeFirst(_T(
';')))
1878 std::string mailfrom = m_pSenderAddress->GetValue().ToStdString();
1880 std::regex mailregex(
"^([a-z0-9+_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$");
1882 if ((!mailto.empty() && !std::regex_match(mailto, mailregex)) ||
1883 (!mailfrom.empty() && !std::regex_match(mailfrom, mailregex))) {
1886 _(
"Sender or recipient e-mail address seems invalid.\nPlease correct "
1887 "it in the configuration file."),
1888 _(
"Error"), wxOK | wxICON_ERROR);
1898 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1899 ? _T(
"grib-request")
1902 EncodeURL(WriteMail()),
1906 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1907 ? _T(
"grib-request")
1915 if (mail.Send(*message, m_SendMethod)) {
1917 m_MailImage->SetValue(
1918 _(
"Your request is ready. An email is prepared in your email "
1919 "environment. \nYou have just to verify and send it...\nSave or "
1920 "Cancel to finish...or Continue..."));
1922 if (m_SendMethod == 0) {
1923 m_MailImage->SetValue(
1924 _(
"Your request is ready. An email is prepared in your email "
1925 "environment. \nYou have just to verify and send it...\nSave or "
1926 "Cancel to finish...or Continue..."));
1928 m_MailImage->SetValue(
1929 _(
"Your request was sent \n(if your system has an MTA configured and "
1930 "is able to send email).\nSave or Cancel to finish...or "
1935 m_MailImage->SetValue(
1936 _(
"Request can't be sent. Please verify your email systeme "
1937 "parameters.\nYou should also have a look at your log file.\nSave or "
1938 "Cancel to finish..."));
1942 SetRequestDialogSize();
1944 ::wxEndBusyCursor();
1949wxString GribRequestSetting::BuildXyGribUrl() {
1952 wxString::Format(
"http://grbsrv.opengribs.org/getmygribs2.php?");
1954 urlStr << wxString::Format(
"la1=%.0f", floor(
GetMinLat()));
1955 urlStr << wxString::Format(
"&la2=%.0f", ceil(
GetMaxLat()));
1956 urlStr << wxString::Format(
"&lo1=%.0f", floor(
GetMinLon()));
1957 urlStr << wxString::Format(
"&lo2=%.0f", ceil(
GetMaxLon()));
1960 urlStr << wxString::Format(
1962 xygribAtmModelList[m_selectedAtmModelIndex]
1963 ->reqName[m_xygribPanel->m_resolution_choice->GetSelection()]);
1965 urlStr << wxString::Format(
1967 xygribAtmModelList[m_selectedAtmModelIndex]
1968 ->interval[m_xygribPanel->m_interval_choice->GetSelection()]);
1970 urlStr << wxString::Format(
1971 "&days=%d", m_xygribPanel->m_duration_choice->GetSelection() + 1);
1975 wxString selStr = m_xygribPanel->m_run_choice->GetStringSelection();
1976 if (selStr.IsSameAs(
"18h",
false)) {
1977 urlStr <<
"&cyc=18";
1978 }
else if (selStr.IsSameAs(
"12h",
false)) {
1979 urlStr <<
"&cyc=12";
1980 }
else if (selStr.IsSameAs(
"6h",
false)) {
1981 urlStr <<
"&cyc=06";
1982 }
else if (selStr.IsSameAs(
"0h",
false)) {
1983 urlStr <<
"&cyc=00";
1985 urlStr <<
"&cyc=last";
1990 if (m_xygribPanel->m_wind_cbox->IsEnabled() &&
1991 m_xygribPanel->m_wind_cbox->IsChecked())
1993 if (m_xygribPanel->m_pressure_cbox->IsEnabled() &&
1994 m_xygribPanel->m_pressure_cbox->IsChecked()) {
1995 if (xygribAtmModelList[m_selectedAtmModelIndex]->altPressure) {
2001 if (m_xygribPanel->m_precipitation_cbox->IsEnabled() &&
2002 m_xygribPanel->m_precipitation_cbox->IsChecked())
2004 if (m_xygribPanel->m_cloudcover_cbox->IsEnabled() &&
2005 m_xygribPanel->m_cloudcover_cbox->IsChecked())
2007 if (m_xygribPanel->m_temperature_cbox->IsEnabled() &&
2008 m_xygribPanel->m_temperature_cbox->IsChecked())
2010 if (m_xygribPanel->m_cape_cbox->IsEnabled() &&
2011 m_xygribPanel->m_cape_cbox->IsChecked())
2013 if (m_xygribPanel->m_reflectivity_cbox->IsEnabled() &&
2014 m_xygribPanel->m_reflectivity_cbox->IsChecked())
2016 if (m_xygribPanel->m_gust_cbox->IsEnabled() &&
2017 m_xygribPanel->m_gust_cbox->IsChecked())
2021 if ((m_selectedWaveModelIndex >= 0) &&
2022 (xygribWaveModelList[m_selectedWaveModelIndex] !=
nullptr)) {
2023 wxString modelStr = wxString::Format(
2024 "&wmdl=%s", xygribWaveModelList[m_selectedWaveModelIndex]->reqName);
2025 wxString wParams =
"";
2026 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2029 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2030 wParams <<
"h;d;p;";
2032 if (wParams.length() > 0) {
2033 urlStr << wxString::Format(
"%s&wpar=%s", modelStr.c_str(),
2036 urlStr <<
"&wmdl=none";
2039 urlStr <<
"&wmdl=none";
2047wxString GribRequestSetting::BuildGribFileName() {
2048 wxString selStr = m_xygribPanel->m_resolution_choice->GetStringSelection();
2049 selStr.Replace(
".",
"P");
2052 if (m_selectedWaveModelIndex < 0) {
2053 fileName = wxString::Format(
2054 "XyGrib_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2055 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr);
2057 fileName = wxString::Format(
2058 "XyGrib_%s_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2059 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr,
2060 m_xygribPanel->m_wavemodel_choice->GetStringSelection());
2072void GribRequestSetting::OnXyGribDownloadButton(wxCommandEvent &event) {
2074 if (m_downloading) {
2078 m_downloading =
false;
2079 m_download_handle = 0;
2081 wxEVT_DOWNLOAD_EVENT,
2082 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2083 m_connected =
false;
2084 m_xygribPanel->m_progress_gauge->SetValue(0);
2085 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2086 m_xygribPanel->m_status_text->SetLabelText(_(
"Download cancelled"));
2089 EnableDownloadButtons();
2090 wxTheApp->ProcessPendingEvents();
2095 if (m_gribSizeEstimate > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB * 1024 * 1024) {
2096 m_xygribPanel->m_status_text->SetLabelText(
2097 wxString::Format(_(
"Can't download GRIB file bigger than %d MB"),
2098 (
int)XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB));
2104 MemorizeXyGribConfiguration();
2106 m_downloading =
true;
2108 EnableDownloadButtons();
2110 m_xygribPanel->m_download_button->SetLabelText(_(
"Cancel"));
2111 m_xygribPanel->m_status_text->SetLabelText(
2112 _(
"Preparing GRIB file on server..."));
2116 wxString requestUrl = BuildXyGribUrl();
2121 wxString filename = wxString::Format(
"ocpn_xygrib_%s.xml",
2122 wxDateTime::Now().Format(
"%F-%H-%M"));
2123 wxString path = m_parent.GetGribDir();
2124 path << wxFileName::GetPathSeparator();
2129 wxEVT_DOWNLOAD_EVENT,
2130 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2133 &m_download_handle);
2138 while (m_downloading) {
2139 wxTheApp->ProcessPendingEvents();
2143 if ((m_canceled) || (!m_bTransferSuccess)) {
2145 m_xygribPanel->m_status_text->SetLabelText(_(
"Grib request failed"));
2146 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2148 EnableDownloadButtons();
2156 bool readOk = xmlFile.Open(path);
2158 readOk &= xmlFile.ReadAll(&strXml);
2166 if (readOk && (((
int)strXml.find(
"\"status\":true") == wxNOT_FOUND))) {
2169 int errPos = strXml.find(
"\"message\":\"");
2170 int errEnd = strXml.find(
"\"}");
2171 if ((errPos != wxNOT_FOUND) && (errEnd != wxNOT_FOUND)) {
2173 errorStr = strXml.Mid(errPos, errEnd - errPos);
2175 errorStr =
"Unknown server error";
2178 m_xygribPanel->m_status_text->SetLabelText(
2179 wxString::Format(
"%s (%s)", _(
"Server Error"), errorStr));
2180 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2182 EnableDownloadButtons();
2187 int urlPos = strXml.find(
"\"url\":\"http:");
2188 int urlEnd = strXml.find(
".grb2\"");
2189 if ((urlPos != wxNOT_FOUND) && (urlEnd != wxNOT_FOUND)) {
2192 url = strXml.Mid(urlPos, urlEnd - urlPos);
2193 url.Replace(
"\\/",
"/");
2204 m_xygribPanel->m_status_text->SetLabelText(
2205 _(
"Error parsing XML file from server"));
2206 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2208 EnableDownloadButtons();
2212 m_xygribPanel->m_status_text->SetLabelText(_(
"Downloading GRIB file"));
2215 path = m_parent.GetGribDir();
2216 path << wxFileName::GetPathSeparator();
2217 path << BuildGribFileName();
2221 m_downloading =
true;
2225 wxEVT_DOWNLOAD_EVENT,
2226 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2232 while (m_downloading) {
2233 wxTheApp->ProcessPendingEvents();
2238 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2241 if (m_bTransferSuccess) {
2243 m_xygribPanel->m_status_text->SetLabelText(_(
"Download complete"));
2244 wxFileName fn(path);
2248 m_parent.OpenFile();
2250 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
2252 m_parent.SetDialogsStyleSizePosition(
true);
2257 m_xygribPanel->m_status_text->SetLabelText(_(
"Download failed"));
2261 EnableDownloadButtons();
2267void GribRequestSetting::OnXyGribAtmModelChoice(wxCommandEvent &event) {
2271 wxString atmModel = m_xygribPanel->m_atmmodel_choice->GetStringSelection();
2273 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2274 if (selectedAtmModel->name.IsSameAs(atmModel,
true)) {
2281 if (selectedAtmModel ==
nullptr) {
2282 selectedAtmModel = xygribAtmModelList[0];
2287 if (selectedAtmModel->wind)
2288 m_xygribPanel->m_wind_cbox->Enable();
2290 m_xygribPanel->m_wind_cbox->Disable();
2292 if (selectedAtmModel->gust)
2293 m_xygribPanel->m_gust_cbox->Enable();
2295 m_xygribPanel->m_gust_cbox->Disable();
2297 if (selectedAtmModel->pressure)
2298 m_xygribPanel->m_pressure_cbox->Enable();
2300 m_xygribPanel->m_pressure_cbox->Disable();
2302 if (selectedAtmModel->temperature)
2303 m_xygribPanel->m_temperature_cbox->Enable();
2305 m_xygribPanel->m_temperature_cbox->Disable();
2307 if (selectedAtmModel->cape)
2308 m_xygribPanel->m_cape_cbox->Enable();
2310 m_xygribPanel->m_cape_cbox->Disable();
2312 if (selectedAtmModel->reflectivity)
2313 m_xygribPanel->m_reflectivity_cbox->Enable();
2315 m_xygribPanel->m_reflectivity_cbox->Disable();
2317 if (selectedAtmModel->cloudCover)
2318 m_xygribPanel->m_cloudcover_cbox->Enable();
2320 m_xygribPanel->m_cloudcover_cbox->Disable();
2322 if (selectedAtmModel->precipitation)
2323 m_xygribPanel->m_precipitation_cbox->Enable();
2325 m_xygribPanel->m_precipitation_cbox->Disable();
2328 m_xygribPanel->m_resolution_choice->Clear();
2329 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2330 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2335 m_xygribPanel->m_duration_choice->Clear();
2336 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2337 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2341 m_xygribPanel->m_interval_choice->Clear();
2342 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2343 m_xygribPanel->m_interval_choice->Insert(
2344 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2348 m_xygribPanel->m_run_choice->Clear();
2349 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2350 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2351 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2352 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2354 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2355 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2356 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2357 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2358 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2361 if (modelIndex == m_parent.xyGribConfig.atmModelIndex) {
2362 ApplyXyGribConfiguration();
2364 m_selectedAtmModelIndex = modelIndex;
2365 m_xygribPanel->m_resolution_choice->SetSelection(0);
2366 m_xygribPanel->m_duration_choice->SetSelection(
2367 m_xygribPanel->m_duration_choice->GetCount() - 1);
2368 m_xygribPanel->m_interval_choice->SetSelection(0);
2369 m_xygribPanel->m_run_choice->SetSelection(
2370 m_xygribPanel->m_run_choice->GetCount() - 1);
2372 MemorizeXyGribConfiguration();
2378void GribRequestSetting::OnXyGribWaveModelChoice(wxCommandEvent &event) {
2382 wxString waveModel = m_xygribPanel->m_wavemodel_choice->GetStringSelection();
2384 while ((selectedModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2385 if (selectedModel->name.IsSameAs(waveModel,
true)) {
2392 if (selectedModel ==
nullptr) {
2394 m_selectedWaveModelIndex = -1;
2395 m_xygribPanel->m_waveheight_cbox->Disable();
2396 m_xygribPanel->m_windwave_cbox->Disable();
2397 MemorizeXyGribConfiguration();
2401 m_selectedWaveModelIndex = modelIndex;
2404 if (selectedModel->significantHeight) {
2405 m_xygribPanel->m_waveheight_cbox->Enable();
2407 m_xygribPanel->m_waveheight_cbox->Disable();
2410 if (selectedModel->windWaves) {
2411 m_xygribPanel->m_windwave_cbox->Enable();
2413 m_xygribPanel->m_windwave_cbox->Disable();
2415 MemorizeXyGribConfiguration();
2421void GribRequestSetting::OnXyGribConfigChange(wxCommandEvent &event) {
2422 MemorizeXyGribConfiguration();
2426void GribRequestSetting::InitializeXygribDialog() {
2431 m_xygribPanel->m_atmmodel_choice->Clear();
2433 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2434 m_xygribPanel->m_atmmodel_choice->Insert(selectedAtmModel->name,
2439 m_selectedAtmModelIndex = m_parent.xyGribConfig.atmModelIndex;
2440 selectedAtmModel = xygribAtmModelList[m_selectedAtmModelIndex];
2443 m_xygribPanel->m_wavemodel_choice->Clear();
2445 while ((selectedWaveModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2446 m_xygribPanel->m_wavemodel_choice->Insert(selectedWaveModel->name,
2451 m_xygribPanel->m_wavemodel_choice->Insert(
"None", modelIndex);
2452 m_selectedWaveModelIndex = m_parent.xyGribConfig.waveModelIndex;
2453 selectedWaveModel = xygribWaveModelList[m_selectedWaveModelIndex];
2454 if (selectedWaveModel ==
nullptr) {
2455 m_selectedWaveModelIndex = -1;
2459 m_xygribPanel->m_resolution_choice->Clear();
2460 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2461 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2466 m_xygribPanel->m_duration_choice->Clear();
2467 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2468 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2472 m_xygribPanel->m_interval_choice->Clear();
2473 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2474 m_xygribPanel->m_interval_choice->Insert(
2475 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2479 m_xygribPanel->m_run_choice->Clear();
2480 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2481 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2482 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2483 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2485 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2486 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2487 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2488 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2489 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2492 if (selectedAtmModel->wind)
2493 m_xygribPanel->m_wind_cbox->Enable();
2495 m_xygribPanel->m_wind_cbox->Disable();
2497 if (selectedAtmModel->gust)
2498 m_xygribPanel->m_gust_cbox->Enable();
2500 m_xygribPanel->m_gust_cbox->Disable();
2502 if (selectedAtmModel->pressure)
2503 m_xygribPanel->m_pressure_cbox->Enable();
2505 m_xygribPanel->m_pressure_cbox->Disable();
2507 if (selectedAtmModel->temperature)
2508 m_xygribPanel->m_temperature_cbox->Enable();
2510 m_xygribPanel->m_temperature_cbox->Disable();
2512 if (selectedAtmModel->cape)
2513 m_xygribPanel->m_cape_cbox->Enable();
2515 m_xygribPanel->m_cape_cbox->Disable();
2517 if (selectedAtmModel->reflectivity)
2518 m_xygribPanel->m_reflectivity_cbox->Enable();
2520 m_xygribPanel->m_reflectivity_cbox->Disable();
2522 if (selectedAtmModel->cloudCover)
2523 m_xygribPanel->m_cloudcover_cbox->Enable();
2525 m_xygribPanel->m_cloudcover_cbox->Disable();
2527 if (selectedAtmModel->precipitation)
2528 m_xygribPanel->m_precipitation_cbox->Enable();
2530 m_xygribPanel->m_precipitation_cbox->Disable();
2532 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->significantHeight))
2533 m_xygribPanel->m_waveheight_cbox->Enable();
2535 m_xygribPanel->m_waveheight_cbox->Disable();
2537 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->windWaves))
2538 m_xygribPanel->m_windwave_cbox->Enable();
2540 m_xygribPanel->m_windwave_cbox->Disable();
2542 ApplyXyGribConfiguration();
2549void GribRequestSetting::ApplyXyGribConfiguration() {
2550 m_xygribPanel->m_atmmodel_choice->SetSelection(
2551 m_parent.xyGribConfig.atmModelIndex);
2552 m_xygribPanel->m_wavemodel_choice->SetSelection(
2553 m_parent.xyGribConfig.waveModelIndex);
2555 m_xygribPanel->m_wind_cbox->SetValue(m_parent.xyGribConfig.wind);
2556 m_xygribPanel->m_gust_cbox->SetValue(m_parent.xyGribConfig.gust);
2557 m_xygribPanel->m_pressure_cbox->SetValue(m_parent.xyGribConfig.pressure);
2558 m_xygribPanel->m_temperature_cbox->SetValue(
2559 m_parent.xyGribConfig.temperature);
2560 m_xygribPanel->m_cape_cbox->SetValue(m_parent.xyGribConfig.cape);
2561 m_xygribPanel->m_reflectivity_cbox->SetValue(
2562 m_parent.xyGribConfig.reflectivity);
2563 m_xygribPanel->m_cloudcover_cbox->SetValue(m_parent.xyGribConfig.cloudCover);
2564 m_xygribPanel->m_precipitation_cbox->SetValue(
2565 m_parent.xyGribConfig.precipitation);
2566 m_xygribPanel->m_waveheight_cbox->SetValue(m_parent.xyGribConfig.waveHeight);
2567 m_xygribPanel->m_windwave_cbox->SetValue(m_parent.xyGribConfig.windWaves);
2568 m_xygribPanel->m_resolution_choice->SetSelection(
2569 m_parent.xyGribConfig.resolutionIndex);
2570 m_xygribPanel->m_duration_choice->SetSelection(
2571 m_parent.xyGribConfig.durationIndex);
2572 m_xygribPanel->m_interval_choice->SetSelection(
2573 m_parent.xyGribConfig.intervalIndex);
2574 m_xygribPanel->m_run_choice->SetSelection(m_parent.xyGribConfig.runIndex);
2576 UpdateGribSizeEstimate();
2583void GribRequestSetting::MemorizeXyGribConfiguration() {
2584 m_parent.xyGribConfig.atmModelIndex =
2585 m_xygribPanel->m_atmmodel_choice->GetSelection();
2586 m_parent.xyGribConfig.waveModelIndex =
2587 m_xygribPanel->m_wavemodel_choice->GetSelection();
2589 m_parent.xyGribConfig.wind = m_xygribPanel->m_wind_cbox->IsChecked();
2590 m_parent.xyGribConfig.gust = m_xygribPanel->m_gust_cbox->IsChecked();
2591 m_parent.xyGribConfig.pressure = m_xygribPanel->m_pressure_cbox->IsChecked();
2592 m_parent.xyGribConfig.temperature =
2593 m_xygribPanel->m_temperature_cbox->IsChecked();
2594 m_parent.xyGribConfig.cape = m_xygribPanel->m_cape_cbox->IsChecked();
2595 m_parent.xyGribConfig.reflectivity =
2596 m_xygribPanel->m_reflectivity_cbox->IsChecked();
2597 m_parent.xyGribConfig.cloudCover =
2598 m_xygribPanel->m_cloudcover_cbox->IsChecked();
2599 m_parent.xyGribConfig.precipitation =
2600 m_xygribPanel->m_precipitation_cbox->IsChecked();
2601 m_parent.xyGribConfig.waveHeight =
2602 m_xygribPanel->m_waveheight_cbox->IsChecked();
2603 m_parent.xyGribConfig.windWaves = m_xygribPanel->m_windwave_cbox->IsChecked();
2605 m_parent.xyGribConfig.resolutionIndex =
2606 m_xygribPanel->m_resolution_choice->GetSelection();
2607 m_parent.xyGribConfig.durationIndex =
2608 m_xygribPanel->m_duration_choice->GetSelection();
2609 m_parent.xyGribConfig.intervalIndex =
2610 m_xygribPanel->m_interval_choice->GetSelection();
2611 m_parent.xyGribConfig.runIndex = m_xygribPanel->m_run_choice->GetSelection();
2613 UpdateGribSizeEstimate();
2619void GribRequestSetting::UpdateGribSizeEstimate() {
2624 if (!m_xygribPanel->m_resolution_choice->GetStringSelection().ToCDouble(
2626 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2629 if (!m_xygribPanel->m_duration_choice->GetStringSelection().ToCLong(&days)) {
2630 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2633 wxString intvStr = m_xygribPanel->m_interval_choice->GetStringSelection();
2634 intvStr.Replace(
"h",
"");
2635 if (!intvStr.ToCLong(&interval)) {
2636 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2641 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2650 int npts = (int)(ceil(fabs(xmax - xmin) / resolution) *
2651 ceil(fabs(ymax - ymin) / resolution));
2654 int nbrec = (int)days * 24 / interval + 1;
2656 int nbPress = (m_xygribPanel->m_pressure_cbox->IsChecked() &&
2657 m_xygribPanel->m_pressure_cbox->IsEnabled())
2660 int nbWind = (m_xygribPanel->m_wind_cbox->IsChecked() &&
2661 m_xygribPanel->m_wind_cbox->IsEnabled())
2664 int nbRain = (m_xygribPanel->m_precipitation_cbox->IsChecked() &&
2665 m_xygribPanel->m_precipitation_cbox->IsEnabled())
2668 int nbCloud = (m_xygribPanel->m_cloudcover_cbox->IsChecked() &&
2669 m_xygribPanel->m_cloudcover_cbox->IsEnabled())
2672 int nbTemp = (m_xygribPanel->m_temperature_cbox->IsChecked() &&
2673 m_xygribPanel->m_temperature_cbox->IsEnabled())
2677 int nbCAPEsfc = (m_xygribPanel->m_cape_cbox->IsChecked() &&
2678 m_xygribPanel->m_cape_cbox->IsEnabled())
2681 int nbReflectivity = (m_xygribPanel->m_reflectivity_cbox->IsChecked() &&
2682 m_xygribPanel->m_reflectivity_cbox->IsEnabled())
2685 int nbGUSTsfc = (m_xygribPanel->m_gust_cbox->IsChecked() &&
2686 m_xygribPanel->m_gust_cbox->IsEnabled())
2696 estimate += nbWind * (head + (nbits * npts) / 8 + 2);
2699 estimate += nbTemp * (head + (nbits * npts) / 8 + 2);
2705 estimate += nbRain * (head + 24 + (nbits * npts) / 8 + 2);
2708 estimate += nbPress * (head + (nbits * npts) / 8 + 2);
2711 estimate += nbCloud * (head + 24 + (nbits * npts) / 8 + 2);
2714 estimate += nbReflectivity * (head + (nbits * npts) / 8 + 2);
2717 estimate += nbCAPEsfc * (head + (nbits * npts) / 8 + 2);
2720 estimate += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
2724 int atmEstimate = estimate;
2728 if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2731 npts = (int)(ceil(fabs(xmax - xmin) / 0.5) * ceil(fabs(ymax - ymin) / 0.5));
2732 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2733 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2737 (int)(ceil(fabs(xmax - xmin) / 0.25) * ceil(fabs(ymax - ymin) / 0.25));
2738 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2739 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2743 (int)(ceil(fabs(xmax - xmin) / 0.05) * ceil(fabs(ymax - ymin) / 0.1));
2744 nbrec = (int)fmin(4, days) * 24 / interval + 1;
2750 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2752 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2755 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2757 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2759 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2761 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2764 int wavEstimate = estimate - atmEstimate;
2766 wavEstimate = wavEstimate * 0.6;
2768 estimate = atmEstimate + wavEstimate;
2771 estimate = estimate * 0.65;
2773 wxString warningStr =
"";
2774 if (estimate / (1024 * 1024) > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB) {
2775 warningStr = wxString::Format(
"(Warning GRIB exceeds %d MB limit)",
2776 XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB);
2779 m_xygribPanel->m_sizeestimate_text->SetLabel(
2780 wxString::Format(
"%d kB %s", estimate / 1024, warningStr));
2782 m_gribSizeEstimate = estimate;
GRIB Data Visualization and Rendering Factory.
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.
#define SAVEDZONE
Save zone.
#define MANSELECT
Manual selection mode.
#define AUTOSELECT
Automatic selection mode.
@ 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.
XyGrib Model Configuration and Definitions.
void SetRequestButtonBitmap(int type)
Set the icon and tooltip for the download request button.
wxString m_grib_dir
Directory containing GRIB files.
grib_pi * pPlugIn
Plugin instance that owns this control bar.
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.
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.
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.
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.
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 Weather Data Plugin for OpenCPN.
@ 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.