1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 // Dedicated to BModel 36 #ifndef _NU_MODEL_H 37 #define _NU_MODEL_H 38 39 40 #include <AppFileInfo.h> 41 #include <Debug.h> 42 #include <Mime.h> 43 #include <StorageDefs.h> 44 #include <String.h> 45 46 #include "IconCache.h" 47 #include "ObjectList.h" 48 49 50 class BPath; 51 class BHandler; 52 class BEntry; 53 class BQuery; 54 55 56 #if __GNUC__ && __GNUC__ < 3 57 // using std::stat instead of just stat here because of what 58 // seems to be a gcc bug involving namespace and struct stat interaction 59 typedef struct std::stat StatStruct; 60 #else 61 // on mwcc std isn't turned on but there is no bug either. 62 // Also seems to be fixed in gcc 3. 63 typedef struct stat StatStruct; 64 #endif 65 66 67 namespace BPrivate { 68 69 enum { 70 kDoesNotSupportType, 71 kSuperhandlerModel, 72 kModelSupportsSupertype, 73 kModelSupportsType, 74 kModelSupportsFile 75 }; 76 77 78 class Model { 79 public: 80 Model(); 81 Model(const Model& other); 82 Model(const BEntry* entry, bool open = false, bool writable = false); 83 Model(const entry_ref*, bool traverse = false, bool open = false, 84 bool writable = false); 85 Model(const node_ref* dirNode, const node_ref* node, const char* name, 86 bool open = false, bool writable = false); 87 ~Model(); 88 89 Model& operator=(const Model&); 90 91 status_t InitCheck() const; 92 93 status_t SetTo(const BEntry*, bool open = false, 94 bool writable = false); 95 status_t SetTo(const entry_ref*, bool traverse = false, 96 bool open = false, bool writable = false); 97 status_t SetTo(const node_ref* dirNode, const node_ref* node, 98 const char* name, bool open = false, bool writable = false); 99 100 int CompareFolderNamesFirst(const Model* compareModel) const; 101 102 // node management 103 status_t OpenNode(bool writable = false); 104 // also used to switch from read-only to writable 105 void CloseNode(); 106 bool IsNodeOpen() const; 107 bool IsNodeOpenForWriting() const; 108 109 status_t UpdateStatAndOpenNode(bool writable = false); 110 // like OpenNode, called on zombie poses to check if they turned 111 // real, starts by rereading the stat structure 112 113 // basic getters 114 const char* Name() const; 115 const entry_ref* EntryRef() const; 116 const node_ref* NodeRef() const; 117 const StatStruct* StatBuf() const; 118 119 BNode* Node() const; 120 // returns NULL if not open 121 void GetPath(BPath*) const; 122 void GetEntry(BEntry*) const; 123 124 const char* MimeType() const; 125 const char* PreferredAppSignature() const; 126 // only not-null if not default for type and not self for app 127 void SetPreferredAppSignature(const char*); 128 129 // type getters 130 bool IsContainer() const; 131 bool IsDesktop() const; 132 bool IsDirectory() const; 133 bool IsFile() const; 134 bool IsQuery() const; 135 bool IsQueryTemplate() const; 136 bool IsExecutable() const; 137 bool IsPrintersDir() const; 138 bool IsSymLink() const; 139 bool InRoot() const; 140 bool IsRoot() const; 141 bool InTrash() const; 142 bool IsTrash() const; 143 bool IsVolume() const; 144 bool IsVirtualDirectory() const; 145 146 IconSource IconFrom() const; 147 void SetIconFrom(IconSource); 148 // where is this model getting it's icon from 149 150 void ResetIconFrom(); 151 // called from the attribute changed calls to force a lookup of 152 // a new icon 153 154 // symlink handling calls, mainly used by the IconCache 155 const Model* ResolveIfLink() const; 156 Model* ResolveIfLink(); 157 // works on anything 158 Model* LinkTo() const; 159 // fast, works only on symlinks 160 void SetLinkTo(Model*); 161 162 status_t GetLongVersionString(BString &, version_kind); 163 status_t GetVersionString(BString &, version_kind); 164 status_t AttrAsString(BString &, int64* value, 165 const char* attributeName, uint32 attributeType); 166 167 // Node monitor update call 168 void UpdateEntryRef(const node_ref* dirRef, const char* name); 169 bool AttrChanged(const char* attrName); 170 // returns true if pose needs to update it's icon, etc. 171 // pass null to force full update 172 bool StatChanged(); 173 // returns true if pose needs to update it's icon 174 175 status_t WatchVolumeAndMountPoint(uint32, BHandler*); 176 // correctly handles boot volume name watching 177 178 bool IsDropTarget(const Model* forDocument = 0, 179 bool traverse = false) const; 180 // if nonzero <forDocument> passed, mime info is used to 181 // resolve if document can be opened 182 // if zero, all executables, directories and volumes pass 183 // if traverse, dereference symlinks 184 bool IsDropTargetForList(const BObjectList<BString>* list) const; 185 // <list> contains mime types of all documents about to be handled 186 // by model 187 188 #if DEBUG 189 void PrintToStream(int32 level = 1, bool deep = false); 190 void TrackIconSource(icon_size); 191 #endif 192 193 bool IsSuperHandler() const; 194 int32 SupportsMimeType(const char* type, 195 const BObjectList<BString>* list, bool exactReason = false) const; 196 // pass in one string in <type> or a bunch in <list> 197 // if <exactReason> false, returns as soon as it figures out that 198 // app supports a given type, if true, returns an exact reason 199 200 // get rid of this?? 201 ssize_t WriteAttr(const char* attr, type_code type, off_t, 202 const void* buffer, size_t ); 203 // cover call, creates a writable node and writes out attributes 204 // into it; work around for file nodes not being writeable 205 ssize_t WriteAttrKillForeign(const char* attr, 206 const char* foreignAttr, type_code type, off_t, 207 const void* buffer, size_t); 208 209 bool Mimeset(bool force); 210 // returns true if mime type changed 211 212 bool HasLocalizedName() const; 213 214 private: 215 status_t OpenNodeCommon(bool writable); 216 void SetupBaseType(); 217 void FinishSettingUpType(); 218 bool ShouldUseWellKnownIcon() const; 219 bool CheckAppIconHint() const; 220 void DeletePreferredAppVolumeNameLinkTo(); 221 void CacheLocalizedName(); 222 223 status_t FetchOneQuery(const BQuery*, BHandler* target, 224 BObjectList<BQuery>*, BVolume*); 225 226 enum CanHandleResult { 227 kCanHandle, 228 kCannotHandle, 229 kNeedToCheckType 230 }; 231 232 CanHandleResult CanHandleDrops() const; 233 234 enum NodeType { 235 kPlainNode, 236 kExecutableNode, 237 kDirectoryNode, 238 kLinkNode, 239 kQueryNode, 240 kQueryTemplateNode, 241 kVolumeNode, 242 kRootNode, 243 kTrashNode, 244 kDesktopNode, 245 kVirtualDirectoryNode, 246 kUnknownNode 247 }; 248 249 entry_ref fEntryRef; 250 StatStruct fStatBuf; 251 BString fMimeType; 252 // should use string that may be shared for common types 253 254 // bit of overloading hackery here to save on footprint 255 union { 256 char* fPreferredAppName; // used if we are neither a volume 257 // nor a symlink 258 char* fVolumeName; // used if we are a volume 259 Model* fLinkTo; // used if we are a symlink 260 }; 261 262 uint8 fBaseType; 263 uint8 fIconFrom; 264 bool fWritable; 265 BNode* fNode; 266 status_t fStatus; 267 BString fLocalizedName; 268 bool fHasLocalizedName; 269 bool fLocalizedNameIsCached; 270 }; 271 272 273 class ModelNodeLazyOpener { 274 // a utility open state manager, usefull to allocate on stack 275 // and have close up model when done, etc. 276 public: 277 // consider failing when open does not succeed 278 279 ModelNodeLazyOpener(Model* model, bool writable = false, 280 bool openLater = true); 281 ~ModelNodeLazyOpener(); 282 283 bool IsOpen() const; 284 bool IsOpenForWriting() const; 285 bool IsOpen(bool forWriting) const; 286 Model* TargetModel() const; 287 status_t OpenNode(bool writable = false); 288 289 private: 290 Model* fModel; 291 bool fWasOpen; 292 bool fWasOpenForWriting; 293 }; 294 295 // handy flavors of openers 296 class BModelOpener : public ModelNodeLazyOpener { 297 public: 298 BModelOpener(Model* model) 299 : ModelNodeLazyOpener(model, false, false) 300 { 301 } 302 }; 303 304 class BModelWriteOpener : public ModelNodeLazyOpener { 305 public: 306 BModelWriteOpener(Model* model) 307 : ModelNodeLazyOpener(model, true, false) 308 { 309 } 310 }; 311 312 313 #if DEBUG 314 // #define CHECK_OPEN_MODEL_LEAKS 315 #endif 316 317 #ifdef CHECK_OPEN_MODEL_LEAKS 318 void DumpOpenModels(bool extensive); 319 void InitOpenModelDumping(); 320 #endif 321 322 // inlines follow ----------------------------------- 323 324 inline const char* 325 Model::MimeType() const 326 { 327 return fMimeType.String(); 328 } 329 330 331 inline const entry_ref* 332 Model::EntryRef() const 333 { 334 return &fEntryRef; 335 } 336 337 338 inline const node_ref* 339 Model::NodeRef() const 340 { 341 // the stat structure begins with a node_ref 342 return (node_ref*)&fStatBuf; 343 } 344 345 346 inline BNode* 347 Model::Node() const 348 { 349 return fNode; 350 } 351 352 353 inline const StatStruct* 354 Model::StatBuf() const 355 { 356 return &fStatBuf; 357 } 358 359 360 inline IconSource 361 Model::IconFrom() const 362 { 363 return (IconSource)fIconFrom; 364 } 365 366 367 inline void 368 Model::SetIconFrom(IconSource from) 369 { 370 fIconFrom = from; 371 } 372 373 374 inline Model* 375 Model::LinkTo() const 376 { 377 ASSERT(IsSymLink()); 378 return fLinkTo; 379 } 380 381 382 inline bool 383 Model::IsContainer() const 384 { 385 // I guess as in should show container window - 386 // volumes show the volume window 387 return IsQuery() || IsDirectory() || IsVirtualDirectory(); 388 } 389 390 391 inline bool 392 Model::IsDesktop() const 393 { 394 return fBaseType == kDesktopNode; 395 } 396 397 398 inline bool 399 Model::IsDirectory() const 400 { 401 switch (fBaseType) { 402 case kDirectoryNode: 403 case kVolumeNode: 404 case kRootNode: 405 case kTrashNode: 406 case kDesktopNode: 407 return true; 408 } 409 410 return false; 411 } 412 413 414 inline bool 415 Model::IsFile() const 416 { 417 switch (fBaseType) { 418 case kPlainNode: 419 case kQueryNode: 420 case kQueryTemplateNode: 421 case kExecutableNode: 422 case kVirtualDirectoryNode: 423 return true; 424 } 425 426 return false; 427 } 428 429 430 inline bool 431 Model::IsExecutable() const 432 { 433 return fBaseType == kExecutableNode; 434 } 435 436 437 inline bool 438 Model::IsQuery() const 439 { 440 return fBaseType == kQueryNode; 441 } 442 443 444 inline bool 445 Model::IsQueryTemplate() const 446 { 447 return fBaseType == kQueryTemplateNode; 448 } 449 450 451 inline bool 452 Model::IsSymLink() const 453 { 454 return fBaseType == kLinkNode; 455 } 456 457 458 inline bool 459 Model::IsRoot() const 460 { 461 return fBaseType == kRootNode; 462 } 463 464 465 inline bool 466 Model::IsTrash() const 467 { 468 return fBaseType == kTrashNode; 469 } 470 471 472 inline bool 473 Model::IsVirtualDirectory() const 474 { 475 return fBaseType == kVirtualDirectoryNode; 476 } 477 478 479 inline bool 480 Model::IsVolume() const 481 { 482 return fBaseType == kVolumeNode; 483 } 484 485 486 inline bool 487 Model::HasLocalizedName() const 488 { 489 return fHasLocalizedName; 490 } 491 492 493 inline 494 ModelNodeLazyOpener::ModelNodeLazyOpener(Model* model, bool writable, 495 bool openLater) 496 : 497 fModel(model), 498 fWasOpen(model->IsNodeOpen()), 499 fWasOpenForWriting(model->IsNodeOpenForWriting()) 500 { 501 if (!openLater) 502 OpenNode(writable); 503 } 504 505 506 inline 507 ModelNodeLazyOpener::~ModelNodeLazyOpener() 508 { 509 if (!fModel->IsNodeOpen()) 510 return; 511 if (!fWasOpen) 512 fModel->CloseNode(); 513 else if (!fWasOpenForWriting) 514 fModel->OpenNode(); 515 } 516 517 518 inline bool 519 ModelNodeLazyOpener::IsOpen() const 520 { 521 return fModel->IsNodeOpen(); 522 } 523 524 525 inline bool 526 ModelNodeLazyOpener::IsOpenForWriting() const 527 { 528 return fModel->IsNodeOpenForWriting(); 529 } 530 531 532 inline bool 533 ModelNodeLazyOpener::IsOpen(bool forWriting) const 534 { 535 return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen(); 536 } 537 538 539 inline Model* 540 ModelNodeLazyOpener::TargetModel() const 541 { 542 return fModel; 543 } 544 545 546 inline status_t 547 ModelNodeLazyOpener::OpenNode(bool writable) 548 { 549 if (writable) { 550 if (!fModel->IsNodeOpenForWriting()) 551 return fModel->OpenNode(true); 552 } else if (!fModel->IsNodeOpen()) 553 return fModel->OpenNode(); 554 555 return B_OK; 556 } 557 558 } // namespace BPrivate 559 560 561 #endif // _NU_MODEL_H 562