From 683a96a5f1e9111d62710fe621d52192d34079ed Mon Sep 17 00:00:00 2001
From: Todd Stinson <stinson@lindenlab.com>
Date: Tue, 14 Aug 2012 14:54:29 -0700
Subject: PATH-849: Refactoring the behavior after loading the owner name of a
 pathfinding object into the avatar name cache so that each object can simply
 update its respective row in the scroll list rather than rebuilding from
 scratch after all names are loaded.

---
 indra/newview/llfloaterpathfindingcharacters.cpp |  28 ++---
 indra/newview/llfloaterpathfindingcharacters.h   |   4 +-
 indra/newview/llfloaterpathfindinglinksets.cpp   |  42 +++-----
 indra/newview/llfloaterpathfindinglinksets.h     |   4 +-
 indra/newview/llfloaterpathfindingobjects.cpp    | 124 ++++++++++++-----------
 indra/newview/llfloaterpathfindingobjects.h      |  16 +--
 indra/newview/llpathfindingobject.cpp            |  30 +++++-
 indra/newview/llpathfindingobject.h              |   9 ++
 8 files changed, 141 insertions(+), 116 deletions(-)

diff --git a/indra/newview/llfloaterpathfindingcharacters.cpp b/indra/newview/llfloaterpathfindingcharacters.cpp
index 99d262344c..4cf82d162c 100644
--- a/indra/newview/llfloaterpathfindingcharacters.cpp
+++ b/indra/newview/llfloaterpathfindingcharacters.cpp
@@ -134,26 +134,20 @@ void LLFloaterPathfindingCharacters::requestGetObjects()
 	LLPathfindingManager::getInstance()->requestGetCharacters(getNewRequestId(), boost::bind(&LLFloaterPathfindingCharacters::handleNewObjectList, this, _1, _2, _3));
 }
 
-LLSD LLFloaterPathfindingCharacters::convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr)
+void LLFloaterPathfindingCharacters::buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr)
 {
 	llassert(pObjectListPtr != NULL);
 	llassert(!pObjectListPtr->isEmpty());
 
-	LLSD scrollListData = LLSD::emptyArray();
-
 	for (LLPathfindingObjectList::const_iterator objectIter = pObjectListPtr->begin();	objectIter != pObjectListPtr->end(); ++objectIter)
 	{
-		const LLPathfindingCharacter *characterPtr = dynamic_cast<const LLPathfindingCharacter *>(objectIter->second.get());
-		LLSD element = buildCharacterScrollListData(characterPtr);
-		scrollListData.append(element);
+		const LLPathfindingObjectPtr objectPtr = objectIter->second;
+		const LLPathfindingCharacter *characterPtr = dynamic_cast<const LLPathfindingCharacter *>(objectPtr.get());
+		llassert(characterPtr != NULL);
 
-		if (characterPtr->hasOwner() && !characterPtr->hasOwnerName())
-		{
-			rebuildScrollListAfterAvatarNameLoads(characterPtr->getUUID());
-		}
+		LLSD scrollListItemData = buildCharacterScrollListItemData(characterPtr);
+		addObjectToScrollList(objectPtr, scrollListItemData);
 	}
-
-	return scrollListData;
 }
 
 void LLFloaterPathfindingCharacters::updateControlsOnScrollListChange()
@@ -201,9 +195,9 @@ void LLFloaterPathfindingCharacters::onShowPhysicsCapsuleClicked()
 	}
 }
 
-LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListData(const LLPathfindingCharacter *pCharacterPtr) const
+LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListItemData(const LLPathfindingCharacter *pCharacterPtr) const
 {
-	LLSD columns;
+	LLSD columns = LLSD::emptyArray();
 
 	columns[0]["column"] = "name";
 	columns[0]["value"] = pCharacterPtr->getName();
@@ -231,11 +225,7 @@ LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListData(const LLPathfi
 	columns[4]["column"] = "altitude";
 	columns[4]["value"] = llformat("%1.0f m", pCharacterPtr->getLocation()[2]);
 
-	LLSD element;
-	element["id"] = pCharacterPtr->getUUID().asString();
-	element["column"] = columns;
-
-	return element;
+	return columns;
 }
 
 void LLFloaterPathfindingCharacters::updateStateOnDisplayControls()
diff --git a/indra/newview/llfloaterpathfindingcharacters.h b/indra/newview/llfloaterpathfindingcharacters.h
index ef389ad428..72974f283d 100644
--- a/indra/newview/llfloaterpathfindingcharacters.h
+++ b/indra/newview/llfloaterpathfindingcharacters.h
@@ -62,7 +62,7 @@ protected:
 
 	virtual void                       requestGetObjects();
 
-	virtual LLSD                       convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr);
+	virtual void                       buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr);
 
 	virtual void                       updateControlsOnScrollListChange();
 
@@ -74,7 +74,7 @@ protected:
 private:
 	void onShowPhysicsCapsuleClicked();
 
-	LLSD buildCharacterScrollListData(const LLPathfindingCharacter *pCharacterPtr) const;
+	LLSD buildCharacterScrollListItemData(const LLPathfindingCharacter *pCharacterPtr) const;
 
 	void updateStateOnDisplayControls();
 	void showSelectedCharacterCapsules();
diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp
index 877bd0822d..dd28f82db1 100644
--- a/indra/newview/llfloaterpathfindinglinksets.cpp
+++ b/indra/newview/llfloaterpathfindinglinksets.cpp
@@ -215,7 +215,7 @@ void LLFloaterPathfindingLinksets::requestGetObjects()
 	LLPathfindingManager::getInstance()->requestGetLinksets(getNewRequestId(), boost::bind(&LLFloaterPathfindingLinksets::handleNewObjectList, this, _1, _2, _3));
 }
 
-LLSD LLFloaterPathfindingLinksets::convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr)
+void LLFloaterPathfindingLinksets::buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr)
 {
 	llassert(pObjectListPtr != NULL);
 	llassert(!pObjectListPtr->isEmpty());
@@ -227,7 +227,6 @@ LLSD LLFloaterPathfindingLinksets::convertObjectsIntoScrollListData(const LLPath
 	bool isFilteringDescription = !descriptionFilter.empty();
 	bool isFilteringLinksetUse = (linksetUseFilter != LLPathfindingLinkset::kUnknown);
 
-	LLSD scrollListData = LLSD::emptyArray();
 	const LLVector3& avatarPosition = gAgent.getPositionAgent();
 
 	if (isFilteringName || isFilteringDescription || isFilteringLinksetUse)
@@ -236,22 +235,21 @@ LLSD LLFloaterPathfindingLinksets::convertObjectsIntoScrollListData(const LLPath
 		LLStringUtil::toUpper(descriptionFilter);
 		for (LLPathfindingObjectList::const_iterator objectIter = pObjectListPtr->begin();	objectIter != pObjectListPtr->end(); ++objectIter)
 		{
-			const LLPathfindingLinkset *linksetPtr = dynamic_cast<const LLPathfindingLinkset *>(objectIter->second.get());
+			const LLPathfindingObjectPtr objectPtr = objectIter->second;
+			const LLPathfindingLinkset *linksetPtr = dynamic_cast<const LLPathfindingLinkset *>(objectPtr.get());
+			llassert(linksetPtr != NULL);
+
 			std::string linksetName = (linksetPtr->isTerrain() ? getString("linkset_terrain_name") : linksetPtr->getName());
 			std::string linksetDescription = linksetPtr->getDescription();
 			LLStringUtil::toUpper(linksetName);
 			LLStringUtil::toUpper(linksetDescription);
+
 			if ((!isFilteringName || (linksetName.find(nameFilter) != std::string::npos)) &&
 				(!isFilteringDescription || (linksetDescription.find(descriptionFilter) != std::string::npos)) &&
 				(!isFilteringLinksetUse || (linksetPtr->getLinksetUse() == linksetUseFilter)))
 			{
-				LLSD element = buildLinksetScrollListData(linksetPtr, avatarPosition);
-				scrollListData.append(element);
-
-				if (linksetPtr->hasOwner() && !linksetPtr->hasOwnerName())
-				{
-					rebuildScrollListAfterAvatarNameLoads(linksetPtr->getUUID());
-				}
+				LLSD scrollListItemData = buildLinksetScrollListItemData(linksetPtr, avatarPosition);
+				addObjectToScrollList(objectPtr, scrollListItemData);
 			}
 		}
 	}
@@ -259,18 +257,14 @@ LLSD LLFloaterPathfindingLinksets::convertObjectsIntoScrollListData(const LLPath
 	{
 		for (LLPathfindingObjectList::const_iterator objectIter = pObjectListPtr->begin();	objectIter != pObjectListPtr->end(); ++objectIter)
 		{
-			const LLPathfindingLinkset *linksetPtr = dynamic_cast<const LLPathfindingLinkset *>(objectIter->second.get());
-			LLSD element = buildLinksetScrollListData(linksetPtr, avatarPosition);
-			scrollListData.append(element);
+			const LLPathfindingObjectPtr objectPtr = objectIter->second;
+			const LLPathfindingLinkset *linksetPtr = dynamic_cast<const LLPathfindingLinkset *>(objectPtr.get());
+			llassert(linksetPtr != NULL);
 
-			if (linksetPtr->hasOwner() && !linksetPtr->hasOwnerName())
-			{
-				rebuildScrollListAfterAvatarNameLoads(linksetPtr->getUUID());
-			}
+			LLSD scrollListItemData = buildLinksetScrollListItemData(linksetPtr, avatarPosition);
+			addObjectToScrollList(objectPtr, scrollListItemData);
 		}
 	}
-
-	return scrollListData;
 }
 
 void LLFloaterPathfindingLinksets::updateControlsOnScrollListChange()
@@ -373,10 +367,10 @@ void LLFloaterPathfindingLinksets::updateEditFieldValues()
 	}
 }
 
-LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListData(const LLPathfindingLinkset *pLinksetPtr, const LLVector3 &pAvatarPosition) const
+LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListItemData(const LLPathfindingLinkset *pLinksetPtr, const LLVector3 &pAvatarPosition) const
 {
 	llassert(pLinksetPtr != NULL);
-	LLSD columns;
+	LLSD columns = LLSD::emptyArray();
 
 	if (pLinksetPtr->isTerrain())
 	{
@@ -451,11 +445,7 @@ LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListData(const LLPathfindin
 	columns[9]["column"] = "d_percent";
 	columns[9]["value"] = llformat("%3d", pLinksetPtr->getWalkabilityCoefficientD());
 
-	LLSD element;
-	element["id"] = pLinksetPtr->getUUID().asString();
-	element["column"] = columns;
-
-	return element;
+	return columns;
 }
 
 LLSD LLFloaterPathfindingLinksets::buildLinksetUseScrollListData(const std::string &pLabel, S32 pValue) const
diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h
index 342a64fc77..0877a427b3 100644
--- a/indra/newview/llfloaterpathfindinglinksets.h
+++ b/indra/newview/llfloaterpathfindinglinksets.h
@@ -58,7 +58,7 @@ protected:
 
 	virtual void                       requestGetObjects();
 
-	virtual LLSD                       convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr);
+	virtual void                       buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr);
 
 	virtual void                       updateControlsOnScrollListChange();
 
@@ -78,7 +78,7 @@ private:
 	void clearFilters();
 
 	void updateEditFieldValues();
-	LLSD buildLinksetScrollListData(const LLPathfindingLinkset *pLinksetPtr, const LLVector3 &pAvatarPosition) const;
+	LLSD buildLinksetScrollListItemData(const LLPathfindingLinkset *pLinksetPtr, const LLVector3 &pAvatarPosition) const;
 	LLSD buildLinksetUseScrollListData(const std::string &pLabel, S32 pValue) const;
 
 	bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
