1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        dialog.cpp
3 // Purpose:     wxCurlDownloadDialog, wxCurlUploadDialog
4 // Author:      Francesco Montorsi
5 // Created:     2007/04/14
6 // RCS-ID:      $Id: dialog.cpp 1240 2010-03-10 23:54:25Z frm $
7 // Copyright:   (c) 2007 Francesco Montorsi
8 // Licence:     wxWidgets licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18 
19 // includes
20 #ifndef WX_PRECOMP
21     #include <wx/log.h>
22     #include <wx/intl.h>        // for _() support
23     #include <wx/utils.h>       // for wxMilliSleep
24 
25     #if wxUSE_GUI
26         #include <wx/textctrl.h>
27         #include <wx/gauge.h>
28         #include <wx/stattext.h>
29         #include <wx/sizer.h>
30         #include <wx/msgdlg.h>
31         #include <wx/settings.h>
32         #include <wx/button.h>
33         #include <wx/statbmp.h>
34     #endif
35 #endif
36 
37 #ifdef __WXMSW__
38     #include <wx/msw/msvcrt.h>      // useful to catch memory leaks when compiling under MSVC
39 #endif
40 
41 #include <wx/wfstream.h>
42 #include <wx/filename.h>
43 #include <wx/statline.h>
44 
45 //class WXDLLIMPEXP_CORE wxTextCtrl;
46 class WXDLLIMPEXP_CORE wxCheckBox;
47 #include "wx/curl/dialog.h"
48 
49 
50 // ----------------------------------------------------------------------------
51 // wxCurlTransferDialog
52 // ----------------------------------------------------------------------------
53 
54 enum
55 {
56     AbortButtonId = wxID_HIGHEST+1,
57     PauseResumeButtonId,
58     StartButtonId,
59     ConnSettingsButtonId,
60 
61     ThreadId
62 };
63 
BEGIN_EVENT_TABLE(wxCurlTransferDialog,wxDialog)64 BEGIN_EVENT_TABLE( wxCurlTransferDialog, wxDialog )
65 
66     // network events
67     EVT_CURL_END_PERFORM( ThreadId, wxCurlTransferDialog::OnEndPerform )
68 
69     // user events
70     EVT_BUTTON( AbortButtonId, wxCurlTransferDialog::OnAbort )
71     EVT_BUTTON( ConnSettingsButtonId, wxCurlTransferDialog::OnConnSettings )
72     EVT_BUTTON( PauseResumeButtonId, wxCurlTransferDialog::OnPauseResume )
73     EVT_BUTTON( StartButtonId, wxCurlTransferDialog::OnStart )
74 
75     // update UI
76     EVT_UPDATE_UI( AbortButtonId, wxCurlTransferDialog::OnAbortUpdateUI )
77     EVT_UPDATE_UI( ConnSettingsButtonId, wxCurlTransferDialog::OnConnSettingsUpdateUI )
78     EVT_UPDATE_UI( PauseResumeButtonId, wxCurlTransferDialog::OnPauseResumeUpdateUI )
79     EVT_UPDATE_UI( StartButtonId, wxCurlTransferDialog::OnStartUpdateUI )
80 
81     // misc
82     EVT_CLOSE( wxCurlTransferDialog::OnClose )
83 
84 END_EVENT_TABLE()
85 
86 bool wxCurlTransferDialog::Create(const wxString &url, const wxString& title, const wxString& message,
87                               const wxString &sizeLabel, const wxBitmap& bitmap, wxWindow *parent, long style)
88 {
89     if (!wxDialog::Create(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
90                           (wxDEFAULT_DIALOG_STYLE |wxRESIZE_BORDER)))
91         return false;
92 
93     // save&check our style
94     m_nStyle = style;
95     wxASSERT_MSG(HasFlag(wxCTDS_AUTO_CLOSE) || HasFlag(wxCTDS_CAN_ABORT),
96              wxS("If both these flags are missing the user will be unable to close the dialog window!"));
97 
98     // do we need to use wxCurlConnectionSettingsDialog?
99     wxASSERT_MSG(!(HasFlag(wxCTDS_CONN_SETTINGS_AUTH) ||
100                    HasFlag(wxCTDS_CONN_SETTINGS_PORT) ||
101                    HasFlag(wxCTDS_CONN_SETTINGS_PROXY)) || HasFlag(wxCTDS_CAN_START),
102                  wxS("the connection settings may only be changed before the transfer starts; if wxCTDS_CAN_START ")
103                  wxS("is missing the user will be unable to use the connection settings button!"));
104 
105     // set up our controls
106     CreateControls(url, message, sizeLabel, bitmap);
107 
108     return true;
109 }
110 
RunModal()111 wxCurlDialogReturnFlag wxCurlTransferDialog::RunModal()
112 {
113     m_pThread->GetCurlSession()->SetVerbose(m_bVerbose);
114 
115     if (!HasFlag(wxCTDS_CAN_START))
116     {
117         wxCommandEvent fake;
118         OnStart(fake);        // start immediately
119     }
120 
121     CenterOnScreen();
122 
123     return (wxCurlDialogReturnFlag)wxDialog::ShowModal();
124 }
125 
126 #define OUTER_BORDER    12
127 #define BORDER          5
128 #define MINWIDTH        300
129 
AddSizerRow(wxSizer * sz,const wxString & name)130 wxStaticText *wxCurlTransferDialog::AddSizerRow(wxSizer *sz, const wxString &name)
131 {
132     // the static text
133     wxStaticText *st = new wxStaticText( this, wxID_STATIC, name, wxDefaultPosition, wxDefaultSize );
134     st->SetFont(wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxS("")));
135 
136     // the value
137     wxStaticText *ret = new wxStaticText( this, wxID_STATIC, _("Not available"),
138                                           wxDefaultPosition, wxDefaultSize,
139                                           wxALIGN_LEFT|wxST_NO_AUTORESIZE );
140 
141     wxBoxSizer* time = new wxBoxSizer(wxHORIZONTAL);
142     time->Add(st, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT, 5);
143     time->Add(ret, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT, 5);
144 
145     sz->Add(time, 0, wxGROW|wxLEFT|wxRIGHT, OUTER_BORDER);
146 
147     return ret;
148 }
149 
CreateControls(const wxString & url,const wxString & msg,const wxString & sizeLabel,const wxBitmap & bitmap)150 void wxCurlTransferDialog::CreateControls(const wxString &url, const wxString &msg,
151                                       const wxString &sizeLabel, const wxBitmap &bitmap)
152 {
153     wxBoxSizer* main = new wxBoxSizer(wxVERTICAL);
154 
155     // message row
156     if (!msg.IsEmpty())
157     {
158         wxStaticText *st = new wxStaticText( this, wxID_STATIC, msg );
159         st->SetMinSize(wxSize(MINWIDTH, -1));
160         main->Add(st, 0, wxLEFT|wxTOP|wxRIGHT|wxBOTTOM|wxGROW, OUTER_BORDER);
161     }
162 
163     // URL row
164     if (HasFlag(wxCTDS_URL))
165     {
166         wxBoxSizer* downloading = new wxBoxSizer(wxHORIZONTAL);
167 
168         wxStaticText *st = new wxStaticText( this, wxID_STATIC, _("URL:") );
169         wxFont boldFont(st->GetFont());
170         boldFont.SetWeight(wxFONTWEIGHT_BOLD);
171         st->SetFont(boldFont);
172         downloading->Add(st, 0, wxRIGHT|wxTOP|wxALIGN_CENTER_VERTICAL, BORDER);
173 
174         m_pURL = new wxStaticText( this, wxID_STATIC, url, wxDefaultPosition,
175                                    wxSize(MINWIDTH, -1));//, wxST_ELLIPSIZE_MIDDLE);
176         downloading->Add(m_pURL, 1, wxALIGN_CENTER_VERTICAL|wxTOP, BORDER);
177 
178         main->Add(downloading, 0, wxGROW|wxLEFT|wxRIGHT, OUTER_BORDER);
179         main->AddSpacer(5);
180     }
181 
182 
183     wxSizer *leftcolumn = new wxBoxSizer(wxVERTICAL);
184 
185     // speed & size row
186     if (HasFlag(wxCTDS_SPEED))
187         m_pSpeed = AddSizerRow(leftcolumn, _("Speed:"));
188     if (HasFlag(wxCTDS_SIZE))
189         m_pSize = AddSizerRow(leftcolumn, sizeLabel);
190 
191     // a spacer
192     leftcolumn->AddSpacer(5);
193 
194     // the time rows
195     if (HasFlag(wxCTDS_ELAPSED_TIME))
196         m_pElapsedTime = AddSizerRow(leftcolumn, _("Elapsed time:"));
197     if (HasFlag(wxCTDS_ESTIMATED_TIME))
198         m_pEstimatedTime = AddSizerRow(leftcolumn, _("Estimated total time:"));
199     if (HasFlag(wxCTDS_REMAINING_TIME))
200         m_pRemainingTime = AddSizerRow(leftcolumn, _("Estimated remaining time:"));
201 
202     if (bitmap.IsOk())
203     {
204         wxSizer *rightcolumn = new wxBoxSizer(wxVERTICAL);
205         rightcolumn->Add( new wxStaticBitmap(this, wxID_ANY, bitmap),
206                           0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, BORDER);
207 
208         wxSizer *both = new wxBoxSizer(wxHORIZONTAL);
209         both->Add(leftcolumn);
210         both->Add(rightcolumn, 1, wxGROW);
211         main->Add(both, 0, wxGROW);
212     }
213     else
214         main->Add(leftcolumn);
215 
216 
217     // the gauge
218     // VERY IMPORTANT: we set as range 101 so that when, because of some approximation,
219     //                 the update event handler will SetValue(100), while the transfer
220     //                 is not yet complete, the gauge will not appear completely filled.
221     m_pGauge = new wxGauge( this, wxID_ANY, 101 );
222 
223     main->AddSpacer(5);
224     main->Add(m_pGauge, 0, wxGROW|wxLEFT|wxRIGHT|wxTOP, OUTER_BORDER);
225 
226     // do we need to use wxCurlConnectionSettingsDialog?
227     bool needsConnSettings = HasFlag(wxCTDS_CONN_SETTINGS_AUTH) ||
228                              HasFlag(wxCTDS_CONN_SETTINGS_PORT) ||
229                              HasFlag(wxCTDS_CONN_SETTINGS_PROXY);
230 
231     // an horizontal line of buttons
232     if (HasFlag(wxCTDS_CAN_ABORT) || HasFlag(wxCTDS_CAN_PAUSE) || HasFlag(wxCTDS_CAN_START) ||
233         needsConnSettings)
234     {
235         main->AddStretchSpacer(1);
236         main->AddSpacer(BORDER*2);
237         main->Add( new wxStaticLine(this), 0, wxGROW|wxLEFT|wxRIGHT, OUTER_BORDER);
238 
239         // the button row
240         wxBoxSizer *btn = new wxBoxSizer(wxHORIZONTAL);
241 
242         if (HasFlag(wxCTDS_CAN_ABORT))
243             btn->Add(new wxButton( this, AbortButtonId, _("Abort") ), 0, wxRIGHT, BORDER);
244         if (needsConnSettings)
245             btn->Add(new wxButton( this, ConnSettingsButtonId, _("Settings") ), 0);
246 
247         btn->AddStretchSpacer(1);
248 
249         if (HasFlag(wxCTDS_CAN_PAUSE))
250             btn->Add(new wxButton( this, PauseResumeButtonId, _("Pause") ), 0);
251         if (HasFlag(wxCTDS_CAN_START))
252             btn->Add(new wxButton( this, StartButtonId, _("Start") ), 0, wxLEFT, BORDER);
253 
254         btn->SetMinSize( wxSize( -1, wxButton::GetDefaultSize().GetHeight() + 2 * OUTER_BORDER ) );
255 
256         main->Add(btn, 0, wxGROW|wxLEFT|wxRIGHT|wxTOP|wxBOTTOM, OUTER_BORDER);
257     }
258 
259     this->SetSizerAndFit(main);
260     main->SetSizeHints(this);
261 }
262 
EndModal(int retCode)263 void wxCurlTransferDialog::EndModal(int retCode)
264 {
265     wxDialog::EndModal(retCode);
266 
267     // before dying we must be sure our thread has completed, too
268     // otherwise it will try to send events to a non-existent handler
269     // NB: this must be done *after* calling wxDialog::EndModal
270     //     so that while we wait we are hidden
271     HandleCurlThreadError(m_pThread->Wait(), m_pThread);
272 }
273 
UpdateLabels(wxCurlProgressBaseEvent * ev)274 void wxCurlTransferDialog::UpdateLabels(wxCurlProgressBaseEvent *ev)
275 {
276     // ignore this update if the thread has been paused
277     // since this event was generated...
278     if (m_pThread->IsPaused())
279         return;
280 
281     // NOTE: we need instead to process this update if the thread has completed
282     //       but that's for another reason: see m_pLastEvent stuff
283 
284     double fraction = ev->GetPercent();
285     if (fraction != 0)
286     {
287         m_pGauge->SetValue((int)fraction);
288     }
289     else
290     {
291         // we don't know how much we progressed...
292         m_pGauge->Pulse();
293     }
294 
295     //  Correct an occasional ASSERT for invalid wxTimeSpan.   dsr
296     if(ev->GetElapsedTime().IsShorterThan( wxTimeSpan::Minutes(120))){
297         if (m_pElapsedTime)
298             m_pElapsedTime->SetLabel(ev->GetElapsedTime().Format());
299         if (m_pRemainingTime)
300             m_pRemainingTime->SetLabel(ev->GetEstimatedRemainingTime().Format());
301         if (m_pEstimatedTime)
302             m_pEstimatedTime->SetLabel(ev->GetEstimatedTime().Format());
303     }
304 
305     if (m_pSize)
306     {
307         wxString currsize(ev->GetHumanReadableTransferredBytes().c_str(), wxConvUTF8);
308         wxString totalsize(ev->GetHumanReadableTotalBytes().c_str(), wxConvUTF8);
309         m_pSize->SetLabel(
310             wxString::Format(wxS("%s / %s  (%0.1f%%)"),
311                                 currsize.c_str(), totalsize.c_str(), ev->GetPercent()));
312     }
313 
314     if (m_pSpeed)
315     {
316         wxString s(ev->GetHumanReadableSpeed().c_str(), wxConvUTF8);
317         m_pSpeed->SetLabel(s);
318     }
319 }
320 
HandleCurlThreadError(wxCurlThreadError err,wxCurlBaseThread * p,const wxString & url)321 bool wxCurlTransferDialog::HandleCurlThreadError(wxCurlThreadError err, wxCurlBaseThread *p, const wxString &url)
322 {
323     switch (err)
324     {
325         case wxCTE_NO_ERROR:
326             return true;        // ignore this
327 
328         case wxCTE_NO_RESOURCE:
329             wxLogError(wxS("Insufficient resources for correct execution of the program."));
330             break;
331 
332         case wxCTE_ALREADY_RUNNING:
333             wxFAIL;      // should never happen!
334             break;
335 
336         case wxCTE_INVALID_PROTOCOL:
337             wxLogError(wxS("The URL '%s' uses an unsupported protocol."), url.c_str());
338             break;
339 
340         case wxCTE_NO_VALID_STREAM:
341             wxFAIL;     // should never happen - the user streams should always be valid!
342             break;
343 
344         case wxCTE_ABORTED:
345             return true;        // ignore this
346 
347         case wxCTE_CURL_ERROR:
348             {
349                 wxString err = wxS("unknown");
350                 if (p->GetCurlSession())
351                     err = wxString(p->GetCurlSession()->GetErrorString().c_str(), wxConvUTF8);
352                 wxLogError(wxS("Network error: %s"), err.c_str());
353             }
354             break;
355     }
356 
357     // stop the thread
358     if (p->IsAlive()) p->Abort();
359 
360     // this is an unrecoverable error:
361     return false;
362 }
363 
364 
365 // ----------------------------------------------------------------------------
366 // wxCurlTransferDialog - button events
367 // ----------------------------------------------------------------------------
368 
OnClose(wxCloseEvent & WXUNUSED (ev))369 void wxCurlTransferDialog::OnClose(wxCloseEvent &WXUNUSED(ev))
370 {
371     wxCommandEvent fake;
372     OnAbort(fake);
373 }
374 
OnAbort(wxCommandEvent & WXUNUSED (ev))375 void wxCurlTransferDialog::OnAbort(wxCommandEvent &WXUNUSED(ev))
376 {
377     // NOTE: the wxCTDS_ABORT flag may be absent if the user wxASSERT(HasFlag(wxCTDS_CAN_ABORT));
378 
379     if (m_pThread->IsAlive())
380     {
381         m_pThread->Abort();
382         EndModal(wxCDRF_USER_ABORTED);
383     }
384     else
385     {
386         wxASSERT(HasFlag(wxCTDS_CAN_START) || !HasFlag(wxCTDS_AUTO_CLOSE));
387             // thread is not alive: means the user has not
388             // clicked on Start button yet or the download is complete
389             // and the dialog does not auto close
390 
391         // if the transfer has been completed, then the OnEndPerform event handler
392         // has already set the return code to a valid value:
393         EndModal(m_bTransferComplete ? GetReturnCode() : wxCDRF_USER_ABORTED);
394     }
395 }
396 
OnAbortUpdateUI(wxUpdateUIEvent & ev)397 void wxCurlTransferDialog::OnAbortUpdateUI(wxUpdateUIEvent &ev)
398 {
399     ev.SetText(m_pThread->IsAlive() ? _("Abort") : _("Close"));
400 }
401 
OnPauseResume(wxCommandEvent & WXUNUSED (ev))402 void wxCurlTransferDialog::OnPauseResume(wxCommandEvent &WXUNUSED(ev))
403 {
404     wxASSERT(HasFlag(wxCTDS_CAN_PAUSE));
405 
406     if (m_pThread->IsRunning())
407     {
408         if (HandleCurlThreadError(m_pThread->Pause(), m_pThread))
409         {
410             FindWindowById(PauseResumeButtonId)->SetLabel(_("Resume"));
411 
412             if (m_pSpeed)
413                 m_pSpeed->SetLabel(_("0 (transfer paused)"));
414         }
415     }
416     else
417     {
418         if (HandleCurlThreadError(m_pThread->Resume(), m_pThread))
419         {
420             FindWindowById(PauseResumeButtonId)->SetLabel(_("Pause"));
421         }
422     }
423 }
424 
OnPauseResumeUpdateUI(wxUpdateUIEvent & ev)425 void wxCurlTransferDialog::OnPauseResumeUpdateUI(wxUpdateUIEvent &ev)
426 {
427     ev.Enable(m_pThread->IsAlive());
428 }
429 
OnStart(wxCommandEvent & WXUNUSED (ev))430 void wxCurlTransferDialog::OnStart(wxCommandEvent &WXUNUSED(ev))
431 {
432     //wxASSERT(HasFlag(wxCTDS_CAN_START));      // OnStart() must be usable also from RunModal() when !HasFlag(wxCTDS_CAN_START)
433 
434     wxCurlThreadError err = m_pThread->StartTransfer();
435     if (err != wxCTE_NO_ERROR)
436     {
437         HandleCurlThreadError(err, m_pThread);     // shows a message to the user
438         m_pThread->Abort();
439         EndModal(wxCDRF_FAILED);
440     }
441 }
442 
OnStartUpdateUI(wxUpdateUIEvent & ev)443 void wxCurlTransferDialog::OnStartUpdateUI(wxUpdateUIEvent &ev)
444 {
445     ev.Enable(!m_pThread->IsAlive() && !m_bTransferComplete);
446 }
447 
OnConnSettings(wxCommandEvent & WXUNUSED (ev))448 void wxCurlTransferDialog::OnConnSettings(wxCommandEvent &WXUNUSED(ev))
449 {
450     long style = 0;
451 
452     // convert our style into wxCurlConnectionSettingsDialog style:
453     if (HasFlag(wxCTDS_CONN_SETTINGS_AUTH))
454         style |= wxCCSP_AUTHENTICATION_OPTIONS;
455     if (HasFlag(wxCTDS_CONN_SETTINGS_PORT))
456         style |= wxCCSP_PORT_OPTION;
457     if (HasFlag(wxCTDS_CONN_SETTINGS_PROXY))
458         style |= wxCCSP_PROXY_OPTIONS;
459 
460     wxCurlConnectionSettingsDialog
461         dlg(_("Connection settings"), _("Connection settings used for the transfer:"),
462             this, style);
463 
464     dlg.RunModal(m_pThread->GetCurlSession());
465 }
466 
OnConnSettingsUpdateUI(wxUpdateUIEvent & ev)467 void wxCurlTransferDialog::OnConnSettingsUpdateUI(wxUpdateUIEvent &ev)
468 {
469     ev.Enable(!m_pThread->IsAlive() && !m_bTransferComplete);
470 }
471 
472 
473 // ----------------------------------------------------------------------------
474 // wxCurlTransferDialog - network events
475 // ----------------------------------------------------------------------------
476 
OnEndPerform(wxCurlEndPerformEvent & ev)477 void wxCurlTransferDialog::OnEndPerform(wxCurlEndPerformEvent &ev)
478 {
479     wxLogDebug(wxS("wxCurlTransferDialog::OnEndPerform"));
480 
481     // in case the very last transfer update event was skipped because
482     // of our anti-flickering label update policy, force the update with
483     // that event now (otherwise the dialog may remain open showing data
484     // related not to the end of the download!)
485     if (m_pLastEvent)
486         UpdateLabels(m_pLastEvent);
487     //else: we may have transferred a file of zero size and thus have never received any progress event...
488 
489     // now we're sure the transfer has completed: make the gauge
490     // completely "filled"
491     m_pGauge->SetValue(101);
492 
493     // this flag is used for updating labels etc:
494     m_bTransferComplete = true;
495 
496     // transfer has completed...
497     wxCurlDialogReturnFlag retCode = ev.IsSuccessful() ? wxCDRF_SUCCESS : wxCDRF_FAILED;
498 #if 0 // below is bugged because m_pThread->GetCurlSession() is NULL at this point...
499     if (retCode == wxCDRF_FAILED)
500     {
501         // show the user a message...
502         wxLogError(wxS("The transfer failed: %s (%s)"),
503                    m_pThread->GetCurlSession()->GetErrorString().c_str(),
504                    m_pThread->GetCurlSession()->GetDetailedErrorString().c_str());
505     }
506 #endif
507 
508     // do we need to close this window?
509     if (HasFlag(wxCTDS_AUTO_CLOSE))
510         EndModal(retCode);
511     else
512     {
513         SetReturnCode(retCode);     // will exit later in OnAbort()
514 
515         if (m_pSpeed)
516             m_pSpeed->SetLabel(_("0 (transfer completed)"));
517     }
518 }
519 
520 
521 
522 
523 // ----------------------------------------------------------------------------
524 // wxCurlDownloadDialog
525 // ----------------------------------------------------------------------------
526 
IMPLEMENT_DYNAMIC_CLASS(wxCurlDownloadDialog,wxCurlTransferDialog)527 IMPLEMENT_DYNAMIC_CLASS( wxCurlDownloadDialog, wxCurlTransferDialog )
528 BEGIN_EVENT_TABLE( wxCurlDownloadDialog, wxCurlTransferDialog )
529     EVT_CURL_DOWNLOAD( ThreadId, wxCurlDownloadDialog::OnDownload )
530 END_EVENT_TABLE()
531 
532 bool wxCurlDownloadDialog::Create(const wxString &url, wxOutputStream *out,
533                                   const wxString& title, const wxString& message,
534                                   const wxBitmap& bitmap,
535                                   wxWindow *parent, long style)
536 {
537     if (!wxCurlTransferDialog::Create(url, title, message, _("Downloaded:"), bitmap, parent, style))
538         return false;
539 
540     // register as the thread's event handler
541     wxCurlDownloadThread *thread = new wxCurlDownloadThread(this, ThreadId);
542 
543     m_pThread = thread;     // downcast our pointer for usage by wxCurlTransferDialog
544 
545     if (!HandleCurlThreadError(thread->SetURL(url), thread, url))
546         return false;
547     if (!HandleCurlThreadError(thread->SetOutputStream(out), thread))
548         return false;
549 
550     return true;
551 }
552 
OnDownload(wxCurlDownloadEvent & ev)553 void wxCurlDownloadDialog::OnDownload(wxCurlDownloadEvent &ev)
554 {
555     static wxDateTime lastLabelUpdate(0, 0, 0, 0);      // zero is to force always at least an update
556     if ((wxDateTime::Now() - lastLabelUpdate).GetMilliseconds() > 200)   // avoid flickering
557     {
558         UpdateLabels(&ev);
559 
560         lastLabelUpdate = wxDateTime::Now();
561     }
562 
563     // see OnEndPerform for more info.
564     if (m_pLastEvent)
565         delete m_pLastEvent;
566     m_pLastEvent = wx_static_cast(wxCurlProgressBaseEvent*, ev.Clone());
567 }
568 
569 
570 
571 // ----------------------------------------------------------------------------
572 // wxCurlUploadDialog
573 // ----------------------------------------------------------------------------
574 
IMPLEMENT_DYNAMIC_CLASS(wxCurlUploadDialog,wxCurlTransferDialog)575 IMPLEMENT_DYNAMIC_CLASS( wxCurlUploadDialog, wxCurlTransferDialog )
576 BEGIN_EVENT_TABLE( wxCurlUploadDialog, wxCurlTransferDialog )
577     EVT_CURL_UPLOAD( ThreadId, wxCurlUploadDialog::OnUpload )
578 END_EVENT_TABLE()
579 
580 bool wxCurlUploadDialog::Create(const wxString &url, wxInputStream *in,
581                                   const wxString& title, const wxString& message,
582                                   const wxBitmap& bitmap,
583                                   wxWindow *parent, long style)
584 {
585     if (!wxCurlTransferDialog::Create(url, title, message, _("Uploaded:"), bitmap, parent, style))
586         return false;
587 
588     // register as the thread's event handler
589     wxCurlUploadThread *thread = new wxCurlUploadThread(this, ThreadId);
590 
591     m_pThread = thread;     // downcast our pointer for usage by wxCurlTransferDialog
592 
593     if (!HandleCurlThreadError(thread->SetURL(url), thread, url))
594         return false;
595     if (!HandleCurlThreadError(thread->SetInputStream(in), thread))
596         return false;
597 
598     return true;
599 }
600 
OnUpload(wxCurlUploadEvent & ev)601 void wxCurlUploadDialog::OnUpload(wxCurlUploadEvent &ev)
602 {
603     static wxDateTime lastLabelUpdate(0, 0, 0, 0);      // zero is to force always at least an update
604     if ((wxDateTime::Now() - lastLabelUpdate).GetMilliseconds() > 200)   // avoid flickering
605     {
606         UpdateLabels(&ev);
607 
608         lastLabelUpdate = wxDateTime::Now();
609     }
610 
611     // see OnEndPerform for more info.
612     if (m_pLastEvent)
613         delete m_pLastEvent;
614     m_pLastEvent = wx_static_cast(wxCurlProgressBaseEvent*, ev.Clone());
615 }
616 
617 
618 
619 // ----------------------------------------------------------------------------
620 // wxCurlConnectionSettingsDialog
621 // ----------------------------------------------------------------------------
622 
IMPLEMENT_DYNAMIC_CLASS(wxCurlConnectionSettingsDialog,wxDialog)623 IMPLEMENT_DYNAMIC_CLASS( wxCurlConnectionSettingsDialog, wxDialog )
624 
625 bool wxCurlConnectionSettingsDialog::Create(const wxString& title,
626                                             const wxString& message,
627                                             wxWindow *parent,
628                                             long style)
629 {
630     if (!wxDialog::Create(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
631                           wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER))
632         return false;
633 
634     m_pPanel = new wxCurlConnectionSettingsPanel(this, wxID_ANY, message, wxDefaultPosition,
635                                                  wxDefaultSize, style);
636 
637     wxSizer *main = new wxBoxSizer(wxVERTICAL);
638     wxSizer *buttons = CreateSeparatedButtonSizer(wxOK|wxCANCEL);
639 
640     main->Add(m_pPanel, 1, wxGROW|wxALL, 10);
641     main->Add(buttons, 0, wxGROW|wxALL, 10);
642 
643     SetSizerAndFit(main);
644 
645     return true;
646 }
647 
RunModal(wxCurlBase * pCURL)648 void wxCurlConnectionSettingsDialog::RunModal(wxCurlBase *pCURL)
649 {
650     if (ShowModal() == wxID_OK)
651         m_pPanel->SetCURLOptions(pCURL);
652 }
653 
654