llavatarlist.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llavatarlist.h
  3.  * @brief Generic avatar list
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llavatarlist.h"
  34. #include "llagentdata.h" // for comparator
  35. // newview
  36. #include "llcallingcard.h" // for LLAvatarTracker
  37. #include "llcachename.h"
  38. #include "llrecentpeople.h"
  39. #include "llvoiceclient.h"
  40. #include "llviewercontrol.h" // for gSavedSettings
  41. static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
  42. // Last interaction time update period.
  43. static const F32 LIT_UPDATE_PERIOD = 5;
  44. // Maximum number of avatars that can be added to a list in one pass.
  45. // Used to limit time spent for avatar list update per frame.
  46. static const unsigned ADD_LIMIT = 50;
  47. bool LLAvatarList::contains(const LLUUID& id)
  48. {
  49. const uuid_vector_t& ids = getIDs();
  50. return std::find(ids.begin(), ids.end(), id) != ids.end();
  51. }
  52. void LLAvatarList::toggleIcons()
  53. {
  54. // Save the new value for new items to use.
  55. mShowIcons = !mShowIcons;
  56. gSavedSettings.setBOOL(mIconParamName, mShowIcons);
  57. // Show/hide icons for all existing items.
  58. std::vector<LLPanel*> items;
  59. getItems(items);
  60. for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
  61. {
  62. static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
  63. }
  64. }
  65. void LLAvatarList::setSpeakingIndicatorsVisible(bool visible)
  66. {
  67. // Save the new value for new items to use.
  68. mShowSpeakingIndicator = visible;
  69. // Show/hide icons for all existing items.
  70. std::vector<LLPanel*> items;
  71. getItems(items);
  72. for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
  73. {
  74. static_cast<LLAvatarListItem*>(*it)->showSpeakingIndicator(mShowSpeakingIndicator);
  75. }
  76. }
  77. static bool findInsensitive(std::string haystack, const std::string& needle_upper)
  78. {
  79.     LLStringUtil::toUpper(haystack);
  80.     return haystack.find(needle_upper) != std::string::npos;
  81. }
  82. //comparators
  83. static const LLAvatarItemNameComparator NAME_COMPARATOR;
  84. static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR);
  85. LLAvatarList::Params::Params()
  86. : ignore_online_status("ignore_online_status", false)
  87. , show_last_interaction_time("show_last_interaction_time", false)
  88. , show_info_btn("show_info_btn", true)
  89. , show_profile_btn("show_profile_btn", true)
  90. , show_speaking_indicator("show_speaking_indicator", true)
  91. {
  92. }
  93. LLAvatarList::LLAvatarList(const Params& p)
  94. : LLFlatListView(p)
  95. , mIgnoreOnlineStatus(p.ignore_online_status)
  96. , mShowLastInteractionTime(p.show_last_interaction_time)
  97. , mContextMenu(NULL)
  98. , mDirty(true) // to force initial update
  99. , mLITUpdateTimer(NULL)
  100. , mShowIcons(true)
  101. , mShowInfoBtn(p.show_info_btn)
  102. , mShowProfileBtn(p.show_profile_btn)
  103. , mShowSpeakingIndicator(p.show_speaking_indicator)
  104. {
  105. setCommitOnSelectionChange(true);
  106. // Set default sort order.
  107. setComparator(&NAME_COMPARATOR);
  108. if (mShowLastInteractionTime)
  109. {
  110. mLITUpdateTimer = new LLTimer();
  111. mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
  112. mLITUpdateTimer->start();
  113. }
  114. }
  115. LLAvatarList::~LLAvatarList()
  116. {
  117. delete mLITUpdateTimer;
  118. }
  119. void LLAvatarList::setShowIcons(std::string param_name)
  120. {
  121. mIconParamName= param_name;
  122. mShowIcons = gSavedSettings.getBOOL(mIconParamName);
  123. }
  124. // virtual
  125. void LLAvatarList::draw()
  126. {
  127. // *NOTE dzaporozhan
  128. // Call refresh() after draw() to avoid flickering of avatar list items.
  129. LLFlatListView::draw();
  130. if (mDirty)
  131. refresh();
  132. if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
  133. {
  134. updateLastInteractionTimes();
  135. mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
  136. }
  137. }
  138. //virtual
  139. void LLAvatarList::clear()
  140. {
  141. getIDs().clear();
  142. setDirty(true);
  143. LLFlatListView::clear();
  144. }
  145. void LLAvatarList::setNameFilter(const std::string& filter)
  146. {
  147. if (mNameFilter != filter)
  148. {
  149. mNameFilter = filter;
  150. setDirty();
  151. }
  152. }
  153. void LLAvatarList::sortByName()
  154. {
  155. setComparator(&NAME_COMPARATOR);
  156. sort();
  157. }
  158. //////////////////////////////////////////////////////////////////////////
  159. // PROTECTED SECTION
  160. //////////////////////////////////////////////////////////////////////////
  161. void LLAvatarList::refresh()
  162. {
  163. bool have_names = TRUE;
  164. bool add_limit_exceeded = false;
  165. bool modified = false;
  166. bool have_filter = !mNameFilter.empty();
  167. // Save selection.
  168. std::vector<LLUUID> selected_ids;
  169. getSelectedUUIDs(selected_ids);
  170. LLUUID current_id = getSelectedUUID();
  171. // Determine what to add and what to remove.
  172. std::vector<LLUUID> added, removed;
  173. LLAvatarList::computeDifference(getIDs(), added, removed);
  174. // Handle added items.
  175. unsigned nadded = 0;
  176. for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
  177. {
  178. std::string name;
  179. const LLUUID& buddy_id = *it;
  180. have_names &= (bool)gCacheName->getFullName(buddy_id, name);
  181. if (!have_filter || findInsensitive(name, mNameFilter))
  182. {
  183. if (nadded >= ADD_LIMIT)
  184. {
  185. add_limit_exceeded = true;
  186. break;
  187. }
  188. else
  189. {
  190. addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
  191. modified = true;
  192. nadded++;
  193. }
  194. }
  195. }
  196. // Handle removed items.
  197. for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
  198. {
  199. removeItemByUUID(*it);
  200. modified = true;
  201. }
  202. // Handle filter.
  203. if (have_filter)
  204. {
  205. std::vector<LLSD> cur_values;
  206. getValues(cur_values);
  207. for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
  208. {
  209. std::string name;
  210. const LLUUID& buddy_id = it->asUUID();
  211. have_names &= (bool)gCacheName->getFullName(buddy_id, name);
  212. if (!findInsensitive(name, mNameFilter))
  213. {
  214. removeItemByUUID(buddy_id);
  215. modified = true;
  216. }
  217. }
  218. }
  219. // Changed item in place, need to request sort and update columns
  220. // because we might have changed data in a column on which the user
  221. // has already sorted. JC
  222. sort();
  223. // re-select items
  224. // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
  225. selectItemByUUID(current_id);
  226. // If the name filter is specified and the names are incomplete,
  227. // we need to re-update when the names are complete so that
  228. // the filter can be applied correctly.
  229. //
  230. // Otherwise, if we have no filter then no need to update again
  231. // because the items will update their names.
  232. bool dirty = add_limit_exceeded || (have_filter && !have_names);
  233. setDirty(dirty);
  234. // Refreshed all items.
  235. if(!dirty)
  236. {
  237. // Highlight items matching the filter.
  238. std::vector<LLPanel*> items;
  239. getItems(items);
  240. for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
  241. {
  242. static_cast<LLAvatarListItem*>(*it)->setHighlight(mNameFilter);
  243. }
  244. // Send refresh_complete signal.
  245. std::vector<LLSD> cur_values;
  246. getValues(cur_values);
  247. mRefreshCompleteSignal(this, LLSD((S32)cur_values.size()));
  248. }
  249. // Commit if we've added/removed items.
  250. if (modified)
  251. onCommit();
  252. }
  253. bool LLAvatarList::filterHasMatches()
  254. {
  255. uuid_vector_t values = getIDs();
  256. for (uuid_vector_t::const_iterator it=values.begin(); it != values.end(); it++)
  257. {
  258. std::string name;
  259. const LLUUID& buddy_id = *it;
  260. BOOL have_name = gCacheName->getFullName(buddy_id, name);
  261. // If name has not been loaded yet we consider it as a match.
  262. // When the name will be loaded the filter will be applied again(in refresh()).
  263. if (have_name && !findInsensitive(name, mNameFilter))
  264. {
  265. continue;
  266. }
  267. return true;
  268. }
  269. return false;
  270. }
  271. boost::signals2::connection LLAvatarList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb)
  272. {
  273. return mRefreshCompleteSignal.connect(cb);
  274. }
  275. boost::signals2::connection LLAvatarList::setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb)
  276. {
  277. return mItemDoubleClickSignal.connect(cb);
  278. }
  279. void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
  280. {
  281. LLAvatarListItem* item = new LLAvatarListItem();
  282. item->setName(name);
  283. item->setAvatarId(id, mIgnoreOnlineStatus);
  284. item->setOnline(mIgnoreOnlineStatus ? true : is_online);
  285. item->showLastInteractionTime(mShowLastInteractionTime);
  286. item->setAvatarIconVisible(mShowIcons);
  287. item->setShowInfoBtn(mShowInfoBtn);
  288. item->setShowProfileBtn(mShowProfileBtn);
  289. item->showSpeakingIndicator(mShowSpeakingIndicator);
  290. item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoucleClicked, this, _1, _2, _3, _4));
  291. addItem(item, id, pos);
  292. }
  293. // virtual
  294. BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
  295. {
  296. BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
  297. if ( mContextMenu )
  298. {
  299. std::vector<LLUUID> selected_uuids;
  300. getSelectedUUIDs(selected_uuids);
  301. mContextMenu->show(this, selected_uuids, x, y);
  302. }
  303. return handled;
  304. }
  305. void LLAvatarList::computeDifference(
  306. const std::vector<LLUUID>& vnew_unsorted,
  307. std::vector<LLUUID>& vadded,
  308. std::vector<LLUUID>& vremoved)
  309. {
  310. std::vector<LLUUID> vcur;
  311. std::vector<LLUUID> vnew = vnew_unsorted;
  312. // Convert LLSDs to LLUUIDs.
  313. {
  314. std::vector<LLSD> vcur_values;
  315. getValues(vcur_values);
  316. for (size_t i=0; i<vcur_values.size(); i++)
  317. vcur.push_back(vcur_values[i].asUUID());
  318. }
  319. std::sort(vcur.begin(), vcur.end());
  320. std::sort(vnew.begin(), vnew.end());
  321. std::vector<LLUUID>::iterator it;
  322. size_t maxsize = llmax(vcur.size(), vnew.size());
  323. vadded.resize(maxsize);
  324. vremoved.resize(maxsize);
  325. // what to remove
  326. it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin());
  327. vremoved.erase(it, vremoved.end());
  328. // what to add
  329. it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin());
  330. vadded.erase(it, vadded.end());
  331. }
  332. // Refresh shown time of our last interaction with all listed avatars.
  333. void LLAvatarList::updateLastInteractionTimes()
  334. {
  335. S32 now = (S32) LLDate::now().secondsSinceEpoch();
  336. std::vector<LLPanel*> items;
  337. getItems(items);
  338. for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
  339. {
  340. // *TODO: error handling
  341. LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
  342. S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch();
  343. if (secs_since >= 0)
  344. item->setLastInteractionTime(secs_since);
  345. }
  346. }
  347. void LLAvatarList::onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
  348. {
  349. mItemDoubleClickSignal(ctrl, x, y, mask);
  350. }
  351. bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
  352. {
  353. const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
  354. const LLAvatarListItem* avatar_item2 = dynamic_cast<const LLAvatarListItem*>(item2);
  355. if (!avatar_item1 || !avatar_item2)
  356. {
  357. llerror("item1 and item2 cannot be null", 0);
  358. return true;
  359. }
  360. return doCompare(avatar_item1, avatar_item2);
  361. }
  362. bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
  363. {
  364. std::string name1 = avatar_item1->getAvatarName();
  365. std::string name2 = avatar_item2->getAvatarName();
  366. LLStringUtil::toUpper(name1);
  367. LLStringUtil::toUpper(name2);
  368. return name1 < name2;
  369. }
  370. bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
  371. {
  372. //keep agent on top, if first is agent, 
  373. //then we need to return true to elevate this id, otherwise false.
  374. if(avatar_item1->getAvatarId() == gAgentID)
  375. {
  376. return true;
  377. }
  378. else if (avatar_item2->getAvatarId() == gAgentID)
  379. {
  380. return false;
  381. }
  382. return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2);
  383. }