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