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