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