diff --git a/indra/newview/llfloaterpathfindingobjects.cpp b/indra/newview/llfloaterpathfindingobjects.cpp
index e246265be9..b3ac18e106 100644
--- a/indra/newview/llfloaterpathfindingobjects.cpp
+++ b/indra/newview/llfloaterpathfindingobjects.cpp
@@ -29,6 +29,8 @@
 
 #include "llfloaterpathfindingobjects.h"
 
+#include <string>
+#include <map>
 #include <vector>
 
 #include <boost/bind.hpp>
@@ -96,7 +98,6 @@ void LLFloaterPathfindingObjects::onOpen(const LLSD &pKey)
 
 void LLFloaterPathfindingObjects::onClose(bool pIsAppQuitting)
 {
-	
 	if (mGodLevelChangeSlot.connected())
 	{
 		mGodLevelChangeSlot.disconnect();
@@ -119,6 +120,11 @@ void LLFloaterPathfindingObjects::onClose(bool pIsAppQuitting)
 	{
 		mObjectsSelection.clear();
 	}
+
+	if (pIsAppQuitting)
+	{
+		clearAllObjects();
+	}
 }
 
 void LLFloaterPathfindingObjects::draw()
@@ -168,13 +174,13 @@ LLFloaterPathfindingObjects::LLFloaterPathfindingObjects(const LLSD &pSeed)
 	mReturnButton(NULL),
 	mDeleteButton(NULL),
 	mTeleportButton(NULL),
-	mLoadingAvatarNames(),
 	mDefaultBeaconColor(),
 	mDefaultBeaconTextColor(),
 	mErrorTextColor(),
 	mWarningTextColor(),
 	mMessagingState(kMessagingUnknown),
 	mMessagingRequestId(0U),
+	mMissingNameObjectsScrollListItems(),
 	mObjectList(),
 	mObjectsSelection(),
 	mHasObjectsToBeSelected(false),
@@ -186,6 +192,7 @@ LLFloaterPathfindingObjects::LLFloaterPathfindingObjects(const LLSD &pSeed)
 
 LLFloaterPathfindingObjects::~LLFloaterPathfindingObjects()
 {
+	clearAllObjects();
 }
 
 BOOL LLFloaterPathfindingObjects::postBuild()
@@ -343,54 +350,21 @@ void LLFloaterPathfindingObjects::rebuildObjectsScrollList()
 
 	S32 origScrollPosition = mObjectsScrollList->getScrollPos();
 	mObjectsScrollList->deleteAllItems();
+	mMissingNameObjectsScrollListItems.clear();
 
 	if ((mObjectList != NULL) && !mObjectList->isEmpty())
 	{
-		LLSD scrollListData = convertObjectsIntoScrollListData(mObjectList);
-		llassert(scrollListData.isArray());
+		buildObjectsScrollList(mObjectList);
 
-		LLScrollListCell::Params cellParams;
-		cellParams.font = LLFontGL::getFontSansSerif();
-
-		for (LLSD::array_const_iterator rowElementIter = scrollListData.beginArray(); rowElementIter != scrollListData.endArray(); ++rowElementIter)
+		mObjectsScrollList->selectMultiple(mObjectsToBeSelected);
+		if (mHasObjectsToBeSelected)
 		{
-			const LLSD &rowElement = *rowElementIter;
-
-			LLScrollListItem::Params rowParams;
-			llassert(rowElement.has("id"));
-			llassert(rowElement.get("id").isString());
-			rowParams.value = rowElement.get("id");
-
-			llassert(rowElement.has("column"));
-			llassert(rowElement.get("column").isArray());
-			const LLSD &columnElement = rowElement.get("column");
-			for (LLSD::array_const_iterator cellIter = columnElement.beginArray(); cellIter != columnElement.endArray(); ++cellIter)
-			{
-				const LLSD &cellElement = *cellIter;
-
-				llassert(cellElement.has("column"));
-				llassert(cellElement.get("column").isString());
-				cellParams.column = cellElement.get("column").asString();
-
-				llassert(cellElement.has("value"));
-				llassert(cellElement.get("value").isString());
-				cellParams.value = cellElement.get("value").asString();
-
-				rowParams.columns.add(cellParams);
-			}
-
-			mObjectsScrollList->addRow(rowParams);
+			mObjectsScrollList->scrollToShowSelected();
+		}
+		else
+		{
+			mObjectsScrollList->setScrollPos(origScrollPosition);
 		}
-	}
-
-	mObjectsScrollList->selectMultiple(mObjectsToBeSelected);
-	if (mHasObjectsToBeSelected)
-	{
-		mObjectsScrollList->scrollToShowSelected();
-	}
-	else
-	{
-		mObjectsScrollList->setScrollPos(origScrollPosition);
 	}
 
 	mObjectsToBeSelected.clear();
@@ -399,20 +373,42 @@ void LLFloaterPathfindingObjects::rebuildObjectsScrollList()
 	updateControlsOnScrollListChange();
 }
 
