diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index d8ad1abd5c..c099a86e86 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -2679,32 +2679,10 @@ FSGetTrashDir(BDirectory* trashDir, dev_t dev) PoseInfo poseInfo; poseInfo.fInvisible = true; poseInfo.fInitedDirectory = sbuf.st_ino; - trashDir->WriteAttr(kAttrPoseInfo, B_RAW_TYPE, 0, &poseInfo, - sizeof(PoseInfo)); + trashDir->WriteAttr(kAttrPoseInfo, B_RAW_TYPE, 0, &poseInfo, sizeof(PoseInfo)); } - // set Trash icons (if they haven't already been set) - attr_info attrInfo; - size_t size; - const void* data; - if (trashDir->GetAttrInfo(kAttrLargeIcon, &attrInfo) == B_ENTRY_NOT_FOUND) { - data = GetTrackerResources()->LoadResource('ICON', R_TrashIcon, &size); - if (data != NULL) - trashDir->WriteAttr(kAttrLargeIcon, 'ICON', 0, data, size); - } - - if (trashDir->GetAttrInfo(kAttrMiniIcon, &attrInfo) == B_ENTRY_NOT_FOUND) { - data = GetTrackerResources()->LoadResource('MICN', R_TrashIcon, &size); - if (data != NULL) - trashDir->WriteAttr(kAttrMiniIcon, 'MICN', 0, data, size); - } - - if (trashDir->GetAttrInfo(kAttrIcon, &attrInfo) == B_ENTRY_NOT_FOUND) { - data = GetTrackerResources()->LoadResource(B_VECTOR_ICON_TYPE, - R_TrashIcon, &size); - if (data != NULL) - trashDir->WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0, data, size); - } + // icon attributes set by TrashWatcher return B_OK; } @@ -3233,7 +3211,7 @@ FSCreateTrashDirs() roster.Rewind(); while (roster.GetNextVolume(&volume) == B_OK) { - if (volume.IsReadOnly() || !volume.IsPersistent()) + if (volume.IsReadOnly() || !volume.IsPersistent() || volume.Capacity() == 0) continue; BDirectory trashDir; diff --git a/src/kits/tracker/Model.cpp b/src/kits/tracker/Model.cpp index cacdcd16c9..ac5f906668 100644 --- a/src/kits/tracker/Model.cpp +++ b/src/kits/tracker/Model.cpp @@ -727,16 +727,6 @@ Model::FinishSettingUpType() } -bool -Model::ShouldUseWellKnownIcon() const -{ - if (fBaseType == kDirectoryNode || fBaseType == kVolumeNode - || fBaseType == kTrashNode || fBaseType == kDesktopNode) - return !CheckAppIconHint(); - return false; -} - - bool Model::CheckAppIconHint() const { @@ -770,7 +760,14 @@ Model::ResetIconFrom() if (InitCheck() != B_OK) return; - if (ShouldUseWellKnownIcon()) { + bool hasAttrIcon = CheckAppIconHint(); + + if (hasAttrIcon && (fBaseType == kDesktopNode || fBaseType == kTrashNode)) { + // Desktop or Trash with an icon attribute + fIconFrom = kNode; + return; + } else if (!hasAttrIcon && (fBaseType == kDirectoryNode || fBaseType == kVolumeNode)) { + // No icon attribute override, check if well-known or root directory BDirectory* directory = dynamic_cast(fNode); if (WellKnowEntryList::Match(NodeRef()) > (directory_which)-1) { fIconFrom = kTrackerSupplied; @@ -780,6 +777,7 @@ Model::ResetIconFrom() return; } } + fIconFrom = kUnknownSource; } @@ -966,6 +964,9 @@ Model::AttrChanged(const char* attrName) bool Model::StatChanged() { + if (fNode == NULL) + return false; + ASSERT(IsNodeOpen()); mode_t oldMode = fStatBuf.st_mode; fStatus = fNode->GetStat(&fStatBuf); diff --git a/src/kits/tracker/Model.h b/src/kits/tracker/Model.h index 333f75f70c..cd1210f047 100644 --- a/src/kits/tracker/Model.h +++ b/src/kits/tracker/Model.h @@ -215,7 +215,6 @@ private: status_t OpenNodeCommon(bool writable); void SetupBaseType(); void FinishSettingUpType(); - bool ShouldUseWellKnownIcon() const; bool CheckAppIconHint() const; void DeletePreferredAppVolumeNameLinkTo(); void CacheLocalizedName(); diff --git a/src/kits/tracker/Pose.cpp b/src/kits/tracker/Pose.cpp index 410873adf1..c8152fb271 100644 --- a/src/kits/tracker/Pose.cpp +++ b/src/kits/tracker/Pose.cpp @@ -241,18 +241,18 @@ BPose::UpdateAllWidgets(int32, BPoint poseLoc, BPoseView* poseView) void -BPose::UpdateWidgetAndModel(Model* resolvedModel, const char* attrName, - uint32 attrType, int32, BPoint poseLoc, BPoseView* poseView, bool visible) +BPose::UpdateWidgetAndModel(const char* attrName, uint32 attrType, int32, BPoint poseLoc, + BPoseView* poseView, bool visible) { - if (poseView->ViewMode() != kListMode) - poseLoc = Location(poseView); - + Model* resolvedModel = ResolvedModel(); ASSERT(resolvedModel == NULL || resolvedModel->IsNodeOpen()); if (attrName != NULL) { // pick up new attributes and find out if icon needs updating - if (resolvedModel->AttrChanged(attrName) && visible) + if (visible && resolvedModel != NULL && resolvedModel->InitCheck() == B_OK + && resolvedModel->AttrChanged(attrName)) { UpdateIcon(poseLoc, poseView); + } // ToDo: the following code is wrong, because this sort of hashing // may overlap and we get aliasing @@ -280,12 +280,9 @@ BPose::UpdateWidgetAndModel(Model* resolvedModel, const char* attrName, // no attr name means check all widgets for stat info changes // pick up stat changes - if (resolvedModel && resolvedModel->StatChanged()) { - if (resolvedModel->InitCheck() != B_OK) - return; - - if (visible) - UpdateIcon(poseLoc, poseView); + if (visible && resolvedModel != NULL && resolvedModel->InitCheck() == B_OK + && resolvedModel->StatChanged()) { + UpdateIcon(poseLoc, poseView); } // distribute stat changes diff --git a/src/kits/tracker/Pose.h b/src/kits/tracker/Pose.h index 93347644f5..b5bccf3ad3 100644 --- a/src/kits/tracker/Pose.h +++ b/src/kits/tracker/Pose.h @@ -95,9 +95,8 @@ public: BRect CalcRect(BPoint loc, const BPoseView*, bool minimal_rect = false) const; BRect CalcRect(const BPoseView*) const; void UpdateAllWidgets(int32 poseIndex, BPoint poseLoc, BPoseView*); - void UpdateWidgetAndModel(Model* resolvedModel, const char* attrName, - uint32 attrType, int32 poseIndex, BPoint poseLoc, - BPoseView* view, bool visible); + void UpdateWidgetAndModel(const char* attrName, uint32 attrType, int32 poseIndex, + BPoint poseLoc, BPoseView* view, bool visible); bool UpdateVolumeSpaceBar(BVolume* volume); void UpdateIcon(BPoint poseLoc, BPoseView*); diff --git a/src/kits/tracker/PoseView.cpp b/src/kits/tracker/PoseView.cpp index d0e949b599..970e7ddb01 100644 --- a/src/kits/tracker/PoseView.cpp +++ b/src/kits/tracker/PoseView.cpp @@ -1797,15 +1797,16 @@ BPoseView::RemoveRootPose() void BPoseView::CreateTrashPose() { - BVolume volume; - if (BVolumeRoster().GetBootVolume(&volume) == B_OK) { + BVolume boot; + if (BVolumeRoster().GetBootVolume(&boot) == B_OK) { BDirectory trash; BEntry entry; - node_ref ref; - if (FSGetTrashDir(&trash, volume.Device()) == B_OK + node_ref nref; + if (FSGetTrashDir(&trash, boot.Device()) == B_OK && trash.GetEntry(&entry) == B_OK - && entry.GetNodeRef(&ref) == B_OK) { - WatchNewNode(&ref); + && entry.GetNodeRef(&nref) == B_OK) { + WatchNewNode(&nref, B_WATCH_ATTR, BMessenger(this)); + // redraw Trash icon when attribute changes Model* model = new Model(&entry); PoseInfo info; ReadPoseInfo(model, &info); @@ -5873,8 +5874,7 @@ BPoseView::AttributeChanged(const BMessage* message) if (result == B_OK || result != B_BUSY) break; - PRINT(("poseModel %s busy, retrying in a bit\n", - poseModel->Name())); + PRINT(("poseModel %s busy, retrying in a bit\n", poseModel->Name())); snooze(10000); } if (result != B_OK) { @@ -5888,18 +5888,50 @@ BPoseView::AttributeChanged(const BMessage* message) if (IsFiltering()) visible = fFilteredPoseList->FindPose(poseModel->NodeRef(), &index) != NULL; - BPoint loc(0, index * fListElemHeight); - if (attrName != NULL && poseModel->Node() != NULL) { + status_t infoStatus = B_ERROR; + if (attrName != NULL) { memset(&info, 0, sizeof(attr_info)); - // the call below might fail if the attribute has been removed - poseModel->Node()->GetAttrInfo(attrName, &info); - pose->UpdateWidgetAndModel(poseModel, attrName, info.type, index, loc, this, visible); + if (strcmp(attrName, kAttrIcon) == 0 + || strcmp(attrName, kAttrLargeIcon) == 0 + || strcmp(attrName, kAttrMiniIcon) == 0 + || strcmp(attrName, kAttrThumbnail) == 0) { + // set icon type manually in case attribute was removed + if (strcmp(attrName, kAttrIcon) == 0) + info.type = B_VECTOR_ICON_TYPE; + else if (strcmp(attrName, kAttrLargeIcon) == 0) + info.type = 'ICON'; + else if (strcmp(attrName, kAttrMiniIcon) == 0) + info.type = 'MICN'; + else if (strcmp(attrName, kAttrThumbnail) == 0) + info.type = B_RAW_TYPE; + + info.size = 0; + // old size not needed, writing new attr + infoStatus = B_OK; + } else if (poseModel->Node() != NULL) { + // the call below might fail if the attribute has been removed + infoStatus = poseModel->Node()->GetAttrInfo(attrName, &info); + } + } + + BPoint poseLoc; + if (ViewMode() == kListMode) + poseLoc.Set(0, index * fListElemHeight); + else + poseLoc = pose->Location(this); + + if (attrName != NULL) { + // update attr + pose->UpdateWidgetAndModel(attrName, infoStatus == B_OK ? info.type : 0, + index, poseLoc, this, visible); if (strcmp(attrName, kAttrMIMEType) == 0) RefreshMimeTypeList(); } else { - pose->UpdateWidgetAndModel(poseModel, 0, 0, index, loc, this, visible); + // update stat + pose->UpdateWidgetAndModel(0, 0, index, poseLoc, this, visible); } poseModel->CloseNode(); + if (IsFiltering()) { if (!visible && FilterPose(pose)) { visible = true; diff --git a/src/kits/tracker/Tracker.cpp b/src/kits/tracker/Tracker.cpp index a01afe078f..7612a51d04 100644 --- a/src/kits/tracker/Tracker.cpp +++ b/src/kits/tracker/Tracker.cpp @@ -296,6 +296,9 @@ TTracker::TTracker() // init Desktop now that pose view is created and window is locked deskWindow->Init(); + + // create this before ReadyToRun() so that the Trash icon gets set + fTrashWatcher = new BTrashWatcher(); } @@ -1550,7 +1553,6 @@ TTracker::ReadyToRun() InstallIndices(); InstallTemporaryBackgroundImages(); - fTrashWatcher = new BTrashWatcher(); fTrashWatcher->Run(); fClipboardRefsWatcher = new BClipboardRefsWatcher(); diff --git a/src/kits/tracker/TrashWatcher.cpp b/src/kits/tracker/TrashWatcher.cpp index 847efa816e..a814a92de0 100644 --- a/src/kits/tracker/TrashWatcher.cpp +++ b/src/kits/tracker/TrashWatcher.cpp @@ -154,25 +154,28 @@ BTrashWatcher::MessageReceived(BMessage* message) void BTrashWatcher::UpdateTrashIcons() { - BVolumeRoster roster; - BVolume volume; - roster.Rewind(); - + // only update Trash icon attributes on boot volume + BVolume boot; BDirectory trashDir; - while (roster.GetNextVolume(&volume) == B_OK) { - if (FSGetTrashDir(&trashDir, volume.Device()) == B_OK) { - // pull out the icons for the current trash state from resources - // and apply them onto the trash directory node - size_t vectorSize = 0; - const void* vectorData = GetTrackerResources()->LoadResource( - B_VECTOR_ICON_TYPE, - fTrashFull ? R_TrashFullIcon : R_TrashIcon, &vectorSize); + if (BVolumeRoster().GetBootVolume(&boot) == B_OK + && FSGetTrashDir(&trashDir, boot.Device()) == B_OK) { + // pull out the icons for the current trash state from resources + // and apply them onto the trash directory node + int32 id = fTrashFull ? R_TrashFullIcon : R_TrashIcon; + size_t size = 0; + const void* data = GetTrackerResources()->LoadResource(B_VECTOR_ICON_TYPE, id, &size); + if (data != NULL && size > 0) { + // write vector icon attribute + trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0, data, size); + } else { + // write large and mini icon attributes + data = GetTrackerResources()->LoadResource('ICON', id, &size); + if (data != NULL && size > 0) + trashDir.WriteAttr(kAttrLargeIcon, 'ICON', 0, data, size); - if (vectorData) { - trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0, - vectorData, vectorSize); - } else - TRESPASS(); + data = GetTrackerResources()->LoadResource('MICN', id, &size); + if (data != NULL && size > 0) + trashDir.WriteAttr(kAttrMiniIcon, 'MICN', 0, data, size); } } } @@ -206,7 +209,7 @@ BTrashWatcher::CheckTrashDirs() volRoster.Rewind(); BVolume volume; while (volRoster.GetNextVolume(&volume) == B_OK) { - if (volume.IsReadOnly() || !volume.IsPersistent()) + if (volume.IsReadOnly() || !volume.IsPersistent() || volume.Capacity() == 0) continue; BDirectory trashDir;