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 // GetPreferredApp 399 /*! \brief Gets the node's preferred application. 400 401 Writes the contents of the "BEOS:PREF_APP" attribute into the supplied 402 buffer \a signature. The preferred application is identifief by its 403 signature. 404 405 \param signature A pointer to a pre-allocated character buffer of size 406 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 407 preferred application shall be written. 408 \param verb Specifies the type of access the preferred application is 409 requested for. Currently only \c B_OPEN is meaningful. 410 \return 411 - \c B_OK: Everything went fine. 412 - \c B_NO_INIT: The object is not properly initialized. 413 - \c B_BAD_VALUE: \c NULL \a signature or bad app_verb \a verb. 414 - other error codes 415 */ 416 status_t 417 BNodeInfo::GetPreferredApp(char *signature, app_verb verb) const 418 { 419 // check parameter and initialization 420 status_t error = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE); 421 if (error == B_OK && InitCheck() != B_OK) 422 error = B_NO_INIT; 423 424 // get the attribute info and check type and length of the attr contents 425 attr_info attrInfo; 426 if (error == B_OK) 427 error = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo); 428 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 429 error = B_BAD_TYPE; 430 if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH) 431 error = B_BAD_DATA; 432 433 // read the data 434 if (error == B_OK) { 435 ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type, 436 0, signature, attrInfo.size); 437 if (read < 0) 438 error = read; 439 else if (read != attrInfo.size) 440 error = B_ERROR; 441 442 if (error == B_OK) { 443 // attribute strings doesn't have to be null terminated 444 signature[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0'; 445 } 446 } 447 return error; 448 } 449 450 // SetPreferredApp 451 /*! \brief Sets the node's preferred application. 452 453 The supplied string is written into the node's "BEOS:PREF_APP" attribute. 454 455 If \a signature is \c NULL, the respective attribute is removed. 456 457 \param signature The signature of the preferred application to be set. 458 Must not be longer than \c B_MIME_TYPE_LENGTH (including the 459 terminating null). May be \c NULL. 460 \param verb Specifies the type of access the preferred application shall 461 be set for. Currently only \c B_OPEN is meaningful. 462 \return 463 - \c B_OK: Everything went fine. 464 - \c B_NO_INIT: The object is not properly initialized. 465 - \c B_BAD_VALUE: \c NULL \a signature, \a signature is longer than 466 \c B_MIME_TYPE_LENGTH or bad app_verb \a verb. 467 - other error codes 468 */ 469 status_t 470 BNodeInfo::SetPreferredApp(const char *signature, app_verb verb) 471 { 472 // check parameters and initialization 473 status_t error = (verb == B_OPEN ? B_OK : B_BAD_VALUE); 474 if (error == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH) 475 error = B_BAD_VALUE; 476 if (error == B_OK && InitCheck() != B_OK) 477 error = B_NO_INIT; 478 479 // write/remove the attribute 480 if (error == B_OK) { 481 if (signature) { 482 size_t toWrite = strlen(signature) + 1; 483 ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute, 484 B_MIME_STRING_TYPE, 0, 485 signature, toWrite); 486 if (written < 0) 487 error = written; 488 else if (written != (ssize_t)toWrite) 489 error = B_ERROR; 490 } else 491 error = fNode->RemoveAttr(kNIPreferredAppAttribute); 492 } 493 return error; 494 } 495 496 // GetAppHint 497 /*! \brief Returns a hint in form of and entry_ref to the application that 498 shall be used to open this node. 499 500 The path contained in the node's "BEOS:PPATH" attribute is converted into 501 an entry_ref and returned in \a ref. 502 503 \param ref A pointer to a pre-allocated entry_ref into which the requested 504 app hint shall be written. 505 \return 506 - \c B_OK: Everything went fine. 507 - \c B_NO_INIT: The object is not properly initialized. 508 - \c B_BAD_VALUE: \c NULL \a ref. 509 - other error codes 510 */ 511 status_t 512 BNodeInfo::GetAppHint(entry_ref *ref) const 513 { 514 // check parameter and initialization 515 status_t error = (ref ? B_OK : B_BAD_VALUE); 516 if (error == B_OK && InitCheck() != B_OK) 517 error = B_NO_INIT; 518 519 // get the attribute info and check type and length of the attr contents 520 attr_info attrInfo; 521 if (error == B_OK) 522 error = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo); 523 // NOTE: The attribute type should be B_STRING_TYPE, but R5 uses 524 // B_MIME_STRING_TYPE. 525 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 526 error = B_BAD_TYPE; 527 if (error == B_OK && attrInfo.size > B_PATH_NAME_LENGTH) 528 error = B_BAD_DATA; 529 530 // read the data 531 if (error == B_OK) { 532 char path[B_PATH_NAME_LENGTH]; 533 ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0, 534 path, attrInfo.size); 535 if (read < 0) 536 error = read; 537 else if (read != attrInfo.size) 538 error = B_ERROR; 539 // get the entry_ref for the path 540 if (error == B_OK) { 541 // attribute strings doesn't have to be null terminated 542 path[min_c(attrInfo.size, B_PATH_NAME_LENGTH - 1)] = '\0'; 543 error = get_ref_for_path(path, ref); 544 } 545 } 546 return error; 547 } 548 549 // SetAppHint 550 /*! \brief Sets the node's app hint. 551 552 The supplied entry_ref is converted into a path and stored in the node's 553 "BEOS:PPATH" attribute. 554 555 If \a ref is \c NULL, the respective attribute is removed. 556 557 \param ref A pointer to an entry_ref referring to the application. 558 May be \c NULL. 559 \return 560 - \c B_OK: Everything went fine. 561 - \c B_NO_INIT: The object is not properly initialized. 562 - \c B_BAD_VALUE: \c NULL \a ref. 563 - other error codes 564 */ 565 status_t 566 BNodeInfo::SetAppHint(const entry_ref *ref) 567 { 568 // check parameter and initialization 569 status_t error = B_OK; 570 if (error == B_OK && InitCheck() != B_OK) 571 error = B_NO_INIT; 572 573 // write/remove the attribute 574 if (error == B_OK) { 575 if (ref) { 576 BPath path; 577 error = path.SetTo(ref); 578 if (error == B_OK) { 579 size_t toWrite = strlen(path.Path()) + 1; 580 ssize_t written = fNode->WriteAttr(kNIAppHintAttribute, 581 B_MIME_STRING_TYPE, 0, 582 path.Path(), toWrite); 583 if (written < 0) 584 error = written; 585 else if (written != (ssize_t)toWrite) 586 error = B_ERROR; 587 } 588 } else 589 error = fNode->RemoveAttr(kNIAppHintAttribute); 590 } 591 return error; 592 } 593 594 // GetTrackerIcon 595 /*! \brief Gets the icon which tracker displays. 596 597 This method tries real hard to find an icon for the node: 598 - If the node has no type, return the icon for B_FILE_MIME_TYPE if it's a 599 regular file, for B_DIRECTORY_MIME_TYPE if it's a directory, etc. from 600 the MIME database. Even, if the node has an own icon! 601 - Ask GetIcon(). 602 - Get the preferred application and ask the MIME database, if that 603 application has a special icon for the node's file type. 604 - Ask the MIME database whether there is an icon for the node's file type. 605 - Ask the MIME database for the preferred application for the node's 606 file type and whether this application has a special icon for the type. 607 - Return the icon for whatever type of node (file/dir/etc.) from the MIME database. 608 This list is processed in the given order and the icon the first 609 successful attempt provides is returned. In case none of them yields an 610 icon, this method fails. This is very unlikely though. 611 612 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 613 to store the requested icon (16x16 for the mini and 32x32 for the 614 large icon). 615 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 616 for the mini and \c B_LARGE_ICON for the large icon. 617 \return 618 - \c B_OK: Everything went fine. 619 - \c B_NO_INIT: The object is not properly initialized. 620 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a iconSize or bitmap 621 dimensions (\a icon) and icon size (\a iconSize) do not match. 622 - other error codes 623 */ 624 status_t 625 BNodeInfo::GetTrackerIcon(BBitmap *icon, icon_size iconSize) const 626 { 627 if (!icon) 628 return B_BAD_VALUE; 629 630 // set some icon size related variables 631 status_t error = B_OK; 632 BRect bounds; 633 switch (iconSize) { 634 case B_MINI_ICON: 635 bounds.Set(0, 0, 15, 15); 636 break; 637 case B_LARGE_ICON: 638 bounds.Set(0, 0, 31, 31); 639 break; 640 default: 641 // error = B_BAD_VALUE; 642 // NOTE: added to be less strict and support scaled icons 643 bounds = icon->Bounds(); 644 break; 645 } 646 647 // check parameters and initialization 648 if (error == B_OK 649 && (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 650 error = B_BAD_VALUE; 651 } 652 if (error == B_OK && InitCheck() != B_OK) 653 error = B_NO_INIT; 654 655 bool success = false; 656 657 // get node MIME type, and, if that fails, the generic icon 658 char mimeString[B_MIME_TYPE_LENGTH]; 659 if (error == B_OK) { 660 if (GetType(mimeString) != B_OK) { 661 struct stat stat; 662 error = fNode->GetStat(&stat); 663 if (error == B_OK) { 664 // no type available -- get the icon for the appropriate type (file/dir/etc.) 665 BMimeType type; 666 if (S_ISREG(stat.st_mode)) { 667 // is it an application (executable) or just a regular file? 668 if ((stat.st_mode & S_IXUSR) != 0) 669 type.SetTo(B_APP_MIME_TYPE); 670 else 671 type.SetTo(B_FILE_MIME_TYPE); 672 } else if (S_ISDIR(stat.st_mode)) { 673 // it's either a volume or just a standard directory 674 fs_info info; 675 if (fs_stat_dev(stat.st_dev, &info) == 0 && stat.st_ino == info.root) 676 type.SetTo(B_VOLUME_MIME_TYPE); 677 else 678 type.SetTo(B_DIRECTORY_MIME_TYPE); 679 } else if (S_ISLNK(stat.st_mode)) 680 type.SetTo(B_SYMLINK_MIME_TYPE); 681 682 success = (type.GetIcon(icon, iconSize) == B_OK); 683 // NOTE: if there is an icon but getting it failes for some reason, 684 // the error is not reported, and the fall back retrieval methods 685 // are still tried. (IAW, we can't differentiate the reason for error.) 686 } 687 } 688 } 689 690 // Ask GetIcon(). 691 if (error == B_OK && !success) 692 success = (GetIcon(icon, iconSize) == B_OK); 693 694 // Get the preferred application and ask the MIME database, if that 695 // application has a special icon for the node's file type. 696 if (error == B_OK && !success) { 697 char signature[B_MIME_TYPE_LENGTH]; 698 if (GetPreferredApp(signature) == B_OK) { 699 BMimeType type(signature); 700 success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK); 701 } 702 } 703 704 // Ask the MIME database whether there is an icon for the node's file type. 705 BMimeType nodeType; 706 if (error == B_OK && !success) { 707 nodeType.SetTo(mimeString); 708 success = (nodeType.GetIcon(icon, iconSize) == B_OK); 709 } 710 711 // Ask the MIME database for the preferred application for the node's 712 // file type and whether this application has a special icon for the type. 713 if (error == B_OK && !success) { 714 char signature[B_MIME_TYPE_LENGTH]; 715 if (nodeType.GetPreferredApp(signature) == B_OK) { 716 BMimeType type(signature); 717 success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK); 718 } 719 } 720 721 // Return the icon for "application/octet-stream" from the MIME database. 722 if (error == B_OK && !success) { 723 // get the "application/octet-stream" icon 724 BMimeType type(B_FILE_MIME_TYPE); 725 error = type.GetIcon(icon, iconSize); 726 success = (error == B_OK); 727 } 728 return error; 729 } 730 731 // GetTrackerIcon 732 /*! \brief Gets the icon which tracker displays for the node referred to by 733 the supplied entry_ref. 734 735 This methods works similar to the non-static version. The first argument 736 \a ref identifies the node in question. 737 738 \param ref An entry_ref referring to the node for which the icon shall be 739 retrieved. 740 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 741 to store the requested icon (16x16 for the mini and 32x32 for the 742 large icon). 743 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 744 for the mini and \c B_LARGE_ICON for the large icon. 745 \return 746 - \c B_OK: Everything went fine. 747 - \c B_NO_INIT: The object is not properly initialized. 748 - \c B_BAD_VALUE: \c NULL ref or \a icon, unsupported icon size \a iconSize or 749 bitmap dimensions (\a icon) and icon size (\a iconSize) do not match. 750 - other error codes 751 */ 752 status_t 753 BNodeInfo::GetTrackerIcon(const entry_ref *ref, BBitmap *icon, icon_size iconSize) 754 { 755 // check ref param 756 status_t error = (ref ? B_OK : B_BAD_VALUE); 757 758 // init a BNode 759 BNode node; 760 if (error == B_OK) 761 error = node.SetTo(ref); 762 763 // init a BNodeInfo 764 BNodeInfo nodeInfo; 765 if (error == B_OK) 766 error = nodeInfo.SetTo(&node); 767 768 // let the non-static GetTrackerIcon() do the dirty work 769 if (error == B_OK) 770 error = nodeInfo.GetTrackerIcon(icon, iconSize); 771 return error; 772 } 773 774 // TODO: just here for providing binary compatibility 775 // (for example "Guido" needs this) 776 extern "C" 777 status_t 778 GetTrackerIcon__9BNodeInfoP9entry_refP7BBitmap9icon_size( 779 BNodeInfo *nodeInfo, entry_ref* ref, 780 BBitmap* bitmap, icon_size iconSize) 781 { 782 // NOTE: nodeInfo is ignored - maybe that's wrong! 783 return BNodeInfo::GetTrackerIcon(ref, bitmap, iconSize); 784 } 785 786 void 787 BNodeInfo::_ReservedNodeInfo1() 788 { 789 } 790 791 void 792 BNodeInfo::_ReservedNodeInfo2() 793 { 794 } 795 796 void 797 BNodeInfo::_ReservedNodeInfo3() 798 { 799 } 800 801 // = 802 /*! \brief Privatized assignment operator to prevent usage. 803 */ 804 BNodeInfo & 805 BNodeInfo::operator=(const BNodeInfo &nodeInfo) 806 { 807 return *this; 808 } 809 810 // copy constructor 811 /*! \brief Privatized copy constructor to prevent usage. 812 */ 813 BNodeInfo::BNodeInfo(const BNodeInfo &) 814 { 815 } 816 817 818 // #pragma mark - 819 820 namespace BPrivate { 821 822 /*! 823 Private function used by Tracker. Should be moved into the Tracker sources. 824 */ 825 extern bool 826 CheckNodeIconHintPrivate(const BNode *node, bool checkMiniIconOnly) 827 { 828 attr_info info; 829 if (node->GetAttrInfo(kNIMiniIconAttribute, &info) != B_OK && checkMiniIconOnly) 830 return false; 831 832 if (node->GetAttrInfo(kNILargeIconAttribute, &info) != B_OK) 833 return false; 834 835 return true; 836 } 837 838 } // namespace BPrivate 839