From af2f61af502d483011a8f6722686a2c343bd0f7d Mon Sep 17 00:00:00 2001
From: Loren Shih <seraph@lindenlab.com>
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 <seraph@lindenlab.com>
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 <seraph@lindenlab.com>
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<LLInventoryCallback> 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<LLUUID> 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<LLPanelOutfitsInventory> 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<LLInventoryPanel>("cof_tab");
+	LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>(COF_TAB_NAME);
 	cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
-	mTabPanels[0] = cof_panel;
-	
-	LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>("outfitslist_tab");
+	mTabPanels.push_back(cof_panel);
+
+	LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>(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<LLFolderViewItem*> &items, BOOL user_action);
-	void 				onTabChange();
-	
+	void 					initTabPanels();
+	void 					onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+	void 					onTabChange();
+	BOOL 					isCOFPanelActive() const;
+
 private:
-	LLInventoryPanel* 	mActivePanel;
+	LLInventoryPanel* 		mActivePanel;
 	typedef std::vector<LLInventoryPanel *> 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" />
    </tab_container>
-- 
cgit v1.2.3