[haiku-webkit-commits] r352 - in webkit/trunk/WebKit: . haiku/WebPositive

  • From: webkit@xxxxxxxxxxxxxxx
  • To: haiku-webkit-commits@xxxxxxxxxxxxx
  • Date: Wed, 24 Mar 2010 20:20:54 +0000

Author: stippi
Date: Wed Mar 24 20:20:53 2010
New Revision: 352
URL: http://mmlr.dyndns.org/changeset/352

Log:
Implemented displaying the download speed and estimated finish time. Looks and
behaves the same as in Tracker's status window.

Modified:
   webkit/trunk/WebKit/Jamfile
   webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.cpp
   webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.h
   webkit/trunk/WebKit/haiku/WebPositive/DownloadWindow.cpp

Modified: webkit/trunk/WebKit/Jamfile
==============================================================================
--- webkit/trunk/WebKit/Jamfile Wed Mar 24 20:19:40 2010        (r351)
+++ webkit/trunk/WebKit/Jamfile Wed Mar 24 20:20:53 2010        (r352)
@@ -131,6 +131,7 @@
     FontSelectionView.cpp
     IconButton.cpp
     SettingsMessage.cpp
+    StringForSize.cpp
        # WebPositive
     AuthenticationPanel.cpp
     BrowsingHistory.cpp

Modified: webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.cpp      Wed Mar 
24 20:19:40 2010        (r351)
+++ webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.cpp      Wed Mar 
24 20:20:53 2010        (r352)
@@ -35,15 +35,17 @@
 #include <Directory.h>
 #include <Entry.h>
 #include <FindDirectory.h>
-#include <GridLayoutBuilder.h>
+#include <GroupLayoutBuilder.h>
 #include <NodeInfo.h>
 #include <NodeMonitor.h>
 #include <Roster.h>
 #include <SpaceLayoutItem.h>
 #include <StatusBar.h>
+#include <StringView.h>
 
 #include "WebDownload.h"
 #include "WebPage.h"
+#include "StringForSize.h"
 
 
 enum {
@@ -53,6 +55,14 @@
        REMOVE_DOWNLOAD = 'rmdn',
 };
 
+const bigtime_t kMaxUpdateInterval = 100000LL;
+const bigtime_t kSpeedReferenceInterval = 500000LL;
+const bigtime_t kShowSpeedInterval = 8000000LL;
+const bigtime_t kShowEstimatedFinishInterval = 4000000LL;
+
+bigtime_t DownloadProgressView::sLastEstimatedFinishSpeedToggleTime = -1;
+bool DownloadProgressView::sShowSpeed = true;
+
 
 class IconView : public BView {
 public:
@@ -167,22 +177,20 @@
 
 DownloadProgressView::DownloadProgressView(BWebDownload* download)
        :
-       BGridView(8, 3),
+       BGroupView(B_HORIZONTAL, 8),
        fDownload(download),
        fURL(download->URL()),
-       fPath(download->Path()),
-       fExpectedSize(download->ExpectedSize())
+       fPath(download->Path())
 {
 }
 
 
 DownloadProgressView::DownloadProgressView(const BMessage* archive)
        :
-       BGridView(8, 3),
+       BGroupView(B_HORIZONTAL, 8),
        fDownload(NULL),
        fURL(),
-       fPath(),
-       fExpectedSize(0)
+       fPath()
 {
        const char* string;
        if (archive->FindString("path", &string) == B_OK)
@@ -195,10 +203,22 @@
 bool
 DownloadProgressView::Init(BMessage* archive)
 {
+       fCurrentSize = 0;
+       fExpectedSize = 0;
+       fLastUpdateTime = 0;
+       fBytesPerSecond = 0.0;
+       for (size_t i = 0; i < kBytesPerSecondSlots; i++)
+               fBytesPerSecondSlot[i] = 0.0;
+       fCurrentBytesPerSecondSlot = 0;
+       fLastSpeedReferenceSize = 0;
+       fEstimatedFinishReferenceSize = 0;
+
+       fProcessStartTime = fLastSpeedReferenceTime = 
fEstimatedFinishReferenceTime
+               = system_time();
+
        SetViewColor(245, 245, 245);
        SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW);
 
-       BGridLayout* layout = GridLayout();
        if (archive) {
                fStatusBar = new BStatusBar("download progress", fPath.Leaf());
                float value;
@@ -233,11 +253,37 @@
                fBottomButton->SetEnabled(fDownload == NULL);
        }
 
+       fInfoView = new BStringView("info view", "");
+
+       BGroupLayout* layout = GroupLayout();
        layout->SetInsets(8, 5, 5, 6);
-       layout->AddView(fIconView, 0, 0, 1, 2);
-       layout->AddView(fStatusBar, 1, 0, 1, 2);
-       layout->AddView(fTopButton, 2, 0);
-       layout->AddView(fBottomButton, 2, 1);
+       layout->AddView(fIconView);
+       BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
+               .Add(fStatusBar)
+               .Add(fInfoView)
+       ;
+       verticalGroup->SetViewColor(ViewColor());
+       layout->AddView(verticalGroup);
+       verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
+               .Add(fTopButton)
+               .Add(fBottomButton)
+       ;
+       verticalGroup->SetViewColor(ViewColor());
+       layout->AddView(verticalGroup);
+
+       BFont font;
+       fInfoView->GetFont(&font);
+       float fontSize = font.Size() * 0.8f;
+       font.SetSize(max_c(8.0f, fontSize));
+       fInfoView->SetFont(&font, B_FONT_SIZE);
+       fInfoView->SetHighColor(tint_color(fInfoView->LowColor(),
+               B_DARKEN_4_TINT));
+//     font_height fontHeight;
+//     font.GetHeight(&fontHeight);
+//     float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
+//     fInfoView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight));
+//     fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, textHeight));
+       fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
 
        return true;
 }
@@ -314,13 +360,23 @@
                        fIconView->SetTo(entry);
                        fStatusBar->Reset(fPath.Leaf());
                        _StartNodeMonitor(entry);
+
+                       // Immediately switch to speed display whenever a new 
download
+                       // starts.
+                       sShowSpeed = true;
+                       sLastEstimatedFinishSpeedToggleTime
+                               = fProcessStartTime = fLastSpeedReferenceTime
+                               = fEstimatedFinishReferenceTime = system_time();
                        break;
                };
                case B_DOWNLOAD_PROGRESS:
                {
-                       float progress;
-                       if (message->FindFloat("progress", &progress) == B_OK)
-                               fStatusBar->SetTo(progress);
+                       int64 currentSize;
+                       int64 expectedSize;
+                       if (message->FindInt64("current size", &currentSize) == 
B_OK
+                               && message->FindInt64("expected size", 
&expectedSize) == B_OK) {
+                               _UpdateStatus(currentSize, expectedSize);
+                       }
                        break;
                }
                case OPEN_DOWNLOAD:
@@ -427,7 +483,7 @@
                        break;
                }
                default:
-                       BGridView::MessageReceived(message);
+                       BGroupView::MessageReceived(message);
        }
 }
 
@@ -468,6 +524,7 @@
        fBottomButton->SetLabel("Remove");
        fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD));
        fBottomButton->SetEnabled(true);
+       fInfoView->SetText("");
 }
 
 
@@ -484,10 +541,172 @@
 }
 
 
+/*static*/ void
+DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse()
+{
+       bigtime_t now = system_time();
+       if (sShowSpeed
+               && sLastEstimatedFinishSpeedToggleTime + kShowSpeedInterval
+                       <= now) {
+               sShowSpeed = false;
+               sLastEstimatedFinishSpeedToggleTime = now;
+       } else if (!sShowSpeed
+               && sLastEstimatedFinishSpeedToggleTime
+                       + kShowEstimatedFinishInterval <= now) {
+               sShowSpeed = true;
+               sLastEstimatedFinishSpeedToggleTime = now;
+       }
+}
+
+
 // #pragma mark - private
 
 
 void
+DownloadProgressView::_UpdateStatus(off_t currentSize, off_t expectedSize)
+{
+       fCurrentSize = currentSize;
+       fExpectedSize = expectedSize;
+
+       fStatusBar->SetTo(100.0 * currentSize / expectedSize);
+
+       bigtime_t currentTime = system_time();
+       if ((currentTime - fLastUpdateTime) > kMaxUpdateInterval) {
+               fLastUpdateTime = currentTime;
+
+               if (currentTime >= fLastSpeedReferenceTime + 
kSpeedReferenceInterval) {
+                       // update current speed every kSpeedReferenceInterval
+                       fCurrentBytesPerSecondSlot
+                               = (fCurrentBytesPerSecondSlot + 1) % 
kBytesPerSecondSlots;
+                       fBytesPerSecondSlot[fCurrentBytesPerSecondSlot]
+                               = (double)(currentSize - 
fLastSpeedReferenceSize)
+                                       * 1000000LL / (currentTime - 
fLastSpeedReferenceTime);
+                       fLastSpeedReferenceSize = currentSize;
+                       fLastSpeedReferenceTime = currentTime;
+                       fBytesPerSecond = 0.0;
+                       size_t count = 0;
+                       for (size_t i = 0; i < kBytesPerSecondSlots; i++) {
+                               if (fBytesPerSecondSlot[i] != 0.0) {
+                                       fBytesPerSecond += 
fBytesPerSecondSlot[i];
+                                       count++;
+                               }
+                       }
+                       if (count > 0)
+                               fBytesPerSecond /= count;
+               }
+               _UpdateStatusText();
+       }
+}
+
+
+void
+DownloadProgressView::_UpdateStatusText()
+{
+       fInfoView->SetText("");
+       BString buffer;
+       if (sShowSpeed && fBytesPerSecond != 0.0) {
+               // Draw speed info
+               char sizeBuffer[128];
+               buffer = "(";
+               buffer << string_for_size((double)fCurrentSize, sizeBuffer,
+                       sizeof(sizeBuffer));
+               buffer << " of ";
+               buffer << string_for_size((double)fExpectedSize, sizeBuffer,
+                       sizeof(sizeBuffer));
+               buffer << ", ";
+               buffer << string_for_size(fBytesPerSecond, sizeBuffer,
+                       sizeof(sizeBuffer));
+               buffer << "/s)";
+               float stringWidth = fInfoView->StringWidth(buffer.String());
+               if (stringWidth < fInfoView->Bounds().Width())
+                       fInfoView->SetText(buffer.String());
+               else {
+                       // complete string too wide, try with shorter version
+                       buffer << string_for_size(fBytesPerSecond, sizeBuffer,
+                               sizeof(sizeBuffer));
+                       buffer << "/s";
+                       stringWidth = fInfoView->StringWidth(buffer.String());
+                       if (stringWidth < fInfoView->Bounds().Width())
+                               fInfoView->SetText(buffer.String());
+               }
+       } else if (!sShowSpeed && fCurrentSize < fExpectedSize) {
+               double totalBytesPerSecond = (double)(fCurrentSize
+                               - fEstimatedFinishReferenceSize)
+                       * 1000000LL / (system_time() - 
fEstimatedFinishReferenceTime);
+               double secondsRemaining = (fExpectedSize - fCurrentSize)
+                       / totalBytesPerSecond;
+               time_t now = (time_t)real_time_clock();
+               time_t finishTime = (time_t)(now + secondsRemaining);
+
+               tm _time;
+               tm* time = localtime_r(&finishTime, &_time);
+               int32 year = time->tm_year + 1900;
+
+               char timeText[32];
+               time_t secondsPerDay = 24 * 60 * 60;
+               // TODO: Localization of time string...
+               if (now < finishTime - secondsPerDay) {
+                       // process is going to take more than a day!
+                       sprintf(timeText, "%0*d:%0*d %0*d/%0*d/%ld",
+                               2, time->tm_hour, 2, time->tm_min,
+                               2, time->tm_mon + 1, 2, time->tm_mday, year);
+               } else {
+                       sprintf(timeText, "%0*d:%0*d",
+                               2, time->tm_hour, 2, time->tm_min);
+               }
+
+               BString buffer1("Finish: ");
+               buffer1 << timeText;
+               finishTime -= now;
+               time = gmtime(&finishTime);
+
+               BString buffer2;
+               if (finishTime > secondsPerDay) {
+                       int64 days = finishTime / secondsPerDay;
+                       if (days == 1)
+                               buffer2 << "Over 1 day";
+                       else
+                               buffer2 << "Over " << days << " days";
+               } else if (finishTime > 60 * 60) {
+                       int64 hours = finishTime / (60 * 60);
+                       if (hours == 1)
+                               buffer2 << "Over 1 hour";
+                       else
+                               buffer2 << "Over " << hours << " hours";
+               } else if (finishTime > 60) {
+                       int64 minutes = finishTime / 60;
+                       if (minutes == 1)
+                               buffer2 << "Over 1 minute";
+                       else
+                               buffer2 << minutes << " minutes";
+               } else {
+                       if (finishTime == 1)
+                               buffer2 << "1 second";
+                       else
+                               buffer2 << finishTime << " seconds";
+               }
+
+               buffer2 << " left";
+
+               buffer = "(";
+               buffer << buffer1 << " - " << buffer2 << ")";
+
+               float stringWidth = fInfoView->StringWidth(buffer.String());
+               if (stringWidth < fInfoView->Bounds().Width())
+                       fInfoView->SetText(buffer.String());
+               else {
+                       // complete string too wide, try with shorter version
+                       buffer = "(";
+                       buffer << buffer1 << ")";
+                       stringWidth = fInfoView->StringWidth(buffer.String());
+                       if (stringWidth < fInfoView->Bounds().Width())
+                               fInfoView->SetText(buffer.String());
+               }
+       }
+}
+
+
+void
 DownloadProgressView::_StartNodeMonitor(const BEntry& entry)
 {
        node_ref nref;

Modified: webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.h
==============================================================================
--- webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.h        Wed Mar 
24 20:19:40 2010        (r351)
+++ webkit/trunk/WebKit/haiku/WebPositive/DownloadProgressView.h        Wed Mar 
24 20:20:53 2010        (r352)
@@ -28,12 +28,13 @@
 #define DOWNLOAD_PROGRESS_VIEW_H
 
 
-#include <GridView.h>
+#include <GroupView.h>
 #include <Path.h>
 #include <String.h>
 
 class BEntry;
 class BStatusBar;
+class BStringView;
 class BWebDownload;
 class IconView;
 class SmallButton;
@@ -44,7 +45,7 @@
 };
 
 