-LLSD LLFloaterPathfindingObjects::convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr)
+void LLFloaterPathfindingObjects::buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr)
 {
 	llassert(0);
-	LLSD nullObjs = LLSD::emptyArray();
-	return nullObjs;
 }
 
-void LLFloaterPathfindingObjects::rebuildScrollListAfterAvatarNameLoads(const LLUUID &pAvatarId)
+void LLFloaterPathfindingObjects::addObjectToScrollList(const LLPathfindingObjectPtr pObjectPtr, const LLSD &pScrollListItemData)
 {
-	std::set<LLUUID>::const_iterator iter = mLoadingAvatarNames.find(pAvatarId);
-	if (iter == mLoadingAvatarNames.end())
+	LLScrollListCell::Params cellParams;
+	cellParams.font = LLFontGL::getFontSansSerif();
+
+	LLScrollListItem::Params rowParams;
+	rowParams.value = pObjectPtr->getUUID().asString();
+
+	llassert(pScrollListItemData.isArray());
+	for (LLSD::array_const_iterator cellIter = pScrollListItemData.beginArray();
+		cellIter != pScrollListItemData.endArray(); ++cellIter)
+	{
+		const LLSD &cellElement = *cellIter;
+
+		llassert(cellElement.has("column"));
+		llassert(cellElement.get("column").isString());
+		cellParams.column = cellElement.get("column").asString();
+
+		llassert(cellElement.has("value"));
+		llassert(cellElement.get("value").isString());
+		cellParams.value = cellElement.get("value").asString();
+
+		rowParams.columns.add(cellParams);
+	}
+
+	LLScrollListItem *scrollListItem = mObjectsScrollList->addRow(rowParams);
+
+	if (pObjectPtr->hasOwner() && !pObjectPtr->hasOwnerName())
 	{
-		mLoadingAvatarNames.insert(pAvatarId);
-		LLAvatarNameCache::get(pAvatarId, boost::bind(&LLFloaterPathfindingObjects::handleAvatarNameLoads, this, _1, _2));
+		mMissingNameObjectsScrollListItems.insert(std::make_pair<std::string, LLScrollListItem *>(pObjectPtr->getUUID().asString(), scrollListItem));
+		pObjectPtr->registerOwnerNameListener(boost::bind(&LLFloaterPathfindingObjects::handleObjectNameResponse, this, _1, _2));
 	}
 }
 
@@ -434,6 +430,11 @@ S32 LLFloaterPathfindingObjects::getNameColumnIndex() const
 	return 0;
 }
 
+S32 LLFloaterPathfindingObjects::getOwnerNameColumnIndex() const
+{
+	return 2;
+}
+
 const LLColor4 &LLFloaterPathfindingObjects::getBeaconColor() const
 {
 	return mDefaultBeaconColor;
@@ -496,6 +497,7 @@ void LLFloaterPathfindingObjects::clearAllObjects()
 {
 	selectNoneObjects();
 	mObjectsScrollList->deleteAllItems();
+	mMissingNameObjectsScrollListItems.clear();
 	mObjectList.reset();
 }
 
@@ -683,13 +685,21 @@ void LLFloaterPathfindingObjects::onGodLevelChange(U8 pGodLevel)
 	requestGetObjects();
 }
 
