downloadprogresspanel.cpp

00001 
00002 // Name:        downloadprogresspanel.cpp
00003 // Purpose:     wxDownloadProgressPanel
00004 // Author:      Francesco Montorsi
00005 // Modified by:
00006 // Created:     15/07/2006 16:25:14
00007 // RCS-ID:      $Id: downloadprogresspanel.cpp,v 1.8 2007/01/31 14:39:31 frm Exp $
00008 // Copyright:   (c) 2006 Francesco Montorsi
00009 // Licence:     wxWidgets license
00011 
00012 
00013 // For compilers that support precompilation, includes "wx/wx.h".
00014 #include "wx/wxprec.h"
00015 
00016 #ifdef __BORLANDC__
00017 #pragma hdrstop
00018 #endif
00019 
00020 #ifndef WX_PRECOMP
00021 #include "wx/wx.h"
00022 #endif
00023 
00024 #include "guipm/downloadprogresspanel.h"
00025 #include "wx/oscopectrl.h"
00026 #include "wx/stdpaths.h"
00027 
00028 
00029 // ----------------------------------------------------------------------------
00030 // wxDownloadProgressPanel
00031 // ----------------------------------------------------------------------------
00032 
00033 IMPLEMENT_DYNAMIC_CLASS( wxDownloadProgressPanel, wxProgressPanel )
00034 BEGIN_EVENT_TABLE( wxDownloadProgressPanel, wxProgressPanel )
00035 
00036     EVT_TIMER(ID_DOWNLOADPROGRESS_TIMER, wxDownloadProgressPanel::OnTimer)
00037 
00038     // download thread events
00039     EVT_DOWNLOAD_UPDATE(ID_DOWNLOADPROGRESS_THREAD, 
00040                         wxDownloadProgressPanel::OnDownloadProgress)
00041     EVT_DOWNLOAD_COMPLETE(ID_DOWNLOADPROGRESS_THREAD, 
00042                           wxDownloadProgressPanel::OnDownloadComplete)
00043     EVT_DOWNLOAD_ABORTED(ID_DOWNLOADPROGRESS_THREAD, 
00044                          wxDownloadProgressPanel::OnDownloadAbort)
00045     EVT_DOWNLOAD_USER_ABORTED(ID_DOWNLOADPROGRESS_THREAD, 
00046                               wxDownloadProgressPanel::OnDownloadUserAbort)
00047 END_EVENT_TABLE()
00048 
00049 
00050 wxDownloadProgressPanel::wxDownloadProgressPanel( )
00051 {
00052 }
00053 
00054 wxDownloadProgressPanel::wxDownloadProgressPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
00055 {
00056     Create(parent, id, pos, size, style);
00057 }
00058 
00059 bool wxDownloadProgressPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
00060 {
00061     m_bThreadExists = false;
00062 
00064     m_pRemainingTime = NULL;
00065     m_pElapsedTime = NULL;
00066     m_pSize = NULL;
00067     m_pSpeed = NULL;
00068     m_pDestination = NULL;
00069     m_pAnimation = NULL;
00070     m_pOScope = NULL;
00071     m_pGauge = NULL;
00073 
00075     wxProgressPanel::Create( parent, id, pos, size, style );
00076 
00077     CreateControls();
00078     if (GetSizer())
00079     {
00080         GetSizer()->SetSizeHints(this);
00081     }
00083     return true;
00084 }
00085 
00086 void wxDownloadProgressPanel::CreateControls()
00087 {
00088         // the label and the URL will be set later
00089         m_pSource = new wxHyperlinkCtrl(this, ID_DOWNLOADPROGRESS_SOURCE,
00090                                             wxT("Not Available"), wxEmptyString,
00091                                     wxDefaultPosition, wxDefaultSize,
00092                                     wxNO_BORDER|wxHL_CONTEXTMENU|wxHL_ALIGN_LEFT);
00093 
00094     wxString imgpath = wxStandardPaths::Get().GetDataDir() + 
00095                        wxFileName::GetPathSeparator() + 
00096                        wxT("images") + wxFileName::GetPathSeparator();
00097     m_animation.LoadFile(imgpath + wxT("internetfiletransfer.gif"));
00098 
00099 
00101     wxDownloadProgressPanel* itemProgressPanel1 = this;
00102 
00103     wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
00104     itemProgressPanel1->SetSizer(itemBoxSizer2);
00105 
00106     wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
00107     itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW, 5);
00108 
00109     wxFlexGridSizer* itemFlexGridSizer4 = new wxFlexGridSizer(2, 2, 0, 15);
00110     itemFlexGridSizer4->AddGrowableCol(1);
00111     itemBoxSizer3->Add(itemFlexGridSizer4, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
00112 
00113     wxStaticText* itemStaticText5 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Time left:"), wxDefaultPosition, wxDefaultSize, 0 );
00114     itemFlexGridSizer4->Add(itemStaticText5, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00115 
00116     m_pRemainingTime = new wxStaticText( itemProgressPanel1, ID_DOWNLOADPROGRESS_TIMELEFT, _("Static text"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
00117     itemFlexGridSizer4->Add(m_pRemainingTime, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00118 
00119     wxStaticText* itemStaticText7 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Elapsed time:"), wxDefaultPosition, wxDefaultSize, 0 );
00120     itemFlexGridSizer4->Add(itemStaticText7, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00121 
00122     m_pElapsedTime = new wxStaticText( itemProgressPanel1, ID_DOWNLOADPROGRESS_ELAPSEDTIME, _("Static text"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
00123     itemFlexGridSizer4->Add(m_pElapsedTime, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00124 
00125     wxStaticText* itemStaticText9 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Size:"), wxDefaultPosition, wxDefaultSize, 0 );
00126     itemFlexGridSizer4->Add(itemStaticText9, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00127 
00128     m_pSize = new wxStaticText( itemProgressPanel1, ID_DOWNLOADPROGRESS_SIZE, _("Static text"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
00129     itemFlexGridSizer4->Add(m_pSize, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00130 
00131     wxStaticText* itemStaticText11 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
00132     itemFlexGridSizer4->Add(itemStaticText11, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00133 
00134     m_pSpeed = new wxStaticText( itemProgressPanel1, ID_DOWNLOADPROGRESS_SPEED, _("Static text"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
00135     itemFlexGridSizer4->Add(m_pSpeed, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00136 
00137     wxStaticText* itemStaticText13 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Downloading:"), wxDefaultPosition, wxDefaultSize, 0 );
00138     itemFlexGridSizer4->Add(itemStaticText13, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00139 
00140     wxWindow* itemWindow14 = (wxWindow*) FindWindow(ID_DOWNLOADPROGRESS_SOURCE);
00141     wxASSERT( itemWindow14 != NULL );
00142     itemFlexGridSizer4->Add(itemWindow14, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP, 5);
00143 
00144     wxStaticText* itemStaticText15 = new wxStaticText( itemProgressPanel1, wxID_STATIC, _("Destination:"), wxDefaultPosition, wxDefaultSize, 0 );
00145     itemFlexGridSizer4->Add(itemStaticText15, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00146 
00147     m_pDestination = new wxStaticText( itemProgressPanel1, ID_DOWNLOADPROGRESS_DESTINATION, _("Static text"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE );
00148     itemFlexGridSizer4->Add(m_pDestination, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
00149 
00150     m_pAnimation = new wxAnimationCtrl( itemProgressPanel1, ID_DOWNLOADPROGRESS_ANIMATION, m_animation );
00151     itemBoxSizer3->Add(m_pAnimation, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
00152 
00153     itemBoxSizer3->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
00154 
00155     itemBoxSizer2->Add(50, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT|wxBOTTOM, 5);
00156 
00157     m_pOScope = new wxOScopeCtrl( itemProgressPanel1, ID_DOWNLOADPROGRESS_SPEEDLOG, wxDefaultPosition, wxDefaultSize, 0 );
00158     itemBoxSizer2->Add(m_pOScope, 1, wxGROW|wxALL, 5);
00159 
00160     m_pGauge = new wxGauge( itemProgressPanel1, ID_DOWNLOADPROGRESS_GAUGE, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL );
00161     m_pGauge->SetValue(0);
00162     itemBoxSizer2->Add(m_pGauge, 0, wxGROW|wxALL, 5);
00163 
00164     itemBoxSizer2->Add(50, 1, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT|wxBOTTOM, 5);
00165 
00167 
00168 #define NUM_MINUTES     5
00169 
00170     // setup the oscope control to show the speed of the downloads
00171     // in the last NUM_MINUTES minutes
00172     m_pOScope->SetFixedXRange(1000 * 60 * NUM_MINUTES);
00173     m_pOScope->SetXUnits(wxString::Format(wxT("Last %d minutes"), NUM_MINUTES));
00174 
00175     wxOScopeData dt(ID_DOWNLOADPROGRESS_TIMER_INTERVAL, 
00176                     0.0, 100.0, *wxGREEN);
00177     m_pOScope->AddData(dt);
00178 
00179     // NB: later in OnTimer() we tell the oscope control to update the
00180     //     y range keeping a little negative offset from the lowest
00181     //     sampled data point available, which in our case is always zero
00182     //     (we don't sample any negative value!); we do that to avoid that
00183     //     for some rounding errors the zero-speed line is clipped off the
00184     //     oscope control - but in any case we still want to have the ymin
00185     //     labeled as "0" so we explicitely set the ymin label here
00186     m_pOScope->SetYUnits(wxT("Kb/s"), wxT("0"));
00187 
00188     // run the timer even when not downloading...
00189     m_timer.SetOwner(this, ID_DOWNLOADPROGRESS_TIMER);
00190     m_timer.Start(ID_DOWNLOADPROGRESS_TIMER_INTERVAL);
00191 
00192     ClearControls();
00193 }
00194 
00195 bool wxDownloadProgressPanel::ShowToolTips()
00196 {
00197     return true;
00198 }
00199 
00200 void wxDownloadProgressPanel::Start()
00201 {
00202     wxFileOutputStream *out = new wxFileOutputStream(m_pkg.GetDownloadPath());
00203     if (!out->IsOk())
00204     {
00205         wxLogError(wxT("Problems creating the output file %s!"),
00206                    m_pkg.GetDownloadPath().c_str());
00207         return;
00208     }
00209 
00210     // reset the gauge GUI
00211     m_pGauge->SetValue(0);
00212     m_pGauge->SetRange(100);
00213     m_flag = wxDTF_CONTINUE;
00214 
00215     // by now, set it to false
00216     m_bSuccess = false;
00217 
00218     // just before launching the new thread, set up some things;
00219     // note that these must be done _before_ launching the thread
00220     // since it may happen that just after thread creation the thread
00221     // ends and the wxEVT_DOWNLOAD_COMPLETE is received before e.g.
00222     // the animation has started to play!
00223     m_bThreadExists = true;
00224     m_pAnimation->Play();
00225 
00226     wxString url = m_pkg.GetDownloadLink();
00227     wxASSERT_MSG(!url.IsEmpty(), 
00228                  wxT("packages without valid download links shouldn't have been queued!"));
00229 
00230     // launch the new download thread
00231     new wxDownloadThread(this, ID_DOWNLOADPROGRESS_THREAD, &m_flag, url, out);
00232 }
00233 
00234 void wxDownloadProgressPanel::Stop()
00235 {
00236     // stop the thread but don't delete it
00237     m_flag = wxDTF_ABORT;
00238 
00239     // wait until the thread does not receive this pause command
00240     while (m_bThreadExists)
00241     {
00242         // process events
00243         wxYield();
00244     }
00245 
00246     // ClearControls() will be automatically called by wxPackageTaskQueuePanel
00247 }
00248 
00249 bool wxDownloadProgressPanel::IsProcessing() const
00250 {
00251     return m_bThreadExists;
00252 }
00253 
00254 void wxDownloadProgressPanel::SetPackage(const wxPackage &pkg)
00255 {
00256     wxProgressPanel::SetPackage(pkg);
00257 
00258     // update source label
00259     m_pSource->SetLabel(pkg.GetDownloadLink());
00260     m_pSource->SetURL(pkg.GetDownloadLink());
00261     m_pSource->Refresh();
00262 
00263     m_pDestination->SetLabel(pkg.GetDownloadPath());
00264 }
00265 
00266 wxString wxDownloadProgressPanel::GetLogData() const
00267 {
00268     return wxString::Format(
00269         wxT("Download of %s (size of the compressed package) %s"),
00270         wxFileName::GetHumanReadableSize(
00271                 (const wxULongLong &)m_pkg.GetCompressedSize()).c_str(),
00272         m_bSuccess ? wxT("was successful.") : wxT("failed!"));
00273 }
00274 
00275 wxString wxDownloadProgressPanel::GetLogLabel() const
00276 {
00277     return wxString::Format(wxT("Download log for %s:"),
00278                             m_pkg.GetName().c_str());
00279 }
00280 
00281 void wxDownloadProgressPanel::ClearControls()
00282 {
00283     m_pRemainingTime->SetLabel(wxT("Not available"));
00284     m_pElapsedTime->SetLabel(wxT("Not available"));
00285     m_pSpeed->SetLabel(wxT("Not available"));
00286     m_pSize->SetLabel(wxT("Not available"));
00287 
00288     m_pSource->SetURL(wxT("Not Available"));
00289     m_pSource->SetLabel(wxT("Not Available"));
00290     m_pSource->Refresh();
00291 
00292     m_pDestination->SetLabel(wxT("Not Available"));
00293 
00294     m_pRemainingTime->GetContainingSizer()->Layout();
00295 }
00296 
00297 void wxDownloadProgressPanel::DoEnd(bool success)
00298 {
00299     // for some reason the download has ended...
00300 
00301     m_bSuccess = success;
00302     m_bThreadExists = false;
00303 
00304     // reset the GUI
00305     m_pGauge->SetValue(0);
00306     m_pAnimation->Stop();
00307     m_nLastSpeed = 0;
00308 
00309     // remove the partially downloaded file, if the download failed
00310     // (else it will force wxPM to show an annoying message 'cannot load package X'
00311     //  the next time the wxPM is started).
00312     wxString path = m_pkg.GetDownloadPath();
00313     if (success == false && wxFileExists(path))
00314     {
00315         bool removeSuccess;
00316 
00317         {
00318             wxLogNull trash;
00319             removeSuccess = wxRemoveFile(m_pkg.GetDownloadPath());
00320         }
00321 
00322         if (!removeSuccess)
00323             wxLogError(wxT("Couldn't remove the '%s' incomplete download. Please do remove it manually."), path.c_str());
00324     }
00325 
00326     // download ended...
00327     wxCommandEvent ev(success ? wxEVT_COMMAND_PROGRESS_END : wxEVT_COMMAND_PROGRESS_FAILED,
00328                       GetId());
00329     GetEventHandler()->AddPendingEvent(ev);
00330 }
00331 
00332 
00333 // ----------------------------------------------------------------------------
00334 // wxDownloadProgressPanel - event handlers
00335 // ----------------------------------------------------------------------------
00336 
00337 void wxDownloadProgressPanel::OnDownloadProgress(wxDownloadEvent &ev)
00338 {
00339     static wxDateTime lastLabelUpdate = wxDateTime::Now();
00340 
00341     // avoid flickering: update no more often than 200 ms
00342     if ((wxDateTime::Now() - lastLabelUpdate).GetMilliseconds() < 200)
00343         return;
00344 
00345     double fraction = ev.GetDownloadProgress();
00346     if (fraction != 0)
00347     {
00348         m_pGauge->SetValue((int)(fraction * 100));
00349     }
00350     else
00351     {
00352         // we don't know how much we progressed
00353         m_pGauge->Pulse();
00354     }
00355 
00356     if (m_pElapsedTime)
00357         m_pElapsedTime->SetLabel(ev.GetElapsedTime().Format());
00358     if (m_pRemainingTime)
00359         m_pRemainingTime->SetLabel(ev.GetEstimatedRemainingTime().Format());
00360 
00361     // update size & speed
00362     wxString currsize = wxFileName::GetHumanReadableSize(ev.GetCurrentSize()),
00363              totalsize = wxFileName::GetHumanReadableSize(ev.GetTotalSize());
00364     m_pSize->SetLabel(currsize + wxT(" / ") + totalsize);
00365     m_pSpeed->SetLabel(ev.GetHumanReadableDownloadSpeed());
00366 
00367     // add a new sample for the download speed
00368     m_nLastSpeed = ev.GetDownloadSpeed();
00369 
00370     lastLabelUpdate = wxDateTime::Now();
00371 }
00372 
00373 void wxDownloadProgressPanel::OnDownloadComplete(wxDownloadEvent &event)
00374 {
00375     m_pkg.SetCompressedSize(event.GetTotalSize());
00376     DoEnd(true);
00377 }
00378 
00379 void wxDownloadProgressPanel::OnDownloadAbort(wxDownloadEvent &WXUNUSED(event))
00380 {
00381     DoEnd(false);
00382 }
00383 
00384 void wxDownloadProgressPanel::OnDownloadUserAbort(wxDownloadEvent &WXUNUSED(event))
00385 {
00386     DoEnd(false);
00387 }
00388 
00389 void wxDownloadProgressPanel::OnTimer(wxTimerEvent& WXUNUSED(evt))
00390 {
00391     // update the oscope ctrl with the speed for the last event
00392     // NOTE: we need to convert from bytes/second to kilobyte/second
00393     m_pOScope->AddSampleDataAndUpdateRange(0, (float)(m_nLastSpeed.ToDouble() / 1000.),
00394                                               (float)-0.5, +10.0);
00395 }

Generated on Thu Feb 1 22:14:30 2007 for wxWidgets Package Manager by  doxygen 1.5.1-p1