PageRenderTime 52ms CodeModel.GetById 1ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llavatariconctrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 310 lines | 214 code | 50 blank | 46 comment | 37 complexity | 2092eb35d110bc4875c5c350c4f1f8b0 MD5 | raw file
  1/** 
  2 * @file llavatariconctrl.cpp
  3 * @brief LLAvatarIconCtrl class implementation
  4 *
  5 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llavatariconctrl.h"
 30
 31// viewer includes
 32#include "llagent.h"
 33#include "llavatarconstants.h"
 34#include "llcallingcard.h" // for LLAvatarTracker
 35#include "llavataractions.h"
 36#include "llmenugl.h"
 37#include "lluictrlfactory.h"
 38#include "llagentdata.h"
 39#include "llimfloater.h"
 40
 41// library includes
 42#include "llavatarnamecache.h"
 43
 44#define MENU_ITEM_VIEW_PROFILE 0
 45#define MENU_ITEM_SEND_IM 1
 46
 47static LLDefaultChildRegistry::Register<LLAvatarIconCtrl> r("avatar_icon");
 48
 49bool LLAvatarIconIDCache::LLAvatarIconIDCacheItem::expired()
 50{
 51	const F64 SEC_PER_DAY_PLUS_HOUR = (24.0 + 1.0) * 60.0 * 60.0;
 52	F64 delta = LLDate::now().secondsSinceEpoch() - cached_time.secondsSinceEpoch();
 53	if (delta > SEC_PER_DAY_PLUS_HOUR)
 54		return true;
 55	return false;
 56}
 57
 58void LLAvatarIconIDCache::load	()
 59{
 60	llinfos << "Loading avatar icon id cache." << llendl;
 61	
 62	// build filename for each user
 63	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename);
 64	llifstream file(resolved_filename);
 65
 66	if (!file.is_open())
 67		return;
 68	
 69	// add each line in the file to the list
 70	int uuid_len = UUID_STR_LENGTH-1;
 71	std::string line;
 72	while (std::getline(file, line)) 
 73	{
 74		LLUUID avatar_id;
 75		LLUUID icon_id;
 76		LLDate date;
 77
 78		if (line.length()<=uuid_len*2)
 79			continue; // short line, bail out to prevent substr calls throwing exception.
 80
 81		std::string avatar_id_str = line.substr(0,uuid_len);
 82		std::string icon_id_str = line.substr(uuid_len,uuid_len);
 83		
 84		std::string date_str = line.substr(uuid_len*2, line.length()-uuid_len*2);
 85
 86		if(!avatar_id.set(avatar_id_str) || !icon_id.set(icon_id_str) || !date.fromString(date_str))
 87			continue;
 88
 89		LLAvatarIconIDCacheItem item = {icon_id,date};
 90		mCache[avatar_id] = item;
 91	}
 92
 93	file.close();
 94	
 95}
 96
 97void LLAvatarIconIDCache::save	()
 98{
 99	std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename);
100
101	// open a file for writing
102	llofstream file (resolved_filename);
103	if (!file.is_open())
104	{
105		llwarns << "can't open avatar icons cache file\"" << mFilename << "\" for writing" << llendl;
106		return;
107	}
108
109	for(std::map<LLUUID,LLAvatarIconIDCacheItem>::iterator it = mCache.begin();it!=mCache.end();++it)
110	{
111		if(!it->second.expired())
112		{
113			file << it->first << it->second.icon_id << it->second.cached_time << std::endl;	
114		}
115	}
116	
117	file.close();
118}
119
120LLUUID*	LLAvatarIconIDCache::get		(const LLUUID& avatar_id)
121{
122	std::map<LLUUID,LLAvatarIconIDCacheItem>::iterator it = mCache.find(avatar_id);
123	if(it==mCache.end())
124		return 0;
125	if(it->second.expired())
126		return 0;
127	return &it->second.icon_id;
128}
129
130void LLAvatarIconIDCache::add		(const LLUUID& avatar_id,const LLUUID& icon_id)
131{
132	LLAvatarIconIDCacheItem item = {icon_id,LLDate::now()};
133	mCache[avatar_id] = item;
134}
135
136void LLAvatarIconIDCache::remove	(const LLUUID& avatar_id)
137{
138	mCache.erase(avatar_id);
139}
140
141
142LLAvatarIconCtrl::Params::Params()
143:	avatar_id("avatar_id"),
144	draw_tooltip("draw_tooltip", true),
145	default_icon_name("default_icon_name")
146{
147}
148
149
150LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
151:	LLIconCtrl(p),
152	mDrawTooltip(p.draw_tooltip),
153	mDefaultIconName(p.default_icon_name)
154{
155	mPriority = LLViewerFetchedTexture::BOOST_ICON;
156	
157	LLRect rect = p.rect;
158	mDrawWidth  = llmax(32, rect.getWidth()) ;
159	mDrawHeight = llmax(32, rect.getHeight()) ;
160
161	static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2);
162	static LLUICachedControl<S32> llavatariconctrl_symbol_vpad("UIAvatariconctrlSymbolVPad", 2);
163	static LLUICachedControl<S32> llavatariconctrl_symbol_size("UIAvatariconctrlSymbolSize", 5);
164	static LLUICachedControl<std::string> llavatariconctrl_symbol_pos("UIAvatariconctrlSymbolPosition", "BottomRight");
165
166	// BottomRight is the default position
167	S32 left = rect.getWidth() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_hpad;
168	S32 bottom = llavatariconctrl_symbol_vpad;
169
170	if ("BottomLeft" == (std::string)llavatariconctrl_symbol_pos)
171	{
172		left = llavatariconctrl_symbol_hpad;
173		bottom = llavatariconctrl_symbol_vpad;
174	}
175	else if ("TopLeft" == (std::string)llavatariconctrl_symbol_pos)
176	{
177		left = llavatariconctrl_symbol_hpad;
178		bottom = rect.getHeight() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_vpad;
179	}
180	else if ("TopRight" == (std::string)llavatariconctrl_symbol_pos)
181	{
182		left = rect.getWidth() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_hpad;
183		bottom = rect.getHeight() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_vpad;
184	}
185
186	rect.setOriginAndSize(left, bottom, llavatariconctrl_symbol_size, llavatariconctrl_symbol_size);
187
188	if (p.avatar_id.isProvided())
189	{
190		LLSD value(p.avatar_id);
191		setValue(value);
192	}
193	else
194	{
195		LLIconCtrl::setValue(mDefaultIconName);
196	}
197}
198
199LLAvatarIconCtrl::~LLAvatarIconCtrl()
200{
201	if (mAvatarId.notNull())
202	{
203		LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this);
204		// Name callbacks will be automatically disconnected since LLUICtrl is trackable
205	}
206}
207
208//virtual
209void LLAvatarIconCtrl::setValue(const LLSD& value)
210{
211	if (value.isUUID())
212	{
213		LLAvatarPropertiesProcessor* app =
214			LLAvatarPropertiesProcessor::getInstance();
215		if (mAvatarId.notNull())
216		{
217			app->removeObserver(mAvatarId, this);
218		}
219
220		if (mAvatarId != value.asUUID())
221		{
222			mAvatarId = value.asUUID();
223
224			// *BUG: This will return stale icons if a user changes their
225			// profile picture. However, otherwise we send too many upstream
226			// AvatarPropertiesRequest messages.
227
228			// to get fresh avatar icon use
229			// LLAvatarIconIDCache::getInstance()->remove(avatar_id);
230
231			// Check if cache already contains image_id for that avatar
232			if (!updateFromCache())
233			{
234				// *TODO: Consider getting avatar icon/badge directly from 
235				// People API, rather than sending AvatarPropertyRequest
236				// messages.  People API already hits the user table.
237				LLIconCtrl::setValue(mDefaultIconName);
238				app->addObserver(mAvatarId, this);
239				app->sendAvatarPropertiesRequest(mAvatarId);
240			}
241		}
242	}
243	else
244	{
245		LLIconCtrl::setValue(value);
246	}
247
248	LLAvatarNameCache::get(mAvatarId,
249		boost::bind(&LLAvatarIconCtrl::onAvatarNameCache, 
250			this, _1, _2));
251}
252
253bool LLAvatarIconCtrl::updateFromCache()
254{
255	LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(mAvatarId);
256	if(!icon_id_ptr)
257		return false;
258
259	const LLUUID& icon_id = *icon_id_ptr;
260
261	// Update the avatar
262	if (icon_id.notNull())
263	{
264		LLIconCtrl::setValue(icon_id);
265	}
266	else
267	{
268		LLIconCtrl::setValue(mDefaultIconName);
269	}
270
271	return true;
272}
273
274//virtual
275void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
276{
277	if (APT_PROPERTIES == type)
278	{
279		LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
280		if (avatar_data)
281		{
282			if (avatar_data->avatar_id != mAvatarId)
283			{
284				return;
285			}
286
287			LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id);
288			updateFromCache();
289		}
290	}
291}
292
293void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
294{
295	if (agent_id == mAvatarId)
296	{
297		// Most avatar icon controls are next to a UI element that shows
298		// a display name, so only show username.
299		mFullName = av_name.mUsername;
300
301		if (mDrawTooltip)
302		{
303			setToolTip(mFullName);
304		}
305		else
306		{
307			setToolTip(std::string());
308		}
309	}
310}