#ifndef _NU_MODEL_H
#define _NU_MODEL_H
#include <AppFileInfo.h>
#include <Debug.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
typedef struct std::stat StatStruct;
#else
typedef struct stat StatStruct;
#endif
namespace BPrivate {
enum {
kDoesNotSupportType,
kSuperhandlerModel,
kModelSupportsSupertype,
kModelSupportsType,
kModelSupportsFile
};
class Model {
public:
Model();
Model(const Model& other);
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* compare) const;
status_t OpenNode(bool writable = false);
void CloseNode();
bool IsNodeOpen() const;
bool IsNodeOpenForWriting() const;
status_t UpdateStatAndOpenNode(bool writable = false);
const char* Name() const;
const entry_ref* EntryRef() const;
const node_ref* NodeRef() const;
const StatStruct* StatBuf() const;
BNode* Node() const;
void GetPath(BPath*) const;
void GetEntry(BEntry*) const;
const char* MimeType() const;
const char* PreferredAppSignature() const;
void SetPreferredAppSignature(const char*);
bool IsContainer() const;
bool IsDesktop() const;
bool IsDirectory() const;
bool IsFile() const;
bool IsQuery() const;
bool IsQueryTemplate() const;
bool IsExecutable() const;
bool IsPrintersDir() const;
bool IsSymLink() const;
bool InRoot() const;
bool IsRoot() const;
bool InTrash() const;
bool IsTrash() const;
bool IsVolume() const;
bool IsVirtualDirectory() const;
IconSource IconFrom() const;
void SetIconFrom(IconSource);
void ResetIconFrom();
const Model* ResolveIfLink() const;
Model* ResolveIfLink();
Model* LinkTo() const;
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);
void UpdateEntryRef(const node_ref* dirRef, const char* name);
bool AttrChanged(const char* attrName);
bool IconAttrChanged(const char* attrName);
bool StatChanged();
status_t WatchVolumeAndMountPoint(uint32, BHandler*);
bool IsDropTarget(const Model* forDocument = 0,
bool traverse = false) const;
bool IsDropTargetForList(const BStringList* list) const;
#if DEBUG
void PrintToStream(int32 level = 1, bool deep = false);
void TrackIconSource(icon_size);
#endif
bool IsSuperHandler() const;
int32 SupportsMimeType(const char* type,
const BStringList* list, bool exactReason = false) const;
ssize_t WriteAttr(const char* attr, type_code type, off_t,
const void* buffer, size_t );
ssize_t WriteAttrKillForeign(const char* attr,
const char* foreignAttr, type_code type, off_t,
const void* buffer, size_t);
bool Mimeset(bool force);
void SniffMimeIfNeeded();
bool HasLocalizedName() const;
private:
status_t OpenNodeCommon(bool writable);
void SetupBaseType();
void FinishSettingUpType();
bool CheckAppIconHint() const;
void DeletePreferredAppVolumeNameLinkTo();
void CacheLocalizedName();
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,
kTrashNode,
kDesktopNode,
kVirtualDirectoryNode,
kUnknownNode
};
entry_ref fEntryRef;
StatStruct fStatBuf;
BString fMimeType;
union {
char* fPreferredAppName;
char* fVolumeName;
Model* fLinkTo;
};
uint8 fBaseType;
uint8 fIconFrom;
bool fWritable;
BNode* fNode;
status_t fStatus;
BString fLocalizedName;
bool fHasLocalizedName;
bool fLocalizedNameIsCached;
};
class ModelNodeLazyOpener {
public:
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;
};
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
#endif
#ifdef CHECK_OPEN_MODEL_LEAKS
void DumpOpenModels(bool extensive);
void InitOpenModelDumping();
#endif
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
{
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::IsContainer() const
{
return IsQuery() || IsDirectory() || IsVirtualDirectory();
}
inline bool
Model::IsDesktop() const
{
return fBaseType == kDesktopNode;
}
inline bool
Model::IsDirectory() const
{
switch (fBaseType) {
case kDirectoryNode:
case kVolumeNode:
case kRootNode:
case kTrashNode:
case kDesktopNode:
return true;
}
return false;
}
inline bool
Model::IsFile() const
{
switch (fBaseType) {
case kPlainNode:
case kQueryNode:
case kQueryTemplateNode:
case kExecutableNode:
case kVirtualDirectoryNode:
return true;
}
return false;
}
inline bool
Model::IsExecutable() const
{
return fBaseType == kExecutableNode;
}
inline bool
Model::IsQuery() const
{
return fBaseType == kQueryNode;
}
inline bool
Model::IsQueryTemplate() const
{
return fBaseType == kQueryTemplateNode;
}
inline bool
Model::IsSymLink() const
{
return fBaseType == kLinkNode;
}
inline bool
Model::IsRoot() const
{
return fBaseType == kRootNode;
}
inline bool
Model::IsTrash() const
{
return fBaseType == kTrashNode;
}
inline bool
Model::IsVirtualDirectory() const
{
return fBaseType == kVirtualDirectoryNode;
}
inline bool
Model::IsVolume() const
{
return fBaseType == kVolumeNode;
}
inline bool
Model::HasLocalizedName() const
{
return fHasLocalizedName;
}
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;
}
}
#endif