diff options
Diffstat (limited to 'indra/newview')
34 files changed, 836 insertions, 157 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 43d5f70b2f..9878a71d89 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -213,6 +213,7 @@ set(viewer_SOURCE_FILES      llfolderview.cpp      llfolderviewitem.cpp      llfollowcam.cpp +    llfriendcard.cpp      llgesturemgr.cpp      llgivemoney.cpp      llglsandbox.cpp @@ -668,6 +669,7 @@ set(viewer_HEADER_FILES      llfoldervieweventlistener.h      llfolderviewitem.h      llfollowcam.h +    llfriendcard.h      llgesturemgr.h      llgivemoney.h      llgroupactions.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 4e289efd1b..5f71b6e3f6 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -42,7 +42,7 @@  #include "llagent.h"  #include "llappviewer.h"		// for gLastVersionChannel  #include "llcallingcard.h"		// for LLAvatarTracker -#include "llinventorymodel.h" +#include "llinventorymodel.h"	// for gInventory.findCategoryUUIDForType  #include "llimview.h"			// for gIMMgr  #include "llsidetray.h"  #include "llviewermessage.h"	// for handle_lure @@ -229,8 +229,6 @@ bool LLAvatarActions::handleRemove(const LLSD& notification, const LLSD& respons  				}  				LLAvatarTracker::instance().terminateBuddy(id);  				LLAvatarTracker::instance().notifyObservers(); -				gInventory.addChangedMask(LLInventoryObserver::LABEL | LLInventoryObserver::CALLING_CARD, LLUUID::null); -				gInventory.notifyObservers();  				break;  			case 1: // NO diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 355a90209a..7326e39af3 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -95,29 +95,8 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;  // static  LLAvatarTracker LLAvatarTracker::sInstance; -/* -class LLAvatarTrackerInventoryObserver : public LLInventoryObserver -{ -public: -	LLAvatarTrackerInventoryObserver(LLAvatarTracker* at) : -		mAT(at) {} -	virtual ~LLAvatarTrackerInventoryObserver() {} -	virtual void changed(U32 mask); -protected: -	LLAvatarTracker* mAT; -}; -*/ -/* -void LLAvatarTrackerInventoryObserver::changed(U32 mask) -{ -	// if there's a calling card change, just do it. -	if((mask & LLInventoryObserver::CALLING_CARD) != 0) -	{ -		mAT->inventoryChanged(); -	} -} -*/ +  ///----------------------------------------------------------------------------  /// Class LLAvatarTracker @@ -329,7 +308,8 @@ void LLAvatarTracker::terminateBuddy(const LLUUID& id)  	msg->nextBlock("ExBlock");  	msg->addUUID("OtherID", id);  	gAgent.sendReliableMessage(); -	mModifyMask |= LLFriendObserver::REMOVE; +	  +	addChangedMask(LLFriendObserver::REMOVE, id);  	delete buddy;  } @@ -503,6 +483,18 @@ void LLAvatarTracker::notifyObservers()  		(*it)->changed(mModifyMask);  	}  	mModifyMask = LLFriendObserver::NONE; +	mChangedBuddyIDs.clear(); +} + +// store flag for change +// and id of object change applies to +void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent) +{  +	mModifyMask |= mask;  +	if (referent.notNull()) +	{ +		mChangedBuddyIDs.insert(referent); +	}  }  void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f) @@ -706,7 +698,7 @@ void LLAvatarTracker::formFriendship(const LLUUID& id)  			//visible online to each other.  			buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);  			at.mBuddyInfo[id] = buddy_info; -			at.mModifyMask |= LLFriendObserver::ADD; +			at.addChangedMask(LLFriendObserver::ADD, id);  			at.notifyObservers();  		}  	} @@ -722,7 +714,7 @@ void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)  		LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);  		if(!buddy) return;  		at.mBuddyInfo.erase(id); -		at.mModifyMask |= LLFriendObserver::REMOVE; +		at.addChangedMask(LLFriendObserver::REMOVE, id);  		delete buddy;  		at.notifyObservers();  	} diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 85a1ab6e1e..113f16de70 100644 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -147,6 +147,17 @@ public:  	void removeObserver(LLFriendObserver* observer);  	void notifyObservers(); +	/** +	 * Stores flag for change and id of object change applies to +	 * +	 * This allows outsiders to tell the AvatarTracker if something has +	 * been changed 'under the hood', +	 * and next notification will have exact avatar IDs have been changed. +	 */ +	void addChangedMask(U32 mask, const LLUUID& referent); + +	const std::set<LLUUID>& getChangedIDs() { return mChangedBuddyIDs; } +  	// Apply the functor to every buddy. Do not actually modify the  	// buddy list in the functor or bad things will happen.  	void applyFunctor(LLRelationshipFunctor& f); @@ -179,6 +190,9 @@ protected:  	buddy_map_t mBuddyInfo; +	typedef std::set<LLUUID> changed_buddy_t; +	changed_buddy_t mChangedBuddyIDs; +  	typedef std::vector<LLFriendObserver*> observer_list_t;  	observer_list_t mObservers; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 70ee5d395e..7ad60232c7 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -61,6 +61,55 @@ static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar");  const S32 DROP_DOWN_MENU_WIDTH = 250;  /** + * Helper for LLFavoriteLandmarkButton and LLFavoriteLandmarkMenuItem. + * Performing requests for SLURL for given Landmark ID + */ +class LLSLURLGetter +{ +public: +	LLSLURLGetter() +		: mLandmarkID(LLUUID::null) +		, mSLURL("(Loading...)") +		, mLoaded(false) {} + +	void setLandmarkID(const LLUUID& id) { mLandmarkID = id; } + +	const std::string& getSLURL() +	{ +		if(!mLoaded) +			requestSLURL(); + +		return mSLURL; +	} +private: +	/** +	 * Requests landmark data from server. +	 */ +	void requestSLURL() +	{ +		if (mLandmarkID.isNull()) +			return; + +		LLVector3d g_pos; +		if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos)) +		{ +			LLLandmarkActions::getSLURLfromPosGlobal(g_pos, +				boost::bind(&LLSLURLGetter::landmarkNameCallback, this, _1), false); +		} +	} + +	void landmarkNameCallback(const std::string& name) +	{ +		mSLURL = name; +		mLoaded = true; +	} + +	LLUUID mLandmarkID; +	std::string mSLURL; +	bool mLoaded; +}; + +/**   * This class is needed to override LLButton default handleToolTip function and   * show SLURL as button tooltip.   * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons @@ -71,9 +120,6 @@ class LLFavoriteLandmarkButton : public LLButton  {  public: -	/** -	 * Requests landmark data from server and shows landmark SLURL as tooltip. -	 */  	BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)  	{  		if(LLUI::sShowXUINames) @@ -81,48 +127,53 @@ public:  			return LLButton::handleToolTip(x, y, msg, sticky_rect);  		} -		if(!mLoaded) -		{ -			LLVector3d g_pos; -			if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos)) -			{ -				LLLandmarkActions::getSLURLfromPosGlobal(g_pos,  -					boost::bind(&LLFavoriteLandmarkButton::landmarkNameCallback, this, _1), false); -			} -		} - -		msg = mSLURL; +		msg = mUrlGetter.getSLURL();  		return TRUE;  	} - -	void landmarkNameCallback(const std::string& name) -	{ -		mSLURL = name; -		mLoaded = true; -	} -	void setLandmarkID(const LLUUID& id){ mLandmarkID = id; } +	void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }  protected: +	LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {} +	friend class LLUICtrlFactory; -	LLFavoriteLandmarkButton(const LLButton::Params& p) -		: LLButton(p) -		, mLandmarkID(LLUUID::null) -		, mSLURL("(Loading...)") -		, mLoaded(false) +private: +	LLSLURLGetter mUrlGetter; +}; + +/** + * This class is needed to override LLMenuItemCallGL default handleToolTip function and + * show SLURL as button tooltip. + * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons + * in showDropDownMenu function but landmark data is not available when Favorites Bar is + * created. Thats why we are requesting landmark data after  + */ +class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL +{ +public: +	BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)  	{ -		static std::string loading_tooltip = LLTrans::getString("favorite_landmark_loading_tooltip"); -		mSLURL = loading_tooltip; +		if(LLUI::sShowXUINames) +		{ +			return LLMenuItemCallGL::handleToolTip(x, y, msg, sticky_rect); +		} + +		msg = mUrlGetter.getSLURL(); +		return TRUE;  	} +	 +	void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); } + +protected: +	LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {}  	friend class LLUICtrlFactory;  private: -	LLUUID mLandmarkID; -	std::string mSLURL; -	bool mLoaded; +	LLSLURLGetter mUrlGetter;  }; +  // updateButtons's helper  struct LLFavoritesSort  { @@ -483,6 +534,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()  		menu_p.visible(false);  		menu_p.scrollable(true);  		menu_p.max_scrollable_items = 10; +		menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;  		LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p); @@ -554,8 +606,10 @@ void LLFavoritesBarCtrl::showDropDownMenu()  			item_params.label(item_name);  			item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); -			LLMenuItemCallGL *menu_item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); +			LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params);  			menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4)); +			menu_item->setLandmarkID(item->getUUID()); +  			// Check whether item name wider than menu  			if (menu_item->getNominalWidth() > max_width)  			{ @@ -583,7 +637,8 @@ void LLFavoritesBarCtrl::showDropDownMenu()  		menu->setButtonRect(mChevronRect, this); -		LLMenuGL::showPopup(this, menu, getRect().getWidth() - widest_item, 0); +		LLMenuGL::showPopup(this, menu, getRect().getWidth() - max_width, 0); +		  	}  } diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 818381b561..4d154c4cd3 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -54,7 +54,6 @@  #include "llagent.h"  #include "llbutton.h"  #include "llcheckboxctrl.h" -#include "llfloaterinventory.h"  #include "llfloaterreg.h"  #include "lllineeditor.h"  #include "lltexturectrl.h" diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 8961508bcc..f1e499e14b 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -231,6 +231,8 @@ void LLFolderViewItem::refreshFromListener()  		// *TODO: to be removed when database supports multi language. This is a  		// temporary attempt to display the inventory folder in the user locale. +		// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID +		//		it uses the same way to find localized string  		if (LLAssetType::lookupIsProtectedCategoryType(preferred_type))  		{  			LLTrans::findString(mLabel, "InvFolder " + mLabel); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp new file mode 100644 index 0000000000..bef5f094e3 --- /dev/null +++ b/indra/newview/llfriendcard.cpp @@ -0,0 +1,425 @@ +/**  + * @file llfriendcard.cpp + * @brief Implementation of classes to process Friends Cards + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinventory.h" +#include "lltrans.h" + +#include "llfriendcard.h" + +#include "llcallingcard.h" // for LLAvatarTracker +#include "llviewerinventory.h" +#include "llinventorymodel.h" + +// Constants; + +static const std::string INVENTORY_STRING_FRIENDS_SUBFOLDER = "Friends"; +static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All"; + +// helper functions + +/* +mantipov *NOTE: unable to use  +LLTrans::getString("InvFolder Friends"); or +LLTrans::getString("InvFolder FriendsAll"); +in next two functions to set localized folders' names because of there is a hack in the +LLFolderViewItem::refreshFromListener() method for protected asset types. +So, localized names will be got from the strings with "InvFolder LABEL_NAME" in the strings.xml +*/ +inline const std::string& get_friend_folder_name() +{ +	return INVENTORY_STRING_FRIENDS_SUBFOLDER; +} + +inline const std::string& get_friend_all_subfolder_name() +{ +	return INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER; +} + +void move_from_to_arrays(LLInventoryModel::cat_array_t& from, LLInventoryModel::cat_array_t& to) +{ +	while (from.count() > 0) +	{ +		to.put(from.get(0)); +		from.remove(0); +	} +} + +const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollectFunctor& matchFunctor) +{ +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; + +	gInventory.collectDescendentsIf(parentFolderUUID, cats, items,  +		LLInventoryModel::EXCLUDE_TRASH, matchFunctor); + +	if (cats.count() == 1) +	{ +		return cats.get(0)->getUUID(); +	} + +	return LLUUID::null; +} + +// LLFriendCardsManager Constructor / Destructor +LLFriendCardsManager::LLFriendCardsManager() +{ +	LLAvatarTracker::instance().addObserver(this); +} + +LLFriendCardsManager::~LLFriendCardsManager() +{ +	LLAvatarTracker::instance().removeObserver(this); +} + +void LLFriendCardsManager::putAvatarData(const LLUUID& avatarID) +{ +	llinfos << "Store avatar data, avatarID: " << avatarID << llendl; +	std::pair< avatar_uuid_set_t::iterator, bool > pr; +	pr = mBuddyIDSet.insert(avatarID); +	if (pr.second == false) +	{ +		llwarns << "Trying to add avatar UUID for the stored avatar: "  +			<< avatarID +			<< llendl; +	} +} + +const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID) +{ +	LLUUID rv; +	avatar_uuid_set_t::iterator it = mBuddyIDSet.find(avatarID); +	if (mBuddyIDSet.end() == it) +	{ +		llwarns << "Call method for non-existent avatar name in the map: " << avatarID << llendl; +	} +	else +	{ +		rv = (*it); +		mBuddyIDSet.erase(it); +	} +	return rv; +} + +// be sure LLInventoryModel::buildParentChildMap() has been called before it. +// and this method must be called before any actions with friend list +void LLFriendCardsManager::ensureFriendFoldersExist() +{ +	LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + +	LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); + +	if (friendFolderUUID.isNull()) +	{ +		friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID, +			LLAssetType::AT_CALLINGCARD, get_friend_folder_name()); +	} + +	LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl(); + +	if (friendAllSubfolderUUID.isNull()) +	{ +		friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID, +			LLAssetType::AT_CALLINGCARD, get_friend_all_subfolder_name()); +	} +} + + +bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* item) +{ +	if (item->getType() != LLAssetType::AT_CALLINGCARD) +		return false; + +	LLInventoryModel::item_array_t items; +	findMatchedFriendCards(item->getCreatorUUID(), items); + +	return items.count() > 0; +} + +bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const +{ +	if (NULL == cat) +		return false; +	return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl()); +} + +void LLFriendCardsManager::syncFriendsFolder() +{ +	//lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent +	LLFriendCardsManager::instance().ensureFriendFoldersExist(); + +	LLAvatarTracker::buddy_map_t all_buddies; +	LLAvatarTracker::instance().copyBuddyList(all_buddies); + +	// 1. Remove Friend Cards for non-friends +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; + +	gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH); +	 +	LLInventoryModel::item_array_t::const_iterator it; +	for (it = items.begin(); it != items.end(); ++it) +	{ +		lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl; +		if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID())) +		{ +			lldebugs << "NONEXISTS, so remove it" << llendl; +			removeFriendCardFromInventory((*it)->getCreatorUUID()); +		} +	} + +	// 2. Add missing Friend Cards for friends +	LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); +	llinfos << "try to build friends, count: " << all_buddies.size() << llendl;  +	for(; buddy_it != all_buddies.end(); ++buddy_it) +	{ +		const LLUUID& buddy_id = (*buddy_it).first; +		addFriendCardToInventory(buddy_id); +	} +} + +void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const +{ +	folderBuddiesMap.clear(); + +	LLInventoryModel::cat_array_t* listFolders; +	LLInventoryModel::item_array_t* items; + +	// get folders in the Friend folder. Items should be NULL due to Cards should be in lists. +	gInventory.getDirectDescendentsOf(findFriendFolderUUIDImpl(), listFolders, items); + +	if (NULL == listFolders) +		return; + +	LLInventoryModel::cat_array_t::const_iterator itCats;	// to iterate Friend Lists (categories) +	LLInventoryModel::item_array_t::const_iterator itBuddy;	// to iterate Buddies in each List +	LLInventoryModel::cat_array_t* fakeCatsArg; +	for (itCats = listFolders->begin(); itCats != listFolders->end(); ++itCats) +	{ +		if (items) +			items->clear(); + +		// *HACK: Only Friends/All content will be shown for now +		// *TODO: Remove this hack, implement sorting if it will be needded by spec. +		if ((*itCats)->getUUID() != findFriendAllSubfolderUUIDImpl()) +			continue; + +		gInventory.getDirectDescendentsOf((*itCats)->getUUID(), fakeCatsArg, items); + +		if (NULL == items) +			continue; + +		std::vector<LLUUID> buddyUUIDs; +		for (itBuddy = items->begin(); itBuddy != items->end(); ++itBuddy) +		{ +			buddyUUIDs.push_back((*itBuddy)->getCreatorUUID()); +		} + +		folderBuddiesMap.insert(make_pair((*itCats)->getUUID(), buddyUUIDs)); +	} +} + + +/************************************************************************/ +/*		Private Methods                                                 */ +/************************************************************************/ +const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const +{ +	LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + +	std::string friendFolderName = get_friend_folder_name(); + +	return findChildFolderUUID(callingCardsFolderID, friendFolderName); +} + +const LLUUID& LLFriendCardsManager::findFriendAllSubfolderUUIDImpl() const +{ +	LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); + +	std::string friendAllSubfolderName = get_friend_all_subfolder_name(); + +	return findChildFolderUUID(friendFolderUUID, friendAllSubfolderName); +} + +const LLUUID& LLFriendCardsManager::findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& folderLabel) const +{ +	// mantipov *HACK: get localaized name in the same way like in the LLFolderViewItem::refreshFromListener() method. +	// be sure these both methods are synchronized. +	// see also get_friend_folder_name() and get_friend_all_subfolder_name() functions +	std::string localizedName = LLTrans::getString("InvFolder " + folderLabel); + +	LLNameCategoryCollector matchFolderFunctor(localizedName); + +	return get_folder_uuid(parentFolderUUID, matchFolderFunctor); +} +const LLUUID& LLFriendCardsManager::findFriendCardInventoryUUIDImpl(const LLUUID& avatarID) +{ +	LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl(); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLInventoryModel::item_array_t::const_iterator it; + +	// it is not necessary to check friendAllSubfolderUUID against NULL. It will be processed by collectDescendents +	gInventory.collectDescendents(friendAllSubfolderUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH); +	for (it = items.begin(); it != items.end(); ++it) +	{ +		if ((*it)->getCreatorUUID() == avatarID) +			return (*it)->getUUID(); +	} + +	return LLUUID::null; +} + +void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const +{ +	LLInventoryModel::cat_array_t cats; +	LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); + +	LLParticularBuddyCollector matchFunctor(avatarID); + +	LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID); + +	LLInventoryModel::cat_array_t subFolders; +	subFolders.push_back(friendFolder); + +	while (subFolders.count() > 0) +	{ +		LLViewerInventoryCategory* cat = subFolders.get(0); +		subFolders.remove(0); + +		gInventory.collectDescendentsIf(cat->getUUID(), cats, items,  +			LLInventoryModel::EXCLUDE_TRASH, matchFunctor); + +		move_from_to_arrays(cats, subFolders); +	} +} + +class CreateFriendCardCallback : public LLInventoryCallback +{ +public: +	void fire(const LLUUID& inv_item_id) +	{ +		LLViewerInventoryItem* item = gInventory.getItem(inv_item_id); + +		if (item) +			LLFriendCardsManager::instance().extractAvatarID(item->getCreatorUUID()); +	} +}; + +bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID) +{ +	LLInventoryModel* invModel = &gInventory; + +	bool shouldBeAdded = true; +	std::string name; +	gCacheName->getFullName(avatarID, name); + +	lldebugs << "Processing buddy name: " << name  +		<< ", id: " << avatarID +		<< llendl;  + +	if (shouldBeAdded && findFriendCardInventoryUUIDImpl(avatarID).notNull()) +	{ +		shouldBeAdded = false; +		lldebugs << "is found in Inventory: " << name << llendl;  +	} + +	if (shouldBeAdded && isAvatarDataStored(avatarID)) +	{ +		shouldBeAdded = false; +		lldebugs << "is found in sentRequests: " << name << llendl;  +	} + +	LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl(); +	if (shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID)) +	{ +		shouldBeAdded = false; +	} +	if (shouldBeAdded) +	{ +		putAvatarData(avatarID); +		lldebugs << "Sent create_inventory_item for " << avatarID << ", " << name << llendl; + +		// TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not +		LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback(); + +		create_inventory_callingcard(avatarID, friendListFolderID, cb); +	} + +	return shouldBeAdded; +} + +void LLFriendCardsManager::removeFriendCardFromInventory(const LLUUID& avatarID) +{ +	LLInventoryModel::item_array_t items; +	findMatchedFriendCards(avatarID, items); + +	LLInventoryModel::item_array_t::const_iterator it; +	for (it = items.begin(); it != items.end(); ++ it) +	{ +		gInventory.removeItem((*it)->getUUID()); +	} +} + +void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask) +{ +	LLAvatarTracker& at = LLAvatarTracker::instance(); + +	switch(changed_mask) { +	case LLFriendObserver::ADD: +		{ +			const std::set<LLUUID>& changed_items = at.getChangedIDs(); +			std::set<LLUUID>::const_iterator id_it = changed_items.begin(); +			std::set<LLUUID>::const_iterator id_end = changed_items.end(); +			for (;id_it != id_end; ++id_it) +			{ +				LLFriendCardsManager::instance().addFriendCardToInventory(*id_it); +			} +		} +		break; +	case LLFriendObserver::REMOVE: +		{ +			const std::set<LLUUID>& changed_items = at.getChangedIDs(); +			std::set<LLUUID>::const_iterator id_it = changed_items.begin(); +			std::set<LLUUID>::const_iterator id_end = changed_items.end(); +			for (;id_it != id_end; ++id_it) +			{ +				LLFriendCardsManager::instance().removeFriendCardFromInventory(*id_it); +			} +		} + +	default:; +	} +} + +// EOF diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h new file mode 100644 index 0000000000..18a6d0ab69 --- /dev/null +++ b/indra/newview/llfriendcard.h @@ -0,0 +1,143 @@ +/**  + * @file llfriendcard.h + * @brief Definition of classes to process Friends Cards + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFRIENDCARD_H +#define LL_LLFRIENDCARD_H + + +#include "llcallingcard.h" +#include "llinventorymodel.h" // for LLInventoryModel::item_array_t + +class LLViewerInventoryItem; + +class LLFriendCardsManager +	: public LLSingleton<LLFriendCardsManager> +	, public LLFriendObserver +{ +	LOG_CLASS(LLFriendCardsManager); + +	friend class LLSingleton<LLFriendCardsManager>; +	friend class CreateFriendCardCallback; + +public: +	typedef std::map<LLUUID, std::vector<LLUUID> > folderid_buddies_map_t; + +	// LLFriendObserver implementation +	void changed(U32 mask) +	{ +		onFriendListUpdate(mask); +	} + +	/** +	 *	Ensures that all necessary folders are created in Inventory. +	 *  +	 *	For now it processes Calling Card, Calling Card/Friends & Calling Card/Friends/All folders +	 */ +	void ensureFriendFoldersExist(); + + +	/** +	 *	Determines if specified Inventory Calling Card exists in any of lists  +	 *	in the Calling Card/Friends/ folder (Default, or Custom) +	 */ +	bool isItemInAnyFriendsList(const LLViewerInventoryItem* item); + +	/** +	 *	Checks is the specified category is in the Calling Card/Friends folder +	 */ +	bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const; + +	/** +	 *	Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List +	 */ +	void syncFriendsFolder(); + +	/*! +	 * \brief +	 * Collects folders' IDs with the buddies' IDs in the Inventory Calling Card/Friends folder. +	 *  +	 * \param folderBuddiesMap +	 * map into collected data will be put. It will be cleared before adding new data. +	 *  +	 * Each item in the out map is a pair where first is an LLViewerInventoryCategory UUID, +	 * second is a vector with UUID of Avatars from this folder. +	 *  +	 */ +	void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const; + +private: +	LLFriendCardsManager(); +	~LLFriendCardsManager(); + + +	/** +	 *	Stores buddy id to avoid sent create_inventory_callingcard several time for the same Avatar +	 */ +	void putAvatarData(const LLUUID& avatarID); + +	/** +	 *	Extracts buddy id of Created Friend Card +	 */ +	const LLUUID extractAvatarID(const LLUUID& avatarID); + +	bool isAvatarDataStored(const LLUUID& avatarID) const +	{ +		return (mBuddyIDSet.end() != mBuddyIDSet.find(avatarID)); +	} + +	const LLUUID& findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& folderLabel) const; +	const LLUUID& findFriendFolderUUIDImpl() const; +	const LLUUID& findFriendAllSubfolderUUIDImpl() const; +	const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID); +	void findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const; + +	/** +	 *	Adds avatar specified by its UUID into the Calling Card/Friends/All Global Inventory folder +	 */ +	bool addFriendCardToInventory(const LLUUID& avatarID); + +	/** +	 *	Removes an avatar specified by its UUID from the Calling Card/Friends/All Global Inventory folder +	 *		and from the all Custom Folders +	 */ +	void removeFriendCardFromInventory(const LLUUID& avatarID); + +	void onFriendListUpdate(U32 changed_mask); + + +private: +	typedef std::set<LLUUID> avatar_uuid_set_t; + +	avatar_uuid_set_t mBuddyIDSet; +}; + +#endif // LL_LLFRIENDCARD_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index efa97de692..789e628b67 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -58,6 +58,7 @@  #include "llfloaterworldmap.h"  #include "llfocusmgr.h"  #include "llfolderview.h" +#include "llfriendcard.h"  #include "llavataractions.h"  #include "llgesturemgr.h"  #include "lliconctrl.h" @@ -162,10 +163,26 @@ std::string ICON_NAME[ICON_NAME_COUNT] =  BOOL gAddToOutfit = FALSE; + +// +=================================================+ +// |        LLInventoryPanelObserver                 | +// +=================================================+ +void LLInventoryPanelObserver::changed(U32 mask) +{ +	mIP->modelChanged(mask); +} + +  // +=================================================+  // |        LLInvFVBridge                            |  // +=================================================+ +LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : +mUUID(uuid), mInvType(LLInventoryType::IT_NONE) +{ +	mInventoryPanel = inventory->getHandle(); +} +  const std::string& LLInvFVBridge::getName() const  {  	LLInventoryObject* obj = getInventoryObject(); @@ -2302,7 +2319,11 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	}  	else if(isAgentInventory()) // do not allow creating in library  	{ -		mItems.push_back(std::string("New Folder")); +		LLViewerInventoryCategory *cat =  getCategory(); + +		// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. +		if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) +			mItems.push_back(std::string("New Folder"));  		mItems.push_back(std::string("New Script"));  		mItems.push_back(std::string("New Note"));  		mItems.push_back(std::string("New Gesture")); @@ -2310,7 +2331,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		mItems.push_back(std::string("New Body Parts"));  		mItems.push_back(std::string("Change Type")); -		LLViewerInventoryCategory *cat =  getCategory();  		if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))  		{  			mDisabledItems.push_back(std::string("Change Type")); @@ -2879,6 +2899,16 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  // |        LLLandmarkBridge                         |  // +=================================================+ +LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : +LLItemBridge(inventory, uuid)  +{ +	mVisited = FALSE; +	if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) +	{ +		mVisited = TRUE; +	} +} +  LLUIImagePtr LLLandmarkBridge::getIcon() const  {  	return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); @@ -3216,6 +3246,18 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,  	return rv;  } +BOOL LLCallingCardBridge::removeItem() +{ +	if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) +	{ +		LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); +		return FALSE; +	} +	else  +	{ +		return LLItemBridge::removeItem(); +	} +}  // +=================================================+  // |        LLNotecardBridge                         |  // +=================================================+ @@ -3450,6 +3492,14 @@ void LLAnimationBridge::openItem()  // static  LLUUID LLObjectBridge::sContextMenuItemID; +LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : +LLItemBridge(inventory, uuid), mInvType(type) +{ +	mAttachPt = (flags & 0xff); // low bye of inventory flags + +	mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ?  TRUE: FALSE; +} +  BOOL LLObjectBridge::isItemRemovable()  {  	LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 3af54c52ea..25859b7f73 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -38,9 +38,10 @@  #include "llviewercontrol.h"  #include "llcallingcard.h"  #include "llinventorymodel.h" -#include "llfloaterinventory.h"  #include "llfoldervieweventlistener.h" +class LLInventoryPanel; +  enum EInventoryIcon  {  	TEXTURE_ICON_NAME, @@ -114,7 +115,7 @@ class LLInventoryPanelObserver : public LLInventoryObserver  public:  	LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {}  	virtual ~LLInventoryPanelObserver() {} -	virtual void changed(U32 mask) { mIP->modelChanged(mask); } +	virtual void changed(U32 mask);  protected:  	LLInventoryPanel* mIP;  }; @@ -191,11 +192,7 @@ public:  	virtual void clearDisplayName() {}  protected: -	LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : -		mUUID(uuid), mInvType(LLInventoryType::IT_NONE) -	{ -		mInventoryPanel = inventory->getHandle(); -	} +	LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid);  	LLInventoryObject* getInventoryObject() const;  	LLInventoryModel* getInventoryModel() const; @@ -395,15 +392,7 @@ public:  	virtual void openItem();  protected: -	LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00) : -		LLItemBridge(inventory, uuid)  -	{ -		mVisited = FALSE; -		if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) -		{ -			mVisited = TRUE; -		} -	} +	LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00);  protected:  	BOOL mVisited; @@ -438,6 +427,7 @@ public:  							EDragAndDropType cargo_type,  							void* cargo_data);  	void refreshFolderViewItem(); +	BOOL removeItem();  protected:  	LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ); @@ -515,13 +505,7 @@ public:  	LLInventoryObject* getObject() const;  protected: -	LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : -		LLItemBridge(inventory, uuid), mInvType(type) -	{ -		mAttachPt = (flags & 0xff); // low bye of inventory flags - -		mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ?  TRUE: FALSE; -	} +	LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags);  protected:  	static LLUUID	sContextMenuItemID;  // Only valid while the context menu is open. @@ -788,6 +772,7 @@ void wear_inventory_item_on_avatar(LLInventoryItem* item);  void wear_outfit_by_name(const std::string& name);  void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append); +class LLViewerJointAttachment;  void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);  // Move items from an in-world object's "Contents" folder to a specified diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index efa15e05da..1666ec1336 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -50,7 +50,6 @@  #include "llfloaterdirectory.h"  #include "llfloaterworldmap.h"  #include "llgivemoney.h" -#include "llfloaterinventory.h"  #include "lllineeditor.h"  #include "llnotify.h"  #include "llstatusbar.h" diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 7bf7ceb6d2..1d79ea4a21 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -38,6 +38,7 @@  #include "lllandmark.h"  #include "llfloaterworldmap.h" +#include "llfloaterinventory.h"  #include "llfoldervieweventlistener.h"  #include "lllandmarklist.h"  #include "llsidetray.h" diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 0b11270fb5..14cbbd6123 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -33,10 +33,13 @@  #ifndef LL_LLPANELLANDMARKS_H  #define LL_LLPANELLANDMARKS_H -#include "llfloaterinventory.h"  #include "llinventorymodel.h"  #include "llpanelplacestab.h" +class LLFolderViewItem; +class LLInventoryPanel; +class LLSaveFolderState; +  class LLLandmarksPanel : public LLPanelPlacesTab  {  public: diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 844e5122f4..697182c8fc 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -47,6 +47,7 @@  #include "llcallingcard.h"			// for LLAvatarTracker  #include "llfloateravatarpicker.h"  //#include "llfloaterminiinspector.h" +#include "llfriendcard.h"  #include "llavataractions.h"  #include "llgroupactions.h"  #include "llgrouplist.h" @@ -302,7 +303,7 @@ LLPanelPeople::LLPanelPeople()  		mFilterEditor(NULL),  		mTabContainer(NULL),  		mOnlineFriendList(NULL), -		mOfflineFriendList(NULL), +		mAllFriendList(NULL),  		mNearbyList(NULL),  		mRecentList(NULL)  { @@ -337,7 +338,7 @@ BOOL LLPanelPeople::postBuild()  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));  	mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online"); -	mOfflineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_offline"); +	mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");  	mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list"); @@ -354,11 +355,11 @@ BOOL LLPanelPeople::postBuild()  	friends_panel->childSetAction("del_btn",	boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this));  	mOnlineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOnlineFriendList)); -	mOfflineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOfflineFriendList)); +	mAllFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mAllFriendList));  	mNearbyList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mNearbyList));  	mRecentList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mRecentList));  	mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList)); -	mOfflineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOfflineFriendList)); +	mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList));  	mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));  	mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList)); @@ -427,17 +428,25 @@ bool LLPanelPeople::updateFriendList(U32 changed_mask)  		// *TODO: it's suboptimal to rebuild the whole lists on online status change. -		// save them to the online and offline friends vectors +		// save them to the online and all friends vectors  		mOnlineFriendVec.clear(); -		mOfflineFriendVec.clear(); +		mAllFriendVec.clear(); + +		LLFriendCardsManager::folderid_buddies_map_t listMap; + +		// *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694. +		LLFriendCardsManager::instance().collectFriendsLists(listMap); +		if (listMap.size() > 0) +		{ +			mAllFriendVec = listMap.begin()->second; +		} +  		LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();  		for (; buddy_it != all_buddies.end(); ++buddy_it)  		{  			LLUUID buddy_id = buddy_it->first;  			if (av_tracker.isBuddyOnline(buddy_id))  				mOnlineFriendVec.push_back(buddy_id); -			else -				mOfflineFriendVec.push_back(buddy_id);  		}  		return filterFriendList(); @@ -477,19 +486,19 @@ bool LLPanelPeople::updateGroupList()  bool LLPanelPeople::filterFriendList()  { -	if (!mOnlineFriendList || !mOfflineFriendList) +	if (!mOnlineFriendList || !mAllFriendList)  		return true; // there's no point in further updates  	// We must always update Friends list to clear the latest removed friend.  	bool have_names =  			mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) & -			mOfflineFriendList->update(mOfflineFriendVec, mFilterSubString); +			mAllFriendList->update(mAllFriendVec, mFilterSubString);  	if (mOnlineFriendVec.size() == 0)  		mOnlineFriendList->setCommentText(getString("no_friends_online")); -	if (mOfflineFriendVec.size() == 0) -		mOfflineFriendList->setCommentText(getString("no_friends_offline")); +	if (mAllFriendVec.size() == 0) +		mAllFriendList->setCommentText(getString("no_friends"));  	return have_names;  } @@ -615,7 +624,7 @@ LLUUID LLPanelPeople::getCurrentItemID() const  		if ((cur_online_friend = mOnlineFriendList->getCurrentID()).notNull())  			return cur_online_friend; -		return mOfflineFriendList->getCurrentID(); +		return mAllFriendList->getCurrentID();  	}  	if (cur_tab == NEARBY_TAB_NAME) @@ -720,12 +729,12 @@ void LLPanelPeople::onAvatarListDoubleClicked(LLAvatarList* list)  void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)  { -	// Make sure only one of the friends lists (online/offline) has selection. +	// Make sure only one of the friends lists (online/all) has selection.  	if (getActiveTabName() == FRIENDS_TAB_NAME)  	{  		if (list == mOnlineFriendList) -			mOfflineFriendList->deselectAllItems(TRUE); -		else if (list == mOfflineFriendList) +			mAllFriendList->deselectAllItems(TRUE); +		else if (list == mAllFriendList)  			mOnlineFriendList->deselectAllItems(TRUE);  		else  			llassert(0 && "commit on unknown friends list"); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index d0f78f4247..3358a70bac 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -116,7 +116,7 @@ private:  	LLFilterEditor*			mFilterEditor;  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mOnlineFriendList; -	LLAvatarList*			mOfflineFriendList; +	LLAvatarList*			mAllFriendList;  	LLAvatarList*			mNearbyList;  	LLAvatarList*			mRecentList;  	LLGroupList*			mGroupList; @@ -142,7 +142,7 @@ private:  	typedef std::vector<LLUUID> uuid_vector_t;  	uuid_vector_t			mNearbyVec;  	uuid_vector_t			mOnlineFriendVec; -	uuid_vector_t			mOfflineFriendVec; +	uuid_vector_t			mAllFriendVec;  	uuid_vector_t			mRecentVec;  }; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index ad1dd74cc6..7cb9e61e72 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -32,6 +32,7 @@  #include "llviewerprecompiledheaders.h"  #include "llassettype.h" +#include "llwindow.h"  #include "lllandmark.h" @@ -51,6 +52,7 @@  #include "llpanelteleporthistory.h"  #include "llsidetray.h"  #include "lltoggleablemenu.h" +#include "llviewerinventory.h"  #include "llviewermenu.h"  #include "llviewerparcelmgr.h"  #include "llviewerregion.h" diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 7faabbb28b..ab253e012d 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -51,7 +51,6 @@  #include "llagent.h"  #include "llvoavatarself.h"  #include "llselectmgr.h" -#include "llfloaterinventory.h"  #include "llviewerinventory.h"  #include "llviewerwindow.h"  #include "lltrans.h" diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 6fe23e8aeb..3bda30e0c6 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -36,7 +36,6 @@  #include "llbutton.h"  #include "llresmgr.h"  #include "llinventory.h" -#include "llfloaterinventory.h"  #include "llvoavatarself.h"  #include "llagent.h"          // gAgent  #include "llkeyframemotion.h" diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index 0f2b94ebd4..7659c50ed3 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -36,7 +36,6 @@  #include "llagent.h"          // gAgent  #include "llbutton.h"  #include "llinventory.h" -#include "llfloaterinventory.h"  #include "lllineeditor.h"  #include "llpreviewsound.h"  #include "llresmgr.h" diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 9122e49a06..9d7338c111 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -32,6 +32,8 @@  #include "llviewerprecompiledheaders.h" +#include "llwindow.h" +  #include "llpreviewtexture.h"  #include "llagent.h" @@ -39,7 +41,6 @@  #include "llfilepicker.h"  #include "llfloaterreg.h"  #include "llimagetga.h" -#include "llfloaterinventory.h"  #include "llinventory.h"  #include "llresmgr.h"  #include "lltrans.h" diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 3ac9076e85..afa8e5f072 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -642,20 +642,18 @@ LLPanel*	LLSideTray::showPanel		(const std::string& panel_name, const LLSD& para  	return NULL;  } +// *TODO: Eliminate magic constants.  static const S32	fake_offset = 132;  static const S32	fake_top_offset = 18;  void LLSideTray::resetPanelRect	()  { -	LLNavigationBar* nav_bar = LLNavigationBar::getInstance(); -	LLRect nav_rect = nav_bar->getRect();  	const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();  	static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());	 -	S32 panel_width = sidetray_params.default_button_width+sidetray_params.default_button_margin; -	if(!mCollapsed) -		panel_width+=mMaxBarWidth; +	S32 panel_width = sidetray_params.default_button_width; +	panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;  	S32 panel_height = parent_rect.getHeight()-fake_top_offset; @@ -671,9 +669,8 @@ void	LLSideTray::setPanelRect	()  	const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); -	S32 panel_width = sidetray_params.default_button_width+sidetray_params.default_button_margin; -	if(!mCollapsed) -		panel_width+=mMaxBarWidth; +	S32 panel_width = sidetray_params.default_button_width; +	panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;  	S32 panel_height = parent_rect.getHeight()-fake_top_offset - nav_rect.getHeight();  	S32 panel_top = parent_rect.mTop-fake_top_offset - nav_rect.getHeight(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 920ec0c65d..6c0481feaa 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -77,6 +77,7 @@  #include "llviewercontrol.h"  #include "llvfs.h"  #include "llxorcipher.h"	// saved password, MAC address +#include "llwindow.h"  #include "imageids.h"  #include "message.h"  #include "v3math.h" @@ -111,7 +112,7 @@  #include "llimagebmp.h"  #include "llinventorybridge.h"  #include "llinventorymodel.h" -#include "llfloaterinventory.h" +#include "llfriendcard.h"  #include "llkeyboard.h"  #include "llloginhandler.h"			// gLoginHandler, SLURL support  #include "llpanellogin.h" @@ -2142,10 +2143,15 @@ bool idle_startup()  		} +		// This method MUST be called before gInventory.findCategoryUUIDForType because of  +		// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap. +		gInventory.buildParentChildMap(); +  		//all categories loaded. lets create "My Favorites" category  		gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE,true); -		gInventory.buildParentChildMap(); +		// lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies +		LLFriendCardsManager::instance().syncFriendsFolder();  		llinfos << "Setting Inventory changed mask and notifying observers" << llendl;  		gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 9cabcf4680..c724fb5315 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -46,7 +46,6 @@  #include "llfloaterregioninfo.h"  #include "llfloaterscriptdebug.h"  #include "llhudicon.h" -#include "llfloaterinventory.h"  #include "llnavigationbar.h"  #include "llkeyboard.h"  #include "lllineeditor.h" @@ -224,7 +223,7 @@ void LLStatusBar::draw()  	LLPanel::draw();  } -BOOL LLStatusBar::handleRightMouseUp(S32 x, S32 y, MASK mask) +BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	if (mHideNavbarContextMenu)  	{ @@ -603,7 +602,7 @@ void LLStatusBar::onHideNavbarContextMenuItemClicked(const LLSD& userdata)  void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)  { -	handleRightMouseUp(x, y, mask); +	handleRightMouseDown(x, y, mask);  }  // static diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 0cb3551768..b77db2c525 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -58,7 +58,7 @@ public:  	/*virtual*/ void draw(); -	/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL postBuild();  	// MANIPULATORS diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index b5dd34df15..c58457d599 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -51,7 +51,6 @@  #include "llhudmanager.h"  #include "llinventorybridge.h"  #include "llinventorymodel.h" -#include "llfloaterinventory.h"  #include "llmutelist.h"  #include "llnotify.h"  #include "llpreviewnotecard.h" diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 4645b9bf59..95ab40f9bf 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -799,14 +799,14 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,  	gAgent.sendReliableMessage();  } -void create_inventory_callingcard(const LLUUID& avatar_id) +void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)  {  	std::string item_desc = avatar_id.asString();  	std::string item_name;  	gCacheName->getFullName(avatar_id, item_name);  	create_inventory_item(gAgent.getID(), gAgent.getSessionID(), -						  LLUUID::null, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD, -						  LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, NULL); +						  parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD, +						  LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);  }  void copy_inventory_item( diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 8920fb053b..0bfb37f7e8 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -286,7 +286,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,  						   U32 next_owner_perm,  						   LLPointer<LLInventoryCallback> cb); -void create_inventory_callingcard(const LLUUID& avatar_id); +void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent = LLUUID::null, LLPointer<LLInventoryCallback> cb=NULL);  /**   * @brief Securely create a new inventory item by copying from another. diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 7bbe2c89b4..de01e79803 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -39,7 +39,6 @@  #include "llinventory.h"  #include "llinventorybridge.h"  #include "llinventorymodel.h" -#include "llfloaterinventory.h"  #include "llviewertexteditor.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 9bdf9d2aac..461f7fc1c7 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -116,7 +116,6 @@  #include "llhudview.h"  #include "llimagebmp.h"  #include "llimagej2c.h" -#include "llfloaterinventory.h"  #include "llkeyboard.h"  #include "lllineeditor.h"  #include "llmenugl.h" diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 98d8b27e09..018cce4b49 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -52,7 +52,6 @@  #include "llheadrotmotion.h"  #include "llhudeffecttrail.h"  #include "llhudmanager.h" -#include "llfloaterinventory.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" @@ -5510,6 +5509,24 @@ void LLVOAvatar::sitDown(BOOL bSitting)  //-----------------------------------------------------------------------------  void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)  { +	if (isSelf()) +	{ +		// Might be first sit +		LLFirstUse::useSit(); + +		gAgent.setFlying(FALSE); +		gAgent.setThirdPersonHeadOffset(LLVector3::zero); +		//interpolate to new camera position +		gAgent.startCameraAnimation(); +		// make sure we are not trying to autopilot +		gAgent.stopAutoPilot(); +		gAgent.setupSitCamera(); +		if (gAgent.getForceMouselook()) +		{ +			gAgent.changeCameraToMouselook(); +		} +	} +  	if (mDrawable.isNull())  	{  		return; @@ -5531,23 +5548,6 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)  	stopMotion(ANIM_AGENT_BODY_NOISE); -	if (isSelf()) -	{ -		// Might be first sit -		LLFirstUse::useSit(); - -		gAgent.setFlying(FALSE); -		gAgent.setThirdPersonHeadOffset(LLVector3::zero); -		//interpolate to new camera position -		gAgent.startCameraAnimation(); -		// make sure we are not trying to autopilot -		gAgent.stopAutoPilot(); -		gAgent.setupSitCamera(); -		if (gAgent.getForceMouselook()) -		{ -			gAgent.changeCameraToMouselook(); -		} -	}  }  //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 9777e1ec21..a7b5b60842 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -54,7 +54,6 @@  #include "llheadrotmotion.h"  #include "llhudeffecttrail.h"  #include "llhudmanager.h" -#include "llfloaterinventory.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index fce31a2c68..22823ea98b 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -19,8 +19,8 @@       name="no_friends_online"       value="No friends online" />      <string -     name="no_friends_offline" -     value="No friends offline" /> +     name="no_friends" +     value="No friends" />      <string       name="no_groups"       value="No groups" /> @@ -153,14 +153,14 @@                   can_resize="false"                   layout="topleft"                   min_height="100" -                 name="tab_offline" -                 title="Offline"> +                 name="tab_all" +                 title="All">                      <panel                       follows="all"                       height="260"                       layout="topleft"                       left="0" -                     name="tab_offline_panel" +                     name="tab_all_panel"                       top="100"                       width="285">                          <avatar_list @@ -169,7 +169,7 @@                           height="255"                           layout="topleft"                           left="0" -                         name="avatars_offline" +                         name="avatars_all"                           top="0"                           width="285" />                      </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4560a7138c..27b34d16a8 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -413,6 +413,10 @@ this texture in your inventory  	<string name="InvFolder Current Outfit">Current Outfit</string>  	<string name="InvFolder My Outfits">My Outfits</string> +  <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694--> +	<string name="InvFolder Friends">Friends</string> +	<string name="InvFolder All">All</string> +  	<!-- inventory FVBridge -->  	<string name="Buy">Buy</string>  	<string name="BuyforL$">Buy for L$</string>  | 
