PageRenderTime 625ms CodeModel.GetById 363ms app.highlight 83ms RepoModel.GetById 108ms app.codeStats 0ms

/indra/newview/llinventorymodel.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 550 lines | 240 code | 69 blank | 241 comment | 0 complexity | e1a3cf25032904b5038fdc71312c9bf3 MD5 | raw file
  1/** 
  2 * @file llinventorymodel.h
  3 * @brief LLInventoryModel class header file
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLINVENTORYMODEL_H
 28#define LL_LLINVENTORYMODEL_H
 29
 30#include "llassettype.h"
 31#include "llfoldertype.h"
 32#include "lldarray.h"
 33#include "llframetimer.h"
 34#include "llhttpclient.h"
 35#include "lluuid.h"
 36#include "llpermissionsflags.h"
 37#include "llstring.h"
 38#include "llmd5.h"
 39#include <map>
 40#include <set>
 41#include <string>
 42#include <vector>
 43
 44class LLInventoryObserver;
 45class LLInventoryObject;
 46class LLInventoryItem;
 47class LLInventoryCategory;
 48class LLViewerInventoryItem;
 49class LLViewerInventoryCategory;
 50class LLViewerInventoryItem;
 51class LLViewerInventoryCategory;
 52class LLMessageSystem;
 53class LLInventoryCollectFunctor;
 54
 55
 56//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 57// LLInventoryModel
 58//
 59// Represents a collection of inventory, and provides efficient ways to access 
 60// that information.
 61//   NOTE: This class could in theory be used for any place where you need 
 62//   inventory, though it optimizes for time efficiency - not space efficiency, 
 63//   probably making it inappropriate for use on tasks.
 64//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 65class LLInventoryModel
 66{
 67	LOG_CLASS(LLInventoryModel);
 68public:
 69	friend class LLInventoryModelFetchDescendentsResponder;
 70
 71	enum EHasChildren
 72	{
 73		CHILDREN_NO,
 74		CHILDREN_YES,
 75		CHILDREN_MAYBE
 76	};
 77
 78	typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
 79	typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
 80	typedef std::set<LLUUID> changed_items_t;
 81
 82	class fetchInventoryResponder : public LLHTTPClient::Responder
 83	{
 84	public:
 85		fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
 86		void result(const LLSD& content);			
 87		void error(U32 status, const std::string& reason);
 88	protected:
 89		LLSD mRequestSD;
 90	};
 91
 92/********************************************************************************
 93 **                                                                            **
 94 **                    INITIALIZATION/SETUP
 95 **/
 96
 97	//--------------------------------------------------------------------
 98	// Constructors / Destructors
 99	//--------------------------------------------------------------------
