* 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
This commit is contained in:
Axel Dörfler 2007-06-26 17:43:55 +00:00
parent 985d6b5437
commit eeb608e1c7
7 changed files with 164 additions and 92 deletions

View File

@ -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<BSeparatorItem *>(menu->ItemAt(removeIndex)) == NULL)
removeIndex--;
}
// Add a separator item if there is none yet
if (dynamic_cast<BSeparatorItem *>(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;

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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);
}

View File

@ -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<int32>(fAttrHash));
message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType));
if (fDisplayAs.Length() > 0)
message.AddString(kColumnDisplayAsName, fDisplayAs.String());
message.AddBool(kColumnStatFieldName, fStatField);
message.AddBool(kColumnEditableName, fEditable);
}

View File

@ -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
{