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.cpp173
1 files changed, 115 insertions, 58 deletions
diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
index 97b7131..acdd5ce 100644
--- a/linden/indra/newview/llfloaterfriends.cpp
+++ b/linden/indra/newview/llfloaterfriends.cpp
@@ -41,10 +41,10 @@
41#include "lldir.h" 41#include "lldir.h"
42 42
43#include "llagent.h" 43#include "llagent.h"
44#include "llappviewer.h" // for gLastVersionChannel
44#include "llfloateravatarpicker.h" 45#include "llfloateravatarpicker.h"
45#include "llviewerwindow.h" 46#include "llviewerwindow.h"
46#include "llbutton.h" 47#include "llbutton.h"
47#include "llcallingcard.h"
48#include "llfloateravatarinfo.h" 48#include "llfloateravatarinfo.h"
49#include "llinventorymodel.h" 49#include "llinventorymodel.h"
50#include "llnamelistctrl.h" 50#include "llnamelistctrl.h"
@@ -143,7 +143,7 @@ void LLPanelFriends::updateFriends(U32 changed_mask)
143 LLDynamicArray<LLUUID> selected_friends = getSelectedIDs(); 143 LLDynamicArray<LLUUID> selected_friends = getSelectedIDs();
144 if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) 144 if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
145 { 145 {
146 refreshNames(); 146 refreshNames(changed_mask);
147 } 147 }
148 else if(changed_mask & LLFriendObserver::POWERS) 148 else if(changed_mask & LLFriendObserver::POWERS)
149 { 149 {
@@ -185,7 +185,8 @@ BOOL LLPanelFriends::postBuild()
185 childSetCommitCallback("friend_list", onSelectName, this); 185 childSetCommitCallback("friend_list", onSelectName, this);
186 childSetDoubleClickCallback("friend_list", onClickIM); 186 childSetDoubleClickCallback("friend_list", onClickIM);
187 187
188 refreshNames(); 188 U32 changed_mask = LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE;
189 refreshNames(changed_mask);
189 190
190 childSetAction("im_btn", onClickIM, this); 191 childSetAction("im_btn", onClickIM, this);
191 childSetAction("profile_btn", onClickProfile, this); 192 childSetAction("profile_btn", onClickProfile, this);
@@ -200,13 +201,12 @@ BOOL LLPanelFriends::postBuild()
200 refreshUI(); 201 refreshUI();
201 202
202 // primary sort = online status, secondary sort = name 203 // primary sort = online status, secondary sort = name
203 mFriendsList->sortByColumn("friend_name", TRUE); 204 mFriendsList->sortByColumn(std::string("friend_name"), TRUE);
204 mFriendsList->sortByColumn("icon_online_status", FALSE); 205 mFriendsList->sortByColumn(std::string("icon_online_status"), FALSE);
205 206
206 return TRUE; 207 return TRUE;
207} 208}
208 209
209
210BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) 210BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
211{ 211{
212 LLAvatarTracker& at = LLAvatarTracker::instance(); 212 LLAvatarTracker& at = LLAvatarTracker::instance();
@@ -264,7 +264,8 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
264 return have_name; 264 return have_name;
265} 265}
266 266
267// propagate actual relationship to UI 267// propagate actual relationship to UI.
268// Does not resort the UI list because it can be called frequently. JC
268BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationship* info) 269BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationship* info)
269{ 270{
270 if (!info) return FALSE; 271 if (!info) return FALSE;
@@ -274,7 +275,7 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
274 std::string fullname; 275 std::string fullname;
275 BOOL have_name = gCacheName->getFullName(agent_id, fullname); 276 BOOL have_name = gCacheName->getFullName(agent_id, fullname);
276 277
277 itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? "icon_avatar_online.tga" : LLString::null); 278 itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? std::string("icon_avatar_online.tga") : LLStringUtil::null);
278 itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname); 279 itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname);
279 // render name of online friends in bold text 280 // render name of online friends in bold text
280 ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL); 281 ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
@@ -287,9 +288,7 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
287 // enable this item, in case it was disabled after user input 288 // enable this item, in case it was disabled after user input
288 itemp->setEnabled(TRUE); 289 itemp->setEnabled(TRUE);
289 290
290 // changed item in place, need to request sort 291 // Do not resort, this function can be called frequently.
291 mFriendsList->sortItems();
292
293 return have_name; 292 return have_name;
294} 293}
295 294
@@ -326,14 +325,9 @@ void LLPanelFriends::refreshRightsChangeList()
326 { 325 {
327 if(!friend_status->isOnline()) 326 if(!friend_status->isOnline())
328 { 327 {
329 can_offer_teleport = false;
330 selected_friends_online = false; 328 selected_friends_online = false;
331 } 329 }
332 } 330 }
333 else // missing buddy info, don't allow any operations
334 {
335 can_offer_teleport = false;
336 }
337 } 331 }
338 332
339 if (num_selected == 0) // nothing selected 333 if (num_selected == 0) // nothing selected
@@ -359,7 +353,7 @@ struct SortFriendsByID
359 } 353 }
360}; 354};
361 355
362void LLPanelFriends::refreshNames() 356void LLPanelFriends::refreshNames(U32 changed_mask)
363{ 357{
364 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs(); 358 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs();
365 S32 pos = mFriendsList->getScrollPos(); 359 S32 pos = mFriendsList->getScrollPos();
@@ -367,27 +361,67 @@ void LLPanelFriends::refreshNames()
367 // get all buddies we know about 361 // get all buddies we know about
368 LLAvatarTracker::buddy_map_t all_buddies; 362 LLAvatarTracker::buddy_map_t all_buddies;
369 LLAvatarTracker::instance().copyBuddyList(all_buddies); 363 LLAvatarTracker::instance().copyBuddyList(all_buddies);
370 364
371 // get all friends in list and sort by UUID 365 BOOL have_names = TRUE;
366
367 if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
368 {
369 have_names &= refreshNamesSync(all_buddies);
370 }
371
372 if(changed_mask & LLFriendObserver::ONLINE)
373 {
374 have_names &= refreshNamesPresence(all_buddies);
375 }
376
377 if (!have_names)
378 {
379 mEventTimer.start();
380 }
381 // Changed item in place, need to request sort and update columns
382 // because we might have changed data in a column on which the user
383 // has already sorted. JC
384 mFriendsList->sortItems();
385
386 // re-select items
387 mFriendsList->selectMultiple(selected_ids);
388 mFriendsList->setScrollPos(pos);
389}
390
391BOOL LLPanelFriends::refreshNamesSync(const LLAvatarTracker::buddy_map_t & all_buddies)
392{
393 mFriendsList->deleteAllItems();
394
395 BOOL have_names = TRUE;
396 LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
397
398 for(; buddy_it != all_buddies.end(); ++buddy_it)
399 {
400 have_names &= addFriend(buddy_it->first);
401 }
402
403 return have_names;
404}
405
406BOOL LLPanelFriends::refreshNamesPresence(const LLAvatarTracker::buddy_map_t & all_buddies)
407{
372 std::vector<LLScrollListItem*> items = mFriendsList->getAllData(); 408 std::vector<LLScrollListItem*> items = mFriendsList->getAllData();
373 std::sort(items.begin(), items.end(), SortFriendsByID()); 409 std::sort(items.begin(), items.end(), SortFriendsByID());
374 410
375 std::vector<LLScrollListItem*>::iterator item_it = items.begin(); 411 LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
376 std::vector<LLScrollListItem*>::iterator item_end = items.end(); 412 std::vector<LLScrollListItem*>::const_iterator item_it = items.begin();
377
378 BOOL have_names = TRUE; 413 BOOL have_names = TRUE;
379 LLAvatarTracker::buddy_map_t::iterator buddy_it; 414
380 for (buddy_it = all_buddies.begin() ; buddy_it != all_buddies.end(); ++buddy_it) 415 while(true)
381 { 416 {
382 // erase any items that reflect residents who are no longer buddies 417 if(item_it == items.end() || buddy_it == all_buddies.end())
383 while(item_it != item_end && buddy_it->first > (*item_it)->getValue().asUUID())
384 { 418 {
385 mFriendsList->deleteItems((*item_it)->getValue()); 419 break;
386 ++item_it;
387 } 420 }
388 421
389 // update existing friends with new info 422 const LLUUID & buddy_uuid = buddy_it->first;
390 if (item_it != item_end && buddy_it->first == (*item_it)->getValue().asUUID()) 423 const LLUUID & item_uuid = (*item_it)->getValue().asUUID();
424 if(item_uuid == buddy_uuid)
391 { 425 {
392 const LLRelationship* info = buddy_it->second; 426 const LLRelationship* info = buddy_it->second;
393 if (!info) 427 if (!info)
@@ -402,27 +436,23 @@ void LLPanelFriends::refreshNames()
402 // update existing item in UI 436 // update existing item in UI
403 have_names &= updateFriendItem(buddy_it->first, info); 437 have_names &= updateFriendItem(buddy_it->first, info);
404 } 438 }
439
440 ++buddy_it;
405 ++item_it; 441 ++item_it;
406 } 442 }
407 // add new friend to list 443 else if(item_uuid < buddy_uuid)
408 else
409 { 444 {
410 have_names &= addFriend(buddy_it->first); 445 ++item_it;
446 }
447 else //if(item_uuid > buddy_uuid)
448 {
449 ++buddy_it;
411 } 450 }
412 } 451 }
413 if (!have_names)
414 {
415 mEventTimer.start();
416 }
417 // changed item in place, need to request sort and update columns
418 mFriendsList->sortItems();
419 452
420 // re-select items 453 return have_names;
421 mFriendsList->selectMultiple(selected_ids);
422 mFriendsList->setScrollPos(pos);
423} 454}
424 455
425
426void LLPanelFriends::refreshUI() 456void LLPanelFriends::refreshUI()
427{ 457{
428 BOOL single_selected = FALSE; 458 BOOL single_selected = FALSE;
@@ -443,7 +473,7 @@ void LLPanelFriends::refreshUI()
443 } 473 }
444 else 474 else
445 { 475 {
446 childSetText("friend_name_label", LLString::null); 476 childSetText("friend_name_label", LLStringUtil::null);
447 } 477 }
448 478
449 479
@@ -488,7 +518,7 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
488//static 518//static
489void LLPanelFriends::onMaximumSelect(void* user_data) 519void LLPanelFriends::onMaximumSelect(void* user_data)
490{ 520{
491 LLString::format_map_t args; 521 LLStringUtil::format_map_t args;
492 args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT); 522 args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT);
493 LLNotifyBox::showXml("MaxListSelectMessage", args); 523 LLNotifyBox::showXml("MaxListSelectMessage", args);
494}; 524};
@@ -539,16 +569,15 @@ void LLPanelFriends::onClickIM(void* user_data)
539} 569}
540 570
541// static 571// static
542void LLPanelFriends::requestFriendship(const LLUUID& target_id, const LLString& target_name) 572void LLPanelFriends::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
543{ 573{
544 // HACK: folder id stored as "message"
545 LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); 574 LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
546 std::string message = calling_card_folder_id.asString();
547 send_improved_im(target_id, 575 send_improved_im(target_id,
548 target_name.c_str(), 576 target_name,
549 message.c_str(), 577 message,
550 IM_ONLINE, 578 IM_ONLINE,
551 IM_FRIENDSHIP_OFFERED); 579 IM_FRIENDSHIP_OFFERED,
580 calling_card_folder_id);
552} 581}
553 582
554struct LLAddFriendData 583struct LLAddFriendData
@@ -558,12 +587,28 @@ struct LLAddFriendData
558}; 587};
559 588
560// static 589// static
590void LLPanelFriends::callbackAddFriendWithMessage(S32 option, const std::string& text, void* data)
591{
592 LLAddFriendData* add = (LLAddFriendData*)data;
593 if (option == 0)
594 {
595 requestFriendship(add->mID, add->mName, text);
596 }
597 delete add;
598}
599
600// static
561void LLPanelFriends::callbackAddFriend(S32 option, void* data) 601void LLPanelFriends::callbackAddFriend(S32 option, void* data)
562{ 602{
563 LLAddFriendData* add = (LLAddFriendData*)data; 603 LLAddFriendData* add = (LLAddFriendData*)data;
564 if (option == 0) 604 if (option == 0)
565 { 605 {
566 requestFriendship(add->mID, add->mName); 606 // Servers older than 1.25 require the text of the message to be the
607 // calling card folder ID for the offering user. JC
608 LLUUID calling_card_folder_id =
609 gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
610 std::string message = calling_card_folder_id.asString();
611 requestFriendship(add->mID, add->mName, message);
567 } 612 }
568 delete add; 613 delete add;
569} 614}
@@ -592,10 +637,20 @@ void LLPanelFriends::requestFriendshipDialog(const LLUUID& id,
592 data->mID = id; 637 data->mID = id;
593 data->mName = name; 638 data->mName = name;
594 639
595 // TODO: accept a line of text with this dialog 640 LLStringUtil::format_map_t args;
596 LLString::format_map_t args;
597 args["[NAME]"] = name; 641 args["[NAME]"] = name;
598 gViewerWindow->alertXml("AddFriend", args, callbackAddFriend, data); 642
643 // Look for server versions like: Second Life Server 1.24.4.95600
644 if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
645 {
646 // Old and busted server version, doesn't support friend
647 // requests with messages.
648 gViewerWindow->alertXml("AddFriend", args, callbackAddFriend, data);
649 }
650 else
651 {
652 gViewerWindow->alertXmlEditText("AddFriendWithMessage", args, NULL, NULL, callbackAddFriendWithMessage, data);
653 }
599} 654}
600 655
601// static 656// static
@@ -617,10 +672,10 @@ void LLPanelFriends::onClickRemove(void* user_data)
617 672
618 //llinfos << "LLPanelFriends::onClickRemove()" << llendl; 673 //llinfos << "LLPanelFriends::onClickRemove()" << llendl;
619 LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs(); 674 LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
620 LLStringBase<char>::format_map_t args; 675 LLStringUtil::format_map_t args;
621 if(ids.size() > 0) 676 if(ids.size() > 0)
622 { 677 {
623 LLString msgType = "RemoveFromFriends"; 678 std::string msgType = "RemoveFromFriends";
624 if(ids.size() == 1) 679 if(ids.size() == 1)
625 { 680 {
626 LLUUID agent_id = ids[0]; 681 LLUUID agent_id = ids[0];
@@ -670,7 +725,7 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
670{ 725{
671 if (ids.empty()) return; 726 if (ids.empty()) return;
672 727
673 LLStringBase<char>::format_map_t args; 728 LLStringUtil::format_map_t args;
674 if(ids.size() > 0) 729 if(ids.size() > 0)
675 { 730 {
676 // copy map of ids onto heap 731 // copy map of ids onto heap
@@ -732,6 +787,8 @@ void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data)
732 { 787 {
733 const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first); 788 const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
734 panelp->updateFriendItem(rights_it->first, info); 789 panelp->updateFriendItem(rights_it->first, info);
790 // Might have changed the column the user is sorted on.
791 panelp->mFriendsList->sortItems();
735 } 792 }
736 } 793 }
737 panelp->refreshUI(); 794 panelp->refreshUI();