709 lines
22 KiB
C++
709 lines
22 KiB
C++
/**
|
|
* @file llpanelgroupinvite.cpp
|
|
*
|
|
* $LicenseInfo:firstyear=2006&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 "llpanelgroupinvite.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llavatarnamecache.h"
|
|
#include "llfloateravatarpicker.h"
|
|
#include "llbutton.h"
|
|
#include "llcallingcard.h"
|
|
#include "llcombobox.h"
|
|
#include "llgroupactions.h"
|
|
#include "llgroupmgr.h"
|
|
#include "llnamelistctrl.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "llscrolllistitem.h"
|
|
#include "llspinctrl.h"
|
|
#include "lltextbox.h"
|
|
#include "llviewerobject.h"
|
|
#include "llviewerobjectlist.h"
|
|
#include "lluictrlfactory.h"
|
|
#include "llviewerwindow.h"
|
|
|
|
class LLPanelGroupInvite::impl
|
|
{
|
|
public:
|
|
impl(const LLUUID& group_id);
|
|
~impl();
|
|
|
|
void addUsers(const std::vector<std::string>& names,
|
|
const uuid_vec_t& agent_ids);
|
|
void submitInvitations();
|
|
void addRoleNames(LLGroupMgrGroupData* gdatap);
|
|
void handleRemove();
|
|
void handleSelection();
|
|
|
|
static void callbackClickCancel(void* userdata);
|
|
static void callbackClickOK(void* userdata);
|
|
static void callbackClickAdd(void* userdata);
|
|
static void callbackClickRemove(void* userdata);
|
|
static void callbackSelect(LLUICtrl* ctrl, void* userdata);
|
|
static void callbackAddUsers(const uuid_vec_t& agent_ids,
|
|
void* user_data);
|
|
|
|
static void onAvatarNameCache(const LLUUID& agent_id,
|
|
const LLAvatarName& av_name,
|
|
void* user_data);
|
|
|
|
bool inviteOwnerCallback(const LLSD& notification, const LLSD& response);
|
|
|
|
public:
|
|
LLUUID mGroupID;
|
|
|
|
std::string mLoadingText;
|
|
LLNameListCtrl *mInvitees;
|
|
LLComboBox *mRoleNames;
|
|
LLButton *mOKButton;
|
|
LLButton *mRemoveButton;
|
|
LLTextBox *mGroupName;
|
|
std::string mOwnerWarning;
|
|
std::string mAlreadyInGroup;
|
|
std::string mTooManySelected;
|
|
bool mConfirmedOwnerInvite;
|
|
std::set<LLUUID> mInviteeIDs;
|
|
|
|
void (*mCloseCallback)(void* data);
|
|
|
|
void* mCloseCallbackUserData;
|
|
|
|
boost::signals2::connection mAvatarNameCacheConnection;
|
|
};
|
|
|
|
|
|
LLPanelGroupInvite::impl::impl(const LLUUID& group_id):
|
|
mGroupID( group_id ),
|
|
mLoadingText (),
|
|
mInvitees ( NULL ),
|
|
mRoleNames( NULL ),
|
|
mOKButton ( NULL ),
|
|
mRemoveButton( NULL ),
|
|
mGroupName( NULL ),
|
|
mConfirmedOwnerInvite( false ),
|
|
mCloseCallback( NULL ),
|
|
mCloseCallbackUserData( NULL ),
|
|
mAvatarNameCacheConnection()
|
|
{
|
|
}
|
|
|
|
LLPanelGroupInvite::impl::~impl()
|
|
{
|
|
if (mAvatarNameCacheConnection.connected())
|
|
{
|
|
mAvatarNameCacheConnection.disconnect();
|
|
}
|
|
}
|
|
|
|
const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap.
|
|
|
|
void LLPanelGroupInvite::impl::addUsers(const std::vector<std::string>& names,
|
|
const uuid_vec_t& agent_ids)
|
|
{
|
|
std::string name;
|
|
LLUUID id;
|
|
|
|
if (names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES)
|
|
{
|
|
// Fail! Show a warning and don't add any names.
|
|
LLSD msg;
|
|
msg["MESSAGE"] = mTooManySelected;
|
|
LLNotificationsUtil::add("GenericAlert", msg);
|
|
return;
|
|
}
|
|
|
|
for (S32 i = 0; i < (S32)names.size(); i++)
|
|
{
|
|
name = names[i];
|
|
id = agent_ids[i];
|
|
|
|
// Make sure this agent isn't already in the list.
|
|
if (mInviteeIDs.find(id) != mInviteeIDs.end())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//add the name to the names list
|
|
LLSD row;
|
|
row["id"] = id;
|
|
row["columns"][0]["value"] = name;
|
|
|
|
mInvitees->addElement(row);
|
|
mInviteeIDs.insert(id);
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::submitInvitations()
|
|
{
|
|
std::map<LLUUID, LLUUID> role_member_pairs;
|
|
|
|
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
|
|
|
|
// Default to everyone role.
|
|
LLUUID role_id = LLUUID::null;
|
|
|
|
if (mRoleNames)
|
|
{
|
|
role_id = mRoleNames->getCurrentID();
|
|
|
|
// owner role: display confirmation and wait for callback
|
|
if ((role_id == gdatap->mOwnerRole) && (!mConfirmedOwnerInvite))
|
|
{
|
|
LLSD args;
|
|
args["MESSAGE"] = mOwnerWarning;
|
|
LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2));
|
|
return; // we'll be called again if user confirms
|
|
}
|
|
}
|
|
|
|
bool already_in_group = false;
|
|
//loop over the users
|
|
std::vector<LLScrollListItem*> items = mInvitees->getAllData();
|
|
for (std::vector<LLScrollListItem*>::iterator iter = items.begin();
|
|
iter != items.end(); ++iter)
|
|
{
|
|
LLScrollListItem* item = *iter;
|
|
if(LLGroupActions::isAvatarMemberOfGroup(mGroupID, item->getUUID()))
|
|
{
|
|
already_in_group = true;
|
|
continue;
|
|
}
|
|
role_member_pairs[item->getUUID()] = role_id;
|
|
}
|
|
|
|
if (role_member_pairs.size() > MAX_GROUP_INVITES)
|
|
{
|
|
// Fail!
|
|
LLSD msg;
|
|
msg["MESSAGE"] = mTooManySelected;
|
|
LLNotificationsUtil::add("GenericAlert", msg);
|
|
(*mCloseCallback)(mCloseCallbackUserData);
|
|
return;
|
|
}
|
|
|
|
LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs);
|
|
|
|
if(already_in_group)
|
|
{
|
|
LLSD msg;
|
|
msg["MESSAGE"] = mAlreadyInGroup;
|
|
LLNotificationsUtil::add("GenericAlert", msg);
|
|
}
|
|
|
|
//then close
|
|
(*mCloseCallback)(mCloseCallbackUserData);
|
|
}
|
|
|
|
bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response)
|
|
{
|
|
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
|
|
|
switch(option)
|
|
{
|
|
case 0:
|
|
// user confirmed that they really want a new group owner
|
|
mConfirmedOwnerInvite = true;
|
|
submitInvitations();
|
|
break;
|
|
case 1:
|
|
// fall through
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)
|
|
{
|
|
LLGroupMgrGroupData::member_list_t::iterator agent_iter =
|
|
gdatap->mMembers.find(gAgent.getID());
|
|
|
|
//loop over the agent's roles in the group
|
|
//then add those roles to the list of roles that the agent
|
|
//can invite people to be.
|
|
//if the user is the owner then we add
|
|
//all of the roles in the group,
|
|
//else if they have the add to roles power
|
|
//we add every role but owner,
|
|
//else if they have the limited add to roles power
|
|
//we add every role the user is in,
|
|
//else we just add to everyone
|
|
bool is_owner = false;
|
|
bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
|
|
GP_ROLE_ASSIGN_MEMBER);
|
|
bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
|
|
GP_ROLE_ASSIGN_MEMBER_LIMITED);
|
|
LLGroupMemberData* member_data = NULL;
|
|
//get the member data for the agent if it exists
|
|
if (agent_iter != gdatap->mMembers.end())
|
|
{
|
|
member_data = (*agent_iter).second;
|
|
if (member_data && mRoleNames)
|
|
{
|
|
is_owner = member_data->isOwner();
|
|
}//end if member data is not null
|
|
}//end if agent is in the group
|
|
|
|
|
|
|
|
LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
|
|
LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
|
|
|
|
//populate the role list:
|
|
for ( ; rit != end; ++rit)
|
|
{
|
|
LLUUID role_id = (*rit).first;
|
|
LLRoleData rd;
|
|
if ( gdatap->getRoleData(role_id,rd) )
|
|
{
|
|
// Owners can add any role.
|
|
if ( is_owner
|
|
// Even 'can_assign_any' can't add owner role.
|
|
|| (can_assign_any && role_id != gdatap->mOwnerRole)
|
|
// Add all roles user is in
|
|
|| (can_assign_limited && member_data && member_data->isInRole(role_id))
|
|
// Everyone role.
|
|
|| role_id == LLUUID::null )
|
|
{
|
|
mRoleNames->add(rd.mRoleName,
|
|
role_id,
|
|
ADD_BOTTOM);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata)
|
|
{
|
|
LLPanelGroupInvite* panelp = (LLPanelGroupInvite*) userdata;
|
|
|
|
if ( panelp )
|
|
{
|
|
//Right now this is hard coded with some knowledge that it is part
|
|
//of a floater since the avatar picker needs to be added as a dependent
|
|
//floater to the parent floater.
|
|
//Soon the avatar picker will be embedded into this panel
|
|
//instead of being it's own separate floater. But that is next week.
|
|
//This will do for now. -jwolk May 10, 2006
|
|
LLView * button = panelp->findChild<LLButton>("add_button");
|
|
LLFloater * root_floater = gFloaterView->getParentFloater(panelp);
|
|
LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(
|
|
boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), true, false, false, root_floater->getName(), button);
|
|
if (picker)
|
|
{
|
|
root_floater->addDependentFloater(picker);
|
|
}
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupInvite::impl::callbackClickRemove(void* userdata)
|
|
{
|
|
impl* selfp = (impl*) userdata;
|
|
|
|
if ( selfp ) selfp->handleRemove();
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::handleRemove()
|
|
{
|
|
// Check if there is anything selected.
|
|
std::vector<LLScrollListItem*> selection =
|
|
mInvitees->getAllSelected();
|
|
if (selection.empty()) return;
|
|
|
|
std::vector<LLScrollListItem*>::iterator iter;
|
|
for(iter = selection.begin(); iter != selection.end(); ++iter)
|
|
{
|
|
mInviteeIDs.erase( (*iter)->getUUID() );
|
|
}
|
|
|
|
// Remove all selected invitees.
|
|
mInvitees->deleteSelectedItems();
|
|
mRemoveButton->setEnabled(false);
|
|
}
|
|
|
|
// static
|
|
void LLPanelGroupInvite::impl::callbackSelect(
|
|
LLUICtrl* ctrl, void* userdata)
|
|
{
|
|
impl* selfp = (impl*) userdata;
|
|
if ( selfp ) selfp->handleSelection();
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::handleSelection()
|
|
{
|
|
// Check if there is anything selected.
|
|
std::vector<LLScrollListItem*> selection =
|
|
mInvitees->getAllSelected();
|
|
if (selection.empty())
|
|
{
|
|
mRemoveButton->setEnabled(false);
|
|
}
|
|
else
|
|
{
|
|
mRemoveButton->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::callbackClickCancel(void* userdata)
|
|
{
|
|
impl* selfp = (impl*) userdata;
|
|
|
|
if ( selfp )
|
|
{
|
|
(*(selfp->mCloseCallback))(selfp->mCloseCallbackUserData);
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::callbackClickOK(void* userdata)
|
|
{
|
|
impl* selfp = (impl*) userdata;
|
|
|
|
if ( selfp ) selfp->submitInvitations();
|
|
}
|
|
|
|
|
|
|
|
//static
|
|
void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data)
|
|
{
|
|
std::vector<std::string> names;
|
|
for (S32 i = 0; i < (S32)agent_ids.size(); i++)
|
|
{
|
|
LLAvatarName av_name;
|
|
if (LLAvatarNameCache::get(agent_ids[i], &av_name))
|
|
{
|
|
LLPanelGroupInvite::impl::onAvatarNameCache(agent_ids[i], av_name, user_data);
|
|
}
|
|
else
|
|
{
|
|
impl* selfp = (impl*) user_data;
|
|
if (selfp)
|
|
{
|
|
if (selfp->mAvatarNameCacheConnection.connected())
|
|
{
|
|
selfp->mAvatarNameCacheConnection.disconnect();
|
|
}
|
|
// *TODO : Add a callback per avatar name being fetched.
|
|
selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id,
|
|
const LLAvatarName& av_name,
|
|
void* user_data)
|
|
{
|
|
impl* selfp = (impl*) user_data;
|
|
|
|
if (selfp)
|
|
{
|
|
if (selfp->mAvatarNameCacheConnection.connected())
|
|
{
|
|
selfp->mAvatarNameCacheConnection.disconnect();
|
|
}
|
|
std::vector<std::string> names;
|
|
uuid_vec_t agent_ids;
|
|
agent_ids.push_back(agent_id);
|
|
names.push_back(av_name.getCompleteName());
|
|
|
|
selfp->addUsers(names, agent_ids);
|
|
}
|
|
}
|
|
|
|
|
|
LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id)
|
|
: LLPanel(),
|
|
mImplementation(new impl(group_id)),
|
|
mPendingUpdate(false)
|
|
{
|
|
// Pass on construction of this panel to the control factory.
|
|
buildFromFile( "panel_group_invite.xml");
|
|
}
|
|
|
|
LLPanelGroupInvite::~LLPanelGroupInvite()
|
|
{
|
|
delete mImplementation;
|
|
}
|
|
|
|
void LLPanelGroupInvite::setCloseCallback(void (*close_callback)(void*),
|
|
void* data)
|
|
{
|
|
mImplementation->mCloseCallback = close_callback;
|
|
mImplementation->mCloseCallbackUserData = data;
|
|
}
|
|
|
|
void LLPanelGroupInvite::clear()
|
|
{
|
|
mStoreSelected = LLUUID::null;
|
|
mImplementation->mInvitees->deleteAllItems();
|
|
mImplementation->mRoleNames->clear();
|
|
mImplementation->mRoleNames->removeall();
|
|
mImplementation->mOKButton->setEnabled(false);
|
|
mImplementation->mInviteeIDs.clear();
|
|
}
|
|
|
|
void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
|
|
{
|
|
std::vector<std::string> names;
|
|
for (S32 i = 0; i < (S32)agent_ids.size(); i++)
|
|
{
|
|
std::string fullname;
|
|
LLUUID agent_id = agent_ids[i];
|
|
LLViewerObject* dest = gObjectList.findObject(agent_id);
|
|
if(dest && dest->isAvatar())
|
|
{
|
|
LLNameValue* nvfirst = dest->getNVPair("FirstName");
|
|
LLNameValue* nvlast = dest->getNVPair("LastName");
|
|
if(nvfirst && nvlast)
|
|
{
|
|
fullname = LLCacheName::buildFullName(
|
|
nvfirst->getString(), nvlast->getString());
|
|
|
|
}
|
|
if (!fullname.empty())
|
|
{
|
|
names.push_back(fullname);
|
|
}
|
|
else
|
|
{
|
|
LL_WARNS() << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << LL_ENDL;
|
|
names.push_back("(Unknown)");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//looks like user try to invite offline avatar (or the avatar from the other region)
|
|
//for offline avatar_id gObjectList.findObject() will return null
|
|
//so we need to do this additional search in avatar tracker, see EXT-4732
|
|
LLAvatarName av_name;
|
|
if (!LLAvatarNameCache::get(agent_id, &av_name))
|
|
{
|
|
// actually it should happen, just in case
|
|
//LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupInvite::addUserCallback, this, _1, _2));
|
|
// for this special case!
|
|
//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence
|
|
// removed id will be added in callback
|
|
agent_ids.erase(agent_ids.begin() + i);
|
|
}
|
|
else
|
|
{
|
|
names.push_back(av_name.getAccountName());
|
|
}
|
|
}
|
|
}
|
|
mImplementation->addUsers(names, agent_ids);
|
|
}
|
|
|
|
void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& av_name)
|
|
{
|
|
std::vector<std::string> names;
|
|
uuid_vec_t agent_ids;
|
|
agent_ids.push_back(id);
|
|
names.push_back(av_name.getAccountName());
|
|
|
|
mImplementation->addUsers(names, agent_ids);
|
|
}
|
|
|
|
void LLPanelGroupInvite::draw()
|
|
{
|
|
LLPanel::draw();
|
|
if (mPendingUpdate)
|
|
{
|
|
updateLists();
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupInvite::update()
|
|
{
|
|
mPendingUpdate = false;
|
|
if (mImplementation->mGroupName)
|
|
{
|
|
mImplementation->mGroupName->setText(mImplementation->mLoadingText);
|
|
}
|
|
if ( mImplementation->mRoleNames )
|
|
{
|
|
mStoreSelected = mImplementation->mRoleNames->getCurrentID();
|
|
mImplementation->mRoleNames->clear();
|
|
mImplementation->mRoleNames->removeall();
|
|
mImplementation->mRoleNames->add(mImplementation->mLoadingText, LLUUID::null, ADD_BOTTOM);
|
|
mImplementation->mRoleNames->setCurrentByID(LLUUID::null);
|
|
}
|
|
|
|
updateLists();
|
|
}
|
|
|
|
void LLPanelGroupInvite::updateLists()
|
|
{
|
|
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
|
|
bool waiting = false;
|
|
|
|
if (gdatap)
|
|
{
|
|
if (gdatap->isGroupPropertiesDataComplete())
|
|
{
|
|
if (mImplementation->mGroupName)
|
|
{
|
|
mImplementation->mGroupName->setText(gdatap->mName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waiting = true;
|
|
}
|
|
if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete()
|
|
&& (gdatap->isRoleMemberDataComplete() || !gdatap->mMembers.size())) // MAINT-5270: large groups receives an empty members list without some powers, so RoleMemberData wouldn't be complete for them
|
|
{
|
|
if ( mImplementation->mRoleNames )
|
|
{
|
|
mImplementation->mRoleNames->clear();
|
|
mImplementation->mRoleNames->removeall();
|
|
|
|
//add the role names and select the everybody role by default
|
|
mImplementation->addRoleNames(gdatap);
|
|
mImplementation->mRoleNames->setCurrentByID(mStoreSelected);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waiting = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waiting = true;
|
|
}
|
|
|
|
if (waiting)
|
|
{
|
|
if (!mPendingUpdate)
|
|
{
|
|
// Note: this will partially fail if some requests are already in progress
|
|
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
|
|
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
|
|
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
|
|
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
|
|
}
|
|
else if (gdatap)
|
|
{
|
|
// <FS:Beq> FIRE-22912 Group send fail on OpenSim
|
|
// Debug shows that GroupProperties data is frequently failing to be returned
|
|
// Note that this method has a time-based SPAM check for existing pending requests.
|
|
if (!gdatap->isGroupPropertiesDataComplete())
|
|
{
|
|
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
|
|
}
|
|
// </FS:Beq>
|
|
// restart requests that were interrupted/dropped/failed to start
|
|
if (!gdatap->isRoleDataPending() && !gdatap->isRoleDataComplete())
|
|
{
|
|
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
|
|
}
|
|
if (!gdatap->isRoleMemberDataPending() && !gdatap->isRoleMemberDataComplete())
|
|
{
|
|
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
|
|
}
|
|
// sendCapGroupMembersRequest has a per frame send limitation that could have
|
|
// interrupted previous request
|
|
if (!gdatap->isMemberDataPending() && !gdatap->isMemberDataComplete())
|
|
{
|
|
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
|
|
}
|
|
}
|
|
mPendingUpdate = true;
|
|
}
|
|
else
|
|
{
|
|
mPendingUpdate = false;
|
|
if (mImplementation->mOKButton && mImplementation->mRoleNames->getItemCount())
|
|
{
|
|
mImplementation->mOKButton->setEnabled(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool LLPanelGroupInvite::postBuild()
|
|
{
|
|
constexpr bool recurse = true;
|
|
|
|
mImplementation->mLoadingText = getString("loading");
|
|
mImplementation->mRoleNames = getChild<LLComboBox>("role_name",
|
|
recurse);
|
|
mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse);
|
|
mImplementation->mInvitees =
|
|
getChild<LLNameListCtrl>("invitee_list", recurse);
|
|
if ( mImplementation->mInvitees )
|
|
{
|
|
mImplementation->mInvitees->setCommitOnSelectionChange(true);
|
|
mImplementation->mInvitees->setCommitCallback(impl::callbackSelect, mImplementation);
|
|
}
|
|
|
|
LLButton* button = getChild<LLButton>("add_button", recurse);
|
|
if ( button )
|
|
{
|
|
// default to opening avatarpicker automatically
|
|
// (*impl::callbackClickAdd)((void*)this);
|
|
button->setClickedCallback(impl::callbackClickAdd, this);
|
|
}
|
|
|
|
mImplementation->mRemoveButton =
|
|
getChild<LLButton>("remove_button", recurse);
|
|
if ( mImplementation->mRemoveButton )
|
|
{
|
|
mImplementation->mRemoveButton->setClickedCallback(impl::callbackClickRemove, mImplementation);
|
|
mImplementation->mRemoveButton->setEnabled(false);
|
|
}
|
|
|
|
mImplementation->mOKButton =
|
|
getChild<LLButton>("invite_button", recurse);
|
|
if ( mImplementation->mOKButton )
|
|
{
|
|
mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation);
|
|
mImplementation->mOKButton->setEnabled(false);
|
|
}
|
|
|
|
button = getChild<LLButton>("cancel_button", recurse);
|
|
if ( button )
|
|
{
|
|
button->setClickedCallback(impl::callbackClickCancel, mImplementation);
|
|
}
|
|
|
|
mImplementation->mOwnerWarning = getString("confirm_invite_owner_str");
|
|
mImplementation->mAlreadyInGroup = getString("already_in_group");
|
|
mImplementation->mTooManySelected = getString("invite_selection_too_large");
|
|
|
|
update();
|
|
|
|
return (mImplementation->mRoleNames &&
|
|
mImplementation->mInvitees &&
|
|
mImplementation->mRemoveButton);
|
|
}
|