diff options
author | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2013-04-25 17:09:05 -0400 |
---|---|---|
committer | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2013-04-25 17:09:05 -0400 |
commit | d843a0d8bef5d36d3a4ef838b1b0335b4532147b (patch) | |
tree | 8861ebcde11e00cc7b900de7bd4cef8869730357 /indra/newview | |
parent | e60cb90b632d175690f48b783ece272deff524cd (diff) |
SH-4137 WIP - added callback-based support for purge descendents, remove category
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 9 | ||||
-rwxr-xr-x | indra/newview/llinventorymodel.cpp | 207 | ||||
-rwxr-xr-x | indra/newview/llinventorymodel.h | 19 | ||||
-rw-r--r-- | indra/newview/llpreview.cpp | 7 | ||||
-rwxr-xr-x | indra/newview/llviewerinventory.cpp | 286 | ||||
-rwxr-xr-x | indra/newview/llviewerinventory.h | 14 |
6 files changed, 321 insertions, 221 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a5043a30ac..27f35c5946 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1159,17 +1159,10 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) { - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } LLInventoryObject* obj = model->getObject(uuid); if (obj) { - model->purgeObject(uuid); - model->notifyObservers(); + remove_inventory_object(uuid, NULL); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a0b9e7b0ec..ae8efeecda 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1136,6 +1136,79 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } +// Update model after descendents have been purged. +void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id) +{ + LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id); + if (cat.notNull()) + { + // do the cache accounting + S32 descendents = cat->getDescendentCount(); + if(descendents > 0) + { + LLInventoryModel::LLCategoryUpdate up(object_id, -descendents); + accountForUpdate(up); + } + + // we know that descendent count is 0, however since the + // accounting may actually not do an update, we should force + // it here. + cat->setDescendentCount(0); + + // unceremoniously remove anything we have locally stored. + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + collectDescendents(object_id, + categories, + items, + LLInventoryModel::INCLUDE_TRASH); + S32 count = items.count(); + + LLUUID uu_id; + for(S32 i = 0; i < count; ++i) + { + uu_id = items.get(i)->getUUID(); + + // This check prevents the deletion of a previously deleted item. + // This is necessary because deletion is not done in a hierarchical + // order. The current item may have been already deleted as a child + // of its deleted parent. + if (getItem(uu_id)) + { + deleteObject(uu_id); + } + } + + count = categories.count(); + for(S32 i = 0; i < count; ++i) + { + uu_id = categories.get(i)->getUUID(); + if (getCategory(uu_id)) + { + deleteObject(uu_id); + } + } + } +} + +// Update model after an item is confirmed as removed from +// server. Works for categories or items. +void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id) +{ + LLPointer<LLInventoryObject> obj = getObject(object_id); + if(obj) + { + // From item/cat removeFromServer() + LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); + accountForUpdate(up); + + // From purgeObject() + LLPreview::hide(object_id); + deleteObject(object_id); + } +} + + // Delete a particular inventory object by ID. void LLInventoryModel::deleteObject(const LLUUID& id) { @@ -1187,20 +1260,7 @@ void LLInventoryModel::deleteObject(const LLUUID& id) { updateLinkedObjectsFromPurge(id); } - gInventory.notifyObservers(); -} - -// Delete a particular inventory item by ID, and remove it from the server. -void LLInventoryModel::purgeObject(const LLUUID &id) -{ - lldebugs << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << llendl; - LLPointer<LLInventoryObject> obj = getObject(id); - if(obj) - { - obj->removeFromServer(); - LLPreview::hide(id); - deleteObject(id); - } + notifyObservers(); } void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) @@ -1225,119 +1285,6 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) } } -// This is a method which collects the descendents of the id -// provided. If the category is not found, no action is -// taken. This method goes through the long winded process of -// cancelling any calling cards, removing server representation of -// folders, items, etc in a fairly efficient manner. -void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) -{ - EHasChildren children = categoryHasChildren(id); - if(children == CHILDREN_NO) - { - llinfos << "Not purging descendents of " << id << llendl; - return; - } - LLPointer<LLViewerInventoryCategory> cat = getCategory(id); - if (cat.notNull()) - { - if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) - { - // Something on the clipboard is in "cut mode" and needs to be preserved - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << " iterate and purge non hidden items" << llendl; - cat_array_t* categories; - item_array_t* items; - // Get the list of direct descendants in tha categoy passed as argument - getDirectDescendentsOf(id, categories, items); - std::vector<LLUUID> list_uuids; - // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) - // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists - for (cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) - { - list_uuids.push_back((*it)->getUUID()); - } - for (item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) - { - list_uuids.push_back((*it)->getUUID()); - } - // Iterate through the list and only purge the UUIDs that are not on the clipboard - for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) - { - if (!LLClipboard::instance().isOnClipboard(*it)) - { - purgeObject(*it); - } - } - } - else - { - // Fast purge - // do the cache accounting - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; - S32 descendents = cat->getDescendentCount(); - if(descendents > 0) - { - LLCategoryUpdate up(id, -descendents); - accountForUpdate(up); - } - - // we know that descendent count is 0, however since the - // accounting may actually not do an update, we should force - // it here. - cat->setDescendentCount(0); - - // send it upstream - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("PurgeInventoryDescendents"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("InventoryData"); - msg->addUUID("FolderID", id); - gAgent.sendReliableMessage(); - - // unceremoniously remove anything we have locally stored. - cat_array_t categories; - item_array_t items; - collectDescendents(id, - categories, - items, - INCLUDE_TRASH); - S32 count = items.count(); - - item_map_t::iterator item_map_end = mItemMap.end(); - cat_map_t::iterator cat_map_end = mCategoryMap.end(); - LLUUID uu_id; - - for(S32 i = 0; i < count; ++i) - { - uu_id = items.get(i)->getUUID(); - - // This check prevents the deletion of a previously deleted item. - // This is necessary because deletion is not done in a hierarchical - // order. The current item may have been already deleted as a child - // of its deleted parent. - if (mItemMap.find(uu_id) != item_map_end) - { - deleteObject(uu_id); - } - } - - count = categories.count(); - for(S32 i = 0; i < count; ++i) - { - uu_id = categories.get(i)->getUUID(); - if (mCategoryMap.find(uu_id) != cat_map_end) - { - deleteObject(uu_id); - } - } - } - } -} - // Add/remove an observer. If the observer is destroyed, be sure to // remove it. void LLInventoryModel::addObserver(LLInventoryObserver* observer) @@ -3114,8 +3061,7 @@ bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const L if (option == 0) // YES { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purgeDescendentsOf(folder_id); - notifyObservers(); + purge_descendents_of(folder_id, NULL); } return false; } @@ -3130,8 +3076,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT else { const LLUUID folder_id = findCategoryUUIDForType(preferred_type); - purgeDescendentsOf(folder_id); - notifyObservers(); + purge_descendents_of(folder_id, NULL); } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 50b57ea08d..b7e1888f20 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -325,6 +325,14 @@ public: // Delete //-------------------------------------------------------------------- public: + + // Update model after an item is confirmed as removed from + // server. Works for categories or items. + void onObjectDeletedFromServer(const LLUUID& item_id); + + // Update model after all descendents removed from server. + void onDescendentsPurgedFromServer(const LLUUID& object_id); + // Delete a particular inventory object by ID. Will purge one // object from the internal data structures, maintaining a // consistent internal state. No cache accounting, observer @@ -337,17 +345,6 @@ public: /// removeItem() or removeCategory(), whichever is appropriate void removeObject(const LLUUID& object_id); - // Delete a particular inventory object by ID, and delete it from - // the server. Also updates linked items. - void purgeObject(const LLUUID& id); - - // Collects and purges the descendants of the id - // provided. If the category is not found, no action is - // taken. This method goes through the long winded process of - // removing server representation of folders and items while doing - // cache accounting in a fairly efficient manner. This method does - // not notify observers (though maybe it should...) - void purgeDescendentsOf(const LLUUID& id); protected: void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id); diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 04934b13f1..452efad291 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -401,13 +401,6 @@ void LLPreview::onDiscardBtn(void* data) self->mForceClose = TRUE; self->closeFloater(); - // Delete the item entirely - /* - item->removeFromServer(); - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - */ - // Move the item to the trash const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if (item->getParentUUID() != trash_id) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 06efeb86d9..fbd6b292bd 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -65,6 +65,7 @@ #include "llavataractions.h" #include "lllogininstance.h" #include "llfavoritesbar.h" +#include "llclipboard.h" // Two do-nothing ops for use in callbacks. void no_op_inventory_func(const LLUUID&) {} @@ -345,24 +346,6 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer<LLViewerInventoryItem>& ne } } -void LLViewerInventoryItem::removeFromServer() -{ - lldebugs << "Removing inventory item " << mUUID << " from server." - << llendl; - - LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); - gInventory.accountForUpdate(up); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, mUUID); - gAgent.sendReliableMessage(); -} - void LLViewerInventoryItem::updateServer(BOOL is_new) const { if(!mIsComplete) @@ -637,30 +620,6 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const gAgent.sendReliableMessage(); } -void LLViewerInventoryCategory::removeFromServer( void ) -{ - llinfos << "Removing inventory category " << mUUID << " from server." - << llendl; - // communicate that change with the server. - if(LLFolderType::lookupIsProtectedType(mPreferredType)) - { - LLNotificationsUtil::add("CannotRemoveProtectedCategories"); - return; - } - - LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); - gInventory.accountForUpdate(up); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, mUUID); - gAgent.sendReliableMessage(); -} - S32 LLViewerInventoryCategory::getVersion() const { return mVersion; @@ -1179,25 +1138,10 @@ void move_inventory_item( gAgent.sendReliableMessage(); } -void handle_item_deletion(const LLUUID& item_id) -{ - LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id); - if(obj) - { - // From item removeFromServer() - LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); - gInventory.accountForUpdate(up); - - // From purgeObject() - LLPreview::hide(item_id); - gInventory.deleteObject(item_id); - } -} - -class RemoveItemResponder: public LLHTTPClient::Responder +class RemoveObjectResponder: public LLHTTPClient::Responder { public: - RemoveItemResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback): + RemoveObjectResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback): mItemUUID(item_id), mCallback(callback) { @@ -1212,7 +1156,7 @@ public: } llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; - handle_item_deletion(mItemUUID); + gInventory.onObjectDeletedFromServer(mItemUUID); if (mCallback) { @@ -1251,7 +1195,7 @@ void remove_inventory_item( { std::string url = cap + std::string("/item/") + item_id.asString(); llinfos << "url: " << url << llendl; - LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb); + LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(item_id,cb); LLHTTPClient::del(url,responder_ptr); } else // no cap @@ -1267,7 +1211,7 @@ void remove_inventory_item( // Update inventory and call callback immediately since // message-based system has no callback mechanism (!) - handle_item_deletion(item_id); + gInventory.onObjectDeletedFromServer(item_id); if (cb) { cb->fire(item_id); @@ -1280,6 +1224,224 @@ void remove_inventory_item( } } +class LLRemoveObjectOnDestroy: public LLInventoryCallback +{ +public: + LLRemoveObjectOnDestroy(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb): + mID(item_id), + mCB(cb) + { + } + /* virtual */ void fire(const LLUUID& item_id) {} + ~LLRemoveObjectOnDestroy() + { + remove_inventory_object(mID, mCB); + } +private: + LLUUID mID; + LLPointer<LLInventoryCallback> mCB; +}; + +void remove_inventory_category( + const LLUUID& cat_id, + LLPointer<LLInventoryCallback> cb) +{ + llinfos << "cat_id: [" << cat_id << "] " << llendl; + LLPointer<LLViewerInventoryCategory> obj = gInventory.getCategory(cat_id); + if(obj) + { + if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) + { + LLNotificationsUtil::add("CannotRemoveProtectedCategories"); + return; + } + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); + if(children != LLInventoryModel::CHILDREN_NO) + { + llinfos << "Will purge descendents first before deleting category " << cat_id << llendl; + LLPointer<LLInventoryCallback> wrap_cb = new LLRemoveObjectOnDestroy(cat_id,cb); + purge_descendents_of(cat_id, wrap_cb); + return; + } + + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/category/") + cat_id.asString(); + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(cat_id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RemoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, cat_id); + gAgent.sendReliableMessage(); + + // Update inventory and call callback immediately since + // message-based system has no callback mechanism (!) + gInventory.onObjectDeletedFromServer(cat_id); + if (cb) + { + cb->fire(cat_id); + } + } + } + else + { + llwarns << "remove_inventory_category called for invalid or nonexistent item " << cat_id << llendl; + } +} + +void remove_inventory_object( + const LLUUID& object_id, + LLPointer<LLInventoryCallback> cb) +{ + if (gInventory.getCategory(object_id)) + { + remove_inventory_category(object_id, cb); + } + else + { + remove_inventory_item(object_id, cb); + } +} + +class PurgeDescendentsResponder: public LLHTTPClient::Responder +{ +public: + PurgeDescendentsResponder(const LLUUID& item_id, LLPointer<LLInventoryCallback> callback): + mItemUUID(item_id), + mCallback(callback) + { + } + /* virtual */ void httpSuccess() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; + + gInventory.onDescendentsPurgedFromServer(mItemUUID); + + if (mCallback) + { + mCallback->fire(mItemUUID); + } + } + /*virtual*/ void httpFailure() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + } +private: + LLPointer<LLInventoryCallback> mCallback; + const LLUUID mItemUUID; +}; + +// This is a method which collects the descendents of the id +// provided. If the category is not found, no action is +// taken. This method goes through the long winded process of +// cancelling any calling cards, removing server representation of +// folders, items, etc in a fairly efficient manner. +void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb) +{ + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); + if(children == LLInventoryModel::CHILDREN_NO) + { + llinfos << "No descendents to purge for " << id << llendl; + return; + } + LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(id); + if (cat.notNull()) + { + if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) + { + // Something on the clipboard is in "cut mode" and needs to be preserved + llinfos << "purge_descendents_of clipboard case " << cat->getName() + << " iterate and purge non hidden items" << llendl; + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + // Get the list of direct descendants in tha categoy passed as argument + gInventory.getDirectDescendentsOf(id, categories, items); + std::vector<LLUUID> list_uuids; + // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) + // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) + { + list_uuids.push_back((*it)->getUUID()); + } + for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it != items->end(); ++it) + { + list_uuids.push_back((*it)->getUUID()); + } + // Iterate through the list and only purge the UUIDs that are not on the clipboard + for (std::vector<LLUUID>::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + { + if (!LLClipboard::instance().isOnClipboard(*it)) + { + remove_inventory_object(*it, NULL); + } + } + } + else + { + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/category/") + id.asString() + "/children"; + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new PurgeDescendentsResponder(id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + // Fast purge + llinfos << "purge_descendents_of fast case " << cat->getName() << llendl; + + // send it upstream + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("PurgeInventoryDescendents"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("InventoryData"); + msg->addUUID("FolderID", id); + gAgent.sendReliableMessage(); + + // Update model immediately because there is no callback mechanism. + gInventory.onDescendentsPurgedFromServer(id); + if (cb) + { + cb->fire(id); + } + } + } + } +} + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) { LLUUID retval = LLUUID::null; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 6b0e8ed4ef..4e24dc87d1 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -118,7 +118,6 @@ public: void cloneViewerItem(LLPointer<LLViewerInventoryItem>& newitem) const; // virtual methods - virtual void removeFromServer( void ); virtual void updateParentOnServer(BOOL restamp) const; virtual void updateServer(BOOL is_new) const; void fetchFromServer(void) const; @@ -198,7 +197,6 @@ public: LLViewerInventoryCategory(const LLViewerInventoryCategory* other); void copyViewerCategory(const LLViewerInventoryCategory* other); - virtual void removeFromServer(); virtual void updateParentOnServer(BOOL restamp_children) const; virtual void updateServer(BOOL is_new) const; @@ -369,6 +367,18 @@ void remove_inventory_item( const LLUUID& item_id, LLPointer<LLInventoryCallback> cb); +void remove_inventory_category( + const LLUUID& cat_id, + LLPointer<LLInventoryCallback> cb); + +void remove_inventory_object( + const LLUUID& object_id, + LLPointer<LLInventoryCallback> cb); + +void purge_descendents_of( + const LLUUID& cat_id, + LLPointer<LLInventoryCallback> cb); + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src); void copy_inventory_from_notecard(const LLUUID& destination_id, |