Author: stippi Date: 2010-01-17 19:40:25 +0100 (Sun, 17 Jan 2010) New Revision: 35129 Changeset: http://dev.haiku-os.org/changeset/35129/haiku Modified: haiku/trunk/src/kits/tracker/StatusWindow.cpp haiku/trunk/src/kits/tracker/StatusWindow.h Log: Implemented display of current size/total size copied and current copy speed. It will begin to play after a short time (10 seconds). Estimated finish time is still a TODO. Modified: haiku/trunk/src/kits/tracker/StatusWindow.cpp =================================================================== --- haiku/trunk/src/kits/tracker/StatusWindow.cpp 2010-01-17 18:39:05 UTC (rev 35128) +++ haiku/trunk/src/kits/tracker/StatusWindow.cpp 2010-01-17 18:40:25 UTC (rev 35129) @@ -55,7 +55,8 @@ const float kDefaultStatusViewHeight = 50; -const float kUpdateGrain = 100000; +const bigtime_t kMaxUpdateInterval = 100000LL; +const bigtime_t kSpeedReferenceInterval = 2000000LL; const BRect kStatusRect(200, 200, 550, 200); @@ -500,7 +501,15 @@ fWasCanceled = false; fIsPaused = false; fLastUpdateTime = 0; + fBytesPerSecond = 0.0; + for (size_t i = 0; i < kBytesPerSecondSlots; i++) + fBytesPerSecondSlot[i] = 0.0; + fCurrentBytesPerSecondSlot = 0; fItemSize = 0; + fSizeProcessed = 0; + + fProcessStartTime = fLastSpeedReferenceTime = system_time(); + fLastSpeedReferenceSize = 0; } @@ -559,6 +568,34 @@ } +static const char* +string_for_size(double size, char *string) +{ + double kb = size / 1024.0; + if (kb < 1.0) { + sprintf(string, "%d B", (int)size); + return string; + } + float mb = kb / 1024.0; + if (mb < 1.0) { + sprintf(string, "%3.1f KB", kb); + return string; + } + float gb = mb / 1024.0; + if (gb < 1.0) { + sprintf(string, "%3.1f MB", mb); + return string; + } + float tb = gb / 1024.0; + if (tb < 1.0) { + sprintf(string, "%3.1f GB", gb); + return string; + } + sprintf(string, "%.1f TB", tb); + return string; +} + + void BStatusView::Draw(BRect updateRect) { @@ -604,6 +641,42 @@ buffer << "To: " << fDestDir; SetHighColor(0, 0, 0); DrawString(buffer.String(), tp); + + // Draw speed info + float rightDivider = tp.x + StringWidth(buffer.String()) + 5.0f; + if (fBytesPerSecond != 0.0) { + SetHighColor(tint_color(LowColor(), B_DARKEN_4_TINT)); + + BFont font; + GetFont(&font); + float oldFontSize = font.Size(); + float fontSize = oldFontSize * 0.8f; + font.SetSize(max_c(8.0f, fontSize)); + SetFont(&font, B_FONT_SIZE); + + char sizeBuffer[128]; + buffer = "("; + buffer << string_for_size((double)fSizeProcessed, sizeBuffer); + buffer << " of "; + buffer << string_for_size((double)fTotalSize, sizeBuffer); + buffer << ", "; + buffer << string_for_size(fBytesPerSecond, sizeBuffer); + buffer << "/s)"; + tp.x = fStatusBar->Frame().right - StringWidth(buffer.String()); + if (tp.x > rightDivider) + DrawString(buffer.String(), tp); + else { + // complete string too wide, try with shorter version + buffer << string_for_size(fBytesPerSecond, sizeBuffer); + buffer << "/s"; + tp.x = fStatusBar->Frame().right - StringWidth(buffer.String()); + if (tp.x > rightDivider) + DrawString(buffer.String(), tp); + } + + font.SetSize(oldFontSize); + SetFont(&font, B_FONT_SIZE); + } } } @@ -623,6 +696,12 @@ case kPauseButton: fIsPaused = !fIsPaused; fPauseButton->SetValue(fIsPaused ? B_CONTROL_ON : B_CONTROL_OFF); + if (fBytesPerSecond != 0.0) { + fBytesPerSecond = 0.0; + for (size_t i = 0; i < kBytesPerSecondSlots; i++) + fBytesPerSecondSlot[i] = 0.0; + Invalidate(); + } if (!fIsPaused) { // force window update @@ -657,48 +736,72 @@ void BStatusView::UpdateStatus(const char *curItem, off_t itemSize, bool optional) { - float currentTime = system_time(); + if (!fShowCount) { + fStatusBar->Update((float)fItemSize / fTotalSize); + fItemSize = 0; + return; + } - if (fShowCount) { + if (curItem != NULL) + fCurItem++; - if (curItem) - fCurItem++; + fItemSize += itemSize; + fSizeProcessed += itemSize; - fItemSize += itemSize; + bigtime_t currentTime = system_time(); + if (!optional || ((currentTime - fLastUpdateTime) > kMaxUpdateInterval)) { + if (curItem != NULL || fPendingStatusString[0]) { + // forced update or past update time - if (!optional || ((currentTime - fLastUpdateTime) > kUpdateGrain)) { - if (curItem != NULL || fPendingStatusString[0]) { - // forced update or past update time + BString buffer; + buffer << fCurItem << " "; - BString buffer; - buffer << fCurItem << " "; + // if we don't have curItem, take the one from the stash + const char *statusItem = curItem != NULL + ? curItem : fPendingStatusString; - // if we don't have curItem, take the one from the stash - const char *statusItem = curItem != NULL - ? curItem : fPendingStatusString; + fStatusBar->Update((float)fItemSize / fTotalSize, statusItem, + buffer.String()); - fStatusBar->Update((float)fItemSize / fTotalSize, statusItem, - buffer.String()); + // we already displayed this item, clear the stash + fPendingStatusString[0] = '\0'; - // we already displayed this item, clear the stash - fPendingStatusString[0] = '\0'; + fLastUpdateTime = currentTime; + } else { + // don't have a file to show, just update the bar + fStatusBar->Update((float)fItemSize / fTotalSize); + } - fLastUpdateTime = currentTime; + if (currentTime + >= fLastSpeedReferenceTime + kSpeedReferenceInterval) { + // update current speed every kSpeedReferenceInterval + fCurrentBytesPerSecondSlot + = (fCurrentBytesPerSecondSlot + 1) % kBytesPerSecondSlots; + fBytesPerSecondSlot[fCurrentBytesPerSecondSlot] + = (double)(fSizeProcessed - fLastSpeedReferenceSize) + * 1000000LL / (currentTime - fLastSpeedReferenceTime); + fLastSpeedReferenceSize = fSizeProcessed; + fLastSpeedReferenceTime = currentTime; + fBytesPerSecond = 0.0; + for (size_t i = 0; i < kBytesPerSecondSlots; i++) { + if (fBytesPerSecondSlot[i] != 0.0) + fBytesPerSecond += fBytesPerSecondSlot[i]; + else { + fBytesPerSecond = 0.0; + break; + } } - else - // don't have a file to show, just update the bar - fStatusBar->Update((float)fItemSize / fTotalSize); + if (fBytesPerSecond != 0.0) + fBytesPerSecond /= kBytesPerSecondSlots; + Invalidate(); + } - fItemSize = 0; - } else if (curItem != NULL) { - // stash away the name of the item we are currently processing - // so we can show it when the time comes - strncpy(fPendingStatusString, curItem, 127); - fPendingStatusString[127] = '0'; - } - } else { - fStatusBar->Update((float)fItemSize / fTotalSize); fItemSize = 0; + } else if (curItem != NULL) { + // stash away the name of the item we are currently processing + // so we can show it when the time comes + strncpy(fPendingStatusString, curItem, 127); + fPendingStatusString[127] = '0'; } } Modified: haiku/trunk/src/kits/tracker/StatusWindow.h =================================================================== --- haiku/trunk/src/kits/tracker/StatusWindow.h 2010-01-17 18:39:05 UTC (rev 35128) +++ haiku/trunk/src/kits/tracker/StatusWindow.h 2010-01-17 18:40:25 UTC (rev 35129) @@ -132,13 +132,22 @@ BStatusBar* fStatusBar; off_t fTotalSize; off_t fItemSize; + off_t fSizeProcessed; + off_t fLastSpeedReferenceSize; int32 fCurItem; int32 fType; BBitmap* fBitmap; BButton* fStopButton; BButton* fPauseButton; thread_id fThread; - float fLastUpdateTime; + bigtime_t fLastUpdateTime; + bigtime_t fLastSpeedReferenceTime; + bigtime_t fProcessStartTime; + bigtime_t fLastSpeedUpdateTime; + static const size_t kBytesPerSecondSlots = 5; + size_t fCurrentBytesPerSecondSlot; + double fBytesPerSecondSlot[kBytesPerSecondSlots]; + double fBytesPerSecond; bool fShowCount; bool fWasCanceled; bool fIsPaused;