From b897b9427fa409a173818db8f9621622278c66b1 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Wed, 14 Nov 2012 16:48:03 -0500 Subject: [PATCH 1/4] Fix unclickable explanatory link on Outbox floater mOutboxInventoryPanel couldn't be setVisible(false) while it was NULL, thus it sat on top of the rest of the UI. Set it to panel_outbox_inventory in postBuild, instead of setupOutbox. --- indra/newview/llfloateroutbox.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 67e6b45c9..33208767f 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -149,6 +149,12 @@ BOOL LLFloaterOutbox::postBuild() mImportButton = getChild("outbox_import_btn"); mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this)); + // + // Set up the outbox inventory view + // + + mOutboxInventoryPanel = getChild("panel_outbox_inventory"); + mOutboxTopLevelDropZone = getChild("outbox_generic_drag_target"); LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); @@ -239,12 +245,6 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); - // - // Set up the outbox inventory view - // - - mOutboxInventoryPanel = getChild("panel_outbox_inventory"); - llassert(mOutboxInventoryPanel); // Reshape the inventory to the proper size From 2bd5d88dbfcf56d55f6a36b45798f0f0b226568c Mon Sep 17 00:00:00 2001 From: Scott Meitz Date: Sun, 14 Oct 2012 21:11:01 -0400 Subject: [PATCH 2/4] fix extra space in strings.xml en. Tooltip was not find them --- indra/newview/skins/default/xui/en-us/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index b349447a7..89aabcb73 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -2676,7 +2676,7 @@ aaSayTo(key userID, string text) Where userID = avatar key, text = string msg. Similar to llOwnerSay but can be directly targeted to an avatar. (Aurora-Sim only) - + aaGetWalkDisabled(key ID) Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid. (Aurora-Sim only) @@ -2686,7 +2686,7 @@ aaSetWalkDisabled(key ID, integer Value) Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables walk, forcing avatar to fly. (Aurora-Sim only) - + aaGetFlyDisabled(key ID) Returns integer of TRUE or FALSE for specifid ID. Where ID = avatar uuid. (Aurora-Sim only) @@ -2696,7 +2696,7 @@ aaSetFlyDisabled(key ID, integer Value) Where ID = avatar uuid, Value = TRUE or FALSE. If PERMISSION_COMBAT is accepted, this disables flying, forcing avatar to walk. (Aurora-Sim only) - + aaAvatarFullName2Key(string FullName) Returns the avatar uuid from their fullname. Where FullName = "Firstname Lastnameā€. (Aurora-Sim only) @@ -2706,17 +2706,17 @@ aaRaiseError(string message) Allows you to have errors that end the execution of the event and fire another event in the script. (Aurora-Sim only) - + aaGetText() Returns a string of the hover text of an object. (Aurora-Sim only) - + aaGetTextColor() Returns the hovertext color in rotation. Use Ex: rotation color = aaGetTextColor() to separate color.x, color.y, color.z, color.s Where s = value of alpha in llSetText. (Aurora-Sim only) - + aaSetEnv(string EnvName, list Value) Sets environment values. Where EnvName = ENABLE_GRAVITY, GRAVITY_FORCE_X, GRAVITY_FORCE_Y, GRAVITY_FORCE_Z, ADD_GRAVITY_POINT, ADD_GRAVITY_FORCE, START_TIME_REVERSAL_SAVING, STOP_TIME_REVERSAL_SAVING, START_TIME_REVERSAL, STOP_TIME_REVERSAL. From 760ac98ab6c3609cc29776715d823881a3f13aeb Mon Sep 17 00:00:00 2001 From: Scott Meitz Date: Mon, 15 Oct 2012 21:28:19 -0400 Subject: [PATCH 3/4] missed another spot with trailing spaces in aa functions, TNX LightDrake and Shyot1 :) --- indra/lscript/lscript_library/lscript_library.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 4599aa135..4837b4f6b 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -703,15 +703,15 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "aaGetLastOwner", "s", NULL); addFunction(10.f, 0.f, dummy_func, "aaSayDistance", NULL, "ifs"); addFunction(10.f, 0.f, dummy_func, "aaSayTo", NULL, "ss"); - addFunction(10.f, 0.f, dummy_func, "aaGetWalkDisabled ", "i", "s"); + addFunction(10.f, 0.f, dummy_func, "aaGetWalkDisabled", "i", "s"); addFunction(10.f, 0.f, dummy_func, "aaSetWalkDisabled", NULL, "si"); - addFunction(10.f, 0.f, dummy_func, "aaGetFlyDisabled ", "i", "s"); + addFunction(10.f, 0.f, dummy_func, "aaGetFlyDisabled", "i", "s"); addFunction(10.f, 0.f, dummy_func, "aaSetFlyDisabled", NULL, "sf"); - addFunction(10.f, 0.f, dummy_func, "aaAvatarFullName2Key ", "s", "s"); + addFunction(10.f, 0.f, dummy_func, "aaAvatarFullName2Key", "s", "s"); addFunction(10.f, 0.f, dummy_func, "aaRaiseError", NULL, "s"); - addFunction(10.f, 0.f, dummy_func, "aaGetText ", "s", NULL); - addFunction(10.f, 0.f, dummy_func, "aaGetTextColor ", "r", NULL); - addFunction(10.f, 0.f, dummy_func, "aaSetEnv ", NULL, "sl"); + addFunction(10.f, 0.f, dummy_func, "aaGetText", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "aaGetTextColor", "r", NULL); + addFunction(10.f, 0.f, dummy_func, "aaSetEnv", NULL, "sl"); addFunction(10.f, 0.f, dummy_func, "aaGetIsInfiniteRegion", "i", NULL); // botFunctions Aurora-Sim ONLY addFunction(10.f, 0.f, dummy_func, "botGetWaitingTime", "v", "i"); From 7b2536eb0dac59fead55536b26ca3b4b6a028b98 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Fri, 16 Nov 2012 02:47:05 -0500 Subject: [PATCH 4/4] Inventory cut support! Also fixes a bunch of comments, implementation based off of v-d. Added isOnClipboard and setCutMode functions to LLInventoryClipboard, in part from v-d's LLClipboard. LLInventoryFilter has a few rearrangements of code; only real change is now it has checkAgainstClipboard and uses it to filter out cut items. There is a massive retabbed block in llinventorymodel.cpp, view without space changes. Implements removeObject. Note: We are not afflicted by MAINT-1197: Fix inventory deselection/reselection when cutting items --- indra/newview/llfolderview.cpp | 25 +++- indra/newview/llfolderview.h | 7 +- indra/newview/llinventoryactions.cpp | 2 +- indra/newview/llinventorybridge.cpp | 32 +++- indra/newview/llinventoryclipboard.cpp | 6 + indra/newview/llinventoryclipboard.h | 4 + indra/newview/llinventoryfilter.cpp | 67 +++++++-- indra/newview/llinventoryfilter.h | 9 +- indra/newview/llinventorymodel.cpp | 138 +++++++++++++----- .../default/xui/en-us/menu_inventory.xml | 4 + 10 files changed, 230 insertions(+), 64 deletions(-) diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1fc54068c..82e12f525 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -429,7 +429,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -// This view grows and shinks to enclose all of its children items and folders. +// This view grows and shrinks to enclose all of its children items and folders. S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { if(!mScrollContainer) @@ -1049,6 +1049,24 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector exit + if (!LLInventoryClipboard::instance().isCutMode()) + return; + + // Get the list of clipboard item uuids and iterate through them + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + for (LLDynamicArray::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + gInventory.removeObject(*iter); + } +} + void LLFolderView::removeSelectedItems( void ) { if(getVisible() && getEnabled()) @@ -1385,6 +1403,7 @@ void LLFolderView::cut() listener->cutToClipboard(); } } + LLFolderView::removeCutItems(); } mSearchString.clear(); } @@ -2015,7 +2034,7 @@ void LLFolderView::scrollToShowSelection() } } -// If the parent is scroll containter, scroll it to make the selection +// If the parent is scroll container, scroll it to make the selection // is maximally visible. void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) { @@ -2165,7 +2184,7 @@ void LLFolderView::doIdle() mNeedsAutoSelect = filter_modified_and_active && !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - // filter to determine visiblity before arranging + // filter to determine visibility before arranging filterFromRoot(); // automatically show matching items, and select first one diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 8563b98a4..0d36bfe3b 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -67,8 +67,8 @@ class LLTextBox; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderView // -// Th LLFolderView represents the root level folder view object. It -// manages the screen region of the folder view. +// The LLFolderView represents the root level folder view object. +// It manages the screen region of the folder view. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler @@ -160,6 +160,7 @@ public: // Deletion functionality void removeSelectedItems(); + static void removeCutItems(); // Open the selected item void openSelectedItems( void ); @@ -320,7 +321,7 @@ protected: /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. - * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel. + * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. */ bool mUseEllipses; // See EXT-719 diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index c01dae99d..372b9bf83 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -124,7 +124,7 @@ bool doToSelected(LLFolderView* folder, std::string action) return true; } - if ("copy" == action) + if ("copy" == action || "cut" == action) { LLInventoryClipboard::instance().reset(); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ffd9a7eaf..8efcc693d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -319,7 +319,6 @@ BOOL LLInvFVBridge::isLink() const /** * @brief Adds this item into clipboard storage */ -//Unused. void LLInvFVBridge::cutToClipboard() { if(isItemMovable()) @@ -568,6 +567,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray(mInventoryPanel.get()); LLDynamicArray objects; LLInventoryClipboard::instance().retrieve(objects); @@ -772,6 +779,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } + items.push_back(std::string("Cut")); + if (!isItemMovable() || !isItemRemovable()) + { + disabled_items.push_back(std::string("Cut")); + } + if (canListOnMarketplace()) { items.push_back(std::string("Marketplace Separator")); @@ -1434,6 +1447,12 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer)); return; } + else if ("cut" == action) + { + cutToClipboard(); + LLFolderView::removeCutItems(); + return; + } else if ("copy" == action) { copyToClipboard(); @@ -1441,7 +1460,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) } else if ("paste" == action) { - // Single item only LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; @@ -2826,6 +2844,12 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) modifyOutfit(TRUE); return; } + else if ("cut" == action) + { + cutToClipboard(); + LLFolderView::removeCutItems(); + return; + } else if ("copy" == action) { copyToClipboard(); @@ -3099,6 +3123,7 @@ void LLFolderBridge::pasteFromClipboard() ++iter) { const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); LLInventoryObject *obj = model->getObject(item_id); if (obj) @@ -3158,6 +3183,8 @@ void LLFolderBridge::pasteFromClipboard() } } } + // Change mode to copy for next paste + LLInventoryClipboard::instance().setCutMode(false); } } @@ -3220,6 +3247,7 @@ void LLFolderBridge::pasteLinkFromClipboard() LLPointer(NULL)); } } + //Singu Note: Don't setCutMode(false) here, we can link now but real paste later. } } diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp index 53da34f44..50a9d2a92 100644 --- a/indra/newview/llinventoryclipboard.cpp +++ b/indra/newview/llinventoryclipboard.cpp @@ -104,6 +104,12 @@ BOOL LLInventoryClipboard::hasContents() const return (mObjects.count() > 0); } +// returns true if the input uuid is in the list of clipboard objects. +bool LLInventoryClipboard::isOnClipboard(const LLUUID& object) const +{ + std::vector::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); + return (iter != mObjects.end()); +} ///---------------------------------------------------------------------------- /// Local function definitions diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h index b9f1451e5..398ac5c11 100644 --- a/indra/newview/llinventoryclipboard.h +++ b/indra/newview/llinventoryclipboard.h @@ -64,7 +64,11 @@ public: // returns true if the clipboard has something pasteable in it. BOOL hasContents() const; + // returns true if the input object uuid is on the clipboard + bool isOnClipboard(const LLUUID& object) const; + bool isCutMode() const { return mCutMode; } + void setCutMode(bool mode) { mCutMode = mode; } protected: static LLInventoryClipboard sInstance; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 429b68ac0..ceabe493a 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -39,6 +39,7 @@ #include "llviewerfoldertype.h" #include "llagentwearables.h" #include "llvoavatarself.h" +#include "llinventoryclipboard.h" // linden library includes #include "lltrans.h" @@ -88,18 +89,20 @@ LLInventoryFilter::~LLInventoryFilter() { } -BOOL LLInventoryFilter::check(LLFolderViewItem* item) +BOOL LLInventoryFilter::check(LLFolderViewItem* item) { - // If it's a folder and we're showing all folders, return TRUE automatically. + // Clipboard cut items are *always* filtered so we need this value upfront + const LLFolderViewEventListener* listener = item->getListener(); + const LLUUID item_id = listener ? listener->getUUID() : LLUUID::null; + const bool passed_clipboard = item_id.notNull() ? checkAgainstClipboard(item_id) : true; + + // If it's a folder and we're showing all folders, return automatically. const BOOL is_folder = (dynamic_cast(item) != NULL); if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - return TRUE; + return passed_clipboard; } - const LLFolderViewEventListener* listener = item->getListener(); - const LLUUID item_id = listener ? listener->getUUID() : LLUUID::null; - mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; const BOOL passed_filtertype = checkAgainstFilterType(item); @@ -109,23 +112,41 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item) const BOOL passed = (passed_filtertype && passed_permissions && passed_filterlink && + passed_clipboard && passed_wearable && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); return passed; } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) +bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const { - // we're showing all folders, overriding filter - if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + if (!folder) { - return true; + llwarns << "The filter can not be checked on an invalid folder." << llendl; + llassert(false); // crash in development builds + return false; } const LLFolderViewEventListener* listener = folder->getListener(); + if (!listener) + { + llwarns << "Folder view event listener not found." << llendl; + llassert(false); // crash in development builds + return false; + } + const LLUUID folder_id = listener->getUUID(); + // Always check against the clipboard + const BOOL passed_clipboard = checkAgainstClipboard(folder_id); + + // we're showing all folders, overriding filter + if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) + { + return passed_clipboard; + } + if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) { // Can only filter categories for items in your inventory @@ -138,7 +159,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) return false; } - return true; + return passed_clipboard; } BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const @@ -234,6 +255,30 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con return TRUE; } +// Items and folders that are on the clipboard or, recursively, in a folder which +// is on the clipboard must be filtered out if the clipboard is in the "cut" mode. +bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const +{ + if (LLInventoryClipboard::instance().isCutMode()) + { + LLUUID current_id = object_id; + LLInventoryObject *current_object = gInventory.getObject(object_id); + while (current_id.notNull() && current_object) + { + if (LLInventoryClipboard::instance().isOnClipboard(current_id)) + { + return false; + } + current_id = current_object->getParentUUID(); + if (current_id.notNull()) + { + current_object = gInventory.getObject(current_id); + } + } + } + return true; +} + BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index b999843b5..588844c01 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -118,10 +118,11 @@ public: // + Execution And Results // +-------------------------------------------------------------------+ BOOL check(LLFolderViewItem* item); - bool checkFolder(const LLFolderViewFolder* folder); + bool checkFolder(const LLFolderViewFolder* folder) const; BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const; + bool checkAgainstClipboard(const LLUUID& object_id) const; std::string::size_type getStringMatchOffset() const; @@ -171,9 +172,9 @@ public: S32 getMinRequiredGeneration() const; S32 getMustPassGeneration() const; - - - + // +-------------------------------------------------------------------+ + // + Conversion + // +-------------------------------------------------------------------+ void toLLSD(LLSD& data) const; void fromLLSD(LLSD& data); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0b369df09..cacdc559a 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 "llinventoryclipboard.h" #include "llinventorypanel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -1249,47 +1250,80 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) LLPointer cat = getCategory(id); if(cat.notNull()) { - // do the cache accounting - llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; - S32 descendents = cat->getDescendentCount(); - if(descendents > 0) + if (LLInventoryClipboard::instance().hasContents() && LLInventoryClipboard::instance().isCutMode()) { - LLCategoryUpdate up(id, -descendents); - accountForUpdate(up); + // 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 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 (!LLInventoryClipboard::instance().isOnClipboard(*it)) + { + purgeObject(*it); + } + } } - - // 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); - - // 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(); - for(S32 i = 0; i < count; ++i) + else { - deleteObject(items.get(i)->getUUID()); - } - count = categories.count(); - for(S32 i = 0; i < count; ++i) - { - deleteObject(categories.get(i)->getUUID()); + // 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(); + 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()); + } } } } @@ -2908,7 +2942,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer tfolder = new LLViewerInventoryCategory(gAgent.getID()); tfolder->unpackMessage(msg, _PREHASH_FolderData, i); - //llinfos << "unpaked folder '" << tfolder->getName() << "' (" + //llinfos << "unpacked folder '" << tfolder->getName() << "' (" // << tfolder->getUUID() << ") in " << tfolder->getParentUUID() // << llendl; if(tfolder->getUUID().notNull()) @@ -2964,7 +2998,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) { LLPointer titem = new LLViewerInventoryItem; titem->unpackMessage(msg, _PREHASH_ItemData, i); - //llinfos << "unpaked item '" << titem->getName() << "' in " + //llinfos << "unpacked item '" << titem->getName() << "' in " // << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); @@ -3261,6 +3295,30 @@ void LLInventoryModel::removeCategory(const LLUUID& category_id) } } } + +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/skins/default/xui/en-us/menu_inventory.xml b/indra/newview/skins/default/xui/en-us/menu_inventory.xml index ab1976d66..012524098 100644 --- a/indra/newview/skins/default/xui/en-us/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en-us/menu_inventory.xml @@ -186,6 +186,10 @@ + + +