xref: /haiku/src/kits/tracker/Model.h (revision 93e30a47bed879ad448b3e2d9e10333d3f2e60ae)
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 #ifndef _NU_MODEL_H
35 #define _NU_MODEL_H
36 
37 
38 //	Dedicated to BModel
39 
40 
41 #include <AppFileInfo.h>
42 #include <Debug.h>
43 #include <Mime.h>
44 #include <StorageDefs.h>
45 #include <String.h>
46 
47 #include "IconCache.h"
48 #include "ObjectList.h"
49 
50 
51 class BPath;
52 class BHandler;
53 class BEntry;
54 class BQuery;
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 namespace BPrivate {
67 
68 enum {
69 	kDoesNotSupportType,
70 	kSuperhandlerModel,
71 	kModelSupportsSupertype,
72 	kModelSupportsType,
73 	kModelSupportsFile
74 };
75 
76 class Model {
77 	public:
78 		Model();
79 		Model(const Model &);
80 		Model(const BEntry* entry, bool open = false, bool writable = false);
81 		Model(const entry_ref*, bool traverse = false, bool open = false,
82 			bool writable = false);
83 		Model(const node_ref* dirNode, const node_ref* node, const char* name,
84 			bool open = false, bool writable = false);
85 		~Model();
86 
87 		Model& operator=(const Model&);
88 
89 		status_t InitCheck() const;
90 
91 		status_t SetTo(const BEntry*, bool open = false,
92 			bool writable = false);
93 		status_t SetTo(const entry_ref*, bool traverse = false,
94 			bool open = false, bool writable = false);
95 		status_t SetTo(const node_ref* dirNode, const node_ref* node,
96 			const char* name, bool open = false, bool writable = false);
97 
98 		int CompareFolderNamesFirst(const Model* compareModel) const;
99 
100 		// node management
101 		status_t OpenNode(bool writable = false);
102 			// also used to switch from read-only to writable
103 		void CloseNode();
104 		bool IsNodeOpen() const;
105 		bool IsNodeOpenForWriting() const;
106 
107 		status_t UpdateStatAndOpenNode(bool writable = false);
108 			// like OpenNode, called on zombie poses to check if they turned
109 			// real, starts by rereading the stat structure
110 
111 		// basic getters
112 		const char* Name() const;
113 		const entry_ref* EntryRef() const;
114 		const node_ref* NodeRef() const;
115 		const StatStruct* StatBuf() const;
116 
117 		BNode* Node() const;
118 			// returns null if not Open
119 		void GetPath(BPath*) const;
120 		void GetEntry(BEntry*) const;
121 
122 		const char* MimeType() const;
123 		const char* PreferredAppSignature() const;
124 			// only not-null if not default for type and not self for app
125 		void SetPreferredAppSignature(const char*);
126 
127 		void GetPreferredAppForBrokenSymLink(BString &result);
128 			// special purpose call - if a symlink is unresolvable, it makes
129 			// sense to be able to get at it's preferred handler which may be
130 			// different from the Tracker. Used by the network neighborhood.
131 
132 		// type getters
133 		bool IsFile() const;
134 		bool IsDirectory() const;
135 		bool IsQuery() const;
136 		bool IsQueryTemplate() const;
137 		bool IsContainer() const;
138 		bool IsExecutable() const;
139 		bool IsSymLink() const;
140 		bool IsRoot() const;
141 		bool IsTrash() const;
142 		bool IsDesktop() const;
143 		bool IsVolume() const;
144 
145 		IconSource IconFrom() const;
146 		void SetIconFrom(IconSource);
147 			// where is this model getting it's icon from
148 
149 		void ResetIconFrom();
150 			// called from the attribute changed calls to force a lookup of
151 			// a new icon
152 
153 		// symlink handling calls, mainly used by the IconCache
154 		const Model* ResolveIfLink() const;
155 		Model* ResolveIfLink();
156 			// works on anything
157 		Model* LinkTo() const;
158 			// fast, works only on symlinks
159 		void SetLinkTo(Model*);
160 
161 		status_t GetLongVersionString(BString &, version_kind);
162 		status_t GetVersionString(BString &, version_kind);
163 		status_t AttrAsString(BString &, int64* value,
164 			const char* attributeName, uint32 attributeType);
165 
166 		// Node monitor update call
167 		void UpdateEntryRef(const node_ref* dirRef, const char* name);
168 		bool AttrChanged(const char*);
169 			// returns true if pose needs to update it's icon, etc.
170 			// pass null to force full update
171 		bool StatChanged();
172 			// returns true if pose needs to update it's icon
173 
174 		status_t WatchVolumeAndMountPoint(uint32, BHandler*);
175 			// correctly handles boot volume name watching
176 
177 		bool IsDropTarget(const Model* forDocument = 0,
178 			bool traverse = false) const;
179 			// if nonzero <forDocument> passed, mime info is used to
180 			// resolve if document can be opened
181 			// if zero, all executables, directories and volumes pass
182 			// if traverse, dereference symlinks
183 		bool IsDropTargetForList(const BObjectList<BString>* list) const;
184 			// <list> contains mime types of all documents about to be handled
185 			// by model
186 
187 	#if DEBUG
188 		void PrintToStream(int32 level = 1, bool deep = false);
189 		void TrackIconSource(icon_size);
190 	#endif
191 
192 		bool IsSuperHandler() const;
193 		int32 SupportsMimeType(const char* type,
194 			const BObjectList<BString>* list, bool exactReason = false) const;
195 			// pass in one string in <type> or a bunch in <list>
196 			// if <exactReason> false, returns as soon as it figures out that
197 			// app supports a given type, if true, returns an exact reason
198 
199 		// get rid of this??
200 		ssize_t WriteAttr(const char* attr, type_code type, off_t,
201 			const void* buffer, size_t );
202 			// cover call, creates a writable node and writes out attributes
203 			// into it; work around for file nodes not being writeable
204 		ssize_t WriteAttrKillForeign(const char* attr,
205 			const char* foreignAttr, type_code type, off_t,
206 			const void* buffer, size_t);
207 
208 		bool Mimeset(bool force);
209 			// returns true if mime type changed
210 
211 		bool HasLocalizedName() const;
212 
213 	private:
214 		status_t OpenNodeCommon(bool writable);
215 		void SetupBaseType();
216 		void FinishSettingUpType();
217 		void DeletePreferredAppVolumeNameLinkTo();
218 		void CacheLocalizedName();
219 
220 		status_t FetchOneQuery(const BQuery*, BHandler* target,
221 			BObjectList<BQuery>*, BVolume*);
222 
223 		enum CanHandleResult {
224 			kCanHandle,
225 			kCannotHandle,
226 			kNeedToCheckType
227 		};
228 
229 		CanHandleResult CanHandleDrops() const;
230 
231 		enum NodeType {
232 			kPlainNode,
233 			kExecutableNode,
234 			kDirectoryNode,
235 			kLinkNode,
236 			kQueryNode,
237 			kQueryTemplateNode,
238 			kVolumeNode,
239 			kRootNode,
240 			kTrashNode,
241 			kDesktopNode,
242 			kUnknownNode
243 		};
244 
245 		entry_ref fEntryRef;
246 		StatStruct fStatBuf;
247 		BString fMimeType;
248 			// should use string that may be shared for common types
249 
250 		// bit of overloading hackery here to save on footprint
251 		union {
252 			char* fPreferredAppName;	// used if we are neither a volume
253 										// nor a symlink
254 			char* fVolumeName;			// used if we are a volume
255 			Model* fLinkTo;				// used if we are a symlink
256 		};
257 
258 		uint8 fBaseType;
259 		uint8 fIconFrom;
260 		bool fWritable;
261 		BNode* fNode;
262 		status_t fStatus;
263 		BString fLocalizedName;
264 		bool fHasLocalizedName;
265 };
266 
267 
268 class ModelNodeLazyOpener {
269 	// a utility open state manager, usefull to allocate on stack
270 	// and have close up model when done, etc.
271 	public:
272 		// consider failing when open does not succeed
273 
274 		ModelNodeLazyOpener(Model* model, bool writable = false,
275 			bool openLater = true);
276 		~ModelNodeLazyOpener();
277 
278 		bool IsOpen() const;
279 		bool IsOpenForWriting() const;
280 		bool IsOpen(bool forWriting) const;
281 		Model* TargetModel() const;
282 		status_t OpenNode(bool writable = false);
283 
284 	private:
285 		Model* fModel;
286 		bool fWasOpen;
287 		bool fWasOpenForWriting;
288 };
289 
290 // handy flavors of openers
291 class BModelOpener : public ModelNodeLazyOpener {
292 	public:
293 		BModelOpener(Model* model)
294 		:	ModelNodeLazyOpener(model, false, false)
295 		{
296 		}
297 };
298 
299 class BModelWriteOpener : public ModelNodeLazyOpener {
300 	public:
301 		BModelWriteOpener(Model* model)
302 		:	ModelNodeLazyOpener(model, true, false)
303 		{
304 		}
305 };
306 
307 
308 #if DEBUG
309 // #define CHECK_OPEN_MODEL_LEAKS
310 #endif
311 
312 #ifdef CHECK_OPEN_MODEL_LEAKS
313 void DumpOpenModels(bool extensive);
314 void InitOpenModelDumping();
315 #endif
316 
317 // inlines follow -----------------------------------
318 
319 inline const char*
320 Model::MimeType() const
321 {
322 	return fMimeType.String();
323 }
324 
325 
326 inline const entry_ref*
327 Model::EntryRef() const
328 {
329 	return &fEntryRef;
330 }
331 
332 
333 inline const node_ref*
334 Model::NodeRef() const
335 {
336 	// the stat structure begins with a node_ref
337 	return (node_ref*)&fStatBuf;
338 }
339 
340 
341 inline BNode*
342 Model::Node() const
343 {
344 	return fNode;
345 }
346 
347 
348 inline const StatStruct*
349 Model::StatBuf() const
350 {
351 	return &fStatBuf;
352 }
353 
354 
355 inline IconSource
356 Model::IconFrom() const
357 {
358 	return (IconSource)fIconFrom;
359 }
360 
361 
362 inline void
363 Model::SetIconFrom(IconSource from)
364 {
365 	fIconFrom = from;
366 }
367 
368 
369 inline Model*
370 Model::LinkTo() const
371 {
372 	ASSERT(IsSymLink());
373 	return fLinkTo;
374 }
375 
376 
377 inline bool
378 Model::IsFile() const
379 {
380 	return fBaseType == kPlainNode
381 		|| fBaseType == kQueryNode
382 		|| fBaseType == kQueryTemplateNode
383 		|| fBaseType == kExecutableNode;
384 }
385 
386 
387 inline bool
388 Model::IsVolume() const
389 {
390 	return fBaseType == kVolumeNode;
391 }
392 
393 
394 inline bool
395 Model::IsDirectory() const
396 {
397 	return fBaseType == kDirectoryNode
398 		|| fBaseType == kVolumeNode
399 		|| fBaseType == kRootNode
400 		|| fBaseType == kTrashNode
401 		|| fBaseType == kDesktopNode;
402 }
403 
404 
405 inline bool
406 Model::IsQuery() const
407 {
408 	return fBaseType == kQueryNode;
409 }
410 
411 
412 inline bool
413 Model::IsQueryTemplate() const
414 {
415 	return fBaseType == kQueryTemplateNode;
416 }
417 
418 
419 inline bool
420 Model::IsContainer() const
421 {
422 	// I guess as in should show container window -
423 	// volumes show the volume window
424 	return IsQuery() || IsDirectory();
425 }
426 
427 
428 inline bool
429 Model::IsRoot() const
430 {
431 	return fBaseType == kRootNode;
432 }
433 
434 
435 inline bool
436 Model::IsTrash() const
437 {
438 	return fBaseType == kTrashNode;
439 }
440 
441 
442 inline bool
443 Model::IsDesktop() const
444 {
445 	return fBaseType == kDesktopNode;
446 }
447 
448 
449 inline bool
450 Model::IsExecutable() const
451 {
452 	return fBaseType == kExecutableNode;
453 }
454 
455 
456 inline bool
457 Model::IsSymLink() const
458 {
459 	return fBaseType == kLinkNode;
460 }
461 
462 
463 inline bool
464 Model::HasLocalizedName() const
465 {
466 	return fHasLocalizedName;
467 }
468 
469 
470 inline
471 ModelNodeLazyOpener::ModelNodeLazyOpener(Model* model, bool writable,
472 	bool openLater)
473 	:	fModel(model),
474 		fWasOpen(model->IsNodeOpen()),
475 		fWasOpenForWriting(model->IsNodeOpenForWriting())
476 {
477 	if (!openLater)
478 		OpenNode(writable);
479 }
480 
481 
482 inline
483 ModelNodeLazyOpener::~ModelNodeLazyOpener()
484 {
485 	if (!fModel->IsNodeOpen())
486 		return;
487 	if (!fWasOpen)
488 		fModel->CloseNode();
489 	else if (!fWasOpenForWriting)
490 		fModel->OpenNode();
491 }
492 
493 
494 inline bool
495 ModelNodeLazyOpener::IsOpen() const
496 {
497 	return fModel->IsNodeOpen();
498 }
499 
500 
501 inline bool
502 ModelNodeLazyOpener::IsOpenForWriting() const
503 {
504 	return fModel->IsNodeOpenForWriting();
505 }
506 
507 
508 inline bool
509 ModelNodeLazyOpener::IsOpen(bool forWriting) const
510 {
511 	return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen();
512 }
513 
514 
515 inline Model*
516 ModelNodeLazyOpener::TargetModel() const
517 {
518 	return fModel;
519 }
520 
521 
522 inline status_t
523 ModelNodeLazyOpener::OpenNode(bool writable)
524 {
525 	if (writable) {
526 		if (!fModel->IsNodeOpenForWriting())
527 			return fModel->OpenNode(true);
528 	} else if (!fModel->IsNodeOpen())
529 		return fModel->OpenNode();
530 
531 	return B_OK;
532 }
533 
534 } // namespace BPrivate
535 
536 #endif	// _NU_MODEL_H
537