xref: /haiku/src/kits/tracker/Model.h (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
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 <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 #if __GNUC__ && __GNUC__ < 3
56 // using std::stat instead of just stat here because of what
57 // seems to be a gcc bug involving namespace and struct stat interaction
58 typedef struct std::stat StatStruct;
59 #else
60 // on mwcc std isn't turned on but there is no bug either.
61 // Also seems to be fixed in gcc 3.
62 typedef struct stat StatStruct;
63 #endif
64 
65 namespace BPrivate {
66 
67 enum {
68 	kDoesNotSupportType,
69 	kSuperhandlerModel,
70 	kModelSupportsSupertype,
71 	kModelSupportsType,
72 	kModelSupportsFile
73 };
74 
75 class Model {
76 	public:
77 		Model();
78 		Model(const Model &);
79 		Model(const BEntry *entry, bool open = false, bool writable = false);
80 		Model(const entry_ref *, bool traverse = false, bool open = false,
81 			bool writable = false);
82 		Model(const node_ref *dirNode, const node_ref *node, const char *name,
83 			bool open = false, bool writable = false);
84 		~Model();
85 
86 		Model& operator=(const Model &);
87 
88 		status_t InitCheck() const;
89 
90 		status_t SetTo(const BEntry *, bool open = false, bool writable = false);
91 		status_t SetTo(const entry_ref *, bool traverse = false, bool open = false,
92 			bool writable = false);
93 		status_t SetTo(const node_ref *dirNode, const node_ref *node, const char *name,
94 			bool open = false, bool writable = false);
95 
96 		int CompareFolderNamesFirst(const Model *compareModel) const;
97 
98 		// node management
99 		status_t OpenNode(bool writable = false);
100 			// also used to switch from read-only to writable
101 		void CloseNode();
102 		bool IsNodeOpen() const;
103 		bool IsNodeOpenForWriting() const;
104 
105 		status_t UpdateStatAndOpenNode(bool writable = false);
106 			// like OpenNode, called on zombie poses to check if they turned
107 			// real, starts by rereading the stat structure
108 
109 		// basic getters
110 		const char *Name() const;
111 		const entry_ref *EntryRef() const;
112 		const node_ref *NodeRef() const;
113 		const StatStruct *StatBuf() const;
114 
115 		BNode *Node() const;
116 			// returns null if not Open
117 		void GetPath(BPath *) const;
118 		void GetEntry(BEntry *) const;
119 
120 		const char *MimeType() const;
121 		const char *PreferredAppSignature() const;
122 			// only not-null if not default for type and not self for app
123 		void SetPreferredAppSignature(const char *);
124 
125 		void GetPreferredAppForBrokenSymLink(BString &result);
126 			// special purpose call - if a symlink is unresolvable, it makes sense
127 			// to be able to get at it's preferred handler which may be different
128 			// from the Tracker. Used by the network neighborhood.
129 
130 		// type getters
131 		bool IsFile() const;
132 		bool IsDirectory() const;
133 		bool IsQuery() const;
134 		bool IsQueryTemplate() const;
135 		bool IsContainer() const;
136 		bool IsExecutable() const;
137 		bool IsSymLink() const;
138 		bool IsRoot() const;
139 		bool IsTrash() const;
140 		bool IsDesktop() const;
141 		bool IsVolume() 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, const char *attributeName,
162 			uint32 attributeType);
163 
164 		// Node monitor update call
165 		void UpdateEntryRef(const node_ref *dirRef, const char *name);
166 		bool AttrChanged(const char *);
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, const BObjectList<BString> *list,
192 			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, const char *foreignAttr,
203 			type_code type, off_t, const void *buffer, size_t);
204 
205 		bool Mimeset(bool force);
206 			// returns true if mime type changed
207 
208 		bool HasLocalizedName() const;
209 
210 	private:
211 		status_t OpenNodeCommon(bool writable);
212 		void SetupBaseType();
213 		void FinishSettingUpType();
214 		void DeletePreferredAppVolumeNameLinkTo();
215 		void CacheLocalizedName();
216 
217 		status_t FetchOneQuery(const BQuery *, BHandler *target,
218 			BObjectList<BQuery>*, BVolume *);
219 
220 		enum CanHandleResult {
221 			kCanHandle,
222 			kCannotHandle,
223 			kNeedToCheckType
224 		};
225 
226 		CanHandleResult CanHandleDrops() const;
227 
228 		enum NodeType {
229 			kPlainNode,
230 			kExecutableNode,
231 			kDirectoryNode,
232 			kLinkNode,
233 			kQueryNode,
234 			kQueryTemplateNode,
235 			kVolumeNode,
236 			kRootNode,
237 			kTrashNode,
238 			kDesktopNode,
239 			kUnknownNode
240 		};
241 
242 		entry_ref fEntryRef;
243 		StatStruct fStatBuf;
244 		BString fMimeType;		// should use string that may be shared for common types
245 
246 		// bit of overloading hackery here to save on footprint
247 		union {
248 			char *fPreferredAppName;	// used if we are neither a volume nor a symlink
249 			char *fVolumeName;			// used if we are a volume
250 			Model *fLinkTo;				// used if we are a symlink
251 		};
252 
253 		uint8 fBaseType;
254 		uint8 fIconFrom;
255 		bool fWritable;
256 		BNode *fNode;
257 		status_t fStatus;
258 		BString fLocalizedName;
259 		bool fHasLocalizedName;
260 };
261 
262 
263 class ModelNodeLazyOpener {
264 	// a utility open state manager, usefull to allocate on stack
265 	// and have close up model when done, etc.
266 	public:
267 		// consider failing when open does not succeed
268 
269 		ModelNodeLazyOpener(Model *model, bool writable = false, bool openLater = true);
270 		~ModelNodeLazyOpener();
271 
272 		bool IsOpen() const;
273 		bool IsOpenForWriting() const;
274 		bool IsOpen(bool forWriting) const;
275 		Model *TargetModel() const;
276 		status_t OpenNode(bool writable = false);
277 
278 	private:
279 		Model *fModel;
280 		bool fWasOpen;
281 		bool fWasOpenForWriting;
282 };
283 
284 // handy flavors of openers
285 class BModelOpener : public ModelNodeLazyOpener {
286 	public:
287 		BModelOpener(Model *model)
288 		:	ModelNodeLazyOpener(model, false, false)
289 		{
290 		}
291 };
292 
293 class BModelWriteOpener : public ModelNodeLazyOpener {
294 	public:
295 		BModelWriteOpener(Model *model)
296 		:	ModelNodeLazyOpener(model, true, false)
297 		{
298 		}
299 };
300 
301 
302 #if DEBUG
303 // #define CHECK_OPEN_MODEL_LEAKS
304 #endif
305 
306 #ifdef CHECK_OPEN_MODEL_LEAKS
307 void DumpOpenModels(bool extensive);
308 void InitOpenModelDumping();
309 #endif
310 
311 // inlines follow -----------------------------------
312 
313 inline const char *
314 Model::MimeType() const
315 {
316 	return fMimeType.String();
317 }
318 
319 
320 inline const entry_ref *
321 Model::EntryRef() const
322 {
323 	return &fEntryRef;
324 }
325 
326 
327 inline const node_ref *
328 Model::NodeRef() const
329 {
330 	// the stat structure begins with a node_ref
331 	return (node_ref *)&fStatBuf;
332 }
333 
334 
335 inline BNode *
336 Model::Node() const
337 {
338 	return fNode;
339 }
340 
341 
342 inline const StatStruct *
343 Model::StatBuf() const
344 {
345 	return &fStatBuf;
346 }
347 
348 
349 inline IconSource
350 Model::IconFrom() const
351 {
352 	return (IconSource)fIconFrom;
353 }
354 
355 
356 inline void
357 Model::SetIconFrom(IconSource from)
358 {
359 	fIconFrom = from;
360 }
361 
362 
363 inline Model *
364 Model::LinkTo() const
365 {
366 	ASSERT(IsSymLink());
367 	return fLinkTo;
368 }
369 
370 
371 inline bool
372 Model::IsFile() const
373 {
374 	return fBaseType == kPlainNode
375 		|| fBaseType == kQueryNode
376 		|| fBaseType == kQueryTemplateNode
377 		|| fBaseType == kExecutableNode;
378 }
379 
380 
381 inline bool
382 Model::IsVolume() const
383 {
384 	return fBaseType == kVolumeNode;
385 }
386 
387 
388 inline bool
389 Model::IsDirectory() const
390 {
391 	return fBaseType == kDirectoryNode
392 		|| fBaseType == kVolumeNode
393 		|| fBaseType == kRootNode
394 		|| fBaseType == kTrashNode
395 		|| fBaseType == kDesktopNode;
396 }
397 
398 
399 inline bool
400 Model::IsQuery() const
401 {
402 	return fBaseType == kQueryNode;
403 }
404 
405 
406 inline bool
407 Model::IsQueryTemplate() const
408 {
409 	return fBaseType == kQueryTemplateNode;
410 }
411 
412 
413 inline bool
414 Model::IsContainer() const
415 {
416 	// I guess as in should show container window -
417 	// volumes show the volume window
418 	return IsQuery() || IsDirectory();
419 }
420 
421 
422 inline bool
423 Model::IsRoot() const
424 {
425 	return fBaseType == kRootNode;
426 }
427 
428 
429 inline bool
430 Model::IsTrash() const
431 {
432 	return fBaseType == kTrashNode;
433 }
434 
435 
436 inline bool
437 Model::IsDesktop() const
438 {
439 	return fBaseType == kDesktopNode;
440 }
441 
442 
443 inline bool
444 Model::IsExecutable() const
445 {
446 	return fBaseType == kExecutableNode;
447 }
448 
449 
450 inline bool
451 Model::IsSymLink() const
452 {
453 	return fBaseType == kLinkNode;
454 }
455 
456 
457 inline bool
458 Model::HasLocalizedName() const
459 {
460 	return fHasLocalizedName;
461 }
462 
463 
464 inline
465 ModelNodeLazyOpener::ModelNodeLazyOpener(Model *model, bool writable, bool openLater)
466 	:	fModel(model),
467 		fWasOpen(model->IsNodeOpen()),
468 		fWasOpenForWriting(model->IsNodeOpenForWriting())
469 {
470 	if (!openLater)
471 		OpenNode(writable);
472 }
473 
474 
475 inline
476 ModelNodeLazyOpener::~ModelNodeLazyOpener()
477 {
478 	if (!fModel->IsNodeOpen())
479 		return;
480 	if (!fWasOpen)
481 		fModel->CloseNode();
482 	else if (!fWasOpenForWriting)
483 		fModel->OpenNode();
484 }
485 
486 
487 inline bool
488 ModelNodeLazyOpener::IsOpen() const
489 {
490 	return fModel->IsNodeOpen();
491 }
492 
493 
494 inline bool
495 ModelNodeLazyOpener::IsOpenForWriting() const
496 {
497 	return fModel->IsNodeOpenForWriting();
498 }
499 
500 
501 inline bool
502 ModelNodeLazyOpener::IsOpen(bool forWriting) const
503 {
504 	return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen();
505 }
506 
507 
508 inline Model *
509 ModelNodeLazyOpener::TargetModel() const
510 {
511 	return fModel;
512 }
513 
514 
515 inline status_t
516 ModelNodeLazyOpener::OpenNode(bool writable)
517 {
518 	if (writable) {
519 		if (!fModel->IsNodeOpenForWriting())
520 			return fModel->OpenNode(true);
521 	} else if (!fModel->IsNodeOpen())
522 		return fModel->OpenNode();
523 
524 	return B_OK;
525 }
526 
527 
528 } // namespace BPrivate
529 
530 
531 #endif
532