PageRenderTime 51ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpanelgrouproles.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2485 lines | 1828 code | 425 blank | 232 comment | 347 complexity | bb32cc6690ff46a106b20a14dffc7978 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpanelgrouproles.cpp
  3. * @brief Panel for roles information about a particular group.
  4. *
  5. * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llcheckboxctrl.h"
  28. #include "llagent.h"
  29. #include "llbutton.h"
  30. #include "llfiltereditor.h"
  31. #include "llfloatergroupinvite.h"
  32. #include "llavataractions.h"
  33. #include "lliconctrl.h"
  34. #include "lllineeditor.h"
  35. #include "llnamelistctrl.h"
  36. #include "llnotifications.h"
  37. #include "llnotificationsutil.h"
  38. #include "llpanelgrouproles.h"
  39. #include "llscrolllistctrl.h"
  40. #include "llscrolllistitem.h"
  41. #include "llscrolllistcell.h"
  42. #include "llslurl.h"
  43. #include "lltabcontainer.h"
  44. #include "lltextbox.h"
  45. #include "lltexteditor.h"
  46. #include "lltrans.h"
  47. #include "llviewertexturelist.h"
  48. #include "llviewerwindow.h"
  49. #include "llfocusmgr.h"
  50. #include "llviewercontrol.h"
  51. #include "roles_constants.h"
  52. static LLRegisterPanelClassWrapper<LLPanelGroupRoles> t_panel_group_roles("panel_group_roles");
  53. bool agentCanRemoveFromRole(const LLUUID& group_id,
  54. const LLUUID& role_id)
  55. {
  56. return gAgent.hasPowerInGroup(group_id, GP_ROLE_REMOVE_MEMBER);
  57. }
  58. bool agentCanAddToRole(const LLUUID& group_id,
  59. const LLUUID& role_id)
  60. {
  61. if (gAgent.isGodlike())
  62. return true;
  63. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
  64. if (!gdatap)
  65. {
  66. llwarns << "agentCanAddToRole "
  67. << "-- No group data!" << llendl;
  68. return false;
  69. }
  70. //make sure the agent is in the group
  71. LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
  72. if (mi == gdatap->mMembers.end())
  73. {
  74. return false;
  75. }
  76. LLGroupMemberData* member_data = (*mi).second;
  77. // Owners can add to any role.
  78. if ( member_data->isInRole(gdatap->mOwnerRole) )
  79. {
  80. return true;
  81. }
  82. // 'Limited assign members' can add to roles the user is in.
  83. if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER_LIMITED) &&
  84. member_data->isInRole(role_id) )
  85. {
  86. return true;
  87. }
  88. // 'assign members' can add to non-owner roles.
  89. if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER) &&
  90. role_id != gdatap->mOwnerRole )
  91. {
  92. return true;
  93. }
  94. return false;
  95. }
  96. // static
  97. LLPanelGroupRoles::LLPanelGroupRoles()
  98. : LLPanelGroupTab(),
  99. mCurrentTab(NULL),
  100. mRequestedTab( NULL ),
  101. mSubTabContainer( NULL ),
  102. mFirstUse( TRUE )
  103. {
  104. }
  105. LLPanelGroupRoles::~LLPanelGroupRoles()
  106. {
  107. }
  108. BOOL LLPanelGroupRoles::postBuild()
  109. {
  110. lldebugs << "LLPanelGroupRoles::postBuild()" << llendl;
  111. mSubTabContainer = getChild<LLTabContainer>("roles_tab_container");
  112. if (!mSubTabContainer) return FALSE;
  113. // Hook up each sub-tabs callback and widgets.
  114. for (S32 i = 0; i < mSubTabContainer->getTabCount(); ++i)
  115. {
  116. LLPanel* panel = mSubTabContainer->getPanelByIndex(i);
  117. LLPanelGroupSubTab* subtabp = dynamic_cast<LLPanelGroupSubTab*>(panel);
  118. if (!subtabp)
  119. {
  120. llwarns << "Invalid subtab panel: " << panel->getName() << llendl;
  121. return FALSE;
  122. }
  123. // Hand the subtab a pointer to this LLPanelGroupRoles, so that it can
  124. // look around for the widgets it is interested in.
  125. if (!subtabp->postBuildSubTab(this))
  126. return FALSE;
  127. //subtabp->addObserver(this);
  128. }
  129. // Add click callbacks to tab switching.
  130. mSubTabContainer->setValidateBeforeCommit(boost::bind(&LLPanelGroupRoles::handleSubTabSwitch, this, _1));
  131. // Set the current tab to whatever is currently being shown.
  132. mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  133. if (!mCurrentTab)
  134. {
  135. // Need to select a tab.
  136. mSubTabContainer->selectFirstTab();
  137. mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  138. }
  139. if (!mCurrentTab) return FALSE;
  140. // Act as though this tab was just activated.
  141. mCurrentTab->activate();
  142. // Read apply text from the xml file.
  143. mDefaultNeedsApplyMesg = getString("default_needs_apply_text");
  144. mWantApplyMesg = getString("want_apply_text");
  145. return LLPanelGroupTab::postBuild();
  146. }
  147. BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp)
  148. {
  149. /* This power was removed to make group roles simpler
  150. return agentp->hasPowerInGroup(mGroupID,
  151. GP_ROLE_CREATE |
  152. GP_ROLE_DELETE |
  153. GP_ROLE_PROPERTIES |
  154. GP_ROLE_VIEW |
  155. GP_ROLE_ASSIGN_MEMBER |
  156. GP_ROLE_REMOVE_MEMBER |
  157. GP_ROLE_CHANGE_ACTIONS |
  158. GP_MEMBER_INVITE |
  159. GP_MEMBER_EJECT |
  160. GP_MEMBER_OPTIONS );
  161. */
  162. return mAllowEdit && agentp->isInGroup(mGroupID);
  163. }
  164. bool LLPanelGroupRoles::handleSubTabSwitch(const LLSD& data)
  165. {
  166. std::string panel_name = data.asString();
  167. if(mRequestedTab != NULL)//we already have tab change request
  168. {
  169. return false;
  170. }
  171. mRequestedTab = static_cast<LLPanelGroupTab*>(mSubTabContainer->getPanelByName(panel_name));
  172. std::string mesg;
  173. if (mCurrentTab && mCurrentTab->needsApply(mesg))
  174. {
  175. // If no message was provided, give a generic one.
  176. if (mesg.empty())
  177. {
  178. mesg = mDefaultNeedsApplyMesg;
  179. }
  180. // Create a notify box, telling the user about the unapplied tab.
  181. LLSD args;
  182. args["NEEDS_APPLY_MESSAGE"] = mesg;
  183. args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
  184. LLNotificationsUtil::add("PanelGroupApply", args, LLSD(),
  185. boost::bind(&LLPanelGroupRoles::handleNotifyCallback, this, _1, _2));
  186. mHasModal = TRUE;
  187. // Returning FALSE will block a close action from finishing until
  188. // we get a response back from the user.
  189. return false;
  190. }
  191. transitionToTab();
  192. return true;
  193. }
  194. void LLPanelGroupRoles::transitionToTab()
  195. {
  196. // Tell the current panel that it is being deactivated.
  197. if (mCurrentTab)
  198. {
  199. mCurrentTab->deactivate();
  200. }
  201. // Tell the new panel that it is being activated.
  202. if (mRequestedTab)
  203. {
  204. // This is now the current tab;
  205. mCurrentTab = mRequestedTab;
  206. mCurrentTab->activate();
  207. mRequestedTab = 0;
  208. }
  209. }
  210. bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLSD& response)
  211. {
  212. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  213. mHasModal = FALSE;
  214. LLPanelGroupTab* transition_tab = mRequestedTab;
  215. switch (option)
  216. {
  217. case 0: // "Apply Changes"
  218. {
  219. // Try to apply changes, and switch to the requested tab.
  220. std::string apply_mesg;
  221. if ( !apply( apply_mesg ) )
  222. {
  223. // There was a problem doing the apply.
  224. if ( !apply_mesg.empty() )
  225. {
  226. mHasModal = TRUE;
  227. LLSD args;
  228. args["MESSAGE"] = apply_mesg;
  229. LLNotificationsUtil::add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2));
  230. }
  231. // Skip switching tabs.
  232. break;
  233. }
  234. transitionToTab();
  235. mSubTabContainer->selectTabPanel( transition_tab );
  236. break;
  237. }
  238. case 1: // "Ignore Changes"
  239. // Switch to the requested panel without applying changes
  240. cancel();
  241. transitionToTab();
  242. mSubTabContainer->selectTabPanel( transition_tab );
  243. break;
  244. case 2: // "Cancel"
  245. default:
  246. mRequestedTab = NULL;
  247. // Do nothing. The user is canceling the action.
  248. break;
  249. }
  250. return false;
  251. }
  252. bool LLPanelGroupRoles::onModalClose(const LLSD& notification, const LLSD& response)
  253. {
  254. mHasModal = FALSE;
  255. return false;
  256. }
  257. bool LLPanelGroupRoles::apply(std::string& mesg)
  258. {
  259. // Pass this along to the currently visible sub tab.
  260. if (!mSubTabContainer) return false;
  261. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  262. if (!panelp) return false;
  263. // Ignore the needs apply message.
  264. std::string ignore_mesg;
  265. if ( !panelp->needsApply(ignore_mesg) )
  266. {
  267. // We don't need to apply anything.
  268. // We're done.
  269. return true;
  270. }
  271. // Try to do the actual apply.
  272. return panelp->apply(mesg);
  273. }
  274. void LLPanelGroupRoles::cancel()
  275. {
  276. // Pass this along to the currently visible sub tab.
  277. if (!mSubTabContainer) return;
  278. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  279. if (!panelp) return;
  280. panelp->cancel();
  281. }
  282. void LLPanelGroupRoles::update(LLGroupChange gc)
  283. {
  284. if (mGroupID.isNull()) return;
  285. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  286. if (panelp)
  287. {
  288. panelp->update(gc);
  289. }
  290. else
  291. {
  292. llwarns << "LLPanelGroupRoles::update() -- No subtab to update!" << llendl;
  293. }
  294. }
  295. void LLPanelGroupRoles::activate()
  296. {
  297. // Start requesting member and role data if needed.
  298. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  299. //if (!gdatap || mFirstUse)
  300. {
  301. // Check member data.
  302. if (!gdatap || !gdatap->isMemberDataComplete() )
  303. {
  304. LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID);
  305. }
  306. // Check role data.
  307. if (!gdatap || !gdatap->isRoleDataComplete() )
  308. {
  309. // Mildly hackish - clear all pending changes
  310. cancel();
  311. LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
  312. }
  313. // Check role-member mapping data.
  314. if (!gdatap || !gdatap->isRoleMemberDataComplete() )
  315. {
  316. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
  317. }
  318. // Need this to get base group member powers
  319. if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
  320. {
  321. LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
  322. }
  323. mFirstUse = FALSE;
  324. }
  325. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  326. if (panelp) panelp->activate();
  327. }
  328. void LLPanelGroupRoles::deactivate()
  329. {
  330. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  331. if (panelp) panelp->deactivate();
  332. }
  333. bool LLPanelGroupRoles::needsApply(std::string& mesg)
  334. {
  335. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  336. if (!panelp) return false;
  337. return panelp->needsApply(mesg);
  338. }
  339. BOOL LLPanelGroupRoles::hasModal()
  340. {
  341. if (mHasModal) return TRUE;
  342. LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
  343. if (!panelp) return FALSE;
  344. return panelp->hasModal();
  345. }
  346. ////////////////////////////
  347. // LLPanelGroupSubTab
  348. ////////////////////////////
  349. LLPanelGroupSubTab::LLPanelGroupSubTab()
  350. : LLPanelGroupTab(),
  351. mHeader(NULL),
  352. mFooter(NULL),
  353. mActivated(false),
  354. mSearchEditor(NULL)
  355. {
  356. }
  357. LLPanelGroupSubTab::~LLPanelGroupSubTab()
  358. {
  359. }
  360. BOOL LLPanelGroupSubTab::postBuildSubTab(LLView* root)
  361. {
  362. // Get icons for later use.
  363. mActionIcons.clear();
  364. if (hasString("power_folder_icon"))
  365. {
  366. mActionIcons["folder"] = getString("power_folder_icon");
  367. }
  368. if (hasString("power_all_have_icon"))
  369. {
  370. mActionIcons["full"] = getString("power_all_have_icon");
  371. }
  372. if (hasString("power_partial_icon"))
  373. {
  374. mActionIcons["partial"] = getString("power_partial_icon");
  375. }
  376. return TRUE;
  377. }
  378. BOOL LLPanelGroupSubTab::postBuild()
  379. {
  380. // Hook up the search widgets.
  381. bool recurse = true;
  382. mSearchEditor = getChild<LLFilterEditor>("filter_input", recurse);
  383. if (!mSearchEditor)
  384. return FALSE;
  385. mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::setSearchFilter, this, _2));
  386. return LLPanelGroupTab::postBuild();
  387. }
  388. void LLPanelGroupSubTab::setGroupID(const LLUUID& id)
  389. {
  390. LLPanelGroupTab::setGroupID(id);
  391. if(mSearchEditor)
  392. {
  393. mSearchEditor->clear();
  394. setSearchFilter("");
  395. }
  396. mActivated = false;
  397. }
  398. void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
  399. {
  400. if(mSearchFilter == filter)
  401. return;
  402. mSearchFilter = filter;
  403. LLStringUtil::toLower(mSearchFilter);
  404. update(GC_ALL);
  405. }
  406. void LLPanelGroupSubTab::activate()
  407. {
  408. setOthersVisible(TRUE);
  409. }
  410. void LLPanelGroupSubTab::deactivate()
  411. {
  412. setOthersVisible(FALSE);
  413. }
  414. void LLPanelGroupSubTab::setOthersVisible(BOOL b)
  415. {
  416. if (mHeader)
  417. {
  418. mHeader->setVisible( b );
  419. }
  420. if (mFooter)
  421. {
  422. mFooter->setVisible( b );
  423. }
  424. }
  425. bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
  426. {
  427. // If the search filter is empty, everything passes.
  428. if (mSearchFilter.empty()) return true;
  429. LLStringUtil::toLower(action);
  430. std::string::size_type match = action.find(mSearchFilter);
  431. if (std::string::npos == match)
  432. {
  433. // not found
  434. return false;
  435. }
  436. else
  437. {
  438. return true;
  439. }
  440. }
  441. void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
  442. U64 allowed_by_some,
  443. U64 allowed_by_all,
  444. LLUICtrl::commit_callback_t commit_callback,
  445. BOOL show_all,
  446. BOOL filter,
  447. BOOL is_owner_role)
  448. {
  449. if (LLGroupMgr::getInstance()->mRoleActionSets.empty())
  450. {
  451. llwarns << "Can't build action list - no actions found." << llendl;
  452. return;
  453. }
  454. std::vector<LLRoleActionSet*>::iterator ras_it = LLGroupMgr::getInstance()->mRoleActionSets.begin();
  455. std::vector<LLRoleActionSet*>::iterator ras_end = LLGroupMgr::getInstance()->mRoleActionSets.end();
  456. for ( ; ras_it != ras_end; ++ras_it)
  457. {
  458. buildActionCategory(ctrl,
  459. allowed_by_some,
  460. allowed_by_all,
  461. (*ras_it),
  462. commit_callback,
  463. show_all,
  464. filter,
  465. is_owner_role);
  466. }
  467. }
  468. void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
  469. U64 allowed_by_some,
  470. U64 allowed_by_all,
  471. LLRoleActionSet* action_set,
  472. LLUICtrl::commit_callback_t commit_callback,
  473. BOOL show_all,
  474. BOOL filter,
  475. BOOL is_owner_role)
  476. {
  477. lldebugs << "Building role list for: " << action_set->mActionSetData->mName << llendl;
  478. // See if the allow mask matches anything in this category.
  479. if (show_all || (allowed_by_some & action_set->mActionSetData->mPowerBit))
  480. {
  481. // List all the actions in this category that at least some members have.
  482. LLSD row;
  483. row["columns"][0]["column"] = "icon";
  484. row["columns"][0]["type"] = "icon";
  485. icon_map_t::iterator iter = mActionIcons.find("folder");
  486. if (iter != mActionIcons.end())
  487. {
  488. row["columns"][0]["value"] = (*iter).second;
  489. }
  490. row["columns"][1]["column"] = "action";
  491. row["columns"][1]["type"] = "text";
  492. row["columns"][1]["value"] = LLTrans::getString(action_set->mActionSetData->mName);
  493. row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
  494. LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
  495. LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(title_row->getColumn(2)); //?? I have no idea fix getColumn(1) return column spacer...
  496. if (name_textp)
  497. name_textp->setFontStyle(LLFontGL::BOLD);
  498. bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
  499. std::vector<LLRoleAction*>::iterator ra_it = action_set->mActions.begin();
  500. std::vector<LLRoleAction*>::iterator ra_end = action_set->mActions.end();
  501. bool items_match_filter = false;
  502. BOOL can_change_actions = (!is_owner_role && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CHANGE_ACTIONS));
  503. for ( ; ra_it != ra_end; ++ra_it)
  504. {
  505. // See if anyone has these action.
  506. if (!show_all && !(allowed_by_some & (*ra_it)->mPowerBit))
  507. {
  508. continue;
  509. }
  510. // See if we are filtering out these actions
  511. // If we aren't using filters, category_matches_filter will be true.
  512. if (!category_matches_filter
  513. && !matchesActionSearchFilter((*ra_it)->mDescription))
  514. {
  515. continue;
  516. }
  517. items_match_filter = true;
  518. // See if everyone has these actions.
  519. bool show_full_strength = false;
  520. if ( (allowed_by_some & (*ra_it)->mPowerBit) == (allowed_by_all & (*ra_it)->mPowerBit) )
  521. {
  522. show_full_strength = true;
  523. }
  524. LLSD row;
  525. S32 column_index = 0;
  526. row["columns"][column_index]["column"] = "icon";
  527. ++column_index;
  528. S32 check_box_index = -1;
  529. if (commit_callback)
  530. {
  531. row["columns"][column_index]["column"] = "checkbox";
  532. row["columns"][column_index]["type"] = "checkbox";
  533. check_box_index = column_index;
  534. ++column_index;
  535. }
  536. else
  537. {
  538. if (show_full_strength)
  539. {
  540. icon_map_t::iterator iter = mActionIcons.find("full");
  541. if (iter != mActionIcons.end())
  542. {
  543. row["columns"][column_index]["column"] = "checkbox";
  544. row["columns"][column_index]["type"] = "icon";
  545. row["columns"][column_index]["value"] = (*iter).second;
  546. ++column_index;
  547. }
  548. }
  549. else
  550. {
  551. icon_map_t::iterator iter = mActionIcons.find("partial");
  552. if (iter != mActionIcons.end())
  553. {
  554. row["columns"][column_index]["column"] = "checkbox";
  555. row["columns"][column_index]["type"] = "icon";
  556. row["columns"][column_index]["value"] = (*iter).second;
  557. ++column_index;
  558. }
  559. row["enabled"] = false;
  560. }
  561. }
  562. row["columns"][column_index]["column"] = "action";
  563. row["columns"][column_index]["value"] = (*ra_it)->mDescription;
  564. row["columns"][column_index]["font"] = "SANSSERIF_SMALL";
  565. LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
  566. if (-1 != check_box_index)
  567. {
  568. // Extract the checkbox that was created.
  569. LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(check_box_index);
  570. LLCheckBoxCtrl* check = check_cell->getCheckBox();
  571. check->setEnabled(can_change_actions);
  572. check->setCommitCallback(commit_callback);
  573. check->setToolTip( check->getLabel() );
  574. if (show_all)
  575. {
  576. check->setTentative(FALSE);
  577. if (allowed_by_some & (*ra_it)->mPowerBit)
  578. {
  579. check->set(TRUE);
  580. }
  581. else
  582. {
  583. check->set(FALSE);
  584. }
  585. }
  586. else
  587. {
  588. check->set(TRUE);
  589. if (show_full_strength)
  590. {
  591. check->setTentative(FALSE);
  592. }
  593. else
  594. {
  595. check->setTentative(TRUE);
  596. }
  597. }
  598. }
  599. }
  600. if (!items_match_filter)
  601. {
  602. S32 title_index = ctrl->getItemIndex(title_row);
  603. ctrl->deleteSingleItem(title_index);
  604. }
  605. }
  606. }
  607. void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
  608. {
  609. if (mFooter)
  610. {
  611. mFooter->setAllChildrenEnabled(enable);
  612. }
  613. }
  614. ////////////////////////////
  615. // LLPanelGroupMembersSubTab
  616. ////////////////////////////
  617. static LLRegisterPanelClassWrapper<LLPanelGroupMembersSubTab> t_panel_group_members_subtab("panel_group_members_subtab");
  618. LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
  619. : LLPanelGroupSubTab(),
  620. mMembersList(NULL),
  621. mAssignedRolesList(NULL),
  622. mAllowedActionsList(NULL),
  623. mChanged(FALSE),
  624. mPendingMemberUpdate(FALSE),
  625. mHasMatch(FALSE),
  626. mNumOwnerAdditions(0)
  627. {
  628. mUdpateSessionID = LLUUID::null;
  629. }
  630. LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
  631. {
  632. gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName());
  633. }
  634. BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
  635. {
  636. LLPanelGroupSubTab::postBuildSubTab(root);
  637. // Upcast parent so we can ask it for sibling controls.
  638. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
  639. // Look recursively from the parent to find all our widgets.
  640. bool recurse = true;
  641. mHeader = parent->getChild<LLPanel>("members_header", recurse);
  642. mFooter = parent->getChild<LLPanel>("members_footer", recurse);
  643. mMembersList = parent->getChild<LLNameListCtrl>("member_list", recurse);
  644. mAssignedRolesList = parent->getChild<LLScrollListCtrl>("member_assigned_roles", recurse);
  645. mAllowedActionsList = parent->getChild<LLScrollListCtrl>("member_allowed_actions", recurse);
  646. if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE;
  647. // We want to be notified whenever a member is selected.
  648. mMembersList->setCommitOnSelectionChange(TRUE);
  649. mMembersList->setCommitCallback(onMemberSelect, this);
  650. // Show the member's profile on double click.
  651. mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
  652. mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
  653. LLSD row;
  654. row["columns"][0]["column"] = "name";
  655. row["columns"][1]["column"] = "donated";
  656. row["columns"][2]["column"] = "online";
  657. mMembersList->addElement(row);
  658. std::string order_by = gSavedSettings.getString("GroupMembersSortOrder");
  659. if(!order_by.empty())
  660. {
  661. mMembersList->sortByColumn(order_by, TRUE);
  662. }
  663. LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
  664. if ( button )
  665. {
  666. button->setClickedCallback(onInviteMember, this);
  667. button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
  668. }
  669. mEjectBtn = parent->getChild<LLButton>("member_eject", recurse);
  670. if ( mEjectBtn )
  671. {
  672. mEjectBtn->setClickedCallback(onEjectMembers, this);
  673. mEjectBtn->setEnabled(FALSE);
  674. }
  675. return TRUE;
  676. }
  677. void LLPanelGroupMembersSubTab::setGroupID(const LLUUID& id)
  678. {
  679. //clear members list
  680. if(mMembersList) mMembersList->deleteAllItems();
  681. if(mAssignedRolesList) mAssignedRolesList->deleteAllItems();
  682. if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
  683. LLPanelGroupSubTab::setGroupID(id);
  684. }
  685. void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id)
  686. {
  687. if(mRolesList) mRolesList->deleteAllItems();
  688. if(mAssignedMembersList) mAssignedMembersList->deleteAllItems();
  689. if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
  690. if(mRoleName) mRoleName->clear();
  691. if(mRoleDescription) mRoleDescription->clear();
  692. if(mRoleTitle) mRoleTitle->clear();
  693. mHasRoleChange = FALSE;
  694. setFooterEnabled(FALSE);
  695. LLPanelGroupSubTab::setGroupID(id);
  696. }
  697. void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)
  698. {
  699. if(mActionList) mActionList->deleteAllItems();
  700. if(mActionRoles) mActionRoles->deleteAllItems();
  701. if(mActionMembers) mActionMembers->deleteAllItems();
  702. if(mActionDescription) mActionDescription->clear();
  703. LLPanelGroupSubTab::setGroupID(id);
  704. }
  705. // static
  706. void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
  707. {
  708. LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
  709. self->handleMemberSelect();
  710. }
  711. void LLPanelGroupMembersSubTab::handleMemberSelect()
  712. {
  713. lldebugs << "LLPanelGroupMembersSubTab::handleMemberSelect" << llendl;
  714. mAssignedRolesList->deleteAllItems();
  715. mAllowedActionsList->deleteAllItems();
  716. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  717. if (!gdatap)
  718. {
  719. llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() "
  720. << "-- No group data!" << llendl;
  721. return;
  722. }
  723. // Check if there is anything selected.
  724. std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
  725. if (selection.empty()) return;
  726. // Build a vector of all selected members, and gather allowed actions.
  727. uuid_vec_t selected_members;
  728. U64 allowed_by_all = 0xffffffffffffLL;
  729. U64 allowed_by_some = 0;
  730. std::vector<LLScrollListItem*>::iterator itor;
  731. for (itor = selection.begin();
  732. itor != selection.end(); ++itor)
  733. {
  734. LLUUID member_id = (*itor)->getUUID();
  735. selected_members.push_back( member_id );
  736. // Get this member's power mask including any unsaved changes
  737. U64 powers = getAgentPowersBasedOnRoleChanges( member_id );
  738. allowed_by_all &= powers;
  739. allowed_by_some |= powers;
  740. }
  741. std::sort(selected_members.begin(), selected_members.end());
  742. //////////////////////////////////
  743. // Build the allowed actions list.
  744. //////////////////////////////////
  745. buildActionsList(mAllowedActionsList,
  746. allowed_by_some,
  747. allowed_by_all,
  748. NULL,
  749. FALSE,
  750. FALSE,
  751. FALSE);
  752. //////////////////////////////////
  753. // Build the assigned roles list.
  754. //////////////////////////////////
  755. // Add each role to the assigned roles list.
  756. LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin();
  757. LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
  758. BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
  759. GP_MEMBER_EJECT);
  760. BOOL member_is_owner = FALSE;
  761. for( ; iter != end; ++iter)
  762. {
  763. // Count how many selected users are in this role.
  764. const LLUUID& role_id = iter->first;
  765. LLGroupRoleData* group_role_data = iter->second;
  766. if (group_role_data)
  767. {
  768. const BOOL needs_sort = FALSE;
  769. S32 count = group_role_data->getMembersInRole(
  770. selected_members, needs_sort);
  771. //check if the user has permissions to assign/remove
  772. //members to/from the role (but the ability to add/remove
  773. //should only be based on the "saved" changes to the role
  774. //not in the temp/meta data. -jwolk
  775. BOOL cb_enable = ( (count > 0) ?
  776. agentCanRemoveFromRole(mGroupID, role_id) :
  777. agentCanAddToRole(mGroupID, role_id) );
  778. // Owner role has special enabling permissions for removal.
  779. if (cb_enable && (count > 0) && role_id == gdatap->mOwnerRole)
  780. {
  781. // Check if any owners besides this agent are selected.
  782. uuid_vec_t::const_iterator member_iter;
  783. uuid_vec_t::const_iterator member_end =
  784. selected_members.end();
  785. for (member_iter = selected_members.begin();
  786. member_iter != member_end;
  787. ++member_iter)
  788. {
  789. // Don't count the agent.
  790. if ((*member_iter) == gAgent.getID()) continue;
  791. // Look up the member data.
  792. LLGroupMgrGroupData::member_list_t::iterator mi =
  793. gdatap->mMembers.find((*member_iter));
  794. if (mi == gdatap->mMembers.end()) continue;
  795. LLGroupMemberData* member_data = (*mi).second;
  796. // Is the member an owner?
  797. if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
  798. {
  799. // Can't remove other owners.
  800. cb_enable = FALSE;
  801. break;
  802. }
  803. }
  804. }
  805. //now see if there are any role changes for the selected
  806. //members and remember to include them
  807. uuid_vec_t::iterator sel_mem_iter = selected_members.begin();
  808. for (; sel_mem_iter != selected_members.end(); sel_mem_iter++)
  809. {
  810. LLRoleMemberChangeType type;
  811. if ( getRoleChangeType(*sel_mem_iter, role_id, type) )
  812. {
  813. if ( type == RMC_ADD ) count++;
  814. else if ( type == RMC_REMOVE ) count--;
  815. }
  816. }
  817. // If anyone selected is in any role besides 'Everyone' then they can't be ejected.
  818. if (role_id.notNull() && (count > 0))
  819. {
  820. can_eject_members = FALSE;
  821. if (role_id == gdatap->mOwnerRole)
  822. {
  823. member_is_owner = TRUE;
  824. }
  825. }
  826. LLRoleData rd;
  827. if (gdatap->getRoleData(role_id,rd))
  828. {
  829. std::ostringstream label;
  830. label << rd.mRoleName;
  831. // Don't bother showing a count, if there is only 0 or 1.
  832. if (count > 1)
  833. {
  834. label << ": " << count ;
  835. }
  836. LLSD row;
  837. row["id"] = role_id;
  838. row["columns"][0]["column"] = "checkbox";
  839. row["columns"][0]["type"] = "checkbox";
  840. row["columns"][1]["column"] = "role";
  841. row["columns"][1]["value"] = label.str();
  842. if (row["id"].asUUID().isNull())
  843. {
  844. // This is the everyone role, you can't take people out of the everyone role!
  845. row["enabled"] = false;
  846. }
  847. LLScrollListItem* item = mAssignedRolesList->addElement(row);
  848. // Extract the checkbox that was created.
  849. LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(0);
  850. LLCheckBoxCtrl* check = check_cell->getCheckBox();
  851. check->setCommitCallback(onRoleCheck, this);
  852. check->set( count > 0 );
  853. check->setTentative(
  854. (0 != count)
  855. && (selected_members.size() !=
  856. (uuid_vec_t::size_type)count));
  857. //NOTE: as of right now a user can break the group
  858. //by removing himself from a role if he is the
  859. //last owner. We should check for this special case
  860. // -jwolk
  861. check->setEnabled(cb_enable);
  862. item->setEnabled(cb_enable);
  863. }
  864. }
  865. else
  866. {
  867. // This could happen if changes are not synced right on sub-panel change.
  868. llwarns << "No group role data for " << iter->second << llendl;
  869. }
  870. }
  871. mAssignedRolesList->setEnabled(TRUE);
  872. if (gAgent.isGodlike())
  873. can_eject_members = TRUE;
  874. if (!can_eject_members && !member_is_owner)
  875. {
  876. // Maybe we can eject them because we are an owner...
  877. LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
  878. if (mi != gdatap->mMembers.end())
  879. {
  880. LLGroupMemberData* member_data = (*mi).second;
  881. if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
  882. {
  883. can_eject_members = TRUE;
  884. }
  885. }
  886. }
  887. mEjectBtn->setEnabled(can_eject_members);
  888. }
  889. // static
  890. void LLPanelGroupMembersSubTab::onMemberDoubleClick(void* user_data)
  891. {
  892. LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
  893. self->handleMemberDoubleClick();
  894. }
  895. //static
  896. void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
  897. {
  898. LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
  899. if ( selfp )
  900. {
  901. selfp->handleInviteMember();
  902. }
  903. }
  904. void LLPanelGroupMembersSubTab::handleInviteMember()
  905. {
  906. LLFloaterGroupInvite::showForGroup(mGroupID);
  907. }
  908. void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
  909. {
  910. LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
  911. if ( selfp )
  912. {
  913. selfp->handleEjectMembers();
  914. }
  915. }
  916. void LLPanelGroupMembersSubTab::handleEjectMembers()
  917. {
  918. //send down an eject message
  919. uuid_vec_t selected_members;
  920. std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
  921. if (selection.empty()) return;
  922. std::vector<LLScrollListItem*>::iterator itor;
  923. for (itor = selection.begin() ;
  924. itor != selection.end(); ++itor)
  925. {
  926. LLUUID member_id = (*itor)->getUUID();
  927. selected_members.push_back( member_id );
  928. }
  929. mMembersList->deleteSelectedItems();
  930. sendEjectNotifications(mGroupID, selected_members);
  931. LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID,
  932. selected_members);
  933. }
  934. void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
  935. {
  936. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
  937. if (group_data)
  938. {
  939. for (uuid_vec_t::const_iterator i = selected_members.begin(); i != selected_members.end(); ++i)
  940. {
  941. LLSD args;
  942. args["AVATAR_NAME"] = LLSLURL("agent", *i, "displayname").getSLURLString();
  943. args["GROUP_NAME"] = group_data->mName;
  944. LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
  945. }
  946. }
  947. }
  948. void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
  949. LLRoleMemberChangeType type)
  950. {
  951. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  952. if (!gdatap) return;
  953. //add that the user is requesting to change the roles for selected
  954. //members
  955. U64 powers_all_have = 0xffffffffffffLL;
  956. U64 powers_some_have = 0;
  957. BOOL is_owner_role = ( gdatap->mOwnerRole == role_id );
  958. LLUUID member_id;
  959. std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
  960. if (selection.empty())
  961. {
  962. return;
  963. }
  964. for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;
  965. itor != selection.end(); ++itor)
  966. {
  967. member_id = (*itor)->getUUID();
  968. //see if we requested a change for this member before
  969. if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() )
  970. {
  971. mMemberRoleChangeData[member_id] = new role_change_data_map_t;
  972. }
  973. role_change_data_map_t* role_change_datap = mMemberRoleChangeData[member_id];
  974. //now check to see if the selected group member
  975. //had changed his association with the selected role before
  976. role_change_data_map_t::iterator role = role_change_datap->find(role_id);
  977. if ( role != role_change_datap->end() )
  978. {
  979. //see if the new change type cancels out the previous change
  980. if (role->second != type)
  981. {
  982. role_change_datap->erase(role_id);
  983. if ( is_owner_role ) mNumOwnerAdditions--;
  984. }
  985. //else do nothing
  986. if ( role_change_datap->empty() )
  987. {
  988. //the current member now has no role changes
  989. //so erase the role change and erase the member's entry
  990. delete role_change_datap;
  991. role_change_datap = NULL;
  992. mMemberRoleChangeData.erase(member_id);
  993. }
  994. }
  995. else
  996. {
  997. //a previously unchanged role is being changed
  998. (*role_change_datap)[role_id] = type;
  999. if ( is_owner_role && type == RMC_ADD ) mNumOwnerAdditions++;
  1000. }
  1001. //we need to calculate what powers the selected members
  1002. //have (including the role changes we're making)
  1003. //so that we can rebuild the action list
  1004. U64 new_powers = getAgentPowersBasedOnRoleChanges(member_id);
  1005. powers_all_have &= new_powers;
  1006. powers_some_have |= new_powers;
  1007. }
  1008. mChanged = !mMemberRoleChangeData.empty();
  1009. notifyObservers();
  1010. //alrighty now we need to update the actions list
  1011. //to reflect the changes
  1012. mAllowedActionsList->deleteAllItems();
  1013. buildActionsList(mAllowedActionsList,
  1014. powers_some_have,
  1015. powers_all_have,
  1016. NULL,
  1017. FALSE,
  1018. FALSE,
  1019. FALSE);
  1020. }
  1021. // static
  1022. void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
  1023. {
  1024. LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
  1025. LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl);
  1026. if (!check_box || !self) return;
  1027. LLScrollListItem* first_selected =
  1028. self->mAssignedRolesList->getFirstSelected();
  1029. if (first_selected)
  1030. {
  1031. LLUUID role_id = first_selected->getUUID();
  1032. LLRoleMemberChangeType change_type = (check_box->get() ?
  1033. RMC_ADD :
  1034. RMC_REMOVE);
  1035. self->handleRoleCheck(role_id, change_type);
  1036. }
  1037. }
  1038. void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
  1039. {
  1040. LLScrollListItem* selected = mMembersList->getFirstSelected();
  1041. if (selected)
  1042. {
  1043. LLUUID member_id = selected->getUUID();
  1044. LLAvatarActions::showProfile( member_id );
  1045. }
  1046. }
  1047. void LLPanelGroupMembersSubTab::activate()
  1048. {
  1049. LLPanelGroupSubTab::activate();
  1050. if(!mActivated)
  1051. {
  1052. update(GC_ALL);
  1053. mActivated = true;
  1054. }
  1055. }
  1056. void LLPanelGroupMembersSubTab::deactivate()
  1057. {
  1058. LLPanelGroupSubTab::deactivate();
  1059. }
  1060. bool LLPanelGroupMembersSubTab::needsApply(std::string& mesg)
  1061. {
  1062. return mChanged;
  1063. }
  1064. void LLPanelGroupMembersSubTab::cancel()
  1065. {
  1066. if ( mChanged )
  1067. {
  1068. std::for_each(mMemberRoleChangeData.begin(),
  1069. mMemberRoleChangeData.end(),
  1070. DeletePairedPointer());
  1071. mMemberRoleChangeData.clear();
  1072. mChanged = FALSE;
  1073. notifyObservers();
  1074. }
  1075. }
  1076. bool LLPanelGroupMembersSubTab::apply(std::string& mesg)
  1077. {
  1078. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1079. if (!gdatap)
  1080. {
  1081. llwarns << "Unable to get group data for group " << mGroupID << llendl;
  1082. mesg.assign("Unable to save member data. Try again later.");
  1083. return false;
  1084. }
  1085. if (mChanged)
  1086. {
  1087. //figure out if we are somehow adding an owner or not and alert
  1088. //the user...possibly make it ignorable
  1089. if ( mNumOwnerAdditions > 0 )
  1090. {
  1091. LLRoleData rd;
  1092. LLSD args;
  1093. if ( gdatap->getRoleData(gdatap->mOwnerRole, rd) )
  1094. {
  1095. mHasModal = TRUE;
  1096. args["ROLE_NAME"] = rd.mRoleName;
  1097. LLNotificationsUtil::add("AddGroupOwnerWarning",
  1098. args,
  1099. LLSD(),
  1100. boost::bind(&LLPanelGroupMembersSubTab::addOwnerCB, this, _1, _2));
  1101. }
  1102. else
  1103. {
  1104. llwarns << "Unable to get role information for the owner role in group " << mGroupID << llendl;
  1105. mesg.assign("Unable to retried specific group information. Try again later");
  1106. return false;
  1107. }
  1108. }
  1109. else
  1110. {
  1111. applyMemberChanges();
  1112. }
  1113. }
  1114. return true;
  1115. }
  1116. bool LLPanelGroupMembersSubTab::addOwnerCB(const LLSD& notification, const LLSD& response)
  1117. {
  1118. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1119. mHasModal = FALSE;
  1120. if (0 == option)
  1121. {
  1122. // User clicked "Yes"
  1123. applyMemberChanges();
  1124. }
  1125. return false;
  1126. }
  1127. void LLPanelGroupMembersSubTab::applyMemberChanges()
  1128. {
  1129. //sucks to do a find again here, but it is in constant time, so, could
  1130. //be worse
  1131. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1132. if (!gdatap)
  1133. {
  1134. llwarns << "Unable to get group data for group " << mGroupID << llendl;
  1135. return;
  1136. }
  1137. //we need to add all of the changed roles data
  1138. //for each member whose role changed
  1139. for (member_role_changes_map_t::iterator member = mMemberRoleChangeData.begin();
  1140. member != mMemberRoleChangeData.end(); ++member)
  1141. {
  1142. for (role_change_data_map_t::iterator role = member->second->begin();
  1143. role != member->second->end(); ++role)
  1144. {
  1145. gdatap->changeRoleMember(role->first, //role_id
  1146. member->first, //member_id
  1147. role->second); //add/remove
  1148. }
  1149. member->second->clear();
  1150. delete member->second;
  1151. }
  1152. mMemberRoleChangeData.clear();
  1153. LLGroupMgr::getInstance()->sendGroupRoleMemberChanges(mGroupID);
  1154. //force a UI update
  1155. handleMemberSelect();
  1156. mChanged = FALSE;
  1157. mNumOwnerAdditions = 0;
  1158. notifyObservers();
  1159. }
  1160. bool LLPanelGroupMembersSubTab::matchesSearchFilter(const std::string& fullname)
  1161. {
  1162. // If the search filter is empty, everything passes.
  1163. if (mSearchFilter.empty()) return true;
  1164. // Create a full name, and compare it to the search filter.
  1165. std::string fullname_lc(fullname);
  1166. LLStringUtil::toLower(fullname_lc);
  1167. std::string::size_type match = fullname_lc.find(mSearchFilter);
  1168. if (std::string::npos == match)
  1169. {
  1170. // not found
  1171. return false;
  1172. }
  1173. else
  1174. {
  1175. return true;
  1176. }
  1177. }
  1178. U64 LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges(const LLUUID& agent_id)
  1179. {
  1180. //we loop over all of the changes
  1181. //if we are adding a role, then we simply add the role's powers
  1182. //if we are removing a role, we store that role id away
  1183. //and then we have to build the powers up bases on the roles the agent
  1184. //is in
  1185. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1186. if (!gdatap)
  1187. {
  1188. llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No group data!" << llendl;
  1189. return GP_NO_POWERS;
  1190. }
  1191. LLGroupMemberData* member_data = gdatap->mMembers[agent_id];
  1192. if ( !member_data )
  1193. {
  1194. llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No member data for member with UUID " << agent_id << llendl;
  1195. return GP_NO_POWERS;
  1196. }
  1197. //see if there are unsaved role changes for this agent
  1198. role_change_data_map_t* role_change_datap = NULL;
  1199. member_role_changes_map_t::iterator member = mMemberRoleChangeData.find(agent_id);
  1200. if ( member != mMemberRoleChangeData.end() )
  1201. {
  1202. //this member has unsaved role changes
  1203. //so grab them
  1204. role_change_datap = (*member).second;
  1205. }
  1206. U64 new_powers = GP_NO_POWERS;
  1207. if ( role_change_datap )
  1208. {
  1209. uuid_vec_t roles_to_be_removed;
  1210. for (role_change_data_map_t::iterator role = role_change_datap->begin();
  1211. role != role_change_datap->end(); ++ role)
  1212. {
  1213. if ( role->second == RMC_ADD )
  1214. {
  1215. new_powers |= gdatap->getRolePowers(role->first);
  1216. }
  1217. else
  1218. {
  1219. roles_to_be_removed.push_back(role->first);
  1220. }
  1221. }
  1222. //loop over the member's current roles, summing up
  1223. //the powers (not including the role we are removing)
  1224. for (LLGroupMemberData::role_list_t::iterator current_role = member_data->roleBegin();
  1225. current_role != member_data->roleEnd(); ++current_role)
  1226. {
  1227. bool role_in_remove_list =
  1228. (std::find(roles_to_be_removed.begin(),
  1229. roles_to_be_removed.end(),
  1230. current_role->second->getID()) !=
  1231. roles_to_be_removed.end());
  1232. if ( !role_in_remove_list )
  1233. {
  1234. new_powers |=
  1235. current_role->second->getRoleData().mRolePowers;
  1236. }
  1237. }
  1238. }
  1239. else
  1240. {
  1241. //there are no changes for this member
  1242. //the member's powers are just the ones stored in the group
  1243. //manager
  1244. new_powers = member_data->getAgentPowers();
  1245. }
  1246. return new_powers;
  1247. }
  1248. //If there is no change, returns false be sure to verify
  1249. //that there is a role change before attempting to get it or else
  1250. //the data will make no sense. Stores the role change type
  1251. bool LLPanelGroupMembersSubTab::getRoleChangeType(const LLUUID& member_id,
  1252. const LLUUID& role_id,
  1253. LLRoleMemberChangeType& type)
  1254. {
  1255. member_role_changes_map_t::iterator member_changes_iter = mMemberRoleChangeData.find(member_id);
  1256. if ( member_changes_iter != mMemberRoleChangeData.end() )
  1257. {
  1258. role_change_data_map_t::iterator role_changes_iter = member_changes_iter->second->find(role_id);
  1259. if ( role_changes_iter != member_changes_iter->second->end() )
  1260. {
  1261. type = role_changes_iter->second;
  1262. return true;
  1263. }
  1264. }
  1265. return false;
  1266. }
  1267. void LLPanelGroupMembersSubTab::draw()
  1268. {
  1269. LLPanelGroupSubTab::draw();
  1270. if (mPendingMemberUpdate)
  1271. {
  1272. updateMembers();
  1273. }
  1274. }
  1275. void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
  1276. {
  1277. if (mGroupID.isNull()) return;
  1278. if ( GC_TITLES == gc || GC_PROPERTIES == gc )
  1279. {
  1280. // Don't care about title or general group properties updates.
  1281. return;
  1282. }
  1283. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1284. if (!gdatap)
  1285. {
  1286. llwarns << "LLPanelGroupMembersSubTab::update() -- No group data!" << llendl;
  1287. return;
  1288. }
  1289. // Wait for both all data to be retrieved before displaying anything.
  1290. if ( gdatap->isMemberDataComplete()
  1291. && gdatap->isRoleDataComplete()
  1292. && gdatap->isRoleMemberDataComplete())
  1293. {
  1294. mMemberProgress = gdatap->mMembers.begin();
  1295. mPendingMemberUpdate = TRUE;
  1296. mHasMatch = FALSE;
  1297. // Generate unique ID for current updateMembers()- see onNameCache for details.
  1298. // Using unique UUID is perhaps an overkill but this way we are perfectly safe
  1299. // from coincidences.
  1300. mUdpateSessionID.generate();
  1301. }
  1302. else
  1303. {
  1304. // Build a string with info on retrieval progress.
  1305. std::ostringstream retrieved;
  1306. if ( !gdatap->isMemberDataComplete() )
  1307. {
  1308. // Still busy retreiving member list.
  1309. retrieved << "Retrieving member list (" << gdatap->mMembers.size()
  1310. << " / " << gdatap->mMemberCount << ")...";
  1311. }
  1312. else if( !gdatap->isRoleDataComplete() )
  1313. {
  1314. // Still busy retreiving role list.
  1315. retrieved << "Retrieving role list (" << gdatap->mRoles.size()
  1316. << " / " << gdatap->mRoleCount << ")...";
  1317. }
  1318. else // (!gdatap->isRoleMemberDataComplete())
  1319. {
  1320. // Still busy retreiving role/member mappings.
  1321. retrieved << "Retrieving role member mappings...";
  1322. }
  1323. mMembersList->setEnabled(FALSE);
  1324. mMembersList->setCommentText(retrieved.str());
  1325. }
  1326. }
  1327. void LLPanelGroupMembersSubTab::addMemberToList(LLUUID id, LLGroupMemberData* data)
  1328. {
  1329. if (!data) return;
  1330. LLUIString donated = getString("donation_area");
  1331. donated.setArg("[AREA]", llformat("%d", data->getContribution()));
  1332. LLSD row;
  1333. row["id"] = id;
  1334. row["columns"][0]["column"] = "name";
  1335. // value is filled in by name list control
  1336. row["columns"][1]["column"] = "donated";
  1337. row["columns"][1]["value"] = donated.getString();
  1338. row["columns"][2]["column"] = "online";
  1339. row["columns"][2]["value"] = data->getOnlineStatus();
  1340. row["columns"][2]["font"] = "SANSSERIF_SMALL";
  1341. mMembersList->addElement(row);
  1342. mHasMatch = TRUE;
  1343. }
  1344. void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUID& id)
  1345. {
  1346. // Update ID is used to determine whether member whose id is passed
  1347. // into onNameCache() was passed after current or previous user-initiated update.
  1348. // This is needed to avoid probable duplication of members in list after changing filter
  1349. // or adding of members of another group if gets for their names were called on
  1350. // previous update. If this id is from get() called from older update,
  1351. // we do nothing.
  1352. if (mUdpateSessionID != update_id) return;
  1353. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1354. if (!gdatap)
  1355. {
  1356. llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
  1357. return;
  1358. }
  1359. std::string fullname;
  1360. gCacheName->getFullName(id, fullname);
  1361. LLGroupMemberData* data;
  1362. // trying to avoid unnecessary hash lookups
  1363. if (matchesSearchFilter(fullname) && ((data = gdatap->mMembers[id]) != NULL))
  1364. {
  1365. addMemberToList(id, data);
  1366. if(!mMembersList->getEnabled())
  1367. {
  1368. mMembersList->setEnabled(TRUE);
  1369. }
  1370. }
  1371. }
  1372. void LLPanelGroupMembersSubTab::updateMembers()
  1373. {
  1374. mPendingMemberUpdate = FALSE;
  1375. // Rebuild the members list.
  1376. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1377. if (!gdatap)
  1378. {
  1379. llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
  1380. return;
  1381. }
  1382. // Make sure all data is still complete. Incomplete data
  1383. // may occur if we refresh.
  1384. if ( !gdatap->isMemberDataComplete()
  1385. || !gdatap->isRoleDataComplete()
  1386. || !gdatap->isRoleMemberDataComplete())
  1387. {
  1388. return;
  1389. }
  1390. //cleanup list only for first iretation
  1391. if(mMemberProgress == gdatap->mMembers.begin())
  1392. {
  1393. mMembersList->deleteAllItems();
  1394. }
  1395. LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
  1396. S32 i = 0;
  1397. for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
  1398. ++mMemberProgress, ++i)
  1399. {
  1400. if (!mMemberProgress->second)
  1401. continue;
  1402. // Do filtering on name if it is already in the cache.
  1403. std::string fullname;
  1404. if (gCacheName->getFullName(mMemberProgress->first, fullname))
  1405. {
  1406. if (matchesSearchFilter(fullname))
  1407. {
  1408. addMemberToList(mMemberProgress->first, mMemberProgress->second);
  1409. }
  1410. }
  1411. else
  1412. {
  1413. // If name is not cached, onNameCache() should be called when it is cached and add this member to list.
  1414. gCacheName->get(mMemberProgress->first, FALSE, boost::bind(&LLPanelGroupMembersSubTab::onNameCache,
  1415. this, mUdpateSessionID, _1));
  1416. }
  1417. }
  1418. if (mMemberProgress == end)
  1419. {
  1420. if (mHasMatch)
  1421. {
  1422. mMembersList->setEnabled(TRUE);
  1423. }
  1424. else
  1425. {
  1426. mMembersList->setEnabled(FALSE);
  1427. mMembersList->setCommentText(std::string("No match."));
  1428. }
  1429. }
  1430. else
  1431. {
  1432. mPendingMemberUpdate = TRUE;
  1433. }
  1434. // This should clear the other two lists, since nothing is selected.
  1435. handleMemberSelect();
  1436. }
  1437. ////////////////////////////
  1438. // LLPanelGroupRolesSubTab
  1439. ////////////////////////////
  1440. static LLRegisterPanelClassWrapper<LLPanelGroupRolesSubTab> t_panel_group_roles_subtab("panel_group_roles_subtab");
  1441. LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
  1442. : LLPanelGroupSubTab(),
  1443. mRolesList(NULL),
  1444. mAssignedMembersList(NULL),
  1445. mAllowedActionsList(NULL),
  1446. mRoleName(NULL),
  1447. mRoleTitle(NULL),
  1448. mRoleDescription(NULL),
  1449. mMemberVisibleCheck(NULL),
  1450. mDeleteRoleButton(NULL),
  1451. mCreateRoleButton(NULL),
  1452. mHasRoleChange(FALSE)
  1453. {
  1454. }
  1455. LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab()
  1456. {
  1457. }
  1458. BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
  1459. {
  1460. LLPanelGroupSubTab::postBuildSubTab(root);
  1461. // Upcast parent so we can ask it for sibling controls.
  1462. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
  1463. // Look recursively from the parent to find all our widgets.
  1464. bool recurse = true;
  1465. mHeader = parent->getChild<LLPanel>("roles_header", recurse);
  1466. mFooter = parent->getChild<LLPanel>("roles_footer", recurse);
  1467. mRolesList = parent->getChild<LLScrollListCtrl>("role_list", recurse);
  1468. mAssignedMembersList = parent->getChild<LLNameListCtrl>("role_assigned_members", recurse);
  1469. mAllowedActionsList = parent->getChild<LLScrollListCtrl>("role_allowed_actions", recurse);
  1470. mRoleName = parent->getChild<LLLineEditor>("role_name", recurse);
  1471. mRoleTitle = parent->getChild<LLLineEditor>("role_title", recurse);
  1472. mRoleDescription = parent->getChild<LLTextEditor>("role_description", recurse);
  1473. mMemberVisibleCheck = parent->getChild<LLCheckBoxCtrl>("role_visible_in_list", recurse);
  1474. if (!mRolesList || !mAssignedMembersList || !mAllowedActionsList
  1475. || !mRoleName || !mRoleTitle || !mRoleDescription || !mMemberVisibleCheck)
  1476. {
  1477. llwarns << "ARG! element not found." << llendl;
  1478. return FALSE;
  1479. }
  1480. mRemoveEveryoneTxt = getString("cant_delete_role");
  1481. mCreateRoleButton =
  1482. parent->getChild<LLButton>("role_create", recurse);
  1483. if ( mCreateRoleButton )
  1484. {
  1485. mCreateRoleButton->setClickedCallback(onCreateRole, this);
  1486. mCreateRoleButton->setEnabled(FALSE);
  1487. }
  1488. mDeleteRoleButton =
  1489. parent->getChild<LLButton>("role_delete", recurse);
  1490. if ( mDeleteRoleButton )
  1491. {
  1492. mDeleteRoleButton->setClickedCallback(onDeleteRole, this);
  1493. mDeleteRoleButton->setEnabled(FALSE);
  1494. }
  1495. mRolesList->setCommitOnSelectionChange(TRUE);
  1496. mRolesList->setCommitCallback(onRoleSelect, this);
  1497. mAssignedMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
  1498. mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange, this);
  1499. mAllowedActionsList->setCommitOnSelectionChange(TRUE);
  1500. mRoleName->setCommitOnFocusLost(TRUE);
  1501. mRoleName->setKeystrokeCallback(onPropertiesKey, this);
  1502. mRoleTitle->setCommitOnFocusLost(TRUE);
  1503. mRoleTitle->setKeystrokeCallback(onPropertiesKey, this);
  1504. mRoleDescription->setCommitOnFocusLost(TRUE);
  1505. mRoleDescription->setKeystrokeCallback(boost::bind(&LLPanelGroupRolesSubTab::onDescriptionKeyStroke, this, _1));
  1506. setFooterEnabled(FALSE);
  1507. return TRUE;
  1508. }
  1509. void LLPanelGroupRolesSubTab::activate()
  1510. {
  1511. LLPanelGroupSubTab::activate();
  1512. mRolesList->deselectAllItems();
  1513. mAssignedMembersList->deleteAllItems();
  1514. mAllowedActionsList->deleteAllItems();
  1515. mRoleName->clear();
  1516. mRoleDescription->clear();
  1517. mRoleTitle->clear();
  1518. setFooterEnabled(FALSE);
  1519. mHasRoleChange = FALSE;
  1520. update(GC_ALL);
  1521. }
  1522. void LLPanelGroupRolesSubTab::deactivate()
  1523. {
  1524. lldebugs << "LLPanelGroupRolesSubTab::deactivate()" << llendl;
  1525. LLPanelGroupSubTab::deactivate();
  1526. }
  1527. bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg)
  1528. {
  1529. lldebugs << "LLPanelGroupRolesSubTab::needsApply()" << llendl;
  1530. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1531. return (mHasRoleChange // Text changed in current role
  1532. || (gdatap && gdatap->pendingRoleChanges())); // Pending role changes in the group
  1533. }
  1534. bool LLPanelGroupRolesSubTab::apply(std::string& mesg)
  1535. {
  1536. lldebugs << "LLPanelGroupRolesSubTab::apply()" << llendl;
  1537. saveRoleChanges(true);
  1538. LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID);
  1539. notifyObservers();
  1540. return true;
  1541. }
  1542. void LLPanelGroupRolesSubTab::cancel()
  1543. {
  1544. mHasRoleChange = FALSE;
  1545. LLGroupMgr::getInstance()->cancelGroupRoleChanges(mGroupID);
  1546. notifyObservers();
  1547. }
  1548. LLSD LLPanelGroupRolesSubTab::createRoleItem(const LLUUID& role_id,
  1549. std::string name,
  1550. std::string title,
  1551. S32 members)
  1552. {
  1553. LLSD row;
  1554. row["id"] = role_id;
  1555. row["columns"][0]["column"] = "name";
  1556. row["columns"][0]["value"] = name;
  1557. row["columns"][1]["column"] = "title";
  1558. row["columns"][1]["value"] = title;
  1559. row["columns"][2]["column"] = "members";
  1560. row["columns"][2]["value"] = members;
  1561. return row;
  1562. }
  1563. bool LLPanelGroupRolesSubTab::matchesSearchFilter(std::string rolename, std::string roletitle)
  1564. {
  1565. // If the search filter is empty, everything passes.
  1566. if (mSearchFilter.empty()) return true;
  1567. LLStringUtil::toLower(rolename);
  1568. LLStringUtil::toLower(roletitle);
  1569. std::string::size_type match_name = rolename.find(mSearchFilter);
  1570. std::string::size_type match_title = roletitle.find(mSearchFilter);
  1571. if ( (std::string::npos == match_name)
  1572. && (std::string::npos == match_title))
  1573. {
  1574. // not found
  1575. return false;
  1576. }
  1577. else
  1578. {
  1579. return true;
  1580. }
  1581. }
  1582. void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
  1583. {
  1584. lldebugs << "LLPanelGroupRolesSubTab::update()" << llendl;
  1585. if (mGroupID.isNull()) return;
  1586. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1587. if (!gdatap || !gdatap->isRoleDataComplete())
  1588. {
  1589. LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
  1590. }
  1591. else
  1592. {
  1593. bool had_selection = false;
  1594. LLUUID last_selected;
  1595. if (mRolesList->getFirstSelected())
  1596. {
  1597. last_selected = mRolesList->getFirstSelected()->getUUID();
  1598. had_selection = true;
  1599. }
  1600. mRolesList->deleteAllItems();
  1601. LLScrollListItem* item = NULL;
  1602. LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
  1603. LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
  1604. for ( ; rit != end; ++rit)
  1605. {
  1606. LLRoleData rd;
  1607. if (gdatap->getRoleData((*rit).first,rd))
  1608. {
  1609. if (matchesSearchFilter(rd.mRoleName, rd.mRoleTitle))
  1610. {
  1611. // If this is the everyone role, then EVERYONE is in it.
  1612. S32 members_in_role = (*rit).first.isNull() ? gdatap->mMembers.size() : (*rit).second->getTotalMembersInRole();
  1613. LLSD row = createRoleItem((*rit).first,rd.mRoleName, rd.mRoleTitle, members_in_role);
  1614. item = mRolesList->addElement(row, ((*rit).first.isNull()) ? ADD_TOP : ADD_BOTTOM, this);
  1615. if (had_selection && ((*rit).first == last_selected))
  1616. {
  1617. item->setSelected(TRUE);
  1618. }
  1619. }
  1620. }
  1621. else
  1622. {
  1623. llwarns << "LLPanelGroupRolesSubTab::update() No role data for role " << (*rit).first << llendl;
  1624. }
  1625. }
  1626. mRolesList->sortByColumn(std::string("name"), TRUE);
  1627. if ( (gdatap->mRoles.size() < (U32)MAX_ROLES)
  1628. && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) )
  1629. {
  1630. mCreateRoleButton->setEnabled(TRUE);
  1631. }
  1632. else
  1633. {
  1634. mCreateRoleButton->setEnabled(FALSE);
  1635. }
  1636. if (had_selection)
  1637. {
  1638. handleRoleSelect();
  1639. }
  1640. else
  1641. {
  1642. mAssignedMembersList->deleteAllItems();
  1643. mAllowedActionsList->deleteAllItems();
  1644. mRoleName->clear();
  1645. mRoleDescription->clear();
  1646. mRoleTitle->clear();
  1647. setFooterEnabled(FALSE);
  1648. mDeleteRoleButton->setEnabled(FALSE);
  1649. }
  1650. }
  1651. if (!gdatap || !gdatap->isMemberDataComplete())
  1652. {
  1653. LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID);
  1654. }
  1655. if (!gdatap || !gdatap->isRoleMemberDataComplete())
  1656. {
  1657. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
  1658. }
  1659. if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
  1660. && gdatap
  1661. && gdatap->isMemberDataComplete()
  1662. && gdatap->isRoleMemberDataComplete())
  1663. {
  1664. buildMembersList();
  1665. }
  1666. }
  1667. // static
  1668. void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
  1669. {
  1670. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1671. self->handleRoleSelect();
  1672. }
  1673. void LLPanelGroupRolesSubTab::handleRoleSelect()
  1674. {
  1675. BOOL can_delete = TRUE;
  1676. lldebugs << "LLPanelGroupRolesSubTab::handleRoleSelect()" << llendl;
  1677. mAssignedMembersList->deleteAllItems();
  1678. mAllowedActionsList->deleteAllItems();
  1679. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1680. if (!gdatap)
  1681. {
  1682. llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
  1683. << "-- No group data!" << llendl;
  1684. return;
  1685. }
  1686. saveRoleChanges(false);
  1687. // Check if there is anything selected.
  1688. LLScrollListItem* item = mRolesList->getFirstSelected();
  1689. if (!item)
  1690. {
  1691. setFooterEnabled(FALSE);
  1692. return;
  1693. }
  1694. setFooterEnabled(TRUE);
  1695. LLRoleData rd;
  1696. if (gdatap->getRoleData(item->getUUID(),rd))
  1697. {
  1698. BOOL is_owner_role = ( gdatap->mOwnerRole == item->getUUID() );
  1699. mRoleName->setText(rd.mRoleName);
  1700. mRoleTitle->setText(rd.mRoleTitle);
  1701. mRoleDescription->setText(rd.mRoleDescription);
  1702. mAllowedActionsList->setEnabled(gAgent.hasPowerInGroup(mGroupID,
  1703. GP_ROLE_CHANGE_ACTIONS));
  1704. buildActionsList(mAllowedActionsList,
  1705. rd.mRolePowers,
  1706. 0LL,
  1707. boost::bind(&LLPanelGroupRolesSubTab::handleActionCheck, this, _1, false),
  1708. TRUE,
  1709. FALSE,
  1710. is_owner_role);
  1711. mMemberVisibleCheck->set((rd.mRolePowers & GP_MEMBER_VISIBLE_IN_DIR) == GP_MEMBER_VISIBLE_IN_DIR);
  1712. mRoleName->setEnabled(!is_owner_role &&
  1713. gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
  1714. mRoleTitle->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
  1715. mRoleDescription->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
  1716. if ( is_owner_role )
  1717. {
  1718. // you can't delete the owner role
  1719. can_delete = FALSE;
  1720. // ... or hide members with this role
  1721. mMemberVisibleCheck->setEnabled(FALSE);
  1722. }
  1723. else
  1724. {
  1725. mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
  1726. }
  1727. if (item->getUUID().isNull())
  1728. {
  1729. // Everyone role, can't edit description or name or delete
  1730. mRoleDescription->setEnabled(FALSE);
  1731. mRoleName->setEnabled(FALSE);
  1732. can_delete = FALSE;
  1733. }
  1734. }
  1735. else
  1736. {
  1737. mRolesList->deselectAllItems();
  1738. mAssignedMembersList->deleteAllItems();
  1739. mAllowedActionsList->deleteAllItems();
  1740. mRoleName->clear();
  1741. mRoleDescription->clear();
  1742. mRoleTitle->clear();
  1743. setFooterEnabled(FALSE);
  1744. can_delete = FALSE;
  1745. }
  1746. mSelectedRole = item->getUUID();
  1747. buildMembersList();
  1748. can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
  1749. GP_ROLE_DELETE);
  1750. mDeleteRoleButton->setEnabled(can_delete);
  1751. }
  1752. void LLPanelGroupRolesSubTab::buildMembersList()
  1753. {
  1754. mAssignedMembersList->deleteAllItems();
  1755. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1756. if (!gdatap)
  1757. {
  1758. llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
  1759. << "-- No group data!" << llendl;
  1760. return;
  1761. }
  1762. // Check if there is anything selected.
  1763. LLScrollListItem* item = mRolesList->getFirstSelected();
  1764. if (!item) return;
  1765. if (item->getUUID().isNull())
  1766. {
  1767. // Special cased 'Everyone' role
  1768. LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.begin();
  1769. LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
  1770. for ( ; mit != end; ++mit)
  1771. {
  1772. mAssignedMembersList->addNameItem((*mit).first);
  1773. }
  1774. }
  1775. else
  1776. {
  1777. LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.find(item->getUUID());
  1778. if (rit != gdatap->mRoles.end())
  1779. {
  1780. LLGroupRoleData* rdatap = (*rit).second;
  1781. if (rdatap)
  1782. {
  1783. uuid_vec_t::const_iterator mit = rdatap->getMembersBegin();
  1784. uuid_vec_t::const_iterator end = rdatap->getMembersEnd();
  1785. for ( ; mit != end; ++mit)
  1786. {
  1787. mAssignedMembersList->addNameItem((*mit));
  1788. }
  1789. }
  1790. }
  1791. }
  1792. }
  1793. struct ActionCBData
  1794. {
  1795. LLPanelGroupRolesSubTab* mSelf;
  1796. LLCheckBoxCtrl* mCheck;
  1797. };
  1798. void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
  1799. {
  1800. LLCheckBoxCtrl* check = dynamic_cast<LLCheckBoxCtrl*>(ctrl);
  1801. if (!check)
  1802. return;
  1803. lldebugs << "LLPanelGroupRolesSubTab::handleActionSelect()" << llendl;
  1804. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1805. if (!gdatap)
  1806. {
  1807. llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
  1808. << "-- No group data!" << llendl;
  1809. return;
  1810. }
  1811. LLScrollListItem* action_item = mAllowedActionsList->getFirstSelected();
  1812. if (!action_item)
  1813. {
  1814. return;
  1815. }
  1816. LLScrollListItem* role_item = mRolesList->getFirstSelected();
  1817. if (!role_item)
  1818. {
  1819. return;
  1820. }
  1821. LLUUID role_id = role_item->getUUID();
  1822. LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
  1823. U64 power = rap->mPowerBit;
  1824. if (check->get())
  1825. {
  1826. if (!force && ( (GP_ROLE_ASSIGN_MEMBER == power)
  1827. || (GP_ROLE_CHANGE_ACTIONS == power) ))
  1828. {
  1829. // Uncheck the item, for now. It will be
  1830. // checked if they click 'Yes', below.
  1831. check->set(FALSE);
  1832. LLRoleData rd;
  1833. LLSD args;
  1834. if ( gdatap->getRoleData(role_id, rd) )
  1835. {
  1836. args["ACTION_NAME"] = rap->mDescription;
  1837. args["ROLE_NAME"] = rd.mRoleName;
  1838. mHasModal = TRUE;
  1839. std::string warning = "AssignDangerousActionWarning";
  1840. if (GP_ROLE_CHANGE_ACTIONS == power)
  1841. {
  1842. warning = "AssignDangerousAbilityWarning";
  1843. }
  1844. LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
  1845. }
  1846. else
  1847. {
  1848. llwarns << "Unable to look up role information for role id: "
  1849. << role_id << llendl;
  1850. }
  1851. }
  1852. else
  1853. {
  1854. gdatap->addRolePower(role_id,power);
  1855. }
  1856. }
  1857. else
  1858. {
  1859. gdatap->removeRolePower(role_id,power);
  1860. }
  1861. mHasRoleChange = TRUE;
  1862. notifyObservers();
  1863. }
  1864. bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check)
  1865. {
  1866. if (!check) return false;
  1867. mHasModal = FALSE;
  1868. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1869. if (0 == option)
  1870. {
  1871. // User clicked "Yes"
  1872. check->set(TRUE);
  1873. const bool force_add = true;
  1874. handleActionCheck(check, force_add);
  1875. }
  1876. return false;
  1877. }
  1878. // static
  1879. void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
  1880. {
  1881. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1882. if (!self) return;
  1883. self->mHasRoleChange = TRUE;
  1884. self->notifyObservers();
  1885. }
  1886. void LLPanelGroupRolesSubTab::onDescriptionKeyStroke(LLTextEditor* caller)
  1887. {
  1888. mHasRoleChange = TRUE;
  1889. notifyObservers();
  1890. }
  1891. // static
  1892. void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data)
  1893. {
  1894. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1895. if (!self) return;
  1896. self->mHasRoleChange = TRUE;
  1897. self->notifyObservers();
  1898. }
  1899. // static
  1900. void LLPanelGroupRolesSubTab::onMemberVisibilityChange(LLUICtrl* ctrl, void* user_data)
  1901. {
  1902. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1903. LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
  1904. if (!check || !self) return;
  1905. self->handleMemberVisibilityChange(check->get());
  1906. }
  1907. void LLPanelGroupRolesSubTab::handleMemberVisibilityChange(bool value)
  1908. {
  1909. lldebugs << "LLPanelGroupRolesSubTab::handleMemberVisibilityChange()" << llendl;
  1910. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1911. if (!gdatap)
  1912. {
  1913. llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
  1914. << "-- No group data!" << llendl;
  1915. return;
  1916. }
  1917. LLScrollListItem* role_item = mRolesList->getFirstSelected();
  1918. if (!role_item)
  1919. {
  1920. return;
  1921. }
  1922. if (value)
  1923. {
  1924. gdatap->addRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
  1925. }
  1926. else
  1927. {
  1928. gdatap->removeRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
  1929. }
  1930. }
  1931. // static
  1932. void LLPanelGroupRolesSubTab::onCreateRole(void* user_data)
  1933. {
  1934. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1935. if (!self) return;
  1936. self->handleCreateRole();
  1937. }
  1938. void LLPanelGroupRolesSubTab::handleCreateRole()
  1939. {
  1940. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1941. if (!gdatap) return;
  1942. LLUUID new_role_id;
  1943. new_role_id.generate();
  1944. LLRoleData rd;
  1945. rd.mRoleName = "New Role";
  1946. gdatap->createRole(new_role_id,rd);
  1947. mRolesList->deselectAllItems(TRUE);
  1948. LLSD row;
  1949. row["id"] = new_role_id;
  1950. row["columns"][0]["column"] = "name";
  1951. row["columns"][0]["value"] = rd.mRoleName;
  1952. mRolesList->addElement(row, ADD_BOTTOM, this);
  1953. mRolesList->selectByID(new_role_id);
  1954. // put focus on name field and select its contents
  1955. if(mRoleName)
  1956. {
  1957. mRoleName->setFocus(TRUE);
  1958. mRoleName->onTabInto();
  1959. gFocusMgr.triggerFocusFlash();
  1960. }
  1961. notifyObservers();
  1962. }
  1963. // static
  1964. void LLPanelGroupRolesSubTab::onDeleteRole(void* user_data)
  1965. {
  1966. LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
  1967. if (!self) return;
  1968. self->handleDeleteRole();
  1969. }
  1970. void LLPanelGroupRolesSubTab::handleDeleteRole()
  1971. {
  1972. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1973. if (!gdatap) return;
  1974. LLScrollListItem* role_item = mRolesList->getFirstSelected();
  1975. if (!role_item)
  1976. {
  1977. return;
  1978. }
  1979. if (role_item->getUUID().isNull() || role_item->getUUID() == gdatap->mOwnerRole)
  1980. {
  1981. LLSD args;
  1982. args["MESSAGE"] = mRemoveEveryoneTxt;
  1983. LLNotificationsUtil::add("GenericAlert", args);
  1984. return;
  1985. }
  1986. gdatap->deleteRole(role_item->getUUID());
  1987. mRolesList->deleteSingleItem(mRolesList->getFirstSelectedIndex());
  1988. mRolesList->selectFirstItem();
  1989. notifyObservers();
  1990. }
  1991. void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role)
  1992. {
  1993. LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
  1994. if (!gdatap) return;
  1995. if (mHasRoleChange)
  1996. {
  1997. LLRoleData rd;
  1998. if (!gdatap->getRoleData(mSelectedRole,rd)) return;
  1999. rd.mRoleName = mRoleName->getText();
  2000. rd.mRoleDescription = mRoleDescription->getText();
  2001. rd.mRoleTitle = mRoleTitle->getText();
  2002. S32 role_members_count = 0;
  2003. if (mSelectedRole.isNull())
  2004. {
  2005. role_members_count = gdatap->mMemberCount;
  2006. }
  2007. else if(LLGroupRoleData* grd = get_ptr_in_map(gdatap->mRoles, mSelectedRole))
  2008. {
  2009. role_members_count = grd->getTotalMembersInRole();
  2010. }
  2011. gdatap->setRoleData(mSelectedRole,rd);
  2012. mRolesList->deleteSingleItem(mRolesList->getItemIndex(mSelectedRole));
  2013. LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,role_members_count);
  2014. LLScrollListItem* item = mRolesList->addElement(row, ADD_BOTTOM, this);
  2015. item->setSelected(select_saved_role);
  2016. mHasRoleChange = FALSE;
  2017. }
  2018. }
  2019. ////////////////////////////
  2020. // LLPanelGroupActionsSubTab
  2021. ////////////////////////////
  2022. static LLRegisterPanelClassWrapper<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
  2023. LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab()
  2024. : LLPanelGroupSubTab()
  2025. {
  2026. }
  2027. LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab()
  2028. {
  2029. }
  2030. BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
  2031. {
  2032. LLPanelGroupSubTab::postBuildSubTab(root);
  2033. // Upcast parent so we can ask it for sibling controls.
  2034. LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
  2035. // Look recursively from the parent to find all our widgets.
  2036. bool recurse = true;
  2037. mHeader = parent->getChild<LLPanel>("actions_header", recurse);
  2038. mFooter = parent->getChild<LLPanel>("actions_footer", recurse);
  2039. mActionDescription = parent->getChild<LLTextEditor>("action_description", recurse);
  2040. mActionList = parent->getChild<LLScrollListCtrl>("action_list",recurse);
  2041. mActionRoles = parent->getChild<LLScrollListCtrl>("action_roles",recurse);
  2042. mActionMembers = parent->getChild<LLNameListCtrl>("action_members",recurse);
  2043. if (!mActionList || !mActionDescription || !mActionRoles || !mActionMembers) return FALSE;
  2044. mActionList->setCommitOnSelectionChange(TRUE);
  2045. mActionList->setCommitCallback(boost::bind(&LLPanelGroupActionsSubTab::handleActionSelect, this));
  2046. mActionList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
  2047. update(GC_ALL);
  2048. return TRUE;
  2049. }
  2050. void LLPanelGroupActionsSubTab::activate()
  2051. {
  2052. LLPanelGroupSubTab::activate();
  2053. update(GC_ALL);
  2054. }
  2055. void LLPanelGroupActionsSubTab::deactivate()
  2056. {
  2057. lldebugs << "LLPanelGroupActionsSubTab::deactivate()" << llendl;
  2058. LLPanelGroupSubTab::deactivate();
  2059. }
  2060. bool LLPanelGroupActionsSubTab::needsApply(std::string& mesg)