From af2f61af502d483011a8f6722686a2c343bd0f7d Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Thu, 21 Jan 2010 20:34:10 -0500 Subject: EXT-4492 Deleting gestures from the wearing tab causes the viewer to crash Removed "delete" from the COF menu, since it is normally disabled from the inventory view. --- indra/newview/llinventorybridge.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 099f863dc9..1c88658920 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -574,18 +574,35 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Paste As Link")); } } - items.push_back(std::string("Paste Separator")); + // Don't add a separator unless we have at least one entry beneath it, + // to avoid double separators. + BOOL separator_pasted = FALSE; if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) { + if (!separator_pasted) + { + items.push_back(std::string("Paste Separator")); + separator_pasted = TRUE; + } items.push_back(std::string("Remove Link")); } - items.push_back(std::string("Delete")); - if (!isItemRemovable()) + // Hide the delete button from the COF. Detaching/removing/etc. an item in the COF + // will naturally delete it. This prevents double delete crash possibilities. + if (!isCOFFolder()) { - disabled_items.push_back(std::string("Delete")); + if (!separator_pasted) + { + items.push_back(std::string("Paste Separator")); + separator_pasted = TRUE; + } + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } } // If multiple items are selected, disable properties (if it exists). -- cgit v1.2.3 From c64638dc2114a91b8efb17c1e37481ce34df84d5 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 22 Jan 2010 10:48:24 -0500 Subject: EXT-4492 Deleting gestures from the wearing tab causes the viewer to crash Revert removal of "delete" option from last checkin. Now enabling "delete" but checking if *this was deleted within removeItem(). --- indra/newview/llinventorybridge.cpp | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1c88658920..df089cb0f9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -575,34 +575,17 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } - // Don't add a separator unless we have at least one entry beneath it, - // to avoid double separators. - BOOL separator_pasted = FALSE; + items.push_back(std::string("Paste Separator")); if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) { - if (!separator_pasted) - { - items.push_back(std::string("Paste Separator")); - separator_pasted = TRUE; - } items.push_back(std::string("Remove Link")); } - // Hide the delete button from the COF. Detaching/removing/etc. an item in the COF - // will naturally delete it. This prevents double delete crash possibilities. - if (!isCOFFolder()) + items.push_back(std::string("Delete")); + if (!isItemRemovable()) { - if (!separator_pasted) - { - items.push_back(std::string("Paste Separator")); - separator_pasted = TRUE; - } - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } + disabled_items.push_back(std::string("Delete")); } // If multiple items are selected, disable properties (if it exists). @@ -3827,8 +3810,25 @@ void LLGestureBridge::openItem() BOOL LLGestureBridge::removeItem() { - // Force close the preview window, if it exists - LLGestureManager::instance().deactivateGesture(mUUID); + // Grab class information locally since *this may be deleted + // within this function. Not a great pattern... + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + const LLUUID item_id = mUUID; + + // This will also force close the preview window, if it exists. + // This may actually delete *this, if mUUID is in the COF. + LLGestureManager::instance().deactivateGesture(item_id); + + // If deactivateGesture deleted *this, then return out immediately. + if (!model->getObject(item_id)) + { + return TRUE; + } + return LLItemBridge::removeItem(); } -- cgit v1.2.3 From 0283837e56e69c8a6757d8366b82065e04ae966b Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 22 Jan 2010 14:44:32 -0500 Subject: EXT-4492 : Deleting gestures from the wearing tab causes the viewer to crash EXT-4660 : Can delete a bodypart from the COF through inventory view or WEARING tab delete key EXT-4662 : remove leading separator from COF right-click menu EXT-4633 : AppearanceSP trash button doesn't update enabled state correctly Bunch of UI fixes related to the trash/delete functionality in InventoryFloater/SP and AppearanceSP "WEARING" tab. The main idea is that we don't want to allow deletion of bodyparts and folder links from the COF by the user. --- indra/newview/llappearancemgr.cpp | 22 +++++++++++- indra/newview/llappearancemgr.h | 10 +++++- indra/newview/llinventorybridge.cpp | 19 +++++----- indra/newview/llinventorypanel.cpp | 8 +++++ indra/newview/llinventorypanel.h | 2 +- indra/newview/llpaneloutfitsinventory.cpp | 40 +++++++++++----------- indra/newview/llpaneloutfitsinventory.h | 24 +++++++------ .../default/xui/en/panel_outfits_inventory.xml | 2 +- 8 files changed, 83 insertions(+), 44 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 748d8bdfbf..0ff839849f 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -358,7 +358,7 @@ static void onWearableAssetFetch(LLWearable* wearable, void* data) } } -LLUUID LLAppearanceManager::getCOF() +const LLUUID LLAppearanceManager::getCOF() const { return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); } @@ -1263,3 +1263,23 @@ void LLAppearanceManager::linkRegisteredAttachments() } mRegisteredAttachments.clear(); } + +BOOL LLAppearanceManager::getIsInCOF(const LLUUID& obj_id) const +{ + return gInventory.isObjectDescendentOf(obj_id, getCOF()); +} + +BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const +{ + if (!getIsInCOF(obj_id)) return FALSE; + const LLInventoryObject *obj = gInventory.getObject(obj_id); + if (!obj) return FALSE; + + // Can't delete bodyparts, since this would be equivalent to removing the item. + if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE; + + // Can't delete the folder link, since this is saved for bookkeeping. + if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE; + + return FALSE; +} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 20745b70e4..0093d30817 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -59,7 +59,7 @@ public: LLPointer cb); // Find the Current Outfit folder. - LLUUID getCOF(); + const LLUUID getCOF() const; // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); @@ -132,6 +132,14 @@ private: std::set mRegisteredAttachments; bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; + + ////////////////////////////////////////////////////////////////////////////////// + // Item-specific convenience functions +public: + // Is this in the COF? + BOOL getIsInCOF(const LLUUID& obj_id) const; + // Is this in the COF and can the user delete it from the COF? + BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; }; #define SUPPORT_ENSEMBLES 0 diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index df089cb0f9..a7ce111b18 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -185,6 +185,11 @@ BOOL LLInvFVBridge::isItemRemovable() { return FALSE; } + if (LLAppearanceManager::instance().getIsProtectedCOFItem(mUUID)) + { + return FALSE; + } + const LLInventoryObject *obj = model->getItem(mUUID); if (obj && obj->getIsLinkType()) { @@ -712,14 +717,7 @@ BOOL LLInvFVBridge::isAgentInventory() const BOOL LLInvFVBridge::isCOFFolder() const { - const LLInventoryModel* model = getInventoryModel(); - if(!model) return TRUE; - const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) - { - return TRUE; - } - return FALSE; + return LLAppearanceManager::instance().getIsInCOF(mUUID); } BOOL LLInvFVBridge::isItemPermissive() const @@ -4622,7 +4620,10 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); - items.push_back(std::string("Wearable Separator")); + if (!is_sidepanel) + { + items.push_back(std::string("Wearable Separator")); + } items.push_back(std::string("Wearable Edit")); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 9141d50829..7e71ac90b4 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -682,6 +682,14 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc mFolders->setSelectionByID(obj_id, take_keyboard_focus); } +void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) +{ + if (mFolders) + { + mFolders->setSelectCallback(cb); + } +} + void LLInventoryPanel::clearSelection() { mFolders->clearSelection(); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 09533b52f1..ccff795a51 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -123,7 +123,7 @@ public: // Call this method to set the selection. void openAllFolders(); void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); - void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); } + void setSelectCallback(const LLFolderView::signal_t::slot_type& cb); void clearSelection(); LLInventoryFilter* getFilter(); void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index fd5ce7a46d..cf903958ee 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -61,6 +61,9 @@ #include "llviewercontrol.h" +static const std::string OUTFITS_TAB_NAME = "outfitslist_tab"; +static const std::string COF_TAB_NAME = "cof_tab"; + static LLRegisterPanelClassWrapper t_inventory("panel_outfits_inventory"); bool LLPanelOutfitsInventory::sShowDebugEditor = false; @@ -267,7 +270,7 @@ void LLPanelOutfitsInventory::onSaveCommit(const std::string& outfit_name) if (mAppearanceTabs) { - mAppearanceTabs->selectTabByName("outfitslist_tab"); + mAppearanceTabs->selectTabByName(OUTFITS_TAB_NAME); } } @@ -503,8 +506,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) if (command_name == "wear") { - const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab"); - if (!is_my_outfits) + if (isCOFPanelActive()) { return FALSE; } @@ -558,17 +560,15 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy void LLPanelOutfitsInventory::initTabPanels() { - mTabPanels.resize(2); - - LLInventoryPanel *cof_panel = getChild("cof_tab"); + LLInventoryPanel *cof_panel = getChild(COF_TAB_NAME); cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mTabPanels[0] = cof_panel; - - LLInventoryPanel *myoutfits_panel = getChild("outfitslist_tab"); + mTabPanels.push_back(cof_panel); + + LLInventoryPanel *myoutfits_panel = getChild(OUTFITS_TAB_NAME); myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY); myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mTabPanels[1] = myoutfits_panel; - + mTabPanels.push_back(myoutfits_panel); + for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); iter != mTabPanels.end(); ++iter) @@ -615,19 +615,19 @@ void LLPanelOutfitsInventory::onTabChange() updateVerbs(); } -LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel() -{ - return mActivePanel; -} - -bool LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) +BOOL LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) const { - for(tabpanels_vec_t::iterator it = mTabPanels.begin(); + for(tabpanels_vec_t::const_iterator it = mTabPanels.begin(); it != mTabPanels.end(); ++it) { if (*it == panel) - return true; + return TRUE; } - return false; + return FALSE; +} + +BOOL LLPanelOutfitsInventory::isCOFPanelActive() const +{ + return (getActivePanel()->getName() == COF_TAB_NAME); } diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 76110e2a3f..ab25ef0a49 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -78,24 +78,26 @@ protected: bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const; private: - LLSidepanelAppearance* mParent; - LLSaveFolderState* mSavedFolderState; - LLTabContainer* mAppearanceTabs; - std::string mFilterSubString; + LLSidepanelAppearance* mParent; + LLSaveFolderState* mSavedFolderState; + LLTabContainer* mAppearanceTabs; + std::string mFilterSubString; public: ////////////////////////////////////////////////////////////////////////////////// // tab panels - LLInventoryPanel* getActivePanel(); - bool isTabPanel(LLInventoryPanel *panel); + LLInventoryPanel* getActivePanel() { return mActivePanel; } + const LLInventoryPanel* getActivePanel() const { return mActivePanel; } + BOOL isTabPanel(LLInventoryPanel *panel) const; protected: - void initTabPanels(); - void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque &items, BOOL user_action); - void onTabChange(); - + void initTabPanels(); + void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque &items, BOOL user_action); + void onTabChange(); + BOOL isCOFPanelActive() const; + private: - LLInventoryPanel* mActivePanel; + LLInventoryPanel* mActivePanel; typedef std::vector tabpanels_vec_t; tabpanels_vec_t mTabPanels; diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 8895484326..710ca733e0 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -45,7 +45,7 @@ left="0" top="0" mouse_opaque="true" - name="cof_accordionpanel" + name="cof_tab" start_folder="Current Outfit" width="313" /> -- cgit v1.2.3