diff options
| -rw-r--r-- | indra/llcommon/llevents.h | 203 | ||||
| -rw-r--r-- | indra/llmessage/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.h | 159 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 210 | ||||
| -rw-r--r-- | indra/newview/llpanelplaceinfo.cpp | 1 | 
6 files changed, 259 insertions, 318 deletions
| diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 2f6515a4cb..c5a27ab68e 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -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: @@ -255,13 +253,61 @@ namespace LLEventDetail  } // 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 diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 29e7aed898..35e6f9d640 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -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) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 48cb3babfa..3fc3c8e382 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -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;  	} diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b55a6a658b..3958f7e9c2 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -575,165 +575,6 @@ 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) -// -// 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, diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9177d51d5c..bac02e30bf 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -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) -	{ -		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) -		{ -			preferred_type = LLAssetType::AT_NONE; + +	for(LLSD::array_const_iterator it = options.beginArray(), +		end = options.endArray(); it != end; ++it) +	{ +		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. +			) 		 +		{ +			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) -	{ -		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) -		{ -			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); -		} -		else -		{ -			meat = (*it).find("perm_mask"); -			if(meat != no_response) -			{ -				PermissionMask perm_mask = atoi((*meat).second.c_str()); -				default_perm.initMasks( +	for(LLSD::array_const_iterator it = options.beginArray(), +		end = options.endArray(); it != end; ++it) +	{ +		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()) +		{ +			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(id); -		} -		meat = (*it).find("flags"); -		if(meat != no_response) -		{ -			item->setFlags(strtoul((*meat).second.c_str(), NULL, 0)); +                } +                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);  		} -		meat = (*it).find("time"); -		if(meat != no_response) +		else  		{ -			item->setCreationDate(atoi((*meat).second.c_str())); +			llwarns << "Unable to import near " << name.asString() << llendl; +            rv = false;  		} -		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;  } diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 3ed93e5598..951c223668 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -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"); | 
