/* * Copyright (C) 2019-2020 Adrien Destugues * * Distributed under terms of the MIT license. */ #include "AttributesView.h" #include #include #include #include #include #include #include #include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "AttributesView" int kValueColumn = 1; int kTypeColumn = 2; AttributesView::AttributesView(Model* model) : BGroupView(B_VERTICAL, 0), fListView(new BColumnListView("attrs", 0, B_PLAIN_BORDER, false)) { SetName(B_TRANSLATE("Attributes")); AddChild(fListView); GroupLayout()->SetInsets(-1, -1, -1, -1); float nameWidth = StringWidth("SYS:PACKAGE_FILE") + 16; float typeMaxWidth = StringWidth(B_TRANSLATE( "Double-precision floating point number")) + 16; float typeWidth = StringWidth(B_TRANSLATE("64-bit unsigned integer")) + 16; float valueMaxWidth = StringWidth("W") * 64 + 16; float valueWidth = StringWidth("(94.00, 95.00) (1920, 1080)") + 16; BStringColumn* nameColumn = new BStringColumn(B_TRANSLATE("Name"), nameWidth, nameWidth, nameWidth, 0); BStringColumn* typeColumn = new BStringColumn(B_TRANSLATE("Type"), typeWidth, typeWidth, typeMaxWidth, 0); BStringColumn* valueColumn = new BStringColumn(B_TRANSLATE("Value"), valueWidth, valueWidth, valueMaxWidth, 0); fListView->AddColumn(nameColumn, 0); fListView->AddColumn(valueColumn, 1); fListView->AddColumn(typeColumn, 2); SetExplicitMinSize(BSize(typeWidth + valueWidth + nameWidth + 40, B_SIZE_UNSET)); BNode* node = model->Node(); node->RewindAttrs(); char name[B_ATTR_NAME_LENGTH]; // Initialize formatters only once for all attributes BDateTimeFormat dateTimeFormatter; BStringFormat multiValueFormat(B_TRANSLATE( "{0, plural, other{<# values>}}")); while (node->GetNextAttrName(name) == B_OK) { // Skip well-known attributes already shown elsewhere in the window if (strcmp(name, "BEOS:TYPE") == 0) continue; attr_info info; node->GetAttrInfo(name, &info); BRow* row = new BRow; row->SetField(new BStringField(name), 0); BString representation; switch(info.type) { case B_STRING_TYPE: case B_MIME_STRING_TYPE: case 'MSIG': case 'MSDC': case 'MPTH': { // Use a small buffer, long strings will be truncated char buffer[64]; ssize_t size = node->ReadAttr(name, info.type, 0, buffer, sizeof(buffer)); if (size > 0) representation.SetTo(buffer, size); break; } case B_BOOL_TYPE: { if (info.size == sizeof(bool)) { bool value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation = value ? B_TRANSLATE("yes") : B_TRANSLATE("no"); } else { multiValueFormat.Format(representation, info.size / sizeof(bool)); } break; } case B_INT16_TYPE: { if (info.size == sizeof(int16)) { int16 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRId16, value); } else { multiValueFormat.Format(representation, info.size / sizeof(int16)); } break; } case B_INT32_TYPE: { if (info.size == sizeof(int32)) { int32 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRId32, value); } else { multiValueFormat.Format(representation, info.size / sizeof(int32)); } break; } case B_INT64_TYPE: { if (info.size == sizeof(int64)) { int64 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRId64, value); } else { multiValueFormat.Format(representation, info.size / sizeof(int64)); } break; } case B_INT8_TYPE: { if (info.size == sizeof(int8)) { int8 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRId8, value); } else { multiValueFormat.Format(representation, info.size / sizeof(int8)); } break; } case B_RECT_TYPE: { if (info.size == sizeof(BRect)) { BRect value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("(%g,%g) (%g,%g)", value.left, value.top, value.right, value.bottom); } else { BStringFormat multiRectFormat(B_TRANSLATE( "{0, plural, other{<# rectangles>}}")); multiRectFormat.Format(representation, info.size / sizeof(BRect)); } break; } case B_DOUBLE_TYPE: { if (info.size == sizeof(double)) { double value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%f", value); } else { multiValueFormat.Format(representation, info.size / sizeof(double)); } break; } case B_FLOAT_TYPE: { if (info.size == sizeof(float)) { float value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%f", value); } else { multiValueFormat.Format(representation, info.size / sizeof(float)); } break; } case B_TIME_TYPE: { // Try to handle attributes written on both 32 and 64bit systems if (info.size == sizeof(int32)) { int32 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); dateTimeFormatter.Format(representation, value, B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT); } else if (info.size == sizeof(int64)) { int64 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); dateTimeFormatter.Format(representation, value, B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT); } else { BStringFormat multiDateFormat(B_TRANSLATE( "{0, plural, other{<# dates>}}")); multiDateFormat.Format(representation, info.size / sizeof(time_t)); } break; } case B_UINT16_TYPE: { if (info.size == sizeof(uint16)) { uint16 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRIu16, value); } else { multiValueFormat.Format(representation, info.size / sizeof(uint16)); } break; } case B_UINT32_TYPE: { if (info.size == sizeof(uint32)) { uint32 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRIu32, value); } else { multiValueFormat.Format(representation, info.size / sizeof(uint32)); } break; } case B_UINT64_TYPE: { if (info.size == sizeof(uint64)) { uint64 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRIu64, value); } else { multiValueFormat.Format(representation, info.size / sizeof(uint64)); } break; } case B_UINT8_TYPE: { if (info.size == sizeof(uint8)) { uint8 value; node->ReadAttr(name, info.type, 0, &value, sizeof(value)); representation.SetToFormat("%" B_PRIu8, value); } else { multiValueFormat.Format(representation, info.size / sizeof(uint8)); } break; } default: { BStringFormat sizeFormat(B_TRANSLATE( "{0, plural, one{<# data byte>} other{<# bytes of data>}}")); sizeFormat.Format(representation, info.size); break; } } row->SetField(new BStringField(representation), kValueColumn); switch(info.type) { case B_AFFINE_TRANSFORM_TYPE: row->SetField(new BStringField(B_TRANSLATE("Affine transform")), kTypeColumn); break; case B_ALIGNMENT_TYPE: row->SetField(new BStringField(B_TRANSLATE("Alignment")), kTypeColumn); break; case B_ANY_TYPE: row->SetField(new BStringField(B_TRANSLATE("Any")), kTypeColumn); break; case B_ATOM_TYPE: row->SetField(new BStringField(B_TRANSLATE("Atom")), kTypeColumn); break; case B_ATOMREF_TYPE: row->SetField(new BStringField(B_TRANSLATE("Atom reference")), kTypeColumn); break; case B_BOOL_TYPE: row->SetField(new BStringField(B_TRANSLATE("Boolean")), kTypeColumn); break; case B_CHAR_TYPE: row->SetField(new BStringField(B_TRANSLATE("Character")), kTypeColumn); break; case B_COLOR_8_BIT_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Palette-indexed picture")), kTypeColumn); break; case B_DOUBLE_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Double-precision floating point number")), kTypeColumn); break; case B_FLOAT_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Floating point number")), kTypeColumn); break; case B_GRAYSCALE_8_BIT_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Grayscale picture")), kTypeColumn); break; case B_INT16_TYPE: row->SetField(new BStringField(B_TRANSLATE("16-bit integer")), kTypeColumn); break; case B_INT32_TYPE: row->SetField(new BStringField(B_TRANSLATE("32-bit integer")), kTypeColumn); break; case B_INT64_TYPE: row->SetField(new BStringField(B_TRANSLATE("64-bit integer")), kTypeColumn); break; case B_INT8_TYPE: row->SetField(new BStringField(B_TRANSLATE("8-bit integer")), kTypeColumn); break; case B_LARGE_ICON_TYPE: row->SetField(new BStringField(B_TRANSLATE("Bitmap icon")), kTypeColumn); break; case B_MEDIA_PARAMETER_GROUP_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Media parameter group")), kTypeColumn); break; case B_MEDIA_PARAMETER_TYPE: row->SetField(new BStringField(B_TRANSLATE("Media parameter")), kTypeColumn); break; case B_MEDIA_PARAMETER_WEB_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Media parameter web")), kTypeColumn); break; case B_MESSAGE_TYPE: row->SetField(new BStringField(B_TRANSLATE("Message")), kTypeColumn); break; case B_MESSENGER_TYPE: row->SetField(new BStringField(B_TRANSLATE("Messenger")), kTypeColumn); break; case B_MIME_TYPE: row->SetField(new BStringField(B_TRANSLATE("MIME Type")), kTypeColumn); break; case B_MINI_ICON_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Small bitmap icon")), kTypeColumn); break; case B_MONOCHROME_1_BIT_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Monochrome picture")), kTypeColumn); break; case B_OBJECT_TYPE: row->SetField(new BStringField(B_TRANSLATE("Object")), kTypeColumn); break; case B_OFF_T_TYPE: row->SetField(new BStringField(B_TRANSLATE("File offset")), kTypeColumn); break; case B_PATTERN_TYPE: row->SetField(new BStringField(B_TRANSLATE("Drawing pattern")), kTypeColumn); break; case B_POINTER_TYPE: row->SetField(new BStringField(B_TRANSLATE("Memory pointer")), kTypeColumn); break; case B_POINT_TYPE: row->SetField(new BStringField(B_TRANSLATE("Point")), kTypeColumn); break; case B_PROPERTY_INFO_TYPE: row->SetField(new BStringField(B_TRANSLATE("Property info")), kTypeColumn); break; case B_RAW_TYPE: row->SetField(new BStringField(B_TRANSLATE("Raw data")), kTypeColumn); break; case B_RECT_TYPE: row->SetField(new BStringField(B_TRANSLATE("Rectangle")), kTypeColumn); break; case B_REF_TYPE: row->SetField(new BStringField(B_TRANSLATE("Entry ref")), kTypeColumn); break; case B_NODE_REF_TYPE: row->SetField(new BStringField(B_TRANSLATE("Node ref")), kTypeColumn); break; case B_RGB_32_BIT_TYPE: row->SetField(new BStringField(B_TRANSLATE( "True-color picture")), kTypeColumn); break; case B_RGB_COLOR_TYPE: row->SetField(new BStringField(B_TRANSLATE("Color")), kTypeColumn); break; case B_SIZE_TYPE: row->SetField(new BStringField(B_TRANSLATE("Geometric size")), kTypeColumn); break; case B_SIZE_T_TYPE: row->SetField(new BStringField(B_TRANSLATE("Memory size")), kTypeColumn); break; case B_SSIZE_T_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Signed memory size")), kTypeColumn); break; case B_STRING_TYPE: row->SetField(new BStringField(B_TRANSLATE("Plain text")), kTypeColumn); break; case B_STRING_LIST_TYPE: row->SetField(new BStringField(B_TRANSLATE("Text list")), kTypeColumn); break; case B_TIME_TYPE: row->SetField(new BStringField(B_TRANSLATE("Time")), kTypeColumn); break; case B_UINT16_TYPE: row->SetField(new BStringField(B_TRANSLATE( "16-bit unsigned integer")), kTypeColumn); break; case B_UINT32_TYPE: row->SetField(new BStringField(B_TRANSLATE( "32-bit unsigned integer")), kTypeColumn); break; case B_UINT64_TYPE: row->SetField(new BStringField(B_TRANSLATE( "64-bit unsigned integer")), kTypeColumn); break; case B_UINT8_TYPE: row->SetField(new BStringField(B_TRANSLATE( "8-bit unsigned integer")), kTypeColumn); break; case B_VECTOR_ICON_TYPE: row->SetField(new BStringField(B_TRANSLATE("Icon")), kTypeColumn); break; case B_XATTR_TYPE: row->SetField(new BStringField(B_TRANSLATE( "Extended attribute")), kTypeColumn); break; case B_NETWORK_ADDRESS_TYPE: row->SetField(new BStringField(B_TRANSLATE("Network address")), kTypeColumn); break; case B_MIME_STRING_TYPE: row->SetField(new BStringField(B_TRANSLATE("MIME String")), kTypeColumn); break; case 'MSIG': row->SetField(new BStringField(B_TRANSLATE("MIME Signature")), kTypeColumn); break; case 'MSDC': row->SetField(new BStringField(B_TRANSLATE("MIME Description")), kTypeColumn); break; case 'MPTH': row->SetField(new BStringField(B_TRANSLATE("MIME Path")), kTypeColumn); break; case B_ASCII_TYPE: row->SetField(new BStringField(B_TRANSLATE("ASCII Text")), kTypeColumn); break; default: row->SetField(new BStringField(B_TRANSLATE("(unknown)")), kTypeColumn); break; } fListView->AddRow(row); } int32 rows = fListView->CountRows(NULL); if (rows < 5) rows = 5; BRow* first = fListView->RowAt(0, NULL); if (first != NULL) { float height = first->Height() * (rows + 2); SetExplicitMaxSize(BSize(B_SIZE_UNSET, height)); } }