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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llparticipantlist.cpp
  3.  * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages
  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. // common includes
  34. #include "lltrans.h"
  35. #include "llavataractions.h"
  36. #include "llagent.h"
  37. #include "llparticipantlist.h"
  38. #include "llspeakers.h"
  39. #include "llviewermenu.h"
  40. #include "llvoiceclient.h"
  41. //LLParticipantList retrieves add, clear and remove events and updates view accordingly 
  42. #if LL_MSVC
  43. #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
  44. #endif
  45. static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR;
  46. LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/,
  47. bool exclude_agent /*= true*/):
  48. mSpeakerMgr(data_source),
  49. mAvatarList(avatar_list),
  50. mSortOrder(E_SORT_BY_NAME)
  51. , mParticipantListMenu(NULL)
  52. , mExcludeAgent(exclude_agent)
  53. , mValidateSpeakerCallback(NULL)
  54. {
  55. mSpeakerAddListener = new SpeakerAddListener(*this);
  56. mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
  57. mSpeakerClearListener = new SpeakerClearListener(*this);
  58. mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
  59. mSpeakerMuteListener = new SpeakerMuteListener(*this);
  60. mSpeakerMgr->addListener(mSpeakerAddListener, "add");
  61. mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
  62. mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
  63. mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
  64. mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
  65. mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1));
  66. mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2));
  67.     // Set onAvatarListDoubleClicked as default on_return action.
  68. mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));
  69. if (use_context_menu)
  70. {
  71. mParticipantListMenu = new LLParticipantListMenu(*this);
  72. mAvatarList->setContextMenu(mParticipantListMenu);
  73. }
  74. else
  75. {
  76. mAvatarList->setContextMenu(NULL);
  77. }
  78. //Lets fill avatarList with existing speakers
  79. LLSpeakerMgr::speaker_list_t speaker_list;
  80. mSpeakerMgr->getSpeakerList(&speaker_list, true);
  81. for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
  82. {
  83. const LLPointer<LLSpeaker>& speakerp = *it;
  84. addAvatarIDExceptAgent(speakerp->mID);
  85. if ( speakerp->mIsModerator )
  86. {
  87. mModeratorList.insert(speakerp->mID);
  88. }
  89. else
  90. {
  91. mModeratorToRemoveList.insert(speakerp->mID);
  92. }
  93. }
  94. // we need to exclude agent id for non group chat
  95. sort();
  96. }
  97. LLParticipantList::~LLParticipantList()
  98. {
  99. mAvatarListDoubleClickConnection.disconnect();
  100. mAvatarListRefreshConnection.disconnect();
  101. mAvatarListReturnConnection.disconnect();
  102. // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged()
  103. // See ticket EXT-3427
  104. // hide menu before deleting it to stop enable and check handlers from triggering.
  105. if(mParticipantListMenu && !LLApp::isExiting())
  106. {
  107. mParticipantListMenu->hide();
  108. }
  109. if (mParticipantListMenu)
  110. {
  111. delete mParticipantListMenu;
  112. mParticipantListMenu = NULL;
  113. }
  114. mAvatarList->setContextMenu(NULL);
  115. }
  116. void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
  117. {
  118. mAvatarList->setSpeakingIndicatorsVisible(visible);
  119. };
  120. void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl)
  121. {
  122. LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl);
  123. if(!item)
  124. {
  125. return;
  126. }
  127. LLUUID clicked_id = item->getAvatarId();
  128. if (clicked_id.isNull() || clicked_id == gAgent.getID())
  129. return;
  130. LLAvatarActions::startIM(clicked_id);
  131. }
  132. void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
  133. {
  134. LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl);
  135. if (list)
  136. {
  137. const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); 
  138. const std::size_t moderator_indicator_len = moderator_indicator.length();
  139. // Firstly remove moderators indicator
  140. std::set<LLUUID>::const_iterator
  141. moderator_list_it = mModeratorToRemoveList.begin(),
  142. moderator_list_end = mModeratorToRemoveList.end();
  143. for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
  144. {
  145. LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
  146. if ( item )
  147. {
  148. std::string name = item->getAvatarName();
  149. size_t found = name.find(moderator_indicator);
  150. if (found != std::string::npos)
  151. {
  152. name.erase(found, moderator_indicator_len);
  153. item->setName(name);
  154. }
  155. }
  156. }
  157. mModeratorToRemoveList.clear();
  158. // Add moderators indicator
  159. moderator_list_it = mModeratorList.begin();
  160. moderator_list_end = mModeratorList.end();
  161. for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
  162. {
  163. LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
  164. if ( item )
  165. {
  166. std::string name = item->getAvatarName();
  167. size_t found = name.find(moderator_indicator);
  168. if (found == std::string::npos)
  169. {
  170. name += " ";
  171. name += moderator_indicator;
  172. item->setName(name);
  173. }
  174. }
  175. }
  176. }
  177. }
  178. void LLParticipantList::setSortOrder(EParticipantSortOrder order)
  179. {
  180. if ( mSortOrder != order )
  181. {
  182. mSortOrder = order;
  183. sort();
  184. }
  185. }
  186. LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
  187. {
  188. return mSortOrder;
  189. }
  190. void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
  191. {
  192. mValidateSpeakerCallback = cb;
  193. }
  194. void LLParticipantList::updateRecentSpeakersOrder()
  195. {
  196. if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
  197. {
  198. // Need to update speakers to sort list correctly
  199. mSpeakerMgr->update(true);
  200. // Resort avatar list
  201. sort();
  202. }
  203. }
  204. bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  205. {
  206. LLUUID uu_id = event->getValue().asUUID();
  207. if (mValidateSpeakerCallback && !mValidateSpeakerCallback(uu_id))
  208. {
  209. return true;
  210. }
  211. addAvatarIDExceptAgent(uu_id);
  212. sort();
  213. return true;
  214. }
  215. bool LLParticipantList::onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  216. {
  217. LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
  218. LLAvatarList::uuid_vector_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID());
  219. if(pos != group_members.end())
  220. {
  221. group_members.erase(pos);
  222. mAvatarList->setDirty();
  223. }
  224. return true;
  225. }
  226. bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  227. {
  228. LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
  229. group_members.clear();
  230. mAvatarList->setDirty();
  231. return true;
  232. }
  233. bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  234. {
  235. const LLSD& evt_data = event->getValue();
  236. if ( evt_data.has("id") && evt_data.has("is_moderator") )
  237. {
  238. LLUUID id = evt_data["id"];
  239. bool is_moderator = evt_data["is_moderator"];
  240. if ( id.notNull() )
  241. {
  242. if ( is_moderator )
  243. mModeratorList.insert(id);
  244. else
  245. {
  246. std::set<LLUUID>::iterator it = mModeratorList.find (id);
  247. if ( it != mModeratorList.end () )
  248. {
  249. mModeratorToRemoveList.insert(id);
  250. mModeratorList.erase(id);
  251. }
  252. }
  253. // apply changes immediately
  254. onAvatarListRefreshed(mAvatarList, LLSD());
  255. }
  256. }
  257. return true;
  258. }
  259. bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  260. {
  261. LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource();
  262. if (speakerp.isNull()) return false;
  263. // update UI on confirmation of moderator mutes
  264. if (event->getValue().asString() == "voice")
  265. {
  266. LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID));
  267. if (item)
  268. {
  269. LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator");
  270. indicator->setIsMuted(speakerp->mModeratorMutedVoice);
  271. }
  272. }
  273. return true;
  274. }
  275. void LLParticipantList::sort()
  276. {
  277. if ( !mAvatarList )
  278. return;
  279. switch ( mSortOrder ) {
  280. case E_SORT_BY_NAME :
  281. // if mExcludeAgent == true , then no need to keep agent on top of the list
  282. if(mExcludeAgent)
  283. {
  284. mAvatarList->sortByName();
  285. }
  286. else
  287. {
  288. mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
  289. mAvatarList->sort();
  290. }
  291. break;
  292. case E_SORT_BY_RECENT_SPEAKERS:
  293. if (mSortByRecentSpeakers.isNull())
  294. mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
  295. mAvatarList->setComparator(mSortByRecentSpeakers.get());
  296. mAvatarList->sort();
  297. break;
  298. default :
  299. llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
  300. return;
  301. }
  302. }
  303. void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
  304. {
  305. if (mExcludeAgent && gAgent.getID() == avatar_id) return;
  306. if (mAvatarList->contains(avatar_id)) return;
  307. mAvatarList->getIDs().push_back(avatar_id);
  308. mAvatarList->setDirty();
  309. adjustParticipant(avatar_id);
  310. }
  311. void LLParticipantList::adjustParticipant(const LLUUID& speaker_id)
  312. {
  313. LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id);
  314. if (speakerp.isNull()) return;
  315. // add listener to process moderation changes
  316. speakerp->addListener(mSpeakerMuteListener);
  317. }
  318. //
  319. // LLParticipantList::SpeakerAddListener
  320. //
  321. bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  322. {
  323. /**
  324.  * We need to filter speaking objects. These objects shouldn't appear in the list
  325.  * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
  326.  */
  327. const LLUUID& speaker_id = event->getValue().asUUID();
  328. LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id);
  329. if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT)
  330. {
  331. return false;
  332. }
  333. return mParent.onAddItemEvent(event, userdata);
  334. }
  335. //
  336. // LLParticipantList::SpeakerRemoveListener
  337. //
  338. bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  339. {
  340. return mParent.onRemoveItemEvent(event, userdata);
  341. }
  342. //
  343. // LLParticipantList::SpeakerClearListener
  344. //
  345. bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  346. {
  347. return mParent.onClearListEvent(event, userdata);
  348. }
  349. //
  350. // LLParticipantList::SpeakerModeratorListener
  351. //
  352. bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  353. {
  354. return mParent.onModeratorUpdateEvent(event, userdata);
  355. }
  356. bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
  357. {
  358. return mParent.onSpeakerMuteEvent(event, userdata);
  359. }
  360. LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
  361. {
  362. // set up the callbacks for all of the avatar menu items
  363. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  364. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  365. registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2));
  366. registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2));
  367. registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2));
  368. registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mUUIDs.front()));
  369. registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front()));
  370. registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front()));
  371. registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2));
  372. registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front()));
  373. registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front()));
  374. registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front()));
  375. registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2));
  376. enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2));
  377. enable_registrar.add("ParticipantList.CheckItem",  boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2));
  378. // create the context menu from the XUI
  379. LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
  380. "menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
  381. // Don't show sort options for P2P chat
  382. bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
  383. main_menu->setItemVisible("SortByName", is_sort_visible);
  384. main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);
  385. main_menu->setItemVisible("Moderator Options", isGroupModerator());
  386. main_menu->arrangeAndClear();
  387. return main_menu;
  388. }
  389. void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y)
  390. {
  391. LLPanelPeopleMenus::ContextMenu::show(spawning_view, uuids, x, y);
  392. if (uuids.size() == 0) return;
  393. const LLUUID speaker_id = mUUIDs.front();
  394. BOOL is_muted = isMuted(speaker_id);
  395. if (is_muted)
  396. {
  397. LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteSelected", false);
  398. LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteOthers", false);
  399. }
  400. else
  401. {
  402. LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);
  403. LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);
  404. }
  405. }
  406. void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata)
  407. {
  408. std::string param = userdata.asString();
  409. if ("sort_by_name" == param)
  410. {
  411. mParent.setSortOrder(E_SORT_BY_NAME);
  412. }
  413. else if ("sort_by_recent_speakers" == param)
  414. {
  415. mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS);
  416. }
  417. }
  418. void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata)
  419. {
  420. LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
  421. if (mgr)
  422. {
  423. const LLUUID speaker_id = mUUIDs.front();
  424. mgr->toggleAllowTextChat(speaker_id);
  425. }
  426. }
  427. void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags)
  428. {
  429. const LLUUID speaker_id = mUUIDs.front();
  430. BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags);
  431. std::string name;
  432. //fill in name using voice client's copy of name cache
  433. LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id);
  434. if (speakerp.isNull())
  435. {
  436. return;
  437. }
  438. name = speakerp->mDisplayName;
  439. LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT);
  440. if (!is_muted)
  441. {
  442. LLMuteList::getInstance()->add(mute, flags);
  443. }
  444. else
  445. {
  446. LLMuteList::getInstance()->remove(mute, flags);
  447. }
  448. }
  449. void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata)
  450. {
  451. toggleMute(userdata, LLMute::flagTextChat);
  452. }
  453. void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata)
  454. {
  455. toggleMute(userdata, LLMute::flagVoiceChat);
  456. }
  457. bool LLParticipantList::LLParticipantListMenu::isGroupModerator()
  458. {
  459. // Agent is in Group Call
  460. if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID()))
  461. {
  462. // Agent is Moderator
  463. return mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator;
  464. }
  465. return false;
  466. }
  467. bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id)
  468. {
  469. LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id);
  470. if (!selected_speakerp) return true;
  471. return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED;
  472. }
  473. void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata)
  474. {
  475. if (!gAgent.getRegion()) return;
  476. bool moderate_selected = userdata.asString() == "selected";
  477. const LLUUID& selected_avatar_id = mUUIDs.front();
  478. bool is_muted = isMuted(selected_avatar_id);
  479. if (moderate_selected)
  480. {
  481. moderateVoiceParticipant(selected_avatar_id, is_muted);
  482. }
  483. else
  484. {
  485. moderateVoiceOtherParticipants(selected_avatar_id, is_muted);
  486. }
  487. }
  488. void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)
  489. {
  490. LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
  491. if (mgr)
  492. {
  493. mgr->moderateVoiceParticipant(avatar_id, unmute);
  494. }
  495. }
  496. void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute)
  497. {
  498. LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
  499. if (mgr)
  500. {
  501. mgr->moderateVoiceOtherParticipants(excluded_avatar_id, unmute);
  502. }
  503. }
  504. bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata)
  505. {
  506. std::string item = userdata.asString();
  507. if (item == "can_mute_text" || "can_block" == item || "can_share" == item || "can_im" == item 
  508. || "can_pay" == item)
  509. {
  510. return mUUIDs.front() != gAgentID;
  511. }
  512. else if (item == "can_allow_text_chat")
  513. {
  514. return isGroupModerator();
  515. }
  516. else if ("can_moderate_voice" == item)
  517. {
  518. if (isGroupModerator())
  519. {
  520. LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front());
  521. if (speakerp.notNull())
  522. {
  523. // not in voice participants can not be moderated
  524. return speakerp->isInVoiceChannel();
  525. }
  526. }
  527. return false;
  528. }
  529. else if (item == std::string("can_add"))
  530. {
  531. // We can add friends if:
  532. // - there are selected people
  533. // - and there are no friends among selection yet.
  534. bool result = (mUUIDs.size() > 0);
  535. std::vector<LLUUID>::const_iterator
  536. id = mUUIDs.begin(),
  537. uuids_end = mUUIDs.end();
  538. for (;id != uuids_end; ++id)
  539. {
  540. if ( *id == gAgentID || LLAvatarActions::isFriend(*id) )
  541. {
  542. result = false;
  543. break;
  544. }
  545. }
  546. return result;
  547. }
  548. else if (item == "can_call")
  549. {
  550. bool not_agent = mUUIDs.front() != gAgentID;
  551. bool can_call = not_agent && LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
  552. return can_call;
  553. }
  554. return true;
  555. }
  556. bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& userdata)
  557. {
  558. std::string item = userdata.asString();
  559. const LLUUID& id = mUUIDs.front();
  560. if (item == "is_muted")
  561. {
  562. return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat);
  563. }
  564. else if (item == "is_allowed_text_chat")
  565. {
  566. LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id);
  567. if (selected_speakerp.notNull())
  568. {
  569. return !selected_speakerp->mModeratorMutedText;
  570. }
  571. }
  572. else if(item == "is_blocked")
  573. {
  574. return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat);
  575. }
  576. else if(item == "is_sorted_by_name")
  577. {
  578. return E_SORT_BY_NAME == mParent.mSortOrder;
  579. }
  580. else if(item == "is_sorted_by_recent_speakers")
  581. {
  582. return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder;
  583. }
  584. return false;
  585. }
  586. bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
  587. {
  588. if (mParent.mSpeakerMgr)
  589. {
  590. LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId());
  591. LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId());
  592. if ( lhs.notNull() && rhs.notNull() )
  593. {
  594. // Compare by last speaking time
  595. if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
  596. return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
  597. else if ( lhs->mSortIndex != rhs->mSortIndex )
  598. return ( lhs->mSortIndex < rhs->mSortIndex );
  599. }
  600. else if ( lhs.notNull() )
  601. {
  602. // True if only avatar_item1 speaker info available
  603. return true;
  604. }
  605. else if ( rhs.notNull() )
  606. {
  607. // False if only avatar_item2 speaker info available
  608. return false;
  609. }
  610. }
  611. // By default compare by name.
  612. return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2);
  613. }
  614. //EOF