1 /* 2 * Copyright (C) 2019 Adrien Destugues <pulkomandy@pulkomandy.tk> 3 * 4 * Distributed under terms of the MIT license. 5 */ 6 7 #include "AttributesView.h" 8 9 #include <Catalog.h> 10 #include <ColumnListView.h> 11 #include <ColumnTypes.h> 12 #include <DateTimeFormat.h> 13 #include <FormattingConventions.h> 14 #include <fs_attr.h> 15 #include <Node.h> 16 17 18 #undef B_TRANSLATION_CONTEXT 19 #define B_TRANSLATION_CONTEXT "AttributesView" 20 21 int kValueColumn = 1; 22 int kTypeColumn = 2; 23 24 25 AttributesView::AttributesView(Model* model) 26 : 27 BGroupView(B_VERTICAL, 0), 28 fListView(new BColumnListView("attrs", 0, B_PLAIN_BORDER, false)) 29 { 30 SetName(B_TRANSLATE("Attributes")); 31 AddChild(fListView); 32 33 float nameWidth = StringWidth("SYS:PACKAGE_FILE") + 16; 34 float typeMaxWidth = StringWidth(B_TRANSLATE( 35 "Double-precision floating point number")) + 16; 36 float typeWidth = StringWidth(B_TRANSLATE("64-bit unsigned integer")) + 16; 37 float valueMaxWidth = StringWidth("W") * 64 + 16; 38 float valueWidth = StringWidth("(94.00, 95.00) (1920, 1080)") + 16; 39 BStringColumn* nameColumn = new BStringColumn(B_TRANSLATE("Name"), 40 nameWidth, nameWidth, nameWidth, 0); 41 BStringColumn* typeColumn = new BStringColumn(B_TRANSLATE("Type"), 42 typeWidth, typeWidth, typeMaxWidth, 0); 43 BStringColumn* valueColumn = new BStringColumn(B_TRANSLATE("Value"), 44 valueWidth, valueWidth, valueMaxWidth, 0); 45 46 fListView->AddColumn(nameColumn, 0); 47 fListView->AddColumn(valueColumn, 1); 48 fListView->AddColumn(typeColumn, 2); 49 50 SetExplicitMinSize(BSize(typeWidth + valueWidth + nameWidth + 40, 51 B_SIZE_UNSET)); 52 53 BNode* node = model->Node(); 54 55 node->RewindAttrs(); 56 char name[B_ATTR_NAME_LENGTH]; 57 BDateTimeFormat dateTimeFormatter; 58 // Initialize only once for all attributes 59 while (node->GetNextAttrName(name) == B_OK) { 60 // Skip well-known attributes already shown elsewhere in the window 61 if (strcmp(name, "BEOS:TYPE") == 0) 62 continue; 63 64 attr_info info; 65 node->GetAttrInfo(name, &info); 66 BRow* row = new BRow; 67 row->SetField(new BStringField(name), 0); 68 69 BString representation; 70 switch(info.type) { 71 case B_STRING_TYPE: 72 case B_MIME_STRING_TYPE: 73 { 74 // Use a small buffer, long strings will be truncated 75 char buffer[64]; 76 ssize_t size = node->ReadAttr(name, info.type, 0, buffer, 77 sizeof(buffer)); 78 if (size > 0) 79 representation.SetTo(buffer, size); 80 break; 81 } 82 case B_BOOL_TYPE: 83 { 84 if (info.size == sizeof(bool)) { 85 bool value; 86 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 87 representation = value ? B_TRANSLATE("yes") 88 : B_TRANSLATE("no"); 89 } else { 90 representation.SetToFormat(B_TRANSLATE( 91 "<%" B_PRIdOFF " values>"), info.size / sizeof(bool)); 92 } 93 break; 94 } 95 case B_INT16_TYPE: 96 { 97 if (info.size == sizeof(int16)) { 98 int16 value; 99 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 100 representation.SetToFormat("%" B_PRId16, value); 101 } else { 102 representation.SetToFormat(B_TRANSLATE( 103 "<%" B_PRIdOFF " values>"), info.size / sizeof(int16)); 104 } 105 break; 106 } 107 case B_INT32_TYPE: 108 { 109 if (info.size == sizeof(int32)) { 110 int32 value; 111 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 112 representation.SetToFormat("%" B_PRId32, value); 113 } else { 114 representation.SetToFormat(B_TRANSLATE( 115 "<%" B_PRIdOFF " values>"), info.size / sizeof(int32)); 116 } 117 break; 118 } 119 case B_INT64_TYPE: 120 { 121 if (info.size == sizeof(int64)) { 122 int64 value; 123 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 124 representation.SetToFormat("%" B_PRId64, value); 125 } else { 126 representation.SetToFormat(B_TRANSLATE( 127 "<%" B_PRIdOFF " values>"), info.size / sizeof(int64)); 128 } 129 break; 130 } 131 case B_INT8_TYPE: 132 { 133 if (info.size == sizeof(int8)) { 134 int8 value; 135 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 136 representation.SetToFormat("%" B_PRId8, value); 137 } else { 138 representation.SetToFormat(B_TRANSLATE( 139 "<%" B_PRIdOFF " values>"), info.size / sizeof(int8)); 140 } 141 break; 142 } 143 case B_RECT_TYPE: 144 { 145 if (info.size == sizeof(BRect)) { 146 BRect value; 147 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 148 representation.SetToFormat("(%g,%g) (%g,%g)", value.left, 149 value.top, value.right, value.bottom); 150 } else { 151 representation.SetToFormat(B_TRANSLATE( 152 "<%" B_PRIdOFF " rectangles>"), info.size / sizeof(BRect)); 153 } 154 break; 155 } 156 case B_DOUBLE_TYPE: 157 { 158 if (info.size == sizeof(double)) { 159 double value; 160 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 161 representation.SetToFormat("%f", value); 162 } else { 163 representation.SetToFormat(B_TRANSLATE( 164 "<%" B_PRIdOFF " values>"), info.size / sizeof(double)); 165 } 166 break; 167 } 168 case B_FLOAT_TYPE: 169 { 170 if (info.size == sizeof(float)) { 171 float value; 172 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 173 representation.SetToFormat("%f", value); 174 } else { 175 representation.SetToFormat(B_TRANSLATE( 176 "<%" B_PRIdOFF " values>"), info.size / sizeof(float)); 177 } 178 break; 179 } 180 case B_TIME_TYPE: 181 { 182 // Try to handle attributes written on both 32 and 64bit systems 183 if (info.size == sizeof(int32)) { 184 int32 value; 185 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 186 dateTimeFormatter.Format(representation, value, 187 B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT); 188 } else if (info.size == sizeof(int64)) { 189 int64 value; 190 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 191 dateTimeFormatter.Format(representation, value, 192 B_SHORT_DATE_FORMAT, B_SHORT_TIME_FORMAT); 193 } else { 194 representation.SetToFormat(B_TRANSLATE( 195 "<%" B_PRIdOFF " dates>"), info.size / sizeof(time_t)); 196 } 197 break; 198 } 199 case B_UINT16_TYPE: 200 { 201 if (info.size == sizeof(uint16)) { 202 uint16 value; 203 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 204 representation.SetToFormat("%" B_PRIu16, value); 205 } else { 206 representation.SetToFormat(B_TRANSLATE( 207 "<%" B_PRIdOFF " values>"), info.size / sizeof(uint16)); 208 } 209 break; 210 } 211 case B_UINT32_TYPE: 212 { 213 if (info.size == sizeof(uint32)) { 214 uint32 value; 215 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 216 representation.SetToFormat("%" B_PRIu32, value); 217 } else { 218 representation.SetToFormat(B_TRANSLATE( 219 "<%" B_PRIdOFF " values>"), info.size / sizeof(uint32)); 220 } 221 break; 222 } 223 case B_UINT64_TYPE: 224 { 225 if (info.size == sizeof(uint64)) { 226 uint64 value; 227 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 228 representation.SetToFormat("%" B_PRIu64, value); 229 } else { 230 representation.SetToFormat(B_TRANSLATE( 231 "<%" B_PRIdOFF " values>"), info.size / sizeof(int64)); 232 } 233 break; 234 } 235 case B_UINT8_TYPE: 236 { 237 if (info.size == sizeof(uint8)) { 238 uint8 value; 239 node->ReadAttr(name, info.type, 0, &value, sizeof(value)); 240 representation.SetToFormat("%" B_PRIu8, value); 241 } else { 242 representation.SetToFormat(B_TRANSLATE( 243 "<%" B_PRIdOFF " values>"), info.size / sizeof(int8)); 244 } 245 break; 246 } 247 default: 248 representation.SetToFormat(B_TRANSLATE( 249 "<%" B_PRIdOFF " bytes of data>"), info.size); 250 break; 251 } 252 row->SetField(new BStringField(representation), kValueColumn); 253 254 switch(info.type) { 255 case B_AFFINE_TRANSFORM_TYPE: 256 row->SetField(new BStringField(B_TRANSLATE("Affine transform")), 257 kTypeColumn); 258 break; 259 case B_ALIGNMENT_TYPE: 260 row->SetField(new BStringField(B_TRANSLATE("Alignment")), 261 kTypeColumn); 262 break; 263 case B_ANY_TYPE: 264 row->SetField(new BStringField(B_TRANSLATE("Any")), 265 kTypeColumn); 266 break; 267 case B_ATOM_TYPE: 268 row->SetField(new BStringField(B_TRANSLATE("Atom")), 269 kTypeColumn); 270 break; 271 case B_ATOMREF_TYPE: 272 row->SetField(new BStringField(B_TRANSLATE("Atom reference")), 273 kTypeColumn); 274 break; 275 case B_BOOL_TYPE: 276 row->SetField(new BStringField(B_TRANSLATE("Boolean")), 277 kTypeColumn); 278 break; 279 case B_CHAR_TYPE: 280 row->SetField(new BStringField(B_TRANSLATE("Character")), 281 kTypeColumn); 282 break; 283 case B_COLOR_8_BIT_TYPE: 284 row->SetField(new BStringField(B_TRANSLATE( 285 "Palette-indexed picture")), kTypeColumn); 286 break; 287 case B_DOUBLE_TYPE: 288 row->SetField(new BStringField(B_TRANSLATE( 289 "Double-precision floating point number")), kTypeColumn); 290 break; 291 case B_FLOAT_TYPE: 292 row->SetField(new BStringField(B_TRANSLATE( 293 "Floating point number")), kTypeColumn); 294 break; 295 case B_GRAYSCALE_8_BIT_TYPE: 296 row->SetField(new BStringField(B_TRANSLATE( 297 "Grayscale picture")), kTypeColumn); 298 break; 299 case B_INT16_TYPE: 300 row->SetField(new BStringField(B_TRANSLATE("16-bit integer")), 301 kTypeColumn); 302 break; 303 case B_INT32_TYPE: 304 row->SetField(new BStringField(B_TRANSLATE("32-bit integer")), 305 kTypeColumn); 306 break; 307 case B_INT64_TYPE: 308 row->SetField(new BStringField(B_TRANSLATE("64-bit integer")), 309 kTypeColumn); 310 break; 311 case B_INT8_TYPE: 312 row->SetField(new BStringField(B_TRANSLATE("8-bit integer")), 313 kTypeColumn); 314 break; 315 case B_LARGE_ICON_TYPE: 316 row->SetField(new BStringField(B_TRANSLATE("Bitmap icon")), 317 kTypeColumn); 318 break; 319 case B_MEDIA_PARAMETER_GROUP_TYPE: 320 row->SetField(new BStringField(B_TRANSLATE( 321 "Media parameter group")), kTypeColumn); 322 break; 323 case B_MEDIA_PARAMETER_TYPE: 324 row->SetField(new BStringField(B_TRANSLATE("Media parameter")), 325 kTypeColumn); 326 break; 327 case B_MEDIA_PARAMETER_WEB_TYPE: 328 row->SetField(new BStringField(B_TRANSLATE( 329 "Media parameter web")), kTypeColumn); 330 break; 331 case B_MESSAGE_TYPE: 332 row->SetField(new BStringField(B_TRANSLATE("Message")), 333 kTypeColumn); 334 break; 335 case B_MESSENGER_TYPE: 336 row->SetField(new BStringField(B_TRANSLATE("Messenger")), 337 kTypeColumn); 338 break; 339 case B_MIME_TYPE: 340 row->SetField(new BStringField(B_TRANSLATE("MIME Type")), 341 kTypeColumn); 342 break; 343 case B_MINI_ICON_TYPE: 344 row->SetField(new BStringField(B_TRANSLATE( 345 "Small bitmap icon")), kTypeColumn); 346 break; 347 case B_MONOCHROME_1_BIT_TYPE: 348 row->SetField(new BStringField(B_TRANSLATE( 349 "Monochrome picture")), kTypeColumn); 350 break; 351 case B_OBJECT_TYPE: 352 row->SetField(new BStringField(B_TRANSLATE("Object")), 353 kTypeColumn); 354 break; 355 case B_OFF_T_TYPE: 356 row->SetField(new BStringField(B_TRANSLATE("File offset")), 357 kTypeColumn); 358 break; 359 case B_PATTERN_TYPE: 360 row->SetField(new BStringField(B_TRANSLATE("Drawing pattern")), 361 kTypeColumn); 362 break; 363 case B_POINTER_TYPE: 364 row->SetField(new BStringField(B_TRANSLATE("Memory pointer")), 365 kTypeColumn); 366 break; 367 case B_POINT_TYPE: 368 row->SetField(new BStringField(B_TRANSLATE("Point")), 369 kTypeColumn); 370 break; 371 case B_PROPERTY_INFO_TYPE: 372 row->SetField(new BStringField(B_TRANSLATE("Property info")), 373 kTypeColumn); 374 break; 375 case B_RAW_TYPE: 376 row->SetField(new BStringField(B_TRANSLATE("Raw data")), 377 kTypeColumn); 378 break; 379 case B_RECT_TYPE: 380 row->SetField(new BStringField(B_TRANSLATE("Rectangle")), 381 kTypeColumn); 382 break; 383 case B_REF_TYPE: 384 row->SetField(new BStringField(B_TRANSLATE("Reference")), 385 kTypeColumn); 386 break; 387 case B_RGB_32_BIT_TYPE: 388 row->SetField(new BStringField(B_TRANSLATE( 389 "True-color picture")), kTypeColumn); 390 break; 391 case B_RGB_COLOR_TYPE: 392 row->SetField(new BStringField(B_TRANSLATE("Color")), 393 kTypeColumn); 394 break; 395 case B_SIZE_TYPE: 396 row->SetField(new BStringField(B_TRANSLATE("Geometric size")), 397 kTypeColumn); 398 break; 399 case B_SIZE_T_TYPE: 400 row->SetField(new BStringField(B_TRANSLATE("Memory size")), 401 kTypeColumn); 402 break; 403 case B_SSIZE_T_TYPE: 404 row->SetField(new BStringField(B_TRANSLATE( 405 "Signed memory size")), kTypeColumn); 406 break; 407 case B_STRING_TYPE: 408 row->SetField(new BStringField(B_TRANSLATE("Plain text")), 409 kTypeColumn); 410 break; 411 case B_STRING_LIST_TYPE: 412 row->SetField(new BStringField(B_TRANSLATE("Text list")), 413 kTypeColumn); 414 break; 415 case B_TIME_TYPE: 416 row->SetField(new BStringField(B_TRANSLATE("Time")), 417 kTypeColumn); 418 break; 419 case B_UINT16_TYPE: 420 row->SetField(new BStringField(B_TRANSLATE( 421 "16-bit unsigned integer")), kTypeColumn); 422 break; 423 case B_UINT32_TYPE: 424 row->SetField(new BStringField(B_TRANSLATE( 425 "32-bit unsigned integer")), kTypeColumn); 426 break; 427 case B_UINT64_TYPE: 428 row->SetField(new BStringField(B_TRANSLATE( 429 "64-bit unsigned integer")), kTypeColumn); 430 break; 431 case B_UINT8_TYPE: 432 row->SetField(new BStringField(B_TRANSLATE( 433 "8-bit unsigned integer")), kTypeColumn); 434 break; 435 case B_VECTOR_ICON_TYPE: 436 row->SetField(new BStringField(B_TRANSLATE("Icon")), 437 kTypeColumn); 438 break; 439 case B_XATTR_TYPE: 440 row->SetField(new BStringField(B_TRANSLATE( 441 "Extended attribute")), kTypeColumn); 442 break; 443 case B_NETWORK_ADDRESS_TYPE: 444 row->SetField(new BStringField(B_TRANSLATE("Network address")), 445 kTypeColumn); 446 break; 447 case B_MIME_STRING_TYPE: 448 row->SetField(new BStringField(B_TRANSLATE("MIME String")), 449 kTypeColumn); 450 break; 451 case B_ASCII_TYPE: 452 row->SetField(new BStringField(B_TRANSLATE("ASCII Text")), 453 kTypeColumn); 454 break; 455 default: 456 row->SetField(new BStringField(B_TRANSLATE("(unknown)")), 457 kTypeColumn); 458 break; 459 } 460 fListView->AddRow(row); 461 } 462 } 463