llpanelgrouproles.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llcheckboxctrl.h"
00035 
00036 #include "llagent.h"
00037 #include "llbutton.h"
00038 #include "llfloateravatarinfo.h"
00039 #include "llfloatergroupinvite.h"
00040 #include "lliconctrl.h"
00041 #include "lllineeditor.h"
00042 #include "llnamelistctrl.h"
00043 #include "llnotify.h"
00044 #include "llpanelgrouproles.h"
00045 #include "llscrolllistctrl.h"
00046 #include "lltabcontainer.h"
00047 #include "lltextbox.h"
00048 #include "lltexteditor.h"
00049 #include "llviewerimagelist.h"
00050 #include "llviewerwindow.h"
00051 #include "llfocusmgr.h"
00052 
00053 #include "roles_constants.h"
00054 
00055 bool agentCanRemoveFromRole(const LLUUID& group_id,
00056                                                         const LLUUID& role_id)
00057 {
00058         return gAgent.hasPowerInGroup(group_id, GP_ROLE_REMOVE_MEMBER);
00059 }
00060 
00061 bool agentCanAddToRole(const LLUUID& group_id,
00062                                            const LLUUID& role_id)
00063 {
00064         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
00065         if (!gdatap) 
00066         {
00067                 llwarns << "agentCanAddToRole "
00068                                 << "-- No group data!" << llendl;
00069                 return false;
00070         }
00071 
00072         //make sure the agent is in the group
00073         LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
00074         if (mi == gdatap->mMembers.end())
00075         {
00076                 return false;
00077         }
00078         
00079         LLGroupMemberData* member_data = (*mi).second;
00080 
00081         // Owners can add to any role.
00082         if ( member_data->isInRole(gdatap->mOwnerRole) )
00083         {
00084                 return true;
00085         }
00086 
00087         // 'Limited assign members' can add to roles the user is in.
00088         if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER_LIMITED) &&
00089                         member_data->isInRole(role_id) )
00090         {
00091                 return true;
00092         }
00093 
00094         // 'assign members' can add to non-owner roles.
00095         if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER) &&
00096                          role_id != gdatap->mOwnerRole )
00097         {
00098                 return true;
00099         }
00100 
00101         return false;
00102 }
00103 
00104 // static
00105 void* LLPanelGroupRoles::createTab(void* data)
00106 {
00107         LLUUID* group_id = static_cast<LLUUID*>(data);
00108         return new LLPanelGroupRoles("panel group roles", *group_id);
00109 }
00110 
00111 LLPanelGroupRoles::LLPanelGroupRoles(const std::string& name, const LLUUID& group_id)
00112 :       LLPanelGroupTab(name, group_id),
00113         mCurrentTab(NULL),
00114         mRequestedTab( NULL ),
00115         mSubTabContainer( NULL ),
00116         mFirstUse( TRUE ),
00117         mIgnoreTransition( FALSE )
00118 {
00119 }
00120 
00121 LLPanelGroupRoles::~LLPanelGroupRoles()
00122 {
00123         int i;
00124         for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
00125         {
00126                 LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
00127 
00128                 subtabp->removeObserver(this);
00129         }
00130 }
00131 
00132 BOOL LLPanelGroupRoles::postBuild()
00133 {
00134         lldebugs << "LLPanelGroupRoles::postBuild()" << llendl;
00135 
00136         mSubTabContainer = getChild<LLTabContainer>("roles_tab_container");
00137 
00138         if (!mSubTabContainer) return FALSE;
00139 
00140         // Hook up each sub-tabs callback and widgets.
00141         S32 i;
00142         for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
00143         {
00144                 LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
00145 
00146                 // Add click callbacks to all the tabs.
00147                 mSubTabContainer->setTabChangeCallback(subtabp, onClickSubTab);
00148                 mSubTabContainer->setTabUserData(subtabp, this);
00149 
00150                 // Hand the subtab a pointer to this LLPanelGroupRoles, so that it can
00151                 // look around for the widgets it is interested in.
00152                 if (!subtabp->postBuildSubTab(this)) return FALSE;
00153 
00154                 subtabp->addObserver(this);
00155         }
00156 
00157         // Set the current tab to whatever is currently being shown.
00158         mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00159         if (!mCurrentTab)
00160         {
00161                 // Need to select a tab.
00162                 mSubTabContainer->selectFirstTab();
00163                 mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00164         }
00165 
00166         if (!mCurrentTab) return FALSE;
00167 
00168         // Act as though this tab was just activated.
00169         mCurrentTab->activate();
00170 
00171         // Read apply text from the xml file.
00172         mDefaultNeedsApplyMesg = getString("default_needs_apply_text");
00173         mWantApplyMesg = getString("want_apply_text");
00174 
00175         return LLPanelGroupTab::postBuild();
00176 }
00177 
00178 BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp)
00179 {
00180         if (agentp->isGodlike())
00181                 return TRUE;
00182         
00183         /* This power was removed to make group roles simpler
00184         return agentp->hasPowerInGroup(mGroupID, 
00185                                                                    GP_ROLE_CREATE |
00186                                                                    GP_ROLE_DELETE |
00187                                                                    GP_ROLE_PROPERTIES |
00188                                                                    GP_ROLE_VIEW |
00189                                                                    GP_ROLE_ASSIGN_MEMBER |
00190                                                                    GP_ROLE_REMOVE_MEMBER |
00191                                                                    GP_ROLE_CHANGE_ACTIONS |
00192                                                                    GP_MEMBER_INVITE |
00193                                                                    GP_MEMBER_EJECT |
00194                                                                    GP_MEMBER_OPTIONS );
00195         */
00196         return mAllowEdit && agentp->isInGroup(mGroupID);
00197                                                                    
00198 }
00199 
00200 // static
00201 void LLPanelGroupRoles::onClickSubTab(void* user_data, bool from_click)
00202 {
00203         LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
00204         self->handleClickSubTab();
00205 }
00206 
00207 void LLPanelGroupRoles::handleClickSubTab()
00208 {
00209         // If we are already handling a transition,
00210         // ignore this.
00211         if (mIgnoreTransition)
00212         {
00213                 return;
00214         }
00215 
00216         mRequestedTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00217 
00218         // Make sure they aren't just clicking the same tab...
00219         if (mRequestedTab == mCurrentTab)
00220         {
00221                 return;
00222         }
00223 
00224         // Try to switch from the current panel to the panel the user selected.
00225         attemptTransition();
00226 }
00227 
00228 BOOL LLPanelGroupRoles::attemptTransition()
00229 {
00230         // Check if the current tab needs to be applied.
00231         LLString mesg;
00232         if (mCurrentTab && mCurrentTab->needsApply(mesg))
00233         {
00234                 // If no message was provided, give a generic one.
00235                 if (mesg.empty())
00236                 {
00237                         mesg = mDefaultNeedsApplyMesg;
00238                 }
00239                 // Create a notify box, telling the user about the unapplied tab.
00240                 LLString::format_map_t args;
00241                 args["[NEEDS_APPLY_MESSAGE]"] = mesg;
00242                 args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
00243                 gViewerWindow->alertXml("PanelGroupApply", args,
00244                                                                 onNotifyCallback, (void*) this);
00245                 mHasModal = TRUE;
00246                 // We need to reselect the current tab, since it isn't finished.
00247                 if (mSubTabContainer)
00248                 {
00249                         mIgnoreTransition = TRUE;
00250                         mSubTabContainer->selectTabPanel( mCurrentTab );
00251                         mIgnoreTransition = FALSE;
00252                 }
00253                 // Returning FALSE will block a close action from finishing until
00254                 // we get a response back from the user.
00255                 return FALSE;
00256         }
00257         else
00258         {
00259                 // The current panel didn't have anything it needed to apply.
00260                 if (mRequestedTab)
00261                 {
00262                         transitionToTab();
00263                 }
00264                 return TRUE;
00265         }
00266 }
00267 
00268 void LLPanelGroupRoles::transitionToTab()
00269 {
00270         // Tell the current panel that it is being deactivated.
00271         if (mCurrentTab)
00272         {
00273                 mCurrentTab->deactivate();
00274         }
00275         
00276         // Tell the new panel that it is being activated.
00277         if (mRequestedTab)
00278         {
00279                 // This is now the current tab;
00280                 mCurrentTab = mRequestedTab;
00281                 mCurrentTab->activate();
00282         }
00283 }
00284 
00285 // static
00286 void LLPanelGroupRoles::onNotifyCallback(S32 option, void* user_data)
00287 {
00288         LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
00289         if (self)
00290         {
00291                 self->handleNotifyCallback(option);
00292         }
00293 }
00294 
00295 void LLPanelGroupRoles::handleNotifyCallback(S32 option)
00296 {
00297         mHasModal = FALSE;
00298         switch (option)
00299         {
00300         case 0: // "Apply Changes"
00301         {
00302                 // Try to apply changes, and switch to the requested tab.
00303                 LLString apply_mesg;
00304                 if ( !apply( apply_mesg ) )
00305                 {
00306                         // There was a problem doing the apply.
00307                         if ( !apply_mesg.empty() )
00308                         {
00309                                 mHasModal = TRUE;
00310                                 LLString::format_map_t args;
00311                                 args["[MESSAGE]"] = apply_mesg;
00312                                 gViewerWindow->alertXml("GenericAlert", args, onModalClose, (void*) this);
00313                         }
00314                         // Skip switching tabs.
00315                         break;
00316                 }
00317 
00318                 // This panel's info successfully applied.
00319                 // Switch to the next panel.
00320                 // No break!  Continue into 'Ignore Changes' which just switches tabs.
00321                 mIgnoreTransition = TRUE;
00322                 mSubTabContainer->selectTabPanel( mRequestedTab );
00323                 mIgnoreTransition = FALSE;
00324                 transitionToTab();
00325                 break;
00326         }
00327         case 1: // "Ignore Changes"
00328                 // Switch to the requested panel without applying changes
00329                 cancel();
00330                 mIgnoreTransition = TRUE;
00331                 mSubTabContainer->selectTabPanel( mRequestedTab );
00332                 mIgnoreTransition = FALSE;
00333                 transitionToTab();
00334                 break;
00335         case 2: // "Cancel"
00336         default:
00337                 // Do nothing.  The user is canceling the action.
00338                 break;
00339         }
00340 }
00341 
00342 // static
00343 void LLPanelGroupRoles::onModalClose(S32 option, void* user_data)
00344 {
00345         LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
00346         if (self)
00347         {
00348                 self->mHasModal = FALSE;
00349         }
00350 }
00351 
00352 
00353 bool LLPanelGroupRoles::apply(LLString& mesg)
00354 {
00355         // Pass this along to the currently visible sub tab.
00356         if (!mSubTabContainer) return false;
00357 
00358         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00359         if (!panelp) return false;
00360         
00361         // Ignore the needs apply message.
00362         LLString ignore_mesg;
00363         if ( !panelp->needsApply(ignore_mesg) )
00364         {
00365                 // We don't need to apply anything.
00366                 // We're done.
00367                 return true;
00368         }
00369 
00370         // Try to do the actual apply.
00371         return panelp->apply(mesg);
00372 }
00373 
00374 void LLPanelGroupRoles::cancel()
00375 {
00376         // Pass this along to the currently visible sub tab.
00377         if (!mSubTabContainer) return;
00378 
00379         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00380         if (!panelp) return;
00381 
00382         panelp->cancel();
00383 }
00384 
00385 // Pass all of these messages to the currently visible sub tab.
00386 LLString LLPanelGroupRoles::getHelpText() const
00387 {
00388         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00389         if (panelp)
00390         {
00391                 return panelp->getHelpText();
00392         }
00393         else
00394         {
00395                 return mHelpText;
00396         }
00397 }
00398 
00399 void LLPanelGroupRoles::update(LLGroupChange gc)
00400 {
00401         if (mGroupID.isNull()) return;
00402 
00403         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00404         if (panelp)
00405         {
00406                 panelp->update(gc);
00407         }
00408         else
00409         {
00410                 llwarns << "LLPanelGroupRoles::update() -- No subtab to update!" << llendl;
00411         }
00412 }
00413 
00414 void LLPanelGroupRoles::activate()
00415 {
00416         // Start requesting member and role data if needed.
00417         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
00418         //if (!gdatap || mFirstUse)
00419         {
00420                 // Check member data.
00421                 
00422                 if (!gdatap || !gdatap->isMemberDataComplete() )
00423                 {
00424                         LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID);
00425                 }
00426 
00427                 // Check role data.
00428                 if (!gdatap || !gdatap->isRoleDataComplete() )
00429                 {
00430                         // Mildly hackish - clear all pending changes
00431                         cancel();
00432 
00433                         LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
00434                 }
00435 
00436                 // Check role-member mapping data.
00437                 if (!gdatap || !gdatap->isRoleMemberDataComplete() )
00438                 {
00439                         LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
00440                 }
00441 
00442                 // Need this to get base group member powers
00443                 if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
00444                 {
00445                         LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
00446                 }
00447 
00448                 mFirstUse = FALSE;
00449         }
00450 
00451         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00452         if (panelp) panelp->activate();
00453 }
00454 
00455 void LLPanelGroupRoles::deactivate()
00456 {
00457         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00458         if (panelp) panelp->deactivate();
00459 }
00460 
00461 bool LLPanelGroupRoles::needsApply(LLString& mesg)
00462 {
00463         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00464         if (!panelp) return false;
00465                 
00466         return panelp->needsApply(mesg);
00467 }
00468 
00469 BOOL LLPanelGroupRoles::hasModal()
00470 {
00471         if (mHasModal) return TRUE;
00472 
00473         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
00474         if (!panelp) return FALSE;
00475                 
00476         return panelp->hasModal();
00477 }
00478 
00479 // PanelGroupTab observer trigger
00480 void LLPanelGroupRoles::tabChanged()
00481 {
00482         notifyObservers();
00483 }
00484 
00486 // LLPanelGroupSubTab
00488 LLPanelGroupSubTab::LLPanelGroupSubTab(const std::string& name, const LLUUID& group_id)
00489 :       LLPanelGroupTab(name, group_id),
00490         mHeader(NULL),
00491         mFooter(NULL),
00492         mSearchLineEditor(NULL),
00493         mSearchButton(NULL),
00494         mShowAllButton(NULL)
00495 {
00496 }
00497 
00498 LLPanelGroupSubTab::~LLPanelGroupSubTab()
00499 {
00500 }
00501 
00502 BOOL LLPanelGroupSubTab::postBuild()
00503 {
00504         // Hook up the search widgets.
00505         bool recurse = true;
00506         mSearchLineEditor = getChild<LLLineEditor>("search_text", recurse);
00507 
00508         if (!mSearchLineEditor) return FALSE;
00509         mSearchLineEditor->setKeystrokeCallback(onSearchKeystroke);
00510         mSearchLineEditor->setCallbackUserData(this);
00511 
00512         mSearchButton = getChild<LLButton>("search_button", recurse);
00513 
00514         if (!mSearchButton) return FALSE;
00515         mSearchButton->setClickedCallback(onClickSearch);
00516         mSearchButton->setCallbackUserData(this);
00517         mSearchButton->setEnabled(FALSE);
00518 
00519         mShowAllButton = getChild<LLButton>("show_all_button", recurse);
00520 
00521         if (!mShowAllButton) return FALSE;
00522         mShowAllButton->setClickedCallback(onClickShowAll);
00523         mShowAllButton->setCallbackUserData(this);
00524         mShowAllButton->setEnabled(FALSE);
00525         
00526         // Get icons for later use.
00527         mActionIcons.clear();
00528 
00529         bool no_recurse = false;
00530 
00531         LLIconCtrl* icon = getChild<LLIconCtrl>("power_folder_icon",no_recurse);
00532         if (icon && !icon->getImageName().empty())
00533         {
00534                 mActionIcons["folder"] = icon->getImageName();
00535                 removeChild(icon, TRUE);
00536         }
00537 
00538         icon = getChild<LLIconCtrl>("power_all_have_icon",no_recurse);
00539         if (icon && !icon->getImageName().empty())
00540         {
00541                 mActionIcons["full"] = icon->getImageName();
00542                 removeChild(icon, TRUE);
00543         }
00544 
00545         icon = getChild<LLIconCtrl>("power_partial_icon",no_recurse);
00546         if (icon && !icon->getImageName().empty())
00547         {
00548                 mActionIcons["partial"] = icon->getImageName();
00549                 removeChild(icon, TRUE);
00550         }
00551 
00552         return LLPanelGroupTab::postBuild();
00553 }
00554 
00555 // static
00556 void LLPanelGroupSubTab::onSearchKeystroke(LLLineEditor* caller, void* user_data)
00557 {
00558         LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
00559         self->handleSearchKeystroke(caller);
00560 }
00561 
00562 void LLPanelGroupSubTab::handleSearchKeystroke(LLLineEditor* caller)
00563 {
00564         if (caller->getText().size())
00565         {
00566                 setDefaultBtn( mSearchButton );
00567                 mSearchButton->setEnabled(TRUE);
00568         }
00569         else
00570         {
00571                 setDefaultBtn( NULL );
00572                 mSearchButton->setEnabled(FALSE);
00573         }
00574 }
00575 
00576 // static 
00577 void LLPanelGroupSubTab::onClickSearch(void* user_data)
00578 {
00579         LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
00580         self->handleClickSearch();
00581 }
00582  
00583 void LLPanelGroupSubTab::handleClickSearch()
00584 {
00585         lldebugs << "LLPanelGroupSubTab::handleClickSearch()" << llendl;
00586 
00587         if (0 == mSearchLineEditor->getText().size())
00588         {
00589                 // No search text.  (This shouldn't happen... the search button should have been disabled).
00590                 llwarns << "handleClickSearch with no search text!" << llendl;
00591                 mSearchButton->setEnabled(FALSE);
00592                 return;
00593         }
00594 
00595         setSearchFilter( mSearchLineEditor->getText() );
00596         mShowAllButton->setEnabled(TRUE);
00597 }
00598 
00599 // static
00600 void LLPanelGroupSubTab::onClickShowAll(void* user_data)
00601 {
00602         LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
00603         self->handleClickShowAll();
00604 }
00605 
00606 void LLPanelGroupSubTab::handleClickShowAll()
00607 {
00608         lldebugs << "LLPanelGroupSubTab::handleClickShowAll()" << llendl;
00609         setSearchFilter( LLString::null );
00610         mShowAllButton->setEnabled(FALSE);
00611 }
00612 
00613 void LLPanelGroupSubTab::setSearchFilter(const LLString& filter)
00614 {
00615         lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
00616         mSearchFilter = filter;
00617         LLString::toLower(mSearchFilter);
00618         update(GC_ALL);
00619 }
00620 
00621 void LLPanelGroupSubTab::activate()
00622 {
00623         lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
00624         setOthersVisible(TRUE);
00625 }
00626 
00627 void LLPanelGroupSubTab::deactivate()
00628 {
00629         lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
00630         setOthersVisible(FALSE);
00631 }
00632 
00633 void LLPanelGroupSubTab::setOthersVisible(BOOL b)
00634 {
00635         if (mHeader)
00636         {
00637                 mHeader->setVisible( b );
00638         }
00639         else
00640         {
00641                 llwarns << "LLPanelGroupSubTab missing header!" << llendl;
00642         }
00643 
00644         if (mFooter)
00645         {
00646                 mFooter->setVisible( b );
00647         }
00648         else
00649         {
00650                 llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
00651         }
00652 }
00653 
00654 bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
00655 {
00656         // If the search filter is empty, everything passes.
00657         if (mSearchFilter.empty()) return true;
00658 
00659         LLString::toLower(action);
00660         std::string::size_type match = action.find(mSearchFilter);
00661 
00662         if (std::string::npos == match)
00663         {
00664                 // not found
00665                 return false;
00666         }
00667         else
00668         {
00669                 return true;
00670         }
00671 }
00672 
00673 void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl, 
00674                                                                                   U64 allowed_by_some, 
00675                                                                                   U64 allowed_by_all,
00676                                                                                   icon_map_t& icons,
00677                                                                                   void (*commit_callback)(LLUICtrl*,void*),
00678                                                                                   BOOL show_all,
00679                                                                                   BOOL filter,
00680                                                                                   BOOL is_owner_role)
00681 {
00682         if (LLGroupMgr::getInstance()->mRoleActionSets.empty())
00683         {
00684                 llwarns << "Can't build action list - no actions found." << llendl;
00685                 return;
00686         }
00687 
00688         std::vector<LLRoleActionSet*>::iterator ras_it = LLGroupMgr::getInstance()->mRoleActionSets.begin();
00689         std::vector<LLRoleActionSet*>::iterator ras_end = LLGroupMgr::getInstance()->mRoleActionSets.end();
00690 
00691         for ( ; ras_it != ras_end; ++ras_it)
00692         {
00693                 buildActionCategory(ctrl,
00694                                                         allowed_by_some,
00695                                                         allowed_by_all,
00696                                                         (*ras_it),
00697                                                         icons, 
00698                                                         commit_callback,
00699                                                         show_all,
00700                                                         filter,
00701                                                         is_owner_role);
00702         }
00703 }
00704 
00705 void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
00706                                                                                          U64 allowed_by_some,
00707                                                                                          U64 allowed_by_all,
00708                                                                                          LLRoleActionSet* action_set,
00709                                                                                          icon_map_t& icons,
00710                                                                                          void (*commit_callback)(LLUICtrl*,void*),
00711                                                                                          BOOL show_all,
00712                                                                                          BOOL filter,
00713                                                                                          BOOL is_owner_role)
00714 {
00715         lldebugs << "Building role list for: " << action_set->mActionSetData->mName << llendl;
00716         // See if the allow mask matches anything in this category.
00717         if (show_all || (allowed_by_some & action_set->mActionSetData->mPowerBit))
00718         {
00719                 // List all the actions in this category that at least some members have.
00720                 LLSD row;
00721 
00722                 row["columns"][0]["column"] = "icon";
00723                 icon_map_t::iterator iter = icons.find("folder");
00724                 if (iter != icons.end())
00725                 {
00726                         row["columns"][0]["type"] = "icon";
00727                         row["columns"][0]["value"] = (*iter).second;
00728                 }
00729 
00730                 row["columns"][1]["column"] = "action";
00731                 row["columns"][1]["value"] = action_set->mActionSetData->mName;
00732                 row["columns"][1]["font-style"] = "BOLD";
00733 
00734                 LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
00735 
00736                 bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
00737 
00738                 std::vector<LLRoleAction*>::iterator ra_it = action_set->mActions.begin();
00739                 std::vector<LLRoleAction*>::iterator ra_end = action_set->mActions.end();
00740 
00741                 bool items_match_filter = false;
00742                 BOOL can_change_actions = (!is_owner_role && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CHANGE_ACTIONS));
00743 
00744                 for ( ; ra_it != ra_end; ++ra_it)
00745                 {
00746                         // See if anyone has these action.
00747                         if (!show_all && !(allowed_by_some & (*ra_it)->mPowerBit))
00748                         {
00749                                 continue;
00750                         }
00751 
00752                         // See if we are filtering out these actions
00753                         // If we aren't using filters, category_matches_filter will be true.
00754                         if (!category_matches_filter
00755                                 && !matchesActionSearchFilter((*ra_it)->mDescription))
00756                         {
00757                                 continue;                                                                               
00758                         }
00759 
00760                         items_match_filter = true;
00761 
00762                         // See if everyone has these actions.
00763                         bool show_full_strength = false;
00764                         if ( (allowed_by_some & (*ra_it)->mPowerBit) == (allowed_by_all & (*ra_it)->mPowerBit) )
00765                         {
00766                                 show_full_strength = true;
00767                         }
00768 
00769                         LLSD row;
00770 
00771                         S32 column_index = 0;
00772                         row["columns"][column_index]["column"] = "icon";
00773                         ++column_index;
00774 
00775                         
00776                         S32 check_box_index = -1;
00777                         if (commit_callback)
00778                         {
00779                                 row["columns"][column_index]["column"] = "checkbox";
00780                                 row["columns"][column_index]["type"] = "checkbox";
00781                                 check_box_index = column_index;
00782                                 ++column_index;
00783                         }
00784                         else
00785                         {
00786                                 if (show_full_strength)
00787                                 {
00788                                         icon_map_t::iterator iter = icons.find("full");
00789                                         if (iter != icons.end())
00790                                         {
00791                                                 row["columns"][column_index]["column"] = "checkbox";
00792                                                 row["columns"][column_index]["type"] = "icon";
00793                                                 row["columns"][column_index]["value"] = (*iter).second;
00794                                                 ++column_index;
00795                                         }
00796                                 }
00797                                 else
00798                                 {
00799                                         icon_map_t::iterator iter = icons.find("partial");
00800                                         if (iter != icons.end())
00801                                         {
00802                                                 row["columns"][column_index]["column"] = "checkbox";
00803                                                 row["columns"][column_index]["type"] = "icon";
00804                                                 row["columns"][column_index]["value"] = (*iter).second;
00805                                                 ++column_index;
00806                                         }
00807                                         row["enabled"] = false;
00808                                 }
00809                         }
00810 
00811                         row["columns"][column_index]["column"] = "action";
00812                         row["columns"][column_index]["value"] = (*ra_it)->mDescription;
00813                         row["columns"][column_index]["font"] = "SANSSERIFSMALL";
00814 
00815                         LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
00816 
00817                         if (-1 != check_box_index)
00818                         {
00819                                 // Extract the checkbox that was created.
00820                                 LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(check_box_index);
00821                                 LLCheckBoxCtrl* check = check_cell->getCheckBox();
00822                                 check->setEnabled(can_change_actions);
00823                                 check->setCommitCallback(commit_callback);
00824                                 check->setCallbackUserData(ctrl->getCallbackUserData());
00825                                 check->setToolTip( check->getLabel() );
00826 
00827                                 if (show_all)
00828                                 {
00829                                         check->setTentative(FALSE);
00830                                         if (allowed_by_some & (*ra_it)->mPowerBit)
00831                                         {
00832                                                 check->set(TRUE);
00833                                         }
00834                                         else
00835                                         {
00836                                                 check->set(FALSE);
00837                                         }
00838                                 }
00839                                 else
00840                                 {
00841                                         check->set(TRUE);
00842                                         if (show_full_strength)
00843                                         {
00844                                                 check->setTentative(FALSE);
00845                                         }
00846                                         else
00847                                         {
00848                                                 check->setTentative(TRUE);
00849                                         }
00850                                 }
00851                         }
00852                 }
00853 
00854                 if (!items_match_filter)
00855                 {
00856                         S32 title_index = ctrl->getItemIndex(title_row);
00857                         ctrl->deleteSingleItem(title_index);
00858                 }
00859         }
00860 }
00861 
00862 void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
00863 {
00864         if (mFooter)
00865         {
00866                 mFooter->setAllChildrenEnabled(enable);
00867         }
00868 }
00869 
00871 // LLPanelGroupMembersSubTab
00873 
00874 // static
00875 void* LLPanelGroupMembersSubTab::createTab(void* data)
00876 {
00877         LLUUID* group_id = static_cast<LLUUID*>(data);
00878         return new LLPanelGroupMembersSubTab("panel group members sub tab", *group_id);
00879 }
00880 
00881 LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab(const std::string& name, const LLUUID& group_id)
00882 :       LLPanelGroupSubTab(name, group_id),
00883         mMembersList(NULL),
00884         mAssignedRolesList(NULL),
00885         mAllowedActionsList(NULL),
00886         mChanged(FALSE),
00887         mPendingMemberUpdate(FALSE),
00888         mHasMatch(FALSE),
00889         mNumOwnerAdditions(0)
00890 {
00891 }
00892 
00893 LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
00894 {
00895 }
00896 
00897 BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
00898 {
00899         // Upcast parent so we can ask it for sibling controls.
00900         LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
00901 
00902         // Look recursively from the parent to find all our widgets.
00903         bool recurse = true;
00904         mHeader = parent->getChild<LLPanel>("members_header", recurse);
00905         mFooter = parent->getChild<LLPanel>("members_footer", recurse);
00906 
00907         mMembersList            = parent->getChild<LLNameListCtrl>("member_list", recurse);
00908         mAssignedRolesList      = parent->getChild<LLScrollListCtrl>("member_assigned_roles", recurse);
00909         mAllowedActionsList     = parent->getChild<LLScrollListCtrl>("member_allowed_actions", recurse);
00910 
00911         if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE;
00912 
00913         // We want to be notified whenever a member is selected.
00914         mMembersList->setCallbackUserData(this);
00915         mMembersList->setCommitOnSelectionChange(TRUE);
00916         mMembersList->setCommitCallback(onMemberSelect);
00917         // Show the member's profile on double click.
00918         mMembersList->setDoubleClickCallback(onMemberDoubleClick);
00919 
00920         LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
00921         if ( button )
00922         {
00923                 button->setClickedCallback(onInviteMember);
00924                 button->setCallbackUserData(this);
00925                 button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
00926         }
00927 
00928         mEjectBtn = parent->getChild<LLButton>("member_eject", recurse);
00929         if ( mEjectBtn )
00930         {
00931                 mEjectBtn->setClickedCallback(onEjectMembers);
00932                 mEjectBtn->setCallbackUserData(this);
00933                 mEjectBtn->setEnabled(FALSE);
00934         }
00935 
00936         return TRUE;
00937 }
00938 
00939 
00940 // static
00941 void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
00942 {
00943         LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
00944         self->handleMemberSelect();
00945 }
00946 
00947 void LLPanelGroupMembersSubTab::handleMemberSelect()
00948 {
00949         lldebugs << "LLPanelGroupMembersSubTab::handleMemberSelect" << llendl;
00950 
00951         mAssignedRolesList->deleteAllItems();
00952         mAllowedActionsList->deleteAllItems();
00953         
00954         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
00955         if (!gdatap) 
00956         {
00957                 llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() "
00958                                 << "-- No group data!" << llendl;
00959                 return;
00960         }
00961 
00962         // Check if there is anything selected.
00963         std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
00964         if (selection.empty()) return;
00965 
00966         // Build a vector of all selected members, and gather allowed actions.
00967         std::vector<LLUUID> selected_members;
00968         U64 allowed_by_all = 0xffffffffffffLL;
00969         U64 allowed_by_some = 0;
00970 
00971         std::vector<LLScrollListItem*>::iterator itor;
00972         for (itor = selection.begin();
00973                  itor != selection.end(); ++itor)
00974         {
00975                 selected_members.push_back( (*itor)->getUUID() );
00976                 // Get this member's power mask including any unsaved changes
00977 
00978                 U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
00979 
00980                 allowed_by_all &= powers;
00981                 allowed_by_some |= powers;
00982         }
00983         std::sort(selected_members.begin(), selected_members.end());
00984 
00986         // Build the allowed actions list.
00988         buildActionsList(mAllowedActionsList,
00989                                          allowed_by_some,
00990                                          allowed_by_all,
00991                                          mActionIcons,
00992                                          NULL,
00993                                          FALSE,
00994                                          FALSE,
00995                                          FALSE);
00996 
00998         // Build the assigned roles list.
01000         // Add each role to the assigned roles list.
01001         LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin();
01002         LLGroupMgrGroupData::role_list_t::iterator end  = gdatap->mRoles.end();
01003 
01004         BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
01005                                                                                                         GP_MEMBER_EJECT);
01006         BOOL member_is_owner = FALSE;
01007         
01008         for( ; iter != end; ++iter)
01009         {
01010                 // Count how many selected users are in this role.
01011                 const LLUUID& role_id = iter->first;
01012                 LLGroupRoleData* group_role_data = iter->second;
01013 
01014                 if (group_role_data)
01015                 {
01016                         const BOOL needs_sort = FALSE;
01017                         S32 count = group_role_data->getMembersInRole(
01018                                                                                         selected_members, needs_sort);
01019                         //check if the user has permissions to assign/remove
01020                         //members to/from the role (but the ability to add/remove
01021                         //should only be based on the "saved" changes to the role
01022                         //not in the temp/meta data. -jwolk
01023                         BOOL cb_enable = ( (count > 0) ?
01024                                                            agentCanRemoveFromRole(mGroupID, role_id) :
01025                                                            agentCanAddToRole(mGroupID, role_id) );
01026 
01027 
01028                         // Owner role has special enabling permissions for removal.
01029                         if (cb_enable && (count > 0) && role_id == gdatap->mOwnerRole)
01030                         {
01031                                 // Check if any owners besides this agent are selected.
01032                                 std::vector<LLUUID>::const_iterator member_iter;
01033                                 std::vector<LLUUID>::const_iterator member_end =
01034                                                                                                 selected_members.end();
01035                                 for (member_iter = selected_members.begin();
01036                                          member_iter != member_end;     
01037                                          ++member_iter)
01038                                 {
01039                                         // Don't count the agent.
01040                                         if ((*member_iter) == gAgent.getID()) continue;
01041                                         
01042                                         // Look up the member data.
01043                                         LLGroupMgrGroupData::member_list_t::iterator mi = 
01044                                                                         gdatap->mMembers.find((*member_iter));
01045                                         if (mi == gdatap->mMembers.end()) continue;
01046                                         LLGroupMemberData* member_data = (*mi).second;
01047                                         // Is the member an owner?
01048                                         if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
01049                                         {
01050                                                 // Can't remove other owners.
01051                                                 cb_enable = FALSE;
01052                                                 break;
01053                                         }
01054                                 }
01055                         }
01056 
01057                         //now see if there are any role changes for the selected
01058                         //members and remember to include them
01059                         std::vector<LLUUID>::iterator sel_mem_iter = selected_members.begin();
01060                         for (; sel_mem_iter != selected_members.end(); sel_mem_iter++)
01061                         {
01062                                 LLRoleMemberChangeType type;
01063                                 if ( getRoleChangeType(*sel_mem_iter, role_id, type) )
01064                                 {
01065                                         if ( type == RMC_ADD ) count++;
01066                                         else if ( type == RMC_REMOVE ) count--;
01067                                 }
01068                         }
01069                         
01070                         // If anyone selected is in any role besides 'Everyone' then they can't be ejected.
01071                         if (role_id.notNull() && (count > 0))
01072                         {
01073                                 can_eject_members = FALSE;
01074                                 if (role_id == gdatap->mOwnerRole)
01075                                 {
01076                                         member_is_owner = TRUE;
01077                                 }
01078                         }
01079 
01080                         LLRoleData rd;
01081                         if (gdatap->getRoleData(role_id,rd))
01082                         {
01083                                 std::ostringstream label;
01084                                 label << rd.mRoleName;
01085                                 // Don't bother showing a count, if there is only 0 or 1.
01086                                 if (count > 1)
01087                                 {
01088                                         label << ": " << count ;
01089                                 }
01090         
01091                                 LLSD row;
01092                                 row["id"] = role_id;
01093 
01094                                 row["columns"][0]["column"] = "checkbox";
01095                                 row["columns"][0]["type"] = "checkbox";
01096 
01097                                 row["columns"][1]["column"] = "role";
01098                                 row["columns"][1]["value"] = label.str();
01099 
01100                                 if (row["id"].asUUID().isNull())
01101                                 {
01102                                         // This is the everyone role, you can't take people out of the everyone role!
01103                                         row["enabled"] = false;
01104                                 }
01105 
01106                                 LLScrollListItem* item = mAssignedRolesList->addElement(row);
01107 
01108                                 // Extract the checkbox that was created.
01109                                 LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(0);
01110                                 LLCheckBoxCtrl* check = check_cell->getCheckBox();
01111                                 check->setCommitCallback(onRoleCheck);
01112                                 check->setCallbackUserData(this);
01113                                 check->set( count > 0 );
01114                                 check->setTentative(
01115                                         (0 != count)
01116                                         && (selected_members.size() !=
01117                                                 (std::vector<LLUUID>::size_type)count));
01118 
01119                                 //NOTE: as of right now a user can break the group
01120                                 //by removing himself from a role if he is the
01121                                 //last owner.  We should check for this special case
01122                                 // -jwolk
01123                                 check->setEnabled(cb_enable);
01124                         }
01125                 }
01126                 else
01127                 {
01128                         // This could happen if changes are not synced right on sub-panel change.
01129                         llwarns << "No group role data for " << iter->second << llendl;
01130                 }
01131         }
01132         mAssignedRolesList->setEnabled(TRUE);
01133 
01134         if (!can_eject_members && !member_is_owner)
01135         {
01136                 // Maybe we can eject them because we are an owner...
01137                 LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
01138                 if (mi != gdatap->mMembers.end())
01139                 {
01140                         LLGroupMemberData* member_data = (*mi).second;
01141 
01142                         if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
01143                         {
01144                                 can_eject_members = TRUE;
01145                         }
01146                 }
01147         }
01148 
01149         mEjectBtn->setEnabled(can_eject_members);
01150 }
01151 
01152 // static
01153 void LLPanelGroupMembersSubTab::onMemberDoubleClick(void* user_data)
01154 {
01155         LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
01156         self->handleMemberDoubleClick();
01157 }
01158 
01159 //static
01160 void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
01161 {
01162         LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
01163 
01164         if ( selfp )
01165         {
01166                 selfp->handleInviteMember();
01167         }
01168 }
01169 
01170 void LLPanelGroupMembersSubTab::handleInviteMember()
01171 {
01172         LLFloaterGroupInvite::showForGroup(mGroupID);
01173 }
01174 
01175 void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
01176 {
01177         LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
01178 
01179         if ( selfp )
01180         {
01181                 selfp->handleEjectMembers();
01182         }
01183 }
01184 
01185 void LLPanelGroupMembersSubTab::handleEjectMembers()
01186 {
01187         //send down an eject message
01188         std::vector<LLUUID> selected_members;
01189 
01190         std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
01191         if (selection.empty()) return;
01192 
01193         std::vector<LLScrollListItem*>::iterator itor;
01194         for (itor = selection.begin() ; 
01195                  itor != selection.end(); ++itor)
01196         {
01197                 selected_members.push_back((*itor)->getUUID());
01198         }
01199 
01200         mMembersList->deleteSelectedItems();
01201 
01202         LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID,
01203                                                                          selected_members);
01204 }
01205 
01206 void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
01207                                                                                                 LLRoleMemberChangeType type)
01208 {
01209         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01210         if (!gdatap) return;
01211 
01212         //add that the user is requesting to change the roles for selected
01213         //members
01214         U64 powers_all_have  = 0xffffffffffffLL;
01215         U64 powers_some_have = 0;
01216 
01217         BOOL   is_owner_role = ( gdatap->mOwnerRole == role_id );
01218         LLUUID member_id;
01219         
01220 
01221         std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
01222         if (selection.empty())
01223         {
01224                 return;
01225         }
01226         
01227         for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ; 
01228                  itor != selection.end(); ++itor)
01229         {
01230                 member_id = (*itor)->getUUID();
01231 
01232                 //see if we requested a change for this member before
01233                 if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() )
01234                 {
01235                         mMemberRoleChangeData[member_id] = new role_change_data_map_t;
01236                 }
01237                 role_change_data_map_t* role_change_datap = mMemberRoleChangeData[member_id];
01238 
01239                 //now check to see if the selected group member
01240                 //had changed his association with the selected role before
01241 
01242                 role_change_data_map_t::iterator  role = role_change_datap->find(role_id);
01243                 if ( role != role_change_datap->end() )
01244                 {
01245                         //see if the new change type cancels out the previous change
01246                         if (role->second != type)
01247                         {
01248                                 role_change_datap->erase(role_id);
01249                                 if ( is_owner_role ) mNumOwnerAdditions--;
01250                         }
01251                         //else do nothing
01252 
01253                         if ( role_change_datap->empty() )
01254                         {
01255                                 //the current member now has no role changes
01256                                 //so erase the role change and erase the member's entry
01257                                 delete role_change_datap;
01258                 role_change_datap = NULL;
01259 
01260                                 mMemberRoleChangeData.erase(member_id);
01261                         }
01262                 }
01263                 else
01264                 {
01265                         //a previously unchanged role is being changed
01266                         (*role_change_datap)[role_id] = type;
01267                         if ( is_owner_role && type == RMC_ADD ) mNumOwnerAdditions++;
01268                 }
01269 
01270                 //we need to calculate what powers the selected members
01271                 //have (including the role changes we're making)
01272                 //so that we can rebuild the action list
01273                 U64 new_powers = getAgentPowersBasedOnRoleChanges(member_id);
01274 
01275                 powers_all_have  &= new_powers;
01276                 powers_some_have |= new_powers;
01277         }
01278 
01279         
01280         mChanged = !mMemberRoleChangeData.empty();
01281         notifyObservers();
01282 
01283         //alrighty now we need to update the actions list
01284         //to reflect the changes
01285         mAllowedActionsList->deleteAllItems();
01286         buildActionsList(mAllowedActionsList,
01287                                          powers_some_have,
01288                                          powers_all_have,
01289                                          mActionIcons,
01290                                          NULL,
01291                                          FALSE,
01292                                          FALSE,
01293                                          FALSE);
01294 }
01295 
01296 
01297 // static 
01298 void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
01299 {
01300         LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
01301         LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl);
01302         if (!check_box || !self) return;
01303 
01304         LLScrollListItem* first_selected =
01305                 self->mAssignedRolesList->getFirstSelected();
01306         if (first_selected)
01307         {
01308                 LLUUID role_id = first_selected->getUUID();
01309                 LLRoleMemberChangeType change_type = (check_box->get() ? 
01310                                                       RMC_ADD : 
01311                                                       RMC_REMOVE);
01312                 
01313                 self->handleRoleCheck(role_id, change_type);
01314         }
01315 }
01316 
01317 void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
01318 {
01319         LLScrollListItem* selected = mMembersList->getFirstSelected();
01320         if (selected)
01321         {
01322                 LLFloaterAvatarInfo::showFromDirectory( selected->getUUID() );
01323         }
01324 }
01325 
01326 void LLPanelGroupMembersSubTab::activate()
01327 {
01328         LLPanelGroupSubTab::activate();
01329 
01330         update(GC_ALL);
01331 }
01332 
01333 void LLPanelGroupMembersSubTab::deactivate()
01334 {
01335         LLPanelGroupSubTab::deactivate();
01336 }
01337 
01338 bool LLPanelGroupMembersSubTab::needsApply(LLString& mesg)
01339 {
01340         return mChanged;
01341 }
01342 
01343 void LLPanelGroupMembersSubTab::cancel()
01344 {
01345         if ( mChanged )
01346         {
01347                 std::for_each(mMemberRoleChangeData.begin(),
01348                                           mMemberRoleChangeData.end(),
01349                                           DeletePairedPointer());
01350                 mMemberRoleChangeData.clear();
01351 
01352                 mChanged = FALSE;
01353                 notifyObservers();
01354         }
01355 }
01356 
01357 bool LLPanelGroupMembersSubTab::apply(LLString& mesg)
01358 {
01359         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01360         if (!gdatap)
01361         {
01362                 llwarns << "Unable to get group data for group " << mGroupID << llendl;
01363 
01364                 mesg.assign("Unable to save member data.  Try again later.");
01365                 return false;
01366         }
01367 
01368         if (mChanged)
01369         {
01370                 //figure out if we are somehow adding an owner or not and alert
01371                 //the user...possibly make it ignorable
01372                 if ( mNumOwnerAdditions > 0 )
01373                 {
01374                         LLRoleData rd;
01375                         LLStringBase<char>::format_map_t args;
01376 
01377                         if ( gdatap->getRoleData(gdatap->mOwnerRole, rd) )
01378                         {
01379                                 mHasModal = TRUE;
01380                                 args["[ROLE_NAME]"] = rd.mRoleName;
01381                                 gViewerWindow->alertXml("AddGroupOwnerWarning",
01382                                                                                 args,
01383                                                                                 addOwnerCB,
01384                                                                                 this);
01385                         }
01386                         else
01387                         {
01388                                 llwarns << "Unable to get role information for the owner role in group " << mGroupID << llendl;
01389 
01390                                 mesg.assign("Unable to retried specific group information.  Try again later");
01391                                 return false;
01392                         }
01393                                  
01394                 }
01395                 else
01396                 {
01397                         applyMemberChanges();
01398                 }
01399         }
01400 
01401         return true;
01402 }
01403 
01404 //static
01405 void LLPanelGroupMembersSubTab::addOwnerCB(S32 option, void* data)
01406 {
01407         LLPanelGroupMembersSubTab* self = (LLPanelGroupMembersSubTab*) data;
01408 
01409         if (!self) return;
01410         
01411         self->mHasModal = FALSE;
01412 
01413         if (0 == option)
01414         {
01415                 // User clicked "Yes"
01416                 self->applyMemberChanges();
01417         }
01418 }
01419 
01420 void LLPanelGroupMembersSubTab::applyMemberChanges()
01421 {
01422         //sucks to do a find again here, but it is in constant time, so, could
01423         //be worse
01424         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01425         if (!gdatap)
01426         {
01427                 llwarns << "Unable to get group data for group " << mGroupID << llendl;
01428                 return;
01429         }
01430 
01431         //we need to add all of the changed roles data
01432         //for each member whose role changed
01433         for (member_role_changes_map_t::iterator member = mMemberRoleChangeData.begin();
01434                  member != mMemberRoleChangeData.end(); ++member)
01435         {
01436                 for (role_change_data_map_t::iterator role = member->second->begin();
01437                          role != member->second->end(); ++role)
01438                 {
01439                         gdatap->changeRoleMember(role->first, //role_id
01440                                                                          member->first, //member_id
01441                                                                          role->second); //add/remove
01442                 }
01443 
01444                 member->second->clear();
01445                 delete member->second;
01446         }
01447         mMemberRoleChangeData.clear();
01448 
01449         LLGroupMgr::getInstance()->sendGroupRoleMemberChanges(mGroupID);        
01450         //force a UI update
01451         handleMemberSelect();
01452 
01453         mChanged = FALSE;
01454         mNumOwnerAdditions = 0;
01455         notifyObservers();
01456 }
01457 
01458 bool LLPanelGroupMembersSubTab::matchesSearchFilter(const std::string& fullname)
01459 {
01460         // If the search filter is empty, everything passes.
01461         if (mSearchFilter.empty()) return true;
01462 
01463         // Create a full name, and compare it to the search filter.
01464         std::string fullname_lc(fullname);
01465         LLString::toLower(fullname_lc);
01466 
01467         std::string::size_type match = fullname_lc.find(mSearchFilter);
01468 
01469         if (std::string::npos == match)
01470         {
01471                 // not found
01472                 return false;
01473         }
01474         else
01475         {
01476                 return true;
01477         }
01478 }
01479 
01480 U64 LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges(const LLUUID& agent_id)
01481 {
01482         //we loop over all of the changes
01483         //if we are adding a role, then we simply add the role's powers
01484         //if we are removing a role, we store that role id away
01485         //and then we have to build the powers up bases on the roles the agent
01486         //is in
01487 
01488         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01489         if (!gdatap) 
01490         {
01491                 llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No group data!" << llendl;
01492                 return GP_NO_POWERS;
01493         }
01494 
01495         LLGroupMemberData* member_data = gdatap->mMembers[agent_id];
01496         if ( !member_data )
01497         {
01498                 llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No member data for member with UUID " << agent_id << llendl;
01499                 return GP_NO_POWERS;
01500         }
01501 
01502         //see if there are unsaved role changes for this agent
01503         role_change_data_map_t* role_change_datap = NULL;
01504         member_role_changes_map_t::iterator member = mMemberRoleChangeData.find(agent_id);
01505         if ( member != mMemberRoleChangeData.end() )
01506         {
01507                 //this member has unsaved role changes
01508                 //so grab them
01509                 role_change_datap = (*member).second;
01510         }
01511 
01512         U64 new_powers = GP_NO_POWERS;
01513 
01514         if ( role_change_datap )
01515         {
01516                 std::vector<LLUUID> roles_to_be_removed;
01517 
01518                 for (role_change_data_map_t::iterator role = role_change_datap->begin();
01519                          role != role_change_datap->end(); ++ role)
01520                 {
01521                         if ( role->second == RMC_ADD )
01522                         {
01523                                 new_powers |= gdatap->getRolePowers(role->first);
01524                         }
01525                         else
01526                         {
01527                                 roles_to_be_removed.push_back(role->first);
01528                         }
01529                 }
01530 
01531                 //loop over the member's current roles, summing up
01532                 //the powers (not including the role we are removing)
01533                 for (LLGroupMemberData::role_list_t::iterator current_role = member_data->roleBegin();
01534                          current_role != member_data->roleEnd(); ++current_role)
01535                 {
01536                         bool role_in_remove_list =
01537                                 (std::find(roles_to_be_removed.begin(),
01538                                                    roles_to_be_removed.end(),
01539                                                    current_role->second->getID()) !=
01540                                  roles_to_be_removed.end());
01541 
01542                         if ( !role_in_remove_list )
01543                         {
01544                                 new_powers |= 
01545                                         current_role->second->getRoleData().mRolePowers;
01546                         }
01547                 }
01548         }
01549         else
01550         {
01551                 //there are no changes for this member
01552                 //the member's powers are just the ones stored in the group
01553                 //manager
01554                 new_powers = member_data->getAgentPowers();
01555         }
01556 
01557         return new_powers;
01558 }
01559 
01560 //If there is no change, returns false be sure to verify
01561 //that there is a role change before attempting to get it or else
01562 //the data will make no sense.  Stores the role change type
01563 bool LLPanelGroupMembersSubTab::getRoleChangeType(const LLUUID& member_id,
01564                                                                                                   const LLUUID& role_id,
01565                                                                                                   LLRoleMemberChangeType& type)
01566 {
01567         member_role_changes_map_t::iterator member_changes_iter = mMemberRoleChangeData.find(member_id);
01568         if ( member_changes_iter != mMemberRoleChangeData.end() )
01569         {
01570                 role_change_data_map_t::iterator role_changes_iter = member_changes_iter->second->find(role_id);
01571                 if ( role_changes_iter != member_changes_iter->second->end() )
01572                 {
01573                         type = role_changes_iter->second;
01574                         return true;
01575                 }
01576         }
01577 
01578         return false;
01579 }
01580 
01581 void LLPanelGroupMembersSubTab::draw()
01582 {
01583         LLPanelGroupSubTab::draw();
01584 
01585         if (mPendingMemberUpdate)
01586         {
01587                 updateMembers();
01588         }
01589 }
01590 
01591 void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
01592 {
01593         if (mGroupID.isNull()) return;
01594 
01595         if ( GC_TITLES == gc || GC_PROPERTIES == gc )
01596         {
01597                 // Don't care about title or general group properties updates.
01598                 return;
01599         }
01600 
01601         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01602         if (!gdatap) 
01603         {
01604                 llwarns << "LLPanelGroupMembersSubTab::update() -- No group data!" << llendl;
01605                 return;
01606         }
01607 
01608         // Rebuild the members list.
01609         mMembersList->deleteAllItems();
01610 
01611         // Wait for both all data to be retrieved before displaying anything.
01612         if (   gdatap->isMemberDataComplete() 
01613                 && gdatap->isRoleDataComplete()
01614                 && gdatap->isRoleMemberDataComplete())
01615         {
01616                 mMemberProgress = gdatap->mMembers.begin();
01617                 mPendingMemberUpdate = TRUE;
01618                 mHasMatch = FALSE;
01619         }
01620         else
01621         {
01622                 // Build a string with info on retrieval progress.
01623                 std::ostringstream retrieved;
01624                 if ( !gdatap->isMemberDataComplete() )
01625                 {
01626                         // Still busy retreiving member list.
01627                         retrieved << "Retrieving member list (" << gdatap->mMembers.size()
01628                                           << " / " << gdatap->mMemberCount << ")...";
01629                 }
01630                 else if( !gdatap->isRoleDataComplete() )
01631                 {
01632                         // Still busy retreiving role list.
01633                         retrieved << "Retrieving role list (" << gdatap->mRoles.size()
01634                                           << " / " << gdatap->mRoleCount << ")...";
01635                 }
01636                 else // (!gdatap->isRoleMemberDataComplete())
01637                 {
01638                         // Still busy retreiving role/member mappings.
01639                         retrieved << "Retrieving role member mappings...";
01640                 }
01641                 mMembersList->setEnabled(FALSE);
01642                 mMembersList->addCommentText(retrieved.str());
01643         }
01644 }
01645 
01646 void LLPanelGroupMembersSubTab::updateMembers()
01647 {
01648         mPendingMemberUpdate = FALSE;
01649 
01650         lldebugs << "LLPanelGroupMembersSubTab::updateMembers()" << llendl;
01651 
01652         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01653         if (!gdatap) 
01654         {
01655                 llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
01656                 return;
01657         }
01658 
01659         // Make sure all data is still complete.  Incomplete data
01660         // may occur if we refresh.
01661         if (   !gdatap->isMemberDataComplete() 
01662                 || !gdatap->isRoleDataComplete()
01663                 || !gdatap->isRoleMemberDataComplete())
01664         {
01665                 return;
01666         }
01667                 
01668         LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
01669 
01670         S32 i = 0;
01671         for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME; 
01672                         ++mMemberProgress, ++i)
01673         {
01674                 if (!mMemberProgress->second)
01675                         continue;
01676                 // Do filtering on name if it is already in the cache.
01677                 bool add_member = true;
01678 
01679                 std::string fullname;
01680                 if (gCacheName->getFullName(mMemberProgress->first, fullname))
01681                 {
01682                         if ( !matchesSearchFilter(fullname) )
01683                         {
01684                                 add_member = false;
01685                         }
01686                 }
01687 
01688                 if (add_member)
01689                 {
01690                         // Build the donated tier string.
01691                         std::ostringstream donated;
01692                         donated << mMemberProgress->second->getContribution() << " sq. m.";
01693 
01694                         LLSD row;
01695                         row["id"] = (*mMemberProgress).first;
01696 
01697                         row["columns"][0]["column"] = "name";
01698                         // value is filled in by name list control
01699 
01700                         row["columns"][1]["column"] = "donated";
01701                         row["columns"][1]["value"] = donated.str();
01702 
01703                         row["columns"][2]["column"] = "online";
01704                         row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
01705                         row["columns"][2]["font"] = "SANSSERIFSMALL";
01706 
01707                         mMembersList->addElement(row);//, ADD_SORTED);
01708                         mHasMatch = TRUE;
01709                 }
01710         }
01711 
01712         if (mMemberProgress == end)
01713         {
01714                 if (mHasMatch)
01715                 {
01716                         mMembersList->setEnabled(TRUE);
01717                 }
01718                 else
01719                 {
01720                         mMembersList->setEnabled(FALSE);
01721                         mMembersList->addCommentText("No match.");
01722                 }
01723         }
01724         else
01725         {
01726                 mPendingMemberUpdate = TRUE;
01727         }
01728 
01729         // This should clear the other two lists, since nothing is selected.
01730         handleMemberSelect();
01731 }
01732 
01733 
01734 
01736 // LLPanelGroupRolesSubTab
01738 
01739 // static
01740 void* LLPanelGroupRolesSubTab::createTab(void* data)
01741 {
01742         LLUUID* group_id = static_cast<LLUUID*>(data);
01743         return new LLPanelGroupRolesSubTab("panel group roles sub tab", *group_id);
01744 }
01745 
01746 LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab(const std::string& name, const LLUUID& group_id)
01747 : LLPanelGroupSubTab(name, group_id), mHasRoleChange(FALSE)
01748 {
01749 }
01750 
01751 LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab()
01752 {
01753 }
01754 
01755 BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
01756 {
01757         // Upcast parent so we can ask it for sibling controls.
01758         LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
01759 
01760         // Look recursively from the parent to find all our widgets.
01761         bool recurse = true;
01762         mHeader = parent->getChild<LLPanel>("roles_header", recurse);
01763         mFooter = parent->getChild<LLPanel>("roles_footer", recurse);
01764 
01765 
01766         mRolesList              = parent->getChild<LLScrollListCtrl>("role_list", recurse);
01767         mAssignedMembersList    = parent->getChild<LLNameListCtrl>("role_assigned_members", recurse);
01768         mAllowedActionsList     = parent->getChild<LLScrollListCtrl>("role_allowed_actions", recurse);
01769 
01770         mRoleName = parent->getChild<LLLineEditor>("role_name", recurse);
01771         mRoleTitle = parent->getChild<LLLineEditor>("role_title", recurse);
01772         mRoleDescription = parent->getChild<LLTextEditor>("role_description", recurse);
01773 
01774         mMemberVisibleCheck = parent->getChild<LLCheckBoxCtrl>("role_visible_in_list", recurse);
01775 
01776         if (!mRolesList || !mAssignedMembersList || !mAllowedActionsList
01777                 || !mRoleName || !mRoleTitle || !mRoleDescription || !mMemberVisibleCheck)
01778         {
01779                 llwarns << "ARG! element not found." << llendl;
01780                 return FALSE;
01781         }
01782 
01783         mRemoveEveryoneTxt = getString("cant_delete_role");
01784 
01785         mCreateRoleButton = 
01786                 parent->getChild<LLButton>("role_create", recurse);
01787         if ( mCreateRoleButton )
01788         {
01789                 mCreateRoleButton->setCallbackUserData(this);
01790                 mCreateRoleButton->setClickedCallback(onCreateRole);
01791                 mCreateRoleButton->setEnabled(FALSE);
01792         }
01793         
01794         mDeleteRoleButton =  
01795                 parent->getChild<LLButton>("role_delete", recurse);
01796         if ( mDeleteRoleButton )
01797         {
01798                 mDeleteRoleButton->setCallbackUserData(this);
01799                 mDeleteRoleButton->setClickedCallback(onDeleteRole);
01800                 mDeleteRoleButton->setEnabled(FALSE);
01801         }
01802 
01803         mRolesList->setCommitOnSelectionChange(TRUE);
01804         mRolesList->setCallbackUserData(this);
01805         mRolesList->setCommitCallback(onRoleSelect);
01806 
01807         mMemberVisibleCheck->setCallbackUserData(this);
01808         mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange);
01809 
01810         mAllowedActionsList->setCommitOnSelectionChange(TRUE);
01811         mAllowedActionsList->setCallbackUserData(this);
01812 
01813         mRoleName->setCommitOnFocusLost(TRUE);
01814         mRoleName->setCallbackUserData(this);
01815         mRoleName->setKeystrokeCallback(onPropertiesKey);
01816 
01817         mRoleTitle->setCommitOnFocusLost(TRUE);
01818         mRoleTitle->setCallbackUserData(this);
01819         mRoleTitle->setKeystrokeCallback(onPropertiesKey);
01820 
01821         mRoleDescription->setCommitOnFocusLost(TRUE);
01822         mRoleDescription->setCallbackUserData(this);
01823         mRoleDescription->setCommitCallback(onDescriptionCommit);
01824         mRoleDescription->setFocusReceivedCallback(onDescriptionFocus, this);
01825 
01826         setFooterEnabled(FALSE);
01827 
01828         return TRUE;
01829 }
01830 
01831 void LLPanelGroupRolesSubTab::activate()
01832 {
01833         LLPanelGroupSubTab::activate();
01834 
01835         mRolesList->deselectAllItems();
01836         mAssignedMembersList->deleteAllItems();
01837         mAllowedActionsList->deleteAllItems();
01838         mRoleName->clear();
01839         mRoleDescription->clear();
01840         mRoleTitle->clear();
01841 
01842         setFooterEnabled(FALSE);
01843 
01844         mHasRoleChange = FALSE;
01845         update(GC_ALL);
01846 }
01847 
01848 void LLPanelGroupRolesSubTab::deactivate()
01849 {
01850         lldebugs << "LLPanelGroupRolesSubTab::deactivate()" << llendl;
01851 
01852         LLPanelGroupSubTab::deactivate();
01853 }
01854 
01855 bool LLPanelGroupRolesSubTab::needsApply(LLString& mesg)
01856 {
01857         lldebugs << "LLPanelGroupRolesSubTab::needsApply()" << llendl;
01858 
01859         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01860 
01861         return (mHasRoleChange                                                          // Text changed in current role
01862                         || (gdatap && gdatap->pendingRoleChanges()));   // Pending role changes in the group
01863 }
01864 
01865 bool LLPanelGroupRolesSubTab::apply(LLString& mesg)
01866 {
01867         lldebugs << "LLPanelGroupRolesSubTab::apply()" << llendl;
01868 
01869         saveRoleChanges();
01870         LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID);
01871 
01872         notifyObservers();
01873 
01874         return true;
01875 }
01876 
01877 void LLPanelGroupRolesSubTab::cancel()
01878 {
01879         mHasRoleChange = FALSE;
01880         LLGroupMgr::getInstance()->cancelGroupRoleChanges(mGroupID);
01881 
01882         notifyObservers();
01883 }
01884 
01885 LLSD LLPanelGroupRolesSubTab::createRoleItem(const LLUUID& role_id, 
01886                                                                  std::string name, 
01887                                                                  std::string title, 
01888                                                                  S32 members)
01889 {
01890         LLSD row;
01891         row["id"] = role_id;
01892 
01893         row["columns"][0]["column"] = "name";
01894         row["columns"][0]["value"] = name;
01895 
01896         row["columns"][1]["column"] = "title";
01897         row["columns"][1]["value"] = title;
01898 
01899         row["columns"][2]["column"] = "members";
01900         row["columns"][2]["value"] = members;
01901         
01902         return row;
01903 }
01904 
01905 bool LLPanelGroupRolesSubTab::matchesSearchFilter(std::string rolename, std::string roletitle)
01906 {
01907         // If the search filter is empty, everything passes.
01908         if (mSearchFilter.empty()) return true;
01909 
01910         LLString::toLower(rolename);
01911         LLString::toLower(roletitle);
01912         std::string::size_type match_name = rolename.find(mSearchFilter);
01913         std::string::size_type match_title = roletitle.find(mSearchFilter);
01914 
01915         if ( (std::string::npos == match_name)
01916                 && (std::string::npos == match_title))
01917         {
01918                 // not found
01919                 return false;
01920         }
01921         else
01922         {
01923                 return true;
01924         }
01925 }
01926 
01927 void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
01928 {
01929         lldebugs << "LLPanelGroupRolesSubTab::update()" << llendl;
01930 
01931         if (mGroupID.isNull()) return;
01932 
01933         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
01934 
01935         if (!gdatap || !gdatap->isRoleDataComplete())
01936         {
01937                 LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
01938         }
01939         else
01940         {
01941                 bool had_selection = false;
01942                 LLUUID last_selected;
01943                 if (mRolesList->getFirstSelected())
01944                 {
01945                         last_selected = mRolesList->getFirstSelected()->getUUID();
01946                         had_selection = true;
01947                 }
01948                 mRolesList->deleteAllItems();
01949 
01950                 LLScrollListItem* item = NULL;
01951 
01952                 LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
01953                 LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
01954 
01955                 for ( ; rit != end; ++rit)
01956                 {
01957                         LLRoleData rd;
01958                         if (gdatap->getRoleData((*rit).first,rd))
01959                         {
01960                                 if (matchesSearchFilter(rd.mRoleName, rd.mRoleTitle))
01961                                 {
01962                                         // If this is the everyone role, then EVERYONE is in it.
01963                                         S32 members_in_role = (*rit).first.isNull() ? gdatap->mMembers.size() : (*rit).second->getTotalMembersInRole();
01964                                         LLSD row = createRoleItem((*rit).first,rd.mRoleName, rd.mRoleTitle, members_in_role);
01965                                         item = mRolesList->addElement(row, ((*rit).first.isNull()) ? ADD_TOP : ADD_BOTTOM, this);
01966                                         if (had_selection && ((*rit).first == last_selected))
01967                                         {
01968                                                 item->setSelected(TRUE);
01969                                         }
01970                                 }
01971                         }
01972                         else
01973                         {
01974                                 llwarns << "LLPanelGroupRolesSubTab::update() No role data for role " << (*rit).first << llendl;
01975                         }
01976                 }
01977 
01978                 mRolesList->sortByColumn("name", TRUE);
01979 
01980                 if ( (gdatap->mRoles.size() < (U32)MAX_ROLES)
01981                         && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) )
01982                 {
01983                         mCreateRoleButton->setEnabled(TRUE);
01984                 }
01985                 else
01986                 {
01987                         mCreateRoleButton->setEnabled(FALSE);
01988                 }
01989 
01990                 if (had_selection)
01991                 {
01992                         handleRoleSelect();
01993                 }
01994                 else
01995                 {
01996                         mAssignedMembersList->deleteAllItems();
01997                         mAllowedActionsList->deleteAllItems();
01998                         mRoleName->clear();
01999                         mRoleDescription->clear();
02000                         mRoleTitle->clear();
02001                         setFooterEnabled(FALSE);
02002                         mDeleteRoleButton->setEnabled(FALSE);
02003                 }
02004         }
02005 
02006         if (!gdatap || !gdatap->isMemberDataComplete())
02007         {
02008                 LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID);
02009         }
02010         
02011         if (!gdatap || !gdatap->isRoleMemberDataComplete())
02012         {
02013                 LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
02014         }
02015 
02016         if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
02017             && gdatap
02018             && gdatap->isMemberDataComplete()
02019             && gdatap->isRoleMemberDataComplete())
02020         {
02021                 buildMembersList();
02022         }
02023 }
02024 
02025 // static
02026 void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
02027 {
02028         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02029         self->handleRoleSelect();
02030 }
02031 
02032 void LLPanelGroupRolesSubTab::handleRoleSelect()
02033 {
02034         BOOL can_delete = TRUE;
02035         lldebugs << "LLPanelGroupRolesSubTab::handleRoleSelect()" << llendl;
02036 
02037         mAssignedMembersList->deleteAllItems();
02038         mAllowedActionsList->deleteAllItems();
02039         
02040         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02041         if (!gdatap) 
02042         {
02043                 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
02044                                 << "-- No group data!" << llendl;
02045                 return;
02046         }
02047 
02048         saveRoleChanges();
02049 
02050         // Check if there is anything selected.
02051         LLScrollListItem* item = mRolesList->getFirstSelected();
02052         if (!item)
02053         {
02054                 setFooterEnabled(FALSE);
02055                 return;
02056         }
02057 
02058         setFooterEnabled(TRUE);
02059 
02060         LLRoleData rd;
02061         if (gdatap->getRoleData(item->getUUID(),rd))
02062         {
02063                 BOOL is_owner_role = ( gdatap->mOwnerRole == item->getUUID() );
02064                 mRoleName->setText(rd.mRoleName);
02065                 mRoleTitle->setText(rd.mRoleTitle);
02066                 mRoleDescription->setText(rd.mRoleDescription);
02067 
02068                 mAllowedActionsList->setEnabled(gAgent.hasPowerInGroup(mGroupID,
02069                                                                            GP_ROLE_CHANGE_ACTIONS));
02070                 buildActionsList(mAllowedActionsList,
02071                                                  rd.mRolePowers,
02072                                                  0LL,
02073                                                  mActionIcons,
02074                                                  onActionCheck,
02075                                                  TRUE,
02076                                                  FALSE,
02077                                                  is_owner_role);
02078 
02079 
02080                 mMemberVisibleCheck->set((rd.mRolePowers & GP_MEMBER_VISIBLE_IN_DIR) == GP_MEMBER_VISIBLE_IN_DIR);
02081                 mRoleName->setEnabled(!is_owner_role &&
02082                                 gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
02083                 mRoleTitle->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
02084                 mRoleDescription->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
02085                 mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
02086 
02087                 if (item->getUUID().isNull())
02088                 {
02089                         // Everyone role, can't edit description or name or delete
02090                         mRoleDescription->setEnabled(FALSE);
02091                         mRoleName->setEnabled(FALSE);
02092                         can_delete = FALSE;
02093                 }
02094                 //you can't delete the owner role
02095                 if ( is_owner_role ) can_delete = FALSE;
02096         }
02097         else
02098         {
02099                 mRolesList->deselectAllItems();
02100                 mAssignedMembersList->deleteAllItems();
02101                 mAllowedActionsList->deleteAllItems();
02102                 mRoleName->clear();
02103                 mRoleDescription->clear();
02104                 mRoleTitle->clear();
02105                 setFooterEnabled(FALSE);
02106 
02107                 can_delete = FALSE;
02108         }
02109         mSelectedRole = item->getUUID();
02110         buildMembersList();
02111 
02112         can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
02113                                                                                                           GP_ROLE_DELETE);
02114         mDeleteRoleButton->setEnabled(can_delete);
02115 }
02116 
02117 void LLPanelGroupRolesSubTab::buildMembersList()
02118 {
02119         mAssignedMembersList->deleteAllItems();
02120 
02121         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02122         if (!gdatap) 
02123         {
02124                 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
02125                                 << "-- No group data!" << llendl;
02126                 return;
02127         }
02128 
02129         // Check if there is anything selected.
02130         LLScrollListItem* item = mRolesList->getFirstSelected();
02131         if (!item) return;
02132 
02133         if (item->getUUID().isNull())
02134         {
02135                 // Special cased 'Everyone' role
02136                 LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.begin();
02137                 LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
02138                 for ( ; mit != end; ++mit)
02139                 {
02140                         mAssignedMembersList->addNameItem((*mit).first);
02141                 }
02142         }
02143         else
02144         {
02145                 LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.find(item->getUUID());
02146                 if (rit != gdatap->mRoles.end())
02147                 {
02148                         LLGroupRoleData* rdatap = (*rit).second;
02149                         if (rdatap)
02150                         {
02151                                 std::vector<LLUUID>::const_iterator mit = rdatap->getMembersBegin();
02152                                 std::vector<LLUUID>::const_iterator end = rdatap->getMembersEnd();
02153                                 for ( ; mit != end; ++mit)
02154                                 {
02155                                         mAssignedMembersList->addNameItem((*mit));
02156                                 }
02157                         }
02158                 }
02159         }
02160 }
02161 
02162 // static
02163 void LLPanelGroupRolesSubTab::onActionCheck(LLUICtrl* ctrl, void* user_data)
02164 {
02165         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02166         LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
02167         if (!check || !self) return;
02168 
02169         self->handleActionCheck(check);
02170 }
02171 
02172 struct ActionCBData
02173 {
02174         LLPanelGroupRolesSubTab*        mSelf;
02175         LLCheckBoxCtrl*                         mCheck;
02176 };
02177 
02178 void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool force)
02179 {
02180         lldebugs << "LLPanelGroupRolesSubTab::handleActionSelect()" << llendl;
02181 
02182         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02183         if (!gdatap) 
02184         {
02185                 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
02186                                 << "-- No group data!" << llendl;
02187                 return;
02188         }
02189 
02190         LLScrollListItem* action_item = mAllowedActionsList->getFirstSelected();
02191         if (!action_item)
02192         {
02193                 return;
02194         }
02195 
02196         LLScrollListItem* role_item = mRolesList->getFirstSelected();
02197         if (!role_item)
02198         {
02199                 return;
02200         }
02201         LLUUID role_id = role_item->getUUID();
02202 
02203         LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
02204         U64 power = rap->mPowerBit;
02205 
02206         if (check->get())
02207         {
02208                 if (!force && (    (GP_ROLE_ASSIGN_MEMBER == power)
02209                                                 || (GP_ROLE_CHANGE_ACTIONS == power) ))
02210                 {
02211                         // Uncheck the item, for now.  It will be
02212                         // checked if they click 'Yes', below.
02213                         check->set(FALSE);
02214 
02215                         LLRoleData rd;
02216                         LLStringBase<char>::format_map_t args;
02217 
02218                         if ( gdatap->getRoleData(role_id, rd) )
02219                         {
02220                                 args["[ACTION_NAME]"] = rap->mDescription;
02221                                 args["[ROLE_NAME]"] = rd.mRoleName;
02222                                 struct ActionCBData* cb_data = new ActionCBData;
02223                                 cb_data->mSelf = this;
02224                                 cb_data->mCheck = check;
02225                                 mHasModal = TRUE;
02226                                 LLString warning = "AssignDangerousActionWarning";
02227                                 if (GP_ROLE_CHANGE_ACTIONS == power)
02228                                 {
02229                                         warning = "AssignDangerousAbilityWarning";
02230                                 }
02231                                 gViewerWindow->alertXml(warning, args, addActionCB, cb_data);
02232                         }
02233                         else
02234                         {
02235                                 llwarns << "Unable to look up role information for role id: "
02236                                                 << role_id << llendl;
02237                         }
02238                 }
02239                 else
02240                 {
02241                         gdatap->addRolePower(role_id,power);
02242                 }
02243         }
02244         else
02245         {
02246                 gdatap->removeRolePower(role_id,power);
02247         }
02248 
02249         mHasRoleChange = TRUE;
02250         notifyObservers();
02251 }
02252 
02253 //static
02254 void LLPanelGroupRolesSubTab::addActionCB(S32 option, void* data)
02255 {
02256         struct ActionCBData* cb_data = (struct ActionCBData*) data;
02257 
02258         if (!cb_data || !cb_data->mSelf || !cb_data->mCheck) return;
02259 
02260         cb_data->mSelf->mHasModal = FALSE;
02261 
02262         if (0 == option)
02263         {
02264                 // User clicked "Yes"
02265                 cb_data->mCheck->set(TRUE);
02266                 const bool force_add = true;
02267                 cb_data->mSelf->handleActionCheck(cb_data->mCheck, force_add);
02268         }
02269 }
02270 
02271 
02272 // static
02273 void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
02274 {
02275         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02276         if (!self) return;
02277 
02278         self->mHasRoleChange = TRUE;
02279         self->notifyObservers();
02280 }
02281 
02282 // static 
02283 void LLPanelGroupRolesSubTab::onDescriptionFocus(LLFocusableElement* ctrl, void* user_data)
02284 {
02285         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02286         if (!self) return;
02287 
02288         self->mHasRoleChange = TRUE;
02289         self->notifyObservers();
02290 }
02291 
02292 // static 
02293 void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data)
02294 {
02295         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02296         if (!self) return;
02297 
02298         self->mHasRoleChange = TRUE;
02299         self->notifyObservers();
02300 }
02301 
02302 // static 
02303 void LLPanelGroupRolesSubTab::onMemberVisibilityChange(LLUICtrl* ctrl, void* user_data)
02304 {
02305         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02306         LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
02307         if (!check || !self) return;
02308 
02309         self->handleMemberVisibilityChange(check->get());
02310 }
02311 
02312 void LLPanelGroupRolesSubTab::handleMemberVisibilityChange(bool value)
02313 {
02314         lldebugs << "LLPanelGroupRolesSubTab::handleMemberVisibilityChange()" << llendl;
02315 
02316         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02317         if (!gdatap) 
02318         {
02319                 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
02320                                 << "-- No group data!" << llendl;
02321                 return;
02322         }
02323 
02324         LLScrollListItem* role_item = mRolesList->getFirstSelected();
02325         if (!role_item)
02326         {
02327                 return;
02328         }
02329 
02330         if (value)
02331         {
02332                 gdatap->addRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
02333         }
02334         else
02335         {
02336                 gdatap->removeRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
02337         }
02338 }
02339 
02340 // static 
02341 void LLPanelGroupRolesSubTab::onCreateRole(void* user_data)
02342 {
02343         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02344         if (!self) return;
02345 
02346         self->handleCreateRole();
02347 }
02348 
02349 void LLPanelGroupRolesSubTab::handleCreateRole()
02350 {
02351         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02352 
02353         if (!gdatap) return;
02354 
02355         LLUUID new_role_id;
02356         new_role_id.generate();
02357 
02358         LLRoleData rd;
02359         rd.mRoleName = "New Role";
02360         gdatap->createRole(new_role_id,rd);
02361 
02362         mRolesList->deselectAllItems(TRUE);
02363         LLSD row;
02364         row["id"] = new_role_id;
02365         row["columns"][0]["column"] = "name";
02366         row["columns"][0]["value"] = rd.mRoleName;
02367         mRolesList->addElement(row, ADD_BOTTOM, this);
02368         mRolesList->selectByID(new_role_id);
02369 
02370         // put focus on name field and select its contents
02371         if(mRoleName)
02372         {
02373                 mRoleName->setFocus(TRUE);
02374                 mRoleName->onTabInto();
02375                 gFocusMgr.triggerFocusFlash();
02376         }
02377 
02378         notifyObservers();
02379 }
02380 
02381 // static 
02382 void LLPanelGroupRolesSubTab::onDeleteRole(void* user_data)
02383 {
02384         LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
02385         if (!self) return;
02386 
02387         self->handleDeleteRole();
02388 }
02389 
02390 void LLPanelGroupRolesSubTab::handleDeleteRole()
02391 {
02392         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02393 
02394         if (!gdatap) return;
02395 
02396         LLScrollListItem* role_item = mRolesList->getFirstSelected();
02397         if (!role_item)
02398         {
02399                 return;
02400         }
02401 
02402         if (role_item->getUUID().isNull() || role_item->getUUID() == gdatap->mOwnerRole)
02403         {
02404                 LLString::format_map_t args;
02405                 args["[MESSAGE]"] = mRemoveEveryoneTxt;
02406                 LLNotifyBox::showXml("GenericNotify", args);
02407                 return;
02408         }
02409 
02410         gdatap->deleteRole(role_item->getUUID());
02411         mRolesList->deleteSingleItem(mRolesList->getFirstSelectedIndex());
02412         mRolesList->selectFirstItem();
02413 
02414         notifyObservers();
02415 }
02416 
02417 void LLPanelGroupRolesSubTab::saveRoleChanges()
02418 {
02419         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02420 
02421         if (!gdatap) return;
02422 
02423         if (mHasRoleChange)
02424         {
02425                 LLRoleData rd;
02426                 if (!gdatap->getRoleData(mSelectedRole,rd)) return;
02427 
02428                 rd.mRoleName = mRoleName->getText();
02429                 rd.mRoleDescription = mRoleDescription->getText();
02430                 rd.mRoleTitle = mRoleTitle->getText();
02431 
02432                 gdatap->setRoleData(mSelectedRole,rd);
02433 
02434                 mRolesList->deleteSingleItem(mRolesList->getItemIndex(mSelectedRole));
02435                 
02436                 LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,0);
02437                 LLScrollListItem* item = mRolesList->addElement(row, ADD_BOTTOM, this);
02438                 item->setSelected(TRUE);
02439 
02440                 mHasRoleChange = FALSE;
02441         }
02442 }
02444 // LLPanelGroupActionsSubTab
02446 
02447 // static
02448 void* LLPanelGroupActionsSubTab::createTab(void* data)
02449 {
02450         LLUUID* group_id = static_cast<LLUUID*>(data);
02451         return new LLPanelGroupActionsSubTab("panel group actions sub tab", *group_id);
02452 }
02453 
02454 LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab(const std::string& name, const LLUUID& group_id)
02455 : LLPanelGroupSubTab(name, group_id)
02456 {
02457 }
02458 
02459 LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab()
02460 {
02461 }
02462 
02463 BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
02464 {
02465         // Upcast parent so we can ask it for sibling controls.
02466         LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
02467 
02468         // Look recursively from the parent to find all our widgets.
02469         bool recurse = true;
02470         mHeader = parent->getChild<LLPanel>("actions_header", recurse);
02471         mFooter = parent->getChild<LLPanel>("actions_footer", recurse);
02472 
02473         mActionDescription = parent->getChild<LLTextEditor>("action_description", recurse);
02474 
02475         mActionList = parent->getChild<LLScrollListCtrl>("action_list",recurse);
02476         mActionRoles = parent->getChild<LLScrollListCtrl>("action_roles",recurse);
02477         mActionMembers  = parent->getChild<LLNameListCtrl>("action_members",recurse);
02478 
02479         if (!mActionList || !mActionDescription || !mActionRoles || !mActionMembers) return FALSE;
02480 
02481         mActionList->setCallbackUserData(this);
02482         mActionList->setCommitOnSelectionChange(TRUE);
02483         mActionList->setCommitCallback(onActionSelect);
02484 
02485         mActionMembers->setCallbackUserData(this);
02486         mActionRoles->setCallbackUserData(this);
02487 
02488         update(GC_ALL);
02489 
02490         return TRUE;
02491 }
02492 
02493 void LLPanelGroupActionsSubTab::activate()
02494 {
02495         LLPanelGroupSubTab::activate();
02496         lldebugs << "LLPanelGroupActionsSubTab::activate()" << llendl;
02497 
02498         mActionList->deselectAllItems();
02499         mActionMembers->deleteAllItems();
02500         mActionRoles->deleteAllItems();
02501         mActionDescription->clear();
02502 }
02503 
02504 void LLPanelGroupActionsSubTab::deactivate()
02505 {
02506         lldebugs << "LLPanelGroupActionsSubTab::deactivate()" << llendl;
02507 
02508         LLPanelGroupSubTab::deactivate();
02509 }
02510 
02511 bool LLPanelGroupActionsSubTab::needsApply(LLString& mesg)
02512 {
02513         lldebugs << "LLPanelGroupActionsSubTab::needsApply()" << llendl;
02514 
02515         return false;
02516 }
02517 
02518 bool LLPanelGroupActionsSubTab::apply(LLString& mesg)
02519 {
02520         lldebugs << "LLPanelGroupActionsSubTab::apply()" << llendl;
02521         return true;
02522 }
02523 
02524 void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
02525 {
02526         lldebugs << "LLPanelGroupActionsSubTab::update()" << llendl;
02527 
02528         if (mGroupID.isNull()) return;
02529 
02530         mActionList->deselectAllItems();
02531         mActionMembers->deleteAllItems();
02532         mActionRoles->deleteAllItems();
02533         mActionDescription->clear();
02534 
02535         mActionList->deleteAllItems();
02536         buildActionsList(mActionList,
02537                                          GP_ALL_POWERS,
02538                                          GP_ALL_POWERS,
02539                                          mActionIcons,
02540                                          NULL,
02541                                          FALSE,
02542                                          TRUE,
02543                                          FALSE);
02544 }
02545 
02546 // static 
02547 void LLPanelGroupActionsSubTab::onActionSelect(LLUICtrl* scroll, void* data)
02548 {
02549         LLPanelGroupActionsSubTab* self = static_cast<LLPanelGroupActionsSubTab*>(data);
02550         self->handleActionSelect();
02551 }
02552 
02553 void LLPanelGroupActionsSubTab::handleActionSelect()
02554 {
02555         mActionMembers->deleteAllItems();
02556         mActionRoles->deleteAllItems();
02557 
02558         U64 power_mask = GP_NO_POWERS;
02559         std::vector<LLScrollListItem*> selection = 
02560                                                         mActionList->getAllSelected();
02561         if (selection.empty()) return;
02562 
02563         LLRoleAction* rap;
02564 
02565         std::vector<LLScrollListItem*>::iterator itor;
02566         for (itor = selection.begin() ; 
02567                  itor != selection.end(); ++itor)
02568         {
02569                 rap = (LLRoleAction*)( (*itor)->getUserdata() );
02570                 power_mask |= rap->mPowerBit;
02571         }
02572 
02573         if (selection.size() == 1)
02574         {
02575                 LLScrollListItem* item = selection[0];
02576                 rap = (LLRoleAction*)(item->getUserdata());
02577 
02578                 if (rap->mLongDescription.empty())
02579                 {
02580                         mActionDescription->setText(rap->mDescription);
02581                 }
02582                 else
02583                 {
02584                         mActionDescription->setText(rap->mLongDescription);
02585                 }
02586         }
02587         else
02588         {
02589                 mActionDescription->clear();
02590         }
02591 
02592         LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
02593 
02594         if (!gdatap) return;
02595 
02596         if (gdatap->isMemberDataComplete())
02597         {
02598                 LLGroupMgrGroupData::member_list_t::iterator it = gdatap->mMembers.begin();
02599                 LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
02600                 LLGroupMemberData* gmd;
02601 
02602                 for ( ; it != end; ++it)
02603                 {
02604                         gmd = (*it).second;
02605                         if (!gmd) continue;
02606                         if ((gmd->getAgentPowers() & power_mask) == power_mask)
02607                         {
02608                                 mActionMembers->addNameItem(gmd->getID());
02609                         }
02610                 }
02611         }
02612         else
02613         {
02614                 LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID);
02615         }
02616 
02617         if (gdatap->isRoleDataComplete())
02618         {
02619                 LLGroupMgrGroupData::role_list_t::iterator it = gdatap->mRoles.begin();
02620                 LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
02621                 LLGroupRoleData* rmd;
02622 
02623                 for ( ; it != end; ++it)
02624                 {
02625                         rmd = (*it).second;
02626                         if (!rmd) continue;
02627                         if ((rmd->getRoleData().mRolePowers & power_mask) == power_mask)
02628                         {
02629                                 mActionRoles->addSimpleElement(rmd->getRoleData().mRoleName);
02630                         }
02631                 }
02632         }
02633         else
02634         {
02635                 LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
02636         }
02637 }

Generated on Fri May 16 08:33:53 2008 for SecondLife by  doxygen 1.5.5