Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
operations (copying, deleting, etc.).
*/
#include <Application.h>
#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <Debug.h>
#include <DurationFormat.h>
#include <Locale.h>
#include <MessageFilter.h>
#include <StringView.h>
#include <String.h>
#include <TimeFormat.h>
#include <string.h>
#include "AutoLock.h"
#include "Bitmaps.h"
#include "Commands.h"
#include "StatusWindow.h"
#include "StringForSize.h"
#include "DeskWindow.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StatusWindow"
const float kDefaultStatusViewHeight = 50;
const bigtime_t kMaxUpdateInterval = 100000LL;
const bigtime_t kSpeedReferenceInterval = 2000000LL;
const bigtime_t kShowSpeedInterval = 8000000LL;
const bigtime_t kShowEstimatedFinishInterval = 4000000LL;
const BRect kStatusRect(200, 200, 550, 200);
static bigtime_t sLastEstimatedFinishSpeedToggleTime = -1;
static bool sShowSpeed = true;
static const time_t kSecondsPerDay = 24 * 60 * 60;
class TCustomButton : public BButton {
public:
TCustomButton(BRect frame, uint32 command);
virtual void Draw(BRect updateRect);
private:
typedef BButton _inherited;
};
class BStatusMouseFilter : public BMessageFilter {
public:
BStatusMouseFilter();
virtual filter_result Filter(BMessage* message, BHandler** target);
};
namespace BPrivate {
BStatusWindow* gStatusWindow = NULL;
}
BStatusMouseFilter::BStatusMouseFilter()
:
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, B_MOUSE_DOWN)
{
}
filter_result
BStatusMouseFilter::Filter(BMessage* message, BHandler** target)
{
if ((*target)->Name() != NULL
&& strcmp((*target)->Name(), "StatusBar") == 0) {
BView* view = dynamic_cast<BView*>(*target);
if (view != NULL)
view = view->Parent();
if (view != NULL)
*target = view;
}
return B_DISPATCH_MESSAGE;
}
TCustomButton::TCustomButton(BRect frame, uint32 what)
:
BButton(frame, "", "", new BMessage(what), B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW)
{
}
void
TCustomButton::Draw(BRect updateRect)
{
_inherited::Draw(updateRect);
if (Message()->what == kStopButton) {
updateRect = Bounds();
updateRect.InsetBy(9, 8);
SetHighColor(0, 0, 0);
if (Value() == B_CONTROL_ON)
updateRect.OffsetBy(1, 1);
FillRect(updateRect);
} else {
updateRect = Bounds();
updateRect.InsetBy(9, 7);
BRect rect(updateRect);
rect.right -= 3;
updateRect.left += 3;
updateRect.OffsetBy(1, 0);
SetHighColor(0, 0, 0);
if (Value() == B_CONTROL_ON) {
updateRect.OffsetBy(1, 1);
rect.OffsetBy(1, 1);
}
FillRect(updateRect);
FillRect(rect);
}
}
class StatusBackgroundView : public BView {
public:
StatusBackgroundView(BRect frame)
:
BView(frame, "BackView", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED)
{
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
}
virtual void Pulse()
{
bigtime_t now = system_time();
if (sShowSpeed
&& sLastEstimatedFinishSpeedToggleTime + kShowSpeedInterval
<= now) {
sShowSpeed = false;
sLastEstimatedFinishSpeedToggleTime = now;
} else if (!sShowSpeed
&& sLastEstimatedFinishSpeedToggleTime
+ kShowEstimatedFinishInterval <= now) {
sShowSpeed = true;
sLastEstimatedFinishSpeedToggleTime = now;
}
}
};
BStatusWindow::BStatusWindow()
:
BWindow(kStatusRect, B_TRANSLATE("Tracker status"), B_TITLED_WINDOW,
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES),
fRetainDesktopFocus(false)
{
SetSizeLimits(0, 100000, 0, 100000);
fMouseDownFilter = new BStatusMouseFilter();
AddCommonFilter(fMouseDownFilter);
BView* view = new StatusBackgroundView(Bounds());
AddChild(view);
SetPulseRate(1000000);
Hide();
Show();
}
BStatusWindow::~BStatusWindow()
{
}
void
BStatusWindow::CreateStatusItem(thread_id thread, StatusWindowState type)
{
AutoLock<BWindow> lock(this);
BRect rect(Bounds());
if (BStatusView* lastView = fViewList.LastItem())
rect.top = lastView->Frame().bottom + 1;
else {
sShowSpeed = true;
sLastEstimatedFinishSpeedToggleTime = system_time();
}
rect.bottom = rect.top + kDefaultStatusViewHeight - 1;
BStatusView* view = new BStatusView(rect, thread, type);
ChildAt(0)->AddChild(view);
fViewList.AddItem(view);
ResizeTo(Bounds().Width(), view->Frame().bottom);
bool desktopActive = false;
{
AutoLock<BLooper> lock(be_app);
int32 count = be_app->CountWindows();
for (int32 index = 0; index < count; index++) {
BWindow* window = be_app->WindowAt(index);
if (dynamic_cast<BDeskWindow*>(window) != NULL
&& window->IsActive()) {
desktopActive = true;
break;
}
}
}
if (IsHidden()) {
fRetainDesktopFocus = desktopActive;
Minimize(false);
Show();
} else
fRetainDesktopFocus &= desktopActive;
}
void
BStatusWindow::InitStatusItem(thread_id thread, int32 totalItems,
off_t totalSize, const entry_ref* destDir, bool showCount)
{
AutoLock<BWindow> lock(this);
int32 numItems = fViewList.CountItems();
for (int32 index = 0; index < numItems; index++) {
BStatusView* view = fViewList.ItemAt(index);
if (view->Thread() == thread) {
view->InitStatus(totalItems, totalSize, destDir, showCount);
break;
}
}
}
void
BStatusWindow::UpdateStatus(thread_id thread, const char* curItem,
off_t itemSize, bool optional)
{
AutoLock<BWindow> lock(this);
int32 numItems = fViewList.CountItems();
for (int32 index = 0; index < numItems; index++) {
BStatusView* view = fViewList.ItemAt(index);
if (view->Thread() == thread) {
view->UpdateStatus(curItem, itemSize, optional);
break;
}
}
}
void
BStatusWindow::RemoveStatusItem(thread_id thread)
{
AutoLock<BWindow> lock(this);
BStatusView* winner = NULL;
int32 numItems = fViewList.CountItems();
int32 index;
for (index = 0; index < numItems; index++) {
BStatusView* view = fViewList.ItemAt(index);
if (view->Thread() == thread) {
winner = view;
break;
}
}
if (winner != NULL) {
float height = winner->Bounds().Height() + 1;
fViewList.RemoveItem(winner);
winner->RemoveSelf();
delete winner;
if (--numItems == 0 && !IsHidden()) {
BDeskWindow* desktop = NULL;
if (fRetainDesktopFocus) {
AutoLock<BLooper> lock(be_app);
int32 count = be_app->CountWindows();
for (int32 index = 0; index < count; index++) {
desktop = dynamic_cast<BDeskWindow*>(
be_app->WindowAt(index));
if (desktop != NULL)
break;
}
}
Hide();
if (desktop != NULL) {
desktop->Activate();
}
}
for (; index < numItems; index++)
fViewList.ItemAt(index)->MoveBy(0, -height);
ResizeTo(Bounds().Width(), Bounds().Height() - height);
}
}
bool
BStatusWindow::CheckCanceledOrPaused(thread_id thread)
{
bool wasCanceled = false;
bool isPaused = false;
BStatusView* view = NULL;
AutoLock<BWindow> lock(this);
for (int32 index = fViewList.CountItems() - 1; index >= 0; index--) {
view = fViewList.ItemAt(index);
if (view && view->Thread() == thread) {
isPaused = view->IsPaused();
wasCanceled = view->WasCanceled();
break;
}
}
if (wasCanceled || !isPaused)
return wasCanceled;
if (isPaused && view != NULL) {
view->Invalidate();
thread_id thread = view->Thread();
lock.Unlock();
ASSERT(find_thread(NULL) == thread);
suspend_thread(thread);
}
return wasCanceled;
}
bool
BStatusWindow::AttemptToQuit()
{
int32 count = fViewList.CountItems();
if (count == 0)
return true;
for (int32 index = 0; index < count; index++)
fViewList.ItemAt(index)->SetWasCanceled();
return false;
}
void
BStatusWindow::WindowActivated(bool state)
{
if (!state)
fRetainDesktopFocus = false;
return _inherited::WindowActivated(state);
}
BStatusView::BStatusView(BRect bounds, thread_id thread, StatusWindowState type)
:
BView(bounds, "StatusView", B_FOLLOW_NONE, B_WILL_DRAW),
fStatusBar(NULL),
fType(type),
fBitmap(NULL),
fStopButton(NULL),
fPauseButton(NULL),
fThread(thread)
{
Init();
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
SetLowUIColor(ViewUIColor());
SetHighColor(20, 20, 20);
SetDrawingMode(B_OP_ALPHA);
const float buttonWidth = 22;
const float buttonHeight = 20;
BRect rect(bounds);
rect.OffsetTo(B_ORIGIN);
rect.left += 40;
rect.right -= buttonWidth * 2 + 12;
rect.top += 6;
rect.bottom = rect.top + 15;
BString caption;
int32 id = 0;
switch (type) {
case kCopyState:
caption = B_TRANSLATE("Preparing to copy items" B_UTF8_ELLIPSIS);
id = R_CopyStatusIcon;
break;
case kMoveState:
caption = B_TRANSLATE("Preparing to move items" B_UTF8_ELLIPSIS);
id = R_MoveStatusIcon;
break;
case kCreateLinkState:
caption = B_TRANSLATE("Preparing to create links"
B_UTF8_ELLIPSIS);
id = R_MoveStatusIcon;
break;
case kTrashState:
caption = B_TRANSLATE("Preparing to empty Trash" B_UTF8_ELLIPSIS);
id = R_TrashIcon;
break;
case kVolumeState:
caption = B_TRANSLATE("Searching for disks to mount"
B_UTF8_ELLIPSIS);
break;
case kDeleteState:
caption = B_TRANSLATE("Preparing to delete items"
B_UTF8_ELLIPSIS);
id = R_TrashIcon;
break;
case kRestoreFromTrashState:
caption = B_TRANSLATE("Preparing to restore items"
B_UTF8_ELLIPSIS);
break;
default:
TRESPASS();
break;
}
if (caption.Length() != 0) {
fStatusBar = new BStatusBar(rect, "StatusBar", caption.String());
fStatusBar->SetBarHeight(12);
float width, height;
fStatusBar->GetPreferredSize(&width, &height);
fStatusBar->ResizeTo(fStatusBar->Frame().Width(), height);
AddChild(fStatusBar);
font_height fh;
GetFontHeight(&fh);
BRect f = fStatusBar->Frame();
ResizeTo(Bounds().Width(), f.top + f.Height() + fh.leading + fh.ascent
+ fh.descent + f.top);
}
if (id != 0) {
fBitmap = new BBitmap(BRect(0, 0, 16, 16), B_RGBA32);
GetTrackerResources()->GetIconResource(id, B_MINI_ICON,
fBitmap);
}
rect = Bounds();
rect.left = rect.right - buttonWidth * 2 - 7;
rect.right = rect.left + buttonWidth;
rect.top = floorf((rect.top + rect.bottom) / 2 + 0.5) - buttonHeight / 2;
rect.bottom = rect.top + buttonHeight;
fPauseButton = new TCustomButton(rect, kPauseButton);
fPauseButton->ResizeTo(buttonWidth, buttonHeight);
AddChild(fPauseButton);
rect.OffsetBy(buttonWidth + 2, 0);
fStopButton = new TCustomButton(rect, kStopButton);
fStopButton->ResizeTo(buttonWidth, buttonHeight);
AddChild(fStopButton);
}
BStatusView::~BStatusView()
{
delete fBitmap;
}
void
BStatusView::Init()
{
fTotalSize = fItemSize = fSizeProcessed = fLastSpeedReferenceSize
= fEstimatedFinishReferenceSize = 0;
fCurItem = 0;
fLastUpdateTime = fLastSpeedReferenceTime = fProcessStartTime
= fLastSpeedUpdateTime = fEstimatedFinishReferenceTime
= system_time();
fCurrentBytesPerSecondSlot = 0;
for (size_t i = 0; i < kBytesPerSecondSlots; i++)
fBytesPerSecondSlot[i] = 0.0;
fBytesPerSecond = 0.0;
fShowCount = fWasCanceled = fIsPaused = false;
fDestDir.SetTo("");
fPendingStatusString[0] = '\0';
}
void
BStatusView::InitStatus(int32 totalItems, off_t totalSize,
const entry_ref* destDir, bool showCount)
{
Init();
fTotalSize = totalSize;
fShowCount = showCount;
BEntry entry;
char name[B_FILE_NAME_LENGTH];
if (destDir != NULL && entry.SetTo(destDir) == B_OK) {
entry.GetName(name);
fDestDir.SetTo(name);
}
BString buffer;
if (totalItems > 0) {
char totalStr[32];
buffer.SetTo(B_TRANSLATE("of %items"));
snprintf(totalStr, sizeof(totalStr), "%" B_PRId32, totalItems);
buffer.ReplaceFirst("%items", totalStr);
}
switch (fType) {
case kCopyState:
fStatusBar->Reset(B_TRANSLATE("Copying: "), buffer.String());
break;
case kCreateLinkState:
fStatusBar->Reset(B_TRANSLATE("Creating links: "),
buffer.String());
break;
case kMoveState:
fStatusBar->Reset(B_TRANSLATE("Moving: "), buffer.String());
break;
case kTrashState:
fStatusBar->Reset(
B_TRANSLATE("Emptying Trash" B_UTF8_ELLIPSIS " "),
buffer.String());
break;
case kDeleteState:
fStatusBar->Reset(B_TRANSLATE("Deleting: "), buffer.String());
break;
case kRestoreFromTrashState:
fStatusBar->Reset(B_TRANSLATE("Restoring: "), buffer.String());
break;
}
fStatusBar->SetMaxValue(1);
Invalidate();
}
void
BStatusView::Draw(BRect updateRect)
{
if (fBitmap != NULL) {
BPoint location;
location.x = (fStatusBar->Frame().left
- fBitmap->Bounds().Width()) / 2;
location.y = (Bounds().Height()- fBitmap->Bounds().Height()) / 2;
DrawBitmap(fBitmap, location);
}
BRect bounds(Bounds());
be_control_look->DrawRaisedBorder(this, bounds, updateRect, ViewColor());
SetHighUIColor(B_PANEL_TEXT_COLOR);
BPoint tp = fStatusBar->Frame().LeftBottom();
font_height fh;
GetFontHeight(&fh);
tp.y += ceilf(fh.leading) + ceilf(fh.ascent);
if (IsPaused()) {
DrawString(B_TRANSLATE("Paused: click to resume or stop"), tp);
return;
}
BFont font;
GetFont(&font);
float normalFontSize = font.Size();
float smallFontSize = max_c(normalFontSize * 0.8f, 8.0f);
float availableSpace = fStatusBar->Frame().Width();
availableSpace -= be_control_look->DefaultLabelSpacing();
float destinationStringWidth = 0.f;
BString destinationString(_DestinationString(&destinationStringWidth));
availableSpace -= destinationStringWidth;
float statusStringWidth = 0.f;
BString statusString(_StatusString(availableSpace, smallFontSize,
&statusStringWidth));
if (statusStringWidth > availableSpace) {
TruncateString(&destinationString, B_TRUNCATE_MIDDLE,
availableSpace + destinationStringWidth - statusStringWidth);
}
BPoint textPoint = fStatusBar->Frame().LeftBottom();
textPoint.y += ceilf(fh.leading) + ceilf(fh.ascent);
if (destinationStringWidth > 0) {
DrawString(destinationString.String(), textPoint);
}
if (LowColor().IsLight())
SetHighColor(tint_color(LowColor(), B_DARKEN_4_TINT));
else
SetHighColor(tint_color(LowColor(), B_LIGHTEN_2_TINT));
font.SetSize(smallFontSize);
SetFont(&font, B_FONT_SIZE);
textPoint.x = fStatusBar->Frame().right - statusStringWidth;
DrawString(statusString.String(), textPoint);
font.SetSize(normalFontSize);
SetFont(&font, B_FONT_SIZE);
}
BString
BStatusView::_DestinationString(float* _width)
{
if (fDestDir.Length() > 0) {
BString buffer(B_TRANSLATE("To: %dir"));
buffer.ReplaceFirst("%dir", fDestDir);
*_width = ceilf(StringWidth(buffer.String()));
return buffer;
} else {
*_width = 0;
return BString();
}
}
BString
BStatusView::_StatusString(float availableSpace, float fontSize,
float* _width)
{
BFont font;
GetFont(&font);
float oldSize = font.Size();
font.SetSize(fontSize);
SetFont(&font, B_FONT_SIZE);
BString status;
if (sShowSpeed) {
status = _SpeedStatusString(availableSpace, _width);
} else
status = _TimeStatusString(availableSpace, _width);
font.SetSize(oldSize);
SetFont(&font, B_FONT_SIZE);
return status;
}
BString
BStatusView::_SpeedStatusString(float availableSpace, float* _width)
{
BString string(_FullSpeedString());
*_width = StringWidth(string.String());
if (*_width > availableSpace) {
string.SetTo(_ShortSpeedString());
*_width = StringWidth(string.String());
}
*_width = ceilf(*_width);
return string;
}
BString
BStatusView::_FullSpeedString()
{
BString buffer;
if (fBytesPerSecond != 0.0) {
char sizeBuffer[128];
buffer.SetTo(B_TRANSLATE(
"%SizeProcessed of %TotalSize, %BytesPerSecond/s"));
buffer.ReplaceFirst("%SizeProcessed",
string_for_size((double)fSizeProcessed, sizeBuffer,
sizeof(sizeBuffer)));
buffer.ReplaceFirst("%TotalSize",
string_for_size((double)fTotalSize, sizeBuffer,
sizeof(sizeBuffer)));
buffer.ReplaceFirst("%BytesPerSecond",
string_for_size(fBytesPerSecond, sizeBuffer, sizeof(sizeBuffer)));
}
return buffer;
}
BString
BStatusView::_ShortSpeedString()
{
BString buffer;
if (fBytesPerSecond != 0.0) {
char sizeBuffer[128];
buffer << B_TRANSLATE("%BytesPerSecond/s");
buffer.ReplaceFirst("%BytesPerSecond",
string_for_size(fBytesPerSecond, sizeBuffer, sizeof(sizeBuffer)));
}
return buffer;
}
BString
BStatusView::_TimeStatusString(float availableSpace, float* _width)
{
double totalBytesPerSecond = (double)(fSizeProcessed
- fEstimatedFinishReferenceSize)
* 1000000LL / (system_time() - fEstimatedFinishReferenceTime);
double secondsRemaining = (fTotalSize - fSizeProcessed)
/ totalBytesPerSecond;
time_t now = (time_t)real_time_clock();
BString string;
if (secondsRemaining < 0 || (sizeof(time_t) == 4
&& now + secondsRemaining > INT32_MAX)) {
string = B_TRANSLATE("Finish: after several years");
} else {
char timeText[32];
time_t finishTime = (time_t)(now + secondsRemaining);
if (finishTime - now > kSecondsPerDay) {
BDateTimeFormat().Format(timeText, sizeof(timeText), finishTime,
B_MEDIUM_DATE_FORMAT, B_MEDIUM_TIME_FORMAT);
} else {
BTimeFormat().Format(timeText, sizeof(timeText), finishTime,
B_MEDIUM_TIME_FORMAT);
}
string = _FullTimeRemainingString(now, finishTime, timeText);
float width = StringWidth(string.String());
if (width > availableSpace) {
string.SetTo(_ShortTimeRemainingString(timeText));
}
}
if (_width != NULL)
*_width = StringWidth(string.String());
return string;
}
BString
BStatusView::_ShortTimeRemainingString(const char* timeText)
{
BString buffer;
buffer.SetTo(B_TRANSLATE("Finish: %time"));
buffer.ReplaceFirst("%time", timeText);
return buffer;
}
BString
BStatusView::_FullTimeRemainingString(time_t now, time_t finishTime,
const char* timeText)
{
BDurationFormat formatter;
BString buffer;
BString finishStr;
if (finishTime - now > 60 * 60) {
buffer.SetTo(B_TRANSLATE("Finish: %time - Over %finishtime left"));
formatter.Format(finishStr, now * 1000000LL, finishTime * 1000000LL);
} else {
buffer.SetTo(B_TRANSLATE("Finish: %time - %finishtime left"));
formatter.Format(finishStr, now * 1000000LL, finishTime * 1000000LL);
}
buffer.ReplaceFirst("%time", timeText);
buffer.ReplaceFirst("%finishtime", finishStr);
return buffer;
}
void
BStatusView::AttachedToWindow()
{
fPauseButton->SetTarget(this);
fStopButton->SetTarget(this);
}
void
BStatusView::MessageReceived(BMessage* message)
{
switch (message->what) {
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) {
fEstimatedFinishReferenceTime = system_time();
fEstimatedFinishReferenceSize = fSizeProcessed;
Invalidate();
resume_thread(Thread());
}
break;
case kStopButton:
fWasCanceled = true;
if (fIsPaused) {
fIsPaused = false;
Invalidate();
resume_thread(Thread());
}
break;
default:
_inherited::MessageReceived(message);
break;
}
}
void
BStatusView::UpdateStatus(const char* curItem, off_t itemSize, bool optional)
{
if (!fShowCount) {
fStatusBar->Update((float)fItemSize / fTotalSize);
fItemSize = 0;
return;
}
if (curItem != NULL)
fCurItem++;
fItemSize += itemSize;
fSizeProcessed += itemSize;
bigtime_t currentTime = system_time();
if (!optional || ((currentTime - fLastUpdateTime) > kMaxUpdateInterval)) {
if (curItem != NULL || fPendingStatusString[0]) {
BString buffer;
buffer << fCurItem << " ";
const char* statusItem = curItem != NULL
? curItem : fPendingStatusString;
fStatusBar->Update((float)fItemSize / fTotalSize, statusItem,
buffer.String());
fPendingStatusString[0] = '\0';
fLastUpdateTime = currentTime;
} else {
fStatusBar->Update((float)fItemSize / fTotalSize);
}
if (currentTime
>= fLastSpeedReferenceTime + kSpeedReferenceInterval) {
fCurrentBytesPerSecondSlot
= (fCurrentBytesPerSecondSlot + 1) % kBytesPerSecondSlots;
fBytesPerSecondSlot[fCurrentBytesPerSecondSlot]
= (double)(fSizeProcessed - fLastSpeedReferenceSize)
* 1000000LL / (currentTime - fLastSpeedReferenceTime);
fLastSpeedReferenceSize = fSizeProcessed;
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;
BString toolTip = _TimeStatusString(1024.f, NULL);
toolTip << "\n" << _FullSpeedString();
SetToolTip(toolTip.String());
Invalidate();
}
fItemSize = 0;
} else if (curItem != NULL) {
strncpy(fPendingStatusString, curItem, 127);
fPendingStatusString[127] = '0';
} else
SetToolTip((const char*)NULL);
}
void
BStatusView::SetWasCanceled()
{
fWasCanceled = true;
}