aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloaterfriends.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llfloaterfriends.cpp')
-rw-r--r--linden/indra/newview/llfloaterfriends.cpp447
1 files changed, 260 insertions, 187 deletions
diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
index 99a33d6..e6ff76b 100644
--- a/linden/indra/newview/llfloaterfriends.cpp
+++ b/linden/indra/newview/llfloaterfriends.cpp
@@ -14,12 +14,12 @@
14 * ("GPL"), unless you have obtained a separate licensing agreement 14 * ("GPL"), unless you have obtained a separate licensing agreement
15 * ("Other License"), formally executed by you and Linden Lab. Terms of 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 16 * the GPL can be found in doc/GPL-license.txt in this distribution, or
17 * online at http://secondlife.com/developers/opensource/gplv2 17 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
18 * 18 *
19 * There are special exceptions to the terms and conditions of the GPL as 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 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 21 * in the file doc/FLOSS-exception.txt in this software distribution, or
22 * online at http://secondlife.com/developers/opensource/flossexception 22 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
23 * 23 *
24 * By copying, modifying or distributing this software, you acknowledge 24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above, 25 * that you have read and understood your obligations described above,
@@ -104,7 +104,6 @@ LLPanelFriends::LLPanelFriends() :
104 LLPanel(), 104 LLPanel(),
105 LLEventTimer(1000000), 105 LLEventTimer(1000000),
106 mObserver(NULL), 106 mObserver(NULL),
107 mMenuState(0),
108 mShowMaxSelectWarning(TRUE), 107 mShowMaxSelectWarning(TRUE),
109 mAllowRightsChange(TRUE), 108 mAllowRightsChange(TRUE),
110 mNumRightsChanged(0) 109 mNumRightsChanged(0)
@@ -182,16 +181,13 @@ BOOL LLPanelFriends::postBuild()
182{ 181{
183 mFriendsList = LLUICtrlFactory::getScrollListByName(this, "friend_list"); 182 mFriendsList = LLUICtrlFactory::getScrollListByName(this, "friend_list");
184 mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT); 183 mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT);
185 mFriendsList->setMaxiumumSelectCallback(onMaximumSelect); 184 mFriendsList->setMaximumSelectCallback(onMaximumSelect);
186 mFriendsList->setCommitOnSelectionChange(TRUE); 185 mFriendsList->setCommitOnSelectionChange(TRUE);
187 childSetCommitCallback("friend_list", onSelectName, this); 186 childSetCommitCallback("friend_list", onSelectName, this);
188 childSetDoubleClickCallback("friend_list", onClickIM); 187 childSetDoubleClickCallback("friend_list", onClickIM);
189 188
190 refreshNames(); 189 refreshNames();
191 190
192 childSetCommitCallback("online_status_cb", onClickOnlineStatus, this);
193 childSetCommitCallback("map_status_cb", onClickMapStatus, this);
194 childSetCommitCallback("modify_status_cb", onClickModifyStatus, this);
195 childSetAction("im_btn", onClickIM, this); 191 childSetAction("im_btn", onClickIM, this);
196 childSetAction("profile_btn", onClickProfile, this); 192 childSetAction("profile_btn", onClickProfile, this);
197 childSetAction("offer_teleport_btn", onClickOfferTeleport, this); 193 childSetAction("offer_teleport_btn", onClickOfferTeleport, this);
@@ -204,6 +200,10 @@ BOOL LLPanelFriends::postBuild()
204 updateFriends(LLFriendObserver::ADD); 200 updateFriends(LLFriendObserver::ADD);
205 refreshUI(); 201 refreshUI();
206 202
203 // primary sort = online status, secondary sort = name
204 mFriendsList->sortByColumn("friend_name", TRUE);
205 mFriendsList->sortByColumn("icon_online_status", TRUE);
206
207 return TRUE; 207 return TRUE;
208} 208}
209 209
@@ -222,64 +222,63 @@ void LLPanelFriends::addFriend(const std::string& name, const LLUUID& agent_id)
222 element["columns"][LIST_FRIEND_NAME]["font"] = "SANSSERIF"; 222 element["columns"][LIST_FRIEND_NAME]["font"] = "SANSSERIF";
223 element["columns"][LIST_FRIEND_NAME]["font-style"] = "NORMAL"; 223 element["columns"][LIST_FRIEND_NAME]["font-style"] = "NORMAL";
224 element["columns"][LIST_ONLINE_STATUS]["column"] = "icon_online_status"; 224 element["columns"][LIST_ONLINE_STATUS]["column"] = "icon_online_status";
225 element["columns"][LIST_ONLINE_STATUS]["type"] = "text"; 225 element["columns"][LIST_ONLINE_STATUS]["type"] = "icon";
226 if (online) 226 if (online)
227 { 227 {
228 element["columns"][LIST_FRIEND_NAME]["font-style"] = "BOLD"; 228 element["columns"][LIST_FRIEND_NAME]["font-style"] = "BOLD";
229 element["columns"][LIST_ONLINE_STATUS]["type"] = "icon";
230 element["columns"][LIST_ONLINE_STATUS]["value"] = gViewerArt.getString("icon_avatar_online.tga"); 229 element["columns"][LIST_ONLINE_STATUS]["value"] = gViewerArt.getString("icon_avatar_online.tga");
231 } 230 }
232 231
233
234 element["columns"][LIST_VISIBLE_ONLINE]["column"] = "icon_visible_online"; 232 element["columns"][LIST_VISIBLE_ONLINE]["column"] = "icon_visible_online";
235 element["columns"][LIST_VISIBLE_ONLINE]["type"] = "text"; 233 element["columns"][LIST_VISIBLE_ONLINE]["type"] = "checkbox";
236 if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)) 234 element["columns"][LIST_VISIBLE_ONLINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS);
237 { 235
238 element["columns"][LIST_VISIBLE_ONLINE]["type"] = "icon";
239 element["columns"][LIST_VISIBLE_ONLINE]["value"] = gViewerArt.getString("ff_visible_online.tga");
240 }
241 element["columns"][LIST_VISIBLE_MAP]["column"] = "icon_visible_map"; 236 element["columns"][LIST_VISIBLE_MAP]["column"] = "icon_visible_map";
242 element["columns"][LIST_VISIBLE_MAP]["type"] = "text"; 237 element["columns"][LIST_VISIBLE_MAP]["type"] = "checkbox";
243 if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)) 238 element["columns"][LIST_VISIBLE_MAP]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION);
244 { 239
245 element["columns"][LIST_VISIBLE_MAP]["type"] = "icon";
246 element["columns"][LIST_VISIBLE_MAP]["value"] = gViewerArt.getString("ff_visible_map.tga");
247 }
248 element["columns"][LIST_EDIT_MINE]["column"] = "icon_edit_mine"; 240 element["columns"][LIST_EDIT_MINE]["column"] = "icon_edit_mine";
249 element["columns"][LIST_EDIT_MINE]["type"] = "text"; 241 element["columns"][LIST_EDIT_MINE]["type"] = "checkbox";
250 if(relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)) 242 element["columns"][LIST_EDIT_MINE]["value"] = relationInfo->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
251 { 243
252 element["columns"][LIST_EDIT_MINE]["type"] = "icon";
253 element["columns"][LIST_EDIT_MINE]["value"] = gViewerArt.getString("ff_edit_mine.tga");
254 }
255 element["columns"][LIST_EDIT_THEIRS]["column"] = "icon_edit_theirs"; 244 element["columns"][LIST_EDIT_THEIRS]["column"] = "icon_edit_theirs";
256 element["columns"][LIST_EDIT_THEIRS]["type"] = "text"; 245 element["columns"][LIST_EDIT_THEIRS]["type"] = "checkbox";
257 if(relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)) 246 element["columns"][LIST_EDIT_THEIRS]["enabled"] = "";
258 { 247 element["columns"][LIST_EDIT_THEIRS]["value"] = relationInfo->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS);
259 element["columns"][LIST_EDIT_THEIRS]["type"] = "icon"; 248
260 element["columns"][LIST_EDIT_THEIRS]["value"] = gViewerArt.getString("ff_edit_theirs.tga"); 249 element["columns"][LIST_FRIEND_UPDATE_GEN]["column"] = "friend_last_update_generation";
261 } 250 element["columns"][LIST_FRIEND_UPDATE_GEN]["value"] = relationInfo->getChangeSerialNum();
251
262 mFriendsList->addElement(element, ADD_BOTTOM); 252 mFriendsList->addElement(element, ADD_BOTTOM);
263} 253}
264 254
255// propagate actual relationship to UI
256void LLPanelFriends::updateFriendItem(LLScrollListItem* itemp, const LLRelationship* info)
257{
258 if (!itemp) return;
259 if (!info) return;
260
261 itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? gViewerArt.getString("icon_avatar_online.tga") : LLString());
262 // render name of online friends in bold text
263 ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
264 itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
265 itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
266 itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
267 itemp->getColumn(LIST_FRIEND_UPDATE_GEN)->setValue(info->getChangeSerialNum());
268
269 // enable this item, in case it was disabled after user input
270 itemp->setEnabled(TRUE);
271
272 // changed item in place, need to request sort
273 mFriendsList->sortItems();
274}
275
265void LLPanelFriends::refreshRightsChangeList() 276void LLPanelFriends::refreshRightsChangeList()
266{ 277{
267 LLDynamicArray<LLUUID> friends = getSelectedIDs(); 278 LLDynamicArray<LLUUID> friends = getSelectedIDs();
268 S32 num_selected = friends.size(); 279 S32 num_selected = friends.size();
269 280
270 LLSD row;
271 bool can_offer_teleport = num_selected >= 1; 281 bool can_offer_teleport = num_selected >= 1;
272
273 // aggregate permissions over all selected friends
274 bool friends_see_online = true;
275 bool friends_see_on_map = true;
276 bool friends_modify_objects = true;
277
278 // do at least some of the friends selected have these rights?
279 bool some_friends_see_online = false;
280 bool some_friends_see_on_map = false;
281 bool some_friends_modify_objects = false;
282
283 bool selected_friends_online = true; 282 bool selected_friends_online = true;
284 283
285 LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label"); 284 LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label");
@@ -294,12 +293,9 @@ void LLPanelFriends::refreshRightsChangeList()
294 num_selected = 0; 293 num_selected = 0;
295 } 294 }
296 } 295 }
297 else 296 else if(processing_label)
298 { 297 {
299 if(processing_label) 298 processing_label->setVisible(false);
300 {
301 processing_label->setVisible(false);
302 }
303 } 299 }
304 300
305 const LLRelationship* friend_status = NULL; 301 const LLRelationship* friend_status = NULL;
@@ -308,20 +304,6 @@ void LLPanelFriends::refreshRightsChangeList()
308 friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr); 304 friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr);
309 if (friend_status) 305 if (friend_status)
310 { 306 {
311 bool can_see_online = friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS);
312 bool can_see_on_map = friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION);
313 bool can_modify_objects = friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
314
315 // aggregate rights of this friend into total selection
316 friends_see_online &= can_see_online;
317 friends_see_on_map &= can_see_on_map;
318 friends_modify_objects &= can_modify_objects;
319
320 // can at least one of your selected friends do any of these?
321 some_friends_see_online |= can_see_online;
322 some_friends_see_on_map |= can_see_on_map;
323 some_friends_modify_objects |= can_modify_objects;
324
325 if(!friend_status->isOnline()) 307 if(!friend_status->isOnline())
326 { 308 {
327 can_offer_teleport = false; 309 can_offer_teleport = false;
@@ -331,44 +313,13 @@ void LLPanelFriends::refreshRightsChangeList()
331 else // missing buddy info, don't allow any operations 313 else // missing buddy info, don't allow any operations
332 { 314 {
333 can_offer_teleport = false; 315 can_offer_teleport = false;
334
335 friends_see_online = false;
336 friends_see_on_map = false;
337 friends_modify_objects = false;
338
339 some_friends_see_online = false;
340 some_friends_see_on_map = false;
341 some_friends_modify_objects = false;
342 } 316 }
343 } 317 }
344 318
345
346 // seeing a friend on the map requires seeing online status as a prerequisite
347 friends_see_on_map &= friends_see_online;
348
349 mMenuState = 0;
350
351 // make checkboxes visible after we have finished processing rights
352 childSetVisible("online_status_cb", mAllowRightsChange);
353 childSetVisible("map_status_cb", mAllowRightsChange);
354 childSetVisible("modify_status_cb", mAllowRightsChange);
355
356 if (num_selected == 0) // nothing selected 319 if (num_selected == 0) // nothing selected
357 { 320 {
358 childSetEnabled("im_btn", FALSE); 321 childSetEnabled("im_btn", FALSE);
359 childSetEnabled("offer_teleport_btn", FALSE); 322 childSetEnabled("offer_teleport_btn", FALSE);
360
361 childSetEnabled("online_status_cb", FALSE);
362 childSetValue("online_status_cb", FALSE);
363 childSetTentative("online_status_cb", FALSE);
364
365 childSetEnabled("map_status_cb", FALSE);
366 childSetValue("map_status_cb", FALSE);
367 childSetTentative("map_status_cb", FALSE);
368
369 childSetEnabled("modify_status_cb", FALSE);
370 childSetValue("modify_status_cb", FALSE);
371 childSetTentative("modify_status_cb", FALSE);
372 } 323 }
373 else // we have at least one friend selected... 324 else // we have at least one friend selected...
374 { 325 {
@@ -376,61 +327,76 @@ void LLPanelFriends::refreshRightsChangeList()
376 // to be consistent with context menus in inventory and because otherwise 327 // to be consistent with context menus in inventory and because otherwise
377 // offline friends would be silently dropped from the session 328 // offline friends would be silently dropped from the session
378 childSetEnabled("im_btn", selected_friends_online || num_selected == 1); 329 childSetEnabled("im_btn", selected_friends_online || num_selected == 1);
379
380 childSetEnabled("offer_teleport_btn", can_offer_teleport); 330 childSetEnabled("offer_teleport_btn", can_offer_teleport);
381
382 childSetEnabled("online_status_cb", TRUE);
383 childSetValue("online_status_cb", some_friends_see_online);
384 childSetTentative("online_status_cb", some_friends_see_online != friends_see_online);
385 if (friends_see_online)
386 {
387 mMenuState |= LLRelationship::GRANT_ONLINE_STATUS;
388 }
389
390 childSetEnabled("map_status_cb", TRUE);
391 childSetValue("map_status_cb", some_friends_see_on_map);
392 childSetTentative("map_status_cb", some_friends_see_on_map != friends_see_on_map);
393 if(friends_see_on_map)
394 {
395 mMenuState |= LLRelationship::GRANT_MAP_LOCATION;
396 }
397
398 // for now, don't allow modify rights change for multiple select
399 childSetEnabled("modify_status_cb", num_selected == 1);
400 childSetValue("modify_status_cb", some_friends_modify_objects);
401 childSetTentative("modify_status_cb", some_friends_modify_objects != friends_modify_objects);
402 if(friends_modify_objects)
403 {
404 mMenuState |= LLRelationship::GRANT_MODIFY_OBJECTS;
405 }
406 } 331 }
407} 332}
408 333
334struct SortFriendsByID
335{
336 bool SortFriendsByID::operator() (const LLScrollListItem* const a, const LLScrollListItem* const b) const
337 {
338 return a->getValue().asUUID() < b->getValue().asUUID();
339 }
340};
341
409void LLPanelFriends::refreshNames() 342void LLPanelFriends::refreshNames()
410{ 343{
411 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs(); 344 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs();
412 S32 pos = mFriendsList->getScrollPos(); 345 S32 pos = mFriendsList->getScrollPos();
413 mFriendsList->operateOnAll(LLCtrlListInterface::OP_DELETE);
414 346
415 LLCollectAllBuddies collect; 347 // get all buddies we know about
416 LLAvatarTracker::instance().applyFunctor(collect); 348 LLAvatarTracker::buddy_map_t all_buddies;
417 LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin(); 349 LLAvatarTracker::instance().copyBuddyList(all_buddies);
418 LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
419 350
420 for ( ; it != end; ++it) 351 // get all friends in list and sort by UUID
421 { 352 std::vector<LLScrollListItem*> items = mFriendsList->getAllData();
422 const std::string& name = it->first; 353 std::sort(items.begin(), items.end(), SortFriendsByID());
423 const LLUUID& agent_id = it->second; 354
424 addFriend(name, agent_id); 355 std::vector<LLScrollListItem*>::iterator item_it = items.begin();
425 } 356 std::vector<LLScrollListItem*>::iterator item_end = items.end();
426 it = collect.mOffline.begin(); 357
427 end = collect.mOffline.end(); 358 LLAvatarTracker::buddy_map_t::iterator buddy_it;
428 for ( ; it != end; ++it) 359 for (buddy_it = all_buddies.begin() ; buddy_it != all_buddies.end(); ++buddy_it)
429 { 360 {
430 const std::string& name = it->first; 361 // erase any items that reflect residents who are no longer buddies
431 const LLUUID& agent_id = it->second; 362 while(item_it != item_end && buddy_it->first > (*item_it)->getValue().asUUID())
432 addFriend(name, agent_id); 363 {
364 mFriendsList->deleteItems((*item_it)->getValue());
365 ++item_it;
366 }
367
368 // update existing friends with new info
369 if (item_it != item_end && buddy_it->first == (*item_it)->getValue().asUUID())
370 {
371 const LLRelationship* info = buddy_it->second;
372 if (!info)
373 {
374 ++item_it;
375 continue;
376 }
377
378 S32 last_change_generation = (*item_it)->getColumn(LIST_FRIEND_UPDATE_GEN)->getValue().asInteger();
379 if (last_change_generation < info->getChangeSerialNum())
380 {
381 // update existing item in UI
382 updateFriendItem(mFriendsList->getItem(buddy_it->first), info);
383 }
384 ++item_it;
385 }
386 // add new friend to list
387 else
388 {
389 const LLUUID& buddy_id = buddy_it->first;
390 char first_name[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
391 char last_name[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
392
393 gCacheName->getName(buddy_id, first_name, last_name);
394 std::ostringstream fullname;
395 fullname << first_name << " " << last_name;
396 addFriend(fullname.str(), buddy_id);
397 }
433 } 398 }
399
434 mFriendsList->selectMultiple(selected_ids); 400 mFriendsList->selectMultiple(selected_ids);
435 mFriendsList->setScrollPos(pos); 401 mFriendsList->setScrollPos(pos);
436} 402}
@@ -451,7 +417,7 @@ void LLPanelFriends::refreshUI()
451 } 417 }
452 else 418 else
453 { 419 {
454 childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getText() + "..."); 420 childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getValue().asString() + "...");
455 } 421 }
456 } 422 }
457 else 423 else
@@ -493,6 +459,8 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
493 if(panelp) 459 if(panelp)
494 { 460 {
495 panelp->refreshUI(); 461 panelp->refreshUI();
462 // check to see if rights have changed
463 panelp->applyRightsToFriends();
496 } 464 }
497} 465}
498 466
@@ -687,35 +655,22 @@ void LLPanelFriends::onClickPay(void* user_data)
687 } 655 }
688} 656}
689 657
690void LLPanelFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data) 658void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command)
691{
692 LLPanelFriends* panelp = (LLPanelFriends*)user_data;
693
694 bool checked = ctrl->getValue();
695 panelp->updateMenuState(LLRelationship::GRANT_ONLINE_STATUS, checked);
696 panelp->applyRightsToFriends(LLRelationship::GRANT_ONLINE_STATUS, checked);
697}
698
699void LLPanelFriends::onClickMapStatus(LLUICtrl* ctrl, void* user_data)
700{
701 LLPanelFriends* panelp = (LLPanelFriends*)user_data;
702 bool checked = ctrl->getValue();
703 panelp->updateMenuState(LLRelationship::GRANT_MAP_LOCATION, checked);
704 panelp->applyRightsToFriends(LLRelationship::GRANT_MAP_LOCATION, checked);
705}
706
707void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data)
708{ 659{
709 LLPanelFriends* panelp = (LLPanelFriends*)user_data; 660 if (ids.empty()) return;
710 661
711 bool checked = ctrl->getValue();
712 LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
713 LLStringBase<char>::format_map_t args; 662 LLStringBase<char>::format_map_t args;
714 if(ids.size() > 0) 663 if(ids.size() > 0)
715 { 664 {
665 // copy map of ids onto heap
666 rights_map_t* rights = new rights_map_t(ids);
667 // package with panel pointer
668 std::pair<LLPanelFriends*, rights_map_t*>* user_data = new std::pair<LLPanelFriends*, rights_map_t*>(this, rights);
669
670 // for single friend, show their name
716 if(ids.size() == 1) 671 if(ids.size() == 1)
717 { 672 {
718 LLUUID agent_id = ids[0]; 673 LLUUID agent_id = ids.begin()->first;
719 char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ 674 char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
720 char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ 675 char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
721 if(gCacheName->getName(agent_id, first, last)) 676 if(gCacheName->getName(agent_id, first, last))
@@ -723,56 +678,174 @@ void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data)
723 args["[FIRST_NAME]"] = first; 678 args["[FIRST_NAME]"] = first;
724 args["[LAST_NAME]"] = last; 679 args["[LAST_NAME]"] = last;
725 } 680 }
726 if(checked) gViewerWindow->alertXml("GrantModifyRights", args, handleModifyRights, user_data); 681 if (command == GRANT)
727 else gViewerWindow->alertXml("RevokeModifyRights", args, handleModifyRights, user_data); 682 {
683 gViewerWindow->alertXml("GrantModifyRights", args, modifyRightsConfirmation, user_data);
684 }
685 else
686 {
687 gViewerWindow->alertXml("RevokeModifyRights", args, modifyRightsConfirmation, user_data);
688 }
689 }
690 else
691 {
692 if (command == GRANT)
693 {
694 gViewerWindow->alertXml("GrantModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
695 }
696 else
697 {
698 gViewerWindow->alertXml("RevokeModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
699 }
728 } 700 }
729 else return;
730 } 701 }
731} 702}
732 703
733void LLPanelFriends::handleModifyRights(S32 option, void* user_data) 704// static
705void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data)
734{ 706{
735 LLPanelFriends* panelp = (LLPanelFriends*)user_data; 707 std::pair<LLPanelFriends*, rights_map_t*>* data = (std::pair<LLPanelFriends*, rights_map_t*>*)user_data;
708 LLPanelFriends* panelp = data->first;
736 709
737 if(panelp) 710 if(panelp)
738 { 711 {
739 if(!option) 712 if(0 == option)
740 { 713 {
741 panelp->updateMenuState(LLRelationship::GRANT_MODIFY_OBJECTS, !((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); 714 panelp->sendRightsGrant(*(data->second));
742 panelp->applyRightsToFriends(LLRelationship::GRANT_MODIFY_OBJECTS, ((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); 715 }
716 else
717 {
718 // need to resync view with model, since user cancelled operation
719 rights_map_t* rights = data->second;
720 rights_map_t::iterator rights_it;
721 for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it)
722 {
723 LLScrollListItem* itemp = panelp->mFriendsList->getItem(rights_it->first);
724 const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
725 panelp->updateFriendItem(itemp, info);
726 }
743 } 727 }
744 panelp->refreshUI(); 728 panelp->refreshUI();
745 } 729 }
730
731 delete data->second;
732 delete data;
746} 733}
747 734
748void LLPanelFriends::updateMenuState(S32 flag, BOOL value) 735void LLPanelFriends::applyRightsToFriends()
749{ 736{
750 if(value) mMenuState |= flag; 737 BOOL rights_changed = FALSE;
751 else mMenuState &= ~flag; 738
739 // store modify rights separately for confirmation
740 rights_map_t rights_updates;
741
742 BOOL need_confirmation = FALSE;
743 EGrantRevoke confirmation_type = GRANT;
744
745 // this assumes that changes only happened to selected items
746 std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected();
747 for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
748 {
749 LLUUID id = (*itr)->getValue();
750 const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(id);
751 if (buddy_relationship == NULL) continue;
752
753 bool show_online_staus = (*itr)->getColumn(LIST_VISIBLE_ONLINE)->getValue().asBoolean();
754 bool show_map_location = (*itr)->getColumn(LIST_VISIBLE_MAP)->getValue().asBoolean();
755 bool allow_modify_objects = (*itr)->getColumn(LIST_EDIT_MINE)->getValue().asBoolean();
756
757 S32 rights = buddy_relationship->getRightsGrantedTo();
758 if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) != show_online_staus)
759 {
760 rights_changed = TRUE;
761 if(show_online_staus)
762 {
763 rights |= LLRelationship::GRANT_ONLINE_STATUS;
764 }
765 else
766 {
767 // ONLINE_STATUS necessary for MAP_LOCATION
768 rights &= ~LLRelationship::GRANT_ONLINE_STATUS;
769 rights &= ~LLRelationship::GRANT_MAP_LOCATION;
770 // propagate rights constraint to UI
771 (*itr)->getColumn(LIST_VISIBLE_MAP)->setValue(FALSE);
772 }
773 }
774 if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) != show_map_location)
775 {
776 rights_changed = TRUE;
777 if(show_map_location)
778 {
779 // ONLINE_STATUS necessary for MAP_LOCATION
780 rights |= LLRelationship::GRANT_MAP_LOCATION;
781 rights |= LLRelationship::GRANT_ONLINE_STATUS;
782 (*itr)->getColumn(LIST_VISIBLE_ONLINE)->setValue(TRUE);
783 }
784 else
785 {
786 rights &= ~LLRelationship::GRANT_MAP_LOCATION;
787 }
788 }
789
790 // now check for change in modify object rights, which requires confirmation
791 if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects)
792 {
793 rights_changed = TRUE;
794 need_confirmation = TRUE;
795
796 if(allow_modify_objects)
797 {
798 rights |= LLRelationship::GRANT_MODIFY_OBJECTS;
799 confirmation_type = GRANT;
800 }
801 else
802 {
803 rights &= ~LLRelationship::GRANT_MODIFY_OBJECTS;
804 confirmation_type = REVOKE;
805 }
806 }
807
808 if (rights_changed)
809 {
810 rights_updates.insert(std::make_pair(id, rights));
811 // disable these ui elements until response from server
812 // to avoid race conditions
813 (*itr)->setEnabled(FALSE);
814 }
815 }
816
817 // separately confirm grant and revoke of modify rights
818 if (need_confirmation)
819 {
820 confirmModifyRights(rights_updates, confirmation_type);
821 }
822 else
823 {
824 sendRightsGrant(rights_updates);
825 }
752} 826}
753 827
754void LLPanelFriends::applyRightsToFriends(S32 flag, BOOL value) 828void LLPanelFriends::sendRightsGrant(rights_map_t& ids)
755{ 829{
830 if (ids.empty()) return;
831
756 LLMessageSystem* msg = gMessageSystem; 832 LLMessageSystem* msg = gMessageSystem;
833
834 // setup message header
757 msg->newMessageFast(_PREHASH_GrantUserRights); 835 msg->newMessageFast(_PREHASH_GrantUserRights);
758 msg->nextBlockFast(_PREHASH_AgentData); 836 msg->nextBlockFast(_PREHASH_AgentData);
759 msg->addUUID(_PREHASH_AgentID, gAgent.getID()); 837 msg->addUUID(_PREHASH_AgentID, gAgent.getID());
760 msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); 838 msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
761 839
762 LLDynamicArray<LLUUID> ids = getSelectedIDs(); 840 rights_map_t::iterator id_it;
763 S32 rights; 841 rights_map_t::iterator end_it = ids.end();
764 for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr) 842 for(id_it = ids.begin(); id_it != end_it; ++id_it)
765 { 843 {
766 rights = LLAvatarTracker::instance().getBuddyInfo(*itr)->getRightsGrantedTo(); 844 msg->nextBlockFast(_PREHASH_Rights);
767 if(LLAvatarTracker::instance().getBuddyInfo(*itr)->isRightGrantedTo(flag) != (bool)value) 845 msg->addUUID(_PREHASH_AgentRelated, id_it->first);
768 { 846 msg->addS32(_PREHASH_RelatedRights, id_it->second);
769 if(value) rights |= flag;
770 else rights &= ~flag;
771 msg->nextBlockFast(_PREHASH_Rights);
772 msg->addUUID(_PREHASH_AgentRelated, *itr);
773 msg->addS32(_PREHASH_RelatedRights, rights);
774 }
775 } 847 }
848
776 mNumRightsChanged = ids.size(); 849 mNumRightsChanged = ids.size();
777 gAgent.sendReliableMessage(); 850 gAgent.sendReliableMessage();
778} 851}