xref: /haiku/src/kits/tracker/Model.h (revision 508f54795f39c3e7552d87c95aae9dd8ec6f505b)
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