1 /* 2 * Copyright 2002-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold, bonefish@users.sf.net 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include <NodeInfo.h> 12 13 #include <new> 14 #include <string.h> 15 16 #include <MimeTypes.h> 17 #include <Bitmap.h> 18 #include <Entry.h> 19 #include <IconUtils.h> 20 #include <Node.h> 21 #include <Path.h> 22 #include <Rect.h> 23 24 #include <fs_attr.h> 25 #include <fs_info.h> 26 27 using namespace std; 28 29 // attribute names 30 #define NI_BEOS "BEOS" 31 static const char *kNITypeAttribute = NI_BEOS ":TYPE"; 32 static const char *kNIPreferredAppAttribute = NI_BEOS ":PREF_APP"; 33 static const char *kNIAppHintAttribute = NI_BEOS ":PPATH"; 34 static const char *kNIMiniIconAttribute = NI_BEOS ":M:STD_ICON"; 35 static const char *kNILargeIconAttribute = NI_BEOS ":L:STD_ICON"; 36 static const char *kNIIconAttribute = NI_BEOS ":ICON"; 37 38 39 /*! \brief Creates an uninitialized BNodeInfo object. 40 41 After created a BNodeInfo with this, you should call SetTo(). 42 43 \see SetTo(BNode *node) 44 */ 45 BNodeInfo::BNodeInfo() 46 : 47 fNode(NULL), 48 fCStatus(B_NO_INIT) 49 { 50 } 51 52 // constructor 53 /*! \brief Creates a BNodeInfo object and initializes it to the supplied node. 54 55 \param node The node to gather information on. Can be any flavor. 56 57 \see SetTo(BNode *node) 58 */ 59 BNodeInfo::BNodeInfo(BNode *node) 60 : 61 fNode(NULL), 62 fCStatus(B_NO_INIT) 63 { 64 fCStatus = SetTo(node); 65 } 66 67 // destructor 68 /*! \brief Frees all resources associated with this object. 69 70 The BNode object passed to the constructor or to SetTo() is not deleted. 71 */ 72 BNodeInfo::~BNodeInfo() 73 { 74 } 75 76 // SetTo 77 /*! \brief Initializes the BNodeInfo to the supplied node. 78 79 The BNodeInfo object does not copy the supplied object, but uses it 80 directly. You must not delete the object you supply while the BNodeInfo 81 does exist. The BNodeInfo does not take over ownership of the BNode and 82 it doesn't delete it on destruction. 83 84 \param node The node to play with 85 86 \return 87 - \c B_OK: Everything went fine. 88 - \c B_BAD_VALUE: The node was bad. 89 */ 90 status_t 91 BNodeInfo::SetTo(BNode *node) 92 { 93 fNode = NULL; 94 // check parameter 95 fCStatus = (node && node->InitCheck() == B_OK ? B_OK : B_BAD_VALUE); 96 if (fCStatus == B_OK) 97 fNode = node; 98 return fCStatus; 99 } 100 101 // InitCheck 102 /*! \brief returns whether the object has been properly initialized. 103 104 \return 105 - \c B_OK: Everything went fine. 106 - \c B_NO_INIT: The node is not properly initialized. 107 */ 108 status_t 109 BNodeInfo::InitCheck() const 110 { 111 return fCStatus; 112 } 113 114 // GetType 115 /*! \brief Gets the node's MIME type. 116 117 Writes the contents of the "BEOS:TYPE" attribute into the supplied buffer 118 \a type. 119 120 \param type A pointer to a pre-allocated character buffer of size 121 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 122 node shall be written. 123 \return 124 - \c B_OK: Everything went fine. 125 - \c B_NO_INIT: The object is not properly initialized. 126 - \c B_BAD_VALUE: \c NULL \a type or the type string stored in the 127 attribute is longer than \c B_MIME_TYPE_LENGTH. 128 - \c B_BAD_TYPE: The attribute the type string is stored in has the wrong 129 type. 130 - \c B_ENTRY_NOT_FOUND: No type is set on the node. 131 - other error codes 132 */ 133 status_t 134 BNodeInfo::GetType(char *type) const 135 { 136 // check parameter and initialization 137 status_t error = (type ? B_OK : B_BAD_VALUE); 138 if (error == B_OK && InitCheck() != B_OK) 139 error = B_NO_INIT; 140 // get the attribute info and check type and length of the attr contents 141 attr_info attrInfo; 142 if (error == B_OK) 143 error = fNode->GetAttrInfo(kNITypeAttribute, &attrInfo); 144 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 145 error = B_BAD_TYPE; 146 if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH) 147 error = B_BAD_DATA; 148 149 // read the data 150 if (error == B_OK) { 151 ssize_t read = fNode->ReadAttr(kNITypeAttribute, attrInfo.type, 0, 152 type, attrInfo.size); 153 if (read < 0) 154 error = read; 155 else if (read != attrInfo.size) 156 error = B_ERROR; 157 158 if (error == B_OK) { 159 // attribute strings doesn't have to be null terminated 160 type[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0'; 161 } 162 } 163 return error; 164 } 165 166 // SetType 167 /*! \brief Sets the node's MIME type. 168 169 The supplied string is written into the node's "BEOS:TYPE" attribute. 170 171 If \a type is \c NULL, the respective attribute is removed. 172 173 \param type The MIME type to be assigned to the node. Must not be longer 174 than \c B_MIME_TYPE_LENGTH (including the terminating null). 175 May be \c NULL. 176 \return 177 - \c B_OK: Everything went fine. 178 - \c B_NO_INIT: The object is not properly initialized. 179 - \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH. 180 - other error codes 181 */ 182 status_t 183 BNodeInfo::SetType(const char *type) 184 { 185 // check parameter and initialization 186 status_t error = B_OK; 187 if (error == B_OK && type && strlen(type) >= B_MIME_TYPE_LENGTH) 188 error = B_BAD_VALUE; 189 if (error == B_OK && InitCheck() != B_OK) 190 error = B_NO_INIT; 191 192 // write/remove the attribute 193 if (error == B_OK) { 194 if (type) { 195 size_t toWrite = strlen(type) + 1; 196 ssize_t written = fNode->WriteAttr(kNITypeAttribute, 197 B_MIME_STRING_TYPE, 0, type, 198 toWrite); 199 if (written < 0) 200 error = written; 201 else if (written != (ssize_t)toWrite) 202 error = B_ERROR; 203 } else 204 error = fNode->RemoveAttr(kNITypeAttribute); 205 } 206 return error; 207 } 208 209 // GetIcon 210 /*! \brief Gets the node's icon. 211 212 The icon stored in the node's "BEOS:L:STD_ICON" (large) or 213 "BEOS:M:STD_ICON" (mini) attribute is retrieved. 214 215 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 216 to store the requested icon (16x16 for the mini and 32x32 for the 217 large icon). 218 \param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON 219 for the mini and \c B_LARGE_ICON for the large icon. 220 \return 221 - \c B_OK: Everything went fine. 222 - \c B_NO_INIT: The object is not properly initialized. 223 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a k or bitmap 224 dimensions (\a icon) and icon size (\a k) do not match. 225 - other error codes 226 */ 227 status_t 228 BNodeInfo::GetIcon(BBitmap *icon, icon_size k) const 229 { 230 const char* iconAttribute = kNIIconAttribute; 231 const char* miniIconAttribute = kNIMiniIconAttribute; 232 const char* largeIconAttribute = kNILargeIconAttribute; 233 234 return BIconUtils::GetIcon(fNode, iconAttribute, miniIconAttribute, 235 largeIconAttribute, k, icon); 236 237 // status_t error = B_OK; 238 // // set some icon size related variables 239 // const char *attribute = NULL; 240 // BRect bounds; 241 // uint32 attrType = 0; 242 // size_t attrSize = 0; 243 // switch (k) { 244 // case B_MINI_ICON: 245 // attribute = kNIMiniIconAttribute; 246 // bounds.Set(0, 0, 15, 15); 247 // attrType = B_MINI_ICON_TYPE; 248 // attrSize = 16 * 16; 249 // break; 250 // case B_LARGE_ICON: 251 // attribute = kNILargeIconAttribute; 252 // bounds.Set(0, 0, 31, 31); 253 // attrType = B_LARGE_ICON_TYPE; 254 // attrSize = 32 * 32; 255 // break; 256 // default: 257 // error = B_BAD_VALUE; 258 // break; 259 // } 260 // 261 // // check parameter and initialization 262 // if (error == B_OK 263 // && (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 264 // error = B_BAD_VALUE; 265 // } 266 // if (error == B_OK && InitCheck() != B_OK) 267 // error = B_NO_INIT; 268 // 269 // // get the attribute info and check type and size of the attr contents 270 // attr_info attrInfo; 271 // if (error == B_OK) 272 // error = fNode->GetAttrInfo(attribute, &attrInfo); 273 // if (error == B_OK && attrInfo.type != attrType) 274 // error = B_BAD_TYPE; 275 // if (error == B_OK && attrInfo.size != attrSize) 276 // error = B_BAD_DATA; 277 // 278 // // read the attribute 279 // if (error == B_OK) { 280 // bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); 281 // char *buffer = NULL; 282 // ssize_t read; 283 // if (otherColorSpace) { 284 // // other color space than stored in attribute 285 // buffer = new(nothrow) char[attrSize]; 286 // if (!buffer) 287 // error = B_NO_MEMORY; 288 // if (error == B_OK) { 289 // read = fNode->ReadAttr(attribute, attrType, 0, buffer, 290 // attrSize); 291 // } 292 // } else { 293 // read = fNode->ReadAttr(attribute, attrType, 0, icon->Bits(), 294 // attrSize); 295 // } 296 // if (error == B_OK) { 297 // if (read < 0) 298 // error = read; 299 // else if (read != attrInfo.size) 300 // error = B_ERROR; 301 // } 302 // if (otherColorSpace) { 303 // // other color space than stored in attribute 304 // if (error == B_OK) { 305 // error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW, 306 // 0, B_CMAP8); 307 // } 308 // delete[] buffer; 309 // } 310 // } 311 // return error; 312 } 313 314 // SetIcon 315 /*! \brief Sets the node's icon. 316 317 The icon is stored in the node's "BEOS:L:STD_ICON" (large) or 318 "BEOS:M:STD_ICON" (mini) attribute. 319 320 If \a icon is \c NULL, the respective attribute is removed. 321 322 \param icon A pointer to the BBitmap containing the icon to be set. 323 May be \c NULL. 324 \param k Specifies the size of the icon to be set: \c B_MINI_ICON 325 for the mini and \c B_LARGE_ICON for the large icon. 326 \return 327 - \c B_OK: Everything went fine. 328 - \c B_NO_INIT: The object is not properly initialized. 329 - \c B_BAD_VALUE: Unknown icon size \a k or bitmap dimensions (\a icon) 330 and icon size (\a k) do not match. 331 - other error codes 332 */ 333 status_t 334 BNodeInfo::SetIcon(const BBitmap *icon, icon_size k) 335 { 336 status_t error = B_OK; 337 // set some icon size related variables 338 const char *attribute = NULL; 339 BRect bounds; 340 uint32 attrType = 0; 341 size_t attrSize = 0; 342 switch (k) { 343 case B_MINI_ICON: 344 attribute = kNIMiniIconAttribute; 345 bounds.Set(0, 0, 15, 15); 346 attrType = B_MINI_ICON_TYPE; 347 attrSize = 16 * 16; 348 break; 349 case B_LARGE_ICON: 350 attribute = kNILargeIconAttribute; 351 bounds.Set(0, 0, 31, 31); 352 attrType = B_LARGE_ICON_TYPE; 353 attrSize = 32 * 32; 354 break; 355 default: 356 error = B_BAD_VALUE; 357 break; 358 } 359 360 // check parameter and initialization 361 if (error == B_OK && icon 362 && (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 363 error = B_BAD_VALUE; 364 } 365 if (error == B_OK && InitCheck() != B_OK) 366 error = B_NO_INIT; 367 368 // write/remove the attribute 369 if (error == B_OK) { 370 if (icon) { 371 bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); 372 ssize_t written = 0; 373 if (otherColorSpace) { 374 BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8); 375 error = bitmap.InitCheck(); 376 if (error == B_OK) 377 error = bitmap.ImportBits(icon); 378 if (error == B_OK) { 379 written = fNode->WriteAttr(attribute, attrType, 0, 380 bitmap.Bits(), attrSize); 381 } 382 } else { 383 written = fNode->WriteAttr(attribute, attrType, 0, 384 icon->Bits(), attrSize); 385 } 386 if (error == B_OK) { 387 if (written < 0) 388 error = written; 389 else if (written != (ssize_t)attrSize) 390 error = B_ERROR; 391 } 392 } else // no icon given => remove 393 error = fNode->RemoveAttr(attribute); 394 } 395 return error; 396 } 397 398 399 // GetIcon 400 /*! \brief Gets the node's icon. 401 402 The icon stored in the node's "BEOS:ICON" attribute is retrieved. 403 The caller is responsible to \c delete[] the returned data if the 404 function was successful. 405 406 \param data A pointer in which a pointer to the icon data 407 will be returned. 408 \param size A pointer in which the size of the found icon data 409 will be returned. 410 \param type A pointer in which the type of the found icon data 411 will be returned. 412 \return 413 - \c B_OK: Everything went fine. 414 - \c B_NO_INIT: The object is not properly initialized. 415 - \c B_BAD_VALUE: \c NULL \a data, \c NULL size or \c NULL \a type. 416 - \c B_NO_MEMORY: No memory to allocate the data buffer. 417 - other error codes 418 */ 419 status_t 420 BNodeInfo::GetIcon(uint8** data, size_t* size, type_code* type) const 421 { 422 // check params 423 if (!data || !size || !type) 424 return B_BAD_VALUE; 425 426 // check initialization 427 if (InitCheck() != B_OK) 428 return B_NO_INIT; 429 430 // get the attribute info and check type and size of the attr contents 431 attr_info attrInfo; 432 status_t ret = fNode->GetAttrInfo(kNIIconAttribute, &attrInfo); 433 if (ret < B_OK) 434 return ret; 435 436 // chicken out on unrealisticly large attributes 437 if (attrInfo.size > 128 * 1024) 438 return B_ERROR; 439 440 // fill the params 441 *type = attrInfo.type; 442 *size = attrInfo.size; 443 *data = new (nothrow) uint8[*size]; 444 445 if (!*data) 446 return B_NO_MEMORY; 447 448 // featch the data 449 ssize_t read = fNode->ReadAttr(kNIIconAttribute, *type, 0, *data, *size); 450 if (read != attrInfo.size) { 451 delete[] *data; 452 *data = NULL; 453 return B_ERROR; 454 } 455 456 return B_OK; 457 } 458 459 // SetIcon 460 /*! \brief Sets the node's icon. 461 462 The icon is stored in the node's "BEOS:ICON" attribute. 463 464 If \a data is \c NULL, the respective attribute is removed. 465 466 \param data A pointer to valid vector icon data. 467 May be \c NULL. 468 \param size Specifies the size of the provided data buffer. 469 \return 470 - \c B_OK: Everything went fine. 471 - \c B_NO_INIT: The object is not properly initialized. 472 - other error codes 473 */ 474 status_t 475 BNodeInfo::SetIcon(const uint8* data, size_t size) 476 { 477 // check initialization 478 if (InitCheck() != B_OK) 479 return B_NO_INIT; 480 481 status_t error = B_OK; 482 483 // write/remove the attribute 484 if (data && size > 0) { 485 ssize_t written = fNode->WriteAttr(kNIIconAttribute, 486 B_VECTOR_ICON_TYPE, 487 0, data, size); 488 if (written < 0) 489 error = (status_t)written; 490 else if (written != (ssize_t)size) 491 error = B_ERROR; 492 } else // no icon given => remove 493 error = fNode->RemoveAttr(kNIIconAttribute); 494 495 return error; 496 } 497 498 // GetPreferredApp 499 /*! \brief Gets the node's preferred application. 500 501 Writes the contents of the "BEOS:PREF_APP" attribute into the supplied 502 buffer \a signature. The preferred application is identifief by its 503 signature. 504 505 \param signature A pointer to a pre-allocated character buffer of size 506 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 507 preferred application shall be written. 508 \param verb Specifies the type of access the preferred application is 509 requested for. Currently only \c B_OPEN is meaningful. 510 \return 511 - \c B_OK: Everything went fine. 512 - \c B_NO_INIT: The object is not properly initialized. 513 - \c B_BAD_VALUE: \c NULL \a signature or bad app_verb \a verb. 514 - other error codes 515 */ 516 status_t 517 BNodeInfo::GetPreferredApp(char *signature, app_verb verb) const 518 { 519 // check parameter and initialization 520 status_t error = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE); 521 if (error == B_OK && InitCheck() != B_OK) 522 error = B_NO_INIT; 523 524 // get the attribute info and check type and length of the attr contents 525 attr_info attrInfo; 526 if (error == B_OK) 527 error = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo); 528 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 529 error = B_BAD_TYPE; 530 if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH) 531 error = B_BAD_DATA; 532 533 // read the data 534 if (error == B_OK) { 535 ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type, 536 0, signature, attrInfo.size); 537 if (read < 0) 538 error = read; 539 else if (read != attrInfo.size) 540 error = B_ERROR; 541 542 if (error == B_OK) { 543 // attribute strings doesn't have to be null terminated 544 signature[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0'; 545 } 546 } 547 return error; 548 } 549 550 // SetPreferredApp 551 /*! \brief Sets the node's preferred application. 552 553 The supplied string is written into the node's "BEOS:PREF_APP" attribute. 554 555 If \a signature is \c NULL, the respective attribute is removed. 556 557 \param signature The signature of the preferred application to be set. 558 Must not be longer than \c B_MIME_TYPE_LENGTH (including the 559 terminating null). May be \c NULL. 560 \param verb Specifies the type of access the preferred application shall 561 be set for. Currently only \c B_OPEN is meaningful. 562 \return 563 - \c B_OK: Everything went fine. 564 - \c B_NO_INIT: The object is not properly initialized. 565 - \c B_BAD_VALUE: \c NULL \a signature, \a signature is longer than 566 \c B_MIME_TYPE_LENGTH or bad app_verb \a verb. 567 - other error codes 568 */ 569 status_t 570 BNodeInfo::SetPreferredApp(const char *signature, app_verb verb) 571 { 572 // check parameters and initialization 573 status_t error = (verb == B_OPEN ? B_OK : B_BAD_VALUE); 574 if (error == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH) 575 error = B_BAD_VALUE; 576 if (error == B_OK && InitCheck() != B_OK) 577 error = B_NO_INIT; 578 579 // write/remove the attribute 580 if (error == B_OK) { 581 if (signature) { 582 size_t toWrite = strlen(signature) + 1; 583 ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute, 584 B_MIME_STRING_TYPE, 0, 585 signature, toWrite); 586 if (written < 0) 587 error = written; 588 else if (written != (ssize_t)toWrite) 589 error = B_ERROR; 590 } else 591 error = fNode->RemoveAttr(kNIPreferredAppAttribute); 592 } 593 return error; 594 } 595 596 // GetAppHint 597 /*! \brief Returns a hint in form of and entry_ref to the application that 598 shall be used to open this node. 599 600 The path contained in the node's "BEOS:PPATH" attribute is converted into 601 an entry_ref and returned in \a ref. 602 603 \param ref A pointer to a pre-allocated entry_ref into which the requested 604 app hint shall be written. 605 \return 606 - \c B_OK: Everything went fine. 607 - \c B_NO_INIT: The object is not properly initialized. 608 - \c B_BAD_VALUE: \c NULL \a ref. 609 - other error codes 610 */ 611 status_t 612 BNodeInfo::GetAppHint(entry_ref *ref) const 613 { 614 // check parameter and initialization 615 status_t error = (ref ? B_OK : B_BAD_VALUE); 616 if (error == B_OK && InitCheck() != B_OK) 617 error = B_NO_INIT; 618 619 // get the attribute info and check type and length of the attr contents 620 attr_info attrInfo; 621 if (error == B_OK) 622 error = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo); 623 // NOTE: The attribute type should be B_STRING_TYPE, but R5 uses 624 // B_MIME_STRING_TYPE. 625 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 626 error = B_BAD_TYPE; 627 if (error == B_OK && attrInfo.size > B_PATH_NAME_LENGTH) 628 error = B_BAD_DATA; 629 630 // read the data 631 if (error == B_OK) { 632 char path[B_PATH_NAME_LENGTH]; 633 ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0, 634 path, attrInfo.size); 635 if (read < 0) 636 error = read; 637 else if (read != attrInfo.size) 638 error = B_ERROR; 639 // get the entry_ref for the path 640 if (error == B_OK) { 641 // attribute strings doesn't have to be null terminated 642 path[min_c(attrInfo.size, B_PATH_NAME_LENGTH - 1)] = '\0'; 643 error = get_ref_for_path(path, ref); 644 } 645 } 646 return error; 647 } 648 649 // SetAppHint 650 /*! \brief Sets the node's app hint. 651 652 The supplied entry_ref is converted into a path and stored in the node's 653 "BEOS:PPATH" attribute. 654 655 If \a ref is \c NULL, the respective attribute is removed. 656 657 \param ref A pointer to an entry_ref referring to the application. 658 May be \c NULL. 659 \return 660 - \c B_OK: Everything went fine. 661 - \c B_NO_INIT: The object is not properly initialized. 662 - \c B_BAD_VALUE: \c NULL \a ref. 663 - other error codes 664 */ 665 status_t 666 BNodeInfo::SetAppHint(const entry_ref *ref) 667 { 668 // check parameter and initialization 669 status_t error = B_OK; 670 if (error == B_OK && InitCheck() != B_OK) 671 error = B_NO_INIT; 672 673 // write/remove the attribute 674 if (error == B_OK) { 675 if (ref) { 676 BPath path; 677 error = path.SetTo(ref); 678 if (error == B_OK) { 679 size_t toWrite = strlen(path.Path()) + 1; 680 ssize_t written = fNode->WriteAttr(kNIAppHintAttribute, 681 B_MIME_STRING_TYPE, 0, 682 path.Path(), toWrite); 683 if (written < 0) 684 error = written; 685 else if (written != (ssize_t)toWrite) 686 error = B_ERROR; 687 } 688 } else 689 error = fNode->RemoveAttr(kNIAppHintAttribute); 690 } 691 return error; 692 } 693 694 // GetTrackerIcon 695 /*! \brief Gets the icon which tracker displays. 696 697 This method tries real hard to find an icon for the node: 698 - If the node has no type, return the icon for B_FILE_MIME_TYPE if it's a 699 regular file, for B_DIRECTORY_MIME_TYPE if it's a directory, etc. from 700 the MIME database. Even, if the node has an own icon! 701 - Ask GetIcon(). 702 - Get the preferred application and ask the MIME database, if that 703 application has a special icon for the node's file type. 704 - Ask the MIME database whether there is an icon for the node's file type. 705 - Ask the MIME database for the preferred application for the node's 706 file type and whether this application has a special icon for the type. 707 - Return the icon for whatever type of node (file/dir/etc.) from the MIME database. 708 This list is processed in the given order and the icon the first 709 successful attempt provides is returned. In case none of them yields an 710 icon, this method fails. This is very unlikely though. 711 712 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 713 to store the requested icon (16x16 for the mini and 32x32 for the 714 large icon). 715 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 716 for the mini and \c B_LARGE_ICON for the large icon. 717 \return 718 - \c B_OK: Everything went fine. 719 - \c B_NO_INIT: The object is not properly initialized. 720 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a iconSize or bitmap 721 dimensions (\a icon) and icon size (\a iconSize) do not match. 722 - other error codes 723 */ 724 status_t 725 BNodeInfo::GetTrackerIcon(BBitmap *icon, icon_size iconSize) const 726 { 727 if (!icon) 728 return B_BAD_VALUE; 729 730 // set some icon size related variables 731 BRect bounds; 732 switch (iconSize) { 733 case B_MINI_ICON: 734 bounds.Set(0, 0, 15, 15); 735 break; 736 case B_LARGE_ICON: 737 bounds.Set(0, 0, 31, 31); 738 break; 739 default: 740 // error = B_BAD_VALUE; 741 // NOTE: added to be less strict and support scaled icons 742 bounds = icon->Bounds(); 743 break; 744 } 745 746 // check parameters and initialization 747 if (icon->InitCheck() != B_OK || icon->Bounds() != bounds) 748 return B_BAD_VALUE; 749 750 if (InitCheck() != B_OK) 751 return B_NO_INIT; 752 753 // Ask GetIcon() first. 754 if (GetIcon(icon, iconSize) == B_OK) 755 return B_OK; 756 757 // If not successful, see if the node has a type available at all. If no type 758 // is available, use one of the standard types depending on 759 status_t error = B_OK; 760 char mimeString[B_MIME_TYPE_LENGTH]; 761 if (GetType(mimeString) != B_OK) { 762 // Get the icon from a mime type... 763 BMimeType type; 764 765 struct stat stat; 766 error = fNode->GetStat(&stat); 767 if (error == B_OK) { 768 // no type available -- get the icon for the appropriate type (file/dir/etc.) 769 if (S_ISREG(stat.st_mode)) { 770 // is it an application (executable) or just a regular file? 771 if ((stat.st_mode & S_IXUSR) != 0) 772 type.SetTo(B_APP_MIME_TYPE); 773 else 774 type.SetTo(B_FILE_MIME_TYPE); 775 } else if (S_ISDIR(stat.st_mode)) { 776 // it's either a volume or just a standard directory 777 fs_info info; 778 if (fs_stat_dev(stat.st_dev, &info) == 0 && stat.st_ino == info.root) 779 type.SetTo(B_VOLUME_MIME_TYPE); 780 else 781 type.SetTo(B_DIRECTORY_MIME_TYPE); 782 } else if (S_ISLNK(stat.st_mode)) 783 type.SetTo(B_SYMLINK_MIME_TYPE); 784 } else { 785 // GetStat() failed. 786 // Return the icon for "application/octet-stream" from the MIME database. 787 type.SetTo(B_FILE_MIME_TYPE); 788 } 789 790 return type.GetIcon(icon, iconSize); 791 792 } else { 793 // We know the mimetype of the node. 794 bool success = false; 795 796 // Get the preferred application and ask the MIME database, if that 797 // application has a special icon for the node's file type. 798 char signature[B_MIME_TYPE_LENGTH]; 799 if (GetPreferredApp(signature) == B_OK) { 800 BMimeType type(signature); 801 success = type.GetIconForType(mimeString, icon, iconSize) == B_OK; 802 } 803 804 // TODO: Confirm Tracker asks preferred app icons before asking mime icons. 805 806 BMimeType nodeType(mimeString); 807 808 // Ask the MIME database for the preferred application for the node's 809 // file type and whether this application has a special icon for the type. 810 if (!success && nodeType.GetPreferredApp(signature) == B_OK) { 811 BMimeType type(signature); 812 success = type.GetIconForType(mimeString, icon, iconSize) == B_OK; 813 } 814 815 // Ask the MIME database whether there is an icon for the node's file type. 816 if (!success) 817 success = nodeType.GetIcon(icon, iconSize) == B_OK; 818 819 // Get the super type if still no success. 820 BMimeType superType; 821 if (!success && nodeType.GetSupertype(&superType) == B_OK) { 822 // Ask the MIME database for the preferred application for the node's 823 // super type and whether this application has a special icon for the type. 824 if (superType.GetPreferredApp(signature) == B_OK) { 825 BMimeType type(signature); 826 success = type.GetIconForType(superType.Type(), icon, iconSize) == B_OK; 827 } 828 // Get the icon of the super type itself. 829 if (!success) 830 success = superType.GetIcon(icon, iconSize) == B_OK; 831 } 832 833 if (success) 834 return B_OK; 835 } 836 837 return B_ERROR; 838 } 839 840 // GetTrackerIcon 841 /*! \brief Gets the icon which tracker displays for the node referred to by 842 the supplied entry_ref. 843 844 This methods works similar to the non-static version. The first argument 845 \a ref identifies the node in question. 846 847 \param ref An entry_ref referring to the node for which the icon shall be 848 retrieved. 849 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 850 to store the requested icon (16x16 for the mini and 32x32 for the 851 large icon). 852 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 853 for the mini and \c B_LARGE_ICON for the large icon. 854 \return 855 - \c B_OK: Everything went fine. 856 - \c B_NO_INIT: The object is not properly initialized. 857 - \c B_BAD_VALUE: \c NULL ref or \a icon, unsupported icon size \a iconSize or 858 bitmap dimensions (\a icon) and icon size (\a iconSize) do not match. 859 - other error codes 860 */ 861 status_t 862 BNodeInfo::GetTrackerIcon(const entry_ref *ref, BBitmap *icon, icon_size iconSize) 863 { 864 // check ref param 865 status_t error = (ref ? B_OK : B_BAD_VALUE); 866 867 // init a BNode 868 BNode node; 869 if (error == B_OK) 870 error = node.SetTo(ref); 871 872 // init a BNodeInfo 873 BNodeInfo nodeInfo; 874 if (error == B_OK) 875 error = nodeInfo.SetTo(&node); 876 877 // let the non-static GetTrackerIcon() do the dirty work 878 if (error == B_OK) 879 error = nodeInfo.GetTrackerIcon(icon, iconSize); 880 return error; 881 } 882 883 // TODO: just here for providing binary compatibility 884 // (for example "Guido" needs this) 885 extern "C" 886 status_t 887 GetTrackerIcon__9BNodeInfoP9entry_refP7BBitmap9icon_size( 888 BNodeInfo *nodeInfo, entry_ref* ref, 889 BBitmap* bitmap, icon_size iconSize) 890 { 891 // NOTE: nodeInfo is ignored - maybe that's wrong! 892 return BNodeInfo::GetTrackerIcon(ref, bitmap, iconSize); 893 } 894 895 void 896 BNodeInfo::_ReservedNodeInfo1() 897 { 898 } 899 900 void 901 BNodeInfo::_ReservedNodeInfo2() 902 { 903 } 904 905 void 906 BNodeInfo::_ReservedNodeInfo3() 907 { 908 } 909 910 // = 911 /*! \brief Privatized assignment operator to prevent usage. 912 */ 913 BNodeInfo & 914 BNodeInfo::operator=(const BNodeInfo &nodeInfo) 915 { 916 return *this; 917 } 918 919 // copy constructor 920 /*! \brief Privatized copy constructor to prevent usage. 921 */ 922 BNodeInfo::BNodeInfo(const BNodeInfo &) 923 { 924 } 925 926 927 // #pragma mark - 928 929 namespace BPrivate { 930 931 /*! 932 Private function used by Tracker. Should be moved into the Tracker sources. 933 */ 934 extern bool 935 CheckNodeIconHintPrivate(const BNode *node, bool checkMiniIconOnly) 936 { 937 attr_info info; 938 if (node->GetAttrInfo(kNIMiniIconAttribute, &info) != B_OK && checkMiniIconOnly) 939 return false; 940 941 if (node->GetAttrInfo(kNILargeIconAttribute, &info) != B_OK) 942 return false; 943 944 return true; 945 } 946 947 } // namespace BPrivate 948