From 2e564abcd682c348de3a2d3a50ef58df545c143b Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Thu, 15 Dec 2011 14:26:42 -0800 Subject: EXP-1730 FIX EXP-1731 FIX EXP-1735 FIX EXP-1736 FIX EXP-1737 FIX EXP-1738 FIX EXP-1739 FIX * Users can no longer drag and drop items to the outbox from in world, notecards or the library. * Drag and drop now blocks the creation of hierarchies that are too deep, too many folders or contain too many items. * Settings now exist to specify drag and drop limitations to the outbox, named: InventoryOutboxMaxFolderDepth (4) InventoryOutboxMaxFolderCount (20) InventoryOutboxMaxItemCount (200) --- indra/newview/llinventorymodel.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index dc25689fa3..2fb9c53857 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -217,6 +217,38 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons return NULL; } +// +// Search up the parent chain until we get to the specified parent, then return the first child category under it +// +const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const +{ + if (master_parent_id == obj_id) + { + return NULL; + } + + const LLViewerInventoryCategory* current_cat = getCategory(obj_id); + + if (current_cat == NULL) + { + current_cat = getCategory(getObject(obj_id)->getParentUUID()); + } + + while (current_cat != NULL) + { + const LLUUID& current_parent_id = current_cat->getParentUUID(); + + if (current_parent_id == master_parent_id) + { + return current_cat; + } + + current_cat = getCategory(current_parent_id); + } + + return NULL; +} + // Get the object by id. Returns NULL if not found. LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const { -- cgit v1.3 From bd3a652eabf09a5843a6a0b8a9f60c4b402ecce5 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Fri, 6 Jan 2012 07:46:53 -0500 Subject: Add capability-based create folder routine for more reliable inventory, with fix for copy and wear --- indra/newview/llfloateropenobject.cpp | 60 ++++++++++++++++++++---- indra/newview/llfloateropenobject.h | 11 +++++ indra/newview/llinventorybridge.cpp | 13 +++--- indra/newview/llinventorymodel.cpp | 87 +++++++++++++++++++++++++++++++++-- indra/newview/llinventorymodel.h | 4 +- indra/newview/llviewerregion.cpp | 1 + 6 files changed, 155 insertions(+), 21 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 8b6619def2..4bfef8b45f 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -162,26 +162,66 @@ void LLFloaterOpenObject::moveToInventory(bool wear) { parent_category_id = gInventory.getRootFolderID(); } + + LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear); + LLUUID category_id = gInventory.createNewCategory(parent_category_id, - LLFolderType::FT_NONE, - name); + LLFolderType::FT_NONE, + name, + callbackCreateInventoryCategory, + (void*)cat_data); + + //If we get a null category ID, we are using a capability in createNewCategory and we will + //handle the following in the callbackCreateInventoryCategory routine. + if ( category_id.notNull() ) + { + delete cat_data; + + LLCatAndWear* data = new LLCatAndWear; + data->mCatID = category_id; + data->mWear = wear; + data->mFolderResponded = false; + + // Copy and/or move the items into the newly created folder. + // Ignore any "you're going to break this item" messages. + BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE, + callbackMoveInventory, + (void*)data); + if (!success) + { + delete data; + data = NULL; - LLCatAndWear* data = new LLCatAndWear; - data->mCatID = category_id; - data->mWear = wear; + LLNotificationsUtil::add("OpenObjectCannotCopy"); + } + } +} +// static +void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data) +{ + LLCategoryCreate* cat_data = (LLCategoryCreate*)data; + + LLUUID category_id = result["folder_id"].asUUID(); + LLCatAndWear* wear_data = new LLCatAndWear; + + wear_data->mCatID = category_id; + wear_data->mWear = cat_data->mWear; + wear_data->mFolderResponded = true; + // Copy and/or move the items into the newly created folder. // Ignore any "you're going to break this item" messages. - BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE, + BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE, callbackMoveInventory, - (void*)data); + (void*)wear_data); if (!success) { - delete data; - data = NULL; - + delete wear_data; + wear_data = NULL; + LLNotificationsUtil::add("OpenObjectCannotCopy"); } + delete cat_data; } // static diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 0706e99f16..bf7fe69c65 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -45,10 +45,20 @@ public: void dirty(); + class LLCategoryCreate + { + public: + LLCategoryCreate(LLUUID object_id, bool wear) : mObjectID(object_id), mWear(wear) {} + public: + LLUUID mObjectID; + bool mWear; + }; + struct LLCatAndWear { LLUUID mCatID; bool mWear; + bool mFolderResponded; }; protected: @@ -62,6 +72,7 @@ protected: void onClickMoveToInventory(); void onClickMoveAndWear(); + static void callbackCreateInventoryCategory(const LLSD& result, void* data); static void callbackMoveInventory(S32 result, void* data); private: diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0c092e9a56..eaf9b53eb9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2305,15 +2305,15 @@ void LLRightClickInventoryFetchDescendentsObserver::done() class LLInventoryCopyAndWearObserver : public LLInventoryObserver { public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) : - mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count, bool folder_added=false) : + mCatID(cat_id), mContentsCount(count), mFolderAdded(folder_added) {} virtual ~LLInventoryCopyAndWearObserver() {} virtual void changed(U32 mask); protected: LLUUID mCatID; int mContentsCount; - BOOL mFolderAdded; + bool mFolderAdded; }; @@ -2341,7 +2341,6 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) if (mFolderAdded) { LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - if (NULL == category) { llwarns << "gInventory.getCategory(" << mCatID @@ -3188,13 +3187,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response if(option == 0 && object) { - if (cat_and_wear && cat_and_wear->mWear) + if (cat_and_wear && cat_and_wear->mWear) // && !cat_and_wear->mFolderResponded) { LLInventoryObject::object_list_t inventory_objects; object->getInventoryContents(inventory_objects); int contents_count = inventory_objects.size()-1; //subtract one for containing folder - - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded); + gInventory.addObserver(inventoryObserver); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index dc25689fa3..568ec4c5e2 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -377,14 +377,67 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe return rv; } +class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder +{ +public: + LLCreateInventoryCategoryResponder(LLInventoryModel* model, + void (*callback)(const LLSD&, void*), + void* user_data) : + mModel(model), + mCallback(callback), + mData(user_data) + { + } + + virtual void error(U32 status, const std::string& reason) + { + LL_WARNS("InvAPI") << "CreateInventoryCategory failed. status = " << status << ", reasion = \"" << reason << "\"" << LL_ENDL; + } + + virtual void result(const LLSD& content) + { + //Server has created folder. + + LLUUID category_id = content["folder_id"].asUUID(); + + + // Add the category to the internal representation + LLPointer cat = + new LLViewerInventoryCategory( category_id, + content["parent_id"].asUUID(), + (LLFolderType::EType)content["type"].asInteger(), + content["name"].asString(), + gAgent.getID() ); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setDescendentCount(0); + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + mModel->accountForUpdate(update); + mModel->updateCategory(cat); + + if (mCallback && mData) + { + mCallback(content, mData); + } + + } + +private: + void (*mCallback)(const LLSD&, void*); + void* mData; + LLInventoryModel* mModel; +}; + // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be // based on preferred type. Returns the UUID of the new category. LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, - const std::string& pname) + const std::string& pname, + void (*callback)(const LLSD&, void*), //Default to NULL + void* user_data) //Default to NULL { + LLUUID id; if(!isInventoryUsable()) { @@ -408,6 +461,35 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, { name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); } + + if ( callback && user_data ) //callback required for acked message. + { + LLViewerRegion* viewer_region = gAgent.getRegion(); + std::string url; + if ( viewer_region ) + url = viewer_region->getCapability("CreateInventoryCategory"); + + if (!url.empty()) + { + //Let's use the new capability. + + LLSD request, body; + body["folder_id"] = id; + body["parent_id"] = parent_id; + body["type"] = (LLSD::Integer) preferred_type; + body["name"] = name; + + request["message"] = "CreateInventoryCategory"; + request["payload"] = body; + + // viewer_region->getCapAPI().post(request); + LLHTTPClient::post( + url, + body, + new LLCreateInventoryCategoryResponder(this, callback, user_data) ); + return LLUUID::null; + } + } // Add the category to the internal representation LLPointer cat = @@ -1087,7 +1169,6 @@ void LLInventoryModel::notifyObservers() iter != mObservers.end(); ) { LLInventoryObserver* observer = *iter; - observer->changed(mModifyMask); // safe way to increment since changed may delete entries! (@!##%@!@&*!) @@ -2574,7 +2655,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); - if(titem->getUUID().notNull()) + if(titem->getUUID().notNull() ) // && callback_id.notNull() ) { items.push_back(titem); cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID())); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 340c1b0c22..0a564d353a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -360,7 +360,9 @@ public: // name based on type, pass in a NULL to the 'name' parameter. LLUUID createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, - const std::string& name); + const std::string& name, + void (*callback)(const LLSD&, void*) = NULL, + void* user_data = NULL ); protected: // Internal methods that add inventory and make sure that all of // the internal data structures are consistent. These methods diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ed943964f9..e3cb985ddb 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1493,6 +1493,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("AvatarPickerSearch"); capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("DispatchRegionInfo"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); -- cgit v1.3 From 7b866448dbeeeb04b074df493369927afcf9971a Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 12 Mar 2012 13:59:25 -0700 Subject: EXP-1922 : Skip the clipboard elements when purging the trash when in cut mode --- indra/newview/llinventorymodel.cpp | 114 ++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 41 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a71b699fdd..06e780508b 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" +#include "llclipboard.h" #include "llinventorypanel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -1110,50 +1111,81 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) return; } LLPointer cat = getCategory(id); - if(cat.notNull()) - { - // do the cache accounting - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; - S32 descendents = cat->getDescendentCount(); - if(descendents > 0) - { - LLCategoryUpdate up(id, -descendents); - accountForUpdate(up); + if (cat.notNull()) + { + if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) + { + // Something on the clipboard is in "cut mode" and needs to be preserved + llinfos << "Merov debug : purging through iteration" << 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 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::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, aide since the - // accounting may actually not do an update, we should force - // it here. - cat->setDescendentCount(0); + // 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(); - // 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(); - S32 i; - for(i = 0; i < count; ++i) - { - deleteObject(items.get(i)->getUUID()); - } - count = categories.count(); - for(i = 0; i < count; ++i) - { - deleteObject(categories.get(i)->getUUID()); + // 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(); + for(S32 i = 0; i < count; ++i) + { + deleteObject(items.get(i)->getUUID()); + } + count = categories.count(); + for(S32 i = 0; i < count; ++i) + { + deleteObject(categories.get(i)->getUUID()); + } } } } -- cgit v1.3 From 82700548058527001657758888cf79df099064b3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 13 Mar 2012 21:08:10 -0700 Subject: EXP-1915 : Rewrote the fetching mechanism for folders making it truly recursive. --- indra/newview/llinventorybridge.cpp | 221 ++++++++++++++++++++---------------- indra/newview/llinventorymodel.cpp | 3 +- 2 files changed, 128 insertions(+), 96 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 060250cc07..03f6a31c6d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -143,19 +143,40 @@ bool isMarketplaceSendAction(const std::string& action) return ("send_to_marketplace" == action); } -//Used by LLFolderBridge as callback for directory recursion. +// Used by LLFolderBridge as callback for directory fetching recursion class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver { public: - LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids, - bool copy_items) : - LLInventoryFetchDescendentsObserver(ids), - mCopyItems(copy_items) - {} + LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids) : LLInventoryFetchDescendentsObserver(ids) {} ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; + virtual void execute(bool clear_observer = false); + virtual void done() + { + execute(true); + } +}; + +// Used by LLFolderBridge as callback for directory content items fetching +class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver +{ +public: + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : LLInventoryFetchItemsObserver(ids) { }; + ~LLRightClickInventoryFetchObserver() {} + void execute(bool clear_observer = false) + { + if (clear_observer) + { + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + } + // we've downloaded all the items, so repaint the dialog + LLFolderBridge::staticFolderOptionsMenu(); + } + virtual void done() + { + execute(true); + } }; // +=================================================+ @@ -2499,106 +2520,114 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return accept; } -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver +void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) { -public: - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : - LLInventoryFetchItemsObserver(ids), - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const uuid_vec_t& ids, - const LLUUID& cat_id, - bool copy_items) : - LLInventoryFetchItemsObserver(ids), - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() -{ - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() + // Bail out immediately if no descendents if( mComplete.empty() ) { llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; + if (clear_observer) + { + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + } return; } - - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mComplete.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; + + // Copy the list of complete fetched folders while "this" is still valid + uuid_vec_t completed_folder = mComplete; + + // Clean up, and remove this as an observer now since recursive calls + // could notify observers and throw us into an infinite loop. + if (clear_observer) + { dec_busy_count(); gInventory.removeObserver(this); delete this; - return; } -#endif - - uuid_vec_t ids; - for(S32 i = 0; i < count; ++i) + + for (uuid_vec_t::iterator current_folder = completed_folder.begin(); current_folder != completed_folder.end(); ++current_folder) { - ids.push_back(item_array.get(i)->getUUID()); - } + // Get the information on the fetched folder items and subfolders and fetch those + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array); - LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems); + S32 item_count = item_array->count(); + S32 cat_count = cat_array->count(); + + // Move to next if current folder empty + if ((item_count == 0) && (cat_count == 0)) + { + continue; + } - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; + uuid_vec_t ids; + LLRightClickInventoryFetchObserver* outfit = NULL; + LLRightClickInventoryFetchDescendentsObserver* categories = NULL; - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); + // Fetch the items + if (item_count) + { + for (S32 i = 0; i < item_count; ++i) + { + ids.push_back(item_array->get(i)->getUUID()); + } + outfit = new LLRightClickInventoryFetchObserver(ids); + } + // Fetch the subfolders + if (cat_count) + { + for (S32 i = 0; i < cat_count; ++i) + { + ids.push_back(cat_array->get(i)->getUUID()); + } + categories = new LLRightClickInventoryFetchDescendentsObserver(ids); + } - // do the fetch - outfit->startFetch(); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. -//Uncomment the following code for laggy Inventory UI. -/* if(outfit->isFinished()) - { - // everything is already here - call done. - outfit->done(); + // Perform the item fetch + if (outfit) + { + outfit->startFetch(); + outfit->execute(); // Not interested in waiting and this will be right 99% of the time. + delete outfit; + // Uncomment the following code for laggy Inventory UI. + /* + if (outfit->isFinished()) + { + // everything is already here - call done. + outfit->execute(); + delete outfit; + } + else + { + // it's all on its way - add an observer, and the inventory + // will call done for us when everything is here. + inc_busy_count(); + gInventory.addObserver(outfit); + } + */ + } + // Perform the subfolders fetch : this is where we truly recurse down the folder hierarchy + if (categories) + { + categories->startFetch(); + if (categories->isFinished()) + { + // everything is already here - call done. + categories->execute(); + delete categories; + } + else + { + // it's all on its way - add an observer, and the inventory + // will call done for us when everything is here. + inc_busy_count(); + gInventory.addObserver(categories); + } + } } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - }*/ } @@ -3375,17 +3404,19 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) folders.push_back(category->getUUID()); sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); fetch->startFetch(); - inc_busy_count(); if (fetch->isFinished()) { + // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down + // This saves lots of time as buildContextMenu() is called a lot delete fetch; buildContextMenuFolderOptions(flags); } else { // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + inc_busy_count(); gInventory.addObserver(fetch); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 06e780508b..0eba8bd0f1 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1116,7 +1116,8 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) { // Something on the clipboard is in "cut mode" and needs to be preserved - llinfos << "Merov debug : purging through iteration" << llendl; + 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 -- cgit v1.3 From fdd018783a0cc06a467443ca7c9ea0876a87ef49 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 27 Mar 2012 18:40:17 -0400 Subject: CHOP-854: move change_(item|category)_parent() into LLInventoryModel. It's not really clear why they're in llinventoryfunctions.{h,cpp} instead of LLInventoryModel, and in fact LLInventoryModel::removeItem() already contains code essentially cloned from change_item_parent() -- or perhaps vice-versa. This changeset addresses only migrating the functions, and fixing up existing references, to simplify code review. --- indra/newview/llinventorybridge.cpp | 4 +-- indra/newview/llinventoryfunctions.cpp | 59 ++-------------------------------- indra/newview/llinventoryfunctions.h | 10 ------ indra/newview/llinventorymodel.cpp | 52 ++++++++++++++++++++++++++++++ indra/newview/llinventorymodel.h | 10 ++++++ indra/newview/llpreviewnotecard.cpp | 3 +- 6 files changed, 68 insertions(+), 70 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c0065a94e6..21f03e3d66 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -910,7 +910,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - change_item_parent(model, item, new_parent_id, restamp); + model->changeItemParent(item, new_parent_id, restamp); } // static @@ -919,7 +919,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, const LLUUID& new_parent_id, BOOL restamp) { - change_category_parent(model, cat, new_parent_id, restamp); + model->changeCategoryParent(cat, new_parent_id, restamp); } LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index dd92188e9d..ae8d11c3f7 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -109,58 +109,6 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } -void change_item_parent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent_id, - BOOL restamp) -{ - if (item->getParentUUID() != new_parent_id) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent_id); - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } -} - -void change_category_parent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent_id, - BOOL restamp) -{ - if (!model || !cat) - { - return; - } - - // Can't move a folder into a child of itself. - if (model->isObjectDescendentOf(new_parent_id, cat->getUUID())) - { - return; - } - - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - model->accountForUpdate(update); - - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent_id); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); -} - void remove_category(LLInventoryModel* model, const LLUUID& cat_id) { if (!model || !get_is_category_removable(model, cat_id)) @@ -190,7 +138,7 @@ void remove_category(LLInventoryModel* model, const LLUUID& cat_id) if (cat) { const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - change_category_parent(model, cat, trash_id, TRUE); + model->changeCategoryParent(cat, trash_id, TRUE); } } @@ -568,8 +516,7 @@ void move_to_outbox_cb_action(const LLSD& payload) LLUUID parent = viitem->getParentUUID(); - change_item_parent( - &gInventory, + gInventory.changeItemParent( viitem, dest_folder_id, false); @@ -670,7 +617,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; - change_item_parent(&gInventory, + gInventory.changeItemParent( viewer_inv_item, dest_folder, false); diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index ce2b89b22e..602c411104 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -57,16 +57,6 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); -void change_item_parent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent_id, - BOOL restamp); - -void change_category_parent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent_id, - BOOL restamp); - void remove_category(LLInventoryModel* model, const LLUUID& cat_id); void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a71b699fdd..6cc0d6768e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1017,6 +1017,58 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) } } +// Migrated from llinventoryfunctions +void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, + const LLUUID& new_parent_id, + BOOL restamp) +{ + if (item->getParentUUID() != new_parent_id) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->setParent(new_parent_id); + new_item->updateParentOnServer(restamp); + updateItem(new_item); + notifyObservers(); + } +} + +// Migrated from llinventoryfunctions +void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, + const LLUUID& new_parent_id, + BOOL restamp) +{ + if (!cat) + { + return; + } + + // Can't move a folder into a child of itself. + if (isObjectDescendentOf(new_parent_id, cat->getUUID())) + { + return; + } + + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); + update.push_back(new_folder); + accountForUpdate(update); + + LLPointer new_cat = new LLViewerInventoryCategory(cat); + new_cat->setParent(new_parent_id); + new_cat->updateParentOnServer(restamp); + updateCategory(new_cat); + notifyObservers(); +} + // Delete a particular inventory object by ID. void LLInventoryModel::deleteObject(const LLUUID& id) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 7cd85c4ab7..f4602ce922 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -306,6 +306,16 @@ public: // observer notification, or server update is performed. void moveObject(const LLUUID& object_id, const LLUUID& cat_id); + // Migrated from llinventoryfunctions + void changeItemParent(LLViewerInventoryItem* item, + const LLUUID& new_parent_id, + BOOL restamp); + + // Migrated from llinventoryfunctions + void changeCategoryParent(LLViewerInventoryCategory* cat, + const LLUUID& new_parent_id, + BOOL restamp); + //-------------------------------------------------------------------- // Delete //-------------------------------------------------------------------- diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 4974dde282..3a9360fd23 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -29,7 +29,6 @@ #include "llpreviewnotecard.h" #include "llinventory.h" -#include "llinventoryfunctions.h" // for change_item_parent() #include "llagent.h" #include "llassetuploadresponders.h" @@ -494,7 +493,7 @@ void LLPreviewNotecard::deleteNotecard() if (item != NULL) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - change_item_parent(&gInventory, item, trash_id, FALSE); + gInventory.changeItemParent(item, trash_id, FALSE); } closeFloater(); -- cgit v1.3 From b8561da34d5d733670b6b1eabf483871ec6c18b0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 27 Mar 2012 19:06:33 -0400 Subject: CHOP-854: Make LLInventoryModel::removeItem() call changeItemParent(). The body of removeItem() was already nearly identical to the body of changeItemParent(); this eliminates the redundancy. Improve logging for changeItemParent(). --- indra/newview/llinventorymodel.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6cc0d6768e..de52f3a18d 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1022,8 +1022,16 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, const LLUUID& new_parent_id, BOOL restamp) { - if (item->getParentUUID() != new_parent_id) + if (item->getParentUUID() == new_parent_id) { + LL_DEBUGS("Inventory") << "'" << item->getName() << "' (" << item->getUUID() + << ") is already in folder " << new_parent_id << LL_ENDL; + } + else + { + LL_INFOS("Inventory") << "Moving '" << item->getName() << "' (" << item->getUUID() + << ") from " << item->getParentUUID() << " to folder " + << new_parent_id << LL_ENDL; LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); update.push_back(old_folder); @@ -2983,21 +2991,15 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT void LLInventoryModel::removeItem(const LLUUID& item_id) { LLViewerInventoryItem* item = getItem(item_id); - const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (item && item->getParentUUID() != new_parent) + if (! item) { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - accountForUpdate(update); - - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent); - new_item->updateParentOnServer(TRUE); - updateItem(new_item); - notifyObservers(); + LL_WARNS("Inventory") << "couldn't find inventory item " << item_id << LL_ENDL; + } + else + { + const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); + LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; + changeItemParent(item, new_parent, TRUE); } } -- cgit v1.3 From b7e0e44e3246299b639f787e3ab9b8e59cdc05c3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 27 Mar 2012 22:39:31 -0400 Subject: CHOP-854: Use new LLInventoryModel::removeObject() to discard offer. Introduce new LLInventoryModel::removeCategory() method comparable to removeItem(), but for folder objects (using changeCategoryParent() rather than changeItemParent()). Introduce removeObject() method that calls one of the above, depending on runtime object type. --- indra/newview/llinventorymodel.cpp | 39 ++++++++++++++++++++++++++++++++++++++ indra/newview/llinventorymodel.h | 7 ++++++- indra/newview/llviewermessage.cpp | 4 +++- 3 files changed, 48 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index de52f3a18d..1ede6bc1c9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -46,6 +46,7 @@ #include "llviewerregion.h" #include "llcallbacklist.h" #include "llvoavatarself.h" +#include //#define DIFF_INVENTORY_FILES #ifdef DIFF_INVENTORY_FILES @@ -3003,6 +3004,44 @@ void LLInventoryModel::removeItem(const LLUUID& item_id) } } +void LLInventoryModel::removeCategory(const LLUUID& category_id) +{ + LLViewerInventoryCategory* cat = getCategory(category_id); + if (! cat) + { + LL_WARNS("Inventory") << "couldn't find inventory folder " << category_id << LL_ENDL; + } + else + { + const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); + LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; + changeCategoryParent(cat, new_parent, TRUE); + } +} + +void LLInventoryModel::removeObject(const LLUUID& object_id) +{ + LLInventoryObject* obj = getObject(object_id); + if (dynamic_cast(obj)) + { + removeItem(object_id); + } + else if (dynamic_cast(obj)) + { + removeCategory(object_id); + } + else if (obj) + { + LL_WARNS("Inventory") << "object ID " << object_id + << " is an object of unrecognized class " + << typeid(*obj).name() << LL_ENDL; + } + else + { + LL_WARNS("Inventory") << "object ID " << object_id << " not found" << LL_ENDL; + } +} + const LLUUID &LLInventoryModel::getRootFolderID() const { return mRootFolderID; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index f4602ce922..8382e875b4 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -325,8 +325,13 @@ public: // consistent internal state. No cache accounting, observer // notification, or server update is performed. void deleteObject(const LLUUID& id); + /// move Item item_id to Trash void removeItem(const LLUUID& item_id); - + /// move Category category_id to Trash + void removeCategory(const LLUUID& category_id); + /// 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); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3c6770df43..ed5dd84586 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1064,7 +1064,9 @@ public: // If we now try to remove the inventory item, it will cause a nested // notifyObservers() call, which won't work. // So defer moving the item to trash until viewer gets idle (in a moment). - LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID)); + // Use removeObject() rather than removeItem() because at this level, + // the object could be either an item or a folder. + LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID)); gInventory.removeObserver(this); delete this; } -- cgit v1.3 From ee87fd975faf403707908cd3c7d37f8431df46ac Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 14 Apr 2012 22:23:24 -0400 Subject: DRTVWR-136: Remove redundant remove_(item|category)() functions. Incoming changes from two different project repos left viewer-development with LLInventoryModel::removeItem() and removeCategory() plus free functions remove_item() and remove_category() in llinventoryfunctions.cpp. remove_category() was actually the better implementation; migrated its body into LLInventoryModel::removeCategory(). Clearly the previous state of affairs -- with LLInventoryModel::removeItem() plus a remove_category() free function in a very different source file -- fooled two different developers into overlooking the other of the pair. Unfortunately we each added different "missing" functions, leaving us with a complete set of four. Fix existing references to remove_item() and remove_category() free functions. --- indra/newview/llfolderview.cpp | 14 +------- indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llinventoryfunctions.cpp | 60 +--------------------------------- indra/newview/llinventoryfunctions.h | 4 --- indra/newview/llinventorymodel.cpp | 43 +++++++++++++++++++----- indra/newview/lloutfitslist.cpp | 2 +- 6 files changed, 38 insertions(+), 87 deletions(-) (limited to 'indra/newview/llinventorymodel.cpp') diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index bad0d8cd8f..1fa194ab19 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1059,19 +1059,7 @@ void LLFolderView::removeCutItems() iter != objects.end(); ++iter) { - const LLUUID& item_id = (*iter); - LLInventoryObject *obj = gInventory.getObject(item_id); - if (obj) - { - if (LLAssetType::AT_CATEGORY == obj->getType()) - { - remove_category(&gInventory, item_id); - } - else - { - remove_item(&gInventory, item_id); - } - } + gInventory.removeObject(*iter); } } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cae04ccb49..b86c453d61 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2948,7 +2948,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re { // move it to the trash LLPreview::hide(mUUID); - remove_category(getInventoryModel(), mUUID); + getInventoryModel()->removeCategory(mUUID); return TRUE; } return FALSE; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 94d1b19726..ab5b082915 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -108,64 +108,6 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } -// Move the item to the trash. Works for folders and objects. -// Caution: This method assumes that the item is removable! -void remove_item(LLInventoryModel* model, const LLUUID& id) -{ - LLViewerInventoryItem* item = model->getItem(id); - if (!item) - return; - - if (item->getType() == LLAssetType::AT_CATEGORY) - { - // Call the general helper function to delete a folder - remove_category(model, id); - } - else - { - // Get the trash UUID - LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - if (trash_id.notNull()) - { - // Finally, move the item to the trash - model->changeItemParent(item, trash_id, true); - } - } -} - -void remove_category(LLInventoryModel* model, const LLUUID& cat_id) -{ - if (!model || !get_is_category_removable(model, cat_id)) - { - return; - } - - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - - for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin(); - iter != descendent_items.end(); - ++iter) - { - const LLViewerInventoryItem* item = (*iter); - const LLUUID& item_id = item->getUUID(); - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureMgr::instance().isGestureActive(item_id)) - { - LLGestureMgr::instance().deactivateGesture(item_id); - } - } - - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat) - { - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - model->changeCategoryParent(cat, trash_id, TRUE); - } -} - void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; @@ -610,7 +552,7 @@ void move_to_outbox_cb_action(const LLSD& payload) if (cat_array->empty() && item_array->empty()) { - remove_category(&gInventory, parent); + gInventory.removeCategory(parent); } if (parent == top_level_folder) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 535d831e47..5cf9c528b0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -57,10 +57,6 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); -void remove_item(LLInventoryModel* model, const LLUUID& id); - -void remove_category(LLInventoryModel* model, const LLUUID& cat_id); - void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1ea4cb63f6..85ecb133d0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -47,6 +47,7 @@ #include "llviewerregion.h" #include "llcallbacklist.h" #include "llvoavatarself.h" +#include "llgesturemgr.h" #include //#define DIFF_INVENTORY_FILES @@ -3032,23 +3033,47 @@ void LLInventoryModel::removeItem(const LLUUID& item_id) else { const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); - LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; - changeItemParent(item, new_parent, TRUE); + if (new_parent.notNull()) + { + LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; + changeItemParent(item, new_parent, TRUE); + } } } void LLInventoryModel::removeCategory(const LLUUID& category_id) { - LLViewerInventoryCategory* cat = getCategory(category_id); - if (! cat) + if (! get_is_category_removable(this, category_id)) { - LL_WARNS("Inventory") << "couldn't find inventory folder " << category_id << LL_ENDL; + return; } - else + + // Look for any gestures and deactivate them + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + collectDescendents(category_id, descendent_categories, descendent_items, FALSE); + + for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin(); + iter != descendent_items.end(); + ++iter) { - const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); - LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL; - changeCategoryParent(cat, new_parent, TRUE); + const LLViewerInventoryItem* item = (*iter); + const LLUUID& item_id = item->getUUID(); + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(item_id)) + { + LLGestureMgr::instance().deactivateGesture(item_id); + } + } + + LLViewerInventoryCategory* cat = getCategory(category_id); + if (cat) + { + const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id.notNull()) + { + changeCategoryParent(cat, trash_id, TRUE); + } } } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 1dc4d796ab..ef5ef2ddc8 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -640,7 +640,7 @@ void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const if (mSelectedOutfitUUID.notNull()) { - remove_category(&gInventory, mSelectedOutfitUUID); + gInventory.removeCategory(mSelectedOutfitUUID); } } -- cgit v1.3