summaryrefslogtreecommitdiff
path: root/indra/newview/llpanelgrouproles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llpanelgrouproles.cpp')
-rw-r--r--indra/newview/llpanelgrouproles.cpp2642
1 files changed, 2642 insertions, 0 deletions
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
new file mode 100644
index 0000000000..ccec55efce
--- /dev/null
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -0,0 +1,2642 @@
+/**
+ * @file llpanelgrouproles.cpp
+ * @brief Panel for roles information about a particular group.
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcheckboxctrl.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llfloateravatarinfo.h"
+#include "llfloatergroupinvite.h"
+#include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "llnamelistctrl.h"
+#include "llnotify.h"
+#include "llpanelgrouproles.h"
+#include "llscrolllistctrl.h"
+#include "lltabcontainer.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+#include "llviewerimagelist.h"
+#include "llviewerwindow.h"
+#include "llfocusmgr.h"
+
+#include "roles_constants.h"
+
+bool agentCanRemoveFromRole(const LLUUID& group_id,
+ const LLUUID& role_id)
+{
+ return gAgent.hasPowerInGroup(group_id, GP_ROLE_REMOVE_MEMBER);
+}
+
+bool agentCanAddToRole(const LLUUID& group_id,
+ const LLUUID& role_id)
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(group_id);
+ if (!gdatap)
+ {
+ llwarns << "agentCanAddToRole "
+ << "-- No group data!" << llendl;
+ return false;
+ }
+
+ //make sure the agent is in the group
+ LLGroupMgrGroupData::member_iter mi = gdatap->mMembers.find(gAgent.getID());
+ if (mi == gdatap->mMembers.end())
+ {
+ return false;
+ }
+
+ LLGroupMemberData* member_data = (*mi).second;
+
+ // Owners can add to any role.
+ if ( member_data->isInRole(gdatap->mOwnerRole) )
+ {
+ return true;
+ }
+
+ // 'Limited assign members' can add to roles the user is in.
+ if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER_LIMITED) &&
+ member_data->isInRole(role_id) )
+ {
+ return true;
+ }
+
+ // 'assign members' can add to non-owner roles.
+ if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER) &&
+ role_id != gdatap->mOwnerRole )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// static
+void* LLPanelGroupRoles::createTab(void* data)
+{
+ LLUUID* group_id = static_cast<LLUUID*>(data);
+ return new LLPanelGroupRoles("panel group roles", *group_id);
+}
+
+LLPanelGroupRoles::LLPanelGroupRoles(const std::string& name, const LLUUID& group_id)
+: LLPanelGroupTab(name, group_id),
+ mCurrentTab(NULL),
+ mRequestedTab( NULL ),
+ mSubTabContainer( NULL ),
+ mFirstUse( TRUE ),
+ mIgnoreTransition( FALSE )
+{
+}
+
+LLPanelGroupRoles::~LLPanelGroupRoles()
+{
+ int i;
+ for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
+ {
+ LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
+
+ subtabp->removeObserver(this);
+ }
+}
+
+BOOL LLPanelGroupRoles::postBuild()
+{
+ lldebugs << "LLPanelGroupRoles::postBuild()" << llendl;
+
+ mSubTabContainer = (LLTabContainerCommon*) getChildByName("roles_tab_container");
+
+ if (!mSubTabContainer) return FALSE;
+
+ // Hook up each sub-tabs callback and widgets.
+ S32 i;
+ for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
+ {
+ LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
+
+ // Add click callbacks to all the tabs.
+ mSubTabContainer->setTabChangeCallback(subtabp, onClickSubTab);
+ mSubTabContainer->setTabUserData(subtabp, this);
+
+ // Hand the subtab a pointer to this LLPanelGroupRoles, so that it can
+ // look around for the widgets it is interested in.
+ if (!subtabp->postBuildSubTab(this)) return FALSE;
+
+ subtabp->addObserver(this);
+ }
+
+ // Set the current tab to whatever is currently being shown.
+ mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (!mCurrentTab)
+ {
+ // Need to select a tab.
+ mSubTabContainer->selectFirstTab();
+ mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ }
+
+ if (!mCurrentTab) return FALSE;
+
+ // Act as though this tab was just activated.
+ mCurrentTab->activate();
+
+ // Read apply text from the xml file.
+ LLTextBox* txt;
+ // Don't recurse for this, since we don't currently have a recursive removeChild()
+ txt = (LLTextBox*)getChildByName("default_needs_apply_text");
+ if (txt)
+ {
+ mDefaultNeedsApplyMesg = txt->getText();
+ removeChild(txt);
+ }
+ txt = (LLTextBox*)getChildByName("want_apply_text");
+ if (txt)
+ {
+ mWantApplyMesg = txt->getText();
+ removeChild(txt);
+ }
+
+ return LLPanelGroupTab::postBuild();
+}
+
+BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp)
+{
+ /* This power was removed to make group roles simpler
+ return agentp->hasPowerInGroup(mGroupID,
+ GP_ROLE_CREATE |
+ GP_ROLE_DELETE |
+ GP_ROLE_PROPERTIES |
+ GP_ROLE_VIEW |
+ GP_ROLE_ASSIGN_MEMBER |
+ GP_ROLE_REMOVE_MEMBER |
+ GP_ROLE_CHANGE_ACTIONS |
+ GP_MEMBER_INVITE |
+ GP_MEMBER_EJECT |
+ GP_MEMBER_OPTIONS );
+ */
+ return mAllowEdit && agentp->isInGroup(mGroupID);
+
+}
+
+// static
+void LLPanelGroupRoles::onClickSubTab(void* user_data, bool from_click)
+{
+ LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
+ self->handleClickSubTab();
+}
+
+void LLPanelGroupRoles::handleClickSubTab()
+{
+ // If we are already handling a transition,
+ // ignore this.
+ if (mIgnoreTransition)
+ {
+ return;
+ }
+
+ mRequestedTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+
+ // Make sure they aren't just clicking the same tab...
+ if (mRequestedTab == mCurrentTab)
+ {
+ return;
+ }
+
+ // Try to switch from the current panel to the panel the user selected.
+ attemptTransition();
+}
+
+BOOL LLPanelGroupRoles::attemptTransition()
+{
+ // Check if the current tab needs to be applied.
+ LLString mesg;
+ if (mCurrentTab && mCurrentTab->needsApply(mesg))
+ {
+ // If no message was provided, give a generic one.
+ if (mesg.empty())
+ {
+ mesg = mDefaultNeedsApplyMesg;
+ }
+ // Create a notify box, telling the user about the unapplied tab.
+ LLString::format_map_t args;
+ args["[NEEDS_APPLY_MESSAGE]"] = mesg;
+ args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
+ gViewerWindow->alertXml("PanelGroupApply", args,
+ onNotifyCallback, (void*) this);
+ mHasModal = TRUE;
+ // We need to reselect the current tab, since it isn't finished.
+ if (mSubTabContainer)
+ {
+ mIgnoreTransition = TRUE;
+ mSubTabContainer->selectTabPanel( mCurrentTab );
+ mIgnoreTransition = FALSE;
+ }
+ // Returning FALSE will block a close action from finishing until
+ // we get a response back from the user.
+ return FALSE;
+ }
+ else
+ {
+ // The current panel didn't have anything it needed to apply.
+ if (mRequestedTab)
+ {
+ transitionToTab();
+ }
+ return TRUE;
+ }
+}
+
+void LLPanelGroupRoles::transitionToTab()
+{
+ // Tell the current panel that it is being deactivated.
+ if (mCurrentTab)
+ {
+ mCurrentTab->deactivate();
+ }
+
+ // Tell the new panel that it is being activated.
+ if (mRequestedTab)
+ {
+ // This is now the current tab;
+ mCurrentTab = mRequestedTab;
+ mCurrentTab->activate();
+ }
+}
+
+// static
+void LLPanelGroupRoles::onNotifyCallback(S32 option, void* user_data)
+{
+ LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
+ if (self)
+ {
+ self->handleNotifyCallback(option);
+ }
+}
+
+void LLPanelGroupRoles::handleNotifyCallback(S32 option)
+{
+ mHasModal = FALSE;
+ switch (option)
+ {
+ case 0: // "Apply Changes"
+ {
+ // Try to apply changes, and switch to the requested tab.
+ LLString apply_mesg;
+ if ( !apply( apply_mesg ) )
+ {
+ // There was a problem doing the apply.
+ if ( !apply_mesg.empty() )
+ {
+ mHasModal = TRUE;
+ LLString::format_map_t args;
+ args["[MESSAGE]"] = apply_mesg;
+ gViewerWindow->alertXml("GenericAlert", args, onModalClose, (void*) this);
+ }
+ // Skip switching tabs.
+ break;
+ }
+
+ // This panel's info successfully applied.
+ // Switch to the next panel.
+ // No break! Continue into 'Ignore Changes' which just switches tabs.
+ mIgnoreTransition = TRUE;
+ mSubTabContainer->selectTabPanel( mRequestedTab );
+ mIgnoreTransition = FALSE;
+ transitionToTab();
+ break;
+ }
+ case 1: // "Ignore Changes"
+ // Switch to the requested panel without applying changes
+ cancel();
+ mIgnoreTransition = TRUE;
+ mSubTabContainer->selectTabPanel( mRequestedTab );
+ mIgnoreTransition = FALSE;
+ transitionToTab();
+ break;
+ case 2: // "Cancel"
+ default:
+ // Do nothing. The user is canceling the action.
+ break;
+ }
+}
+
+// static
+void LLPanelGroupRoles::onModalClose(S32 option, void* user_data)
+{
+ LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
+ if (self)
+ {
+ self->mHasModal = FALSE;
+ }
+}
+
+
+bool LLPanelGroupRoles::apply(LLString& mesg)
+{
+ // Pass this along to the currently visible sub tab.
+ if (!mSubTabContainer) return false;
+
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (!panelp) return false;
+
+ // Ignore the needs apply message.
+ LLString ignore_mesg;
+ if ( !panelp->needsApply(ignore_mesg) )
+ {
+ // We don't need to apply anything.
+ // We're done.
+ return true;
+ }
+
+ // Try to do the actual apply.
+ return panelp->apply(mesg);
+}
+
+void LLPanelGroupRoles::cancel()
+{
+ // Pass this along to the currently visible sub tab.
+ if (!mSubTabContainer) return;
+
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (!panelp) return;
+
+ panelp->cancel();
+}
+
+// Pass all of these messages to the currently visible sub tab.
+LLString LLPanelGroupRoles::getHelpText() const
+{
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (panelp)
+ {
+ return panelp->getHelpText();
+ }
+ else
+ {
+ return mHelpText;
+ }
+}
+
+void LLPanelGroupRoles::update(LLGroupChange gc)
+{
+ if (mGroupID.isNull()) return;
+
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (panelp)
+ {
+ panelp->update(gc);
+ }
+ else
+ {
+ llwarns << "LLPanelGroupRoles::update() -- No subtab to update!" << llendl;
+ }
+}
+
+void LLPanelGroupRoles::activate()
+{
+ // Start requesting member and role data if needed.
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ //if (!gdatap || mFirstUse)
+ {
+ // Check member data.
+
+ if (!gdatap || !gdatap->isMemberDataComplete() )
+ {
+ gGroupMgr->sendGroupMembersRequest(mGroupID);
+ }
+
+ // Check role data.
+ if (!gdatap || !gdatap->isRoleDataComplete() )
+ {
+ // Mildly hackish - clear all pending changes
+ cancel();
+
+ gGroupMgr->sendGroupRoleDataRequest(mGroupID);
+ }
+
+ // Check role-member mapping data.
+ if (!gdatap || !gdatap->isRoleMemberDataComplete() )
+ {
+ gGroupMgr->sendGroupRoleMembersRequest(mGroupID);
+ }
+
+ // Need this to get base group member powers
+ if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
+ {
+ gGroupMgr->sendGroupPropertiesRequest(mGroupID);
+ }
+
+ mFirstUse = FALSE;
+ }
+
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (panelp) panelp->activate();
+}
+
+void LLPanelGroupRoles::deactivate()
+{
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (panelp) panelp->deactivate();
+}
+
+bool LLPanelGroupRoles::needsApply(LLString& mesg)
+{
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (!panelp) return false;
+
+ return panelp->needsApply(mesg);
+}
+
+BOOL LLPanelGroupRoles::hasModal()
+{
+ if (mHasModal) return TRUE;
+
+ LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
+ if (!panelp) return FALSE;
+
+ return panelp->hasModal();
+}
+
+// PanelGroupTab observer trigger
+void LLPanelGroupRoles::tabChanged()
+{
+ notifyObservers();
+}
+
+////////////////////////////
+// LLPanelGroupSubTab
+////////////////////////////
+LLPanelGroupSubTab::LLPanelGroupSubTab(const std::string& name, const LLUUID& group_id)
+: LLPanelGroupTab(name, group_id),
+ mHeader(NULL),
+ mFooter(NULL),
+ mSearchLineEditor(NULL),
+ mSearchButton(NULL),
+ mShowAllButton(NULL)
+{
+}
+
+LLPanelGroupSubTab::~LLPanelGroupSubTab()
+{
+}
+
+BOOL LLPanelGroupSubTab::postBuild()
+{
+ // Hook up the search widgets.
+ bool recurse = true;
+ mSearchLineEditor = (LLLineEditor*) getChildByName("search_text", recurse);
+
+ if (!mSearchLineEditor) return FALSE;
+ mSearchLineEditor->setKeystrokeCallback(onSearchKeystroke);
+ mSearchLineEditor->setCallbackUserData(this);
+
+ mSearchButton = (LLButton*) getChildByName("search_button", recurse);
+
+ if (!mSearchButton) return FALSE;
+ mSearchButton->setClickedCallback(onClickSearch);
+ mSearchButton->setCallbackUserData(this);
+ mSearchButton->setEnabled(FALSE);
+
+ mShowAllButton = (LLButton*) getChildByName("show_all_button", recurse);
+
+ if (!mShowAllButton) return FALSE;
+ mShowAllButton->setClickedCallback(onClickShowAll);
+ mShowAllButton->setCallbackUserData(this);
+ mShowAllButton->setEnabled(FALSE);
+
+ // Get icons for later use.
+ mActionIcons.clear();
+
+ bool no_recurse = false;
+
+ LLIconCtrl* icon = (LLIconCtrl*) getChildByName("power_folder_icon",no_recurse);
+ if (icon && icon->getImage().notNull())
+ {
+ mActionIcons["folder"] = icon->getImage();
+ removeChild(icon);
+ }
+
+ icon = (LLIconCtrl*) getChildByName("power_all_have_icon",no_recurse);
+ if (icon && icon->getImage().notNull())
+ {
+ mActionIcons["full"] = icon->getImage();
+ removeChild(icon);
+ }
+
+ icon = (LLIconCtrl*) getChildByName("power_partial_icon",no_recurse);
+ if (icon && icon->getImage().notNull())
+ {
+ mActionIcons["partial"] = icon->getImage();
+ removeChild(icon);
+ }
+
+ return LLPanelGroupTab::postBuild();
+}
+
+// static
+void LLPanelGroupSubTab::onSearchKeystroke(LLLineEditor* caller, void* user_data)
+{
+ LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
+ self->handleSearchKeystroke(caller);
+}
+
+void LLPanelGroupSubTab::handleSearchKeystroke(LLLineEditor* caller)
+{
+ if (caller->getText().size())
+ {
+ setDefaultBtn( mSearchButton );
+ mSearchButton->setEnabled(TRUE);
+ }
+ else
+ {
+ setDefaultBtn( NULL );
+ mSearchButton->setEnabled(FALSE);
+ }
+}
+
+// static
+void LLPanelGroupSubTab::onClickSearch(void* user_data)
+{
+ LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
+ self->handleClickSearch();
+}
+
+void LLPanelGroupSubTab::handleClickSearch()
+{
+ lldebugs << "LLPanelGroupSubTab::handleClickSearch()" << llendl;
+
+ if (0 == mSearchLineEditor->getText().size())
+ {
+ // No search text. (This shouldn't happen... the search button should have been disabled).
+ llwarns << "handleClickSearch with no search text!" << llendl;
+ mSearchButton->setEnabled(FALSE);
+ return;
+ }
+
+ setSearchFilter( mSearchLineEditor->getText() );
+ mShowAllButton->setEnabled(TRUE);
+}
+
+// static
+void LLPanelGroupSubTab::onClickShowAll(void* user_data)
+{
+ LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
+ self->handleClickShowAll();
+}
+
+void LLPanelGroupSubTab::handleClickShowAll()
+{
+ lldebugs << "LLPanelGroupSubTab::handleClickShowAll()" << llendl;
+ setSearchFilter( LLString::null );
+ mShowAllButton->setEnabled(FALSE);
+}
+
+void LLPanelGroupSubTab::setSearchFilter(const LLString& filter)
+{
+ lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
+ mSearchFilter = filter;
+ LLString::toLower(mSearchFilter);
+ update(GC_ALL);
+}
+
+void LLPanelGroupSubTab::activate()
+{
+ lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
+ setOthersVisible(TRUE);
+}
+
+void LLPanelGroupSubTab::deactivate()
+{
+ lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
+ setOthersVisible(FALSE);
+}
+
+void LLPanelGroupSubTab::setOthersVisible(BOOL b)
+{
+ if (mHeader)
+ {
+ mHeader->setVisible( b );
+ }
+ else
+ {
+ llwarns << "LLPanelGroupSubTab missing header!" << llendl;
+ }
+
+ if (mFooter)
+ {
+ mFooter->setVisible( b );
+ }
+ else
+ {
+ llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
+ }
+}
+
+bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
+{
+ // If the search filter is empty, everything passes.
+ if (mSearchFilter.empty()) return true;
+
+ LLString::toLower(action);
+ std::string::size_type match = action.find(mSearchFilter);
+
+ if (std::string::npos == match)
+ {
+ // not found
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
+ U64 allowed_by_some,
+ U64 allowed_by_all,
+ icon_map_t& icons,
+ void (*commit_callback)(LLUICtrl*,void*),
+ BOOL show_all,
+ BOOL filter,
+ BOOL is_owner_role)
+{
+ if (gGroupMgr->mRoleActionSets.empty())
+ {
+ llwarns << "Can't build action list - no actions found." << llendl;
+ return;
+ }
+
+ std::vector<LLRoleActionSet*>::iterator ras_it = gGroupMgr->mRoleActionSets.begin();
+ std::vector<LLRoleActionSet*>::iterator ras_end = gGroupMgr->mRoleActionSets.end();
+
+ for ( ; ras_it != ras_end; ++ras_it)
+ {
+ buildActionCategory(ctrl,
+ allowed_by_some,
+ allowed_by_all,
+ (*ras_it),
+ icons,
+ commit_callback,
+ show_all,
+ filter,
+ is_owner_role);
+ }
+}
+
+void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
+ U64 allowed_by_some,
+ U64 allowed_by_all,
+ LLRoleActionSet* action_set,
+ icon_map_t& icons,
+ void (*commit_callback)(LLUICtrl*,void*),
+ BOOL show_all,
+ BOOL filter,
+ BOOL is_owner_role)
+{
+ lldebugs << "Building role list for: " << action_set->mActionSetData->mName << llendl;
+ // See if the allow mask matches anything in this category.
+ if (show_all || (allowed_by_some & action_set->mActionSetData->mPowerBit))
+ {
+ // List all the actions in this category that at least some members have.
+ LLSD row;
+
+ row["columns"][0]["column"] = "icon";
+ icon_map_t::iterator iter = icons.find("folder");
+ if (iter != icons.end())
+ {
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = (*iter).second;
+ }
+
+ row["columns"][1]["column"] = "action";
+ row["columns"][1]["value"] = action_set->mActionSetData->mName;
+ row["columns"][1]["font-style"] = "BOLD";
+
+ LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
+
+ bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
+
+ std::vector<LLRoleAction*>::iterator ra_it = action_set->mActions.begin();
+ std::vector<LLRoleAction*>::iterator ra_end = action_set->mActions.end();
+
+ bool items_match_filter = false;
+ BOOL can_change_actions = (!is_owner_role && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CHANGE_ACTIONS));
+
+ for ( ; ra_it != ra_end; ++ra_it)
+ {
+ // See if anyone has these action.
+ if (!show_all && !(allowed_by_some & (*ra_it)->mPowerBit))
+ {
+ continue;
+ }
+
+ // See if we are filtering out these actions
+ // If we aren't using filters, category_matches_filter will be true.
+ if (!category_matches_filter
+ && !matchesActionSearchFilter((*ra_it)->mDescription))
+ {
+ continue;
+ }
+
+ items_match_filter = true;
+
+ // See if everyone has these actions.
+ bool show_full_strength = false;
+ if ( (allowed_by_some & (*ra_it)->mPowerBit) == (allowed_by_all & (*ra_it)->mPowerBit) )
+ {
+ show_full_strength = true;
+ }
+
+ LLSD row;
+
+ S32 column_index = 0;
+ row["columns"][column_index]["column"] = "icon";
+ ++column_index;
+
+
+ S32 check_box_index = -1;
+ if (commit_callback)
+ {
+ row["columns"][column_index]["column"] = "checkbox";
+ row["columns"][column_index]["type"] = "checkbox";
+ row["columns"][column_index]["value"] = (*ra_it)->mName;
+ check_box_index = column_index;
+ ++column_index;
+ }
+ else
+ {
+ if (show_full_strength)
+ {
+ icon_map_t::iterator iter = icons.find("full");
+ if (iter != icons.end())
+ {
+ row["columns"][column_index]["column"] = "checkbox";
+ row["columns"][column_index]["type"] = "icon";
+ row["columns"][column_index]["value"] = (*iter).second;
+ ++column_index;
+ }
+ }
+ else
+ {
+ icon_map_t::iterator iter = icons.find("partial");
+ if (iter != icons.end())
+ {
+ row["columns"][column_index]["column"] = "checkbox";
+ row["columns"][column_index]["type"] = "icon";
+ row["columns"][column_index]["value"] = (*iter).second;
+ ++column_index;
+ }
+ row["enabled"] = false;
+ }
+ }
+
+ row["columns"][column_index]["column"] = "action";
+ row["columns"][column_index]["value"] = (*ra_it)->mDescription;
+ row["columns"][column_index]["font"] = "SANSSERIFSMALL";
+
+ LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
+
+ if (-1 != check_box_index)
+ {
+ // Extract the checkbox that was created.
+ LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(check_box_index);
+ LLCheckBoxCtrl* check = check_cell->getCheckBox();
+ check->setEnabled(can_change_actions);
+ check->setCommitCallback(commit_callback);
+ check->setCallbackUserData(ctrl->getCallbackUserData());
+ check->setToolTip( check->getLabel() );
+
+ if (show_all)
+ {
+ check->setTentative(FALSE);
+ if (allowed_by_some & (*ra_it)->mPowerBit)
+ {
+ check->set(TRUE);
+ }
+ else
+ {
+ check->set(FALSE);
+ }
+ }
+ else
+ {
+ check->set(TRUE);
+ if (show_full_strength)
+ {
+ check->setTentative(FALSE);
+ }
+ else
+ {
+ check->setTentative(TRUE);
+ }
+ }
+ }
+ }
+
+ if (!items_match_filter)
+ {
+ S32 title_index = ctrl->getItemIndex(title_row);
+ ctrl->deleteSingleItem(title_index);
+ }
+ }
+}
+
+void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
+{
+ if (mFooter)
+ {
+ mFooter->setAllChildrenEnabled(enable);
+ }
+}
+
+////////////////////////////
+// LLPanelGroupMembersSubTab
+////////////////////////////
+
+// static
+void* LLPanelGroupMembersSubTab::createTab(void* data)
+{
+ LLUUID* group_id = static_cast<LLUUID*>(data);
+ return new LLPanelGroupMembersSubTab("panel group members sub tab", *group_id);
+}
+
+LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab(const std::string& name, const LLUUID& group_id)
+: LLPanelGroupSubTab(name, group_id),
+ mMembersList(NULL),
+ mAssignedRolesList(NULL),
+ mAllowedActionsList(NULL),
+ mChanged(FALSE),
+ mPendingMemberUpdate(FALSE),
+ mHasMatch(FALSE),
+ mNumOwnerAdditions(0)
+{
+}
+
+LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
+{
+}
+
+BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
+{
+ // Upcast parent so we can ask it for sibling controls.
+ LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
+
+ // Look recursively from the parent to find all our widgets.
+ bool recurse = true;
+ mHeader = (LLPanel*) parent->getChildByName("members_header", recurse);
+ mFooter = (LLPanel*) parent->getChildByName("members_footer", recurse);
+
+ mMembersList = (LLNameListCtrl*) parent->getChildByName("member_list", recurse);
+ mAssignedRolesList = (LLScrollListCtrl*) parent->getChildByName("member_assigned_roles", recurse);
+ mAllowedActionsList = (LLScrollListCtrl*) parent->getChildByName("member_allowed_actions", recurse);
+
+ if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE;
+
+ // We want to be notified whenever a member is selected.
+ mMembersList->setCallbackUserData(this);
+ mMembersList->setCommitOnSelectionChange(TRUE);
+ mMembersList->setCommitCallback(onMemberSelect);
+ // Show the member's profile on double click.
+ mMembersList->setDoubleClickCallback(onMemberDoubleClick);
+
+ LLButton* button = (LLButton*) parent->getChildByName("member_invite", recurse);
+ if ( button )
+ {
+ button->setClickedCallback(onInviteMember);
+ button->setCallbackUserData(this);
+ button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+ }
+
+ mEjectBtn = (LLButton*) parent->getChildByName("member_eject", recurse);
+ if ( mEjectBtn )
+ {
+ mEjectBtn->setClickedCallback(onEjectMembers);
+ mEjectBtn->setCallbackUserData(this);
+ mEjectBtn->setEnabled(FALSE);
+ }
+
+ return TRUE;
+}
+
+
+// static
+void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
+ self->handleMemberSelect();
+}
+
+void LLPanelGroupMembersSubTab::handleMemberSelect()
+{
+ lldebugs << "LLPanelGroupMembersSubTab::handleMemberSelect" << llendl;
+
+ mAssignedRolesList->deleteAllItems();
+ mAllowedActionsList->deleteAllItems();
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() "
+ << "-- No group data!" << llendl;
+ return;
+ }
+
+ // Check if there is anything selected.
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return;
+
+ // Build a vector of all selected members, and gather allowed actions.
+ std::vector<LLUUID> selected_members;
+ U64 allowed_by_all = 0xffffffffffffLL;
+ U64 allowed_by_some = 0;
+
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin();
+ itor != selection.end(); ++itor)
+ {
+ selected_members.push_back( (*itor)->getUUID() );
+ // Get this member's power mask including any unsaved changes
+
+ U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
+
+ allowed_by_all &= powers;
+ allowed_by_some |= powers;
+ }
+ std::sort(selected_members.begin(), selected_members.end());
+
+ //////////////////////////////////
+ // Build the allowed actions list.
+ //////////////////////////////////
+ buildActionsList(mAllowedActionsList,
+ allowed_by_some,
+ allowed_by_all,
+ mActionIcons,
+ NULL,
+ FALSE,
+ FALSE,
+ FALSE);
+
+ //////////////////////////////////
+ // Build the assigned roles list.
+ //////////////////////////////////
+ // Add each role to the assigned roles list.
+ LLGroupMgrGroupData::role_iter iter = gdatap->mRoles.begin();
+ LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
+
+ BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
+ GP_MEMBER_EJECT);
+ BOOL member_is_owner = FALSE;
+
+ for( ; iter != end; ++iter)
+ {
+ // Count how many selected users are in this role.
+ const LLUUID& role_id = iter->first;
+ LLGroupRoleData* group_role_data = iter->second;
+
+ if (group_role_data)
+ {
+ const BOOL needs_sort = FALSE;
+ S32 count = group_role_data->getMembersInRole(
+ selected_members, needs_sort);
+ //check if the user has permissions to assign/remove
+ //members to/from the role (but the ability to add/remove
+ //should only be based on the "saved" changes to the role
+ //not in the temp/meta data. -jwolk
+ BOOL cb_enable = ( (count > 0) ?
+ agentCanRemoveFromRole(mGroupID, role_id) :
+ agentCanAddToRole(mGroupID, role_id) );
+
+
+ // Owner role has special enabling permissions for removal.
+ if (cb_enable && (count > 0) && role_id == gdatap->mOwnerRole)
+ {
+ // Check if any owners besides this agent are selected.
+ std::vector<LLUUID>::const_iterator member_iter;
+ std::vector<LLUUID>::const_iterator member_end =
+ selected_members.end();
+ for (member_iter = selected_members.begin();
+ member_iter != member_end;
+ ++member_iter)
+ {
+ // Don't count the agent.
+ if ((*member_iter) == gAgent.getID()) continue;
+
+ // Look up the member data.
+ LLGroupMgrGroupData::member_iter mi =
+ gdatap->mMembers.find((*member_iter));
+ if (mi == gdatap->mMembers.end()) continue;
+ LLGroupMemberData* member_data = (*mi).second;
+ // Is the member an owner?
+ if ( member_data->isInRole(gdatap->mOwnerRole) )
+ {
+ // Can't remove other owners.
+ cb_enable = FALSE;
+ break;
+ }
+ }
+ }
+
+ //now see if there are any role changes for the selected
+ //members and remember to include them
+ std::vector<LLUUID>::iterator sel_mem_iter = selected_members.begin();
+ for (; sel_mem_iter != selected_members.end(); sel_mem_iter++)
+ {
+ LLRoleMemberChangeType type;
+ if ( getRoleChangeType(*sel_mem_iter, role_id, type) )
+ {
+ if ( type == RMC_ADD ) count++;
+ else if ( type == RMC_REMOVE ) count--;
+ }
+ }
+
+ // If anyone selected is in any role besides 'Everyone' then they can't be ejected.
+ if (role_id.notNull() && (count > 0))
+ {
+ can_eject_members = FALSE;
+ if (role_id == gdatap->mOwnerRole)
+ {
+ member_is_owner = TRUE;
+ }
+ }
+
+ LLRoleData rd;
+ if (gdatap->getRoleData(role_id,rd))
+ {
+ std::ostringstream label;
+ label << rd.mRoleName;
+ // Don't bother showing a count, if there is only 0 or 1.
+ if (count > 1)
+ {
+ label << ": " << count ;
+ }
+
+ LLSD row;
+ row["id"] = role_id;
+
+ row["columns"][0]["column"] = "checkbox";
+ row["columns"][0]["type"] = "checkbox";
+
+ row["columns"][1]["column"] = "role";
+ row["columns"][1]["value"] = label.str();
+
+ if (row["id"].asUUID().isNull())
+ {
+ // This is the everyone role, you can't take people out of the everyone role!
+ row["enabled"] = false;
+ }
+
+ LLScrollListItem* item = mAssignedRolesList->addElement(row);
+
+ // Extract the checkbox that was created.
+ LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(0);
+ LLCheckBoxCtrl* check = check_cell->getCheckBox();
+ check->setCommitCallback(onRoleCheck);
+ check->setCallbackUserData(this);
+ check->set( count > 0 );
+ check->setTentative(0 != count && selected_members.size() != count);
+
+ //NOTE: as of right now a user can break the group
+ //by removing himself from a role if he is the
+ //last owner. We should check for this special case
+ // -jwolk
+ check->setEnabled(cb_enable);
+ }
+ }
+ else
+ {
+ // This could happen if changes are not synced right on sub-panel change.
+ llwarns << "No group role data for " << iter->second << llendl;
+ }
+ }
+ mAssignedRolesList->setEnabled(TRUE);
+
+ if (!can_eject_members && !member_is_owner)
+ {
+ // Maybe we can eject them because we are an owner...
+ LLGroupMgrGroupData::member_iter mi = gdatap->mMembers.find(gAgent.getID());
+ if (mi != gdatap->mMembers.end())
+ {
+ LLGroupMemberData* member_data = (*mi).second;
+
+ if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
+ {
+ can_eject_members = TRUE;
+ }
+ }
+ }
+
+ mEjectBtn->setEnabled(can_eject_members);
+}
+
+// static
+void LLPanelGroupMembersSubTab::onMemberDoubleClick(void* user_data)
+{
+ LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
+ self->handleMemberDoubleClick();
+}
+
+//static
+void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
+{
+ LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
+
+ if ( selfp )
+ {
+ selfp->handleInviteMember();
+ }
+}
+
+void LLPanelGroupMembersSubTab::handleInviteMember()
+{
+ LLFloaterGroupInvite::showForGroup(mGroupID);
+}
+
+void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
+{
+ LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
+
+ if ( selfp )
+ {
+ selfp->handleEjectMembers();
+ }
+}
+
+void LLPanelGroupMembersSubTab::handleEjectMembers()
+{
+ //send down an eject message
+ std::vector<LLUUID> selected_members;
+
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return;
+
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin() ;
+ itor != selection.end(); ++itor)
+ {
+ selected_members.push_back((*itor)->getUUID());
+ }
+
+ mMembersList->deleteSelectedItems();
+
+ gGroupMgr->sendGroupMemberEjects(mGroupID,
+ selected_members);
+}
+
+void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
+ LLRoleMemberChangeType type)
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap) return;
+
+ //add that the user is requesting to change the roles for selected
+ //members
+ U64 powers_all_have = 0xffffffffffffLL;
+ U64 powers_some_have = 0;
+
+ BOOL is_owner_role = ( gdatap->mOwnerRole == role_id );
+ LLUUID member_id;
+
+
+ member_role_change_iter member_end = mMemberRoleChangeData.end();
+ member_role_change_iter member;
+ role_change_data_map_t *role_change_datap;
+ role_change_data_map_t::iterator role_end;
+ role_change_data_map_t::iterator role;
+
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return;
+
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin() ;
+ itor != selection.end(); ++itor)
+ {
+ member_id = (*itor)->getUUID();
+
+ //see if we requested a change for this member before
+ member = mMemberRoleChangeData.find(member_id);
+ if ( member != member_end )
+ {
+ //this member had previously had their role data changed
+ //so grab it
+ role_change_datap = (*member).second;
+ }
+ else
+ {
+ role_change_datap = new role_change_data_map_t;
+ mMemberRoleChangeData[member_id] = role_change_datap;
+ }
+
+ //now check to see if the selected group member
+ //had changed his association with the selected role before
+ role_end = role_change_datap->end();
+ role = role_change_datap->find(role_id);
+
+ if ( role != role_end )
+ {
+ //see if the new change type cancels out the previous change
+ if (role->second != type)
+ {
+ role_change_datap->erase(role_id);
+ if ( is_owner_role ) mNumOwnerAdditions--;
+ }
+ //else do nothing
+
+ if ( role_change_datap->empty() )
+ {
+ //the current member now has no role changes
+ //so erase the role change and erase the member's entry
+ delete role_change_datap;
+ role_change_datap = NULL;
+
+ mMemberRoleChangeData.erase(member_id);
+ }
+ }
+ else
+ {
+ //a previously unchanged role is being changed
+ (*role_change_datap)[role_id] = type;
+ if ( is_owner_role && type == RMC_ADD ) mNumOwnerAdditions++;
+ }
+
+ //we need to calculate what powers the selected members
+ //have (including the role changes we're making)
+ //so that we can rebuild the action list
+ U64 new_powers = getAgentPowersBasedOnRoleChanges(member_id);
+
+ powers_all_have &= new_powers;
+ powers_some_have |= new_powers;
+ }
+
+
+ mChanged = !mMemberRoleChangeData.empty();
+ notifyObservers();
+
+ //alrighty now we need to update the actions list
+ //to reflect the changes
+ mAllowedActionsList->deleteAllItems();
+ buildActionsList(mAllowedActionsList,
+ powers_some_have,
+ powers_all_have,
+ mActionIcons,
+ NULL,
+ FALSE,
+ FALSE,
+ FALSE);
+}
+
+
+// static
+void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
+ LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl);
+ if (!check_box || !self) return;
+
+
+ LLUUID role_id = self->mAssignedRolesList->getFirstSelected()->getUUID();
+ LLRoleMemberChangeType change_type = (check_box->get() ?
+ RMC_ADD :
+ RMC_REMOVE);
+
+ self->handleRoleCheck(role_id, change_type);
+}
+
+void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
+{
+ LLScrollListItem* selected = mMembersList->getFirstSelected();
+ if (selected)
+ {
+ LLFloaterAvatarInfo::showFromDirectory( selected->getUUID() );
+ }
+}
+
+void LLPanelGroupMembersSubTab::activate()
+{
+ LLPanelGroupSubTab::activate();
+
+ update(GC_ALL);
+}
+
+void LLPanelGroupMembersSubTab::deactivate()
+{
+ LLPanelGroupSubTab::deactivate();
+}
+
+bool LLPanelGroupMembersSubTab::needsApply(LLString& mesg)
+{
+ return mChanged;
+}
+
+void LLPanelGroupMembersSubTab::cancel()
+{
+ if ( mChanged )
+ {
+ std::for_each(mMemberRoleChangeData.begin(),
+ mMemberRoleChangeData.end(),
+ DeletePairedPointer());
+ mMemberRoleChangeData.clear();
+
+ mChanged = FALSE;
+ notifyObservers();
+ }
+}
+
+bool LLPanelGroupMembersSubTab::apply(LLString& mesg)
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "Unable to get group data for group " << mGroupID << llendl;
+
+ mesg.assign("Unable to save member data. Try again later.");
+ return false;
+ }
+
+ if (mChanged)
+ {
+ //figure out if we are somehow adding an owner or not and alert
+ //the user...possibly make it ignorable
+ if ( mNumOwnerAdditions > 0 )
+ {
+ LLRoleData rd;
+ LLStringBase<char>::format_map_t args;
+
+ if ( gdatap->getRoleData(gdatap->mOwnerRole, rd) )
+ {
+ mHasModal = TRUE;
+ args["[ROLE_NAME]"] = rd.mRoleName;
+ gViewerWindow->alertXml("AddGroupOwnerWarning",
+ args,
+ addOwnerCB,
+ this);
+ }
+ else
+ {
+ llwarns << "Unable to get role information for the owner role in group " << mGroupID << llendl;
+
+ mesg.assign("Unable to retried specific group information. Try again later");
+ return false;
+ }
+
+ }
+ else
+ {
+ applyMemberChanges();
+ }
+ }
+
+ return true;
+}
+
+//static
+void LLPanelGroupMembersSubTab::addOwnerCB(S32 option, void* data)
+{
+ LLPanelGroupMembersSubTab* self = (LLPanelGroupMembersSubTab*) data;
+
+ if (!self) return;
+
+ self->mHasModal = FALSE;
+
+ if (0 == option)
+ {
+ // User clicked "Yes"
+ self->applyMemberChanges();
+ }
+}
+
+void LLPanelGroupMembersSubTab::applyMemberChanges()
+{
+ //sucks to do a find again here, but it is in constant time, so, could
+ //be worse
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "Unable to get group data for group " << mGroupID << llendl;
+ return;
+ }
+
+ //we need to add all of the changed roles data
+ //for each member whose role changed
+ member_role_change_iter member_end = mMemberRoleChangeData.end();
+ member_role_change_iter member = mMemberRoleChangeData.begin();
+
+ for (; member != member_end; member++)
+ {
+ role_change_data_map_t::iterator role_end = member->second->end();
+ role_change_data_map_t::iterator role = member->second->begin();
+
+ for (; role != role_end; role++)
+ {
+ gdatap->changeRoleMember(role->first, //role_id
+ member->first, //member_id
+ role->second); //add/remove
+ }
+
+ member->second->clear();
+ delete member->second;
+ }
+ mMemberRoleChangeData.clear();
+
+ gGroupMgr->sendGroupRoleMemberChanges(mGroupID);
+ //force a UI update
+ handleMemberSelect();
+
+ mChanged = FALSE;
+ mNumOwnerAdditions = 0;
+ notifyObservers();
+}
+
+bool LLPanelGroupMembersSubTab::matchesSearchFilter(char* first, char* last)
+{
+ // If the search filter is empty, everything passes.
+ if (mSearchFilter.empty()) return true;
+
+ // Create a full name, and compare it to the search filter.
+ LLString fullname;
+ fullname.assign(first);
+ fullname.append(1, ' ');
+ fullname.append(last);
+ LLString::toLower(fullname);
+
+ std::string::size_type match = fullname.find(mSearchFilter);
+
+ if (std::string::npos == match)
+ {
+ // not found
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+U64 LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges(const LLUUID& agent_id)
+{
+ //we loop over all of the changes
+ //if we are adding a role, then we simply add the role's powers
+ //if we are removing a role, we store that role id away
+ //and then we have to build the powers up bases on the roles the agent
+ //is in
+ member_role_change_iter member_end = mMemberRoleChangeData.end();
+ member_role_change_iter member;
+ role_change_data_map_t *role_change_datap = NULL;
+ role_change_data_map_t::iterator role_end;
+ role_change_data_map_t::iterator role;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No group data!" << llendl;
+ return GP_NO_POWERS;
+ }
+
+ LLGroupMemberData* member_data = gdatap->mMembers[agent_id];
+ if ( !member_data )
+ {
+ llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No member data for member with UUID " << agent_id << llendl;
+ return GP_NO_POWERS;
+ }
+
+ //see if there are unsaved role changes for this agent
+ member = mMemberRoleChangeData.find(agent_id);
+ if ( member != member_end )
+ {
+ //this member has unsaved role changes
+ //so grab them
+ role_change_datap = (*member).second;
+ }
+
+ U64 new_powers = GP_NO_POWERS;
+
+ if ( role_change_datap )
+ {
+ std::vector<LLUUID> roles_to_be_removed;
+
+ role_end = role_change_datap->end();
+ role = role_change_datap->begin();
+
+ for (; role != role_end; role++)
+ {
+ if ( role->second == RMC_ADD )
+ new_powers |= gdatap->getRolePowers(role->first);
+ else
+ {
+ roles_to_be_removed.push_back(role->first);
+ }
+ }
+
+ //loop over the member's current roles, summing up
+ //the powers (not including the role we are removing)
+ std::map<LLUUID,LLGroupRoleData*>::iterator current_role =
+ member_data->roleBegin();
+ std::map<LLUUID,LLGroupRoleData*>::iterator end_role =
+ member_data->roleEnd();
+
+ for (; current_role != end_role; current_role++)
+ {
+ bool role_in_remove_list =
+ (std::find(roles_to_be_removed.begin(),
+ roles_to_be_removed.end(),
+ current_role->second->getID()) !=
+ roles_to_be_removed.end());
+
+ if ( !role_in_remove_list )
+ {
+ new_powers |=
+ current_role->second->getRoleData().mRolePowers;
+ }
+ }
+ }
+ else
+ {
+ //there are no changes for this member
+ //the member's powers are just the ones stored in the group
+ //manager
+ new_powers = member_data->getAgentPowers();
+ }
+
+ return new_powers;
+}
+
+//If there is no change, returns false be sure to verify
+//that there is a role change before attempting to get it or else
+//the data will make no sense. Stores the role change type
+bool LLPanelGroupMembersSubTab::getRoleChangeType(const LLUUID& member_id,
+ const LLUUID& role_id,
+ LLRoleMemberChangeType& type)
+{
+ member_role_change_iter member_changes_iter;
+ role_change_data_map_t::iterator role_changes_iter;
+
+ member_changes_iter = mMemberRoleChangeData.find(member_id);
+ if ( member_changes_iter != mMemberRoleChangeData.end() )
+ {
+ role_changes_iter = member_changes_iter->second->find(role_id);
+ if ( role_changes_iter != member_changes_iter->second->end() )
+ {
+ type = role_changes_iter->second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void LLPanelGroupMembersSubTab::draw()
+{
+ LLPanelGroupSubTab::draw();
+
+ if (mPendingMemberUpdate)
+ {
+ updateMembers();
+ }
+}
+
+void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
+{
+ if (mGroupID.isNull()) return;
+
+ if ( GC_TITLES == gc || GC_PROPERTIES == gc )
+ {
+ // Don't care about title or general group properties updates.
+ return;
+ }
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::update() -- No group data!" << llendl;
+ return;
+ }
+
+ // Rebuild the members list.
+ mMembersList->deleteAllItems();
+
+ // Wait for both all data to be retrieved before displaying anything.
+ if ( gdatap->isMemberDataComplete()
+ && gdatap->isRoleDataComplete()
+ && gdatap->isRoleMemberDataComplete())
+ {
+ mMemberProgress = gdatap->mMembers.begin();
+ mPendingMemberUpdate = TRUE;
+ mHasMatch = FALSE;
+ }
+ else
+ {
+ // Build a string with info on retrieval progress.
+ std::ostringstream retrieved;
+ if ( !gdatap->isMemberDataComplete() )
+ {
+ // Still busy retreiving member list.
+ retrieved << "Retrieving member list (" << gdatap->mMembers.size()
+ << " / " << gdatap->mMemberCount << ")...";
+ }
+ else if( !gdatap->isRoleDataComplete() )
+ {
+ // Still busy retreiving role list.
+ retrieved << "Retrieving role list (" << gdatap->mRoles.size()
+ << " / " << gdatap->mRoleCount << ")...";
+ }
+ else // (!gdatap->isRoleMemberDataComplete())
+ {
+ // Still busy retreiving role/member mappings.
+ retrieved << "Retrieving role member mappings...";
+ }
+ mMembersList->setEnabled(FALSE);
+ mMembersList->addSimpleItem(retrieved.str());
+ }
+}
+
+void LLPanelGroupMembersSubTab::updateMembers()
+{
+ mPendingMemberUpdate = FALSE;
+
+ lldebugs << "LLPanelGroupMembersSubTab::updateMembers()" << llendl;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
+ return;
+ }
+
+ // Make sure all data is still complete. Incomplete data
+ // may occur if we refresh.
+ if ( !gdatap->isMemberDataComplete()
+ || !gdatap->isRoleDataComplete()
+ || !gdatap->isRoleMemberDataComplete())
+ {
+ return;
+ }
+
+ LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
+
+ char first[DB_FIRST_NAME_BUF_SIZE];
+ char last[DB_LAST_NAME_BUF_SIZE];
+ S32 i = 0;
+ for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
+ ++mMemberProgress, ++i)
+ {
+ if (!mMemberProgress->second)
+ continue;
+ // Do filtering on name if it is already in the cache.
+ bool add_member = true;
+
+ if (gCacheName->getName(mMemberProgress->first, first, last))
+ {
+ if ( !matchesSearchFilter(first, last) )
+ {
+ add_member = false;
+ }
+ }
+
+ if (add_member)
+ {
+ // Build the donated tier string.
+ std::ostringstream donated;
+ donated << mMemberProgress->second->getContribution() << " sq. m.";
+
+ LLSD row;
+ row["id"] = (*mMemberProgress).first;
+
+ row["columns"][0]["column"] = "name";
+ // value is filled in by name list control
+
+ row["columns"][1]["column"] = "donated";
+ row["columns"][1]["value"] = donated.str();
+
+ row["columns"][2]["column"] = "online";
+ row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
+ row["columns"][2]["font"] = "SANSSERIFSMALL";
+
+ mMembersList->addElement(row);//, ADD_SORTED);
+ mHasMatch = TRUE;
+ }
+ }
+
+ if (mMemberProgress == end)
+ {
+ if (mHasMatch)
+ {
+ mMembersList->setEnabled(TRUE);
+ }
+ else
+ {
+ mMembersList->setEnabled(FALSE);
+ mMembersList->addSimpleItem("No match.");
+ }
+ }
+ else
+ {
+ mPendingMemberUpdate = TRUE;
+ }
+
+ // This should clear the other two lists, since nothing is selected.
+ handleMemberSelect();
+}
+
+
+
+////////////////////////////
+// LLPanelGroupRolesSubTab
+////////////////////////////
+
+// static
+void* LLPanelGroupRolesSubTab::createTab(void* data)
+{
+ LLUUID* group_id = static_cast<LLUUID*>(data);
+ return new LLPanelGroupRolesSubTab("panel group roles sub tab", *group_id);
+}
+
+LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab(const std::string& name, const LLUUID& group_id)
+: LLPanelGroupSubTab(name, group_id), mHasRoleChange(FALSE)
+{
+}
+
+LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab()
+{
+}
+
+BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
+{
+ // Upcast parent so we can ask it for sibling controls.
+ LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
+
+ // Look recursively from the parent to find all our widgets.
+ bool recurse = true;
+ mHeader = (LLPanel*) parent->getChildByName("roles_header", recurse);
+ mFooter = (LLPanel*) parent->getChildByName("roles_footer", recurse);
+
+
+ mRolesList = (LLScrollListCtrl*) parent->getChildByName("role_list", recurse);
+ mAssignedMembersList = (LLNameListCtrl*) parent->getChildByName("role_assigned_members", recurse);
+ mAllowedActionsList = (LLScrollListCtrl*) parent->getChildByName("role_allowed_actions", recurse);
+
+ mRoleName = (LLLineEditor*) parent->getChildByName("role_name", recurse);
+ mRoleTitle = (LLLineEditor*) parent->getChildByName("role_title", recurse);
+ mRoleDescription = (LLTextEditor*) parent->getChildByName("role_description", recurse);
+
+ mMemberVisibleCheck = (LLCheckBoxCtrl*) parent->getChildByName("role_visible_in_list", recurse);
+
+ if (!mRolesList || !mAssignedMembersList || !mAllowedActionsList
+ || !mRoleName || !mRoleTitle || !mRoleDescription || !mMemberVisibleCheck)
+ {
+ llwarns << "ARG! element not found." << llendl;
+ return FALSE;
+ }
+
+ LLTextBox* txt = (LLTextBox*) parent->getChildByName("cant_delete_role", FALSE);
+ if (txt)
+ {
+ mRemoveEveryoneTxt = txt->getText();
+ parent->removeChild(txt);
+ }
+
+ mCreateRoleButton =
+ (LLButton*) parent->getChildByName("role_create", recurse);
+ if ( mCreateRoleButton )
+ {
+ mCreateRoleButton->setCallbackUserData(this);
+ mCreateRoleButton->setClickedCallback(onCreateRole);
+ mCreateRoleButton->setEnabled(FALSE);
+ }
+
+ mDeleteRoleButton =
+ (LLButton*) parent->getChildByName("role_delete", recurse);
+ if ( mDeleteRoleButton )
+ {
+ mDeleteRoleButton->setCallbackUserData(this);
+ mDeleteRoleButton->setClickedCallback(onDeleteRole);
+ mDeleteRoleButton->setEnabled(FALSE);
+ }
+
+ mRolesList->setCommitOnSelectionChange(TRUE);
+ mRolesList->setCallbackUserData(this);
+ mRolesList->setCommitCallback(onRoleSelect);
+
+ mMemberVisibleCheck->setCallbackUserData(this);
+ mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange);
+
+ mAllowedActionsList->setCommitOnSelectionChange(TRUE);
+ mAllowedActionsList->setCallbackUserData(this);
+
+ mRoleName->setCommitOnFocusLost(TRUE);
+ mRoleName->setCallbackUserData(this);
+ mRoleName->setKeystrokeCallback(onPropertiesKey);
+
+ mRoleTitle->setCommitOnFocusLost(TRUE);
+ mRoleTitle->setCallbackUserData(this);
+ mRoleTitle->setKeystrokeCallback(onPropertiesKey);
+
+ mRoleDescription->setCommitOnFocusLost(TRUE);
+ mRoleDescription->setCallbackUserData(this);
+ mRoleDescription->setCommitCallback(onDescriptionCommit);
+ mRoleDescription->setFocusReceivedCallback(onDescriptionCommit);
+
+ setFooterEnabled(FALSE);
+
+ return TRUE;
+}
+
+void LLPanelGroupRolesSubTab::activate()
+{
+ LLPanelGroupSubTab::activate();
+
+ mRolesList->deselectAllItems();
+ mAssignedMembersList->deleteAllItems();
+ mAllowedActionsList->deleteAllItems();
+ mRoleName->clear();
+ mRoleDescription->clear();
+ mRoleTitle->clear();
+
+ setFooterEnabled(FALSE);
+
+ mHasRoleChange = FALSE;
+ update(GC_ALL);
+}
+
+void LLPanelGroupRolesSubTab::deactivate()
+{
+ lldebugs << "LLPanelGroupRolesSubTab::deactivate()" << llendl;
+
+ LLPanelGroupSubTab::deactivate();
+}
+
+bool LLPanelGroupRolesSubTab::needsApply(LLString& mesg)
+{
+ lldebugs << "LLPanelGroupRolesSubTab::needsApply()" << llendl;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ return (mHasRoleChange // Text changed in current role
+ || (gdatap && gdatap->pendingRoleChanges())); // Pending role changes in the group
+}
+
+bool LLPanelGroupRolesSubTab::apply(LLString& mesg)
+{
+ lldebugs << "LLPanelGroupRolesSubTab::apply()" << llendl;
+
+ saveRoleChanges();
+ gGroupMgr->sendGroupRoleChanges(mGroupID);
+
+ notifyObservers();
+
+ return true;
+}
+
+void LLPanelGroupRolesSubTab::cancel()
+{
+ mHasRoleChange = FALSE;
+ gGroupMgr->cancelGroupRoleChanges(mGroupID);
+
+ notifyObservers();
+}
+
+LLSD LLPanelGroupRolesSubTab::createRoleItem(const LLUUID& role_id,
+ std::string name,
+ std::string title,
+ S32 members)
+{
+ LLSD row;
+ row["id"] = role_id;
+
+ row["columns"][0]["column"] = "name";
+ row["columns"][0]["value"] = name;
+
+ row["columns"][1]["column"] = "title";
+ row["columns"][1]["value"] = title;
+
+ row["columns"][2]["column"] = "members";
+ row["columns"][2]["value"] = members;
+
+ return row;
+}
+
+bool LLPanelGroupRolesSubTab::matchesSearchFilter(std::string rolename, std::string roletitle)
+{
+ // If the search filter is empty, everything passes.
+ if (mSearchFilter.empty()) return true;
+
+ LLString::toLower(rolename);
+ LLString::toLower(roletitle);
+ std::string::size_type match_name = rolename.find(mSearchFilter);
+ std::string::size_type match_title = roletitle.find(mSearchFilter);
+
+ if ( (std::string::npos == match_name)
+ && (std::string::npos == match_title))
+ {
+ // not found
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
+{
+ lldebugs << "LLPanelGroupRolesSubTab::update()" << llendl;
+
+ if (mGroupID.isNull()) return;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ if (!gdatap || !gdatap->isRoleDataComplete())
+ {
+ gGroupMgr->sendGroupRoleDataRequest(mGroupID);
+ }
+ else
+ {
+ bool had_selection = false;
+ LLUUID last_selected;
+ if (mRolesList->getFirstSelected())
+ {
+ last_selected = mRolesList->getFirstSelected()->getUUID();
+ had_selection = true;
+ }
+ mRolesList->deleteAllItems();
+
+ LLScrollListItem* item = NULL;
+
+ LLGroupMgrGroupData::role_iter rit = gdatap->mRoles.begin();
+ LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
+
+ for ( ; rit != end; ++rit)
+ {
+ LLRoleData rd;
+ if (gdatap->getRoleData((*rit).first,rd))
+ {
+ if (matchesSearchFilter(rd.mRoleName, rd.mRoleTitle))
+ {
+ // If this is the everyone role, then EVERYONE is in it.
+ S32 members_in_role = (*rit).first.isNull() ? gdatap->mMembers.size() : (*rit).second->getTotalMembersInRole();
+ LLSD row = createRoleItem((*rit).first,rd.mRoleName, rd.mRoleTitle, members_in_role);
+ item = mRolesList->addElement(row, ((*rit).first.isNull()) ? ADD_TOP : ADD_BOTTOM, this);
+ if (had_selection && ((*rit).first == last_selected))
+ {
+ item->setSelected(TRUE);
+ }
+ }
+ }
+ else
+ {
+ llwarns << "LLPanelGroupRolesSubTab::update() No role data for role " << (*rit).first << llendl;
+ }
+ }
+
+ mRolesList->sortByColumn("name", TRUE);
+
+ if ( (gdatap->mRoles.size() < MAX_ROLES)
+ && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) )
+ {
+ mCreateRoleButton->setEnabled(TRUE);
+ }
+ else
+ {
+ mCreateRoleButton->setEnabled(FALSE);
+ }
+
+ if (had_selection)
+ {
+ handleRoleSelect();
+ }
+ else
+ {
+ mAssignedMembersList->deleteAllItems();
+ mAllowedActionsList->deleteAllItems();
+ mRoleName->clear();
+ mRoleDescription->clear();
+ mRoleTitle->clear();
+ setFooterEnabled(FALSE);
+ mDeleteRoleButton->setEnabled(FALSE);
+ }
+ }
+
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ gGroupMgr->sendGroupMembersRequest(mGroupID);
+ }
+
+ if (!gdatap || !gdatap->isRoleMemberDataComplete())
+ {
+ gGroupMgr->sendGroupRoleMembersRequest(mGroupID);
+ }
+
+ if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
+ && gdatap->isMemberDataComplete()
+ && gdatap->isRoleMemberDataComplete())
+ {
+ buildMembersList();
+ }
+}
+
+// static
+void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ self->handleRoleSelect();
+}
+
+void LLPanelGroupRolesSubTab::handleRoleSelect()
+{
+ BOOL can_delete = TRUE;
+ lldebugs << "LLPanelGroupRolesSubTab::handleRoleSelect()" << llendl;
+
+ mAssignedMembersList->deleteAllItems();
+ mAllowedActionsList->deleteAllItems();
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
+ << "-- No group data!" << llendl;
+ return;
+ }
+
+ saveRoleChanges();
+
+ // Check if there is anything selected.
+ LLScrollListItem* item = mRolesList->getFirstSelected();
+ if (!item)
+ {
+ setFooterEnabled(FALSE);
+ return;
+ }
+
+ setFooterEnabled(TRUE);
+
+ LLRoleData rd;
+ if (gdatap->getRoleData(item->getUUID(),rd))
+ {
+ BOOL is_owner_role = ( gdatap->mOwnerRole == item->getUUID() );
+ mRoleName->setText(rd.mRoleName);
+ mRoleTitle->setText(rd.mRoleTitle);
+ mRoleDescription->setText(rd.mRoleDescription);
+
+ mAllowedActionsList->setEnabled(gAgent.hasPowerInGroup(mGroupID,
+ GP_ROLE_CHANGE_ACTIONS));
+ buildActionsList(mAllowedActionsList,
+ rd.mRolePowers,
+ 0LL,
+ mActionIcons,
+ onActionCheck,
+ TRUE,
+ FALSE,
+ is_owner_role);
+
+
+ mMemberVisibleCheck->set((rd.mRolePowers & GP_MEMBER_VISIBLE_IN_DIR) == GP_MEMBER_VISIBLE_IN_DIR);
+ mRoleName->setEnabled(!is_owner_role &&
+ gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
+ mRoleTitle->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
+ mRoleDescription->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
+ mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
+
+ if (item->getUUID().isNull())
+ {
+ // Everyone role, can't edit description or name or delete
+ mRoleDescription->setEnabled(FALSE);
+ mRoleName->setEnabled(FALSE);
+ can_delete = FALSE;
+ }
+ //you can't delete the owner role
+ if ( is_owner_role ) can_delete = FALSE;
+ }
+ else
+ {
+ mRolesList->deselectAllItems();
+ mAssignedMembersList->deleteAllItems();
+ mAllowedActionsList->deleteAllItems();
+ mRoleName->clear();
+ mRoleDescription->clear();
+ mRoleTitle->clear();
+ setFooterEnabled(FALSE);
+
+ can_delete = FALSE;
+ }
+ mSelectedRole = item->getUUID();
+ buildMembersList();
+
+ can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
+ GP_ROLE_DELETE);
+ mDeleteRoleButton->setEnabled(can_delete);
+}
+
+void LLPanelGroupRolesSubTab::buildMembersList()
+{
+ mAssignedMembersList->deleteAllItems();
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
+ << "-- No group data!" << llendl;
+ return;
+ }
+
+ // Check if there is anything selected.
+ LLScrollListItem* item = mRolesList->getFirstSelected();
+ if (!item) return;
+
+ if (item->getUUID().isNull())
+ {
+ // Special cased 'Everyone' role
+ LLGroupMgrGroupData::member_iter mit = gdatap->mMembers.begin();
+ LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
+ for ( ; mit != end; ++mit)
+ {
+ mAssignedMembersList->addNameItem((*mit).first);
+ }
+ }
+ else
+ {
+ LLGroupMgrGroupData::role_iter rit = gdatap->mRoles.find(item->getUUID());
+ if (rit != gdatap->mRoles.end())
+ {
+ LLGroupRoleData* rdatap = (*rit).second;
+ if (rdatap)
+ {
+ std::vector<LLUUID>::const_iterator mit = rdatap->getMembersBegin();
+ std::vector<LLUUID>::const_iterator end = rdatap->getMembersEnd();
+ for ( ; mit != end; ++mit)
+ {
+ mAssignedMembersList->addNameItem((*mit));
+ }
+ }
+ }
+ }
+}
+
+// static
+void LLPanelGroupRolesSubTab::onActionCheck(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
+ if (!check || !self) return;
+
+ self->handleActionCheck(check);
+}
+
+struct ActionCBData
+{
+ LLPanelGroupRolesSubTab* mSelf;
+ LLCheckBoxCtrl* mCheck;
+};
+
+void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool force)
+{
+ lldebugs << "LLPanelGroupRolesSubTab::handleActionSelect()" << llendl;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
+ << "-- No group data!" << llendl;
+ return;
+ }
+
+ LLScrollListItem* action_item = mAllowedActionsList->getFirstSelected();
+ if (!action_item)
+ {
+ return;
+ }
+
+ LLScrollListItem* role_item = mRolesList->getFirstSelected();
+ if (!role_item)
+ {
+ return;
+ }
+ LLUUID role_id = role_item->getUUID();
+
+ LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
+ U64 power = rap->mPowerBit;
+
+ if (check->get())
+ {
+ if (!force && ( (GP_ROLE_ASSIGN_MEMBER == power)
+ || (GP_ROLE_CHANGE_ACTIONS == power) ))
+ {
+ // Uncheck the item, for now. It will be
+ // checked if they click 'Yes', below.
+ check->set(FALSE);
+
+ LLRoleData rd;
+ LLStringBase<char>::format_map_t args;
+
+ if ( gdatap->getRoleData(role_id, rd) )
+ {
+ args["[ACTION_NAME]"] = rap->mDescription;
+ args["[ROLE_NAME]"] = rd.mRoleName;
+ struct ActionCBData* cb_data = new ActionCBData;
+ cb_data->mSelf = this;
+ cb_data->mCheck = check;
+ mHasModal = TRUE;
+ LLString warning = "AssignDangerousActionWarning";
+ if (GP_ROLE_CHANGE_ACTIONS == power)
+ {
+ warning = "AssignDangerousAbilityWarning";
+ }
+ gViewerWindow->alertXml(warning, args, addActionCB, cb_data);
+ }
+ else
+ {
+ llwarns << "Unable to look up role information for role id: "
+ << role_id << llendl;
+ }
+ }
+ else
+ {
+ gdatap->addRolePower(role_id,power);
+ }
+ }
+ else
+ {
+ gdatap->removeRolePower(role_id,power);
+ }
+
+ mHasRoleChange = TRUE;
+ notifyObservers();
+}
+
+//static
+void LLPanelGroupRolesSubTab::addActionCB(S32 option, void* data)
+{
+ struct ActionCBData* cb_data = (struct ActionCBData*) data;
+
+ if (!cb_data || !cb_data->mSelf || !cb_data->mCheck) return;
+
+ cb_data->mSelf->mHasModal = FALSE;
+
+ if (0 == option)
+ {
+ // User clicked "Yes"
+ cb_data->mCheck->set(TRUE);
+ const bool force_add = true;
+ cb_data->mSelf->handleActionCheck(cb_data->mCheck, force_add);
+ }
+}
+
+
+// static
+void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self) return;
+
+ self->mHasRoleChange = TRUE;
+ self->notifyObservers();
+}
+
+// static
+void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self) return;
+
+ self->mHasRoleChange = TRUE;
+ self->notifyObservers();
+}
+
+// static
+void LLPanelGroupRolesSubTab::onMemberVisibilityChange(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
+ if (!check || !self) return;
+
+ self->handleMemberVisibilityChange(check->get());
+}
+
+void LLPanelGroupRolesSubTab::handleMemberVisibilityChange(bool value)
+{
+ lldebugs << "LLPanelGroupRolesSubTab::handleMemberVisibilityChange()" << llendl;
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
+ << "-- No group data!" << llendl;
+ return;
+ }
+
+ LLScrollListItem* role_item = mRolesList->getFirstSelected();
+ if (!role_item)
+ {
+ return;
+ }
+
+ if (value)
+ {
+ gdatap->addRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
+ }
+ else
+ {
+ gdatap->removeRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
+ }
+}
+
+// static
+void LLPanelGroupRolesSubTab::onCreateRole(void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self) return;
+
+ self->handleCreateRole();
+}
+
+void LLPanelGroupRolesSubTab::handleCreateRole()
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ if (!gdatap) return;
+
+ LLUUID new_role_id;
+ new_role_id.generate();
+
+ LLRoleData rd;
+ rd.mRoleName = "New Role";
+ gdatap->createRole(new_role_id,rd);
+
+ mRolesList->deselectAllItems(TRUE);
+ LLSD row;
+ row["id"] = new_role_id;
+ row["columns"][0]["column"] = "name";
+ row["columns"][0]["value"] = rd.mRoleName;
+ mRolesList->addElement(row, ADD_BOTTOM, this);
+ mRolesList->selectByID(new_role_id);
+
+ // put focus on name field and select its contents
+ if(mRoleName)
+ {
+ mRoleName->setFocus(TRUE);
+ mRoleName->onTabInto();
+ gFocusMgr.triggerFocusFlash();
+ }
+
+ notifyObservers();
+}
+
+// static
+void LLPanelGroupRolesSubTab::onDeleteRole(void* user_data)
+{
+ LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self) return;
+
+ self->handleDeleteRole();
+}
+
+void LLPanelGroupRolesSubTab::handleDeleteRole()
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ if (!gdatap) return;
+
+ LLScrollListItem* role_item = mRolesList->getFirstSelected();
+ if (!role_item)
+ {
+ return;
+ }
+
+ if (role_item->getUUID().isNull() || role_item->getUUID() == gdatap->mOwnerRole)
+ {
+ LLString::format_map_t args;
+ args["[MESSAGE]"] = mRemoveEveryoneTxt;
+ LLNotifyBox::showXml("GenericNotify", args);
+ return;
+ }
+
+ gdatap->deleteRole(role_item->getUUID());
+ mRolesList->deleteSingleItem(mRolesList->getFirstSelectedIndex());
+ mRolesList->selectFirstItem();
+
+ notifyObservers();
+}
+
+void LLPanelGroupRolesSubTab::saveRoleChanges()
+{
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ if (!gdatap) return;
+
+ if (mHasRoleChange)
+ {
+ LLRoleData rd;
+ if (!gdatap->getRoleData(mSelectedRole,rd)) return;
+
+ rd.mRoleName = mRoleName->getText();
+ rd.mRoleDescription = mRoleDescription->getText();
+ rd.mRoleTitle = mRoleTitle->getText();
+
+ gdatap->setRoleData(mSelectedRole,rd);
+
+ mRolesList->deleteSingleItem(mRolesList->getItemIndex(mSelectedRole));
+
+ LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,0);
+ LLScrollListItem* item = mRolesList->addElement(row, ADD_BOTTOM, this);
+ item->setSelected(TRUE);
+
+ mHasRoleChange = FALSE;
+ }
+}
+////////////////////////////
+// LLPanelGroupActionsSubTab
+////////////////////////////
+
+// static
+void* LLPanelGroupActionsSubTab::createTab(void* data)
+{
+ LLUUID* group_id = static_cast<LLUUID*>(data);
+ return new LLPanelGroupActionsSubTab("panel group actions sub tab", *group_id);
+}
+
+LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab(const std::string& name, const LLUUID& group_id)
+: LLPanelGroupSubTab(name, group_id)
+{
+}
+
+LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab()
+{
+}
+
+BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
+{
+ // Upcast parent so we can ask it for sibling controls.
+ LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
+
+ // Look recursively from the parent to find all our widgets.
+ bool recurse = true;
+ mHeader = (LLPanel*) parent->getChildByName("actions_header", recurse);
+ mFooter = (LLPanel*) parent->getChildByName("actions_footer", recurse);
+
+ mActionDescription = (LLTextEditor*) parent->getChildByName("action_description", recurse);
+
+ mActionList = (LLScrollListCtrl*) parent->getChildByName("action_list",recurse);
+ mActionRoles = (LLScrollListCtrl*) parent->getChildByName("action_roles",recurse);
+ mActionMembers = (LLNameListCtrl*) parent->getChildByName("action_members",recurse);
+
+ if (!mActionList || !mActionDescription || !mActionRoles || !mActionMembers) return FALSE;
+
+ mActionList->setCallbackUserData(this);
+ mActionList->setCommitOnSelectionChange(TRUE);
+ mActionList->setCommitCallback(onActionSelect);
+
+ mActionMembers->setCallbackUserData(this);
+ mActionRoles->setCallbackUserData(this);
+
+ update(GC_ALL);
+
+ return TRUE;
+}
+
+void LLPanelGroupActionsSubTab::activate()
+{
+ LLPanelGroupSubTab::activate();
+ lldebugs << "LLPanelGroupActionsSubTab::activate()" << llendl;
+
+ mActionList->deselectAllItems();
+ mActionMembers->deleteAllItems();
+ mActionRoles->deleteAllItems();
+ mActionDescription->clear();
+}
+
+void LLPanelGroupActionsSubTab::deactivate()
+{
+ lldebugs << "LLPanelGroupActionsSubTab::deactivate()" << llendl;
+
+ LLPanelGroupSubTab::deactivate();
+}
+
+bool LLPanelGroupActionsSubTab::needsApply(LLString& mesg)
+{
+ lldebugs << "LLPanelGroupActionsSubTab::needsApply()" << llendl;
+
+ return false;
+}
+
+bool LLPanelGroupActionsSubTab::apply(LLString& mesg)
+{
+ lldebugs << "LLPanelGroupActionsSubTab::apply()" << llendl;
+ return true;
+}
+
+void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
+{
+ lldebugs << "LLPanelGroupActionsSubTab::update()" << llendl;
+
+ if (mGroupID.isNull()) return;
+
+ mActionList->deselectAllItems();
+ mActionMembers->deleteAllItems();
+ mActionRoles->deleteAllItems();
+ mActionDescription->clear();
+
+ mActionList->deleteAllItems();
+ buildActionsList(mActionList,
+ GP_ALL_POWERS,
+ GP_ALL_POWERS,
+ mActionIcons,
+ NULL,
+ FALSE,
+ TRUE,
+ FALSE);
+}
+
+// static
+void LLPanelGroupActionsSubTab::onActionSelect(LLUICtrl* scroll, void* data)
+{
+ LLPanelGroupActionsSubTab* self = static_cast<LLPanelGroupActionsSubTab*>(data);
+ self->handleActionSelect();
+}
+
+void LLPanelGroupActionsSubTab::handleActionSelect()
+{
+ mActionMembers->deleteAllItems();
+ mActionRoles->deleteAllItems();
+
+ U64 power_mask = GP_NO_POWERS;
+ std::vector<LLScrollListItem*> selection =
+ mActionList->getAllSelected();
+ if (selection.empty()) return;
+
+ LLRoleAction* rap;
+
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin() ;
+ itor != selection.end(); ++itor)
+ {
+ rap = (LLRoleAction*)( (*itor)->getUserdata() );
+ power_mask |= rap->mPowerBit;
+ }
+
+ if (selection.size() == 1)
+ {
+ LLScrollListItem* item = selection[0];
+ rap = (LLRoleAction*)(item->getUserdata());
+
+ if (rap->mLongDescription.empty())
+ {
+ mActionDescription->setText(rap->mDescription);
+ }
+ else
+ {
+ mActionDescription->setText(rap->mLongDescription);
+ }
+ }
+ else
+ {
+ mActionDescription->clear();
+ }
+
+ LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
+
+ if (!gdatap) return;
+
+ if (gdatap->isMemberDataComplete())
+ {
+ LLGroupMgrGroupData::member_iter it = gdatap->mMembers.begin();
+ LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
+ LLGroupMemberData* gmd;
+
+ for ( ; it != end; ++it)
+ {
+ gmd = (*it).second;
+ if (!gmd) continue;
+ if ((gmd->getAgentPowers() & power_mask) == power_mask)
+ {
+ mActionMembers->addNameItem(gmd->getID());
+ }
+ }
+ }
+ else
+ {
+ gGroupMgr->sendGroupMembersRequest(mGroupID);
+ }
+
+ if (gdatap->isRoleDataComplete())
+ {
+ LLGroupMgrGroupData::role_iter it = gdatap->mRoles.begin();
+ LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
+ LLGroupRoleData* rmd;
+
+ for ( ; it != end; ++it)
+ {
+ rmd = (*it).second;
+ if (!rmd) continue;
+ if ((rmd->getRoleData().mRolePowers & power_mask) == power_mask)
+ {
+ mActionRoles->addSimpleItem(rmd->getRoleData().mRoleName);
+ }
+ }
+ }
+ else
+ {
+ gGroupMgr->sendGroupRoleDataRequest(mGroupID);
+ }
+}