xref: /haiku/src/kits/tracker/infowindow/AttributesView.cpp (revision 42f51416eb68b0a79f50fe185b6d0ecb064c62dc)
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