DiskUsage enhancement (ticket #3520)
* the volume are now displayed in tabs, mounting and unmounting volume adds and remove tabs accordingly * the infos (file size, etc..) are now displayed below the graph * node monitoring tells you when your current view is outdated. (the ticket suggested to adjust the view automatically, but I'll wait for comments on this first). * Drag&Dropping a file on the graph changes the tabview to the tab representing the volume owning that file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38958 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -90,6 +90,7 @@ App::ReadyToRun()
|
||||
}
|
||||
|
||||
fMainWindow = new MainWindow(frame);
|
||||
fMainWindow->Show();
|
||||
|
||||
if (fSavedRefsReceived) {
|
||||
// RefsReceived() was called earlier than ReadyToRun()
|
||||
|
||||
@@ -78,6 +78,7 @@ read_resources(const char* appSignature)
|
||||
kVolMenuLabel = LoadString("STR_VM_LABEL");
|
||||
kOneFile = LoadString("STR_1_FILE");
|
||||
kManyFiles = LoadString("STR_N_FILES");
|
||||
kStrScan = LoadString("STR_SCAN");
|
||||
kStrRescan = LoadString("STR_RESCAN");
|
||||
kStrScanningX = LoadString("STR_SCN_X");
|
||||
kStrUnavail = LoadString("STR_UNAVAIL");
|
||||
@@ -94,6 +95,7 @@ read_resources(const char* appSignature)
|
||||
kInfoTimeFmt = LoadString("STR_TIMEFMT");
|
||||
kInfoKind = LoadString("STR_KIND");
|
||||
kInfoPath = LoadString("STR_PATH");
|
||||
kOutdatedStr = LoadString("STR_OUTDATED");
|
||||
|
||||
kWindowColor = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
kOutlineColor = LoadColor("RGB_PIE_OL");
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
|
||||
// Resources
|
||||
EXTERN char* kStrScan;
|
||||
EXTERN char* kStrRescan;
|
||||
EXTERN char* kOutdatedStr;
|
||||
EXTERN char* kStrScanningX;
|
||||
EXTERN char* kStrUnavail;
|
||||
EXTERN char* kVolMenuLabel;
|
||||
@@ -93,6 +95,7 @@ EXTERN bool kFoundHelpFile;
|
||||
#define kScanRefresh 'gSRF'
|
||||
#define kScanProgress 'gSPR'
|
||||
#define kScanDone 'gSDN'
|
||||
#define kOutdatedMsg 'gOUT'
|
||||
|
||||
#define deg2rad(x) (2.0 * M_PI * (x) / 360.0)
|
||||
#define rad2deg(x) (360.0 * (x) / (2.0 * M_PI))
|
||||
|
||||
+175
-137
@@ -12,47 +12,44 @@
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Box.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <TabView.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <Volume.h>
|
||||
#include <VolumeRoster.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "VolumeView.h"
|
||||
|
||||
|
||||
class VolumeMenuItem: public BMenuItem {
|
||||
class VolumeTab: public BTab {
|
||||
public:
|
||||
VolumeMenuItem(BVolume* volume, BMessage* message);
|
||||
virtual ~VolumeMenuItem();
|
||||
VolumeTab(BVolume* volume);
|
||||
virtual ~VolumeTab();
|
||||
|
||||
virtual void GetContentSize(float* width, float* height);
|
||||
virtual void DrawContent();
|
||||
BVolume* Volume() const
|
||||
{ return fVolume; }
|
||||
float IconWidth() const;
|
||||
|
||||
BVolume* Volume() const
|
||||
{ return fVolume; }
|
||||
status_t Invoke(BMessage* mesage = NULL)
|
||||
{ return BMenuItem::Invoke(); }
|
||||
virtual void DrawLabel(BView* owner, BRect frame);
|
||||
|
||||
private:
|
||||
BBitmap* fIcon;
|
||||
BVolume* fVolume;
|
||||
BBitmap* fIcon;
|
||||
BVolume* fVolume;
|
||||
};
|
||||
|
||||
|
||||
VolumeMenuItem::VolumeMenuItem(BVolume* volume, BMessage* message)
|
||||
VolumeTab::VolumeTab(BVolume* volume)
|
||||
:
|
||||
BMenuItem(kEmptyStr, message),
|
||||
BTab(),
|
||||
fIcon(new BBitmap(BRect(0, 0, 15, 15), B_RGBA32)),
|
||||
fVolume(volume)
|
||||
{
|
||||
char name[B_PATH_NAME_LENGTH];
|
||||
fVolume->GetName(name);
|
||||
SetLabel(name);
|
||||
|
||||
if (fVolume->GetIcon(fIcon, B_MINI_ICON) < B_OK) {
|
||||
delete fIcon;
|
||||
fIcon = NULL;
|
||||
@@ -60,53 +57,56 @@ VolumeMenuItem::VolumeMenuItem(BVolume* volume, BMessage* message)
|
||||
}
|
||||
|
||||
|
||||
VolumeMenuItem::~VolumeMenuItem()
|
||||
float
|
||||
VolumeTab::IconWidth() const
|
||||
{
|
||||
if (fIcon != NULL)
|
||||
// add a small margin
|
||||
return fIcon->Bounds().Width() + kSmallHMargin;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeTab::DrawLabel(BView* owner, BRect frame)
|
||||
{
|
||||
owner->SetDrawingMode(B_OP_OVER);
|
||||
if (fIcon != NULL) {
|
||||
owner->MovePenTo(frame.left + kSmallHMargin,
|
||||
(frame.top + frame.bottom - fIcon->Bounds().Height()) / 2.0);
|
||||
owner->DrawBitmap(fIcon);
|
||||
}
|
||||
|
||||
font_height fh;
|
||||
owner->GetFontHeight(&fh);
|
||||
|
||||
owner->SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
||||
owner->DrawString(Label(),
|
||||
BPoint(frame.left + IconWidth() + kSmallHMargin,
|
||||
(frame.top + frame.bottom - fh.ascent - fh.descent) / 2.0
|
||||
+ fh.ascent));
|
||||
}
|
||||
|
||||
|
||||
VolumeTab::~VolumeTab()
|
||||
{
|
||||
delete fIcon;
|
||||
delete fVolume;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeMenuItem::GetContentSize(float* width, float* height)
|
||||
{
|
||||
*width = be_plain_font->StringWidth(Label());
|
||||
|
||||
struct font_height fh;
|
||||
be_plain_font->GetHeight(&fh);
|
||||
float fontHeight = fh.ascent + fh.descent + fh.leading;
|
||||
if (fIcon) {
|
||||
*height = max_c(fontHeight, fIcon->Bounds().Height());
|
||||
*width += fIcon->Bounds().Width() + kSmallHMargin;
|
||||
} else
|
||||
*height = fontHeight;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeMenuItem::DrawContent()
|
||||
{
|
||||
if (fIcon) {
|
||||
Menu()->SetDrawingMode(B_OP_OVER);
|
||||
Menu()->MovePenBy(0.0, -1.0);
|
||||
Menu()->DrawBitmap(fIcon);
|
||||
Menu()->SetDrawingMode(B_OP_COPY);
|
||||
Menu()->MovePenBy(fIcon->Bounds().Width() + kSmallHMargin, 0.0);
|
||||
}
|
||||
BMenuItem::DrawContent();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
class ControlsView::VolumePopup: public BMenuField {
|
||||
class ControlsView::VolumeTabView: public BTabView {
|
||||
public:
|
||||
VolumePopup(BRect r);
|
||||
virtual ~VolumePopup();
|
||||
VolumeTabView();
|
||||
virtual ~VolumeTabView();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual BRect TabFrame(int32 index) const;
|
||||
|
||||
BVolume* FindDeviceFor(dev_t device,
|
||||
bool invoke = false);
|
||||
@@ -119,16 +119,40 @@ private:
|
||||
};
|
||||
|
||||
|
||||
ControlsView::VolumePopup::VolumePopup(BRect r)
|
||||
ControlsView::VolumeTabView::VolumeTabView()
|
||||
:
|
||||
BMenuField(r, NULL, kVolMenuLabel, new BPopUpMenu(kVolMenuDefault), false,
|
||||
B_FOLLOW_LEFT)
|
||||
BTabView("volume_tabs", B_WIDTH_FROM_LABEL)
|
||||
{
|
||||
SetViewColor(kWindowColor);
|
||||
SetLowColor(kWindowColor);
|
||||
}
|
||||
|
||||
SetDivider(kSmallHMargin + StringWidth(kVolMenuLabel));
|
||||
|
||||
ControlsView::VolumeTabView::~VolumeTabView()
|
||||
{
|
||||
fVolumeRoster->StopWatching();
|
||||
delete fVolumeRoster;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
ControlsView::VolumeTabView::TabFrame(int32 index) const
|
||||
{
|
||||
float height = BTabView::TabFrame(index).Height();
|
||||
float x = 0.0f;
|
||||
for (int32 i = 0; i < index; i++) {
|
||||
x += StringWidth(TabAt(i)->Label()) + 3.0f * kSmallHMargin
|
||||
+ ((VolumeTab*)TabAt(i))->IconWidth();
|
||||
}
|
||||
|
||||
return BRect(x, 0.0f,
|
||||
x + StringWidth(TabAt(index)->Label()) + 3.0f * kSmallHMargin
|
||||
+ ((VolumeTab*)TabAt(index))->IconWidth(),
|
||||
height);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::VolumeTabView::AttachedToWindow()
|
||||
{
|
||||
// Populate the menu with the persistent volumes.
|
||||
fVolumeRoster = new BVolumeRoster();
|
||||
|
||||
@@ -136,32 +160,20 @@ ControlsView::VolumePopup::VolumePopup(BRect r)
|
||||
while (fVolumeRoster->GetNextVolume(&tempVolume) == B_OK) {
|
||||
if (tempVolume.IsPersistent()) {
|
||||
BVolume* volume = new BVolume(tempVolume);
|
||||
BMessage* message = new BMessage(kMenuSelectVol);
|
||||
message->AddPointer(kNameVolPtr, volume);
|
||||
VolumeMenuItem *item = new VolumeMenuItem(volume, message);
|
||||
Menu()->AddItem(item);
|
||||
VolumeTab *item = new VolumeTab(volume);
|
||||
char name[B_PATH_NAME_LENGTH];
|
||||
volume->GetName(name);
|
||||
AddTab(new VolumeView(name, volume), item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ControlsView::VolumePopup::~VolumePopup()
|
||||
{
|
||||
fVolumeRoster->StopWatching();
|
||||
delete fVolumeRoster;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::VolumePopup::AttachedToWindow()
|
||||
{
|
||||
// Begin watching mount and unmount events.
|
||||
fVolumeRoster->StartWatching(BMessenger(this));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::VolumePopup::MessageReceived(BMessage* message)
|
||||
ControlsView::VolumeTabView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
@@ -176,24 +188,50 @@ ControlsView::VolumePopup::MessageReceived(BMessage* message)
|
||||
}
|
||||
break;
|
||||
|
||||
case kBtnRescan:
|
||||
ViewForTab(Selection())->MessageReceived(message);
|
||||
break;
|
||||
|
||||
case B_SIMPLE_DATA:
|
||||
case B_REFS_RECEIVED:
|
||||
{
|
||||
entry_ref ref;
|
||||
|
||||
for (int i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
|
||||
BEntry entry(&ref, true);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
dev_t device = dev_for_path(path.Path());
|
||||
|
||||
for (int j = 0; VolumeTab* item = (VolumeTab*)TabAt(j); j++) {
|
||||
if (item->Volume()->Device() == device) {
|
||||
Select(j);
|
||||
((VolumeView*)(item->View()))->SetPath(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BMenuField::MessageReceived(message);
|
||||
BTabView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BVolume*
|
||||
ControlsView::VolumePopup::FindDeviceFor(dev_t device, bool invoke)
|
||||
ControlsView::VolumeTabView::FindDeviceFor(dev_t device, bool invoke)
|
||||
{
|
||||
BVolume* volume = NULL;
|
||||
|
||||
// Iterate through items looking for a BVolume representing this device.
|
||||
for (int i = 0; VolumeMenuItem* item = (VolumeMenuItem*)Menu()->ItemAt(i); i++) {
|
||||
for (int i = 0; VolumeTab* item = (VolumeTab*)TabAt(i); i++) {
|
||||
if (item->Volume()->Device() == device) {
|
||||
volume = item->Volume();
|
||||
if (invoke)
|
||||
item->Invoke();
|
||||
Select(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -203,43 +241,36 @@ ControlsView::VolumePopup::FindDeviceFor(dev_t device, bool invoke)
|
||||
|
||||
|
||||
void
|
||||
ControlsView::VolumePopup::_AddVolume(dev_t device)
|
||||
ControlsView::VolumeTabView::_AddVolume(dev_t device)
|
||||
{
|
||||
// Make sure the volume is not already in the menu.
|
||||
for (int i = 0; i < Menu()->CountItems(); i++) {
|
||||
VolumeMenuItem* item = (VolumeMenuItem*)Menu()->ItemAt(i);
|
||||
for (int i = 0; VolumeTab* item = (VolumeTab*)TabAt(i); i++) {
|
||||
if (item->Volume()->Device() == device)
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the newly mounted volume to the menu.
|
||||
BVolume* volume = new BVolume(device);
|
||||
BMessage* message = new BMessage(kMenuSelectVol);
|
||||
message->AddPointer(kNameVolPtr, volume);
|
||||
VolumeMenuItem* item = new VolumeMenuItem(volume, message);
|
||||
Menu()->AddItem(item);
|
||||
|
||||
VolumeTab* item = new VolumeTab(volume);
|
||||
char name[B_PATH_NAME_LENGTH];
|
||||
volume->GetName(name);
|
||||
|
||||
AddTab(new VolumeView(name, volume), item);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::VolumePopup::_RemoveVolume(dev_t device)
|
||||
ControlsView::VolumeTabView::_RemoveVolume(dev_t device)
|
||||
{
|
||||
for (int i = 0; i < Menu()->CountItems(); i++) {
|
||||
VolumeMenuItem* item = (VolumeMenuItem*)Menu()->ItemAt(i);
|
||||
for (int i = 0; VolumeTab* item = (VolumeTab*)TabAt(i); i++) {
|
||||
if (item->Volume()->Device() == device) {
|
||||
// If the volume being removed is currently selected, prompt for a
|
||||
// different volume.
|
||||
if (item->IsMarked()) {
|
||||
// update the displayed volume label now that there is no marked
|
||||
// item:
|
||||
Menu()->Superitem()->SetLabel(kVolMenuDefault);
|
||||
|
||||
BMessage messae(kMenuSelectVol);
|
||||
messae.AddPointer(kNameVolPtr, NULL);
|
||||
Window()->PostMessage(&messae);
|
||||
}
|
||||
|
||||
Menu()->RemoveItem(item);
|
||||
if (i == 0)
|
||||
Select(1);
|
||||
else
|
||||
Select(i - 1);
|
||||
RemoveTab(i);
|
||||
delete item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -249,43 +280,34 @@ ControlsView::VolumePopup::_RemoveVolume(dev_t device)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ControlsView::ControlsView(BRect r)
|
||||
: BView(r, NULL, B_FOLLOW_LEFT_RIGHT, 0)
|
||||
ControlsView::ControlsView()
|
||||
:
|
||||
BView(NULL, B_WILL_DRAW)
|
||||
{
|
||||
SetViewColor(kWindowColor);
|
||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||
fVolumeTabView = new VolumeTabView();
|
||||
AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
|
||||
.Add(fVolumeTabView)
|
||||
);
|
||||
}
|
||||
|
||||
r.top += kSmallVMargin;
|
||||
r.right -= kSmallHMargin;
|
||||
float buttonWidth = kButtonMargin + StringWidth(kHelpBtnLabel);
|
||||
r.left = r.right - buttonWidth;
|
||||
BButton* helpButton = new BButton(r, NULL, kHelpBtnLabel, new BMessage(kBtnHelp),
|
||||
B_FOLLOW_RIGHT);
|
||||
if (!kFoundHelpFile)
|
||||
helpButton->SetEnabled(false);
|
||||
|
||||
r.right = r.left - kSmallHMargin;
|
||||
buttonWidth = kButtonMargin + StringWidth(kStrRescan);
|
||||
r.left = r.right - max_c(kMinButtonWidth, buttonWidth);
|
||||
fRescanButton = new BButton(r, NULL, kStrRescan, new BMessage(kBtnRescan),
|
||||
B_FOLLOW_RIGHT);
|
||||
void
|
||||
ControlsView::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case B_SIMPLE_DATA:
|
||||
case B_REFS_RECEIVED:
|
||||
fVolumeTabView->MessageReceived(msg);
|
||||
break;
|
||||
|
||||
fVolumePopup = new VolumePopup(
|
||||
BRect(kSmallHMargin, kSmallVMargin, r.left - kSmallHMargin, kSmallVMargin));
|
||||
case kBtnRescan:
|
||||
fVolumeTabView->MessageReceived(msg);
|
||||
break;
|
||||
|
||||
float width, height;
|
||||
fRescanButton->GetPreferredSize(&width, &height);
|
||||
ResizeTo(Bounds().Width(), height + 6.0);
|
||||
|
||||
// Horizontal divider
|
||||
r = Bounds();
|
||||
r.top = r.bottom - 1.0;
|
||||
r.left -= 5.0; r.right += 5.0;
|
||||
BBox* divider = new BBox(r, NULL, B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW);
|
||||
|
||||
AddChild(fVolumePopup);
|
||||
AddChild(divider);
|
||||
AddChild(fRescanButton);
|
||||
AddChild(helpButton);
|
||||
default:
|
||||
BView::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,8 +316,24 @@ ControlsView::~ControlsView()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::ShowInfo(const FileInfo* info)
|
||||
{
|
||||
((VolumeView*)fVolumeTabView->ViewForTab(
|
||||
fVolumeTabView->Selection()))->ShowInfo(info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ControlsView::SetRescanEnabled(bool enabled)
|
||||
{
|
||||
((VolumeView*)fVolumeTabView->ViewForTab(
|
||||
fVolumeTabView->Selection()))->SetRescanEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
BVolume*
|
||||
ControlsView::FindDeviceFor(dev_t device, bool invoke)
|
||||
{
|
||||
return fVolumePopup->FindDeviceFor(device, invoke);
|
||||
return fVolumeTabView->FindDeviceFor(device, invoke);
|
||||
}
|
||||
|
||||
@@ -9,29 +9,32 @@
|
||||
#ifndef CONTROLS_VIEW_H
|
||||
#define CONTROLS_VIEW_H
|
||||
|
||||
|
||||
#include <Button.h>
|
||||
#include <View.h>
|
||||
|
||||
|
||||
class BMessage;
|
||||
class BVolume;
|
||||
|
||||
struct FileInfo;
|
||||
|
||||
class ControlsView: public BView {
|
||||
public:
|
||||
ControlsView(BRect r);
|
||||
ControlsView();
|
||||
virtual ~ControlsView();
|
||||
|
||||
void SetRescanEnabled(bool enable)
|
||||
{ fRescanButton->SetEnabled(enable); }
|
||||
virtual void MessageReceived(BMessage* msg);
|
||||
|
||||
BVolume* FindDeviceFor(dev_t device,
|
||||
bool invoke = false);
|
||||
|
||||
private:
|
||||
class VolumePopup;
|
||||
|
||||
VolumePopup* fVolumePopup;
|
||||
BButton* fRescanButton;
|
||||
void SetRescanEnabled(bool enabled);
|
||||
void ShowInfo(const FileInfo* info);
|
||||
|
||||
private:
|
||||
class VolumeTabView;
|
||||
|
||||
VolumeTabView* fVolumeTabView;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ resource(101, "N_PIE_COLORS") (uint8)4;
|
||||
resource(103, "STR_N_FILES") "%d files";
|
||||
resource(102, "STR_1_FILE") "%d file";
|
||||
resource(101, "STR_VM_LABEL") "Volume:";
|
||||
resource(120, "STR_SCAN") "Scan";
|
||||
resource(104, "STR_RESCAN") "Rescan";
|
||||
resource(105, "STR_SCN_X") "Scanning ";
|
||||
resource(106, "STR_UNAVAIL") "file unavailable";
|
||||
@@ -78,4 +79,4 @@ resource(116, "STR_MOD") "Modified";
|
||||
resource(117, "STR_TIMEFMT") "%a, %d %b %Y, %r";
|
||||
resource(118, "STR_KIND") "Kind";
|
||||
resource(119, "STR_PATH") "Path";
|
||||
|
||||
resource(121, "STR_OUTDATED") "Outdated view";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SubDir HAIKU_TOP src apps diskusage ;
|
||||
|
||||
UsePrivateHeaders mount shared tracker ;
|
||||
UsePrivateHeaders mount shared tracker storage ;
|
||||
SubDirHdrs $(HAIKU_TOP) src kits tracker ;
|
||||
|
||||
Application DiskUsage :
|
||||
@@ -14,6 +14,7 @@ Application DiskUsage :
|
||||
Scanner.cpp
|
||||
Snapshot.cpp
|
||||
StatusView.cpp
|
||||
VolumeView.cpp
|
||||
: be $(TARGET_LIBSTDC++)
|
||||
: DiskUsage.rdef
|
||||
;
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
* as long as it is accompanied by it's documentation and this copyright notice.
|
||||
* The software comes with no warranty, etc.
|
||||
*/
|
||||
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <Application.h>
|
||||
@@ -16,58 +14,28 @@
|
||||
#include <Roster.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "ControlsView.h"
|
||||
#include "PieView.h"
|
||||
#include "StatusView.h"
|
||||
|
||||
|
||||
const float kMinWinSize = 275.0;
|
||||
|
||||
|
||||
MainWindow::MainWindow(BRect pieRect)
|
||||
:
|
||||
BWindow(pieRect, "DiskUsage", B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
|
||||
| B_AUTO_UPDATE_SIZE_LIMITS)
|
||||
{
|
||||
BRect r = Bounds();
|
||||
r.bottom = r.top + 1.0;
|
||||
fControlsView = new ControlsView(r);
|
||||
float cvHeight = fControlsView->Bounds().Height();
|
||||
AddChild(fControlsView);
|
||||
fControlsView = new ControlsView();
|
||||
|
||||
r = Bounds();
|
||||
r.top = r.bottom - 1.0;
|
||||
fStatusView = new StatusView(r);
|
||||
float svHeight = fStatusView->Bounds().Height();
|
||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||
|
||||
float winHeight = pieRect.Height() + cvHeight + svHeight;
|
||||
fStatusView->MoveTo(0.0, winHeight - svHeight);
|
||||
ResizeTo(r.Width(), winHeight);
|
||||
|
||||
AddChild(fStatusView);
|
||||
|
||||
r = fControlsView->Frame();
|
||||
r.top = r.bottom + 1.0;
|
||||
r.bottom = fStatusView->Frame().top - 1.0;
|
||||
fPieView = new PieView(r, this);
|
||||
AddChild(fPieView);
|
||||
|
||||
Show();
|
||||
|
||||
// Note: The following code is semi-broken because BScreen::Frame()
|
||||
// returns incorrect dimensions for the G200 in 1152x864 mode. I reported
|
||||
// this bug, and Be said it's not a bug -- the Matrox driver actually uses
|
||||
// a resolution of 1152x900 in that mode. Oh well.
|
||||
Lock();
|
||||
float extraHeight = fControlsView->Bounds().Height()
|
||||
+ fStatusView->Bounds().Height();
|
||||
float minHeight = kMinWinSize + extraHeight;
|
||||
float maxHeight = BScreen(this).Frame().Height();
|
||||
float maxWidth = maxHeight - extraHeight;
|
||||
Unlock();
|
||||
|
||||
SetSizeLimits(kMinWinSize, maxWidth, minHeight, maxHeight);
|
||||
AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
|
||||
.Add(fControlsView)
|
||||
.SetInsets(5, 5, 5, 5)
|
||||
);
|
||||
float maxHeight = BScreen(this).Frame().Height() - 12;
|
||||
fControlsView->SetExplicitMaxSize(BSize(maxHeight, maxHeight));
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +49,11 @@ MainWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kBtnRescan:
|
||||
case kMenuSelectVol:
|
||||
fControlsView->MessageReceived(message);
|
||||
break;
|
||||
case B_SIMPLE_DATA:
|
||||
case B_REFS_RECEIVED:
|
||||
fPieView->MessageReceived(message);
|
||||
fControlsView->MessageReceived(message);
|
||||
break;
|
||||
|
||||
case kBtnHelp:
|
||||
@@ -109,16 +79,16 @@ MainWindow::QuitRequested()
|
||||
|
||||
|
||||
void
|
||||
MainWindow::ShowInfo(const FileInfo* info)
|
||||
MainWindow::SetRescanEnabled(bool enabled)
|
||||
{
|
||||
fStatusView->ShowInfo(info);
|
||||
fControlsView->SetRescanEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::SetRescanEnabled(bool enabled)
|
||||
MainWindow::ShowInfo(const FileInfo* info)
|
||||
{
|
||||
fControlsView->SetRescanEnabled(enabled);
|
||||
fControlsView->ShowInfo(info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#ifndef MAIN_WINDOW_H
|
||||
#define MAIN_WINDOW_H
|
||||
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
@@ -18,8 +17,6 @@ class BVolume;
|
||||
class ControlsView;
|
||||
struct FileInfo;
|
||||
class PieView;
|
||||
class StatusView;
|
||||
|
||||
|
||||
class MainWindow: public BWindow {
|
||||
public:
|
||||
@@ -29,15 +26,14 @@ public:
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
void ShowInfo(const FileInfo* info);
|
||||
void SetRescanEnabled(bool enabled);
|
||||
BVolume* FindDeviceFor(dev_t device,
|
||||
bool invoke = false);
|
||||
|
||||
void ShowInfo(const FileInfo* info);
|
||||
|
||||
private:
|
||||
ControlsView* fControlsView;
|
||||
PieView* fPieView;
|
||||
StatusView* fStatusView;
|
||||
};
|
||||
|
||||
#endif // MAIN_WINDOW_H
|
||||
|
||||
+85
-124
@@ -14,7 +14,6 @@
|
||||
#include <fs_info.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <AppFileInfo.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Entry.h>
|
||||
@@ -41,8 +40,6 @@ static const int32 kIdxOpen = 1;
|
||||
static const int32 kIdxOpenWith = 2;
|
||||
static const int32 kIdxRescan = 3;
|
||||
|
||||
// TODO: It would be nice to make a common base class for AppMenuItem and
|
||||
// VolMenuItem (menu items that include an icon).
|
||||
|
||||
class AppMenuItem : public BMenuItem {
|
||||
public:
|
||||
@@ -125,20 +122,17 @@ AppMenuItem::DrawContent()
|
||||
// #pragma mark - PieView
|
||||
|
||||
|
||||
PieView::PieView(BRect frame, MainWindow* window)
|
||||
PieView::PieView(BVolume* volume)
|
||||
:
|
||||
BView(frame, NULL, B_FOLLOW_ALL,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_SUBPIXEL_PRECISE),
|
||||
fWindow(window),
|
||||
fScanners(),
|
||||
fCurrentVolume(NULL),
|
||||
BView(NULL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_SUBPIXEL_PRECISE),
|
||||
fWindow(NULL),
|
||||
fScanner(NULL),
|
||||
fVolume(volume),
|
||||
fMouseOverInfo(),
|
||||
fClicked(false),
|
||||
fDragging(false)
|
||||
fDragging(false),
|
||||
fOutdated(false)
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
SetLowColor(kWindowColor);
|
||||
|
||||
fMouseOverMenu = new BPopUpMenu(kEmptyStr, false, false);
|
||||
fMouseOverMenu->AddItem(new BMenuItem(kMenuGetInfo, NULL), kIdxGetInfo);
|
||||
fMouseOverMenu->AddItem(new BMenuItem(kMenuOpen, NULL), kIdxOpen);
|
||||
@@ -160,16 +154,19 @@ PieView::PieView(BRect frame, MainWindow* window)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PieView::AttachedToWindow()
|
||||
{
|
||||
fWindow = (MainWindow*)Window();
|
||||
}
|
||||
|
||||
|
||||
PieView::~PieView()
|
||||
{
|
||||
delete fMouseOverMenu;
|
||||
delete fFileUnavailableMenu;
|
||||
|
||||
while (fScanners.size() != 0) {
|
||||
ScannerMap::iterator i = fScanners.begin();
|
||||
(*i).second->RequestQuit();
|
||||
fScanners.erase(i);
|
||||
}
|
||||
if (fScanner != NULL)
|
||||
fScanner->RequestQuit();
|
||||
}
|
||||
|
||||
|
||||
@@ -177,41 +174,31 @@ void
|
||||
PieView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_SIMPLE_DATA:
|
||||
case B_REFS_RECEIVED:
|
||||
{
|
||||
entry_ref ref;
|
||||
for (int i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
|
||||
BEntry entry(&ref, true);
|
||||
_HandleArg(&entry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kBtnRescan:
|
||||
if (fCurrentVolume != NULL) {
|
||||
fScanners[fCurrentVolume]->Refresh();
|
||||
if (fVolume != NULL) {
|
||||
if (fScanner != NULL)
|
||||
fScanner->Refresh();
|
||||
else
|
||||
_ShowVolume(fVolume);
|
||||
|
||||
fOutdated = false;
|
||||
Invalidate();
|
||||
}
|
||||
break;
|
||||
|
||||
case kMenuSelectVol:
|
||||
{
|
||||
BVolume* volume;
|
||||
if (message->FindPointer(kNameVolPtr, (void**)&volume) == B_OK)
|
||||
_ShowVolume(volume);
|
||||
break;
|
||||
}
|
||||
|
||||
case kScanProgress:
|
||||
case kScanDone:
|
||||
{
|
||||
BVolume* volume;
|
||||
if (message->FindPointer(kNameVolPtr, (void**)&volume) == B_OK
|
||||
&& volume == fCurrentVolume) {
|
||||
Invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
case kOutdatedMsg:
|
||||
{
|
||||
if (!fScanner->IsBusy()) {
|
||||
fOutdated = true;
|
||||
Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -251,14 +238,15 @@ PieView::MouseUp(BPoint where)
|
||||
// If the primary button was released and there was no dragging happening,
|
||||
// just zoom in or out.
|
||||
if (fClicked && !fDragging) {
|
||||
Scanner* scanner = fScanners[fCurrentVolume];
|
||||
FileInfo* info = _FileAt(where);
|
||||
if (info != NULL) {
|
||||
if (info == scanner->CurrentDir()) {
|
||||
scanner->ChangeDir(info->parent);
|
||||
if (info == fScanner->CurrentDir()) {
|
||||
fScanner->ChangeDir(info->parent);
|
||||
fOutdated = fScanner->IsOutdated();
|
||||
Invalidate();
|
||||
} else if (info->children.size() > 0) {
|
||||
scanner->ChangeDir(info);
|
||||
fScanner->ChangeDir(info);
|
||||
fOutdated = fScanner->IsOutdated();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
@@ -307,27 +295,32 @@ PieView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
|
||||
void
|
||||
PieView::Draw(BRect updateRect)
|
||||
{
|
||||
if (fScanners.find(fCurrentVolume) != fScanners.end()) {
|
||||
if (fScanner != NULL) {
|
||||
// There is a current volume.
|
||||
Scanner* scanner = fScanners[fCurrentVolume];
|
||||
if (scanner->IsBusy()) {
|
||||
if (fScanner->IsBusy()) {
|
||||
// Show progress of scanning.
|
||||
_DrawProgressBar(updateRect);
|
||||
fWindow->SetRescanEnabled(false);
|
||||
if (fWindow != NULL)
|
||||
fWindow->SetRescanEnabled(false);
|
||||
} else {
|
||||
_DrawPieChart(updateRect);
|
||||
fWindow->SetRescanEnabled(true);
|
||||
if (fWindow != NULL)
|
||||
fWindow->SetRescanEnabled(true);
|
||||
}
|
||||
} else {
|
||||
// No volume has been selected, so display a prompt for one.
|
||||
FillRect(updateRect, B_SOLID_LOW);
|
||||
BRect b = Bounds();
|
||||
float strWidth = StringWidth(kVolPrompt);
|
||||
float bx = (b.left + b.Width() - strWidth) / 2.0;
|
||||
float by = (b.top + b.Height()) / 2.0;
|
||||
SetHighColor(0x00, 0x00, 0x00);
|
||||
DrawString(kVolPrompt, BPoint(bx, by));
|
||||
fWindow->SetRescanEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PieView::SetPath(BPath path)
|
||||
{
|
||||
if (fScanner == NULL)
|
||||
_ShowVolume(fVolume);
|
||||
|
||||
if (fScanner != NULL) {
|
||||
string desiredPath(path.Path());
|
||||
fScanner->SetDesiredPath(desiredPath);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,57 +328,17 @@ PieView::Draw(BRect updateRect)
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
PieView::_HandleArg(const BEntry* entry)
|
||||
{
|
||||
// Going through these seemingly pointless gyrations (instead of getting
|
||||
// the dev_t directly from the BEntry) allows us to process volumes
|
||||
// properly. It looks like a dropped volume refers to dev_t 1 (why?), but
|
||||
// getting the dev_t from the path allows us to get at the dev_t where the
|
||||
// root directory actually lives.
|
||||
BPath path;
|
||||
entry->GetPath(&path);
|
||||
dev_t device = dev_for_path(path.Path());
|
||||
|
||||
// Set the desired path in the scanner.
|
||||
Scanner* scanner = NULL;
|
||||
ScannerMap::iterator i = fScanners.begin();
|
||||
while (i != fScanners.end()) {
|
||||
if ((*i).second->Device() == device) {
|
||||
scanner = (*i).second;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (scanner == NULL) {
|
||||
BVolume* volume = fWindow->FindDeviceFor(device);
|
||||
if (volume != NULL)
|
||||
scanner = fScanners[volume] = new Scanner(volume, this);
|
||||
}
|
||||
if (scanner != NULL) {
|
||||
string desiredPath(path.Path());
|
||||
scanner->SetDesiredPath(desiredPath);
|
||||
|
||||
// Select the volume on the menu.
|
||||
fWindow->FindDeviceFor(device, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PieView::_ShowVolume(BVolume* volume)
|
||||
{
|
||||
if (volume != NULL) {
|
||||
if (fScanners.find(volume) == fScanners.end())
|
||||
fScanners[volume] = new Scanner(volume, this);
|
||||
|
||||
Scanner* scanner = fScanners[volume];
|
||||
if (scanner->Snapshot() == NULL)
|
||||
scanner->Refresh();
|
||||
if (fScanner == NULL)
|
||||
fScanner = new Scanner(volume, this);
|
||||
|
||||
if (fScanner->Snapshot() == NULL)
|
||||
fScanner->Refresh();
|
||||
}
|
||||
|
||||
fCurrentVolume = volume;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
@@ -416,7 +369,7 @@ PieView::_DrawProgressBar(BRect updateRect)
|
||||
bx += 1.0; by += 1.0;
|
||||
ex -= 1.0; ey -= 1.0;
|
||||
float mx = bx + floorf((kProgBarWidth - 2.0)
|
||||
* fScanners[fCurrentVolume]->Progress() / 100.0 + 0.5);
|
||||
* fScanner->Progress() / 100.0 + 0.5);
|
||||
SetHighColor(tint_color(kWindowColor, B_DARKEN_1_TINT));
|
||||
FillRect(BRect(mx, by, ex, ey));
|
||||
|
||||
@@ -433,7 +386,7 @@ PieView::_DrawProgressBar(BRect updateRect)
|
||||
FillRect(BRect(bx, by, mx, ey));
|
||||
|
||||
// Tell what we are doing.
|
||||
const char* task = fScanners[fCurrentVolume]->Task();
|
||||
const char* task = fScanner->Task();
|
||||
float strWidth = StringWidth(task);
|
||||
bx = (b.left + b.Width() - strWidth) / 2.0;
|
||||
by -= fFontHeight + 2.0 * kSmallVMargin;
|
||||
@@ -465,7 +418,7 @@ PieView::_DrawPieChart(BRect updateRect)
|
||||
pieRect.bottom += moveBy;
|
||||
}
|
||||
int colorIdx = 0;
|
||||
FileInfo* currentDir = fScanners[fCurrentVolume]->CurrentDir();
|
||||
FileInfo* currentDir = fScanner->CurrentDir();
|
||||
FileInfo* parent = currentDir;
|
||||
while (parent != NULL) {
|
||||
parent = parent->parent;
|
||||
@@ -473,16 +426,21 @@ PieView::_DrawPieChart(BRect updateRect)
|
||||
}
|
||||
_DrawDirectory(pieRect, currentDir, 0.0, 0.0, colorIdx % kBasePieColorCount,
|
||||
0);
|
||||
|
||||
if (fOutdated) {
|
||||
|
||||
BRect b = Bounds();
|
||||
|
||||
// This is just for the case when the mouse hovers over the view
|
||||
// while the scanning process is running and then does not move
|
||||
// until after the results are shown. In that case the info will
|
||||
// not automatically update. (TODO: fix this and put into MessageReceived()
|
||||
// kScanDone - currently, fileAt() returns NULL (mouseoverinfo...))
|
||||
BPoint where;
|
||||
uint32 ignore;
|
||||
GetMouse(&where, &ignore, false);
|
||||
fWindow->ShowInfo(_FileAt(where));
|
||||
float strWidth = StringWidth(kOutdatedStr);
|
||||
float bx = (b.Width() - strWidth - kSmallHMargin);
|
||||
|
||||
struct font_height fh;
|
||||
be_plain_font->GetHeight(&fh);
|
||||
|
||||
float by = (b.Height() - ceil(fh.descent) - kSmallVMargin);
|
||||
SetHighColor(0x00, 0x00, 0x00);
|
||||
DrawString(kOutdatedStr, BPoint(bx, by));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -500,7 +458,7 @@ PieView::_DrawDirectory(BRect b, FileInfo* info, float parentSpan,
|
||||
else if (info != NULL)
|
||||
info->color = colorIdx;
|
||||
|
||||
VolumeSnapshot* snapshot = fScanners[fCurrentVolume]->Snapshot();
|
||||
VolumeSnapshot* snapshot = fScanner->Snapshot();
|
||||
|
||||
float cx = floorf(b.left + b.Width() / 2.0 + 0.5);
|
||||
float cy = floorf(b.top + b.Height() / 2.0 + 0.5);
|
||||
@@ -525,7 +483,8 @@ PieView::_DrawDirectory(BRect b, FileInfo* info, float parentSpan,
|
||||
FillEllipse(BPoint(cx, cy), kPieCenterSize, kPieCenterSize);
|
||||
|
||||
SetHighColor(kBasePieColor[0]);
|
||||
FillArc(BPoint(cx, cy), kPieCenterSize, kPieCenterSize, 0.0, mySpan);
|
||||
FillArc(BPoint(cx, cy), kPieCenterSize, kPieCenterSize, 0.0,
|
||||
mySpan);
|
||||
|
||||
// Show total volume capacity.
|
||||
char label[B_PATH_NAME_LENGTH];
|
||||
@@ -560,7 +519,8 @@ PieView::_DrawDirectory(BRect b, FileInfo* info, float parentSpan,
|
||||
|
||||
SetPenSize(1.0);
|
||||
SetHighColor(kOutlineColor);
|
||||
StrokeEllipse(BPoint(cx, cy), kPieCenterSize + 0.5, kPieCenterSize + 0.5);
|
||||
StrokeEllipse(BPoint(cx, cy), kPieCenterSize + 0.5,
|
||||
kPieCenterSize + 0.5);
|
||||
|
||||
// Show the name of the volume or directory.
|
||||
BString label(displayName);
|
||||
@@ -803,7 +763,7 @@ PieView::_ShowContextMenu(FileInfo* info, BPoint p)
|
||||
_Launch(info);
|
||||
break;
|
||||
case kIdxRescan:
|
||||
fScanners[fCurrentVolume]->Refresh(info);
|
||||
fScanner->Refresh(info);
|
||||
Invalidate();
|
||||
break;
|
||||
default: // must be "Open With" submenu
|
||||
@@ -844,6 +804,7 @@ PieView::_Launch(FileInfo* info, const entry_ref* appRef)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PieView::_OpenInfo(FileInfo* info, BPoint p)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
class AppMenuItem;
|
||||
class BEntry;
|
||||
class BMenu;
|
||||
class BPath;
|
||||
class BPopUpMenu;
|
||||
class BVolume;
|
||||
struct entry_ref;
|
||||
@@ -33,18 +34,19 @@ using std::vector;
|
||||
|
||||
class PieView: public BView {
|
||||
public:
|
||||
PieView(BRect frame, MainWindow* window);
|
||||
PieView(BVolume* volume);
|
||||
virtual ~PieView();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
virtual void Draw(BRect updateRect);
|
||||
void SetPath(BPath path);
|
||||
|
||||
private:
|
||||
void _HandleArg(const BEntry* entry);
|
||||
void _ShowVolume(BVolume* volume);
|
||||
void _DrawProgressBar(BRect updateRect);
|
||||
void _DrawPieChart(BRect updateRect);
|
||||
@@ -59,6 +61,7 @@ private:
|
||||
void _Launch(FileInfo* info,
|
||||
const entry_ref* ref = NULL);
|
||||
void _OpenInfo(FileInfo* info, BPoint p);
|
||||
|
||||
private:
|
||||
struct Segment {
|
||||
Segment()
|
||||
@@ -76,12 +79,10 @@ private:
|
||||
typedef vector<Segment> SegmentList;
|
||||
typedef map<int, SegmentList> MouseOverInfo;
|
||||
|
||||
typedef map<BVolume*, Scanner*> ScannerMap;
|
||||
|
||||
private:
|
||||
MainWindow* fWindow;
|
||||
ScannerMap fScanners;
|
||||
BVolume* fCurrentVolume;
|
||||
Scanner* fScanner;
|
||||
BVolume* fVolume;
|
||||
FileInfo* fCurrentDir;
|
||||
MouseOverInfo fMouseOverInfo;
|
||||
BPopUpMenu* fMouseOverMenu;
|
||||
@@ -91,6 +92,7 @@ private:
|
||||
bool fDragging;
|
||||
BPoint fDragStart;
|
||||
FileInfo* fClickedFile;
|
||||
bool fOutdated;
|
||||
};
|
||||
|
||||
#endif // PIE_VIEW_H
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <PathMonitor.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
@@ -31,18 +32,27 @@ Scanner::Scanner(BVolume *v, BHandler *handler)
|
||||
fDesiredPath(),
|
||||
fTask(),
|
||||
fBusy(false),
|
||||
fQuitRequested(false)
|
||||
fQuitRequested(false),
|
||||
fIsWatching(false),
|
||||
fModifiedEntries()
|
||||
{
|
||||
fDoneMessage.AddPointer(kNameVolPtr, fVolume);
|
||||
fProgressMessage.AddPointer(kNameVolPtr, fVolume);
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
|
||||
Scanner::~Scanner()
|
||||
{
|
||||
if (fIsWatching) {
|
||||
BPrivate::BPathMonitor::StopWatching(BMessenger(this, this));
|
||||
fIsWatching = false;
|
||||
}
|
||||
delete fSnapshot;
|
||||
|
||||
while (fModifiedEntries.size() != 0) {
|
||||
entry_ref* entry = *fModifiedEntries.begin();
|
||||
delete entry;
|
||||
fModifiedEntries.erase(fModifiedEntries.begin());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +68,38 @@ Scanner::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case B_PATH_MONITOR:
|
||||
{
|
||||
dev_t device;
|
||||
ino_t directory;
|
||||
const char* name = "";
|
||||
const char* path;
|
||||
|
||||
if (((message->FindInt32("device", &device) != B_OK)
|
||||
|| (message->FindInt64("directory", &directory) != B_OK)
|
||||
|| (message->FindString("name", &name) != B_OK))
|
||||
&& ((message->FindString("path", &path) != B_OK)
|
||||
|| (message->FindInt32("device", &device) != B_OK)))
|
||||
return;
|
||||
|
||||
entry_ref* reportedEntry;
|
||||
if (strlen(name) > 0)
|
||||
reportedEntry = new entry_ref(device, directory, name);
|
||||
else {
|
||||
BEntry entry(path);
|
||||
reportedEntry = new entry_ref();
|
||||
entry.GetRef(reportedEntry);
|
||||
}
|
||||
|
||||
fModifiedEntries.push_back(reportedEntry);
|
||||
|
||||
if (IsOutdated()) {
|
||||
BMessage msg(kOutdatedMsg);
|
||||
fListener.SendMessage(&msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
@@ -73,6 +115,12 @@ Scanner::Refresh(FileInfo* startInfo)
|
||||
|
||||
fBusy = true;
|
||||
|
||||
while (fModifiedEntries.size() != 0) {
|
||||
entry_ref* entry = *fModifiedEntries.begin();
|
||||
delete entry;
|
||||
fModifiedEntries.erase(fModifiedEntries.begin());
|
||||
}
|
||||
|
||||
// Remember the current directory, if any, so we can return to it after
|
||||
// the scanning is done.
|
||||
if (fSnapshot != NULL && fSnapshot->currentDir != NULL)
|
||||
@@ -112,9 +160,43 @@ Scanner::RequestQuit()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Scanner::IsOutdated()
|
||||
{
|
||||
FileInfo* currentDir = (fSnapshot->currentDir != NULL ?
|
||||
fSnapshot->currentDir : fSnapshot->rootDir);
|
||||
|
||||
BDirectory currentDirectory(&(currentDir->ref));
|
||||
|
||||
bool isOutdated = currentDirectory.InitCheck() != B_OK;
|
||||
|
||||
vector<entry_ref*>::iterator i = fModifiedEntries.begin();
|
||||
while (!isOutdated && i != fModifiedEntries.end()) {
|
||||
BEntry entry(*i);
|
||||
isOutdated = _DirectoryContains(currentDir, *i)
|
||||
|| currentDirectory.Contains(&entry);
|
||||
i++;
|
||||
}
|
||||
return isOutdated;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
bool
|
||||
Scanner::_DirectoryContains(FileInfo* currentDir, entry_ref* ref)
|
||||
{
|
||||
vector<FileInfo*>::iterator i = currentDir->children.begin();
|
||||
bool contains = currentDir->ref == *ref;
|
||||
while (!contains && i != currentDir->children.end()) {
|
||||
contains |= _DirectoryContains((*i), ref);
|
||||
i++;
|
||||
}
|
||||
return contains;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Scanner::_RunScan(FileInfo* startInfo)
|
||||
{
|
||||
@@ -168,6 +250,16 @@ Scanner::_RunScan(FileInfo* startInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if (!fIsWatching) {
|
||||
string path;
|
||||
fSnapshot->rootDir->GetPath(path);
|
||||
|
||||
BPrivate::BPathMonitor::StartWatching(path.c_str(),
|
||||
B_WATCH_ALL | B_WATCH_RECURSIVELY, BMessenger(this, this));
|
||||
|
||||
fIsWatching = true;
|
||||
}
|
||||
|
||||
fBusy = false;
|
||||
_ChangeToDesired();
|
||||
fListener.SendMessage(&fDoneMessage);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Message.h>
|
||||
@@ -49,11 +50,14 @@ public:
|
||||
dev_t Device() const
|
||||
{ return fVolume->Device(); }
|
||||
void RequestQuit();
|
||||
bool IsOutdated();
|
||||
|
||||
private:
|
||||
void _RunScan(FileInfo *startInfo);
|
||||
FileInfo* _GetFileInfo(BDirectory* dir, FileInfo* parent);
|
||||
void _ChangeToDesired();
|
||||
bool _DirectoryContains(FileInfo* currentDir,
|
||||
entry_ref* ref);
|
||||
|
||||
BMessenger fListener;
|
||||
BMessage fDoneMessage;
|
||||
@@ -69,6 +73,10 @@ private:
|
||||
string fTask;
|
||||
bool fBusy;
|
||||
bool fQuitRequested;
|
||||
|
||||
bool fIsWatching;
|
||||
|
||||
std::vector<entry_ref*> fModifiedEntries;
|
||||
};
|
||||
|
||||
#endif // SCANNER_H
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe St-Pierre <stpere@gmail.com>. All rights reserved.
|
||||
* Copyright (c) 2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||
* Distributed under the terms of the MIT/X11 license.
|
||||
*
|
||||
@@ -14,73 +15,70 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <Node.h>
|
||||
#include <String.h>
|
||||
#include <StringView.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
|
||||
StatusView::StatusView(BRect rect)
|
||||
StatusView::StatusView()
|
||||
:
|
||||
BView(rect, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW),
|
||||
BView(NULL, B_WILL_DRAW),
|
||||
fCurrentFileInfo(NULL)
|
||||
{
|
||||
SetViewColor(kWindowColor);
|
||||
SetViewColor(kPieBGColor);
|
||||
SetLowColor(kPieBGColor);
|
||||
|
||||
struct font_height fh;
|
||||
be_plain_font->GetHeight(&fh);
|
||||
float plainHeight = ceilf(fh.ascent) + ceilf(fh.descent)
|
||||
+ ceilf(fh.leading);
|
||||
float fixedHeight = ceilf(fh.ascent) + ceilf(fh.descent)
|
||||
+ ceilf(fh.leading);
|
||||
ResizeTo(Bounds().Width(),
|
||||
2.0 * kSmallVMargin + max_c(plainHeight, fixedHeight));
|
||||
fSizeView = new BStringView(NULL, kEmptyStr);
|
||||
fSizeView->SetExplicitMinSize(BSize(StringWidth("9999.99 GB"),
|
||||
B_SIZE_UNSET));
|
||||
fSizeView->SetExplicitMaxSize(BSize(StringWidth("9999.99 GB"),
|
||||
B_SIZE_UNSET));
|
||||
|
||||
BRect r = Bounds();
|
||||
r.top += kSmallVMargin;
|
||||
|
||||
// Size display
|
||||
r.right -= kSmallHMargin;
|
||||
r.left = r.right - StringWidth("9999.99 GB");
|
||||
fSizeView = new BStringView(r, NULL, kEmptyStr,
|
||||
B_FOLLOW_RIGHT | B_FOLLOW_TOP_BOTTOM);
|
||||
AddChild(fSizeView);
|
||||
|
||||
// Vertical divider
|
||||
r.right = r.left - kSmallHMargin;
|
||||
r.left = r.right - 1.0;
|
||||
AddChild(new BBox(r.InsetByCopy(0, -5), NULL,
|
||||
B_FOLLOW_RIGHT | B_FOLLOW_TOP_BOTTOM));
|
||||
|
||||
// Count display
|
||||
char testLabel[256];
|
||||
sprintf(testLabel, kManyFiles, 999999);
|
||||
r.right = r.left - kSmallHMargin;
|
||||
r.left = r.right - (StringWidth(testLabel) + kSmallHMargin);
|
||||
fCountView = new BStringView(r, NULL, kEmptyStr,
|
||||
B_FOLLOW_RIGHT|B_FOLLOW_TOP_BOTTOM);
|
||||
AddChild(fCountView);
|
||||
|
||||
// Vertical divider
|
||||
r.right = r.left - kSmallHMargin;
|
||||
r.left = r.right - 1.0;
|
||||
AddChild(new BBox(r.InsetByCopy(0, -5), NULL,
|
||||
B_FOLLOW_RIGHT | B_FOLLOW_TOP_BOTTOM));
|
||||
fCountView = new BStringView(NULL, kEmptyStr);
|
||||
fCountView->SetExplicitMinSize(BSize(StringWidth(testLabel), B_SIZE_UNSET));
|
||||
fCountView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
||||
|
||||
// Path display
|
||||
r.right = r.left - kSmallHMargin;
|
||||
r.left = kSmallHMargin;
|
||||
fPathView = new BStringView(r, NULL, kEmptyStr,
|
||||
B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP_BOTTOM);
|
||||
AddChild(fPathView);
|
||||
fPathView = new BStringView(NULL, kEmptyStr);
|
||||
fPathView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
||||
|
||||
// Horizontal divider
|
||||
r = Bounds();
|
||||
r.bottom = r.top + 1.0;
|
||||
AddChild(new BBox(r.InsetByCopy(-5, 0), NULL,
|
||||
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW));
|
||||
fRefreshBtn = new BButton(NULL, kStrScan, new BMessage(kBtnRescan));
|
||||
|
||||
fRefreshBtn->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNLIMITED));
|
||||
|
||||
BBox* divider1 = new BBox(BRect(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
|
||||
B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER);
|
||||
|
||||
BBox* divider2 = new BBox(BRect(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
|
||||
B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER);
|
||||
|
||||
divider1->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
|
||||
divider2->SetExplicitMaxSize(BSize(1, B_SIZE_UNLIMITED));
|
||||
|
||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||
|
||||
AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL)
|
||||
.AddGroup(B_VERTICAL)
|
||||
.Add(fPathView)
|
||||
.Add(divider1)
|
||||
.AddGroup(B_HORIZONTAL)
|
||||
.Add(fCountView)
|
||||
.Add(divider2)
|
||||
.Add(fSizeView)
|
||||
.End()
|
||||
.End()
|
||||
.AddStrut(kSmallHMargin)
|
||||
.Add(fRefreshBtn)
|
||||
.SetInsets(kSmallHMargin, kSmallVMargin, kSmallVMargin, kSmallVMargin)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +87,20 @@ StatusView::~StatusView()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusView::SetRescanEnabled(bool enabled)
|
||||
{
|
||||
fRefreshBtn->SetEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusView::SetBtnLabel(const char* label)
|
||||
{
|
||||
fRefreshBtn->SetLabel(label);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusView::ShowInfo(const FileInfo* info)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe St-Pierre <stpere@gmail.com>. All rights reserved.
|
||||
* Copyright (c) 2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||
* Distributed under the terms of the MIT/X11 license.
|
||||
*
|
||||
@@ -9,7 +10,7 @@
|
||||
#ifndef STATUS_VIEW_H
|
||||
#define STATUS_VIEW_H
|
||||
|
||||
|
||||
#include <Button.h>
|
||||
#include <View.h>
|
||||
#include <StringView.h>
|
||||
#include <Rect.h>
|
||||
@@ -19,17 +20,22 @@ struct FileInfo;
|
||||
|
||||
class StatusView: public BView {
|
||||
public:
|
||||
StatusView(BRect frame);
|
||||
StatusView();
|
||||
virtual ~StatusView();
|
||||
|
||||
void ShowInfo(const FileInfo* info);
|
||||
void SetBtnLabel(const char* label);
|
||||
void SetRescanEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
BStringView* fPathView;
|
||||
BStringView* fSizeView;
|
||||
BStringView* fCountView;
|
||||
const FileInfo* fCurrentFileInfo;
|
||||
|
||||
BButton* fRefreshBtn;
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_VIEW_H
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe Saint-Pierre, stpere@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Copyright (c) 1999 Mike Steed. You are free to use and distribute this software
|
||||
* as long as it is accompanied by it's documentation and this copyright notice.
|
||||
* The software comes with no warranty, etc.
|
||||
*/
|
||||
|
||||
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <StringView.h>
|
||||
#include <Volume.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "MainWindow.h"
|
||||
#include "PieView.h"
|
||||
#include "StatusView.h"
|
||||
|
||||
#include "VolumeView.h"
|
||||
|
||||
const float kMinWinSize = 275.0;
|
||||
|
||||
VolumeView::VolumeView(const char* name, BVolume* volume)
|
||||
: BView(name, B_WILL_DRAW)
|
||||
{
|
||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||
fPieView = new PieView(volume);
|
||||
|
||||
fPieView->SetExplicitMinSize(BSize(kMinWinSize, kMinWinSize));
|
||||
|
||||
fStatusView = new StatusView();
|
||||
|
||||
AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
|
||||
.Add(fPieView)
|
||||
.Add(fStatusView)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
VolumeView::~VolumeView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeView::SetRescanEnabled(bool enabled)
|
||||
{
|
||||
fStatusView->SetRescanEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeView::SetPath(BPath path)
|
||||
{
|
||||
fPieView->SetPath(path);
|
||||
fStatusView->SetBtnLabel(kStrRescan);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeView::MessageReceived(BMessage* msg)
|
||||
{
|
||||
msg->PrintToStream();
|
||||
switch(msg->what) {
|
||||
case kBtnRescan:
|
||||
fPieView->MessageReceived(msg);
|
||||
fStatusView->SetBtnLabel(kStrRescan);
|
||||
break;
|
||||
|
||||
default:
|
||||
BView::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VolumeView::ShowInfo(const FileInfo* info)
|
||||
{
|
||||
fStatusView->ShowInfo(info);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe Saint-Pierre, stpere@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Copyright (c) 1999 Mike Steed. You are free to use and distribute this software
|
||||
* as long as it is accompanied by it's documentation and this copyright notice.
|
||||
* The software comes with no warranty, etc.
|
||||
*/
|
||||
|
||||
#ifndef VOLUMETAB_VIEW_H
|
||||
#define VOLUMETAB_VIEW_H
|
||||
|
||||
#include <View.h>
|
||||
|
||||
class BButton;
|
||||
class BPath;
|
||||
class BStringView;
|
||||
class BVolume;
|
||||
class PieView;
|
||||
class MainWindow;
|
||||
class StatusView;
|
||||
|
||||
struct FileInfo;
|
||||
|
||||
|
||||
class VolumeView: public BView {
|
||||
|
||||
public:
|
||||
VolumeView(const char* name, BVolume* volume);
|
||||
virtual ~VolumeView();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
void SetRescanEnabled(bool enabled);
|
||||
void SetPath(BPath path);
|
||||
void ShowInfo(const FileInfo* info);
|
||||
|
||||
private:
|
||||
PieView* fPieView;
|
||||
StatusView* fStatusView;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user