100public:
101	LLInventoryModel();
102	~LLInventoryModel();
103	void cleanupInventory();
104protected:
105	void empty(); // empty the entire contents
106
107	//--------------------------------------------------------------------
108	// Initialization
109	//--------------------------------------------------------------------
110public:
111	// The inventory model usage is sensitive to the initial construction of the model
112	bool isInventoryUsable() const;
113private:
114	bool mIsAgentInvUsable; // used to handle an invalid inventory state
115
116	//--------------------------------------------------------------------
117	// Root Folders
118	//--------------------------------------------------------------------
119public:
120	// The following are set during login with data from the server
121	void setRootFolderID(const LLUUID& id);
122	void setLibraryOwnerID(const LLUUID& id);
123	void setLibraryRootFolderID(const LLUUID& id);
124
125	const LLUUID &getRootFolderID() const;
126	const LLUUID &getLibraryOwnerID() const;
127	const LLUUID &getLibraryRootFolderID() const;
128private:
129	LLUUID mRootFolderID;
130	LLUUID mLibraryRootFolderID;
131	LLUUID mLibraryOwnerID;	
132	
133	//--------------------------------------------------------------------
134	// Structure
135	//--------------------------------------------------------------------
136public:
137	// Methods to load up inventory skeleton & meat. These are used
138	// during authentication. Returns true if everything parsed.
139	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
140	void buildParentChildMap(); // brute force method to rebuild the entire parent-child relations
141	// Call on logout to save a terse representation.
142	void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
143private:
144	// Information for tracking the actual inventory. We index this
145	// information in a lot of different ways so we can access
146	// the inventory using several different identifiers.
147	// mInventory member data is the 'master' list of inventory, and
148	// mCategoryMap and mItemMap store uuid->object mappings. 
149	typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
150	typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
151	cat_map_t mCategoryMap;
152	item_map_t mItemMap;
153	// This last set of indices is used to map parents to children.
154	typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
155	typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
156	parent_cat_map_t mParentChildCategoryTree;
157	parent_item_map_t mParentChildItemTree;
158
159	//--------------------------------------------------------------------
160	// Login
161	//--------------------------------------------------------------------
162public:
163	static BOOL getIsFirstTimeInViewer2();
164private:
165	static BOOL sFirstTimeInViewer2;
166	const static S32 sCurrentInvCacheVersion; // expected inventory cache version
167
168/**                    Initialization/Setup
169 **                                                                            **
170 *******************************************************************************/
171
172/********************************************************************************
173 **                                                                            **
174 **                    ACCESSORS
175 **/
176
177	//--------------------------------------------------------------------
178	// Descendents
179	//--------------------------------------------------------------------
180public:
181	// Make sure we have the descendents in the structure.  Returns true
182	// if a fetch was performed.
183	bool fetchDescendentsOf(const LLUUID& folder_id) const;
184
185	// Return the direct descendents of the id provided.Set passed
186	// in values to NULL if the call fails.
187	//    NOTE: The array provided points straight into the guts of
188	//    this object, and should only be used for read operations, since
189	//    modifications may invalidate the internal state of the inventory.
190	void getDirectDescendentsOf(const LLUUID& cat_id,
191								cat_array_t*& categories,
192								item_array_t*& items) const;
193
194	// Compute a hash of direct descendent names (for detecting child name changes)
195	LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const;
196	
197	// Starting with the object specified, add its descendents to the
198	// array provided, but do not add the inventory object specified
199	// by id. There is no guaranteed order. 
200	//    NOTE: Neither array will be erased before adding objects to it. 
201	//    Do not store a copy of the pointers collected - use them, and 
202	//    collect them again later if you need to reference the same objects.
203	enum { 
204		EXCLUDE_TRASH = FALSE, 
205		INCLUDE_TRASH = TRUE 
206	};
207	void collectDescendents(const LLUUID& id,
208							cat_array_t& categories,
209							item_array_t& items,
210							BOOL include_trash);
211	void collectDescendentsIf(const LLUUID& id,
212							  cat_array_t& categories,
213							  item_array_t& items,
214							  BOOL include_trash,
215							  LLInventoryCollectFunctor& add,
216							  BOOL follow_folder_links = FALSE);
217
218	// Collect all items in inventory that are linked to item_id.
219	// Assumes item_id is itself not a linked item.
220	item_array_t collectLinkedItems(const LLUUID& item_id,
221									const LLUUID& start_folder_id = LLUUID::null);
222	
223
224	// Check if one object has a parent chain up to the category specified by UUID.
225	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
226
227	//--------------------------------------------------------------------
228	// Find
229	//--------------------------------------------------------------------
230public:
231	// Returns the uuid of the category that specifies 'type' as what it 
232	// defaults to containing. The category is not necessarily only for that type. 
233	//    NOTE: If create_folder is true, this will create a new inventory category 
234	//    on the fly if one does not exist. *NOTE: if find_in_library is true it 
235	//    will search in the user's library folder instead of "My Inventory"
236	const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, 
237										 bool create_folder = true, 
238										 bool find_in_library = false);
239	
240	// Get whatever special folder this object is a child of, if any.
241	const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
242	
243	// Get first descendant of the child object under the specified parent
244	const LLViewerInventoryCategory *getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const;
245
246	// Get the object by id. Returns NULL if not found.
247	//   NOTE: Use the pointer returned for read operations - do
248	//   not modify the object values in place or you will break stuff.
249	LLInventoryObject* getObject(const LLUUID& id) const;
250
251	// Get the item by id. Returns NULL if not found.
252	//    NOTE: Use the pointer for read operations - use the
253	//    updateItem() method to actually modify values.
254	LLViewerInventoryItem* getItem(const LLUUID& id) const;
255
256	// Get the category by id. Returns NULL if not found.
257	//    NOTE: Use the pointer for read operations - use the
258	//    updateCategory() method to actually modify values.
259	LLViewerInventoryCategory* getCategory(const LLUUID& id) const;
260
261	// Get the inventoryID or item that this item points to, else just return object_id
262	const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
263	LLViewerInventoryItem* getLinkedItem(const LLUUID& object_id) const;
264private:
265	mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups	
266
267	//--------------------------------------------------------------------
268	// Count
269	//--------------------------------------------------------------------
270public:
271	// Return the number of items or categories
272	S32 getItemCount() const;
273	S32 getCategoryCount() const;
274
275/**                    Accessors
276 **                                                                            **
277 *******************************************************************************/
278
279/********************************************************************************
280 **                                                                            **
281 **                    MUTATORS
282 **/
283
284public:
285	// Change an existing item with a matching item_id or add the item
286	// to the current inventory. Returns the change mask generated by
287	// the update. No notification will be sent to observers. This
288	// method will only generate network traffic if the item had to be
289	// reparented.
290	//    NOTE: In usage, you will want to perform cache accounting
291	//    operations in LLInventoryModel::accountForUpdate() or
292	//    LLViewerInventoryItem::updateServer() before calling this method.
293	U32 updateItem(const LLViewerInventoryItem* item);
294
295	// Change an existing item with the matching id or add
296	// the category. No notifcation will be sent to observers. This
297	// method will only generate network traffic if the item had to be
298	// reparented.
299	//    NOTE: In usage, you will want to perform cache accounting
300	//    operations in accountForUpdate() or LLViewerInventoryCategory::
301	//    updateServer() before calling this method.
302	void updateCategory(const LLViewerInventoryCategory* cat);
303
304	// Move the specified object id to the specified category and
305	// update the internal structures. No cache accounting,
306	// observer notification, or server update is performed.
307	void moveObject(const LLUUID& object_id, const LLUUID& cat_id);
308
309	//--------------------------------------------------------------------
310	// Delete
311	//--------------------------------------------------------------------
312public:
313	// Delete a particular inventory object by ID. Will purge one
314	// object from the internal data structures, maintaining a
315	// consistent internal state. No cache accounting, observer
316	// notification, or server update is performed.
317	void deleteObject(const LLUUID& id);
318	void removeItem(const LLUUID& item_id);
319	
320	// Delete a particular inventory object by ID, and delete it from
321	// the server. Also updates linked items.
322	void purgeObject(const LLUUID& id);
323
324	// Collects and purges the descendants of the id
325	// provided. If the category is not found, no action is
326	// taken. This method goes through the long winded process of
327	// removing server representation of folders and items while doing
328	// cache accounting in a fairly efficient manner. This method does
329	// not notify observers (though maybe it should...)
330	void purgeDescendentsOf(const LLUUID& id);
331protected:
332	void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id);
333	
334	//--------------------------------------------------------------------
335	// Reorder
336	//--------------------------------------------------------------------
337public:
338	// Changes items order by insertion of the item identified by src_item_id
339	// before (or after) the item identified by dest_item_id. Both items must exist in items array.
340	// Sorting is stored after method is finished. Only src_item_id is moved before (or after) dest_item_id.
341	// The parameter "insert_before" controls on which side of dest_item_id src_item_id gets rensinserted.
342	static void updateItemsOrder(LLInventoryModel::item_array_t& items, 
343								 const LLUUID& src_item_id, 
344								 const LLUUID& dest_item_id,
345								 bool insert_before = true);
346	// Gets an iterator on an item vector knowing only the item UUID.
347	// Returns end() of the vector if not found.
348	static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
349
350	// Saves current order of the passed items using inventory item sort field.
351	// Resets 'items' sort fields and saves them on server.
352	// Is used to save order for Favorites folder.
353	void saveItemsOrder(const LLInventoryModel::item_array_t& items);
354
355	// Rearranges Landmarks inside Favorites folder.
356	// Moves source landmark before target one.
357	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id);
358
359	//--------------------------------------------------------------------
360	// Creation
361	//--------------------------------------------------------------------
362public:
363	// Returns the UUID of the new category. If you want to use the default 
364	// name based on type, pass in a NULL to the 'name' parameter.
365	LLUUID createNewCategory(const LLUUID& parent_id,
366							 LLFolderType::EType preferred_type,
367							 const std::string& name,
368							 void (*callback)(const LLSD&, void*) = NULL,
369							 void* user_data = NULL );
370protected:
371	// Internal methods that add inventory and make sure that all of
372	// the internal data structures are consistent. These methods
373	// should be passed pointers of newly created objects, and the
374	// instance will take over the memory management from there.
375	void addCategory(LLViewerInventoryCategory* category);
376	void addItem(LLViewerInventoryItem* item);
377	
378/**                    Mutators
379 **                                                                            **
380 *******************************************************************************/
381
382/********************************************************************************
383 **                                                                            **
384 **                    CATEGORY ACCOUNTING
385 **/
386
387public:
388	// Represents the number of items added or removed from a category.
389	struct LLCategoryUpdate
390	{
391		LLCategoryUpdate() : mDescendentDelta(0) {}
392		LLCategoryUpdate(const LLUUID& category_id, S32 delta) :
393			mCategoryID(category_id),
394			mDescendentDelta(delta) {}
395		LLUUID mCategoryID;
396		S32 mDescendentDelta;
397	};
398	typedef std::vector<LLCategoryUpdate> update_list_t;
399
400	// This exists to make it easier to account for deltas in a map.
401	struct LLInitializedS32
402	{
403		LLInitializedS32() : mValue(0) {}
404		LLInitializedS32(S32 value) : mValue(value) {}
405		S32 mValue;
406		LLInitializedS32& operator++() { ++mValue; return *this; }
407		LLInitializedS32& operator--() { --mValue; return *this; }
408	};
409	typedef std::map<LLUUID, LLInitializedS32> update_map_t;
410
411	// Call when there are category updates.  Call them *before* the 
412	// actual update so the method can do descendent accounting correctly.
413	void accountForUpdate(const LLCategoryUpdate& update) const;
414	void accountForUpdate(const update_list_t& updates);
415	void accountForUpdate(const update_map_t& updates);
416
417	// Return (yes/no/maybe) child status of category children.
418	EHasChildren categoryHasChildren(const LLUUID& cat_id) const;
419
420	// Returns true if category version is known and theoretical
421	// descendents == actual descendents.
422	bool isCategoryComplete(const LLUUID& cat_id) const;
423	
424/**                    Category Accounting
425 **                                                                            **
426 *******************************************************************************/
427
428/********************************************************************************
429 **                                                                            **
430 **                    NOTIFICATIONS
431 **/
432
433public:
434	// Called by the idle loop.  Only updates if new state is detected.  Call 
435	// notifyObservers() manually to update regardless of whether state change 
436	// has been indicated.
437	void idleNotifyObservers();
438
439	// Call to explicitly update everyone on a new state.
440	void notifyObservers();
441
442	// Allows outsiders to tell the inventory if something has
443	// been changed 'under the hood', but outside the control of the
444	// inventory. The next notify will include that notification.
445	void addChangedMask(U32 mask, const LLUUID& referent);
446	const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
447protected:
448	// Updates all linked items pointing to this id.
449	void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
450private:
451	// Flag set when notifyObservers is being called, to look for bugs
452	// where it's called recursively.
453	BOOL mIsNotifyObservers;
454	// Variables used to track what has changed since the last notify.
455	U32 mModifyMask;
456	changed_items_t mChangedItemIDs;
457	
458	//--------------------------------------------------------------------
459	// Observers
460	//--------------------------------------------------------------------
461public:
462	// If the observer is destroyed, be sure to remove it.
463	void addObserver(LLInventoryObserver* observer);
464	void removeObserver(LLInventoryObserver* observer);
465	BOOL containsObserver(LLInventoryObserver* observer) const;
466private:
467	typedef std::set<LLInventoryObserver*> observer_list_t;
468	observer_list_t mObservers;
469	
470/**                    Notifications
471 **                                                                            **
472 *******************************************************************************/
473
474
475/********************************************************************************
476 **                                                                            **
477 **                    MISCELLANEOUS
478 **/
479
480	//--------------------------------------------------------------------
481	// Callbacks
482	//--------------------------------------------------------------------
483public:
484	// Trigger a notification and empty the folder type (FT_TRASH or FT_LOST_AND_FOUND) if confirmed
485	void emptyFolderType(const std::string notification, LLFolderType::EType folder_type);
486	bool callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type);
487	static void registerCallbacks(LLMessageSystem* msg);
488
489	//--------------------------------------------------------------------
490	// File I/O
491	//--------------------------------------------------------------------
492protected:
493	static bool loadFromFile(const std::string& filename,
494							 cat_array_t& categories,
495							 item_array_t& items,
496							 bool& is_cache_obsolete); 
497	static bool saveToFile(const std::string& filename,
498						   const cat_array_t& categories,
499						   const item_array_t& items); 
500
501	//--------------------------------------------------------------------
502	// Message handling functionality
503	//--------------------------------------------------------------------
504public:
505	static void processUpdateCreateInventoryItem(LLMessageSystem* msg, void**);
506	static void removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg, const char* msg_label);
507	static void processRemoveInventoryItem(LLMessageSystem* msg, void**);
508	static void processUpdateInventoryFolder(LLMessageSystem* msg, void**);
509	static void removeInventoryFolder(LLUUID agent_id, LLMessageSystem* msg);
510	static void processRemoveInventoryFolder(LLMessageSystem* msg, void**);
511	static void processRemoveInventoryObjects(LLMessageSystem* msg, void**);
512	static void processSaveAssetIntoInventory(LLMessageSystem* msg, void**);
513	static void processBulkUpdateInventory(LLMessageSystem* msg, void**);
514	static void processInventoryDescendents(LLMessageSystem* msg, void**);
515	static void processMoveInventoryItem(LLMessageSystem* msg, void**);
516	static void processFetchInventoryReply(LLMessageSystem* msg, void**);
517protected:
518	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
519
520	//--------------------------------------------------------------------
521	// Locks
522	//--------------------------------------------------------------------
523public:
524	void lockDirectDescendentArrays(const LLUUID& cat_id,
525									cat_array_t*& categories,
526									item_array_t*& items);
527	void unlockDirectDescendentArrays(const LLUUID& cat_id);
528protected:
529	cat_array_t* getUnlockedCatArray(const LLUUID& id);
530	item_array_t* getUnlockedItemArray(const LLUUID& id);
531private:
532	std::map<LLUUID, bool> mCategoryLock;
533	std::map<LLUUID, bool> mItemLock;
534	
535	//--------------------------------------------------------------------
536	// Debugging
537	//--------------------------------------------------------------------
538public:
539	void dumpInventory() const;
540
541/**                    Miscellaneous
542 **                                                                            **
543 *******************************************************************************/
544};
545
546// a special inventory model for the agent
547extern LLInventoryModel gInventory;
548
549#endif // LL_LLINVENTORYMODEL_H
550