Files
wxWidgets/samples/webrequest/webrequest.cpp
2018-12-10 19:37:52 +01:00

414 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: samples/webrequest.cpp
// Purpose: wxWebRequest Sample
// Author: Tobias Taschner
// Created: 2018-10-15
// Copyright: (c) 2018 wxWidgets development team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/notebook.h"
#include "wx/artprov.h"
#include "wx/webrequest.h"
#include "wx/filedlg.h"
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
class WebRequestFrame : public wxFrame
{
public:
enum Pages
{
Page_Image,
Page_Text,
Page_Download,
Page_Advanced
};
WebRequestFrame(const wxString& title):
wxFrame(NULL, wxID_ANY, title)
{
// set the frame icon
SetIcon(wxICON(sample));
// Prepare UI controls
wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
mainSizer->Add(new wxStaticText(this, wxID_ANY, "Request URL:"),
wxSizerFlags().Border());
m_urlTextCtrl = new wxTextCtrl(this, wxID_ANY,
"https://www.wxwidgets.org/downloads/logos/blocks.png");
mainSizer->Add(m_urlTextCtrl,
wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT));
m_notebook = new wxNotebook(this, wxID_ANY);
m_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &WebRequestFrame::OnNotebookPageChanged, this);
// Image page
wxPanel* imagePanel = new wxPanel(m_notebook);
wxSizer* imageSizer = new wxBoxSizer(wxVERTICAL);
m_imageStaticBitmap = new wxStaticBitmap(imagePanel,
wxID_ANY, wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
imageSizer->Add(m_imageStaticBitmap, wxSizerFlags(1).Expand());
imagePanel->SetSizer(imageSizer);
m_notebook->AddPage(imagePanel, "Image", true);
// Text page
wxPanel* textPanel = new wxPanel(m_notebook);
wxSizer* textSizer = new wxBoxSizer(wxVERTICAL);
m_postCheckBox = new wxCheckBox(textPanel, wxID_ANY, "Post request body");
textSizer->Add(m_postCheckBox, wxSizerFlags().Border());
m_postCheckBox->Bind(wxEVT_CHECKBOX, &WebRequestFrame::OnPostCheckBox, this);
m_postRequestTextCtrl = new wxTextCtrl(textPanel, wxID_ANY,
"app=WebRequestSample&version=1",
wxDefaultPosition, wxSize(-1, FromDIP(60)), wxTE_MULTILINE);
textSizer->Add(m_postRequestTextCtrl,
wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT));
textSizer->Add(new wxStaticText(textPanel, wxID_ANY, "Request body content type:"),
wxSizerFlags().Border());
m_postContentTypeTextCtrl = new wxTextCtrl(textPanel, wxID_ANY,
"application/x-www-form-urlencoded");
textSizer->Add(m_postContentTypeTextCtrl,
wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT));
textSizer->Add(new wxStaticText(textPanel, wxID_ANY, "Response body:"),
wxSizerFlags().Border());
m_textResponseTextCtrl = new wxTextCtrl(textPanel, wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
m_textResponseTextCtrl->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
textSizer->Add(m_textResponseTextCtrl,
wxSizerFlags(1).Expand().Border(wxLEFT | wxRIGHT | wxBOTTOM));
textPanel->SetSizer(textSizer);
m_notebook->AddPage(textPanel, "Text");
// Download page
wxPanel* downloadPanel = new wxPanel(m_notebook);
wxSizer* downloadSizer = new wxBoxSizer(wxVERTICAL);
wxStaticText* downloadHeader = new wxStaticText(downloadPanel, wxID_ANY,
"The URL will be downloaded to a file.\n"\
"Progress will be shown and you will be asked, where\n"\
"to save the file when the download completed.");
downloadSizer->Add(downloadHeader, wxSizerFlags().Expand().Border());
downloadSizer->AddStretchSpacer();
m_downloadGauge = new wxGauge(downloadPanel, wxID_ANY, 100);
downloadSizer->Add(m_downloadGauge, wxSizerFlags().Expand().Border());
m_downloadStaticText = new wxStaticText(downloadPanel, wxID_ANY, "");
downloadSizer->Add(m_downloadStaticText, wxSizerFlags().Expand().Border());
downloadSizer->AddStretchSpacer();
downloadPanel->SetSizer(downloadSizer);
m_notebook->AddPage(downloadPanel, "Download");
// Advanced page
wxPanel* advancedPanel = new wxPanel(m_notebook);
wxSizer* advSizer = new wxBoxSizer(wxVERTICAL);
wxStaticText* advHeader = new wxStaticText(advancedPanel, wxID_ANY,
"As an example of processing data while\n"\
"it's being received from the server every\n"\
"zero byte in the response will be counted below.");
advSizer->Add(advHeader, wxSizerFlags().Expand().Border());
advSizer->AddStretchSpacer();
m_advCountStaticText = new wxStaticText(advancedPanel, wxID_ANY, "0",
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE);
m_advCountStaticText->SetFont(m_advCountStaticText->GetFont()
.MakeBold().MakeLarger().MakeLarger());
advSizer->Add(m_advCountStaticText, wxSizerFlags().Expand().Border());
advSizer->AddStretchSpacer();
advancedPanel->SetSizer(advSizer);
m_notebook->AddPage(advancedPanel, "Advanced");
mainSizer->Add(m_notebook, wxSizerFlags(1).Expand().Border());
wxStdDialogButtonSizer* btnSizer = new wxStdDialogButtonSizer();
m_cancelButton = new wxButton(this, wxID_CANCEL, "Cancel");
m_cancelButton->Bind(wxEVT_BUTTON, &WebRequestFrame::OnCancelButton, this);
m_cancelButton->Disable();
btnSizer->AddButton(m_cancelButton);
m_startButton = new wxButton(this, wxID_OK, "&Start Request");
m_startButton->Bind(wxEVT_BUTTON, &WebRequestFrame::OnStartButton, this);
btnSizer->AddButton(m_startButton);
btnSizer->Realize();
mainSizer->Add(btnSizer, wxSizerFlags().Border());
wxCommandEvent evt;
OnPostCheckBox(evt);
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
SetSizer(mainSizer);
SetSize(FromDIP(wxSize(540, 500)));
CreateStatusBar();
m_downloadProgressTimer.Bind(wxEVT_TIMER,
&WebRequestFrame::OnProgressTimer, this);
m_currentRequest = NULL;
}
void OnStartButton(wxCommandEvent& WXUNUSED(evt))
{
GetStatusBar()->SetStatusText("Started request...");
// Create request for the specified URL from the default session
wxObjectDataPtr<wxWebRequest> request(wxWebSession::GetDefault().CreateRequest(
m_urlTextCtrl->GetValue()));
m_currentRequest = request.get();
// Bind event for state change
request->Bind(wxEVT_WEBREQUEST_STATE, &WebRequestFrame::OnWebRequestState, this);
// Prepare request based on selected action
switch (m_notebook->GetSelection())
{
case Page_Image:
// Reset static bitmap image
m_imageStaticBitmap->SetBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
break;
case Page_Text:
// Reset response text control
m_textResponseTextCtrl->Clear();
// Set postdata if checked
if ( m_postCheckBox->IsChecked() )
{
request->SetData(m_postRequestTextCtrl->GetValue(),
m_postContentTypeTextCtrl->GetValue());
}
break;
case Page_Download:
request->SetStorage(wxWebRequest::Storage_File);
m_downloadGauge->SetValue(0);
m_downloadGauge->Pulse();
m_downloadStaticText->SetLabel("");
m_downloadProgressTimer.Start(500);
GetStatusBar()->SetStatusText("");
break;
case Page_Advanced:
request->SetStorage(wxWebRequest::Storage_None);
request->Bind(wxEVT_WEBREQUEST_DATA, &WebRequestFrame::OnRequestData, this);
GetStatusBar()->SetStatusText("Counting...");
m_advCount = 0;
m_advCountStaticText->SetLabel("0");
break;
}
m_startButton->Disable();
// Start the request (events will be called on success or failure)
request->Start();
}
void OnCancelButton(wxCommandEvent& WXUNUSED(evt))
{
if ( m_currentRequest )
m_currentRequest->Cancel();
}
void OnWebRequestState(wxWebRequestEvent& evt)
{
m_startButton->Enable(evt.GetState() != wxWebRequest::State_Active);
m_cancelButton->Enable(evt.GetState() == wxWebRequest::State_Active);
if ( evt.GetState() != wxWebRequest::State_Active )
{
m_currentRequest = NULL;
m_downloadProgressTimer.Stop();
}
switch (evt.GetState())
{
case wxWebRequest::State_Completed:
switch (m_notebook->GetSelection())
{
case Page_Image:
{
wxImage img(*evt.GetResponse()->GetStream());
m_imageStaticBitmap->SetBitmap(img);
m_notebook->GetPage(Page_Image)->Layout();
GetStatusBar()->SetStatusText(wxString::Format("Loaded %lld bytes image data", evt.GetResponse()->GetContentLength()));
break;
}
case Page_Text:
m_textResponseTextCtrl->SetValue(evt.GetResponse()->AsString());
GetStatusBar()->SetStatusText(wxString::Format("Loaded %lld bytes text data (Status: %d %s)",
evt.GetResponse()->GetContentLength(),
evt.GetResponse()->GetStatus(),
evt.GetResponse()->GetStatusText()));
break;
case Page_Download:
{
m_downloadGauge->SetValue(100);
m_downloadStaticText->SetLabel("");
GetStatusBar()->SetStatusText("Download completed");
// Ask the user where to save the file
wxFileDialog fileDlg(this, "Save download", "",
evt.GetResponse()->GetSuggestedFileName(), "*.*",
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if ( fileDlg.ShowModal() == wxID_OK )
{
if ( !wxRenameFile(evt.GetResponseFileName(), fileDlg.GetPath()) )
wxLogError("Could not move file");
}
break;
}
case Page_Advanced:
UpdateAdvCount();
GetStatusBar()->SetStatusText("");
break;
}
break;
case wxWebRequest::State_Failed:
wxLogError("Web Request failed: %s", evt.GetErrorDescription());
GetStatusBar()->SetStatusText("");
break;
case wxWebRequest::State_Cancelled:
m_downloadGauge->SetValue(0);
m_downloadStaticText->SetLabel("");
GetStatusBar()->SetStatusText("Cancelled");
break;
default:
break;
}
}
void OnRequestData(wxWebRequestEvent& evt)
{
// Count zero bytes in data buffer
bool notify = false;
const char* p = (const char*) evt.GetDataBuffer();
for ( size_t i = 0; i < evt.GetDataSize(); i++ )
{
if ( *p == 0 )
{
m_advCount++;
notify = true;
}
p++;
}
if ( notify )
CallAfter(&WebRequestFrame::UpdateAdvCount);
}
void UpdateAdvCount()
{
m_advCountStaticText->SetLabel(wxString::Format("%lld", m_advCount));
}
void OnProgressTimer(wxTimerEvent& WXUNUSED(evt))
{
if ( !m_currentRequest || m_currentRequest->GetBytesExpectedToReceive() <= 0 )
return;
m_downloadGauge->SetValue((m_currentRequest->GetBytesReceived() * 100) /
m_currentRequest->GetBytesExpectedToReceive());
m_downloadStaticText->SetLabelText(wxString::Format("%lld/%lld",
m_currentRequest->GetBytesReceived(), m_currentRequest->GetBytesExpectedToReceive()));
}
void OnPostCheckBox(wxCommandEvent& WXUNUSED(evt))
{
m_postContentTypeTextCtrl->Enable(m_postCheckBox->IsChecked());
m_postRequestTextCtrl->Enable(m_postCheckBox->IsChecked());
wxColour textBg = wxSystemSettings::GetColour(
(m_postCheckBox->IsChecked()) ? wxSYS_COLOUR_WINDOW : wxSYS_COLOUR_BTNFACE);
m_postContentTypeTextCtrl->SetBackgroundColour(textBg);
m_postRequestTextCtrl->SetBackgroundColour(textBg);
}
void OnNotebookPageChanged(wxBookCtrlEvent& event)
{
wxString defaultURL;
switch (event.GetSelection())
{
case Page_Image:
defaultURL = "https://www.wxwidgets.org/downloads/logos/blocks.png";
break;
case Page_Text:
defaultURL = "https://httpbin.org/post";
break;
case Page_Download:
defaultURL = "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.7z";
break;
case Page_Advanced:
defaultURL = "https://httpbin.org/bytes/64000";
break;
}
m_urlTextCtrl->SetValue(defaultURL);
}
private:
wxNotebook* m_notebook;
wxTextCtrl* m_urlTextCtrl;
wxButton* m_startButton;
wxButton* m_cancelButton;
wxStaticBitmap* m_imageStaticBitmap;
wxWebRequest* m_currentRequest;
wxCheckBox* m_postCheckBox;
wxTextCtrl* m_postContentTypeTextCtrl;
wxTextCtrl* m_postRequestTextCtrl;
wxTextCtrl* m_textResponseTextCtrl;
wxGauge* m_downloadGauge;
wxStaticText* m_downloadStaticText;
wxTimer m_downloadProgressTimer;
wxStaticText* m_advCountStaticText;
wxLongLong m_advCount;
};
class WebRequestApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE
{
if ( !wxApp::OnInit() )
return false;
// create the main application window
WebRequestFrame *frame = new WebRequestFrame("wxWebRequest Sample App");
frame->Show(true);
return true;
}
};
wxIMPLEMENT_APP(WebRequestApp);