-void LLFloaterPathfindingObjects::handleAvatarNameLoads(const LLUUID &pAvatarId, const LLAvatarName &pAvatarName)
+void LLFloaterPathfindingObjects::handleObjectNameResponse(const LLUUID &pObjectUUID, const std::string &pOwnerName)
 {
-	llassert(mLoadingAvatarNames.find(pAvatarId) != mLoadingAvatarNames.end());
-	mLoadingAvatarNames.erase(pAvatarId);
-	if (mLoadingAvatarNames.empty())
+	const std::string uuid = pObjectUUID.asString();
+	scroll_list_item_map::iterator scrollListItemIter = mMissingNameObjectsScrollListItems.find(uuid);
+	if (scrollListItemIter != mMissingNameObjectsScrollListItems.end())
 	{
-		rebuildObjectsScrollList();
+		LLScrollListItem *scrollListItem = scrollListItemIter->second;
+		llassert(scrollListItem != NULL);
+
+		LLScrollListCell *scrollListCell = scrollListItem->getColumn(getOwnerNameColumnIndex());
+		LLSD ownerName = pOwnerName;
+
+		scrollListCell->setValue(ownerName);
+
+		mMissingNameObjectsScrollListItems.erase(scrollListItemIter);
 	}
 }
 
diff --git a/indra/newview/llfloaterpathfindingobjects.h b/indra/newview/llfloaterpathfindingobjects.h
index e8d446b598..b7fd4340ed 100644
--- a/indra/newview/llfloaterpathfindingobjects.h
+++ b/indra/newview/llfloaterpathfindingobjects.h
@@ -27,7 +27,8 @@
 #ifndef LL_LLFLOATERPATHFINDINGOBJECTS_H
 #define LL_LLFLOATERPATHFINDINGOBJECTS_H
 
-#include <set>
+#include <string>
+#include <map>
 
 #include <boost/signals2.hpp>
 
@@ -80,14 +81,14 @@ protected:
 	void                               handleUpdateObjectList(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pRequestStatus, LLPathfindingObjectListPtr pObjectList);
 
 	void                               rebuildObjectsScrollList();
-	virtual LLSD                       convertObjectsIntoScrollListData(const LLPathfindingObjectListPtr pObjectListPtr);
-
-	void                               rebuildScrollListAfterAvatarNameLoads(const LLUUID &pAvatarId);
+	virtual void                       buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr);
+	void                               addObjectToScrollList(const LLPathfindingObjectPtr pObjectPr, const LLSD &pScrollListItemData);
 
 	virtual void                       updateControlsOnScrollListChange();
 	virtual void                       updateControlsOnInWorldSelectionChange();
 
 	virtual S32                        getNameColumnIndex() const;
+	virtual S32                        getOwnerNameColumnIndex() const;
 	virtual const LLColor4             &getBeaconColor() const;
 	virtual const LLColor4             &getBeaconTextColor() const;
 	virtual S32                        getBeaconWidth() const;
@@ -126,7 +127,7 @@ private:
 	void                   onRegionBoundaryCrossed();
 	void                   onGodLevelChange(U8 pGodLevel);
 
-	void                   handleAvatarNameLoads(const LLUUID &pAvatarId, const LLAvatarName &pAvatarName);
+	void                   handleObjectNameResponse(const LLUUID &pObjectUUID, const std::string &pOwnerName);
 
 	void                   updateMessagingStatus();
 	void                   updateStateOnListControls();
@@ -151,8 +152,6 @@ private:
 	LLButton                           *mDeleteButton;
 	LLButton                           *mTeleportButton;
 
-	std::set<LLUUID>                   mLoadingAvatarNames;
-
 	LLColor4                           mDefaultBeaconColor;
 	LLColor4                           mDefaultBeaconTextColor;
 	LLColor4                           mErrorTextColor;
@@ -161,6 +160,9 @@ private:
 	EMessagingState                    mMessagingState;
 	LLPathfindingManager::request_id_t mMessagingRequestId;
 
