From 3e52a3d5e5479a4de086a481f3363765149fbd4e Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Wed, 14 Nov 2012 22:31:21 -0500 Subject: [PATCH] DiskUsage: added ability to cancel an ongoing scan. fixes #6801. Also, progress now goes from 0.0 to 1.0 rather than from 0.00 to 100.00 (to avoid a * 100, followed by a / 100) --- src/apps/diskusage/ControlsView.cpp | 14 ++++++++-- src/apps/diskusage/ControlsView.h | 3 ++- src/apps/diskusage/DiskUsage.h | 3 ++- src/apps/diskusage/MainWindow.cpp | 14 +++++++--- src/apps/diskusage/MainWindow.h | 3 ++- src/apps/diskusage/PieView.cpp | 22 +++++++--------- src/apps/diskusage/Scanner.cpp | 41 +++++++++++++++++++++++------ src/apps/diskusage/Scanner.h | 5 +++- src/apps/diskusage/StatusView.cpp | 10 ++++--- src/apps/diskusage/StatusView.h | 4 +-- src/apps/diskusage/VolumeView.cpp | 15 ++++++++--- src/apps/diskusage/VolumeView.h | 3 ++- 12 files changed, 96 insertions(+), 41 deletions(-) diff --git a/src/apps/diskusage/ControlsView.cpp b/src/apps/diskusage/ControlsView.cpp index 4cce24108a..dcb1c00d81 100644 --- a/src/apps/diskusage/ControlsView.cpp +++ b/src/apps/diskusage/ControlsView.cpp @@ -248,6 +248,7 @@ ControlsView::VolumeTabView::MessageReceived(BMessage* message) } break; + case kBtnCancel: case kBtnRescan: ViewForTab(Selection())->MessageReceived(message); break; @@ -361,6 +362,7 @@ ControlsView::MessageReceived(BMessage* msg) fVolumeTabView->MessageReceived(msg); break; + case kBtnCancel: case kBtnRescan: fVolumeTabView->MessageReceived(msg); break; @@ -385,10 +387,18 @@ ControlsView::ShowInfo(const FileInfo* info) void -ControlsView::SetRescanEnabled(bool enabled) +ControlsView::EnableRescan() { ((VolumeView*)fVolumeTabView->ViewForTab( - fVolumeTabView->Selection()))->SetRescanEnabled(enabled); + fVolumeTabView->Selection()))->EnableRescan(); +} + + +void +ControlsView::EnableCancel() +{ + ((VolumeView*)fVolumeTabView->ViewForTab( + fVolumeTabView->Selection()))->EnableCancel(); } diff --git a/src/apps/diskusage/ControlsView.h b/src/apps/diskusage/ControlsView.h index 1e13dcdfc3..cd7217558a 100644 --- a/src/apps/diskusage/ControlsView.h +++ b/src/apps/diskusage/ControlsView.h @@ -28,7 +28,8 @@ public: BVolume* FindDeviceFor(dev_t device, bool invoke = false); - void SetRescanEnabled(bool enabled); + void EnableRescan(); + void EnableCancel(); void ShowInfo(const FileInfo* info); private: diff --git a/src/apps/diskusage/DiskUsage.h b/src/apps/diskusage/DiskUsage.h index 77330fccc6..4766cae45f 100644 --- a/src/apps/diskusage/DiskUsage.h +++ b/src/apps/diskusage/DiskUsage.h @@ -42,7 +42,7 @@ const float kMinButtonWidth = 60.0; const float kProgBarWidth = 150.0; const float kProgBarHeight = 16.0; -const float kReportInterval = 2.5; +const float kReportInterval = 0.0025; const float kDefaultPieSize = 400.0; const float kPieCenterSize = 80.0; @@ -57,6 +57,7 @@ extern bool helpFileWasFound; #define kMenuSelectVol 'gMSV' #define kBtnRescan 'gBRF' +#define kBtnCancel 'gCAN' #define kBtnHelp 'gHLP' #define kScanRefresh 'gSRF' #define kScanProgress 'gSPR' diff --git a/src/apps/diskusage/MainWindow.cpp b/src/apps/diskusage/MainWindow.cpp index c540ca56ff..f5775b2fe8 100644 --- a/src/apps/diskusage/MainWindow.cpp +++ b/src/apps/diskusage/MainWindow.cpp @@ -51,9 +51,8 @@ void MainWindow::MessageReceived(BMessage* message) { switch (message->what) { + case kBtnCancel: case kBtnRescan: - fControlsView->MessageReceived(message); - break; case B_SIMPLE_DATA: case B_REFS_RECEIVED: fControlsView->MessageReceived(message); @@ -83,9 +82,16 @@ MainWindow::QuitRequested() void -MainWindow::SetRescanEnabled(bool enabled) +MainWindow::EnableRescan() { - fControlsView->SetRescanEnabled(enabled); + fControlsView->EnableRescan(); +} + + +void +MainWindow::EnableCancel() +{ + fControlsView->EnableCancel(); } diff --git a/src/apps/diskusage/MainWindow.h b/src/apps/diskusage/MainWindow.h index 638354d4e1..d639337450 100644 --- a/src/apps/diskusage/MainWindow.h +++ b/src/apps/diskusage/MainWindow.h @@ -26,7 +26,8 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); - void SetRescanEnabled(bool enabled); + void EnableRescan(); + void EnableCancel(); BVolume* FindDeviceFor(dev_t device, bool invoke = false); diff --git a/src/apps/diskusage/PieView.cpp b/src/apps/diskusage/PieView.cpp index 9a3526096f..a1d8f4a4b0 100644 --- a/src/apps/diskusage/PieView.cpp +++ b/src/apps/diskusage/PieView.cpp @@ -181,23 +181,26 @@ void PieView::MessageReceived(BMessage* message) { switch (message->what) { + case kBtnCancel: + if (fScanner != NULL) + fScanner->Cancel(); + break; case kBtnRescan: if (fVolume != NULL) { if (fScanner != NULL) fScanner->Refresh(); else _ShowVolume(fVolume); - + fWindow->EnableCancel(); Invalidate(); } break; - - case kScanProgress: + case kScanDone: - { + fWindow->EnableRescan(); + case kScanProgress: Invalidate(); break; - } default: BView::MessageReceived(message); @@ -300,12 +303,8 @@ PieView::Draw(BRect updateRect) if (fScanner->IsBusy()) { // Show progress of scanning. _DrawProgressBar(updateRect); - if (fWindow != NULL) - fWindow->SetRescanEnabled(false); - } else { + } else if (fScanner->Snapshot() != NULL) { _DrawPieChart(updateRect); - if (fWindow != NULL) - fWindow->SetRescanEnabled(true); if (fUpdateFileAt) { fWindow->ShowInfo(_FileAt(fLastWhere)); fUpdateFileAt = false; @@ -362,8 +361,7 @@ PieView::_DrawProgressBar(BRect updateRect) float by = floorf((b.top + b.Height() - kProgBarHeight) / 2.0); float ex = bx + kProgBarWidth; float ey = by + kProgBarHeight; - float mx = bx + floorf((kProgBarWidth - 2.0) - * fScanner->Progress() / 100.0 + 0.5); + float mx = bx + floorf((kProgBarWidth - 2.0) * fScanner->Progress() + 0.5); const rgb_color kBarColor = {50, 150, 255, 255}; BRect barFrame(bx, by, ex, ey); diff --git a/src/apps/diskusage/Scanner.cpp b/src/apps/diskusage/Scanner.cpp index 59384e2235..6307d1f052 100644 --- a/src/apps/diskusage/Scanner.cpp +++ b/src/apps/diskusage/Scanner.cpp @@ -35,7 +35,8 @@ Scanner::Scanner(BVolume *v, BHandler *handler) fDesiredPath(), fTask(), fBusy(false), - fQuitRequested(false) + fQuitRequested(false), + fPreviousSnapshot(NULL) { Run(); } @@ -88,6 +89,16 @@ Scanner::Refresh(FileInfo* startInfo) } +void +Scanner::Cancel() +{ + if (!fBusy) + return; + + fQuitRequested = true; +} + + void Scanner::SetDesiredPath(string &path) { @@ -133,22 +144,29 @@ Scanner::_DirectoryContains(FileInfo* currentDir, entry_ref* ref) void Scanner::_RunScan(FileInfo* startInfo) { + fPreviousSnapshot = fSnapshot; + fQuitRequested = false; BString stringScan(B_TRANSLATE("Scanning %refName%")); if (startInfo == NULL || startInfo == fSnapshot->rootDir) { - delete fSnapshot; fSnapshot = new VolumeSnapshot(fVolume); stringScan.ReplaceFirst("%refName%", fSnapshot->name.c_str()); fTask = stringScan.String(); fVolumeBytesInUse = fSnapshot->capacity - fSnapshot->freeBytes; fVolumeBytesScanned = 0; fProgress = 0.0; - fLastReport = -100.0; + fLastReport = -1.0; BDirectory root; fVolume->GetRootDirectory(&root); fSnapshot->rootDir = _GetFileInfo(&root, NULL); - + if (fSnapshot->rootDir == NULL) { + delete fSnapshot; + fSnapshot = fPreviousSnapshot; + fBusy = false; + fListener.SendMessage(&fDoneMessage); + return; + } FileInfo* freeSpace = new FileInfo; freeSpace->pseudo = true; BString string(B_TRANSLATE("Free on %refName%")); @@ -166,14 +184,21 @@ Scanner::_RunScan(FileInfo* startInfo) fTask = stringScan.String(); fVolumeBytesInUse = fSnapshot->capacity - fSnapshot->freeBytes; fVolumeBytesScanned = fVolumeBytesInUse - startInfo->size; //best guess - fProgress = 100.0 * fVolumeBytesScanned / fVolumeBytesInUse; - fLastReport = -100.0; + fProgress = fVolumeBytesScanned / fVolumeBytesInUse; + fLastReport = -1.0; BDirectory startDir(&startInfo->ref); if (startDir.InitCheck() == B_OK) { FileInfo *parent = startInfo->parent; vector::iterator i = parent->children.begin(); FileInfo* newInfo = _GetFileInfo(&startDir, parent); + if (newInfo == NULL) { + delete fSnapshot; + fSnapshot = fPreviousSnapshot; + fBusy = false; + fListener.SendMessage(&fDoneMessage); + return; + } while (i != parent->children.end() && *i != startInfo) i++; @@ -206,7 +231,7 @@ Scanner::_GetFileInfo(BDirectory* dir, FileInfo* parent) while (true) { if (fQuitRequested) - break; + return NULL; if (dir->GetNextEntry(&entry) == B_ENTRY_NOT_FOUND) break; @@ -223,7 +248,7 @@ Scanner::_GetFileInfo(BDirectory* dir, FileInfo* parent) // Send a progress report periodically. fVolumeBytesScanned += child->size; - fProgress = 100.0 * fVolumeBytesScanned / fVolumeBytesInUse; + fProgress = (float)fVolumeBytesScanned / fVolumeBytesInUse; if (fProgress - fLastReport > kReportInterval) { fLastReport = fProgress; fListener.SendMessage(&fProgressMessage); diff --git a/src/apps/diskusage/Scanner.h b/src/apps/diskusage/Scanner.h index 57904b0f28..db0cd7a395 100644 --- a/src/apps/diskusage/Scanner.h +++ b/src/apps/diskusage/Scanner.h @@ -35,12 +35,13 @@ public: VolumeSnapshot* Snapshot() const { return fBusy ? NULL : fSnapshot; } void Refresh(FileInfo* startInfo = NULL); + void Cancel(); bool IsBusy() const { return fBusy; } const char* Task() const { return fTask.c_str(); } float Progress() const - { return min_c(100.0, fProgress); } + { return min_c(1.0, fProgress); } FileInfo* CurrentDir() const { return fBusy ? NULL : fSnapshot->currentDir; } void ChangeDir(FileInfo* info) @@ -71,6 +72,8 @@ private: string fTask; bool fBusy; bool fQuitRequested; + + VolumeSnapshot* fPreviousSnapshot; }; #endif // SCANNER_H diff --git a/src/apps/diskusage/StatusView.cpp b/src/apps/diskusage/StatusView.cpp index 7584c310cd..ced47a9de0 100644 --- a/src/apps/diskusage/StatusView.cpp +++ b/src/apps/diskusage/StatusView.cpp @@ -97,16 +97,18 @@ StatusView::~StatusView() void -StatusView::SetRescanEnabled(bool enabled) +StatusView::EnableRescan() { - fRefreshBtn->SetEnabled(enabled); + fRefreshBtn->SetLabel(B_TRANSLATE("Rescan")); + fRefreshBtn->SetMessage(new BMessage(kBtnRescan)); } void -StatusView::SetBtnLabel(const char* label) +StatusView::EnableCancel() { - fRefreshBtn->SetLabel(label); + fRefreshBtn->SetLabel(B_TRANSLATE("Abort")); + fRefreshBtn->SetMessage(new BMessage(kBtnCancel)); } diff --git a/src/apps/diskusage/StatusView.h b/src/apps/diskusage/StatusView.h index 97051dac82..1a3596356e 100644 --- a/src/apps/diskusage/StatusView.h +++ b/src/apps/diskusage/StatusView.h @@ -24,8 +24,8 @@ public: virtual ~StatusView(); void ShowInfo(const FileInfo* info); - void SetBtnLabel(const char* label); - void SetRescanEnabled(bool enabled); + void EnableRescan(); + void EnableCancel(); private: BStringView* fPathView; diff --git a/src/apps/diskusage/VolumeView.cpp b/src/apps/diskusage/VolumeView.cpp index ead2c074fd..06c1398715 100644 --- a/src/apps/diskusage/VolumeView.cpp +++ b/src/apps/diskusage/VolumeView.cpp @@ -52,9 +52,16 @@ VolumeView::~VolumeView() void -VolumeView::SetRescanEnabled(bool enabled) +VolumeView::EnableRescan() { - fStatusView->SetRescanEnabled(enabled); + fStatusView->EnableRescan(); +} + + +void +VolumeView::EnableCancel() +{ + fStatusView->EnableCancel(); } @@ -62,7 +69,7 @@ void VolumeView::SetPath(BPath path) { fPieView->SetPath(path); - fStatusView->SetBtnLabel(B_TRANSLATE("Rescan")); + EnableRescan(); } @@ -70,9 +77,9 @@ void VolumeView::MessageReceived(BMessage* msg) { switch(msg->what) { + case kBtnCancel: case kBtnRescan: fPieView->MessageReceived(msg); - fStatusView->SetBtnLabel(B_TRANSLATE("Rescan")); break; default: diff --git a/src/apps/diskusage/VolumeView.h b/src/apps/diskusage/VolumeView.h index 7dc4789b7a..079e7ab21c 100644 --- a/src/apps/diskusage/VolumeView.h +++ b/src/apps/diskusage/VolumeView.h @@ -30,7 +30,8 @@ public: virtual ~VolumeView(); virtual void MessageReceived(BMessage* message); - void SetRescanEnabled(bool enabled); + void EnableRescan(); + void EnableCancel(); void SetPath(BPath path); void ShowInfo(const FileInfo* info);