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