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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloaterfriends.cpp
  3.  * @author Phoenix
  4.  * @date 2005-01-13
  5.  * @brief Implementation of the friends floater
  6.  *
  7.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2005-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "llviewerprecompiledheaders.h"
  35. #include "llfloaterfriends.h"
  36. #include <sstream>
  37. #include "lldir.h"
  38. #include "llagent.h"
  39. #include "llappviewer.h" // for gLastVersionChannel
  40. #include "llfloateravatarpicker.h"
  41. #include "llviewerwindow.h"
  42. #include "llbutton.h"
  43. #include "llavataractions.h"
  44. #include "llinventorymodel.h"
  45. #include "llnamelistctrl.h"
  46. #include "llnotificationsutil.h"
  47. #include "llresmgr.h"
  48. #include "llscrolllistctrl.h"
  49. #include "llscrolllistitem.h"
  50. #include "llscrolllistcell.h"
  51. #include "lluictrlfactory.h"
  52. #include "llmenucommands.h"
  53. #include "llviewercontrol.h"
  54. #include "llviewermessage.h"
  55. #include "lleventtimer.h"
  56. #include "lltextbox.h"
  57. #include "llvoiceclient.h"
  58. // *TODO: Move more common stuff to LLAvatarActions?
  59. //Maximum number of people you can select to do an operation on at once.
  60. #define MAX_FRIEND_SELECT 20
  61. #define DEFAULT_PERIOD 5.0
  62. #define RIGHTS_CHANGE_TIMEOUT 5.0
  63. #define OBSERVER_TIMEOUT 0.5
  64. #define ONLINE_SIP_ICON_NAME "slim_icon_16_viewer.tga"
  65. // simple class to observe the calling cards.
  66. class LLLocalFriendsObserver : public LLFriendObserver, public LLEventTimer
  67. {
  68. public: 
  69. LLLocalFriendsObserver(LLPanelFriends* floater) : mFloater(floater), LLEventTimer(OBSERVER_TIMEOUT)
  70. {
  71. mEventTimer.stop();
  72. }
  73. virtual ~LLLocalFriendsObserver()
  74. {
  75. mFloater = NULL;
  76. }
  77. virtual void changed(U32 mask)
  78. {
  79. // events can arrive quickly in bulk - we need not process EVERY one of them -
  80. // so we wait a short while to let others pile-in, and process them in aggregate.
  81. mEventTimer.start();
  82. // save-up all the mask-bits which have come-in
  83. mMask |= mask;
  84. }
  85. virtual BOOL tick()
  86. {
  87. mFloater->updateFriends(mMask);
  88. mEventTimer.stop();
  89. mMask = 0;
  90. return FALSE;
  91. }
  92. protected:
  93. LLPanelFriends* mFloater;
  94. U32 mMask;
  95. };
  96. LLPanelFriends::LLPanelFriends() :
  97. LLPanel(),
  98. LLEventTimer(DEFAULT_PERIOD),
  99. mObserver(NULL),
  100. mShowMaxSelectWarning(TRUE),
  101. mAllowRightsChange(TRUE),
  102. mNumRightsChanged(0)
  103. {
  104. mEventTimer.stop();
  105. mObserver = new LLLocalFriendsObserver(this);
  106. LLAvatarTracker::instance().addObserver(mObserver);
  107. // For notification when SIP online status changes.
  108. LLVoiceClient::getInstance()->addObserver(mObserver);
  109. }
  110. LLPanelFriends::~LLPanelFriends()
  111. {
  112. // For notification when SIP online status changes.
  113. LLVoiceClient::getInstance()->removeObserver(mObserver);
  114. LLAvatarTracker::instance().removeObserver(mObserver);
  115. delete mObserver;
  116. }
  117. BOOL LLPanelFriends::tick()
  118. {
  119. mEventTimer.stop();
  120. mPeriod = DEFAULT_PERIOD;
  121. mAllowRightsChange = TRUE;
  122. updateFriends(LLFriendObserver::ADD);
  123. return FALSE;
  124. }
  125. void LLPanelFriends::updateFriends(U32 changed_mask)
  126. {
  127. LLUUID selected_id;
  128. LLCtrlListInterface *friends_list = childGetListInterface("friend_list");
  129. if (!friends_list) return;
  130. LLCtrlScrollInterface *friends_scroll = childGetScrollInterface("friend_list");
  131. if (!friends_scroll) return;
  132. // We kill the selection warning, otherwise we'll spam with warning popups
  133. // if the maximum amount of friends are selected
  134. mShowMaxSelectWarning = false;
  135. std::vector<LLUUID> selected_friends = getSelectedIDs();
  136. if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
  137. {
  138. refreshNames(changed_mask);
  139. }
  140. else if(changed_mask & LLFriendObserver::POWERS)
  141. {
  142. --mNumRightsChanged;
  143. if(mNumRightsChanged > 0)
  144. {
  145. mPeriod = RIGHTS_CHANGE_TIMEOUT;
  146. mEventTimer.start();
  147. mAllowRightsChange = FALSE;
  148. }
  149. else
  150. {
  151. tick();
  152. }
  153. }
  154. if(selected_friends.size() > 0)
  155. {
  156. // only non-null if friends was already found. This may fail,
  157. // but we don't really care here, because refreshUI() will
  158. // clean up the interface.
  159. friends_list->setCurrentByID(selected_id);
  160. for(std::vector<LLUUID>::iterator itr = selected_friends.begin(); itr != selected_friends.end(); ++itr)
  161. {
  162. friends_list->setSelectedByValue(*itr, true);
  163. }
  164. }
  165. refreshUI();
  166. mShowMaxSelectWarning = true;
  167. }
  168. // virtual
  169. BOOL LLPanelFriends::postBuild()
  170. {
  171. mFriendsList = getChild<LLScrollListCtrl>("friend_list");
  172. mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT);
  173. mFriendsList->setMaximumSelectCallback(boost::bind(&LLPanelFriends::onMaximumSelect));
  174. mFriendsList->setCommitOnSelectionChange(TRUE);
  175. mFriendsList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
  176. childSetCommitCallback("friend_list", onSelectName, this);
  177. getChild<LLScrollListCtrl>("friend_list")->setDoubleClickCallback(onClickIM, this);
  178. U32 changed_mask = LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE;
  179. refreshNames(changed_mask);
  180. childSetAction("im_btn", onClickIM, this);
  181. childSetAction("profile_btn", onClickProfile, this);
  182. childSetAction("offer_teleport_btn", onClickOfferTeleport, this);
  183. childSetAction("pay_btn", onClickPay, this);
  184. childSetAction("add_btn", onClickAddFriend, this);
  185. childSetAction("remove_btn", onClickRemove, this);
  186. setDefaultBtn("im_btn");
  187. updateFriends(LLFriendObserver::ADD);
  188. refreshUI();
  189. // primary sort = online status, secondary sort = name
  190. mFriendsList->sortByColumn(std::string("friend_name"), TRUE);
  191. mFriendsList->sortByColumn(std::string("icon_online_status"), FALSE);
  192. return TRUE;
  193. }
  194. BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
  195. {
  196. LLAvatarTracker& at = LLAvatarTracker::instance();
  197. const LLRelationship* relationInfo = at.getBuddyInfo(agent_id);
  198. if(!relationInfo) return FALSE;
  199. bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(agent_id);
  200. bool isOnline = relationInfo->isOnline();
  201. std::string fullname;
  202. BOOL have_name = gCacheName->getFullName(agent_id, fullname);
  203. LLSD element;
  204. element["id"] = agent_id;
  205. LLSD& friend_column = element["columns"][LIST_FRIEND_NAME];
  206. friend_column["column"] = "friend_name";
  207. friend_column["value"] = fullname;
  208. friend_column["font"]["name"] = "SANSSERIF";
  209. friend_column["font"]["style"] = "NORMAL";
  210. LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
  211. online_status_column["column"] = "icon_online_status";
  212. online_status_column["type"] = "icon";
  213. if (isOnline)
  214. {
  215. friend_column["font"]["style"] = "BOLD";
  216. online_status_column["value"] = "icon_avatar_online.tga";
  217. }
  218. else if(isOnlineSIP)
  219. {
  220. friend_column["font"]["style"] = "BOLD";
  221. online_status_column["value"] = ONLINE_SIP_ICON_NAME;
  222. }
  223. LLSD& online_column = element["columns"][LIST_VISIBLE_ONLINE];
  224. online_column["column"] = "icon_visible_online";
  225. online_column["type"] = "checkbox";
  226. online_column["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS);
  227. LLSD& visible_map_column = element["columns"][LIST_VISIBLE_MAP];
  228. visible_map_column["column"] = "icon_visible_map";
  229. visible_map_column["type"] = "checkbox";
  230. visible_map_column["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION);
  231. LLSD& edit_my_object_column = element["columns"][LIST_EDIT_MINE];
  232. edit_my_object_column["column"] = "icon_edit_mine";
  233. edit_my_object_column["type"] = "checkbox";
  234. edit_my_object_column["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
  235. LLSD& edit_their_object_column = element["columns"][LIST_EDIT_THEIRS];
  236. edit_their_object_column["column"] = "icon_edit_theirs";
  237. edit_their_object_column["type"] = "checkbox";
  238. edit_their_object_column["enabled"] = "";
  239. edit_their_object_column["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS);
  240. LLSD& update_gen_column = element["columns"][LIST_FRIEND_UPDATE_GEN];
  241. update_gen_column["column"] = "friend_last_update_generation";
  242. update_gen_column["value"] = have_name ? relationInfo->getChangeSerialNum() : -1;
  243. mFriendsList->addElement(element, ADD_BOTTOM);
  244. return have_name;
  245. }
  246. // propagate actual relationship to UI.
  247. // Does not resort the UI list because it can be called frequently. JC
  248. BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationship* info)
  249. {
  250. if (!info) return FALSE;
  251. LLScrollListItem* itemp = mFriendsList->getItem(agent_id);
  252. if (!itemp) return FALSE;
  253. bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(itemp->getUUID());
  254. bool isOnline = info->isOnline();
  255. std::string fullname;
  256. BOOL have_name = gCacheName->getFullName(agent_id, fullname);
  257. // Name of the status icon to use
  258. std::string statusIcon;
  259. if(isOnline)
  260. {
  261. statusIcon = "icon_avatar_online.tga";
  262. }
  263. else if(isOnlineSIP)
  264. {
  265. statusIcon = ONLINE_SIP_ICON_NAME;
  266. }
  267. itemp->getColumn(LIST_ONLINE_STATUS)->setValue(statusIcon);
  268. itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname);
  269. // render name of online friends in bold text
  270. ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle((isOnline || isOnlineSIP) ? LLFontGL::BOLD : LLFontGL::NORMAL);
  271. itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
  272. itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
  273. itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
  274. S32 change_generation = have_name ? info->getChangeSerialNum() : -1;
  275. itemp->getColumn(LIST_FRIEND_UPDATE_GEN)->setValue(change_generation);
  276. // enable this item, in case it was disabled after user input
  277. itemp->setEnabled(TRUE);
  278. // Do not resort, this function can be called frequently.
  279. return have_name;
  280. }
  281. void LLPanelFriends::refreshRightsChangeList()
  282. {
  283. std::vector<LLUUID> friends = getSelectedIDs();
  284. S32 num_selected = friends.size();
  285. bool can_offer_teleport = num_selected >= 1;
  286. bool selected_friends_online = true;
  287. const LLRelationship* friend_status = NULL;
  288. for(std::vector<LLUUID>::iterator itr = friends.begin(); itr != friends.end(); ++itr)
  289. {
  290. friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr);
  291. if (friend_status)
  292. {
  293. if(!friend_status->isOnline())
  294. {
  295. can_offer_teleport = false;
  296. selected_friends_online = false;
  297. }
  298. }
  299. else // missing buddy info, don't allow any operations
  300. {
  301. can_offer_teleport = false;
  302. }
  303. }
  304. if (num_selected == 0)  // nothing selected
  305. {
  306. childSetEnabled("im_btn", FALSE);
  307. childSetEnabled("offer_teleport_btn", FALSE);
  308. }
  309. else // we have at least one friend selected...
  310. {
  311. // only allow IMs to groups when everyone in the group is online
  312. // to be consistent with context menus in inventory and because otherwise
  313. // offline friends would be silently dropped from the session
  314. childSetEnabled("im_btn", selected_friends_online || num_selected == 1);
  315. childSetEnabled("offer_teleport_btn", can_offer_teleport);
  316. }
  317. }
  318. struct SortFriendsByID
  319. {
  320. bool operator() (const LLScrollListItem* const a, const LLScrollListItem* const b) const
  321. {
  322. return a->getValue().asUUID() < b->getValue().asUUID();
  323. }
  324. };
  325. void LLPanelFriends::refreshNames(U32 changed_mask)
  326. {
  327. std::vector<LLUUID> selected_ids = getSelectedIDs();
  328. S32 pos = mFriendsList->getScrollPos();
  329. // get all buddies we know about
  330. LLAvatarTracker::buddy_map_t all_buddies;
  331. LLAvatarTracker::instance().copyBuddyList(all_buddies);
  332. BOOL have_names = TRUE;
  333. if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
  334. {
  335. have_names &= refreshNamesSync(all_buddies);
  336. }
  337. if(changed_mask & LLFriendObserver::ONLINE)
  338. {
  339. have_names &= refreshNamesPresence(all_buddies);
  340. }
  341. if (!have_names)
  342. {
  343. mEventTimer.start();
  344. }
  345. // Changed item in place, need to request sort and update columns
  346. // because we might have changed data in a column on which the user
  347. // has already sorted. JC
  348. mFriendsList->updateSort();
  349. // re-select items
  350. mFriendsList->selectMultiple(selected_ids);
  351. mFriendsList->setScrollPos(pos);
  352. }
  353. BOOL LLPanelFriends::refreshNamesSync(const LLAvatarTracker::buddy_map_t & all_buddies)
  354. {
  355. mFriendsList->deleteAllItems();
  356. BOOL have_names = TRUE;
  357. LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
  358. for(; buddy_it != all_buddies.end(); ++buddy_it)
  359. {
  360. have_names &= addFriend(buddy_it->first);
  361. }
  362. return have_names;
  363. }
  364. BOOL LLPanelFriends::refreshNamesPresence(const LLAvatarTracker::buddy_map_t & all_buddies)
  365. {
  366. std::vector<LLScrollListItem*> items = mFriendsList->getAllData();
  367. std::sort(items.begin(), items.end(), SortFriendsByID());
  368. LLAvatarTracker::buddy_map_t::const_iterator buddy_it  = all_buddies.begin();
  369. std::vector<LLScrollListItem*>::const_iterator item_it = items.begin();
  370. BOOL have_names = TRUE;
  371. while(true)
  372. {
  373. if(item_it == items.end() || buddy_it == all_buddies.end())
  374. {
  375. break;
  376. }
  377. const LLUUID & buddy_uuid = buddy_it->first;
  378. const LLUUID & item_uuid  = (*item_it)->getValue().asUUID();
  379. if(item_uuid == buddy_uuid)
  380. {
  381. const LLRelationship* info = buddy_it->second;
  382. if (!info) 
  383. {
  384. ++item_it;
  385. continue;
  386. }
  387. S32 last_change_generation = (*item_it)->getColumn(LIST_FRIEND_UPDATE_GEN)->getValue().asInteger();
  388. if (last_change_generation < info->getChangeSerialNum())
  389. {
  390. // update existing item in UI
  391. have_names &= updateFriendItem(buddy_it->first, info);
  392. }
  393. ++buddy_it;
  394. ++item_it;
  395. }
  396. else if(item_uuid < buddy_uuid)
  397. {
  398. ++item_it;
  399. }
  400. else //if(item_uuid > buddy_uuid)
  401. {
  402. ++buddy_it;
  403. }
  404. }
  405. return have_names;
  406. }
  407. void LLPanelFriends::refreshUI()
  408. {
  409. BOOL single_selected = FALSE;
  410. BOOL multiple_selected = FALSE;
  411. int num_selected = mFriendsList->getAllSelected().size();
  412. if(num_selected > 0)
  413. {
  414. single_selected = TRUE;
  415. if(num_selected > 1)
  416. {
  417. multiple_selected = TRUE;
  418. }
  419. }
  420. //Options that can only be performed with one friend selected
  421. childSetEnabled("profile_btn", single_selected && !multiple_selected);
  422. childSetEnabled("pay_btn", single_selected && !multiple_selected);
  423. //Options that can be performed with up to MAX_FRIEND_SELECT friends selected
  424. //(single_selected will always be true in this situations)
  425. childSetEnabled("remove_btn", single_selected);
  426. childSetEnabled("im_btn", single_selected);
  427. // childSetEnabled("friend_rights", single_selected);
  428. refreshRightsChangeList();
  429. }
  430. std::vector<LLUUID> LLPanelFriends::getSelectedIDs()
  431. {
  432. LLUUID selected_id;
  433. std::vector<LLUUID> friend_ids;
  434. std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected();
  435. for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
  436. {
  437. friend_ids.push_back((*itr)->getUUID());
  438. }
  439. return friend_ids;
  440. }
  441. // static
  442. void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
  443. {
  444. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  445. if(panelp)
  446. {
  447. panelp->refreshUI();
  448. // check to see if rights have changed
  449. panelp->applyRightsToFriends();
  450. }
  451. }
  452. //static
  453. void LLPanelFriends::onMaximumSelect()
  454. {
  455. LLSD args;
  456. args["MAX_SELECT"] = llformat("%d", MAX_FRIEND_SELECT);
  457. LLNotificationsUtil::add("MaxListSelectMessage", args);
  458. };
  459. // static
  460. void LLPanelFriends::onClickProfile(void* user_data)
  461. {
  462. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  463. std::vector<LLUUID> ids = panelp->getSelectedIDs();
  464. if(ids.size() > 0)
  465. {
  466. LLUUID agent_id = ids[0];
  467. LLAvatarActions::showProfile(agent_id);
  468. }
  469. }
  470. // static
  471. void LLPanelFriends::onClickIM(void* user_data)
  472. {
  473. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  474. std::vector<LLUUID> ids = panelp->getSelectedIDs();
  475. if(ids.size() > 0)
  476. {
  477. if(ids.size() == 1)
  478. {
  479. LLAvatarActions::startIM(ids[0]);
  480. }
  481. else
  482. {
  483. LLAvatarActions::startConference(ids);
  484. }
  485. }
  486. }
  487. // static
  488. void LLPanelFriends::onPickAvatar(const std::vector<std::string>& names,
  489. const std::vector<LLUUID>& ids)
  490. {
  491. if (names.empty()) return;
  492. if (ids.empty()) return;
  493. LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
  494. }
  495. // static
  496. void LLPanelFriends::onClickAddFriend(void* user_data)
  497. {
  498. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  499. LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
  500. LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelFriends::onPickAvatar, _1,_2), FALSE, TRUE);
  501. if (root_floater)
  502. {
  503. root_floater->addDependentFloater(picker);
  504. }
  505. }
  506. // static
  507. void LLPanelFriends::onClickRemove(void* user_data)
  508. {
  509. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  510. LLAvatarActions::removeFriendsDialog(panelp->getSelectedIDs());
  511. }
  512. // static
  513. void LLPanelFriends::onClickOfferTeleport(void* user_data)
  514. {
  515. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  516. LLAvatarActions::offerTeleport(panelp->getSelectedIDs());
  517. }
  518. // static
  519. void LLPanelFriends::onClickPay(void* user_data)
  520. {
  521. LLPanelFriends* panelp = (LLPanelFriends*)user_data;
  522. std::vector<LLUUID> ids = panelp->getSelectedIDs();
  523. if(ids.size() == 1)
  524. {
  525. LLAvatarActions::pay(ids[0]);
  526. }
  527. }
  528. void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command)
  529. {
  530. if (ids.empty()) return;
  531. LLSD args;
  532. if(ids.size() > 0)
  533. {
  534. rights_map_t* rights = new rights_map_t(ids);
  535. // for single friend, show their name
  536. if(ids.size() == 1)
  537. {
  538. LLUUID agent_id = ids.begin()->first;
  539. std::string first, last;
  540. if(gCacheName->getName(agent_id, first, last))
  541. {
  542. args["FIRST_NAME"] = first;
  543. args["LAST_NAME"] = last;
  544. }
  545. if (command == GRANT)
  546. {
  547. LLNotificationsUtil::add("GrantModifyRights", 
  548. args, 
  549. LLSD(), 
  550. boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
  551. }
  552. else
  553. {
  554. LLNotificationsUtil::add("RevokeModifyRights", 
  555. args, 
  556. LLSD(), 
  557. boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
  558. }
  559. }
  560. else
  561. {
  562. if (command == GRANT)
  563. {
  564. LLNotificationsUtil::add("GrantModifyRightsMultiple", 
  565. args, 
  566. LLSD(), 
  567. boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
  568. }
  569. else
  570. {
  571. LLNotificationsUtil::add("RevokeModifyRightsMultiple", 
  572. args, 
  573. LLSD(), 
  574. boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
  575. }
  576. }
  577. }
  578. }
  579. bool LLPanelFriends::modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights)
  580. {
  581. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  582. if(0 == option)
  583. {
  584. sendRightsGrant(*rights);
  585. }
  586. else
  587. {
  588. // need to resync view with model, since user cancelled operation
  589. rights_map_t::iterator rights_it;
  590. for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it)
  591. {
  592. const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
  593. updateFriendItem(rights_it->first, info);
  594. }
  595. }
  596. refreshUI();
  597. delete rights;
  598. return false;
  599. }
  600. void LLPanelFriends::applyRightsToFriends()
  601. {
  602. BOOL rights_changed = FALSE;
  603. // store modify rights separately for confirmation
  604. rights_map_t rights_updates;
  605. BOOL need_confirmation = FALSE;
  606. EGrantRevoke confirmation_type = GRANT;
  607. // this assumes that changes only happened to selected items
  608. std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected();
  609. for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
  610. {
  611. LLUUID id = (*itr)->getValue();
  612. const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(id);
  613. if (buddy_relationship == NULL) continue;
  614. bool show_online_staus = (*itr)->getColumn(LIST_VISIBLE_ONLINE)->getValue().asBoolean();
  615. bool show_map_location = (*itr)->getColumn(LIST_VISIBLE_MAP)->getValue().asBoolean();
  616. bool allow_modify_objects = (*itr)->getColumn(LIST_EDIT_MINE)->getValue().asBoolean();
  617. S32 rights = buddy_relationship->getRightsGrantedTo();
  618. if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) != show_online_staus)
  619. {
  620. rights_changed = TRUE;
  621. if(show_online_staus) 
  622. {
  623. rights |= LLRelationship::GRANT_ONLINE_STATUS;
  624. }
  625. else 
  626. {
  627. // ONLINE_STATUS necessary for MAP_LOCATION
  628. rights &= ~LLRelationship::GRANT_ONLINE_STATUS;
  629. rights &= ~LLRelationship::GRANT_MAP_LOCATION;
  630. // propagate rights constraint to UI
  631. (*itr)->getColumn(LIST_VISIBLE_MAP)->setValue(FALSE);
  632. }
  633. }
  634. if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) != show_map_location)
  635. {
  636. rights_changed = TRUE;
  637. if(show_map_location) 
  638. {
  639. // ONLINE_STATUS necessary for MAP_LOCATION
  640. rights |= LLRelationship::GRANT_MAP_LOCATION;
  641. rights |= LLRelationship::GRANT_ONLINE_STATUS;
  642. (*itr)->getColumn(LIST_VISIBLE_ONLINE)->setValue(TRUE);
  643. }
  644. else 
  645. {
  646. rights &= ~LLRelationship::GRANT_MAP_LOCATION;
  647. }
  648. }
  649. // now check for change in modify object rights, which requires confirmation
  650. if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects)
  651. {
  652. rights_changed = TRUE;
  653. need_confirmation = TRUE;
  654. if(allow_modify_objects)
  655. {
  656. rights |= LLRelationship::GRANT_MODIFY_OBJECTS;
  657. confirmation_type = GRANT;
  658. }
  659. else
  660. {
  661. rights &= ~LLRelationship::GRANT_MODIFY_OBJECTS;
  662. confirmation_type = REVOKE;
  663. }
  664. }
  665. if (rights_changed)
  666. {
  667. rights_updates.insert(std::make_pair(id, rights));
  668. // disable these ui elements until response from server
  669. // to avoid race conditions
  670. (*itr)->setEnabled(FALSE);
  671. }
  672. }
  673. // separately confirm grant and revoke of modify rights
  674. if (need_confirmation)
  675. {
  676. confirmModifyRights(rights_updates, confirmation_type);
  677. }
  678. else
  679. {
  680. sendRightsGrant(rights_updates);
  681. }
  682. }
  683. void LLPanelFriends::sendRightsGrant(rights_map_t& ids)
  684. {
  685. if (ids.empty()) return;
  686. LLMessageSystem* msg = gMessageSystem;
  687. // setup message header
  688. msg->newMessageFast(_PREHASH_GrantUserRights);
  689. msg->nextBlockFast(_PREHASH_AgentData);
  690. msg->addUUID(_PREHASH_AgentID, gAgent.getID());
  691. msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
  692. rights_map_t::iterator id_it;
  693. rights_map_t::iterator end_it = ids.end();
  694. for(id_it = ids.begin(); id_it != end_it; ++id_it)
  695. {
  696. msg->nextBlockFast(_PREHASH_Rights);
  697. msg->addUUID(_PREHASH_AgentRelated, id_it->first);
  698. msg->addS32(_PREHASH_RelatedRights, id_it->second);
  699. }
  700. mNumRightsChanged = ids.size();
  701. gAgent.sendReliableMessage();
  702. }