-class DownloadProgressView : public BGridView {
+class DownloadProgressView : public BGroupView {
 public:
                                                                
DownloadProgressView(BWebDownload* download);
                                                                
DownloadProgressView(const BMessage* archive);
@@ -68,19 +69,41 @@
                        void                            DownloadFinished();
                        void                            DownloadCanceled();
 
+       static  void                            
SpeedVersusEstimatedFinishTogglePulse();
+
 private:
+                       void                            _UpdateStatus(off_t 
currentSize,
+                                                                       off_t 
expectedSize);
+                       void                            _UpdateStatusText();
                        void                            _StartNodeMonitor(const 
BEntry& entry);
                        void                            _StopNodeMonitor();
 
 private:
                        IconView*                       fIconView;
                        BStatusBar*                     fStatusBar;
+                       BStringView*            fInfoView;
                        SmallButton*            fTopButton;
                        SmallButton*            fBottomButton;
                        BWebDownload*           fDownload;
                        BString                         fURL;
                        BPath                           fPath;
+
+                       off_t                           fCurrentSize;
                        off_t                           fExpectedSize;
+                       off_t                           fLastSpeedReferenceSize;
+                       off_t                           
fEstimatedFinishReferenceSize;
+                       bigtime_t                       fLastUpdateTime;
+                       bigtime_t                       fLastSpeedReferenceTime;
+                       bigtime_t                       fProcessStartTime;
+                       bigtime_t                       fLastSpeedUpdateTime;
+                       bigtime_t                       
fEstimatedFinishReferenceTime;
+       static  const size_t            kBytesPerSecondSlots = 10;
+                       size_t                          
fCurrentBytesPerSecondSlot;
+                       double                          
fBytesPerSecondSlot[kBytesPerSecondSlots];
+                       double                          fBytesPerSecond;
+
+       static  bigtime_t                       
sLastEstimatedFinishSpeedToggleTime;
+       static  bool                            sShowSpeed;
 };
 
 #endif // DOWNLOAD_PROGRESS_VIEW_H

Modified: webkit/trunk/WebKit/haiku/WebPositive/DownloadWindow.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/WebPositive/DownloadWindow.cpp    Wed Mar 24 
20:19:40 2010        (r351)
+++ webkit/trunk/WebKit/haiku/WebPositive/DownloadWindow.cpp    Wed Mar 24 
20:20:53 2010        (r352)
@@ -31,6 +31,7 @@
 
 #include <Alert.h>
 #include <Button.h>
+#include <ControlLook.h>
 #include <Entry.h>
 #include <File.h>
 #include <FindDirectory.h>
@@ -65,6 +66,7 @@
                :
                BGroupView(B_VERTICAL)
        {
+               SetFlags(Flags() | B_PULSE_NEEDED);
                SetViewColor(245, 245, 245);
                AddChild(BSpaceLayoutItem::CreateGlue());
        }
@@ -75,6 +77,11 @@
                return BSize(minSize.width, 80);
        }
 
+       virtual void Pulse()
+       {
+               DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse();
+       }
+
 protected:
        virtual void DoLayout()
        {
@@ -129,6 +136,8 @@
                B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
                B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | 
B_NOT_ZOOMABLE)
 {
+       SetPulseRate(1000000);
+
        settings->AddListener(BMessenger(this));
        BPath downloadPath;
        if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK)
@@ -159,15 +168,17 @@
                new BMessage(REMOVE_MISSING_DOWNLOADS));
        fRemoveMissingButton->SetEnabled(false);
 
+       const float spacing = be_control_look->DefaultItemSpacing();
+
        AddChild(BGroupLayoutBuilder(B_VERTICAL)
                .Add(menuBar)
                .Add(scrollView)
                .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
-               .Add(BGroupLayoutBuilder(B_HORIZONTAL)
+               .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
                        .AddGlue()
                        .Add(fRemoveMissingButton)
                        .Add(fRemoveFinishedButton)
-                       .SetInsets(5, 5, 5, 5)
+                       .SetInsets(12, 5, 12, 5)
                )
        );
 

Other related posts:

  • » [haiku-webkit-commits] r352 - in webkit/trunk/WebKit: . haiku/WebPositive - webkit