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