+	typedef std::map<std::string, LLScrollListItem *> scroll_list_item_map;
+	scroll_list_item_map               mMissingNameObjectsScrollListItems;
+
 	LLPathfindingObjectListPtr         mObjectList;
 
 	LLObjectSelectionHandle            mObjectsSelection;
diff --git a/indra/newview/llpathfindingobject.cpp b/indra/newview/llpathfindingobject.cpp
index 39fc3903b4..95da05740d 100644
--- a/indra/newview/llpathfindingobject.cpp
+++ b/indra/newview/llpathfindingobject.cpp
@@ -57,7 +57,8 @@ LLPathfindingObject::LLPathfindingObject()
 	mOwnerName(),
 	mAvatarNameCacheConnection(),
 	mIsGroupOwned(false),
-	mLocation()
+	mLocation(),
+	mOwnerNameSignal()
 {
 }
 
@@ -70,7 +71,8 @@ LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &p
 	mOwnerName(),
 	mAvatarNameCacheConnection(),
 	mIsGroupOwned(false),
-	mLocation()
+	mLocation(),
+	mOwnerNameSignal()
 {
 	parseObjectData(pObjectData);
 }
@@ -84,7 +86,8 @@ LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther)
 	mOwnerName(),
 	mAvatarNameCacheConnection(),
 	mIsGroupOwned(pOther.mIsGroupOwned),
-	mLocation(pOther.mLocation)
+	mLocation(pOther.mLocation),
+	mOwnerNameSignal()
 {
 	fetchOwnerName();
 }
@@ -119,6 +122,23 @@ std::string LLPathfindingObject::getOwnerName() const
 	return ownerName;
 }
 
+LLPathfindingObject::name_connection_t LLPathfindingObject::registerOwnerNameListener(name_callback_t pOwnerNameCallback)
+{
+	llassert(hasOwner());
+
+	name_connection_t connection;
+	if (hasOwnerName())
+	{
+		pOwnerNameCallback(getUUID(), getOwnerName());
+	}
+	else
+	{
+		connection = mOwnerNameSignal.connect(pOwnerNameCallback);
+	}
+
+	return connection;
+}
+
 void LLPathfindingObject::parseObjectData(const LLSD &pObjectData)
 {
 	llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD));
@@ -161,9 +181,13 @@ void LLPathfindingObject::fetchOwnerName()
 void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName)
 {
 	llassert(mOwnerUUID == pOwnerUUID);
+
 	mOwnerName = pAvatarName;
 	mHasOwnerName = true;
+
 	disconnectAvatarNameCacheConnection();
+
+	mOwnerNameSignal(getUUID(), getOwnerName());
 }
 
 void LLPathfindingObject::disconnectAvatarNameCacheConnection()
diff --git a/indra/newview/llpathfindingobject.h b/indra/newview/llpathfindingobject.h
index f3191053a8..81b6a2402f 100644
--- a/indra/newview/llpathfindingobject.h
+++ b/indra/newview/llpathfindingobject.h
@@ -30,6 +30,8 @@
 #include <string>
 
 #include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
 
 #include "llavatarname.h"
 #include "llavatarnamecache.h"
@@ -60,6 +62,12 @@ public:
 	inline BOOL               isGroupOwned() const   {return mIsGroupOwned;};
 	inline const LLVector3&   getLocation() const    {return mLocation;};
 
+	typedef boost::function<void (const LLUUID &, const std::string &)>         name_callback_t;
+	typedef boost::signals2::signal<void (const LLUUID &, const std::string &)> name_signal_t;
+	typedef boost::signals2::connection                                         name_connection_t;
+
+	name_connection_t registerOwnerNameListener(name_callback_t pOwnerNameCallback);
+
 protected:
 
 private:
@@ -78,6 +86,7 @@ private:
 	LLAvatarNameCache::callback_connection_t mAvatarNameCacheConnection;
 	BOOL                                     mIsGroupOwned;
 	LLVector3                                mLocation;
+	name_signal_t                            mOwnerNameSignal;
 };
 
 #endif // LL_LLPATHFINDINGOBJECT_H
-- 
cgit v1.2.3