diff options
Diffstat (limited to 'linden/indra/newview/llfloaterfriends.cpp')
-rw-r--r-- | linden/indra/newview/llfloaterfriends.cpp | 447 |
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 | ||
256 | void 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 | |||
265 | void LLPanelFriends::refreshRightsChangeList() | 276 | void 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 | ||
334 | struct 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 | |||
409 | void LLPanelFriends::refreshNames() | 342 | void 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 | ||
690 | void LLPanelFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data) | 658 | void 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 | |||
699 | void 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 | |||
707 | void 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 | ||
733 | void LLPanelFriends::handleModifyRights(S32 option, void* user_data) | 704 | // static |
705 | void 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 | ||
748 | void LLPanelFriends::updateMenuState(S32 flag, BOOL value) | 735 | void 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 | ||
754 | void LLPanelFriends::applyRightsToFriends(S32 flag, BOOL value) | 828 | void 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 | } |