From eeb608e1c7a4655b1e15f3333b9b3f7ef5a83795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 26 Jun 2007 17:43:55 +0000 Subject: [PATCH] * StringFromStream() did not work correctly for empty strings (messed up the stream position). * StringFromStream() called BString::LockBuffer() with "length", but touched "length + 1" bytes. * Prepared for the new "display as" FileTypes feature. * The "DefaultQueryTemplate" folder now adds the MIME type of the folder to the attribute menu for simplified editing (before, you had to move a file with a matching file type into that folder to be able to add the attributes you likely wanted to see). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21509 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/tracker/ContainerWindow.cpp | 120 +++++++++++++++------------ src/kits/tracker/ContainerWindow.h | 7 +- src/kits/tracker/PoseView.cpp | 7 +- src/kits/tracker/PoseView.h | 4 +- src/kits/tracker/Utilities.cpp | 19 ++--- src/kits/tracker/ViewState.cpp | 75 ++++++++++++----- src/kits/tracker/ViewState.h | 24 ++++-- 7 files changed, 164 insertions(+), 92 deletions(-) diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index 26ff8d737b..5ae3617a1d 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -78,6 +78,7 @@ All rights reserved. #include "Navigator.h" #include "NavMenu.h" #include "PoseView.h" +#include "QueryContainerWindow.h" #include "SelectionWindow.h" #include "TitleView.h" #include "Tracker.h" @@ -2966,18 +2967,30 @@ BContainerWindow::LoadAddOn(BMessage *message) } -BMenuItem * -BContainerWindow::NewAttributeMenuItem(const char *label, const char *attrName, - int32 attrType, float attrWidth, int32 attrAlign, bool attrEditable, bool attrStatField) +BMenuItem * +BContainerWindow::NewAttributeMenuItem(const char *label, const char *name, + int32 type, float width, int32 align, bool editable, bool statField) +{ + return NewAttributeMenuItem(label, name, type, NULL, width, align, + editable, statField); +} + + +BMenuItem * +BContainerWindow::NewAttributeMenuItem(const char *label, const char *name, + int32 type, const char* displayAs, float width, int32 align, + bool editable, bool statField) { BMessage *message = new BMessage(kAttributeItem); - message->AddString("attr_name", attrName); - message->AddInt32("attr_type", attrType); - message->AddInt32("attr_hash", (int32)AttrHashString(attrName, (uint32)attrType)); - message->AddFloat("attr_width", attrWidth); - message->AddInt32("attr_align", attrAlign); - message->AddBool("attr_editable", attrEditable); - message->AddBool("attr_statfield", attrStatField); + message->AddString("attr_name", name); + message->AddInt32("attr_type", type); + message->AddInt32("attr_hash", (int32)AttrHashString(name, (uint32)type)); + message->AddFloat("attr_width", width); + message->AddInt32("attr_align", align); + if (displayAs != NULL) + message->AddString("attr_display_as", displayAs); + message->AddBool("attr_editable", editable); + message->AddBool("attr_statfield", statField); BMenuItem *menuItem = new BMenuItem(label, message); menuItem->SetTarget(PoseView()); @@ -3110,21 +3123,33 @@ BContainerWindow::AddMimeTypesToMenu(BMenu *menu) break; } - // Remove old mime menu: - int32 removeIndex = count - 1; - while (menu->ItemAt(removeIndex)->Submenu() != NULL) { + // Remove old mime menu: + int32 removeIndex = count - 1; + while (menu->ItemAt(removeIndex)->Submenu() != NULL) { delete menu->RemoveItem(removeIndex); - removeIndex--; - } - - // Add a separator item if there is none yet - if (dynamic_cast(menu->ItemAt(removeIndex)) == NULL) + removeIndex--; + } + + // Add a separator item if there is none yet + if (dynamic_cast(menu->ItemAt(removeIndex)) == NULL) menu->AddSeparatorItem(); + // Add MIME type in case we're a default query type window + BPath path; + if (TargetModel() != NULL) { + TargetModel()->GetPath(&path); + if (strstr(path.Path(), "/" kQueryTemplates "/") != NULL) { + // demangle MIME type name + BString name(TargetModel()->Name()); + name.ReplaceFirst('_', '/'); + + PoseView()->AddMimeType(name.String()); + } + } + int32 typeCount = PoseView()->CountMimeTypes(); for (int32 index = 0; index < typeCount; index++) { - bool shouldAdd = true; const char *signature = PoseView()->MimeTypeAt(index); @@ -3144,8 +3169,8 @@ BContainerWindow::AddMimeTypesToMenu(BMenu *menu) } if (shouldAdd) { - BMessage attr_msg; - char desc[B_MIME_TYPE_LENGTH]; + BMessage attrInfo; + char description[B_MIME_TYPE_LENGTH]; const char *nameToAdd = signature; BMimeType mimetype(signature); @@ -3154,43 +3179,39 @@ BContainerWindow::AddMimeTypesToMenu(BMenu *menu) continue; // only add things to menu which have "user-visible" data - if (mimetype.GetAttrInfo(&attr_msg) != B_OK) + if (mimetype.GetAttrInfo(&attrInfo) != B_OK) continue; - if (mimetype.GetShortDescription(desc) == B_OK && desc[0]) - nameToAdd = desc; + if (mimetype.GetShortDescription(description) == B_OK + && description[0]) + nameToAdd = description; - // go through each field in meta mime and add it to a menu + // go through each field in meta mime and add it to a menu BMenu *localMenu = 0; int32 index = -1; const char *str; - while (attr_msg.FindString("attr:public_name", ++index, &str) == B_OK) { - if (!attr_msg.FindBool("attr:viewable", index)) + while (attrInfo.FindString("attr:public_name", ++index, &str) == B_OK) { + if (!attrInfo.FindBool("attr:viewable", index)) { // don't add if attribute not viewable continue; - + } + int32 type; int32 align; int32 width; bool editable; - const char *attrName; - - if (attr_msg.FindString("attr:name", index, &attrName) != B_OK) + + if (attrInfo.FindString("attr:name", index, &attrName) != B_OK + || attrInfo.FindInt32("attr:type", index, &type) != B_OK + || attrInfo.FindBool("attr:editable", index, &editable) != B_OK + || attrInfo.FindInt32("attr:width", index, &width) != B_OK + || attrInfo.FindInt32("attr:alignment", index, &align) != B_OK) continue; - if (attr_msg.FindInt32("attr:type", index, &type) != B_OK) - continue; - - if (attr_msg.FindBool("attr:editable", index, &editable) != B_OK) - continue; - - if (attr_msg.FindInt32("attr:width", index, &width) != B_OK) - continue; - - if (attr_msg.FindInt32("attr:alignment", index, &align) != B_OK) - continue; + BString displayAs; + attrInfo.FindString("attr:display_as", index, &displayAs); if (!localMenu) { // do a lazy allocation of the menu @@ -3199,8 +3220,8 @@ BContainerWindow::AddMimeTypesToMenu(BMenu *menu) menu->GetFont(&font); localMenu->SetFont(&font); } - localMenu->AddItem(NewAttributeMenuItem (str, attrName, type, - width, align, editable, false)); + localMenu->AddItem(NewAttributeMenuItem(str, attrName, type, + displayAs.String(), width, align, editable, false)); } if (localMenu) { BMessage *message = new BMessage(kMIMETypeItem); @@ -3279,7 +3300,6 @@ BContainerWindow::DefaultStateSourceNode(const char *name, BNode *result, BPath path(settingsPath); path.Append(name); if (!BEntry(path.Path()).Exists()) { - if (!createNew) return false; @@ -3289,22 +3309,20 @@ BContainerWindow::DefaultStateSourceNode(const char *name, BNode *result, const char *nextSlash = strchr(name, '/'); if (!nextSlash) break; - + BString tmp; tmp.SetTo(name, nextSlash - name); tmpPath.Append(tmp.String()); - mkdir(tmpPath.Path(), 0777); - + name = nextSlash + 1; if (!name[0]) { // can't deal with a slash at end - return false; } } - + if (createFolder) { if (mkdir(path.Path(), 0777) < 0) return false; @@ -3314,7 +3332,7 @@ BContainerWindow::DefaultStateSourceNode(const char *name, BNode *result, return false; } } - + // PRINT(("using default state from %s\n", path.Path())); result->SetTo(path.Path()); return result->InitCheck() == B_OK; diff --git a/src/kits/tracker/ContainerWindow.h b/src/kits/tracker/ContainerWindow.h index 3dd2e1ae97..beddf8f97a 100644 --- a/src/kits/tracker/ContainerWindow.h +++ b/src/kits/tracker/ContainerWindow.h @@ -150,8 +150,11 @@ class BContainerWindow : public BWindow { void AddMimeTypesToMenu(); virtual void MarkAttributeMenu(BMenu *); void MarkAttributeMenu(); - BMenuItem *NewAttributeMenuItem (const char *label, const char *attrName, int32 attrType, - float attrWidth, int32 attrAlign, bool attrEditable, bool attrStatField); + BMenuItem *NewAttributeMenuItem(const char *label, const char *name, + int32 type, float width, int32 align, bool editable, bool statField); + BMenuItem *NewAttributeMenuItem(const char *label, const char *name, + int32 type, const char* displayAs, float width, int32 align, + bool editable, bool statField); virtual void NewAttributeMenu(BMenu *); void HideAttributeMenu(); diff --git a/src/kits/tracker/PoseView.cpp b/src/kits/tracker/PoseView.cpp index 0b4246b4e5..aa2221b7d5 100644 --- a/src/kits/tracker/PoseView.cpp +++ b/src/kits/tracker/PoseView.cpp @@ -1808,7 +1808,7 @@ BPoseView::RefreshMimeTypeList() if (pose->TargetModel()) AddMimeType(pose->TargetModel()->MimeType()); } -} +} void @@ -2505,8 +2505,11 @@ BPoseView::HandleAttrMenuItemSelected(BMessage *message) if (message->FindBool("attr_statfield", &isStatfield) != B_OK) return; + const char* displayAs; + message->FindString("attr_display_as", &displayAs); + column = new BColumn(item->Label(), 0, attrWidth, attrAlign, - attrName, attrType, isStatfield, isEditable); + attrName, attrType, displayAs, isStatfield, isEditable); AddColumn(column); if (item->Menu()->Supermenu() == NULL) delete item->Menu(); diff --git a/src/kits/tracker/PoseView.h b/src/kits/tracker/PoseView.h index efb832f235..0ca06b4a0c 100644 --- a/src/kits/tracker/PoseView.h +++ b/src/kits/tracker/PoseView.h @@ -315,7 +315,8 @@ class BPoseView : public BView { BRefFilter *RefFilter() const; // access for mime types represented in the pose view - const char *MimeTypeAt(int32); + void AddMimeType(const char* mimeType); + const char *MimeTypeAt(int32 index); int32 CountMimeTypes(); void RefreshMimeTypeList(); @@ -553,7 +554,6 @@ class BPoseView : public BView { virtual void EditQueries(); virtual void AddCountView(); - void AddMimeType(const char *); void HandleAttrMenuItemSelected(BMessage *); void TryUpdatingBrokenLinks(); // ran a little after a volume gets mounted diff --git a/src/kits/tracker/Utilities.cpp b/src/kits/tracker/Utilities.cpp index 92cacc0f05..9b94ab872d 100644 --- a/src/kits/tracker/Utilities.cpp +++ b/src/kits/tracker/Utilities.cpp @@ -127,14 +127,14 @@ AttrHashString(const char *string, uint32 type) bool ValidateStream(BMallocIO *stream, uint32 key, int32 version) { - uint32 test_key; - int32 test_version; + uint32 testKey; + int32 testVersion; - if (stream->Read(&test_key, sizeof(uint32)) <= 0 - || stream->Read(&test_version, sizeof(int32)) <=0) + if (stream->Read(&testKey, sizeof(uint32)) <= 0 + || stream->Read(&testVersion, sizeof(int32)) <=0) return false; - return test_key == key && test_version == version; + return testKey == key && testVersion == version; } @@ -1075,14 +1075,13 @@ StringFromStream(BString *string, BMallocIO *stream, bool endianSwap) if (endianSwap) length = SwapInt32(length); - if (length <= 0 || length > 10000) { - // ToDo: - // should fail here + if (length < 0 || length > 10000) { + // TODO: should fail here PRINT(("problems instatiating a string, length probably wrong %d\n", length)); return; - } + } - char *buffer = string->LockBuffer(length); + char *buffer = string->LockBuffer(length + 1); stream->Read(buffer, (size_t)length + 1); string->UnlockBuffer(length); } diff --git a/src/kits/tracker/ViewState.cpp b/src/kits/tracker/ViewState.cpp index e15b154380..4406c43fe4 100644 --- a/src/kits/tracker/ViewState.cpp +++ b/src/kits/tracker/ViewState.cpp @@ -55,6 +55,7 @@ const char *kColumnAlignmentName = "BColumn:fAlignment"; const char *kColumnAttrName = "BColumn:fAttrName"; const char *kColumnAttrHashName = "BColumn:fAttrHash"; const char *kColumnAttrTypeName = "BColumn:fAttrType"; +const char *kColumnDisplayAsName = "BColumn:fDisplayAs"; const char *kColumnStatFieldName = "BColumn:fStatField"; const char *kColumnEditableName = "BColumn:fEditable"; @@ -71,20 +72,25 @@ const char *kViewStateReverseSortName = "ViewState:fReverseSort"; const char *kViewStateIconSizeName = "ViewState:fIconSize"; -BColumn::BColumn(const char *title, float offset, float width, alignment align, - const char *attributeName, uint32 attrType, bool statField, - bool editable) - : - fTitle(title), - fAttrName(attributeName) +static const int32 kColumnStateMinArchiveVersion = 21; + // bump version when layout changes + + +BColumn::BColumn(const char *title, float offset, float width, + alignment align, const char *attributeName, uint32 attrType, + const char* displayAs, bool statField, bool editable) { - fOffset = offset; - fWidth = width; - fAlignment = align; - fAttrHash = AttrHashString(attributeName, attrType); - fAttrType = attrType; - fStatField = statField; - fEditable = editable; + _Init(title, offset, width, align, attributeName, attrType, displayAs, + statField, editable); +} + + +BColumn::BColumn(const char *title, float offset, float width, + alignment align, const char *attributeName, uint32 attrType, + bool statField, bool editable) +{ + _Init(title, offset, width, align, attributeName, attrType, NULL, + statField, editable); } @@ -93,7 +99,7 @@ BColumn::~BColumn() } -BColumn::BColumn(BMallocIO *stream, bool endianSwap) +BColumn::BColumn(BMallocIO *stream, int32 version, bool endianSwap) { StringFromStream(&fTitle, stream, endianSwap); stream->Read(&fOffset, sizeof(float)); @@ -104,7 +110,9 @@ BColumn::BColumn(BMallocIO *stream, bool endianSwap) stream->Read(&fAttrType, sizeof(uint32)); stream->Read(&fStatField, sizeof(bool)); stream->Read(&fEditable, sizeof(bool)); - + if (version == kColumnStateArchiveVersion) + StringFromStream(&fDisplayAs, stream, endianSwap); + if (endianSwap) { PRINT(("endian swapping column\n")); fOffset = B_SWAP_FLOAT(fOffset); @@ -126,29 +134,53 @@ BColumn::BColumn(const BMessage &message, int32 index) message.FindString(kColumnAttrName, index, &fAttrName); message.FindInt32(kColumnAttrHashName, index, (int32 *)&fAttrHash); message.FindInt32(kColumnAttrTypeName, index, (int32 *)&fAttrType); + message.FindString(kColumnDisplayAsName, index, &fDisplayAs); message.FindBool(kColumnStatFieldName, index, &fStatField); message.FindBool(kColumnEditableName, index, &fEditable); } +void +BColumn::_Init(const char *title, float offset, float width, + alignment align, const char *attributeName, uint32 attrType, + const char* displayAs, bool statField, bool editable) +{ + fTitle = title; + fAttrName = attributeName; + fDisplayAs = displayAs; + fOffset = offset; + fWidth = width; + fAlignment = align; + fAttrHash = AttrHashString(attributeName, attrType); + fAttrType = attrType; + fStatField = statField; + fEditable = editable; +} + + BColumn * BColumn::InstantiateFromStream(BMallocIO *stream, bool endianSwap) { // compare stream header in canonical form - uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE); - int32 version = kColumnStateArchiveVersion; + + // we can't use ValidateStream(), as we preserve backwards compatibility + int32 version; + uint32 key; + if (stream->Read(&key, sizeof(uint32)) <= 0 + || stream->Read(&version, sizeof(int32)) <=0) + return 0; if (endianSwap) { key = SwapUInt32(key); version = SwapInt32(version); } -// PRINT(("validating key %x, version %d\n", key, version)); - if (!ValidateStream(stream, key, version)) + if (key != AttrHashString("BColumn", B_OBJECT_TYPE) + || version < kColumnStateMinArchiveVersion) return 0; // PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : "")); - return _Sanitize(new (std::nothrow) BColumn(stream, endianSwap)); + return _Sanitize(new (std::nothrow) BColumn(stream, version, endianSwap)); } @@ -188,6 +220,7 @@ BColumn::ArchiveToStream(BMallocIO *stream) const stream->Write(&fAttrType, sizeof(uint32)); stream->Write(&fStatField, sizeof(bool)); stream->Write(&fEditable, sizeof(bool)); + StringToStream(&fDisplayAs, stream); } @@ -203,6 +236,8 @@ BColumn::ArchiveToMessage(BMessage &message) const message.AddString(kColumnAttrName, fAttrName); message.AddInt32(kColumnAttrHashName, static_cast(fAttrHash)); message.AddInt32(kColumnAttrTypeName, static_cast(fAttrType)); + if (fDisplayAs.Length() > 0) + message.AddString(kColumnDisplayAsName, fDisplayAs.String()); message.AddBool(kColumnStatFieldName, fStatField); message.AddBool(kColumnEditableName, fEditable); } diff --git a/src/kits/tracker/ViewState.h b/src/kits/tracker/ViewState.h index 1929d3cd95..1d18771373 100644 --- a/src/kits/tracker/ViewState.h +++ b/src/kits/tracker/ViewState.h @@ -41,17 +41,20 @@ All rights reserved. namespace BPrivate { -const int32 kColumnStateArchiveVersion = 21; +const int32 kColumnStateArchiveVersion = 22; // bump version when layout or size changes class BColumn { public: + BColumn(const char *title, float offset, float width, + alignment align, const char *attributeName, uint32 attrType, + const char* displayAs, bool statField, bool editable); BColumn(const char *title, float offset, float width, alignment align, const char *attributeName, uint32 attrType, bool statField, bool editable); ~BColumn(); - BColumn(BMallocIO *stream, bool endianSwap = false); + BColumn(BMallocIO *stream, int32 version, bool endianSwap = false); BColumn(const BMessage &, int32 index = 0); static BColumn *InstantiateFromStream(BMallocIO *stream, bool endianSwap = false); @@ -60,12 +63,13 @@ class BColumn { void ArchiveToStream(BMallocIO *stream) const; void ArchiveToMessage(BMessage &) const; - const char *Title() const; + const char* Title() const; float Offset() const; float Width() const; alignment Alignment() const; - const char *AttrName() const; + const char* AttrName() const; uint32 AttrType() const; + const char* DisplayAs() const; uint32 AttrHash() const; bool StatField() const; bool Editable() const; @@ -74,13 +78,17 @@ class BColumn { void SetWidth(float); private: - static BColumn *_Sanitize(BColumn *column); + void _Init(const char *title, float offset, float width, + alignment align, const char *attributeName, uint32 attrType, + const char* displayAs, bool statField, bool editable); + static BColumn* _Sanitize(BColumn* column); BString fTitle; float fOffset; float fWidth; alignment fAlignment; BString fAttrName; + BString fDisplayAs; uint32 fAttrHash; uint32 fAttrType; bool fStatField; @@ -186,6 +194,12 @@ BColumn::AttrType() const return fAttrType; } +inline const char * +BColumn::DisplayAs() const +{ + return fDisplayAs.String(); +} + inline bool BColumn::StatField() const {