This adds mStatus, mReason and mContent to ResponderBase and fills those in instead of passing it to member functions. The added danger here is that now code can accidently try to access these variables while they didn't already get a correct value. Affected members of ResponderBase (that now have less arguments): decode_llsd_body, decode_raw_body, completedHeaders, completed -> httpCompleted, result -> httpSuccess, errorWithContent and error -> httpFailure. New API: ResponderBase::setResult ResponderBase::getStatus() ResponderBase::getReason() ResponderBase::getContent() ResponderBase::getResponseHeaders() (returns AIHTTPReceivedHeaders though, not LLSD) ResponderBase::dumpResponse() ResponderWithCompleted::completeResult ResponderWithResult::failureResult (previously pubErrorWithContent) ResponderWithResult::successResult (previously pubResult) Not implemented: getHTTPMethod() - use getName() instead which returns the class name of the responder. completedHeaders() is still called as usual, although you can ignore it (not implement in a derived responder) and call getResponseHeaders() instead, provided you implement needsHeaders() and have it return true. However, classes derived from ResponderHeadersOnly do not have completedHeaders(), so they still must implement completedHeaders(), and then call getResponseHeaders() or just access mReceivedHeaders directly, as usual.
788 lines
22 KiB
C++
788 lines
22 KiB
C++
/**
|
|
* @file llfloateravatarpicker.cpp
|
|
*
|
|
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llfloateravatarpicker.h"
|
|
|
|
// Viewer includes
|
|
#include "llagent.h"
|
|
#include "llcallingcard.h"
|
|
#include "llfocusmgr.h"
|
|
#include "llimview.h" // for gIMMgr
|
|
#include "lltooldraganddrop.h" // for LLToolDragAndDrop
|
|
#include "llviewercontrol.h"
|
|
#include "llviewerregion.h" // getCapability()
|
|
#include "llworld.h"
|
|
// [RLVa:KB] - Checked: 2010-06-04 (RLVa-1.2.2a)
|
|
#include "rlvactions.h"
|
|
#include "rlvhandler.h"
|
|
// [/RLVa:KB]
|
|
|
|
// Linden libraries
|
|
#include "llavatarnamecache.h" // IDEVO
|
|
#include "llbutton.h"
|
|
#include "llcachename.h"
|
|
#include "lllineeditor.h"
|
|
#include "llscrolllistctrl.h"
|
|
#include "llscrolllistitem.h"
|
|
#include "lltabcontainer.h"
|
|
#include "lluictrlfactory.h"
|
|
#include "message.h"
|
|
|
|
|
|
//put it back as a member once the legacy path is out?
|
|
static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
|
|
|
|
LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
|
|
BOOL allow_multiple,
|
|
BOOL closeOnSelect)
|
|
{
|
|
// *TODO: Use a key to allow this not to be an effective singleton
|
|
|
|
LLFloaterAvatarPicker* floater = getInstance();
|
|
floater->open();
|
|
|
|
floater->mSelectionCallback = callback;
|
|
floater->setAllowMultiple(allow_multiple);
|
|
floater->mNearMeListComplete = FALSE;
|
|
floater->mCloseOnSelect = closeOnSelect;
|
|
|
|
if (!closeOnSelect)
|
|
{
|
|
// Use Select/Close
|
|
std::string select_string = floater->getString("Select");
|
|
std::string close_string = floater->getString("Close");
|
|
floater->getChild<LLButton>("ok_btn")->setLabel(select_string);
|
|
floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
|
|
}
|
|
|
|
return floater;
|
|
}
|
|
|
|
// Default constructor
|
|
LLFloaterAvatarPicker::LLFloaterAvatarPicker()
|
|
: LLFloater(),
|
|
mNumResultsReturned(0),
|
|
mNearMeListComplete(FALSE),
|
|
mCloseOnSelect(FALSE)
|
|
{
|
|
mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
|
|
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL);
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::postBuild()
|
|
{
|
|
getChild<LLLineEditor>("Edit")->setKeystrokeCallback(boost::bind(&LLFloaterAvatarPicker::editKeystroke,this,_1));
|
|
getChild<LLLineEditor>("EditUUID")->setKeystrokeCallback(boost::bind(&LLFloaterAvatarPicker::editKeystroke, this,_1));
|
|
|
|
childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this));
|
|
getChildView("Find")->setEnabled(FALSE);
|
|
childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this));
|
|
getChild<LLUICtrl>("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this));
|
|
|
|
LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>("SearchResults");
|
|
searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
getChildView("SearchResults")->setEnabled(FALSE);
|
|
|
|
LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
|
|
nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
|
|
LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
|
|
friends->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
getChild<LLUICtrl>("Friends")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
|
|
|
|
childSetAction("ok_btn", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
childSetAction("cancel_btn", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this));
|
|
|
|
getChild<LLUICtrl>("Edit")->setFocus(TRUE);
|
|
|
|
LLPanel* search_panel = getChild<LLPanel>("SearchPanel");
|
|
if (search_panel)
|
|
{
|
|
// Start searching when Return is pressed in the line editor.
|
|
search_panel->setDefaultBtn("Find");
|
|
}
|
|
|
|
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("no_results"));
|
|
|
|
getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(
|
|
boost::bind(&LLFloaterAvatarPicker::onTabChanged, this));
|
|
|
|
setAllowMultiple(FALSE);
|
|
|
|
center();
|
|
|
|
populateFriend();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::setOkBtnEnableCb(validate_callback_t cb)
|
|
{
|
|
mOkButtonValidateSignal.connect(cb);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onTabChanged()
|
|
{
|
|
getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
|
|
}
|
|
|
|
// Destroys the object
|
|
LLFloaterAvatarPicker::~LLFloaterAvatarPicker()
|
|
{
|
|
gFocusMgr.releaseFocusIfNeeded( this );
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnFind()
|
|
{
|
|
find();
|
|
}
|
|
|
|
static void addAvatarUUID(const LLUUID av_id, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
|
|
{
|
|
if (av_id.notNull())
|
|
{
|
|
avatar_ids.push_back(av_id);
|
|
|
|
std::map<LLUUID, LLAvatarName>::iterator iter = sAvatarNameMap.find(av_id);
|
|
if (iter != sAvatarNameMap.end())
|
|
{
|
|
avatar_names.push_back(iter->second);
|
|
}
|
|
else
|
|
{
|
|
// the only case where it isn't in the name map is friends
|
|
// but it should be in the name cache
|
|
LLAvatarName av_name;
|
|
LLAvatarNameCache::get(av_id, &av_name);
|
|
avatar_names.push_back(av_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void getSelectedAvatarData(const LLUICtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
|
|
{
|
|
const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from);
|
|
if(list)
|
|
{
|
|
std::vector<LLScrollListItem*> items = list->getAllSelected();
|
|
for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
|
|
{
|
|
addAvatarUUID((*iter)->getUUID(), avatar_ids, avatar_names);
|
|
}
|
|
}
|
|
else
|
|
addAvatarUUID(from->getValue().asUUID(), avatar_ids, avatar_names);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnSelect()
|
|
{
|
|
|
|
// If select btn not enabled then do not callback
|
|
if (!isSelectBtnEnabled())
|
|
return;
|
|
|
|
if(mSelectionCallback)
|
|
{
|
|
std::string active_panel_name;
|
|
LLUICtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
if(active_panel)
|
|
{
|
|
active_panel_name = active_panel->getName();
|
|
}
|
|
if(active_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(active_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (active_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
else if(active_panel_name == "KeyPanel")
|
|
{
|
|
list = getChild<LLLineEditor>("EditUUID");
|
|
}
|
|
|
|
if(list)
|
|
{
|
|
uuid_vec_t avatar_ids;
|
|
std::vector<LLAvatarName> avatar_names;
|
|
getSelectedAvatarData(list, avatar_ids, avatar_names);
|
|
mSelectionCallback(avatar_ids, avatar_names);
|
|
}
|
|
}
|
|
getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
|
|
getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
|
|
getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
|
|
if(mCloseOnSelect)
|
|
{
|
|
mCloseOnSelect = FALSE;
|
|
close();
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnRefresh()
|
|
{
|
|
getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
|
|
getChild<LLScrollListCtrl>("NearMe")->setCommentText(getString("searching"));
|
|
mNearMeListComplete = FALSE;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onBtnClose()
|
|
{
|
|
close();
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onRangeAdjust()
|
|
{
|
|
onBtnRefresh();
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::onList()
|
|
{
|
|
getChildView("ok_btn")->setEnabled(isSelectBtnEnabled());
|
|
|
|
// [RLVa:KB] - Checked: 2010-06-05 (RLVa-1.2.2a) | Modified: RLVa-1.2.0d
|
|
if (rlv_handler_t::isEnabled())
|
|
{
|
|
LLTabContainer* pTabs = getChild<LLTabContainer>("ResidentChooserTabs");
|
|
LLPanel* pNearMePanel = getChild<LLPanel>("NearMePanel");
|
|
RLV_ASSERT( (pTabs) && (pNearMePanel) );
|
|
if ( (pTabs) && (pNearMePanel) )
|
|
{
|
|
bool fRlvEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES);
|
|
pTabs->enableTabButton(pTabs->getIndexForPanel(pNearMePanel), fRlvEnable);
|
|
if ( (!fRlvEnable) && (pTabs->getCurrentPanel() == pNearMePanel) )
|
|
pTabs->selectTabByName("SearchPanel");
|
|
}
|
|
}
|
|
// [/RLVa:KB]
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::populateNearMe()
|
|
{
|
|
BOOL all_loaded = TRUE;
|
|
BOOL empty = TRUE;
|
|
LLScrollListCtrl* near_me_scroller = getChild<LLScrollListCtrl>("NearMe");
|
|
near_me_scroller->deleteAllItems();
|
|
|
|
uuid_vec_t avatar_ids;
|
|
LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
|
|
for(U32 i=0; i<avatar_ids.size(); i++)
|
|
{
|
|
LLUUID& av = avatar_ids[i];
|
|
if(av == gAgent.getID()) continue;
|
|
LLSD element;
|
|
element["id"] = av; // value
|
|
LLAvatarName av_name;
|
|
|
|
if (!LLAvatarNameCache::get(av, &av_name))
|
|
{
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = LLCacheName::getDefaultName();
|
|
all_loaded = FALSE;
|
|
}
|
|
else
|
|
{
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = av_name.mDisplayName;
|
|
element["columns"][1]["column"] = "username";
|
|
element["columns"][1]["value"] = av_name.mUsername;
|
|
|
|
sAvatarNameMap[av] = av_name;
|
|
}
|
|
near_me_scroller->addElement(element);
|
|
empty = FALSE;
|
|
}
|
|
|
|
if (empty)
|
|
{
|
|
getChildView("NearMe")->setEnabled(FALSE);
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
near_me_scroller->setCommentText(getString("no_one_near"));
|
|
}
|
|
else
|
|
{
|
|
getChildView("NearMe")->setEnabled(TRUE);
|
|
getChildView("ok_btn")->setEnabled(TRUE);
|
|
near_me_scroller->selectFirstItem();
|
|
onList();
|
|
near_me_scroller->setFocus(TRUE);
|
|
}
|
|
|
|
if (all_loaded)
|
|
{
|
|
mNearMeListComplete = TRUE;
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::populateFriend()
|
|
{
|
|
LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends");
|
|
friends_scroller->deleteAllItems();
|
|
LLCollectAllBuddies collector;
|
|
LLAvatarTracker::instance().applyFunctor(collector);
|
|
LLCollectAllBuddies::buddy_map_t::iterator it;
|
|
|
|
for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
|
|
{
|
|
friends_scroller->addStringUUIDItem(it->first, it->second);
|
|
}
|
|
for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++)
|
|
{
|
|
friends_scroller->addStringUUIDItem(it->first, it->second);
|
|
}
|
|
friends_scroller->sortByColumnIndex(0, TRUE);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::draw()
|
|
{
|
|
// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
|
|
// lets check this via mOkButtonValidateSignal callback periodically.
|
|
static LLFrameTimer timer;
|
|
if (timer.hasExpired())
|
|
{
|
|
timer.setTimerExpirySec(0.33f); // three times per second should be enough.
|
|
|
|
// simulate list changes.
|
|
onList();
|
|
timer.start();
|
|
}
|
|
|
|
LLFloater::draw();
|
|
if (!mNearMeListComplete && getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel() == getChild<LLPanel>("NearMePanel"))
|
|
{
|
|
populateNearMe();
|
|
}
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
|
|
{
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
|
|
if(active_panel == getChild<LLPanel>("SearchPanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("SearchResults")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("NearMePanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("FriendsPanel"))
|
|
{
|
|
return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
|
|
}
|
|
else if(active_panel == getChild<LLPanel>("KeyPanel"))
|
|
{
|
|
LLUUID specified = getChild<LLLineEditor>("EditUUID")->getValue().asUUID();
|
|
return !specified.isNull();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
extern AIHTTPTimeoutPolicy avatarPickerResponder_timeout;
|
|
class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted
|
|
{
|
|
public:
|
|
LLUUID mQueryID;
|
|
|
|
LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
|
|
|
|
/*virtual*/ void httpCompleted(void)
|
|
{
|
|
//std::ostringstream ss;
|
|
//LLSDSerialize::toPrettyXML(mContent, ss);
|
|
//llinfos << ss.str() << llendl;
|
|
|
|
// in case of invalid characters, the avatar picker returns a 400
|
|
// just set it to process so it displays 'not found'
|
|
if (isGoodStatus(mStatus) || mStatus == 400)
|
|
{
|
|
if (LLFloaterAvatarPicker::instanceExists())
|
|
{
|
|
LLFloaterAvatarPicker::getInstance()->processResponse(mQueryID, mContent);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
llwarns << "avatar picker failed " << mStatus << " reason " << mReason << llendl;
|
|
|
|
}
|
|
}
|
|
|
|
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return avatarPickerResponder_timeout; }
|
|
/*virtual*/ char const* getName(void) const { return "LLAvatarPickerResponder"; }
|
|
};
|
|
|
|
void LLFloaterAvatarPicker::find()
|
|
{
|
|
//clear our stored LLAvatarNames
|
|
sAvatarNameMap.clear();
|
|
|
|
std::string text = getChild<LLUICtrl>("Edit")->getValue().asString();
|
|
|
|
mQueryID.generate();
|
|
|
|
std::string url;
|
|
url.reserve(128); // avoid a memory allocation or two
|
|
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
url = region->getCapability("AvatarPickerSearch");
|
|
// Prefer use of capabilities to search on both SLID and display name
|
|
// but allow display name search to be manually turned off for test
|
|
if (!url.empty()
|
|
&& LLAvatarNameCache::useDisplayNames())
|
|
{
|
|
// capability urls don't end in '/', but we need one to parse
|
|
// query parameters correctly
|
|
if (url.size() > 0 && url[url.size()-1] != '/')
|
|
{
|
|
url += "/";
|
|
}
|
|
url += "?page_size=100&names=";
|
|
url += LLURI::escape(text);
|
|
llinfos << "avatar picker " << url << llendl;
|
|
LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
|
|
}
|
|
else
|
|
{
|
|
LLMessageSystem* msg = gMessageSystem;
|
|
msg->newMessage("AvatarPickerRequest");
|
|
msg->nextBlock("AgentData");
|
|
msg->addUUID("AgentID", gAgent.getID());
|
|
msg->addUUID("SessionID", gAgent.getSessionID());
|
|
msg->addUUID("QueryID", mQueryID); // not used right now
|
|
msg->nextBlock("Data");
|
|
msg->addString("Name", text);
|
|
gAgent.sendReliableMessage();
|
|
}
|
|
|
|
getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
|
|
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
|
|
|
|
getChildView("ok_btn")->setEnabled(FALSE);
|
|
mNumResultsReturned = 0;
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
|
|
{
|
|
getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
|
|
getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
|
|
getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
|
|
}
|
|
|
|
LLScrollListCtrl* LLFloaterAvatarPicker::getActiveList()
|
|
{
|
|
std::string acvtive_panel_name;
|
|
LLScrollListCtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
if(active_panel)
|
|
{
|
|
acvtive_panel_name = active_panel->getName();
|
|
}
|
|
if(acvtive_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(acvtive_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (acvtive_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
return list;
|
|
}
|
|
|
|
BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,
|
|
BOOL drop, EDragAndDropType cargo_type,
|
|
void *cargo_data, EAcceptance *accept,
|
|
std::string& tooltip_msg)
|
|
{
|
|
LLScrollListCtrl* list = getActiveList();
|
|
if(list)
|
|
{
|
|
LLRect rc_list;
|
|
LLRect rc_point(x,y,x,y);
|
|
if (localRectToOtherView(rc_point, &rc_list, list))
|
|
{
|
|
// Keep selected only one item
|
|
list->deselectAllItems(TRUE);
|
|
list->selectItemAt(rc_list.mLeft, rc_list.mBottom, mask);
|
|
LLScrollListItem* selection = list->getFirstSelected();
|
|
if (selection)
|
|
{
|
|
LLUUID session_id = LLUUID::null;
|
|
LLUUID dest_agent_id = selection->getUUID();
|
|
std::string avatar_name = selection->getColumn(0)->getValue().asString();
|
|
if (dest_agent_id.notNull() && dest_agent_id != gAgentID)
|
|
{
|
|
// if (drop)
|
|
// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0)
|
|
if ( (drop) && (RlvActions::canStartIM(dest_agent_id)) )
|
|
// [/RLVa:KB]
|
|
{
|
|
// Start up IM before give the item
|
|
session_id = gIMMgr->addSession(avatar_name, IM_NOTHING_SPECIAL, dest_agent_id);
|
|
}
|
|
return LLToolDragAndDrop::handleGiveDragAndDrop(dest_agent_id, session_id, drop,
|
|
cargo_type, cargo_data, accept);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*accept = ACCEPT_NO;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void LLFloaterAvatarPicker::openFriendsTab()
|
|
{
|
|
LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs");
|
|
if (tab_container == NULL)
|
|
{
|
|
llassert(tab_container != NULL);
|
|
return;
|
|
}
|
|
|
|
tab_container->selectTabByName("FriendsPanel");
|
|
}
|
|
|
|
// static
|
|
void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**)
|
|
{
|
|
LLUUID agent_id;
|
|
LLUUID query_id;
|
|
LLUUID avatar_id;
|
|
std::string first_name;
|
|
std::string last_name;
|
|
|
|
msg->getUUID("AgentData", "AgentID", agent_id);
|
|
msg->getUUID("AgentData", "QueryID", query_id);
|
|
|
|
// Not for us
|
|
if (agent_id != gAgent.getID()) return;
|
|
|
|
if(!instanceExists())
|
|
return;
|
|
LLFloaterAvatarPicker* floater = getInstance();
|
|
|
|
// floater is closed or these are not results from our last request
|
|
if (NULL == floater || query_id != floater->mQueryID)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LLScrollListCtrl* search_results = floater->getChild<LLScrollListCtrl>("SearchResults");
|
|
|
|
// clear "Searching" label on first results
|
|
if (floater->mNumResultsReturned++ == 0)
|
|
{
|
|
search_results->deleteAllItems();
|
|
}
|
|
|
|
BOOL found_one = FALSE;
|
|
S32 num_new_rows = msg->getNumberOfBlocks("Data");
|
|
for (S32 i = 0; i < num_new_rows; i++)
|
|
{
|
|
msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i);
|
|
msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);
|
|
msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i);
|
|
|
|
std::string avatar_name;
|
|
if (avatar_id.isNull())
|
|
{
|
|
LLStringUtil::format_map_t map;
|
|
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
|
|
avatar_name = floater->getString("not_found", map);
|
|
search_results->setEnabled(FALSE);
|
|
floater->getChildView("ok_btn")->setEnabled(FALSE);
|
|
}
|
|
else
|
|
{
|
|
avatar_name = LLCacheName::buildFullName(first_name, last_name);
|
|
search_results->setEnabled(TRUE);
|
|
found_one = TRUE;
|
|
|
|
LLAvatarName av_name;
|
|
av_name.mLegacyFirstName = first_name;
|
|
av_name.mLegacyLastName = last_name;
|
|
av_name.mDisplayName = avatar_name;
|
|
const LLUUID& agent_id = avatar_id;
|
|
sAvatarNameMap[agent_id] = av_name;
|
|
|
|
}
|
|
LLSD element;
|
|
element["id"] = avatar_id; // value
|
|
element["columns"][0]["column"] = "name";
|
|
element["columns"][0]["value"] = avatar_name;
|
|
search_results->addElement(element);
|
|
}
|
|
|
|
if (found_one)
|
|
{
|
|
floater->getChildView("ok_btn")->setEnabled(TRUE);
|
|
search_results->selectFirstItem();
|
|
floater->onList();
|
|
search_results->setFocus(TRUE);
|
|
}
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)
|
|
{
|
|
// Check for out-of-date query
|
|
if (query_id != mQueryID) return;
|
|
|
|
LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults");
|
|
|
|
LLSD agents = content["agents"];
|
|
if (agents.size() == 0)
|
|
{
|
|
LLStringUtil::format_map_t map;
|
|
map["[TEXT]"] = childGetText("Edit");
|
|
LLSD item;
|
|
item["id"] = LLUUID::null;
|
|
item["columns"][0]["column"] = "name";
|
|
item["columns"][0]["value"] = getString("not_found", map);
|
|
search_results->addElement(item);
|
|
search_results->setEnabled(false);
|
|
getChildView("ok_btn")->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
// clear "Searching" label on first results
|
|
search_results->deleteAllItems();
|
|
|
|
LLSD item;
|
|
LLSD::array_const_iterator it = agents.beginArray();
|
|
for ( ; it != agents.endArray(); ++it)
|
|
{
|
|
const LLSD& row = *it;
|
|
item["id"] = row["id"];
|
|
LLSD& columns = item["columns"];
|
|
columns[0]["column"] = "name";
|
|
columns[0]["value"] = row["display_name"];
|
|
columns[1]["column"] = "username";
|
|
columns[1]["value"] = row["username"];
|
|
search_results->addElement(item);
|
|
|
|
// add the avatar name to our list
|
|
LLAvatarName avatar_name;
|
|
avatar_name.fromLLSD(row);
|
|
sAvatarNameMap[row["id"].asUUID()] = avatar_name;
|
|
}
|
|
|
|
getChildView("ok_btn")->setEnabled(true);
|
|
search_results->setEnabled(true);
|
|
search_results->selectFirstItem();
|
|
onList();
|
|
search_results->setFocus(TRUE);
|
|
}
|
|
|
|
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller)
|
|
{
|
|
if(caller->getName() == "Edit")
|
|
getChildView("Find")->setEnabled(caller->getText().size() >= 3);
|
|
else
|
|
childSetEnabled("Select", caller->getValue().asUUID().notNull());
|
|
}
|
|
|
|
// virtual
|
|
BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)
|
|
{
|
|
if (key == KEY_RETURN && mask == MASK_NONE)
|
|
{
|
|
if (getChild<LLUICtrl>("Edit")->hasFocus())
|
|
{
|
|
onBtnFind();
|
|
}
|
|
else
|
|
{
|
|
onBtnSelect();
|
|
}
|
|
return TRUE;
|
|
}
|
|
else if (key == KEY_ESCAPE && mask == MASK_NONE)
|
|
{
|
|
close();
|
|
return TRUE;
|
|
}
|
|
|
|
return LLFloater::handleKeyHere(key, mask);
|
|
}
|
|
|
|
bool LLFloaterAvatarPicker::isSelectBtnEnabled()
|
|
{
|
|
bool ret_val = visibleItemsSelected();
|
|
|
|
if ( ret_val && mOkButtonValidateSignal.num_slots() )
|
|
{
|
|
std::string active_panel_name;
|
|
LLUICtrl* list = NULL;
|
|
LLPanel* active_panel = getChild<LLTabContainer>("ResidentChooserTabs")->getCurrentPanel();
|
|
|
|
if(active_panel)
|
|
{
|
|
active_panel_name = active_panel->getName();
|
|
}
|
|
if(active_panel_name == "SearchPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("SearchResults");
|
|
}
|
|
else if(active_panel_name == "NearMePanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("NearMe");
|
|
}
|
|
else if (active_panel_name == "FriendsPanel")
|
|
{
|
|
list = getChild<LLScrollListCtrl>("Friends");
|
|
}
|
|
else if(active_panel_name == "KeyPanel")
|
|
{
|
|
list = getChild<LLLineEditor>("EditUUID");
|
|
}
|
|
|
|
if(list)
|
|
{
|
|
uuid_vec_t avatar_ids;
|
|
std::vector<LLAvatarName> avatar_names;
|
|
getSelectedAvatarData(list, avatar_ids, avatar_names);
|
|
return mOkButtonValidateSignal(avatar_ids);
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|