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()));
574 m_xygribPanel->m_progress_gauge->SetValue(100 * ev.getTransferred() /
577 m_xygribPanel->m_status_text->SetLabel(
578 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
590void GribRequestSetting::OnWorldDownload(wxCommandEvent &event) {
593 m_downloading =
false;
594 m_download_handle = 0;
596 wxEVT_DOWNLOAD_EVENT,
597 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
599 m_btnDownloadWorld->SetLabelText(_(
"Download"));
600 m_staticTextInfo->SetLabelText(_(
"Download canceled"));
603 EnableDownloadButtons();
604 wxTheApp->ProcessPendingEvents();
609 m_downloading =
true;
611 EnableDownloadButtons();
612 m_btnDownloadWorld->SetLabelText(_(
"Cancel"));
613 m_staticTextInfo->SetLabelText(_(
"Preparing data on server..."));
616 switch (m_chECMWFResolution->GetSelection()) {
621 model =
"ecmwfaifs0p25";
627 std::ostringstream oss;
628 oss <<
"https://grib.bosun.io/grib?";
629 oss <<
"model=" << model;
634 oss <<
"&length=" << LengthSelToHours(m_chForecastLength->GetSelection());
636 wxString::Format(
"ocpn_%s_%li_%s.grb2", model.c_str(),
637 LengthSelToHours(m_chForecastLength->GetSelection()),
638 wxDateTime::Now().Format(
"%F-%H-%M"));
639 wxString path = m_parent.GetGribDir();
640 path.Append(wxFileName::GetPathSeparator());
641 path.Append(filename);
645 wxEVT_DOWNLOAD_EVENT,
646 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
650 while (m_downloading) {
651 wxTheApp->ProcessPendingEvents();
655 if (m_bTransferSuccess) {
656 m_staticTextInfo->SetLabelText(
657 wxString::Format(_(
"Download complete: %s"), path.c_str()));
664 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
666 m_parent.SetDialogsStyleSizePosition(
true);
670 m_staticTextInfo->SetLabelText(_(
"Download failed"));
673 m_btnDownloadWorld->SetLabelText(_(
"Download"));
675 EnableDownloadButtons();
678enum LocalSourceItem { SOURCE, AREA, GRIB };
680enum LocalGribDownloadType { DIRECT, MANIFEST, WEBPAGE };
683 GribCatalogInfo(LocalSourceItem type, wxString name, wxString description,
684 wxString url, wxString filename,
685 LocalGribDownloadType download_type,
double latmin,
686 double lonmin,
double latmax,
double lonmax)
689 description(description),
692 download_type(download_type),
697 LocalSourceItem type;
699 wxString description;
702 LocalGribDownloadType download_type;
709void GribRequestSetting::FillTreeCtrl(
wxJSONValue &data) {
710 m_SourcesTreeCtrl1->DeleteAllItems();
712 m_SourcesTreeCtrl1->AddRoot(_(
"Local high resolution forecasts"));
713 if (data.HasMember(
"sources") && data[
"sources"].IsArray()) {
714 for (
int i = 0; i < data[
"sources"].Size(); i++) {
717 LocalSourceItem::SOURCE, source[
"source"].AsString(),
718 source[
"description"].AsString(), source[
"url"].AsString(),
719 wxEmptyString, LocalGribDownloadType::WEBPAGE, 0, 0, 0, 0);
720 wxTreeItemId src_id = m_SourcesTreeCtrl1->AppendItem(
721 root, source[
"source"].AsString(), -1, -1, info);
722 if (source.
HasMember(
"areas") && source[
"areas"].IsArray()) {
723 for (
int j = 0; j < source[_T(
"areas")].
Size(); j++) {
726 LocalSourceItem::AREA, area[
"name"].AsString(),
727 source[
"description"].AsString(), source[
"url"].AsString(),
728 wxEmptyString, LocalGribDownloadType::WEBPAGE,
729 area[
"boundary"][
"lat_min"].AsDouble(),
730 area[
"boundary"][
"lon_min"].AsDouble(),
731 area[
"boundary"][
"lat_max"].AsDouble(),
732 area[
"boundary"][
"lon_max"].AsDouble());
733 m_SourcesTreeCtrl1->AppendItem(src_id, area[
"name"].AsString(), -1,
735 if (area.
HasMember(
"gribs") && area[
"gribs"].IsArray()) {
736 for (
int k = 0; k < area[
"gribs"].
Size(); k++) {
739 LocalSourceItem::GRIB, grib[
"name"].AsString(),
740 source[
"description"].AsString(),
741 grib.
HasMember(
"url") ? grib[
"url"].AsString()
742 : grib[
"cat_url"].AsString(),
743 grib.HasMember(
"filename") ? grib[
"filename"].AsString() :
"",
744 grib.HasMember(
"url") ? LocalGribDownloadType::DIRECT
745 : LocalGribDownloadType::MANIFEST,
746 area[
"boundary"][
"lat_min"].AsDouble(),
747 area[
"boundary"][
"lon_min"].AsDouble(),
748 area[
"boundary"][
"lat_max"].AsDouble(),
749 area[
"boundary"][
"lon_max"].AsDouble());
750 m_SourcesTreeCtrl1->AppendItem(
751 m_SourcesTreeCtrl1->GetLastChild(src_id),
752 grib[_T(
"name")].AsString(), -1, -1, info);
757 m_SourcesTreeCtrl1->CollapseAllChildren(src_id);
760 m_SourcesTreeCtrl1->Expand(root);
763void GribRequestSetting::ReadLocalCatalog() {
765 wxFileInputStream str(m_parent.
pPlugIn->m_local_sources_catalog);
767 reader.
Parse(str, &root);
771void GribRequestSetting::HighlightArea(
double latmax,
double lonmax,
772 double latmin,
double lonmin) {
773 m_parent.m_highlight_latmax = latmax;
774 m_parent.m_highlight_lonmax = lonmax;
775 m_parent.m_highlight_latmin = latmin;
776 m_parent.m_highlight_lonmin = lonmin;
779void GribRequestSetting::OnLocalTreeSelChanged(wxTreeEvent &event) {
780 wxTreeItemId item = m_SourcesTreeCtrl1->GetSelection();
783 if (src->type == LocalSourceItem::GRIB) {
784 m_stLocalDownloadInfo->SetLabelText(_(
"Download grib..."));
785 m_bLocal_source_selected =
true;
786 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
788 m_stLocalDownloadInfo->SetLabelText(_(
"Select grib..."));
789 m_bLocal_source_selected =
false;
790 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
793 EnableDownloadButtons();
796void GribRequestSetting::OnUpdateLocalCatalog(wxCommandEvent &event) {
799 m_downloading =
false;
800 m_download_handle = 0;
802 wxEVT_DOWNLOAD_EVENT,
803 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
805 m_btnDownloadLocal->SetLabelText(_(
"Download"));
806 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
809 EnableDownloadButtons();
810 wxTheApp->ProcessPendingEvents();
815 m_downloading =
true;
817 EnableDownloadButtons();
818 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
819 m_staticTextInfo->SetLabelText(_(
"Downloading catalog update..."));
824 wxEVT_DOWNLOAD_EVENT,
825 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
828 CATALOG_URL, m_parent.
pPlugIn->m_local_sources_catalog +
"new",
this,
830 while (m_downloading) {
831 wxTheApp->ProcessPendingEvents();
835 if (m_bTransferSuccess) {
836 wxRenameFile(m_parent.
pPlugIn->m_local_sources_catalog +
"new",
837 m_parent.
pPlugIn->m_local_sources_catalog,
true);
839 m_stLocalDownloadInfo->SetLabelText(_(
"Catalog update complete."));
841 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
844 m_btnDownloadLocal->SetLabelText(_(
"Download"));
846 EnableDownloadButtons();
849void GribRequestSetting::OnDownloadLocal(wxCommandEvent &event) {
852 m_downloading =
false;
853 m_download_handle = 0;
855 wxEVT_DOWNLOAD_EVENT,
856 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
858 m_btnDownloadLocal->SetLabelText(_(
"Download"));
859 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
862 EnableDownloadButtons();
863 wxTheApp->ProcessPendingEvents();
868 m_downloading =
true;
870 EnableDownloadButtons();
871 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
872 m_staticTextInfo->SetLabelText(_(
"Downloading grib..."));
875 m_SourcesTreeCtrl1->GetSelection()));
876 if (!src || src->type != LocalSourceItem::GRIB || src->url.IsEmpty()) {
877 m_downloading =
false;
878 m_stLocalDownloadInfo->SetLabelText(_(
"Download can't be started."));
879 m_btnDownloadWorld->SetLabelText(_(
"Download"));
881 EnableDownloadButtons();
887 wxEVT_DOWNLOAD_EVENT,
888 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
890 wxString url = src->url;
893 if (src->download_type == LocalGribDownloadType::MANIFEST) {
894 wxString path = m_parent.GetGribDir();
895 path.Append(wxFileName::GetPathSeparator());
896 path.Append(
"grib_manifest.json");
898 while (m_downloading) {
899 wxTheApp->ProcessPendingEvents();
904 if (!m_bTransferSuccess) {
906 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
910 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
914 wxFileInputStream str(path);
916 reader.
Parse(str, &root);
918 wxString parsed = root[
"url"].
AsString();
919 if (parsed.StartsWith(
"http")) {
922 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
929 m_downloading =
false;
930 m_download_handle = 0;
931 Disconnect(wxEVT_DOWNLOAD_EVENT,
935 m_btnDownloadLocal->SetLabelText(_(
"Download"));
936 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
939 EnableDownloadButtons();
940 wxTheApp->ProcessPendingEvents();
946 m_downloading =
true;
951 wxEVT_DOWNLOAD_EVENT,
952 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
955 if (!src->filename.IsEmpty()) {
956 filename = src->filename;
961 filename.Replace(
"?",
"_");
962 filename.Replace(
"&",
"_");
963 if (!(filename.Contains(
".grb2") || filename.Contains(
".grib2") ||
964 filename.Contains(
".grb") || filename.Contains(
".grib"))) {
965 filename.Append(
".grb");
969 wxString path = m_parent.GetGribDir();
970 path.Append(wxFileName::GetPathSeparator());
971 path.Append(filename);
973 while (m_downloading) {
974 wxTheApp->ProcessPendingEvents();
978 if (m_bTransferSuccess) {
979 m_stLocalDownloadInfo->SetLabelText(_(
"Grib download complete."));
980 m_stLocalDownloadInfo->SetLabelText(
981 wxString::Format(_(
"Download complete: %s"), path.c_str()));
989 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
991 m_parent.SetDialogsStyleSizePosition(
true);
995 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
998 m_btnDownloadWorld->SetLabelText(_(
"Download"));
1000 EnableDownloadButtons();
1003void GribRequestSetting::EnableDownloadButtons() {
1004 switch (m_downloadType) {
1006 m_btnDownloadWorld->Enable(
true);
1007 m_btnDownloadLocal->Enable(
false);
1008 m_buttonUpdateCatalog->Enable(
false);
1012 m_btnDownloadWorld->Enable(
false);
1013 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1014 m_buttonUpdateCatalog->Enable(
false);
1017 m_xygribPanel->m_download_button->Enable(
true);
1020 m_btnDownloadWorld->Enable(
true);
1021 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1022 m_buttonUpdateCatalog->Enable(
true);
1023 m_xygribPanel->m_download_button->Enable(
true);
1028void GribRequestSetting::StopGraphicalZoneSelection() {
1048 if (!m_AllowSend)
return;
1054 UpdateGribSizeEstimate();
1057void GribRequestSetting::ApplyRequestConfig(
unsigned rs,
unsigned it,
1060 const wxString res[][RESOLUTIONS] = {
1061 {_T(
"0.25"), _T(
"0.5"), _T(
"1.0"), _T(
"2.0")},
1062 {_T(
"0.2"), _T(
"0.8"), _T(
"1.6"), wxEmptyString},
1063 {_T(
"0.08"), _T(
"0.24"), _T(
"1.0"), wxEmptyString},
1064 {_T(
"0.03"), _T(
"0.24"), _T(
"1.0"), wxEmptyString},
1065 {_T(
"0.0625"), _T(
"0.125"), wxEmptyString, wxEmptyString},
1066 {_T(
"0.4"), _T(
"1.0"), _T(
"2.0"), wxEmptyString}
1069 IsZYGRIB = m_pMailTo->GetCurrentSelection() == ZYGRIB;
1071 m_pModel->SetSelection(GFS);
1072 IsGFS = m_pModel->GetCurrentSelection() == GFS;
1073 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1074 bool IsHRRR = m_pModel->GetCurrentSelection() == HRRR;
1075 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1076 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1079 m_pResolution->Clear();
1080 if (m_pModel->GetCurrentSelection() >= 0) {
1081 for (
int i = 0; i < RESOLUTIONS; i++) {
1082 if (res[m_pModel->GetCurrentSelection()][i] != wxEmptyString) {
1083 wxString s = res[m_pModel->GetCurrentSelection()][i];
1084 m_pResolution->Append(s);
1088 m_pResolution->SetSelection(rs);
1092 l = (IsGFS || IsRTOFS || IsICON || IsECMWF) ? 3 : IsHRRR ? 1 : 6;
1095 m = IsHRRR ? 2 : 25;
1097 m_pInterval->Clear();
1098 for (
unsigned i = l; i < m; i *= 2)
1099 m_pInterval->Append(wxString::Format(_T(
"%d"), i));
1100 m_pInterval->SetSelection(wxMin(it, m_pInterval->GetCount() - 1));
1110 m_pTimeRange->Clear();
1111 for (
unsigned i = 2; i < l + 1; i++)
1112 m_pTimeRange->Append(wxString::Format(_T(
"%d"), i));
1113 m_pTimeRange->SetSelection(wxMin(l - 2, tr));
1115 m_pModel->Enable(!IsZYGRIB);
1116 m_pWind->SetValue(!IsRTOFS);
1117 m_pPress->SetValue(!IsRTOFS);
1118 m_pWaves->SetValue(m_RequestConfigBase.GetChar(8) ==
'X' && IsGFS);
1119 m_pWaves->Enable(IsECMWF ||
1120 (IsGFS && m_pTimeRange->GetCurrentSelection() < 7));
1122 m_pRainfall->SetValue(m_RequestConfigBase.GetChar(9) ==
'X' &&
1124 m_pRainfall->Enable(IsGFS || IsHRRR);
1125 m_pCloudCover->SetValue(m_RequestConfigBase.GetChar(10) ==
'X' && IsGFS);
1126 m_pCloudCover->Enable(IsGFS);
1127 m_pAirTemp->SetValue(m_RequestConfigBase.GetChar(11) ==
'X' &&
1128 (IsGFS || IsHRRR || IsICON || IsECMWF));
1129 m_pAirTemp->Enable(IsGFS || IsHRRR || IsICON || IsECMWF);
1130 m_pSeaTemp->SetValue(m_RequestConfigBase.GetChar(12) ==
'X' &&
1131 ((!IsZYGRIB && IsGFS) || IsRTOFS || IsHRRR || IsICON));
1132 m_pSeaTemp->Enable(!IsZYGRIB && (IsGFS || IsHRRR || IsICON));
1133 m_pWindGust->SetValue(m_RequestConfigBase.GetChar(14) ==
'X' &&
1134 (IsGFS || IsHRRR || IsICON));
1135 m_pWindGust->Enable(IsGFS || IsHRRR || IsICON);
1136 m_pCAPE->SetValue(m_RequestConfigBase.GetChar(15) ==
'X' &&
1138 m_pCAPE->Enable(IsGFS || IsHRRR);
1139 m_pReflectivity->Enable(IsGFS || IsHRRR);
1141 m_pAltitudeData->SetValue(
1142 (IsGFS || IsICON || IsECMWF)
1143 ? m_RequestConfigBase.GetChar(17) ==
'X'
1145 m_pAltitudeData->Enable(IsGFS || IsICON || IsECMWF);
1146 m_p850hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(18) ==
'X'
1148 m_p850hpa->Enable(IsZYGRIB);
1149 m_p700hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(19) ==
'X'
1151 m_p700hpa->Enable(IsZYGRIB);
1152 m_p500hpa->SetValue((IsGFS || IsICON || IsECMWF)
1153 ? m_RequestConfigBase.GetChar(20) ==
'X'
1155 m_p500hpa->Enable(IsGFS || IsICON || IsECMWF);
1156 m_p300hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(21) ==
'X'
1158 m_p300hpa->Enable(IsZYGRIB);
1160 m_pCurrent->SetValue(IsRTOFS);
1161 m_pCurrent->Enable(
false);
1164 m_cMovingGribEnabled->Show(!IsZYGRIB);
1165 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1166 m_cMovingGribEnabled->IsShown());
1168 m_fgLog->ShowItems(IsZYGRIB);
1170 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1172 m_fgAltitudeData->ShowItems(
1173 m_pAltitudeData->IsChecked());
1176void GribRequestSetting::OnTopChange(wxCommandEvent &event) {
1178 if (m_pMailTo->GetCurrentSelection() == ZYGRIB) {
1179 m_pMailTo->SetSelection(0);
1182 _(
"Sorry...\nZyGrib momentary stopped providing this service...\nOnly "
1183 "Saildocs option is available"),
1184 _(
"Warning"), wxOK);
1186 ApplyRequestConfig(m_pResolution->GetCurrentSelection(),
1187 m_pInterval->GetCurrentSelection(),
1188 m_pTimeRange->GetCurrentSelection());
1190 m_cMovingGribEnabled->Show(m_pMailTo->GetCurrentSelection() == SAILDOCS);
1192 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1194 SetRequestDialogSize();
1197void GribRequestSetting::UpdateAreaSelectionState() {
1206void GribRequestSetting::OnZoneSelectionModeChange(wxCommandEvent &event) {
1207 StopGraphicalZoneSelection();
1216 }
else if (event.GetId() ==
MANSELECT) {
1222 m_cUseSavedZone->SetValue(
false);
1223 }
else if (event.GetId() ==
SAVEDZONE) {
1231 UpdateAreaSelectionState();
1232 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1234 SetRequestDialogSize();
1248 center.x = x + (zw / 2);
1249 center.y = y + (zh / 2);
1255 wxColour pen_color, back_color;
1256 GetGlobalColor(_T (
"DASHR" ), &pen_color);
1257 GetGlobalColor(_T (
"YELO1" ), &back_color);
1259 int label_offsetx = 5, label_offsety = 1;
1262 EstimateFileSize(&size);
1264 wxString label(_(
"Coord. "));
1265 label.Append(toMailFormat(1,
m_spMaxLat->GetValue()) + _T(
" "));
1266 label.Append(toMailFormat(0,
m_spMinLon->GetValue()) + _T(
" "));
1267 label.Append(toMailFormat(1,
m_spMinLat->GetValue()) + _T(
" "));
1268 label.Append(toMailFormat(0,
m_spMaxLon->GetValue()) + _T(
"\n"));
1269 label.Append(_T(
"Estim. Size "))
1270 .Append((wxString::Format(_T(
"%1.2f " ), size) + _(
"MB")));
1273 wxPen pen(pen_color);
1276 m_pdc->SetBrush(*wxTRANSPARENT_BRUSH);
1277 m_pdc->DrawRectangle(x, y, zw, zh);
1282 sdc.GetMultiLineTextExtent(label, &w, &h, &sl, font);
1284 m_pdc->GetMultiLineTextExtent(label, &w, &h, &sl, font);
1288 w += 2 * label_offsetx, h += 2 * label_offsety;
1289 x = center.x - (w / 2);
1290 y = center.y - (h / 2);
1292 h *= m_displayScale;
1293 w *= m_displayScale;
1300 mdc.SetBrush(back_color);
1301 mdc.SetPen(*wxTRANSPARENT_PEN);
1302 mdc.SetTextForeground(wxColor(0, 0, 0));
1303 mdc.DrawRectangle(0, 0, w, h);
1304 mdc.DrawLabel(label, wxRect(label_offsetx, label_offsety, w, h));
1306 wxImage im = bm.ConvertToImage();
1308 w = im.GetWidth(), h = im.GetHeight();
1309 for (
int j = 0; j < h; j++)
1310 for (
int i = 0; i < w; i++) im.SetAlpha(i, j, 155);
1312 m_pdc->DrawBitmap(im, x, y,
true);
1316#ifndef USE_ANDROID_GLES2
1323 m_oDC->SetPen(wxPen(pen_color, 3));
1326 outline[0] = wxPoint(x, y);
1327 outline[1] = wxPoint(x + zw, y);
1328 outline[2] = wxPoint(x + zw, y + zh);
1329 outline[3] = wxPoint(x, y + zh);
1330 outline[4] = wxPoint(x, y);
1331 m_oDC->DrawLines(5, outline);
1333 m_oDC->SetFont(*font);
1335 m_oDC->GetTextExtent(label, &w, &h);
1336 h *= m_displayScale;
1337 w *= m_displayScale;
1339 m_oDC->GetTextExtent(
"W", &ww, &hw);
1341 int label_offsetx = ww, label_offsety = 1;
1342 int x = center.x - w / 2;
1343 int y = center.y - h / 2;
1345 w += 2 * label_offsetx, h += 2 * label_offsety;
1347 m_oDC->SetBrush(wxBrush(back_color));
1348 m_oDC->DrawRoundedRectangle(x, y, w, h, 0);
1351 m_oDC->SetPen(wxPen(wxColour(0, 0, 0), 1));
1353 outline[0] = wxPoint(x, y);
1354 outline[1] = wxPoint(x + w, y);
1355 outline[2] = wxPoint(x + w, y + h);
1356 outline[3] = wxPoint(x, y + h);
1357 outline[4] = wxPoint(x, y);
1358 m_oDC->DrawLines(5, outline);
1360 m_oDC->DrawText(label, x + label_offsetx, y + label_offsety);
1380void GribRequestSetting::OnMovingClick(wxCommandEvent &event) {
1381 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1382 m_cMovingGribEnabled->IsShown());
1384 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1385 SetRequestDialogSize();
1390void GribRequestSetting::OnCoordinatesChange(wxSpinEvent &event) {
1391 SetCoordinatesText();
1393 StopGraphicalZoneSelection();
1395 if (!m_AllowSend)
return;
1397 m_MailImage->SetValue(WriteMail());
1400void GribRequestSetting::OnAnyChange(wxCommandEvent &event) {
1401 m_fgAltitudeData->ShowItems(m_pAltitudeData->IsChecked());
1403 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1405 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1407 SetRequestDialogSize();
1410void GribRequestSetting::OnTimeRangeChange(wxCommandEvent &event) {
1411 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1413 if (m_pModel->GetCurrentSelection() == 0) {
1414 if (m_pTimeRange->GetCurrentSelection() >
1416 m_pWaves->SetValue(0);
1417 m_pWaves->Enable(
false);
1420 _(
"You request a forecast for more than 8 days horizon.\nThis is "
1421 "conflicting with Wave data which will be removed from your "
1422 "request.\nDon't forget that beyond the first 8 days, the "
1423 "resolution will be only 2.5\u00B0x2.5\u00B0\nand the time "
1424 "intervall 12 hours."),
1427 m_pWaves->Enable(
true);
1430 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1432 SetRequestDialogSize();
1435void GribRequestSetting::OnOK(wxCommandEvent &event) {
1436 bool IsCOAMPS = m_pModel->GetCurrentSelection() == COAMPS;
1437 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1438 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1439 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1440 m_RequestConfigBase.SetChar(
1441 0, (
char)(m_pMailTo->GetCurrentSelection() +
'0'));
1442 m_cMovingGribEnabled->IsChecked()
1443 ? m_RequestConfigBase.SetChar(16,
'X')
1444 : m_RequestConfigBase.SetChar(16,
'.');
1447 m_RequestConfigBase.SetChar(
1448 1, (
char)(m_pModel->GetCurrentSelection() +
'0'));
1450 m_RequestConfigBase.SetChar(
1451 2, (
char)(m_pResolution->GetCurrentSelection() +
'0'));
1453 m_RequestConfigBase.SetChar(3,
1454 (
char)(m_pInterval->GetCurrentSelection() +
'0'));
1457 range.Printf(_T(
"%x"), m_pTimeRange->GetCurrentSelection() +
1459 m_RequestConfigBase.SetChar(4, range.GetChar(0));
1461 if (IsZYGRIB && m_pWModel->IsShown())
1462 m_RequestConfigBase.SetChar(
1463 5, (
char)(m_pWModel->GetCurrentSelection() +
'0'));
1465 m_RequestConfigBase.SetChar(
1467 m_RequestConfigBase.SetChar(
1470 if (!IsCOAMPS && !IsRTOFS) {
1471 m_pWindGust->IsChecked() ? m_RequestConfigBase.SetChar(14,
'X')
1472 : m_RequestConfigBase.SetChar(14,
'.');
1473 m_pWaves->IsChecked() ? m_RequestConfigBase.SetChar(8,
'X')
1474 : m_RequestConfigBase.SetChar(8,
'.');
1475 m_pRainfall->IsChecked() ? m_RequestConfigBase.SetChar(9,
'X')
1476 : m_RequestConfigBase.SetChar(9,
'.');
1477 m_pCloudCover->IsChecked() ? m_RequestConfigBase.SetChar(10,
'X')
1478 : m_RequestConfigBase.SetChar(10,
'.');
1479 m_pAirTemp->IsChecked() ? m_RequestConfigBase.SetChar(11,
'X')
1480 : m_RequestConfigBase.SetChar(11,
'.');
1481 m_pSeaTemp->IsChecked() ? m_RequestConfigBase.SetChar(12,
'X')
1482 : m_RequestConfigBase.SetChar(12,
'.');
1483 m_pCAPE->IsChecked() ? m_RequestConfigBase.SetChar(15,
'X')
1484 : m_RequestConfigBase.SetChar(15,
'.');
1487 m_pCurrent->IsChecked() ? m_RequestConfigBase.SetChar(13,
'X')
1488 : m_RequestConfigBase.SetChar(13,
'.');
1490 if (IsGFS || IsICON || IsECMWF) {
1491 m_pAltitudeData->IsChecked()
1492 ? m_RequestConfigBase.SetChar(17,
'X')
1493 : m_RequestConfigBase.SetChar(17,
'.');
1494 m_p500hpa->IsChecked() ? m_RequestConfigBase.SetChar(20,
'X')
1495 : m_RequestConfigBase.SetChar(20,
'.');
1498 m_p850hpa->IsChecked() ? m_RequestConfigBase.SetChar(18,
'X')
1499 : m_RequestConfigBase.SetChar(18,
'.');
1500 m_p700hpa->IsChecked() ? m_RequestConfigBase.SetChar(19,
'X')
1501 : m_RequestConfigBase.SetChar(19,
'.');
1502 m_p300hpa->IsChecked() ? m_RequestConfigBase.SetChar(21,
'X')
1503 : m_RequestConfigBase.SetChar(21,
'.');
1510wxString GribRequestSetting::WriteMail() {
1512 int limit = IsZYGRIB ? 2 : 0;
1516 const wxString s[] = {_T(
","), _T(
" ")};
1517 const wxString p[][11] = {
1519 {_T(
"APCP"), _T(
"TCDC"), _T(
"AIRTMP"), _T(
"HTSGW,WVPER,WVDIR"),
1520 _T(
"SEATMP"), _T(
"GUST"), _T(
"CAPE"), wxEmptyString, wxEmptyString,
1521 _T(
"WIND500,HGT500"), wxEmptyString},
1526 {_T(
""), _T(
""), _T(
"AIRTMP"), _T(
""), _T(
"SFCTMP"), _T(
"GUST"), _T(
""),
1527 _T(
""), _T(
""), _T(
"WIND500,HGT500"), _T(
"")},
1529 {_T(
""), _T(
""), _T(
"TEMP"), _T(
"WAVES"), _T(
""), _T(
""), _T(
""), _T(
""),
1530 _T(
""), _T(
"WIND500,HGT500"), _T(
"")},
1532 {_T(
"PRECIP"), _T(
"CLOUD"), _T(
"TEMP"), _T(
"WVSIG WVWIND"), wxEmptyString,
1533 _T(
"GUST"), _T(
"CAPE"), _T(
"A850"), _T(
"A700"), _T(
"A500"), _T(
"A300")}};
1535 wxString r_topmess, r_parameters, r_zone;
1537 switch (m_pMailTo->GetCurrentSelection()) {
1539 r_zone = toMailFormat(1,
m_spMaxLat->GetValue()) + _T(
",") +
1540 toMailFormat(1,
m_spMinLat->GetValue()) + _T(
",") +
1541 toMailFormat(2,
m_spMinLon->GetValue()) + _T(
",") +
1543 r_topmess = wxT(
"send ");
1544 r_topmess.Append(m_pModel->GetStringSelection() + _T(
":"));
1545 r_topmess.Append(r_zone + _T(
"|"));
1546 r_topmess.Append(m_pResolution->GetStringSelection())
1548 .Append(m_pResolution->GetStringSelection())
1551 m_pInterval->GetStringSelection().ToDouble(&v);
1552 r_topmess.Append(wxString::Format(_T(
"0,%d,%d"), (
int)v, (
int)v * 2));
1553 m_pTimeRange->GetStringSelection().ToDouble(&v);
1554 r_topmess.Append(wxString::Format(_T(
"..%d"), (
int)v * 24) + _T(
"|=\n"));
1561 r_zone = toMailFormat(1,
m_spMinLat->GetValue()) +
1562 toMailFormat(2,
m_spMinLon->GetValue()) + _T(
" ") +
1564 toMailFormat(2, maxlon);
1565 r_topmess = wxT(
"login : ");
1566 r_topmess.Append(m_pLogin->GetValue() + _T(
"\n"));
1567 r_topmess.Append(wxT(
"code :"));
1568 r_topmess.Append(m_pCode->GetValue() + _T(
"\n"));
1569 r_topmess.Append(wxT(
"area : "));
1570 r_topmess.append(r_zone + _T(
"\n"));
1571 r_topmess.Append(wxT(
"resol : "));
1572 r_topmess.append(m_pResolution->GetStringSelection() + _T(
"\n"));
1573 r_topmess.Append(wxT(
"days : "));
1574 r_topmess.append(m_pTimeRange->GetStringSelection() + _T(
"\n"));
1575 r_topmess.Append(wxT(
"hours : "));
1576 r_topmess.append(m_pInterval->GetStringSelection() + _T(
"\n"));
1577 if (m_pWaves->IsChecked()) {
1578 r_topmess.Append(wxT(
"waves : "));
1579 r_topmess.append(m_pWModel->GetStringSelection() + _T(
"\n"));
1581 r_topmess.Append(wxT(
"meteo : "));
1582 r_topmess.append(m_pModel->GetStringSelection() + _T(
"\n"));
1583 if (m_pLogin->GetValue().IsEmpty() || m_pCode->GetValue().IsEmpty())
1588 int GFSZ = IsZYGRIB ? 6 : 0;
1589 switch (m_pModel->GetCurrentSelection()) {
1591 r_parameters = wxT(
"WIND") + s[m_pMailTo->GetCurrentSelection()] +
1593 if (m_pRainfall->IsChecked())
1594 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1596 if (m_pCloudCover->IsChecked())
1597 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1599 if (m_pAirTemp->IsChecked())
1600 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1602 if (m_pWaves->IsChecked())
1603 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1605 if (m_pSeaTemp->IsChecked())
1606 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1608 if (m_pWindGust->IsChecked())
1609 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1611 if (m_pCAPE->IsChecked())
1612 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1614 if (m_pAltitudeData->IsChecked()) {
1615 if (m_p850hpa->IsChecked())
1616 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1618 if (m_p700hpa->IsChecked())
1619 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1621 if (m_p500hpa->IsChecked())
1622 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1624 if (m_p300hpa->IsChecked())
1625 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1630 r_parameters = wxT(
"WIND,PRMSL");
1634 r_parameters = wxT(
"CUR,WTMP");
1637 r_parameters = wxT(
"WIND,PRMSL");
1639 if (m_pRainfall->IsChecked())
1640 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][0]);
1641 if (m_pAirTemp->IsChecked())
1642 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][2]);
1643 if (m_pSeaTemp->IsChecked())
1644 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][4]);
1645 if (m_pWindGust->IsChecked())
1646 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][5]);
1647 if (m_pCAPE->IsChecked())
1648 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][6]);
1651 r_parameters = wxT(
"WIND,PRMSL");
1653 if (m_pAirTemp->IsChecked())
1654 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][2]);
1655 if (m_pSeaTemp->IsChecked())
1656 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][4]);
1657 if (m_pWindGust->IsChecked())
1658 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][5]);
1659 if (m_pAltitudeData->IsChecked()) {
1660 if (m_p500hpa->IsChecked())
1661 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][9]);
1665 r_parameters = wxT(
"WIND,MSLP");
1667 if (m_pAirTemp->IsChecked())
1668 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][2]);
1669 if (m_pAltitudeData->IsChecked()) {
1670 if (m_p500hpa->IsChecked())
1671 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1674 if (m_pWaves->IsChecked())
1675 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][3]);
1678 if (!IsZYGRIB && m_cMovingGribEnabled->IsChecked())
1679 r_parameters.Append(wxString::Format(
1680 _T(
"|%d,%d"), m_sMovingSpeed->GetValue(), m_sMovingCourse->GetValue()));
1684 char c = m_pMailTo->GetCurrentSelection() == SAILDOCS ?
',' :
' ';
1685 for (
size_t i = 0; i < r_parameters.Len(); i++) {
1686 if (r_parameters.GetChar(i) ==
'|')
1688 if (r_parameters.GetChar(i) == c) j++;
1690 r_parameters.insert(i + 1, m_pMailTo->GetCurrentSelection() == SAILDOCS
1698 m_MailError_Nb += EstimateFileSize(&size);
1700 m_tFileSize->SetLabel(wxString::Format(_T(
"%1.2f " ), size) + _(
"MB"));
1703 m_tLimit->SetLabel(wxString(_T(
"( ")) + _(
"Max") +
1704 wxString::Format(_T(
" %d "), limit) + _(
"MB") +
1706 if (size > limit) m_MailError_Nb += 2;
1708 m_tLimit->SetLabel(wxEmptyString);
1710 return wxString(r_topmess + r_parameters);
1713int GribRequestSetting::EstimateFileSize(
double *size) {
1714 if (!size)
return 0;
1718 double reso, time, inter;
1719 m_pResolution->GetStringSelection().ToDouble(&reso);
1720 m_pTimeRange->GetStringSelection().ToDouble(&time);
1721 m_pInterval->GetStringSelection().ToDouble(&inter);
1725 if (maxlat - minlat < 0)
return 3;
1726 double wlon = (maxlon > minlon ? 0 : 360) + maxlon - minlon;
1727 if (wlon > 180 || (maxlat - minlat > 180))
return 4;
1729 if (fabs(wlon) < 2 * reso || maxlat - minlat < 2 * reso)
1732 int npts = (int)(ceil(((
double)(maxlat - minlat) / reso)) *
1733 ceil(((
double)(wlon) / reso)));
1735 if (m_pModel->GetCurrentSelection() == COAMPS)
1736 npts = wxMin(npts, (
int)(ceil(40.0 / reso) * ceil(40.0 / reso)));
1739 int nbrec = (int)(time * 24 / inter) + 1;
1740 int nbPress = (m_pPress->IsChecked()) ? nbrec : 0;
1741 int nbWind = (m_pWind->IsChecked()) ? 2 * nbrec : 0;
1742 int nbwave = (m_pWaves->IsChecked()) ? 2 * nbrec : 0;
1743 int nbRain = (m_pRainfall->IsChecked()) ? nbrec - 1 : 0;
1744 int nbCloud = (m_pCloudCover->IsChecked()) ? nbrec - 1 : 0;
1745 int nbTemp = (m_pAirTemp->IsChecked()) ? nbrec : 0;
1746 int nbSTemp = (m_pSeaTemp->IsChecked()) ? nbrec : 0;
1747 int nbGUSTsfc = (m_pWindGust->IsChecked()) ? nbrec : 0;
1748 int nbCurrent = (m_pCurrent->IsChecked()) ? nbrec : 0;
1749 int nbCape = (m_pCAPE->IsChecked()) ? nbrec : 0;
1751 IsZYGRIB ? 5 * nbrec : 3 * nbrec;
1755 double estime = 0.0;
1759 estime += nbWind * (head + (nbits * npts) / 8 + 2);
1760 estime += nbCurrent * (head + (nbits * npts) / 8 + 2);
1763 estime += nbTemp * (head + (nbits * npts) / 8 + 2);
1764 estime += nbSTemp * (head + (nbits * npts) / 8 + 2);
1767 estime += nbRain * (head + (nbits * npts) / 8 + 2);
1770 estime += nbPress * (head + (nbits * npts) / 8 + 2);
1773 estime += nbCloud * (head + (nbits * npts) / 8 + 2);
1776 estime += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
1779 estime += nbCape * (head + (nbits * npts) / 8 + 2);
1782 estime += nbwave * (head + (nbits * npts) / 8 + 2);
1784 if (m_pAltitudeData->IsChecked()) {
1786 if (m_p850hpa->IsChecked()) nbalt++;
1787 if (m_p700hpa->IsChecked()) nbalt++;
1788 if (m_p500hpa->IsChecked()) nbalt++;
1789 if (m_p300hpa->IsChecked()) nbalt++;
1792 estime += nbAltitude * nbalt * (head + (nbits * npts) / 8 + 2);
1795 *size = estime / (1024. * 1024.);
1800const wxString EncodeURL(
const wxString &uri) {
1801 static std::unordered_map<int, wxString> sEncodeMap = {
1802 {(int)
'!',
"%21"}, {(int)
'#',
"%23"}, {(int)
'$',
"%24"},
1803 {(int)
'&',
"%26"}, {(int)
'\'',
"%27"}, {(int)
'(',
"%28"},
1804 {(int)
')',
"%29"}, {(int)
'*',
"%2A"}, {(int)
'+',
"%2B"},
1805 {(int)
',',
"%2C"}, {(int)
';',
"%3B"}, {(int)
'=',
"%3D"},
1806 {(int)
'?',
"%3F"}, {(int)
'@',
"%40"}, {(int)
'[',
"%5B"},
1807 {(int)
']',
"%5D"}, {(int)
' ',
"%20"}, {(int)
'|',
"%7C"},
1808 {(int)
':',
"%3A"}, {(int)
'\n',
"%0A"}};
1811 for (
size_t i = 0; i < uri.length(); ++i) {
1813 std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((
int)ch);
1814 if (iter != sEncodeMap.end()) {
1815 encoded << iter->second;
1823void GribRequestSetting::OnSendMaiL(wxCommandEvent &event) {
1824 StopGraphicalZoneSelection();
1831 m_MailImage->SetForegroundColour(
1835 m_MailImage->SetValue(WriteMail());
1836 SetRequestDialogSize();
1841 const wxString error[] = {
1843 _(
"Before sending an email to Zygrib you have to enter your Login and "
1844 "Code.\nPlease visit www.zygrib.org/ and follow instructions..."),
1845 _(
"Too big file! zyGrib limit is 2Mb!"),
1846 _(
"Error! Max Lat lower than Min Lat or Max Lon lower than Min Lon!"),
1847 _(
"Too large area! Each side must be less than 180\u00B0!"),
1848 _(
"Too small area for this resolution!")};
1850 ::wxBeginBusyCursor();
1852 m_MailImage->SetForegroundColour(wxColor(255, 0, 0));
1853 m_AllowSend =
false;
1855 if (m_MailError_Nb) {
1856 if (m_MailError_Nb > 7) {
1857 m_MailImage->SetValue(error[1] + error[0] + error[m_MailError_Nb - 6]);
1859 if (m_MailError_Nb == 6) m_MailError_Nb = 1;
1860 m_MailImage->SetValue(error[m_MailError_Nb]);
1864 SetRequestDialogSize();
1866 ::wxEndBusyCursor();
1871 std::string mailto =
1872 (m_pMailTo->GetCurrentSelection() == SAILDOCS
1873 ? m_MailToAddresses.BeforeFirst(_T(
';'))
1874 : m_MailToAddresses.AfterFirst(_T(
';')).BeforeFirst(_T(
';')))
1876 std::string mailfrom = m_pSenderAddress->GetValue().ToStdString();
1878 std::regex mailregex(
"^([a-z0-9+_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$");
1880 if ((!mailto.empty() && !std::regex_match(mailto, mailregex)) ||
1881 (!mailfrom.empty() && !std::regex_match(mailfrom, mailregex))) {
1884 _(
"Sender or recipient e-mail address seems invalid.\nPlease correct "
1885 "it in the configuration file."),
1886 _(
"Error"), wxOK | wxICON_ERROR);
1896 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1897 ? _T(
"grib-request")
1900 EncodeURL(WriteMail()),
1904 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1905 ? _T(
"grib-request")
1913 if (mail.Send(*message, m_SendMethod)) {
1915 m_MailImage->SetValue(
1916 _(
"Your request is ready. An email is prepared in your email "
1917 "environment. \nYou have just to verify and send it...\nSave or "
1918 "Cancel to finish...or Continue..."));
1920 if (m_SendMethod == 0) {
1921 m_MailImage->SetValue(
1922 _(
"Your request is ready. An email is prepared in your email "
1923 "environment. \nYou have just to verify and send it...\nSave or "
1924 "Cancel to finish...or Continue..."));
1926 m_MailImage->SetValue(
1927 _(
"Your request was sent \n(if your system has an MTA configured and "
1928 "is able to send email).\nSave or Cancel to finish...or "
1933 m_MailImage->SetValue(
1934 _(
"Request can't be sent. Please verify your email systeme "
1935 "parameters.\nYou should also have a look at your log file.\nSave or "
1936 "Cancel to finish..."));
1940 SetRequestDialogSize();
1942 ::wxEndBusyCursor();
1947wxString GribRequestSetting::BuildXyGribUrl() {
1950 wxString::Format(
"http://grbsrv.opengribs.org/getmygribs2.php?");
1952 urlStr << wxString::Format(
"la1=%.0f", floor(
GetMinLat()));
1953 urlStr << wxString::Format(
"&la2=%.0f", ceil(
GetMaxLat()));
1954 urlStr << wxString::Format(
"&lo1=%.0f", floor(
GetMinLon()));
1955 urlStr << wxString::Format(
"&lo2=%.0f", ceil(
GetMaxLon()));
1958 urlStr << wxString::Format(
1960 xygribAtmModelList[m_selectedAtmModelIndex]
1961 ->reqName[m_xygribPanel->m_resolution_choice->GetSelection()]);
1963 urlStr << wxString::Format(
1965 xygribAtmModelList[m_selectedAtmModelIndex]
1966 ->interval[m_xygribPanel->m_interval_choice->GetSelection()]);
1968 urlStr << wxString::Format(
1969 "&days=%d", m_xygribPanel->m_duration_choice->GetSelection() + 1);
1973 wxString selStr = m_xygribPanel->m_run_choice->GetStringSelection();
1974 if (selStr.IsSameAs(
"18h",
false)) {
1975 urlStr <<
"&cyc=18";
1976 }
else if (selStr.IsSameAs(
"12h",
false)) {
1977 urlStr <<
"&cyc=12";
1978 }
else if (selStr.IsSameAs(
"6h",
false)) {
1979 urlStr <<
"&cyc=06";
1980 }
else if (selStr.IsSameAs(
"0h",
false)) {
1981 urlStr <<
"&cyc=00";
1983 urlStr <<
"&cyc=last";
1988 if (m_xygribPanel->m_wind_cbox->IsEnabled() &&
1989 m_xygribPanel->m_wind_cbox->IsChecked())
1991 if (m_xygribPanel->m_pressure_cbox->IsEnabled() &&
1992 m_xygribPanel->m_pressure_cbox->IsChecked()) {
1993 if (xygribAtmModelList[m_selectedAtmModelIndex]->altPressure) {
1999 if (m_xygribPanel->m_precipitation_cbox->IsEnabled() &&
2000 m_xygribPanel->m_precipitation_cbox->IsChecked())
2002 if (m_xygribPanel->m_cloudcover_cbox->IsEnabled() &&
2003 m_xygribPanel->m_cloudcover_cbox->IsChecked())
2005 if (m_xygribPanel->m_temperature_cbox->IsEnabled() &&
2006 m_xygribPanel->m_temperature_cbox->IsChecked())
2008 if (m_xygribPanel->m_cape_cbox->IsEnabled() &&
2009 m_xygribPanel->m_cape_cbox->IsChecked())
2011 if (m_xygribPanel->m_reflectivity_cbox->IsEnabled() &&
2012 m_xygribPanel->m_reflectivity_cbox->IsChecked())
2014 if (m_xygribPanel->m_gust_cbox->IsEnabled() &&
2015 m_xygribPanel->m_gust_cbox->IsChecked())
2019 if ((m_selectedWaveModelIndex >= 0) &&
2020 (xygribWaveModelList[m_selectedWaveModelIndex] !=
nullptr)) {
2021 wxString modelStr = wxString::Format(
2022 "&wmdl=%s", xygribWaveModelList[m_selectedWaveModelIndex]->reqName);
2023 wxString wParams =
"";
2024 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2027 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2028 wParams <<
"h;d;p;";
2030 if (wParams.length() > 0) {
2031 urlStr << wxString::Format(
"%s&wpar=%s", modelStr.c_str(),
2034 urlStr <<
"&wmdl=none";
2037 urlStr <<
"&wmdl=none";
2045wxString GribRequestSetting::BuildGribFileName() {
2046 wxString selStr = m_xygribPanel->m_resolution_choice->GetStringSelection();
2047 selStr.Replace(
".",
"P");
2050 if (m_selectedWaveModelIndex < 0) {
2051 fileName = wxString::Format(
2052 "XyGrib_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2053 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr);
2055 fileName = wxString::Format(
2056 "XyGrib_%s_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2057 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr,
2058 m_xygribPanel->m_wavemodel_choice->GetStringSelection());
2070void GribRequestSetting::OnXyGribDownloadButton(wxCommandEvent &event) {
2072 if (m_downloading) {
2076 m_downloading =
false;
2077 m_download_handle = 0;
2079 wxEVT_DOWNLOAD_EVENT,
2080 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2081 m_connected =
false;
2082 m_xygribPanel->m_progress_gauge->SetValue(0);
2083 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2084 m_xygribPanel->m_status_text->SetLabelText(_(
"Download cancelled"));
2087 EnableDownloadButtons();
2088 wxTheApp->ProcessPendingEvents();
2093 if (m_gribSizeEstimate > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB * 1024 * 1024) {
2094 m_xygribPanel->m_status_text->SetLabelText(
2095 wxString::Format(_(
"Can't download GRIB file bigger than %d MB"),
2096 (
int)XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB));
2102 MemorizeXyGribConfiguration();
2104 m_downloading =
true;
2106 EnableDownloadButtons();
2108 m_xygribPanel->m_download_button->SetLabelText(_(
"Cancel"));
2109 m_xygribPanel->m_status_text->SetLabelText(
2110 _(
"Preparing GRIB file on server..."));
2114 wxString requestUrl = BuildXyGribUrl();
2119 wxString filename = wxString::Format(
"ocpn_xygrib_%s.xml",
2120 wxDateTime::Now().Format(
"%F-%H-%M"));
2121 wxString path = m_parent.GetGribDir();
2122 path << wxFileName::GetPathSeparator();
2127 wxEVT_DOWNLOAD_EVENT,
2128 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2131 &m_download_handle);
2136 while (m_downloading) {
2137 wxTheApp->ProcessPendingEvents();
2141 if ((m_canceled) || (!m_bTransferSuccess)) {
2143 m_xygribPanel->m_status_text->SetLabelText(_(
"Grib request failed"));
2144 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2146 EnableDownloadButtons();
2154 bool readOk = xmlFile.Open(path);
2156 readOk &= xmlFile.ReadAll(&strXml);
2164 if (readOk && (((
int)strXml.find(
"\"status\":true") == wxNOT_FOUND))) {
2167 int errPos = strXml.find(
"\"message\":\"");
2168 int errEnd = strXml.find(
"\"}");
2169 if ((errPos != wxNOT_FOUND) && (errEnd != wxNOT_FOUND)) {
2171 errorStr = strXml.Mid(errPos, errEnd - errPos);
2173 errorStr =
"Unknown server error";
2176 m_xygribPanel->m_status_text->SetLabelText(
2177 wxString::Format(
"%s (%s)", _(
"Server Error"), errorStr));
2178 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2180 EnableDownloadButtons();
2185 int urlPos = strXml.find(
"\"url\":\"http:");
2186 int urlEnd = strXml.find(
".grb2\"");
2187 if ((urlPos != wxNOT_FOUND) && (urlEnd != wxNOT_FOUND)) {
2190 url = strXml.Mid(urlPos, urlEnd - urlPos);
2191 url.Replace(
"\\/",
"/");
2202 m_xygribPanel->m_status_text->SetLabelText(
2203 _(
"Error parsing XML file from server"));
2204 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2206 EnableDownloadButtons();
2210 m_xygribPanel->m_status_text->SetLabelText(_(
"Downloading GRIB file"));
2213 path = m_parent.GetGribDir();
2214 path << wxFileName::GetPathSeparator();
2215 path << BuildGribFileName();
2219 m_downloading =
true;
2223 wxEVT_DOWNLOAD_EVENT,
2224 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2230 while (m_downloading) {
2231 wxTheApp->ProcessPendingEvents();
2236 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2239 if (m_bTransferSuccess) {
2241 m_xygribPanel->m_status_text->SetLabelText(_(
"Download complete"));
2242 wxFileName fn(path);
2246 m_parent.OpenFile();
2248 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
2250 m_parent.SetDialogsStyleSizePosition(
true);
2255 m_xygribPanel->m_status_text->SetLabelText(_(
"Download failed"));
2259 EnableDownloadButtons();
2265void GribRequestSetting::OnXyGribAtmModelChoice(wxCommandEvent &event) {
2269 wxString atmModel = m_xygribPanel->m_atmmodel_choice->GetStringSelection();
2271 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2272 if (selectedAtmModel->name.IsSameAs(atmModel,
true)) {
2279 if (selectedAtmModel ==
nullptr) {
2280 selectedAtmModel = xygribAtmModelList[0];
2285 if (selectedAtmModel->wind)
2286 m_xygribPanel->m_wind_cbox->Enable();
2288 m_xygribPanel->m_wind_cbox->Disable();
2290 if (selectedAtmModel->gust)
2291 m_xygribPanel->m_gust_cbox->Enable();
2293 m_xygribPanel->m_gust_cbox->Disable();
2295 if (selectedAtmModel->pressure)
2296 m_xygribPanel->m_pressure_cbox->Enable();
2298 m_xygribPanel->m_pressure_cbox->Disable();
2300 if (selectedAtmModel->temperature)
2301 m_xygribPanel->m_temperature_cbox->Enable();
2303 m_xygribPanel->m_temperature_cbox->Disable();
2305 if (selectedAtmModel->cape)
2306 m_xygribPanel->m_cape_cbox->Enable();
2308 m_xygribPanel->m_cape_cbox->Disable();
2310 if (selectedAtmModel->reflectivity)
2311 m_xygribPanel->m_reflectivity_cbox->Enable();
2313 m_xygribPanel->m_reflectivity_cbox->Disable();
2315 if (selectedAtmModel->cloudCover)
2316 m_xygribPanel->m_cloudcover_cbox->Enable();
2318 m_xygribPanel->m_cloudcover_cbox->Disable();
2320 if (selectedAtmModel->precipitation)
2321 m_xygribPanel->m_precipitation_cbox->Enable();
2323 m_xygribPanel->m_precipitation_cbox->Disable();
2326 m_xygribPanel->m_resolution_choice->Clear();
2327 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2328 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2333 m_xygribPanel->m_duration_choice->Clear();
2334 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2335 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2339 m_xygribPanel->m_interval_choice->Clear();
2340 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2341 m_xygribPanel->m_interval_choice->Insert(
2342 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2346 m_xygribPanel->m_run_choice->Clear();
2347 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2348 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2349 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2350 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2352 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2353 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2354 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2355 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2356 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2359 if (modelIndex == m_parent.xyGribConfig.atmModelIndex) {
2360 ApplyXyGribConfiguration();
2362 m_selectedAtmModelIndex = modelIndex;
2363 m_xygribPanel->m_resolution_choice->SetSelection(0);
2364 m_xygribPanel->m_duration_choice->SetSelection(
2365 m_xygribPanel->m_duration_choice->GetCount() - 1);
2366 m_xygribPanel->m_interval_choice->SetSelection(0);
2367 m_xygribPanel->m_run_choice->SetSelection(
2368 m_xygribPanel->m_run_choice->GetCount() - 1);
2370 MemorizeXyGribConfiguration();
2376void GribRequestSetting::OnXyGribWaveModelChoice(wxCommandEvent &event) {
2380 wxString waveModel = m_xygribPanel->m_wavemodel_choice->GetStringSelection();
2382 while ((selectedModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2383 if (selectedModel->name.IsSameAs(waveModel,
true)) {
2390 if (selectedModel ==
nullptr) {
2392 m_selectedWaveModelIndex = -1;
2393 m_xygribPanel->m_waveheight_cbox->Disable();
2394 m_xygribPanel->m_windwave_cbox->Disable();
2395 MemorizeXyGribConfiguration();
2399 m_selectedWaveModelIndex = modelIndex;
2402 if (selectedModel->significantHeight) {
2403 m_xygribPanel->m_waveheight_cbox->Enable();
2405 m_xygribPanel->m_waveheight_cbox->Disable();
2408 if (selectedModel->windWaves) {
2409 m_xygribPanel->m_windwave_cbox->Enable();
2411 m_xygribPanel->m_windwave_cbox->Disable();
2413 MemorizeXyGribConfiguration();
2419void GribRequestSetting::OnXyGribConfigChange(wxCommandEvent &event) {
2420 MemorizeXyGribConfiguration();
2424void GribRequestSetting::InitializeXygribDialog() {
2429 m_xygribPanel->m_atmmodel_choice->Clear();
2431 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2432 m_xygribPanel->m_atmmodel_choice->Insert(selectedAtmModel->name,
2437 m_selectedAtmModelIndex = m_parent.xyGribConfig.atmModelIndex;
2438 selectedAtmModel = xygribAtmModelList[m_selectedAtmModelIndex];
2441 m_xygribPanel->m_wavemodel_choice->Clear();
2443 while ((selectedWaveModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2444 m_xygribPanel->m_wavemodel_choice->Insert(selectedWaveModel->name,
2449 m_xygribPanel->m_wavemodel_choice->Insert(
"None", modelIndex);
2450 m_selectedWaveModelIndex = m_parent.xyGribConfig.waveModelIndex;
2451 selectedWaveModel = xygribWaveModelList[m_selectedWaveModelIndex];
2452 if (selectedWaveModel ==
nullptr) {
2453 m_selectedWaveModelIndex = -1;
2457 m_xygribPanel->m_resolution_choice->Clear();
2458 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2459 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2464 m_xygribPanel->m_duration_choice->Clear();
2465 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2466 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2470 m_xygribPanel->m_interval_choice->Clear();
2471 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2472 m_xygribPanel->m_interval_choice->Insert(
2473 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2477 m_xygribPanel->m_run_choice->Clear();
2478 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2479 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2480 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2481 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2483 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2484 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2485 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2486 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2487 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2490 if (selectedAtmModel->wind)
2491 m_xygribPanel->m_wind_cbox->Enable();
2493 m_xygribPanel->m_wind_cbox->Disable();
2495 if (selectedAtmModel->gust)
2496 m_xygribPanel->m_gust_cbox->Enable();
2498 m_xygribPanel->m_gust_cbox->Disable();
2500 if (selectedAtmModel->pressure)
2501 m_xygribPanel->m_pressure_cbox->Enable();
2503 m_xygribPanel->m_pressure_cbox->Disable();
2505 if (selectedAtmModel->temperature)
2506 m_xygribPanel->m_temperature_cbox->Enable();
2508 m_xygribPanel->m_temperature_cbox->Disable();
2510 if (selectedAtmModel->cape)
2511 m_xygribPanel->m_cape_cbox->Enable();
2513 m_xygribPanel->m_cape_cbox->Disable();
2515 if (selectedAtmModel->reflectivity)
2516 m_xygribPanel->m_reflectivity_cbox->Enable();
2518 m_xygribPanel->m_reflectivity_cbox->Disable();
2520 if (selectedAtmModel->cloudCover)
2521 m_xygribPanel->m_cloudcover_cbox->Enable();
2523 m_xygribPanel->m_cloudcover_cbox->Disable();
2525 if (selectedAtmModel->precipitation)
2526 m_xygribPanel->m_precipitation_cbox->Enable();
2528 m_xygribPanel->m_precipitation_cbox->Disable();
2530 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->significantHeight))
2531 m_xygribPanel->m_waveheight_cbox->Enable();
2533 m_xygribPanel->m_waveheight_cbox->Disable();
2535 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->windWaves))
2536 m_xygribPanel->m_windwave_cbox->Enable();
2538 m_xygribPanel->m_windwave_cbox->Disable();
2540 ApplyXyGribConfiguration();
2547void GribRequestSetting::ApplyXyGribConfiguration() {
2548 m_xygribPanel->m_atmmodel_choice->SetSelection(
2549 m_parent.xyGribConfig.atmModelIndex);
2550 m_xygribPanel->m_wavemodel_choice->SetSelection(
2551 m_parent.xyGribConfig.waveModelIndex);
2553 m_xygribPanel->m_wind_cbox->SetValue(m_parent.xyGribConfig.wind);
2554 m_xygribPanel->m_gust_cbox->SetValue(m_parent.xyGribConfig.gust);
2555 m_xygribPanel->m_pressure_cbox->SetValue(m_parent.xyGribConfig.pressure);
2556 m_xygribPanel->m_temperature_cbox->SetValue(
2557 m_parent.xyGribConfig.temperature);
2558 m_xygribPanel->m_cape_cbox->SetValue(m_parent.xyGribConfig.cape);
2559 m_xygribPanel->m_reflectivity_cbox->SetValue(
2560 m_parent.xyGribConfig.reflectivity);
2561 m_xygribPanel->m_cloudcover_cbox->SetValue(m_parent.xyGribConfig.cloudCover);
2562 m_xygribPanel->m_precipitation_cbox->SetValue(
2563 m_parent.xyGribConfig.precipitation);
2564 m_xygribPanel->m_waveheight_cbox->SetValue(m_parent.xyGribConfig.waveHeight);
2565 m_xygribPanel->m_windwave_cbox->SetValue(m_parent.xyGribConfig.windWaves);
2566 m_xygribPanel->m_resolution_choice->SetSelection(
2567 m_parent.xyGribConfig.resolutionIndex);
2568 m_xygribPanel->m_duration_choice->SetSelection(
2569 m_parent.xyGribConfig.durationIndex);
2570 m_xygribPanel->m_interval_choice->SetSelection(
2571 m_parent.xyGribConfig.intervalIndex);
2572 m_xygribPanel->m_run_choice->SetSelection(m_parent.xyGribConfig.runIndex);
2574 UpdateGribSizeEstimate();
2581void GribRequestSetting::MemorizeXyGribConfiguration() {
2582 m_parent.xyGribConfig.atmModelIndex =
2583 m_xygribPanel->m_atmmodel_choice->GetSelection();
2584 m_parent.xyGribConfig.waveModelIndex =
2585 m_xygribPanel->m_wavemodel_choice->GetSelection();
2587 m_parent.xyGribConfig.wind = m_xygribPanel->m_wind_cbox->IsChecked();
2588 m_parent.xyGribConfig.gust = m_xygribPanel->m_gust_cbox->IsChecked();
2589 m_parent.xyGribConfig.pressure = m_xygribPanel->m_pressure_cbox->IsChecked();
2590 m_parent.xyGribConfig.temperature =
2591 m_xygribPanel->m_temperature_cbox->IsChecked();
2592 m_parent.xyGribConfig.cape = m_xygribPanel->m_cape_cbox->IsChecked();
2593 m_parent.xyGribConfig.reflectivity =
2594 m_xygribPanel->m_reflectivity_cbox->IsChecked();
2595 m_parent.xyGribConfig.cloudCover =
2596 m_xygribPanel->m_cloudcover_cbox->IsChecked();
2597 m_parent.xyGribConfig.precipitation =
2598 m_xygribPanel->m_precipitation_cbox->IsChecked();
2599 m_parent.xyGribConfig.waveHeight =
2600 m_xygribPanel->m_waveheight_cbox->IsChecked();
2601 m_parent.xyGribConfig.windWaves = m_xygribPanel->m_windwave_cbox->IsChecked();
2603 m_parent.xyGribConfig.resolutionIndex =
2604 m_xygribPanel->m_resolution_choice->GetSelection();
2605 m_parent.xyGribConfig.durationIndex =
2606 m_xygribPanel->m_duration_choice->GetSelection();
2607 m_parent.xyGribConfig.intervalIndex =
2608 m_xygribPanel->m_interval_choice->GetSelection();
2609 m_parent.xyGribConfig.runIndex = m_xygribPanel->m_run_choice->GetSelection();
2611 UpdateGribSizeEstimate();
2617void GribRequestSetting::UpdateGribSizeEstimate() {
2622 if (!m_xygribPanel->m_resolution_choice->GetStringSelection().ToCDouble(
2624 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2627 if (!m_xygribPanel->m_duration_choice->GetStringSelection().ToCLong(&days)) {
2628 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2631 wxString intvStr = m_xygribPanel->m_interval_choice->GetStringSelection();
2632 intvStr.Replace(
"h",
"");
2633 if (!intvStr.ToCLong(&interval)) {
2634 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2639 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2648 int npts = (int)(ceil(fabs(xmax - xmin) / resolution) *
2649 ceil(fabs(ymax - ymin) / resolution));
2652 int nbrec = (int)days * 24 / interval + 1;
2654 int nbPress = (m_xygribPanel->m_pressure_cbox->IsChecked() &&
2655 m_xygribPanel->m_pressure_cbox->IsEnabled())
2658 int nbWind = (m_xygribPanel->m_wind_cbox->IsChecked() &&
2659 m_xygribPanel->m_wind_cbox->IsEnabled())
2662 int nbRain = (m_xygribPanel->m_precipitation_cbox->IsChecked() &&
2663 m_xygribPanel->m_precipitation_cbox->IsEnabled())
2666 int nbCloud = (m_xygribPanel->m_cloudcover_cbox->IsChecked() &&
2667 m_xygribPanel->m_cloudcover_cbox->IsEnabled())
2670 int nbTemp = (m_xygribPanel->m_temperature_cbox->IsChecked() &&
2671 m_xygribPanel->m_temperature_cbox->IsEnabled())
2675 int nbCAPEsfc = (m_xygribPanel->m_cape_cbox->IsChecked() &&
2676 m_xygribPanel->m_cape_cbox->IsEnabled())
2679 int nbReflectivity = (m_xygribPanel->m_reflectivity_cbox->IsChecked() &&
2680 m_xygribPanel->m_reflectivity_cbox->IsEnabled())
2683 int nbGUSTsfc = (m_xygribPanel->m_gust_cbox->IsChecked() &&
2684 m_xygribPanel->m_gust_cbox->IsEnabled())
2694 estimate += nbWind * (head + (nbits * npts) / 8 + 2);
2697 estimate += nbTemp * (head + (nbits * npts) / 8 + 2);
2703 estimate += nbRain * (head + 24 + (nbits * npts) / 8 + 2);
2706 estimate += nbPress * (head + (nbits * npts) / 8 + 2);
2709 estimate += nbCloud * (head + 24 + (nbits * npts) / 8 + 2);
2712 estimate += nbReflectivity * (head + (nbits * npts) / 8 + 2);
2715 estimate += nbCAPEsfc * (head + (nbits * npts) / 8 + 2);
2718 estimate += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
2722 int atmEstimate = estimate;
2726 if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2729 npts = (int)(ceil(fabs(xmax - xmin) / 0.5) * ceil(fabs(ymax - ymin) / 0.5));
2730 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2731 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2735 (int)(ceil(fabs(xmax - xmin) / 0.25) * ceil(fabs(ymax - ymin) / 0.25));
2736 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2737 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2741 (int)(ceil(fabs(xmax - xmin) / 0.05) * ceil(fabs(ymax - ymin) / 0.1));
2742 nbrec = (int)fmin(4, days) * 24 / interval + 1;
2748 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2750 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2753 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2755 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2757 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2759 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2762 int wavEstimate = estimate - atmEstimate;
2764 wavEstimate = wavEstimate * 0.6;
2766 estimate = atmEstimate + wavEstimate;
2769 estimate = estimate * 0.65;
2771 wxString warningStr =
"";
2772 if (estimate / (1024 * 1024) > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB) {
2773 warningStr = wxString::Format(
"(Warning GRIB exceeds %d MB limit)",
2774 XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB);
2777 m_xygribPanel->m_sizeestimate_text->SetLabel(
2778 wxString::Format(
"%d kB %s", estimate / 1024, warningStr));
2780 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.