From cdb6f67f7199bbd82fe85ccfd5c9812226eb12ba Mon Sep 17 00:00:00 2001
From: "Nyx (Neal Orman)" <nyx@lindenlab.com>
Date: Fri, 8 Jan 2010 13:10:15 -0500
Subject: EXT-3958 title needs to update appropriately when changes made to
 outfit

We now show a string "(unsaved)" under the appearance panel outfit title
when the currently loaded outfit has been modified from its original state.

Tested with following conditions:
1) item added to loaded outfit
2) item removed from loaded outfit
3) item replaced in loaded outfit

Appears to work properly on login as well. Checking is a manual folder compare,
but should be fairly efficient.

XUI changes submitted by Erica

Entire diff reviewed by Vir
---
 indra/newview/llagentwearables.cpp                 |  2 +
 indra/newview/llappearancemgr.cpp                  | 78 +++++++++++++++++++++-
 indra/newview/llappearancemgr.h                    | 11 +++
 indra/newview/llsidepanelappearance.cpp            |  3 +
 indra/newview/llsidepanelappearance.h              |  1 +
 .../default/xui/en/panel_outfits_inventory.xml     |  2 +-
 .../skins/default/xui/en/sidepanel_appearance.xml  | 25 ++++---
 7 files changed, 107 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 29530c9c05..f49f862045 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -2274,6 +2274,8 @@ void LLInitialWearablesFetch::processContents()
 	}
 	else
 	{
+		// if we're constructing the COF from the wearables message, we don't have a proper outfit link
+		LLAppearanceManager::instance().setOutfitDirty(true);
 		processWearablesMessage();
 	}
 	delete this;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 1150d84feb..4d4a89bcd4 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -674,6 +674,10 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
 
 void LLAppearanceManager::updateAppearanceFromCOF()
 {
+	// update dirty flag to see if the state of the COF matches
+	// the saved outfit stored as a folder link
+	updateIsDirty();
+
 	dumpCat(getCOF(),"COF, start");
 
 	bool follow_folder_links = true;
@@ -1005,7 +1009,9 @@ void LLAppearanceManager::addCOFItemLink(const LLInventoryItem *item, bool do_up
 	if (linked_already)
 	{
 		if (do_update)
+		{	
 			LLAppearanceManager::updateAppearanceFromCOF();
+		}
 		return;
 	}
 	else
@@ -1059,6 +1065,75 @@ void LLAppearanceManager::removeCOFItemLinks(const LLUUID& item_id, bool do_upda
 	}
 }
 
+void LLAppearanceManager::updateIsDirty()
+{
+	LLUUID cof = getCOF();
+	LLUUID base_outfit;
+
+	// find base outfit link 
+	const LLViewerInventoryItem* base_outfit_item = getBaseOutfitLink();
+	LLViewerInventoryCategory* catp = NULL;
+	if (base_outfit_item && base_outfit_item->getIsLinkType())
+	{
+		catp = base_outfit_item->getLinkedCategory();
+	}
+	if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+	{
+		base_outfit = catp->getUUID();
+	}
+
+	if(base_outfit.isNull())
+	{
+		// no outfit link found, display "unsaved outfit"
+		mOutfitIsDirty = true;
+	}
+	else
+	{
+		LLInventoryModel::cat_array_t cof_cats;
+		LLInventoryModel::item_array_t cof_items;
+		gInventory.collectDescendents(cof, cof_cats, cof_items,
+									  LLInventoryModel::EXCLUDE_TRASH);
+
+		LLInventoryModel::cat_array_t outfit_cats;
+		LLInventoryModel::item_array_t outfit_items;
+		gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items,
+									  LLInventoryModel::EXCLUDE_TRASH);
+
+		if(outfit_items.count() != cof_items.count() -1)
+		{
+			// Current outfit folder should have one more item than the outfit folder.
+			// this one item is the link back to the outfit folder itself.
+			mOutfitIsDirty = true;
+		}
+		else
+		{
+			typedef std::set<LLUUID> item_set_t;
+			item_set_t cof_set;
+			item_set_t outfit_set;
+
+			// sort COF items by UUID
+			for (S32 i = 0; i < cof_items.count(); ++i)
+			{
+				LLViewerInventoryItem *item = cof_items.get(i);
+				// don't add the base outfit link to the list of objects we're comparing
+				if(item != base_outfit_item)
+				{
+					cof_set.insert(item->getLinkedUUID());
+				}
+			}
+
+			// sort outfit folder by UUID
+			for (S32 i = 0; i < outfit_items.count(); ++i)
+			{
+				LLViewerInventoryItem *item = outfit_items.get(i);
+				outfit_set.insert(item->getLinkedUUID());
+			}
+
+			mOutfitIsDirty = (outfit_set != cof_set);
+		}
+	}
+}
+
 //#define DUMP_CAT_VERBOSE
 
 void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg)
@@ -1095,7 +1170,8 @@ void LLAppearanceManager::dumpItemArray(const LLInventoryModel::item_array_t& it
 }
 
 LLAppearanceManager::LLAppearanceManager():
-	mAttachmentInvLinkEnabled(false)
+	mAttachmentInvLinkEnabled(false),
+	mOutfitIsDirty(false)
 {
 }
 
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 11b910ee11..b954968998 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -96,6 +96,16 @@ public:
 	// Add COF link to ensemble folder.
 	void addEnsembleLink(LLInventoryCategory* item, bool do_update = true);
 
