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