Incomplete attempt to clean up Mercurial branch build

master
Nat Goodspeed 2009-06-23 18:16:57 -04:00
parent d01e9ccb75
commit 07a05e2c0a
6 changed files with 255 additions and 314 deletions

View File

@ -19,7 +19,6 @@
#include <map>
#include <set>
#include <vector>
#include <list>
#include <deque>
#include <stdexcept>
#include <boost/signals2.hpp>
@ -28,13 +27,9 @@
#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp> // noncopyable
#include <boost/optional/optional.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/visit_each.hpp>
#include <boost/ref.hpp> // reference_wrapper
#include <boost/type_traits/is_pointer.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/function.hpp>
#include <boost/static_assert.hpp>
#include "llsd.h"
@ -111,6 +106,9 @@ typedef LLStandardSignal::slot_type LLEventListener;
/// Result of registering a listener, supports <tt>connected()</tt>,
/// <tt>disconnect()</tt> and <tt>blocked()</tt>
typedef boost::signals2::connection LLBoundListener;
/// Storing an LLBoundListener in LLTempBoundListener will disconnect the
/// referenced listener when the LLTempBoundListener instance is destroyed.
typedef boost::signals2::scoped_connection LLTempBoundListener;
/**
* A common idiom for event-based code is to accept either a callable --
@ -127,7 +125,7 @@ typedef boost::signals2::connection LLBoundListener;
* LLListenerOrPumpName::Empty. Test for this condition beforehand using
* either <tt>if (param)</tt> or <tt>if (! param)</tt>.
*/
class LLListenerOrPumpName
class LL_COMMON_API LLListenerOrPumpName
{
public:
/// passing string name of LLEventPump
@ -174,13 +172,13 @@ private:
/*****************************************************************************
* LLEventPumps
*****************************************************************************/
class LLEventPump;
class LL_COMMON_API LLEventPump;
/**
* LLEventPumps is a Singleton manager through which one typically accesses
* this subsystem.
*/
class LLEventPumps: public LLSingleton<LLEventPumps>
class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
{
friend class LLSingleton<LLEventPumps>;
public:
@ -254,14 +252,62 @@ namespace LLEventDetail
const ConnectFunc& connect_func);
} // namespace LLEventDetail
/*****************************************************************************
* LLEventTrackable
*****************************************************************************/
/**
* LLEventTrackable wraps boost::signals2::trackable, which resembles
* boost::trackable. Derive your listener class from LLEventTrackable instead,
* and use something like
* <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
* instance, _1))</tt>. This will implicitly disconnect when the object
* referenced by @c instance is destroyed.
*
* @note
* LLEventTrackable doesn't address a couple of cases:
* * Object destroyed during call
* - You enter a slot call in thread A.
* - Thread B destroys the object, which of course disconnects it from any
* future slot calls.
* - Thread A's call uses 'this', which now refers to a defunct object.
* Undefined behavior results.
* * Call during destruction
* - @c MySubclass is derived from LLEventTrackable.
* - @c MySubclass registers one of its own methods using
* <tt>LLEventPump::listen()</tt>.
* - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
* runs, destroying state specific to the subclass. (For instance, a
* <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
* - The listening method will not be disconnected until
* <tt>~LLEventTrackable()</tt> runs.
* - Before we get there, another thread posts data to the @c LLEventPump
* instance, calling the @c MySubclass method.
* - The method in question relies on valid @c MySubclass state. (For
* instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
* <tt>delete</tt>d but not zeroed.)
* - Undefined behavior results.
* If you suspect you may encounter any such scenario, you're better off
* managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
* Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
* involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
* thread-safe Boost.Signals2 machinery.
*/
typedef boost::signals2::trackable LLEventTrackable;
/*****************************************************************************
* LLEventPump
*****************************************************************************/
/**
* LLEventPump is the base class interface through which we access the
* concrete subclasses LLEventStream and LLEventQueue.
*
* @NOTE
* LLEventPump derives from LLEventTrackable so that when you "chain"
* LLEventPump instances together, they will automatically disconnect on
* destruction. Please see LLEventTrackable documentation for situations in
* which this may be perilous across threads.
*/
class LLEventPump: boost::noncopyable
class LL_COMMON_API LLEventPump: public LLEventTrackable
{
public:
/**
@ -364,10 +410,22 @@ public:
* themselves. listen() can throw any ListenError; see ListenError
* subclasses.
*
* If (as is typical) you pass a <tt>boost::bind()</tt> expression,
* listen() will inspect the components of that expression. If a bound
* object matches any of several cases, the connection will automatically
* be disconnected when that object is destroyed.
* The listener name must be unique among active listeners for this
* LLEventPump, else you get DupListenerName. If you don't care to invent
* a name yourself, use inventName(). (I was tempted to recognize e.g. ""
* and internally generate a distinct name for that case. But that would
* handle badly the scenario in which you want to add, remove, re-add,
* etc. the same listener: each new listen() call would necessarily
* perform a new dependency sort. Assuming you specify the same
* after/before lists each time, using inventName() when you first
* instantiate your listener, then passing the same name on each listen()
* call, allows us to optimize away the second and subsequent dependency
* sorts.
*
* If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
* listener, listen() will inspect the components of that expression. If a
* bound object matches any of several cases, the connection will
* automatically be disconnected when that object is destroyed.
*
* * You bind a <tt>boost::weak_ptr</tt>.
* * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
@ -429,6 +487,9 @@ public:
/// query
virtual bool enabled() const { return mEnabled; }
/// Generate a distinct name for a listener -- see listen()
static std::string inventName(const std::string& pfx="listener");
private:
friend class LLEventPumps;
/// flush queued events
@ -467,7 +528,7 @@ protected:
* LLEventStream is a thin wrapper around LLStandardSignal. Posting an
* event immediately calls all registered listeners.
*/
class LLEventStream: public LLEventPump
class LL_COMMON_API LLEventStream: public LLEventPump
{
public:
LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
@ -484,7 +545,7 @@ public:
* LLEventQueue isa LLEventPump whose post() method defers calling registered
* listeners until flush() is called.
*/
class LLEventQueue: public LLEventPump
class LL_COMMON_API LLEventQueue: public LLEventPump
{
public:
LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
@ -503,47 +564,89 @@ private:
};
/*****************************************************************************
* LLEventTrackable and underpinnings
* LLReqID
*****************************************************************************/
/**
* LLEventTrackable wraps boost::signals2::trackable, which resembles
* boost::trackable. Derive your listener class from LLEventTrackable instead,
* and use something like
* <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
* instance, _1))</tt>. This will implicitly disconnect when the object
* referenced by @c instance is destroyed.
* This class helps the implementer of a given event API to honor the
* ["reqid"] convention. By this convention, each event API stamps into its
* response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
* any, from the corresponding request.
*
* This supports an (atypical, but occasionally necessary) use case in which
* two or more asynchronous requests are multiplexed onto the same ["reply"]
* LLEventPump. Since the response events could arrive in arbitrary order, the
* caller must be able to demux them. It does so by matching the ["reqid"]
* value in each response with the ["reqid"] value in the corresponding
* request.
*
* It is the caller's responsibility to ensure distinct ["reqid"] values for
* that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
* the "namespace" of unique ["reqid"] values is simply the set of requests
* specifying the same ["reply"] LLEventPump name.
*
* Making a given event API echo the request's ["reqid"] into the response is
* nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
* place to put these comments. We hope that each time a coder implements a
* new event API based on some existing one, s/he will say, "Huh, what's an
* LLReqID?" and look up this material.
*
* The hardest part about the convention is deciding where to store the
* ["reqid"] value. Ironically, LLReqID can't help with that: you must store
* an LLReqID instance in whatever storage will persist until the reply is
* sent. For example, if the request ultimately ends up using a Responder
* subclass, storing an LLReqID instance in the Responder works.
*
* @note
* LLEventTrackable doesn't address a couple of cases:
* * Object destroyed during call
* - You enter a slot call in thread A.
* - Thread B destroys the object, which of course disconnects it from any
* future slot calls.
* - Thread A's call uses 'this', which now refers to a defunct object.
* Undefined behavior results.
* * Call during destruction
* - @c MySubclass is derived from LLEventTrackable.
* - @c MySubclass registers one of its own methods using
* <tt>LLEventPump::listen()</tt>.
* - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
* runs, destroying state specific to the subclass. (For instance, a
* <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
* - The listening method will not be disconnected until
* <tt>~LLEventTrackable()</tt> runs.
* - Before we get there, another thread posts data to the @c LLEventPump
* instance, calling the @c MySubclass method.
* - The method in question relies on valid @c MySubclass state. (For
* instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
* <tt>delete</tt>d but not zeroed.)
* - Undefined behavior results.
* If you suspect you may encounter any such scenario, you're better off
* managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
* Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
* involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
* thread-safe Boost.Signals2 machinery.
* The @em implementer of an event API must honor the ["reqid"] convention.
* However, the @em caller of an event API need only use it if s/he is sharing
* the same ["reply"] LLEventPump for two or more asynchronous event API
* requests.
*
* In most cases, it's far easier for the caller to instantiate a local
* LLEventStream and pass its name to the event API in question. Then it's
* perfectly reasonable not to set a ["reqid"] key in the request, ignoring
* the @c isUndefined() ["reqid"] value in the response.
*/
typedef boost::signals2::trackable LLEventTrackable;
class LLReqID
{
public:
/**
* If you have the request in hand at the time you instantiate the
* LLReqID, pass that request to extract its ["reqid"].
*/
LLReqID(const LLSD& request):
mReqid(request["reqid"])
{}
/// If you don't yet have the request, use setFrom() later.
LLReqID() {}
/// Extract and store the ["reqid"] value from an incoming request.
void setFrom(const LLSD& request)
{
mReqid = request["reqid"];
}
/// Set ["reqid"] key into a pending response LLSD object.
void stamp(LLSD& response) const;
/// Make a whole new response LLSD object with our ["reqid"].
LLSD makeResponse() const
{
LLSD response;
stamp(response);
return response;
}
/// Not really sure of a use case for this accessor...
LLSD getReqID() const { return mReqid; }
private:
LLSD mReqid;
};
/*****************************************************************************
* Underpinnings
*****************************************************************************/
/**
* We originally provided a suite of overloaded
* LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call

View File

@ -229,5 +229,5 @@ IF (NOT LINUX AND VIEWER)
# Commented out - see rationale at bottom of newview's build file + poppy 2009-06-05
# Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage!
# ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")
ADD_BUILD_TEST(llareslistener llmessage)
# ADD_BUILD_TEST(llareslistener llmessage)
ENDIF (NOT LINUX AND VIEWER)

View File

@ -3652,7 +3652,7 @@ void LLAppViewer::idleShutdown()
if (!saved_teleport_history)
{
saved_teleport_history = true;
LLTeleportHistory::getInstance()->save();
LLTeleportHistory::getInstance()->dump();
LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
return;
}

View File

@ -562,165 +562,6 @@ protected:
EWearableType mWearableType;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction (& it's derived classes)
//
// This is an implementation class to be able to
// perform action to view inventory items.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInvFVBridgeAction
{
public:
// This method is a convenience function which creates the correct
// type of bridge action based on some basic information
static LLInvFVBridgeAction* createAction(LLAssetType::EType asset_type,
const LLUUID& uuid,LLInventoryModel* model);
static void doAction(LLAssetType::EType asset_type,
const LLUUID& uuid,LLInventoryModel* model);
virtual void doIt() { };
virtual ~LLInvFVBridgeAction(){}//need this because of warning on OSX
protected:
LLInvFVBridgeAction(const LLUUID& id,LLInventoryModel* model):mUUID(id),mModel(model){}
LLViewerInventoryItem* getItem() const;
protected:
const LLUUID& mUUID; // item id
LLInventoryModel* mModel;
};
class LLTextureBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLTextureBridgeAction(){}
protected:
LLTextureBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLSoundBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLSoundBridgeAction(){}
protected:
LLSoundBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLLandmarkBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLLandmarkBridgeAction(){}
protected:
LLLandmarkBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLCallingCardBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLCallingCardBridgeAction(){}
protected:
LLCallingCardBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLNotecardBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLNotecardBridgeAction(){}
protected:
LLNotecardBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLGestureBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLGestureBridgeAction(){}
protected:
LLGestureBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLAnimationBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLAnimationBridgeAction(){}
protected:
LLAnimationBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLObjectBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLObjectBridgeAction(){}
protected:
LLObjectBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLLSLTextBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt() ;
virtual ~LLLSLTextBridgeAction(){}
protected:
LLLSLTextBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
};
class LLWearableBridgeAction: public LLInvFVBridgeAction
{
friend class LLInvFVBridgeAction;
public:
virtual void doIt();
virtual ~LLWearableBridgeAction(){}
protected:
LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
BOOL isInTrash() const;
// return true if the item is in agent inventory. if false, it
// must be lost or in the inventory library.
BOOL isAgentInventory() const;
void wearOnAvatar();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction (& it's derived classes)
//

View File

@ -1844,7 +1844,7 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
}
bool LLInventoryModel::loadSkeleton(
const LLInventoryModel::options_t& options,
const LLSD& options,
const LLUUID& owner_id)
{
lldebugs << "importing inventory skeleton for " << owner_id << llendl;
@ -1857,44 +1857,41 @@ bool LLInventoryModel::loadSkeleton(
LLUUID id;
LLAssetType::EType preferred_type;
bool rv = true;
for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
for(LLSD::array_const_iterator it = options.beginArray(),
end = options.endArray(); it != end; ++it)
{
LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
response_t::const_iterator no_response = (*it).end();
response_t::const_iterator skel;
skel = (*it).find("name");
if(skel == no_response) goto clean_cat;
cat->rename(std::string((*skel).second));
skel = (*it).find("folder_id");
if(skel == no_response) goto clean_cat;
id.set((*skel).second);
// if an id is null, it locks the viewer.
if(id.isNull()) goto clean_cat;
cat->setUUID(id);
skel = (*it).find("parent_id");
if(skel == no_response) goto clean_cat;
id.set((*skel).second);
cat->setParent(id);
skel = (*it).find("type_default");
if(skel == no_response)
LLSD name = (*it)["name"];
LLSD folder_id = (*it)["folder_id"];
LLSD parent_id = (*it)["parent_id"];
LLSD version = (*it)["version"];
if(name.isDefined()
&& folder_id.isDefined()
&& parent_id.isDefined()
&& version.isDefined()
&& folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
)
{
preferred_type = LLAssetType::AT_NONE;
LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
cat->rename(name.asString());
cat->setUUID(folder_id.asUUID());
cat->setParent(parent_id.asUUID());
LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
LLSD type_default = (*it)["type_default"];
if(type_default.isDefined())
{
preferred_type = (LLAssetType::EType)type_default.asInteger();
}
cat->setPreferredType(preferred_type);
cat->setVersion(version.asInteger());
temp_cats.insert(cat);
}
else
{
S32 t = atoi((*skel).second.c_str());
preferred_type = (LLAssetType::EType)t;
llwarns << "Unable to import near " << name.asString() << llendl;
rv = false;
}
cat->setPreferredType(preferred_type);
skel = (*it).find("version");
if(skel == no_response) goto clean_cat;
cat->setVersion(atoi((*skel).second.c_str()));
temp_cats.insert(cat);
continue;
clean_cat:
llwarns << "Unable to import near " << cat->getName() << llendl;
rv = false;
//delete cat; // automatic when cat is reasigned or destroyed
}
S32 cached_category_count = 0;
@ -2053,85 +2050,84 @@ bool LLInventoryModel::loadSkeleton(
return rv;
}
bool LLInventoryModel::loadMeat(
const LLInventoryModel::options_t& options, const LLUUID& owner_id)
bool LLInventoryModel::loadMeat(const LLSD& options, const LLUUID& owner_id)
{
llinfos << "importing inventory for " << owner_id << llendl;
LLPermissions default_perm;
default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
LLPointer<LLViewerInventoryItem> item;
LLUUID id;
LLAssetType::EType type;
LLInventoryType::EType inv_type;
bool rv = true;
for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
for(LLSD::array_const_iterator it = options.beginArray(),
end = options.endArray(); it != end; ++it)
{
item = new LLViewerInventoryItem;
response_t::const_iterator no_response = (*it).end();
response_t::const_iterator meat;
meat = (*it).find("name");
if(meat == no_response) goto clean_item;
item->rename(std::string((*meat).second));
meat = (*it).find("item_id");
if(meat == no_response) goto clean_item;
id.set((*meat).second);
item->setUUID(id);
meat = (*it).find("parent_id");
if(meat == no_response) goto clean_item;
id.set((*meat).second);
item->setParent(id);
meat = (*it).find("type");
if(meat == no_response) goto clean_item;
type = (LLAssetType::EType)atoi((*meat).second.c_str());
item->setType(type);
meat = (*it).find("inv_type");
if(meat != no_response)
LLSD name = (*it)["name"];
LLSD item_id = (*it)["item_id"];
LLSD parent_id = (*it)["parent_id"];
LLSD asset_type = (*it)["type"];
LLSD data_id = (*it)["data_id"];
if(name.isDefined()
&& item_id.isDefined()
&& parent_id.isDefined()
&& asset_type.isDefined()
&& data_id.isDefined())
{
inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str());
item->setInventoryType(inv_type);
}
meat = (*it).find("data_id");
if(meat == no_response) goto clean_item;
id.set((*meat).second);
if(LLAssetType::AT_CALLINGCARD == type)
{
LLPermissions perm;
perm.init(id, owner_id, LLUUID::null, LLUUID::null);
item->setPermissions(perm);
LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
item->rename(name.asString());
item->setUUID(item_id.asUUID());
item->setParent(parent_id.asUUID());
LLAssetType::EType type = (LLAssetType::EType)asset_type.asInteger();
item->setType(type);
LLSD llsd_inv_type = (*it)["inv_type"];
if(llsd_inv_type.isDefined())
{
LLInventoryType::EType inv_type = (LLInventoryType::EType)llsd_inv_type.asInteger();
item->setInventoryType(inv_type);
}
if(LLAssetType::AT_CALLINGCARD == type)
{
LLPermissions perm;
perm.init(data_id.asUUID(), owner_id, LLUUID::null, LLUUID::null);
item->setPermissions(perm);
}
else
{
LLPermissions default_perm;
default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
LLSD llsd_perm_mask = (*it)["perm_mask"];
if(llsd_perm_mask.isDefined())
{
PermissionMask perm_mask = llsd_perm_mask.asInteger();
default_perm.initMasks(
perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
}
else
{
default_perm.initMasks(
PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
}
item->setPermissions(default_perm);
item->setAssetUUID(data_id.asUUID());
}
LLSD flags = (*it)["flags"];
if(flags.isDefined())
{
// Not sure how well LLSD.asInteger() maps to
// unsigned long - using strtoul()
item->setFlags(strtoul(flags.asString().c_str(), NULL, 0));
}
LLSD time = (*it)["time"];
if(time.isDefined())
{
item->setCreationDate(time.asInteger());
}
addItem(item);
}
else
{
meat = (*it).find("perm_mask");
if(meat != no_response)
{
PermissionMask perm_mask = atoi((*meat).second.c_str());
default_perm.initMasks(
perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
}
else
{
default_perm.initMasks(
PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
}
item->setPermissions(default_perm);
item->setAssetUUID(id);
llwarns << "Unable to import near " << name.asString() << llendl;
rv = false;
}
meat = (*it).find("flags");
if(meat != no_response)
{
item->setFlags(strtoul((*meat).second.c_str(), NULL, 0));
}
meat = (*it).find("time");
if(meat != no_response)
{
item->setCreationDate(atoi((*meat).second.c_str()));
}
addItem(item);
continue;
clean_item:
llwarns << "Unable to import near " << item->getName() << llendl;
rv = false;
//delete item; // automatic when item is reassigned or destroyed
}
return rv;
}

View File

@ -61,6 +61,7 @@
#include "lluictrlfactory.h"
#include "llweb.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_places("panel_landmark_info");