+	//has the current outfit changed since it was loaded?
+	bool isOutfitDirty() { return mOutfitIsDirty; }
+
+	// set false if you just loaded the outfit, true otherwise
+	void setOutfitDirty(bool isDirty) { mOutfitIsDirty = isDirty; }
+	
+	// manually compare ouftit folder link to COF to see if outfit has changed.
+	// should only be necessary to do on initial login.
+	void updateIsDirty();
+
 protected:
 	LLAppearanceManager();
 	~LLAppearanceManager();
@@ -120,6 +130,7 @@ private:
 
 	std::set<LLUUID> mRegisteredAttachments;
 	bool mAttachmentInvLinkEnabled;
+	bool mOutfitIsDirty;
 };
 
 #define SUPPORT_ENSEMBLES 0
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 0aefebce10..0a1f7ad0da 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -151,6 +151,8 @@ BOOL LLSidepanelAppearance::postBuild()
 	}
 
 	mCurrentLookName = getChild<LLTextBox>("currentlook_name");
+
+	mOutfitDirtyTag = getChild<LLTextBox>("currentlook_title");
 	
 	mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook");
 
@@ -316,6 +318,7 @@ void LLSidepanelAppearance::updateVerbs()
 
 void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
 {
+	mOutfitDirtyTag->setVisible(LLAppearanceManager::getInstance()->isOutfitDirty());
 	if (name == "")
 	{
 		const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getBaseOutfitLink();
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 8ef2088eda..9524b0ece9 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -86,6 +86,7 @@ private:
 	LLPanel*					mCurrOutfitPanel;
 
 	LLTextBox*					mCurrentLookName;
+	LLTextBox*					mOutfitDirtyTag;
 
 	// Used to make sure the user's inventory is in memory.
 	LLCurrentlyWornFetchObserver* mFetchWorn;
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 7e512f9594..27ab98177c 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -93,7 +93,7 @@
      <button
       follows="bottom|left"
       height="23" 
-      label="Make Outfit" 
+      label="Save Outfit" 
       layout="topleft"
       name="make_outfit_btn"
       tool_tip="Save appearance as an outfit"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index 44248eedd5..fab1f11273 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -52,25 +52,25 @@ width="333">
       text_color="white"
       top="3"
       use_ellipses="true"
-      width="290"
+      width="305"
       follows="top|left"
       word_wrap="true"
       mouse_opaque="false"
       name="currentlook_name">
       MyOutfit With a really Long Name like MOOSE
       </text>
-      <!-- <text
-      text_color="LtGray_50"
-      width="290"
-      left="40"
+      <text
+      font="SansSerifSmall"
+      text_color="White_50"
+      width="300"
       height="1"
       follows="top|left"
       layout="topleft"
-      top_pad="-2"
+      top_pad="5"
       mouse_opaque="false"
       name="currentlook_title" >
-      (current outfit)
-      </text>-->
+      (unsaved)
+       </text>
    </panel>
    <filter_editor
    height="23"
@@ -80,18 +80,18 @@ width="333">
    label="Filter Outfits"
    max_length="300"
    name="Filter"
-   top_pad="0"
+   top_pad="10"
    width="303" />
    <panel
    class="panel_outfits_inventory"
    filename="panel_outfits_inventory.xml"
    name="panel_outfits_inventory"
-   height="515"
+   height="505"
    min_height="410"
    width="320"
+   left="0"
    top_pad="0"
-   follows="all"
-   />
+   follows="all" />
   <!--   <button
 	  follows="bottom|left"
 		height="23"
@@ -120,4 +120,3 @@ width="333">
    top="35"
    visible="false" />
 </panel>
-
-- 
cgit v1.2.3


From 3e23a2cffc8857d7041cb6bb5edf83462e4c2f1a Mon Sep 17 00:00:00 2001
From: Lynx Linden <lynx@lindenlab.com>
Date: Fri, 8 Jan 2010 18:10:24 +0000
Subject: EXT-2647: Removed the help browser's "Open in My Web Browser" button.

Also increased the default height of the help browser a little bit as
it looked a little too squat.
---
 .../skins/default/xui/en/floater_help_browser.xml  | 32 ++++------------------
 1 file changed, 6 insertions(+), 26 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 55a6179afb..446b7138c4 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -2,7 +2,7 @@
 <floater
  legacy_header_height="18"
  can_resize="true"
- height="400"
+ height="480"
  layout="topleft"
  min_height="140"
  min_width="467"
@@ -21,7 +21,7 @@
         http://support.secondlife.com
     </floater.string>
     <layout_stack
-     bottom="400"
+     bottom="480"
      follows="left|right|top|bottom"
      layout="topleft"
      left="10"
@@ -29,42 +29,22 @@
      top="20"
      width="600">
         <layout_panel
-         height="20"
+         height="1"
          layout="topleft"
          left_delta="0"
          name="external_controls"
          top_delta="0"
          user_resize="false"
-         width="570">
+         width="590">
             <web_browser
-             bottom="-10"
+             bottom="-4"
              follows="left|right|top|bottom"
              layout="topleft"
              left="0"
              name="browser"
              top="0"
              start_url="data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#2A2A2A%22%3E%3C/body%3E%3C/html%3E"
-             width="570" />
-            <button
-             follows="bottom|left"
-             height="20"
-             label="Open in My Web Browser"
-             layout="topleft"
-             left_delta="0"
-             name="open_browser"
-             top_pad="5"
-             width="185" />
-<!--
-            <button
-             follows="bottom|right"
-             height="20"
-             label="Close"
-             layout="topleft"
-             left_pad="290"
-             name="close"
-             top_delta="0"
-             width="70" />
--->
+             width="590" />
         </layout_panel>
     </layout_stack>
 </floater>
-- 
cgit v1.2.3