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 IsFile() const; 131 bool IsDirectory() const; 132 bool IsQuery() const; 133 bool IsQueryTemplate() const; 134 bool IsContainer() const; 135 bool IsExecutable() const; 136 bool IsSymLink() const; 137 bool IsRoot() const; 138 bool IsTrash() const; 139 bool IsDesktop() const; 140 bool IsVolume() const; 141 bool IsVirtualDirectory() const; 142 143 IconSource IconFrom() const; 144 void SetIconFrom(IconSource); 145 // where is this model getting it's icon from 146 147 void ResetIconFrom(); 148 // called from the attribute changed calls to force a lookup of 149 // a new icon 150 151 // symlink handling calls, mainly used by the IconCache 152 const Model* ResolveIfLink() const; 153 Model* ResolveIfLink(); 154 // works on anything 155 Model* LinkTo() const; 156 // fast, works only on symlinks 157 void SetLinkTo(Model*); 158 159 status_t GetLongVersionString(BString &, version_kind); 160 status_t GetVersionString(BString &, version_kind); 161 status_t AttrAsString(BString &, int64* value, 162 const char* attributeName, uint32 attributeType); 163 164 // Node monitor update call 165 void UpdateEntryRef(const node_ref* dirRef, const char* name); 166 bool AttrChanged(const char* attrName); 167 // returns true if pose needs to update it's icon, etc. 168 // pass null to force full update 169 bool StatChanged(); 170 // returns true if pose needs to update it's icon 171 172 status_t WatchVolumeAndMountPoint(uint32, BHandler*); 173 // correctly handles boot volume name watching 174 175 bool IsDropTarget(const Model* forDocument = 0, 176 bool traverse = false) const; 177 // if nonzero <forDocument> passed, mime info is used to 178 // resolve if document can be opened 179 // if zero, all executables, directories and volumes pass 180 // if traverse, dereference symlinks 181 bool IsDropTargetForList(const BObjectList<BString>* list) const; 182 // <list> contains mime types of all documents about to be handled 183 // by model 184 185 #if DEBUG 186 void PrintToStream(int32 level = 1, bool deep = false); 187 void TrackIconSource(icon_size); 188 #endif 189 190 bool IsSuperHandler() const; 191 int32 SupportsMimeType(const char* type, 192 const BObjectList<BString>* list, bool exactReason = false) const; 193 // pass in one string in <type> or a bunch in <list> 194 // if <exactReason> false, returns as soon as it figures out that 195 // app supports a given type, if true, returns an exact reason 196 197 // get rid of this?? 198 ssize_t WriteAttr(const char* attr, type_code type, off_t, 199 const void* buffer, size_t ); 200 // cover call, creates a writable node and writes out attributes 201 // into it; work around for file nodes not being writeable 202 ssize_t WriteAttrKillForeign(const char* attr, 203 const char* foreignAttr, type_code type, off_t, 204 const void* buffer, size_t); 205 206 bool Mimeset(bool force); 207 // returns true if mime type changed 208 209 bool HasLocalizedName() const; 210 211 private: 212 status_t OpenNodeCommon(bool writable); 213 void SetupBaseType(); 214 void FinishSettingUpType(); 215 bool CheckNodeIconHint() const; 216 bool CheckAppIconHint() const; 217 void DeletePreferredAppVolumeNameLinkTo(); 218 void CacheLocalizedName(); 219 220 status_t FetchOneQuery(const BQuery*, BHandler* target, 221 BObjectList<BQuery>*, BVolume*); 222 223 enum CanHandleResult { 224 kCanHandle, 225 kCannotHandle, 226 kNeedToCheckType 227 }; 228 229 CanHandleResult CanHandleDrops() const; 230 231 enum NodeType { 232 kPlainNode, 233 kExecutableNode, 234 kDirectoryNode, 235 kLinkNode, 236 kQueryNode, 237 kQueryTemplateNode, 238 kVolumeNode, 239 kRootNode, 240 kTrashNode, 241 kDesktopNode, 242 kVirtualDirectoryNode, 243 kUnknownNode 244 }; 245 246 entry_ref fEntryRef; 247 StatStruct fStatBuf; 248 BString fMimeType; 249 // should use string that may be shared for common types 250 251 // bit of overloading hackery here to save on footprint 252 union { 253 char* fPreferredAppName; // used if we are neither a volume 254 // nor a symlink 255 char* fVolumeName; // used if we are a volume 256 Model* fLinkTo; // used if we are a symlink 257 }; 258 259 uint8 fBaseType; 260 uint8 fIconFrom; 261 bool fWritable; 262 BNode* fNode; 263 status_t fStatus; 264 BString fLocalizedName; 265 bool fHasLocalizedName; 266 bool fLocalizedNameIsCached; 267 }; 268 269 270 class ModelNodeLazyOpener { 271 // a utility open state manager, usefull to allocate on stack 272 // and have close up model when done, etc. 273 public: 274 // consider failing when open does not succeed 275 276 ModelNodeLazyOpener(Model* model, bool writable = false, 277 bool openLater = true); 278 ~ModelNodeLazyOpener(); 279 280 bool IsOpen() const; 281 bool IsOpenForWriting() const; 282 bool IsOpen(bool forWriting) const; 283 Model* TargetModel() const; 284 status_t OpenNode(bool writable = false); 285 286 private: 287 Model* fModel; 288 bool fWasOpen; 289 bool fWasOpenForWriting; 290 }; 291 292 // handy flavors of openers 293 class BModelOpener : public ModelNodeLazyOpener { 294 public: 295 BModelOpener(Model* model) 296 : ModelNodeLazyOpener(model, false, false) 297 { 298 } 299 }; 300 301 class BModelWriteOpener : public ModelNodeLazyOpener { 302 public: 303 BModelWriteOpener(Model* model) 304 : ModelNodeLazyOpener(model, true, false) 305 { 306 } 307 }; 308 309 310 #if DEBUG 311 // #define CHECK_OPEN_MODEL_LEAKS 312 #endif 313 314 #ifdef CHECK_OPEN_MODEL_LEAKS 315 void DumpOpenModels(bool extensive); 316 void InitOpenModelDumping(); 317 #endif 318 319 // inlines follow ----------------------------------- 320 321 inline const char* 322 Model::MimeType() const 323 { 324 return fMimeType.String(); 325 } 326 327 328 inline const entry_ref* 329 Model::EntryRef() const 330 { 331 return &fEntryRef; 332 } 333 334 335 inline const node_ref* 336 Model::NodeRef() const 337 { 338 // the stat structure begins with a node_ref 339 return (node_ref*)&fStatBuf; 340 } 341 342 343 inline BNode* 344 Model::Node() const 345 { 346 return fNode; 347 } 348 349 350 inline const StatStruct* 351 Model::StatBuf() const 352 { 353 return &fStatBuf; 354 } 355 356 357 inline IconSource 358 Model::IconFrom() const 359 { 360 return (IconSource)fIconFrom; 361 } 362 363 364 inline void 365 Model::SetIconFrom(IconSource from) 366 { 367 fIconFrom = from; 368 } 369 370 371 inline Model* 372 Model::LinkTo() const 373 { 374 ASSERT(IsSymLink()); 375 return fLinkTo; 376 } 377 378 379 inline bool 380 Model::IsFile() const 381 { 382 return fBaseType == kPlainNode 383 || fBaseType == kQueryNode 384 || fBaseType == kQueryTemplateNode 385 || fBaseType == kExecutableNode 386 || fBaseType == kVirtualDirectoryNode; 387 } 388 389 390 inline bool 391 Model::IsVolume() const 392 { 393 return fBaseType == kVolumeNode; 394 } 395 396 397 inline bool 398 Model::IsDirectory() const 399 { 400 return fBaseType == kDirectoryNode 401 || fBaseType == kVolumeNode 402 || fBaseType == kRootNode 403 || fBaseType == kTrashNode 404 || fBaseType == kDesktopNode; 405 } 406 407 408 inline bool 409 Model::IsQuery() const 410 { 411 return fBaseType == kQueryNode; 412 } 413 414 415 inline bool 416 Model::IsQueryTemplate() const 417 { 418 return fBaseType == kQueryTemplateNode; 419 } 420 421 422 inline bool 423 Model::IsContainer() const 424 { 425 // I guess as in should show container window - 426 // volumes show the volume window 427 return IsQuery() || IsDirectory() || IsVirtualDirectory(); 428 } 429 430 431 inline bool 432 Model::IsRoot() const 433 { 434 return fBaseType == kRootNode; 435 } 436 437 438 inline bool 439 Model::IsTrash() const 440 { 441 return fBaseType == kTrashNode; 442 } 443 444 445 inline bool 446 Model::IsDesktop() const 447 { 448 return fBaseType == kDesktopNode; 449 } 450 451 452 inline bool 453 Model::IsExecutable() const 454 { 455 return fBaseType == kExecutableNode; 456 } 457 458 459 inline bool 460 Model::IsSymLink() const 461 { 462 return fBaseType == kLinkNode; 463 } 464 465 466 inline bool 467 Model::IsVirtualDirectory() const 468 { 469 return fBaseType == kVirtualDirectoryNode; 470 } 471 472 473 inline bool 474 Model::HasLocalizedName() const 475 { 476 return fHasLocalizedName; 477 } 478 479 480 inline 481 ModelNodeLazyOpener::ModelNodeLazyOpener(Model* model, bool writable, 482 bool openLater) 483 : 484 fModel(model), 485 fWasOpen(model->IsNodeOpen()), 486 fWasOpenForWriting(model->IsNodeOpenForWriting()) 487 { 488 if (!openLater) 489 OpenNode(writable); 490 } 491 492 493 inline 494 ModelNodeLazyOpener::~ModelNodeLazyOpener() 495 { 496 if (!fModel->IsNodeOpen()) 497 return; 498 if (!fWasOpen) 499 fModel->CloseNode(); 500 else if (!fWasOpenForWriting) 501 fModel->OpenNode(); 502 } 503 504 505 inline bool 506 ModelNodeLazyOpener::IsOpen() const 507 { 508 return fModel->IsNodeOpen(); 509 } 510 511 512 inline bool 513 ModelNodeLazyOpener::IsOpenForWriting() const 514 { 515 return fModel->IsNodeOpenForWriting(); 516 } 517 518 519 inline bool 520 ModelNodeLazyOpener::IsOpen(bool forWriting) const 521 { 522 return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen(); 523 } 524 525 526 inline Model* 527 ModelNodeLazyOpener::TargetModel() const 528 { 529 return fModel; 530 } 531 532 533 inline status_t 534 ModelNodeLazyOpener::OpenNode(bool writable) 535 { 536 if (writable) { 537 if (!fModel->IsNodeOpenForWriting()) 538 return fModel->OpenNode(true); 539 } else if (!fModel->IsNodeOpen()) 540 return fModel->OpenNode(); 541 542 return B_OK; 543 } 544 545 } // namespace BPrivate 546 547 548 #endif // _NU_MODEL_H 549