haiku/src/kits/tracker/Model.h
Axel Dörfler 02be5353fd Added libtracker.so to the repository and the build.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12772 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-05-23 00:58:42 +00:00

474 lines
12 KiB
C++

/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
// Dedicated to BModel
#ifndef _NU_MODEL_H
#define _NU_MODEL_H
#include <AppFileInfo.h>
#include <Mime.h>
#include <StorageDefs.h>
#include <String.h>
#include "IconCache.h"
#include "ObjectList.h"
class BPath;
class BHandler;
class BEntry;
class BQuery;
#if __GNUC__ && __GNUC__ < 3
// using std::stat instead of just stat here because of what
// seems to be a gcc bug involving namespace and struct stat interaction
typedef struct std::stat StatStruct;
#else
// on mwcc std isn't turned on but there is no bug either.
// Also seems to be fixed in gcc 3.
typedef struct stat StatStruct;
#endif
namespace BPrivate {
enum {
kDoesNotSupportType,
kSuperhandlerModel,
kModelSupportsSupertype,
kModelSupportsType,
kModelSupportsFile
};
class Model {
public:
Model();
Model(const Model &);
Model(const BEntry *entry, bool open = false, bool writable = false);
Model(const entry_ref *, bool traverse = false, bool open = false,
bool writable = false);
Model(const node_ref *dirNode, const node_ref *node, const char *name,
bool open = false, bool writable = false);
~Model();
Model& operator=(const Model &);
status_t InitCheck() const;
status_t SetTo(const BEntry *, bool open = false, bool writable = false);
status_t SetTo(const entry_ref *, bool traverse = false, bool open = false,
bool writable = false);
status_t SetTo(const node_ref *dirNode, const node_ref *node, const char *name,
bool open = false, bool writable = false);
int CompareFolderNamesFirst(const Model *compareModel) const;
// node management
status_t OpenNode(bool writable = false);
// also used to switch from read-only to writable
void CloseNode();
bool IsNodeOpen() const;
bool IsNodeOpenForWriting() const;
status_t UpdateStatAndOpenNode(bool writable = false);
// like OpenNode, called on zombie poses to check if they turned
// real, starts by rereading the stat structure
// basic getters
const char *Name() const;
const entry_ref *EntryRef() const;
const node_ref *NodeRef() const;
const StatStruct *StatBuf() const;
BNode *Node() const;
// returns null if not Open
void GetPath(BPath *) const;
void GetEntry(BEntry *) const;
const char *MimeType() const;
const char *PreferredAppSignature() const;
// only not-null if not default for type and not self for app
void SetPreferredAppSignature(const char *);
void GetPreferredAppForBrokenSymLink(BString &result);
// special purpose call - if a symlink is unresolvable, it makes sense
// to be able to get at it's preferred handler which may be different
// from the Tracker. Used by the network neighborhood.
// type getters
bool IsFile() const;
bool IsDirectory() const;
bool IsQuery() const;
bool IsQueryTemplate() const;
bool IsContainer() const;
bool IsExecutable() const;
bool IsSymLink() const;
bool IsRoot() const;
bool IsVolume() const;
IconSource IconFrom() const;
void SetIconFrom(IconSource);
// where is this model getting it's icon from
void ResetIconFrom();
// called from the attribute changed calls to force a lookup of
// a new icon
// symlink handling calls, mainly used by the IconCache
const Model *ResolveIfLink() const;
Model *ResolveIfLink();
// works on anything
Model *LinkTo() const;
// fast, works only on symlinks
void SetLinkTo(Model *);
status_t GetLongVersionString(BString &, version_kind);
status_t GetVersionString(BString &, version_kind);
status_t AttrAsString(BString &, int64 *value, const char *attributeName,
uint32 attributeType);
// Node monitor update call
void UpdateEntryRef(const node_ref *dirRef, const char *name);
bool AttrChanged(const char *);
// returns true if pose needs to update it's icon, etc.
// pass null to force full update
bool StatChanged();
// returns true if pose needs to update it's icon
status_t WatchVolumeAndMountPoint(uint32, BHandler *);
// correctly handles boot volume name watching
bool IsDropTarget(const Model *forDocument = 0,
bool traverse = false) const;
// if nonzero <forDocument> passed, mime info is used to
// resolve if document can be opened
// if zero, all executables, directories and volumes pass
// if traverse, dereference symlinks
bool IsDropTargetForList(const BObjectList<BString> *list) const;
// <list> contains mime types of all documents about to be handled
// by model
#if DEBUG
void PrintToStream(int32 level = 1, bool deep = false);
void TrackIconSource(icon_size);
#endif
bool IsSuperHandler() const;
int32 SupportsMimeType(const char *type, const BObjectList<BString> *list,
bool exactReason = false) const;
// pass in one string in <type> or a bunch in <list>
// if <exactReason> false, returns as soon as it figures out that
// app supports a given type, if true, returns an exact reason
// get rid of this??
ssize_t WriteAttr(const char *attr, type_code type, off_t,
const void *buffer, size_t );
// cover call, creates a writable node and writes out attributes
// into it; work around for file nodes not being writeable
ssize_t WriteAttrKillForegin(const char *attr, const char *foreignAttr,
type_code type, off_t, const void *buffer, size_t);
bool Mimeset(bool force);
// returns true if mime type changed
private:
status_t OpenNodeCommon(bool writable);
void SetupBaseType();
void FinishSettingUpType();
void DeletePreferredAppVolumeNameLinkTo();
status_t FetchOneQuery(const BQuery *, BHandler *target,
BObjectList<BQuery>*, BVolume *);
enum CanHandleResult {
kCanHandle,
kCannotHandle,
kNeedToCheckType
};
CanHandleResult CanHandleDrops() const;
enum NodeType {
kPlainNode,
kExecutableNode,
kDirectoryNode,
kLinkNode,
kQueryNode,
kQueryTemplateNode,
kVolumeNode,
kRootNode,
kUnknownNode
};
entry_ref fEntryRef;
StatStruct fStatBuf;
BString fMimeType; // should use string that may be shared for common types
// bit of overloading hackery here to save on footprint
union {
char *fPreferredAppName; // used if we are neither a volume nor a symlink
char *fVolumeName; // used if we are a volume
Model *fLinkTo; // used if we are a symlink
};
uint8 fBaseType;
uint8 fIconFrom;
bool fWritable;
BNode *fNode;
status_t fStatus;
};
class ModelNodeLazyOpener {
// a utility open state manager, usefull to allocate on stack
// and have close up model when done, etc.
public:
// consider failing when open does not succeed
ModelNodeLazyOpener(Model *model, bool writable = false, bool openLater = true);
~ModelNodeLazyOpener();
bool IsOpen() const;
bool IsOpenForWriting() const;
bool IsOpen(bool forWriting) const;
Model *TargetModel() const;
status_t OpenNode(bool writable = false);
private:
Model *fModel;
bool fWasOpen;
bool fWasOpenForWriting;
};
// handy flavors of openers
class BModelOpener : public ModelNodeLazyOpener {
public:
BModelOpener(Model *model)
: ModelNodeLazyOpener(model, false, false)
{
}
};
class BModelWriteOpener : public ModelNodeLazyOpener {
public:
BModelWriteOpener(Model *model)
: ModelNodeLazyOpener(model, true, false)
{
}
};
#if DEBUG
// #define CHECK_OPEN_MODEL_LEAKS
#endif
#ifdef CHECK_OPEN_MODEL_LEAKS
void DumpOpenModels(bool extensive);
void InitOpenModelDumping();
#endif
// inlines follow -----------------------------------
inline const char *
Model::MimeType() const
{
return fMimeType.String();
}
inline const entry_ref *
Model::EntryRef() const
{
return &fEntryRef;
}
inline const node_ref *
Model::NodeRef() const
{
// the stat structure begins with a node_ref
return (node_ref *)&fStatBuf;
}
inline BNode *
Model::Node() const
{
return fNode;
}
inline const StatStruct *
Model::StatBuf() const
{
return &fStatBuf;
}
inline IconSource
Model::IconFrom() const
{
return (IconSource)fIconFrom;
}
inline void
Model::SetIconFrom(IconSource from)
{
fIconFrom = from;
}
inline Model *
Model::LinkTo() const
{
ASSERT(IsSymLink());
return fLinkTo;
}
inline bool
Model::IsFile() const
{
return fBaseType == kPlainNode
|| fBaseType == kQueryNode
|| fBaseType == kQueryTemplateNode
|| fBaseType == kExecutableNode;
}
inline bool
Model::IsVolume() const
{
return fBaseType == kVolumeNode;
}
inline bool
Model::IsDirectory() const
{
return fBaseType == kDirectoryNode
|| fBaseType == kVolumeNode
|| fBaseType == kRootNode;
}
inline bool
Model::IsQuery() const
{
return fBaseType == kQueryNode;
}
inline bool
Model::IsQueryTemplate() const
{
return fBaseType == kQueryTemplateNode;
}
inline bool
Model::IsContainer() const
{
// I guess as in should show container window -
// volumes show the volume window
return IsQuery() || IsDirectory();
}
inline bool
Model::IsRoot() const
{
return fBaseType == kRootNode;
}
inline bool
Model::IsExecutable() const
{
return fBaseType == kExecutableNode;
}
inline bool
Model::IsSymLink() const
{
return fBaseType == kLinkNode;
}
inline
ModelNodeLazyOpener::ModelNodeLazyOpener(Model *model, bool writable, bool openLater)
: fModel(model),
fWasOpen(model->IsNodeOpen()),
fWasOpenForWriting(model->IsNodeOpenForWriting())
{
if (!openLater)
OpenNode(writable);
}
inline
ModelNodeLazyOpener::~ModelNodeLazyOpener()
{
if (!fModel->IsNodeOpen())
return;
if (!fWasOpen)
fModel->CloseNode();
else if (!fWasOpenForWriting)
fModel->OpenNode();
}
inline bool
ModelNodeLazyOpener::IsOpen() const
{
return fModel->IsNodeOpen();
}
inline bool
ModelNodeLazyOpener::IsOpenForWriting() const
{
return fModel->IsNodeOpenForWriting();
}
inline bool
ModelNodeLazyOpener::IsOpen(bool forWriting) const
{
return forWriting ? fModel->IsNodeOpenForWriting() : fModel->IsNodeOpen();
}
inline Model *
ModelNodeLazyOpener::TargetModel() const
{
return fModel;
}
inline status_t
ModelNodeLazyOpener::OpenNode(bool writable)
{
if (writable) {
if (!fModel->IsNodeOpenForWriting())
return fModel->OpenNode(true);
} else if (!fModel->IsNodeOpen())
return fModel->OpenNode();
return B_OK;
}
} // namespace BPrivate
#endif