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.cpp168
1 files changed, 115 insertions, 53 deletions
diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
index 1cb0689..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
@@ -354,7 +353,7 @@ struct SortFriendsByID
354 } 353 }
355}; 354};
356 355
357void LLPanelFriends::refreshNames() 356void LLPanelFriends::refreshNames(U32 changed_mask)
358{ 357{
359 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs(); 358 LLDynamicArray<LLUUID> selected_ids = getSelectedIDs();
360 S32 pos = mFriendsList->getScrollPos(); 359 S32 pos = mFriendsList->getScrollPos();
@@ -362,27 +361,67 @@ void LLPanelFriends::refreshNames()
362 // get all buddies we know about 361 // get all buddies we know about
363 LLAvatarTracker::buddy_map_t all_buddies; 362 LLAvatarTracker::buddy_map_t all_buddies;
364 LLAvatarTracker::instance().copyBuddyList(all_buddies); 363 LLAvatarTracker::instance().copyBuddyList(all_buddies);
365 364
366 // 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{
367 std::vector<LLScrollListItem*> items = mFriendsList->getAllData(); 408 std::vector<LLScrollListItem*> items = mFriendsList->getAllData();
368 std::sort(items.begin(), items.end(), SortFriendsByID()); 409 std::sort(items.begin(), items.end(), SortFriendsByID());
369 410
370 std::vector<LLScrollListItem*>::iterator item_it = items.begin(); 411 LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
371 std::vector<LLScrollListItem*>::iterator item_end = items.end(); 412 std::vector<LLScrollListItem*>::const_iterator item_it = items.begin();
372
373 BOOL have_names = TRUE; 413 BOOL have_names = TRUE;
374 LLAvatarTracker::buddy_map_t::iterator buddy_it; 414
375 for (buddy_it = all_buddies.begin() ; buddy_it != all_buddies.end(); ++buddy_it) 415 while(true)
376 { 416 {
377 // erase any items that reflect residents who are no longer buddies 417 if(item_it == items.end() || buddy_it == all_buddies.end())
378 while(item_it != item_end && buddy_it->first > (*item_it)->getValue().asUUID())
379 { 418 {
380 mFriendsList->deleteItems((*item_it)->getValue()); 419 break;
381 ++item_it;
382 } 420 }
383 421
384 // update existing friends with new info 422 const LLUUID & buddy_uuid = buddy_it->first;
385 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)
386 { 425 {
387 const LLRelationship* info = buddy_it->second; 426 const LLRelationship* info = buddy_it->second;
388 if (!info) 427 if (!info)
@@ -397,27 +436,23 @@ void LLPanelFriends::refreshNames()
397 // update existing item in UI 436 // update existing item in UI
398 have_names &= updateFriendItem(buddy_it->first, info); 437 have_names &= updateFriendItem(buddy_it->first, info);
399 } 438 }
439
440 ++buddy_it;
400 ++item_it; 441 ++item_it;
401 } 442 }
402 // add new friend to list 443 else if(item_uuid < buddy_uuid)
403 else
404 { 444 {
405 have_names &= addFriend(buddy_it->first); 445 ++item_it;
446 }
447 else //if(item_uuid > buddy_uuid)
448 {
449 ++buddy_it;
406 } 450 }
407 } 451 }
408 if (!have_names)
409 {
410 mEventTimer.start();
411 }
412 // changed item in place, need to request sort and update columns
413 mFriendsList->sortItems();
414 452
415 // re-select items 453 return have_names;
416 mFriendsList->selectMultiple(selected_ids);
417 mFriendsList->setScrollPos(pos);
418} 454}
419 455
420
421void LLPanelFriends::refreshUI() 456void LLPanelFriends::refreshUI()
422{ 457{
423 BOOL single_selected = FALSE; 458 BOOL single_selected = FALSE;
@@ -438,7 +473,7 @@ void LLPanelFriends::refreshUI()
438 } 473 }
439 else 474 else
440 { 475 {
441 childSetText("friend_name_label", LLString::null); 476 childSetText("friend_name_label", LLStringUtil::null);
442 } 477 }
443 478
444 479
@@ -483,7 +518,7 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
483//static 518//static
484void LLPanelFriends::onMaximumSelect(void* user_data) 519void LLPanelFriends::onMaximumSelect(void* user_data)
485{ 520{
486 LLString::format_map_t args; 521 LLStringUtil::format_map_t args;
487 args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT); 522 args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT);
488 LLNotifyBox::showXml("MaxListSelectMessage", args); 523 LLNotifyBox::showXml("MaxListSelectMessage", args);
489}; 524};
@@ -534,16 +569,15 @@ void LLPanelFriends::onClickIM(void* user_data)
534} 569}
535 570
536// static 571// static
537void 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)
538{ 573{
539 // HACK: folder id stored as "message"
540 LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); 574 LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
541 std::string message = calling_card_folder_id.asString();
542 send_improved_im(target_id, 575 send_improved_im(target_id,
543 target_name.c_str(), 576 target_name,
544 message.c_str(), 577 message,
545 IM_ONLINE, 578 IM_ONLINE,
546 IM_FRIENDSHIP_OFFERED); 579 IM_FRIENDSHIP_OFFERED,
580 calling_card_folder_id);
547} 581}
548 582
549struct LLAddFriendData 583struct LLAddFriendData
@@ -553,12 +587,28 @@ struct LLAddFriendData
553}; 587};
554 588
555// 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
556void LLPanelFriends::callbackAddFriend(S32 option, void* data) 601void LLPanelFriends::callbackAddFriend(S32 option, void* data)
557{ 602{
558 LLAddFriendData* add = (LLAddFriendData*)data; 603 LLAddFriendData* add = (LLAddFriendData*)data;
559 if (option == 0) 604 if (option == 0)
560 { 605 {
561 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);
562 } 612 }
563 delete add; 613 delete add;
564} 614}
@@ -587,10 +637,20 @@ void LLPanelFriends::requestFriendshipDialog(const LLUUID& id,
587 data->mID = id; 637 data->mID = id;
588 data->mName = name; 638 data->mName = name;
589 639
590 // TODO: accept a line of text with this dialog 640 LLStringUtil::format_map_t args;
591 LLString::format_map_t args;
592 args["[NAME]"] = name; 641 args["[NAME]"] = name;
593 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 }
594} 654}
595 655
596// static 656// static
@@ -612,10 +672,10 @@ void LLPanelFriends::onClickRemove(void* user_data)
612 672
613 //llinfos << "LLPanelFriends::onClickRemove()" << llendl; 673 //llinfos << "LLPanelFriends::onClickRemove()" << llendl;
614 LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs(); 674 LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
615 LLStringBase<char>::format_map_t args; 675 LLStringUtil::format_map_t args;
616 if(ids.size() > 0) 676 if(ids.size() > 0)
617 { 677 {
618 LLString msgType = "RemoveFromFriends"; 678 std::string msgType = "RemoveFromFriends";
619 if(ids.size() == 1) 679 if(ids.size() == 1)
620 { 680 {
621 LLUUID agent_id = ids[0]; 681 LLUUID agent_id = ids[0];
@@ -665,7 +725,7 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
665{ 725{
666 if (ids.empty()) return; 726 if (ids.empty()) return;
667 727
668 LLStringBase<char>::format_map_t args; 728 LLStringUtil::format_map_t args;
669 if(ids.size() > 0) 729 if(ids.size() > 0)
670 { 730 {
671 // copy map of ids onto heap 731 // copy map of ids onto heap
@@ -727,6 +787,8 @@ void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data)
727 { 787 {
728 const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first); 788 const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
729 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();
730 } 792 }
731 } 793 }
732 panelp->refreshUI(); 794 panelp->refreshUI();