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:
BModelOpener(Model * model)298 BModelOpener(Model* model)
299 : ModelNodeLazyOpener(model, false, false)
300 {
301 }
302 };
303
304 class BModelWriteOpener : public ModelNodeLazyOpener {
305 public:
BModelWriteOpener(Model * model)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*
MimeType()325 Model::MimeType() const
326 {
327 return fMimeType.String();
328 }
329
330
331 inline const entry_ref*
EntryRef()332 Model::EntryRef() const
333 {
334 return &fEntryRef;
335 }
336
337
338 inline const node_ref*
NodeRef()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*
Node()347 Model::Node() const
348 {
349 return fNode;
350 }
351
352
353 inline const StatStruct*
StatBuf()354 Model::StatBuf() const
355 {
356 return &fStatBuf;
357 }
358
359
360 inline IconSource
IconFrom()361 Model::IconFrom() const
362 {
363 return (IconSource)fIconFrom;
364 }
365
366
367 inline void
SetIconFrom(IconSource from)368 Model::SetIconFrom(IconSource from)
369 {
370 fIconFrom = from;
371 }
372
373
374 inline Model*
LinkTo()375 Model::LinkTo() const
376 {
377 ASSERT(IsSymLink());
378 return fLinkTo;
379 }
380
381
382 inline bool
IsContainer()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
IsDesktop()392 Model::IsDesktop() const
393 {
394 return fBaseType == kDesktopNode;
395 }
396
397
398 inline bool
IsDirectory()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
IsFile()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
IsExecutable()431 Model::IsExecutable() const
432 {
433 return fBaseType == kExecutableNode;
434 }
435
436
437 inline bool
IsQuery()438 Model::IsQuery() const
439 {
440 return fBaseType == kQueryNode;
441 }
442
443
444 inline bool
IsQueryTemplate()445 Model::IsQueryTemplate() const
446 {
447 return fBaseType == kQueryTemplateNode;
448 }
449
450
451 inline bool
IsSymLink()452 Model::IsSymLink() const
453 {
454 return fBaseType == kLinkNode;
455 }
456
457
458 inline bool
IsRoot()459 Model::IsRoot() const
460 {
461 return fBaseType == kRootNode;
462 }
463
464
465 inline bool
IsTrash()466 Model::IsTrash() const
467 {
468 return fBaseType == kTrashNode;
469 }
470
471
472 inline bool
IsVirtualDirectory()473 Model::IsVirtualDirectory() const
474 {
475 return fBaseType == kVirtualDirectoryNode;
476 }
477
478
479 inline bool
IsVolume()480 Model::IsVolume() const
481 {
482 return fBaseType == kVolumeNode;
483 }
484
485
486 inline bool
HasLocalizedName()487 Model::HasLocalizedName() const
488 {
489 return fHasLocalizedName;
490 }
491
492
493 inline
ModelNodeLazyOpener(Model * model,bool writable,bool openLater)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
~ModelNodeLazyOpener()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
IsOpen()519 ModelNodeLazyOpener::IsOpen() const
520 {
521 return fModel->IsNodeOpen();
522 }
523
524
525 inline bool
IsOpenForWriting()526 ModelNodeLazyOpener::IsOpenForWriting() const
527 {
528 return fModel->IsNodeOpenForWriting();
529 }
530
531
532 inline bool
IsOpen(bool forWriting)533 ModelNodeLazyOpener::IsOpen(bool forWriting) const
534 {
535 return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen();
536 }
537
538
539 inline Model*
TargetModel()540 ModelNodeLazyOpener::TargetModel() const
541 {
542 return fModel;
543 }
544
545
546 inline status_t
OpenNode(bool writable)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