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 37 #ifndef _NU_MODEL_H 38 #define _NU_MODEL_H 39 40 #include <AppFileInfo.h> 41 #include <Mime.h> 42 #include <StorageDefs.h> 43 #include <String.h> 44 45 #include "IconCache.h" 46 #include "ObjectList.h" 47 48 49 class BPath; 50 class BHandler; 51 class BEntry; 52 class BQuery; 53 54 #if __GNUC__ && __GNUC__ < 3 55 // using std::stat instead of just stat here because of what 56 // seems to be a gcc bug involving namespace and struct stat interaction 57 typedef struct std::stat StatStruct; 58 #else 59 // on mwcc std isn't turned on but there is no bug either. 60 // Also seems to be fixed in gcc 3. 61 typedef struct stat StatStruct; 62 #endif 63 64 namespace BPrivate { 65 66 enum { 67 kDoesNotSupportType, 68 kSuperhandlerModel, 69 kModelSupportsSupertype, 70 kModelSupportsType, 71 kModelSupportsFile 72 }; 73 74 class Model { 75 public: 76 Model(); 77 Model(const Model &); 78 Model(const BEntry *entry, bool open = false, bool writable = false); 79 Model(const entry_ref *, bool traverse = false, bool open = false, 80 bool writable = false); 81 Model(const node_ref *dirNode, const node_ref *node, const char *name, 82 bool open = false, bool writable = false); 83 ~Model(); 84 85 Model& operator=(const Model &); 86 87 status_t InitCheck() const; 88 89 status_t SetTo(const BEntry *, bool open = false, bool writable = false); 90 status_t SetTo(const entry_ref *, bool traverse = false, bool open = false, 91 bool writable = false); 92 status_t SetTo(const node_ref *dirNode, const node_ref *node, const char *name, 93 bool open = false, bool writable = false); 94 95 int CompareFolderNamesFirst(const Model *compareModel) const; 96 97 // node management 98 status_t OpenNode(bool writable = false); 99 // also used to switch from read-only to writable 100 void CloseNode(); 101 bool IsNodeOpen() const; 102 bool IsNodeOpenForWriting() const; 103 104 status_t UpdateStatAndOpenNode(bool writable = false); 105 // like OpenNode, called on zombie poses to check if they turned 106 // real, starts by rereading the stat structure 107 108 // basic getters 109 const char *Name() const; 110 const entry_ref *EntryRef() const; 111 const node_ref *NodeRef() const; 112 const StatStruct *StatBuf() const; 113 114 BNode *Node() const; 115 // returns null if not Open 116 void GetPath(BPath *) const; 117 void GetEntry(BEntry *) const; 118 119 const char *MimeType() const; 120 const char *PreferredAppSignature() const; 121 // only not-null if not default for type and not self for app 122 void SetPreferredAppSignature(const char *); 123 124 void GetPreferredAppForBrokenSymLink(BString &result); 125 // special purpose call - if a symlink is unresolvable, it makes sense 126 // to be able to get at it's preferred handler which may be different 127 // from the Tracker. Used by the network neighborhood. 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 142 IconSource IconFrom() const; 143 void SetIconFrom(IconSource); 144 // where is this model getting it's icon from 145 146 void ResetIconFrom(); 147 // called from the attribute changed calls to force a lookup of 148 // a new icon 149 150 // symlink handling calls, mainly used by the IconCache 151 const Model *ResolveIfLink() const; 152 Model *ResolveIfLink(); 153 // works on anything 154 Model *LinkTo() const; 155 // fast, works only on symlinks 156 void SetLinkTo(Model *); 157 158 status_t GetLongVersionString(BString &, version_kind); 159 status_t GetVersionString(BString &, version_kind); 160 status_t AttrAsString(BString &, int64 *value, const char *attributeName, 161 uint32 attributeType); 162 163 // Node monitor update call 164 void UpdateEntryRef(const node_ref *dirRef, const char *name); 165 bool AttrChanged(const char *); 166 // returns true if pose needs to update it's icon, etc. 167 // pass null to force full update 168 bool StatChanged(); 169 // returns true if pose needs to update it's icon 170 171 status_t WatchVolumeAndMountPoint(uint32, BHandler *); 172 // correctly handles boot volume name watching 173 174 bool IsDropTarget(const Model *forDocument = 0, 175 bool traverse = false) const; 176 // if nonzero <forDocument> passed, mime info is used to 177 // resolve if document can be opened 178 // if zero, all executables, directories and volumes pass 179 // if traverse, dereference symlinks 180 bool IsDropTargetForList(const BObjectList<BString> *list) const; 181 // <list> contains mime types of all documents about to be handled 182 // by model 183 184 #if DEBUG 185 void PrintToStream(int32 level = 1, bool deep = false); 186 void TrackIconSource(icon_size); 187 #endif 188 189 bool IsSuperHandler() const; 190 int32 SupportsMimeType(const char *type, const BObjectList<BString> *list, 191 bool exactReason = false) const; 192 // pass in one string in <type> or a bunch in <list> 193 // if <exactReason> false, returns as soon as it figures out that 194 // app supports a given type, if true, returns an exact reason 195 196 // get rid of this?? 197 ssize_t WriteAttr(const char *attr, type_code type, off_t, 198 const void *buffer, size_t ); 199 // cover call, creates a writable node and writes out attributes 200 // into it; work around for file nodes not being writeable 201 ssize_t WriteAttrKillForeign(const char *attr, const char *foreignAttr, 202 type_code type, off_t, const void *buffer, size_t); 203 204 bool Mimeset(bool force); 205 // returns true if mime type changed 206 private: 207 status_t OpenNodeCommon(bool writable); 208 void SetupBaseType(); 209 void FinishSettingUpType(); 210 void DeletePreferredAppVolumeNameLinkTo(); 211 212 status_t FetchOneQuery(const BQuery *, BHandler *target, 213 BObjectList<BQuery>*, BVolume *); 214 215 enum CanHandleResult { 216 kCanHandle, 217 kCannotHandle, 218 kNeedToCheckType 219 }; 220 221 CanHandleResult CanHandleDrops() const; 222 223 enum NodeType { 224 kPlainNode, 225 kExecutableNode, 226 kDirectoryNode, 227 kLinkNode, 228 kQueryNode, 229 kQueryTemplateNode, 230 kVolumeNode, 231 kRootNode, 232 kTrashNode, 233 kDesktopNode, 234 kUnknownNode 235 }; 236 237 entry_ref fEntryRef; 238 StatStruct fStatBuf; 239 BString fMimeType; // should use string that may be shared for common types 240 241 // bit of overloading hackery here to save on footprint 242 union { 243 char *fPreferredAppName; // used if we are neither a volume nor a symlink 244 char *fVolumeName; // used if we are a volume 245 Model *fLinkTo; // used if we are a symlink 246 }; 247 248 uint8 fBaseType; 249 uint8 fIconFrom; 250 bool fWritable; 251 BNode *fNode; 252 status_t fStatus; 253 }; 254 255 256 class ModelNodeLazyOpener { 257 // a utility open state manager, usefull to allocate on stack 258 // and have close up model when done, etc. 259 public: 260 // consider failing when open does not succeed 261 262 ModelNodeLazyOpener(Model *model, bool writable = false, bool openLater = true); 263 ~ModelNodeLazyOpener(); 264 265 bool IsOpen() const; 266 bool IsOpenForWriting() const; 267 bool IsOpen(bool forWriting) const; 268 Model *TargetModel() const; 269 status_t OpenNode(bool writable = false); 270 271 private: 272 Model *fModel; 273 bool fWasOpen; 274 bool fWasOpenForWriting; 275 }; 276 277 // handy flavors of openers 278 class BModelOpener : public ModelNodeLazyOpener { 279 public: 280 BModelOpener(Model *model) 281 : ModelNodeLazyOpener(model, false, false) 282 { 283 } 284 }; 285 286 class BModelWriteOpener : public ModelNodeLazyOpener { 287 public: 288 BModelWriteOpener(Model *model) 289 : ModelNodeLazyOpener(model, true, false) 290 { 291 } 292 }; 293 294 295 #if DEBUG 296 // #define CHECK_OPEN_MODEL_LEAKS 297 #endif 298 299 #ifdef CHECK_OPEN_MODEL_LEAKS 300 void DumpOpenModels(bool extensive); 301 void InitOpenModelDumping(); 302 #endif 303 304 // inlines follow ----------------------------------- 305 306 inline const char * 307 Model::MimeType() const 308 { 309 return fMimeType.String(); 310 } 311 312 313 inline const entry_ref * 314 Model::EntryRef() const 315 { 316 return &fEntryRef; 317 } 318 319 320 inline const node_ref * 321 Model::NodeRef() const 322 { 323 // the stat structure begins with a node_ref 324 return (node_ref *)&fStatBuf; 325 } 326 327 328 inline BNode * 329 Model::Node() const 330 { 331 return fNode; 332 } 333 334 335 inline const StatStruct * 336 Model::StatBuf() const 337 { 338 return &fStatBuf; 339 } 340 341 342 inline IconSource 343 Model::IconFrom() const 344 { 345 return (IconSource)fIconFrom; 346 } 347 348 349 inline void 350 Model::SetIconFrom(IconSource from) 351 { 352 fIconFrom = from; 353 } 354 355 356 inline Model * 357 Model::LinkTo() const 358 { 359 ASSERT(IsSymLink()); 360 return fLinkTo; 361 } 362 363 364 inline bool 365 Model::IsFile() const 366 { 367 return fBaseType == kPlainNode 368 || fBaseType == kQueryNode 369 || fBaseType == kQueryTemplateNode 370 || fBaseType == kExecutableNode; 371 } 372 373 374 inline bool 375 Model::IsVolume() const 376 { 377 return fBaseType == kVolumeNode; 378 } 379 380 381 inline bool 382 Model::IsDirectory() const 383 { 384 return fBaseType == kDirectoryNode 385 || fBaseType == kVolumeNode 386 || fBaseType == kRootNode 387 || fBaseType == kTrashNode 388 || fBaseType == kDesktopNode; 389 } 390 391 392 inline bool 393 Model::IsQuery() const 394 { 395 return fBaseType == kQueryNode; 396 } 397 398 399 inline bool 400 Model::IsQueryTemplate() const 401 { 402 return fBaseType == kQueryTemplateNode; 403 } 404 405 406 inline bool 407 Model::IsContainer() const 408 { 409 // I guess as in should show container window - 410 // volumes show the volume window 411 return IsQuery() || IsDirectory(); 412 } 413 414 415 inline bool 416 Model::IsRoot() const 417 { 418 return fBaseType == kRootNode; 419 } 420 421 422 inline bool 423 Model::IsTrash() const 424 { 425 return fBaseType == kTrashNode; 426 } 427 428 429 inline bool 430 Model::IsDesktop() const 431 { 432 return fBaseType == kDesktopNode; 433 } 434 435 436 inline bool 437 Model::IsExecutable() const 438 { 439 return fBaseType == kExecutableNode; 440 } 441 442 443 inline bool 444 Model::IsSymLink() const 445 { 446 return fBaseType == kLinkNode; 447 } 448 449 450 inline 451 ModelNodeLazyOpener::ModelNodeLazyOpener(Model *model, bool writable, bool openLater) 452 : fModel(model), 453 fWasOpen(model->IsNodeOpen()), 454 fWasOpenForWriting(model->IsNodeOpenForWriting()) 455 { 456 if (!openLater) 457 OpenNode(writable); 458 } 459 460 461 inline 462 ModelNodeLazyOpener::~ModelNodeLazyOpener() 463 { 464 if (!fModel->IsNodeOpen()) 465 return; 466 if (!fWasOpen) 467 fModel->CloseNode(); 468 else if (!fWasOpenForWriting) 469 fModel->OpenNode(); 470 } 471 472 473 inline bool 474 ModelNodeLazyOpener::IsOpen() const 475 { 476 return fModel->IsNodeOpen(); 477 } 478 479 480 inline bool 481 ModelNodeLazyOpener::IsOpenForWriting() const 482 { 483 return fModel->IsNodeOpenForWriting(); 484 } 485 486 487 inline bool 488 ModelNodeLazyOpener::IsOpen(bool forWriting) const 489 { 490 return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen(); 491 } 492 493 494 inline Model * 495 ModelNodeLazyOpener::TargetModel() const 496 { 497 return fModel; 498 } 499 500 501 inline status_t 502 ModelNodeLazyOpener::OpenNode(bool writable) 503 { 504 if (writable) { 505 if (!fModel->IsNodeOpenForWriting()) 506 return fModel->OpenNode(true); 507 } else if (!fModel->IsNodeOpen()) 508 return fModel->OpenNode(); 509 510 return B_OK; 511 } 512 513 514 } // namespace BPrivate 515 516 517 #endif 518