aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpanelgrouproles.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llpanelgrouproles.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llpanelgrouproles.cpp')
-rw-r--r--linden/indra/newview/llpanelgrouproles.cpp2661
1 files changed, 2661 insertions, 0 deletions
diff --git a/linden/indra/newview/llpanelgrouproles.cpp b/linden/indra/newview/llpanelgrouproles.cpp
new file mode 100644
index 0000000..82f38e2
--- /dev/null
+++ b/linden/indra/newview/llpanelgrouproles.cpp
@@ -0,0 +1,2661 @@
1/**
2 * @file llpanelgrouproles.cpp
3 * @brief Panel for roles information about a particular group.
4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llcheckboxctrl.h"
31
32#include "llagent.h"
33#include "llbutton.h"
34#include "llfloateravatarinfo.h"
35#include "llfloatergroupinvite.h"
36#include "lliconctrl.h"
37#include "lllineeditor.h"
38#include "llnamelistctrl.h"
39#include "llnotify.h"
40#include "llpanelgrouproles.h"
41#include "llscrolllistctrl.h"
42#include "lltabcontainer.h"
43#include "lltextbox.h"
44#include "lltexteditor.h"
45#include "llviewerimagelist.h"
46#include "llviewerwindow.h"
47#include "llfocusmgr.h"
48
49#include "roles_constants.h"
50
51bool agentCanRemoveFromRole(const LLUUID& group_id,
52 const LLUUID& role_id)
53{
54 return gAgent.hasPowerInGroup(group_id, GP_ROLE_REMOVE_MEMBER);
55}
56
57bool agentCanAddToRole(const LLUUID& group_id,
58 const LLUUID& role_id)
59{
60 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(group_id);
61 if (!gdatap)
62 {
63 llwarns << "agentCanAddToRole "
64 << "-- No group data!" << llendl;
65 return false;
66 }
67
68 //make sure the agent is in the group
69 LLGroupMgrGroupData::member_iter mi = gdatap->mMembers.find(gAgent.getID());
70 if (mi == gdatap->mMembers.end())
71 {
72 return false;
73 }
74
75 LLGroupMemberData* member_data = (*mi).second;
76
77 // Owners can add to any role.
78 if ( member_data->isInRole(gdatap->mOwnerRole) )
79 {
80 return true;
81 }
82
83 // 'Limited assign members' can add to roles the user is in.
84 if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER_LIMITED) &&
85 member_data->isInRole(role_id) )
86 {
87 return true;
88 }
89
90 // 'assign members' can add to non-owner roles.
91 if ( gAgent.hasPowerInGroup(group_id, GP_ROLE_ASSIGN_MEMBER) &&
92 role_id != gdatap->mOwnerRole )
93 {
94 return true;
95 }
96
97 return false;
98}
99
100// static
101void* LLPanelGroupRoles::createTab(void* data)
102{
103 LLUUID* group_id = static_cast<LLUUID*>(data);
104 return new LLPanelGroupRoles("panel group roles", *group_id);
105}
106
107LLPanelGroupRoles::LLPanelGroupRoles(const std::string& name, const LLUUID& group_id)
108: LLPanelGroupTab(name, group_id),
109 mCurrentTab(NULL),
110 mRequestedTab( NULL ),
111 mSubTabContainer( NULL ),
112 mFirstUse( TRUE ),
113 mIgnoreTransition( FALSE )
114{
115}
116
117LLPanelGroupRoles::~LLPanelGroupRoles()
118{
119 int i;
120 for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
121 {
122 LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
123
124 subtabp->removeObserver(this);
125 }
126}
127
128BOOL LLPanelGroupRoles::postBuild()
129{
130 lldebugs << "LLPanelGroupRoles::postBuild()" << llendl;
131
132 mSubTabContainer = (LLTabContainerCommon*) getChildByName("roles_tab_container");
133
134 if (!mSubTabContainer) return FALSE;
135
136 // Hook up each sub-tabs callback and widgets.
137 S32 i;
138 for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
139 {
140 LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
141
142 // Add click callbacks to all the tabs.
143 mSubTabContainer->setTabChangeCallback(subtabp, onClickSubTab);
144 mSubTabContainer->setTabUserData(subtabp, this);
145
146 // Hand the subtab a pointer to this LLPanelGroupRoles, so that it can
147 // look around for the widgets it is interested in.
148 if (!subtabp->postBuildSubTab(this)) return FALSE;
149
150 subtabp->addObserver(this);
151 }
152
153 // Set the current tab to whatever is currently being shown.
154 mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
155 if (!mCurrentTab)
156 {
157 // Need to select a tab.
158 mSubTabContainer->selectFirstTab();
159 mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
160 }
161
162 if (!mCurrentTab) return FALSE;
163
164 // Act as though this tab was just activated.
165 mCurrentTab->activate();
166
167 // Read apply text from the xml file.
168 LLTextBox* txt;
169 // Don't recurse for this, since we don't currently have a recursive removeChild()
170 txt = (LLTextBox*)getChildByName("default_needs_apply_text");
171 if (txt)
172 {
173 mDefaultNeedsApplyMesg = txt->getText();
174 removeChild(txt);
175 }
176 txt = (LLTextBox*)getChildByName("want_apply_text");
177 if (txt)
178 {
179 mWantApplyMesg = txt->getText();
180 removeChild(txt);
181 }
182
183 return LLPanelGroupTab::postBuild();
184}
185
186BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp)
187{
188 /* This power was removed to make group roles simpler
189 return agentp->hasPowerInGroup(mGroupID,
190 GP_ROLE_CREATE |
191 GP_ROLE_DELETE |
192 GP_ROLE_PROPERTIES |
193 GP_ROLE_VIEW |
194 GP_ROLE_ASSIGN_MEMBER |
195 GP_ROLE_REMOVE_MEMBER |
196 GP_ROLE_CHANGE_ACTIONS |
197 GP_MEMBER_INVITE |
198 GP_MEMBER_EJECT |
199 GP_MEMBER_OPTIONS );
200 */
201 return mAllowEdit && agentp->isInGroup(mGroupID);
202
203}
204
205// static
206void LLPanelGroupRoles::onClickSubTab(void* user_data, bool from_click)
207{
208 LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
209 self->handleClickSubTab();
210}
211
212void LLPanelGroupRoles::handleClickSubTab()
213{
214 // If we are already handling a transition,
215 // ignore this.
216 if (mIgnoreTransition)
217 {
218 return;
219 }
220
221 mRequestedTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
222
223 // Make sure they aren't just clicking the same tab...
224 if (mRequestedTab == mCurrentTab)
225 {
226 return;
227 }
228
229 // Try to switch from the current panel to the panel the user selected.
230 attemptTransition();
231}
232
233BOOL LLPanelGroupRoles::attemptTransition()
234{
235 // Check if the current tab needs to be applied.
236 LLString mesg;
237 if (mCurrentTab && mCurrentTab->needsApply(mesg))
238 {
239 // If no message was provided, give a generic one.
240 if (mesg.empty())
241 {
242 mesg = mDefaultNeedsApplyMesg;
243 }
244 // Create a notify box, telling the user about the unapplied tab.
245 LLString::format_map_t args;
246 args["[NEEDS_APPLY_MESSAGE]"] = mesg;
247 args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
248 gViewerWindow->alertXml("PanelGroupApply", args,
249 onNotifyCallback, (void*) this);
250 mHasModal = TRUE;
251 // We need to reselect the current tab, since it isn't finished.
252 if (mSubTabContainer)
253 {
254 mIgnoreTransition = TRUE;
255 mSubTabContainer->selectTabPanel( mCurrentTab );
256 mIgnoreTransition = FALSE;
257 }
258 // Returning FALSE will block a close action from finishing until
259 // we get a response back from the user.
260 return FALSE;
261 }
262 else
263 {
264 // The current panel didn't have anything it needed to apply.
265 if (mRequestedTab)
266 {
267 transitionToTab();
268 }
269 return TRUE;
270 }
271}
272
273void LLPanelGroupRoles::transitionToTab()
274{
275 // Tell the current panel that it is being deactivated.
276 if (mCurrentTab)
277 {
278 mCurrentTab->deactivate();
279 }
280
281 // Tell the new panel that it is being activated.
282 if (mRequestedTab)
283 {
284 // This is now the current tab;
285 mCurrentTab = mRequestedTab;
286 mCurrentTab->activate();
287 }
288}
289
290// static
291void LLPanelGroupRoles::onNotifyCallback(S32 option, void* user_data)
292{
293 LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
294 if (self)
295 {
296 self->handleNotifyCallback(option);
297 }
298}
299
300void LLPanelGroupRoles::handleNotifyCallback(S32 option)
301{
302 mHasModal = FALSE;
303 switch (option)
304 {
305 case 0: // "Apply Changes"
306 {
307 // Try to apply changes, and switch to the requested tab.
308 LLString apply_mesg;
309 if ( !apply( apply_mesg ) )
310 {
311 // There was a problem doing the apply.
312 if ( !apply_mesg.empty() )
313 {
314 mHasModal = TRUE;
315 LLString::format_map_t args;
316 args["[MESSAGE]"] = apply_mesg;
317 gViewerWindow->alertXml("GenericAlert", args, onModalClose, (void*) this);
318 }
319 // Skip switching tabs.
320 break;
321 }
322
323 // This panel's info successfully applied.
324 // Switch to the next panel.
325 // No break! Continue into 'Ignore Changes' which just switches tabs.
326 mIgnoreTransition = TRUE;
327 mSubTabContainer->selectTabPanel( mRequestedTab );
328 mIgnoreTransition = FALSE;
329 transitionToTab();
330 break;
331 }
332 case 1: // "Ignore Changes"
333 // Switch to the requested panel without applying changes
334 cancel();
335 mIgnoreTransition = TRUE;
336 mSubTabContainer->selectTabPanel( mRequestedTab );
337 mIgnoreTransition = FALSE;
338 transitionToTab();
339 break;
340 case 2: // "Cancel"
341 default:
342 // Do nothing. The user is canceling the action.
343 break;
344 }
345}
346
347// static
348void LLPanelGroupRoles::onModalClose(S32 option, void* user_data)
349{
350 LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
351 if (self)
352 {
353 self->mHasModal = FALSE;
354 }
355}
356
357
358bool LLPanelGroupRoles::apply(LLString& mesg)
359{
360 // Pass this along to the currently visible sub tab.
361 if (!mSubTabContainer) return false;
362
363 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
364 if (!panelp) return false;
365
366 // Ignore the needs apply message.
367 LLString ignore_mesg;
368 if ( !panelp->needsApply(ignore_mesg) )
369 {
370 // We don't need to apply anything.
371 // We're done.
372 return true;
373 }
374
375 // Try to do the actual apply.
376 return panelp->apply(mesg);
377}
378
379void LLPanelGroupRoles::cancel()
380{
381 // Pass this along to the currently visible sub tab.
382 if (!mSubTabContainer) return;
383
384 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
385 if (!panelp) return;
386
387 panelp->cancel();
388}
389
390// Pass all of these messages to the currently visible sub tab.
391LLString LLPanelGroupRoles::getHelpText() const
392{
393 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
394 if (panelp)
395 {
396 return panelp->getHelpText();
397 }
398 else
399 {
400 return mHelpText;
401 }
402}
403
404void LLPanelGroupRoles::update(LLGroupChange gc)
405{
406 if (mGroupID.isNull()) return;
407
408 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
409 if (panelp)
410 {
411 panelp->update(gc);
412 }
413 else
414 {
415 llwarns << "LLPanelGroupRoles::update() -- No subtab to update!" << llendl;
416 }
417}
418
419void LLPanelGroupRoles::activate()
420{
421 // Start requesting member and role data if needed.
422 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
423 //if (!gdatap || mFirstUse)
424 {
425 // Check member data.
426
427 if (!gdatap || !gdatap->isMemberDataComplete() )
428 {
429 gGroupMgr->sendGroupMembersRequest(mGroupID);
430 }
431
432 // Check role data.
433 if (!gdatap || !gdatap->isRoleDataComplete() )
434 {
435 // Mildly hackish - clear all pending changes
436 cancel();
437
438 gGroupMgr->sendGroupRoleDataRequest(mGroupID);
439 }
440
441 // Check role-member mapping data.
442 if (!gdatap || !gdatap->isRoleMemberDataComplete() )
443 {
444 gGroupMgr->sendGroupRoleMembersRequest(mGroupID);
445 }
446
447 // Need this to get base group member powers
448 if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
449 {
450 gGroupMgr->sendGroupPropertiesRequest(mGroupID);
451 }
452
453 mFirstUse = FALSE;
454 }
455
456 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
457 if (panelp) panelp->activate();
458}
459
460void LLPanelGroupRoles::deactivate()
461{
462 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
463 if (panelp) panelp->deactivate();
464}
465
466bool LLPanelGroupRoles::needsApply(LLString& mesg)
467{
468 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
469 if (!panelp) return false;
470
471 return panelp->needsApply(mesg);
472}
473
474BOOL LLPanelGroupRoles::hasModal()
475{
476 if (mHasModal) return TRUE;
477
478 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
479 if (!panelp) return FALSE;
480
481 return panelp->hasModal();
482}
483
484// PanelGroupTab observer trigger
485void LLPanelGroupRoles::tabChanged()
486{
487 notifyObservers();
488}
489
490////////////////////////////
491// LLPanelGroupSubTab
492////////////////////////////
493LLPanelGroupSubTab::LLPanelGroupSubTab(const std::string& name, const LLUUID& group_id)
494: LLPanelGroupTab(name, group_id),
495 mHeader(NULL),
496 mFooter(NULL),
497 mSearchLineEditor(NULL),
498 mSearchButton(NULL),
499 mShowAllButton(NULL)
500{
501}
502
503LLPanelGroupSubTab::~LLPanelGroupSubTab()
504{
505}
506
507BOOL LLPanelGroupSubTab::postBuild()
508{
509 // Hook up the search widgets.
510 bool recurse = true;
511 mSearchLineEditor = (LLLineEditor*) getChildByName("search_text", recurse);
512
513 if (!mSearchLineEditor) return FALSE;
514 mSearchLineEditor->setKeystrokeCallback(onSearchKeystroke);
515 mSearchLineEditor->setCallbackUserData(this);
516
517 mSearchButton = (LLButton*) getChildByName("search_button", recurse);
518
519 if (!mSearchButton) return FALSE;
520 mSearchButton->setClickedCallback(onClickSearch);
521 mSearchButton->setCallbackUserData(this);
522 mSearchButton->setEnabled(FALSE);
523
524 mShowAllButton = (LLButton*) getChildByName("show_all_button", recurse);
525
526 if (!mShowAllButton) return FALSE;
527 mShowAllButton->setClickedCallback(onClickShowAll);
528 mShowAllButton->setCallbackUserData(this);
529 mShowAllButton->setEnabled(FALSE);
530
531 // Get icons for later use.
532 mActionIcons.clear();
533
534 bool no_recurse = false;
535
536 LLIconCtrl* icon = (LLIconCtrl*) getChildByName("power_folder_icon",no_recurse);
537 if (icon && icon->getImage().notNull())
538 {
539 mActionIcons["folder"] = icon->getImage();
540 removeChild(icon);
541 }
542
543 icon = (LLIconCtrl*) getChildByName("power_all_have_icon",no_recurse);
544 if (icon && icon->getImage().notNull())
545 {
546 mActionIcons["full"] = icon->getImage();
547 removeChild(icon);
548 }
549
550 icon = (LLIconCtrl*) getChildByName("power_partial_icon",no_recurse);
551 if (icon && icon->getImage().notNull())
552 {
553 mActionIcons["partial"] = icon->getImage();
554 removeChild(icon);
555 }
556
557 return LLPanelGroupTab::postBuild();
558}
559
560// static
561void LLPanelGroupSubTab::onSearchKeystroke(LLLineEditor* caller, void* user_data)
562{
563 LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
564 self->handleSearchKeystroke(caller);
565}
566
567void LLPanelGroupSubTab::handleSearchKeystroke(LLLineEditor* caller)
568{
569 if (caller->getText().size())
570 {
571 setDefaultBtn( mSearchButton );
572 mSearchButton->setEnabled(TRUE);
573 }
574 else
575 {
576 setDefaultBtn( NULL );
577 mSearchButton->setEnabled(FALSE);
578 }
579}
580
581// static
582void LLPanelGroupSubTab::onClickSearch(void* user_data)
583{
584 LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
585 self->handleClickSearch();
586}
587
588void LLPanelGroupSubTab::handleClickSearch()
589{
590 lldebugs << "LLPanelGroupSubTab::handleClickSearch()" << llendl;
591
592 if (0 == mSearchLineEditor->getText().size())
593 {
594 // No search text. (This shouldn't happen... the search button should have been disabled).
595 llwarns << "handleClickSearch with no search text!" << llendl;
596 mSearchButton->setEnabled(FALSE);
597 return;
598 }
599
600 setSearchFilter( mSearchLineEditor->getText() );
601 mShowAllButton->setEnabled(TRUE);
602}
603
604// static
605void LLPanelGroupSubTab::onClickShowAll(void* user_data)
606{
607 LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
608 self->handleClickShowAll();
609}
610
611void LLPanelGroupSubTab::handleClickShowAll()
612{
613 lldebugs << "LLPanelGroupSubTab::handleClickShowAll()" << llendl;
614 setSearchFilter( LLString::null );
615 mShowAllButton->setEnabled(FALSE);
616}
617
618void LLPanelGroupSubTab::setSearchFilter(const LLString& filter)
619{
620 lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
621 mSearchFilter = filter;
622 LLString::toLower(mSearchFilter);
623 update(GC_ALL);
624}
625
626void LLPanelGroupSubTab::activate()
627{
628 lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
629 setOthersVisible(TRUE);
630}
631
632void LLPanelGroupSubTab::deactivate()
633{
634 lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
635 setOthersVisible(FALSE);
636}
637
638void LLPanelGroupSubTab::setOthersVisible(BOOL b)
639{
640 if (mHeader)
641 {
642 mHeader->setVisible( b );
643 }
644 else
645 {
646 llwarns << "LLPanelGroupSubTab missing header!" << llendl;
647 }
648
649 if (mFooter)
650 {
651 mFooter->setVisible( b );
652 }
653 else
654 {
655 llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
656 }
657}
658
659bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
660{
661 // If the search filter is empty, everything passes.
662 if (mSearchFilter.empty()) return true;
663
664 LLString::toLower(action);
665 std::string::size_type match = action.find(mSearchFilter);
666
667 if (std::string::npos == match)
668 {
669 // not found
670 return false;
671 }
672 else
673 {
674 return true;
675 }
676}
677
678void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
679 U64 allowed_by_some,
680 U64 allowed_by_all,
681 icon_map_t& icons,
682 void (*commit_callback)(LLUICtrl*,void*),
683 BOOL show_all,
684 BOOL filter,
685 BOOL is_owner_role)
686{
687 if (gGroupMgr->mRoleActionSets.empty())
688 {
689 llwarns << "Can't build action list - no actions found." << llendl;
690 return;
691 }
692
693 std::vector<LLRoleActionSet*>::iterator ras_it = gGroupMgr->mRoleActionSets.begin();
694 std::vector<LLRoleActionSet*>::iterator ras_end = gGroupMgr->mRoleActionSets.end();
695
696 for ( ; ras_it != ras_end; ++ras_it)
697 {
698 buildActionCategory(ctrl,
699 allowed_by_some,
700 allowed_by_all,
701 (*ras_it),
702 icons,
703 commit_callback,
704 show_all,
705 filter,
706 is_owner_role);
707 }
708}
709
710void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
711 U64 allowed_by_some,
712 U64 allowed_by_all,
713 LLRoleActionSet* action_set,
714 icon_map_t& icons,
715 void (*commit_callback)(LLUICtrl*,void*),
716 BOOL show_all,
717 BOOL filter,
718 BOOL is_owner_role)
719{
720 lldebugs << "Building role list for: " << action_set->mActionSetData->mName << llendl;
721 // See if the allow mask matches anything in this category.
722 if (show_all || (allowed_by_some & action_set->mActionSetData->mPowerBit))
723 {
724 // List all the actions in this category that at least some members have.
725 LLSD row;
726
727 row["columns"][0]["column"] = "icon";
728 icon_map_t::iterator iter = icons.find("folder");
729 if (iter != icons.end())
730 {
731 row["columns"][0]["type"] = "icon";
732 row["columns"][0]["value"] = (*iter).second;
733 }
734
735 row["columns"][1]["column"] = "action";
736 row["columns"][1]["value"] = action_set->mActionSetData->mName;
737 row["columns"][1]["font-style"] = "BOLD";
738
739 LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
740
741 bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
742
743 std::vector<LLRoleAction*>::iterator ra_it = action_set->mActions.begin();
744 std::vector<LLRoleAction*>::iterator ra_end = action_set->mActions.end();
745
746 bool items_match_filter = false;
747 BOOL can_change_actions = (!is_owner_role && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CHANGE_ACTIONS));
748
749 for ( ; ra_it != ra_end; ++ra_it)
750 {
751 // See if anyone has these action.
752 if (!show_all && !(allowed_by_some & (*ra_it)->mPowerBit))
753 {
754 continue;
755 }
756
757 // See if we are filtering out these actions
758 // If we aren't using filters, category_matches_filter will be true.
759 if (!category_matches_filter
760 && !matchesActionSearchFilter((*ra_it)->mDescription))
761 {
762 continue;
763 }
764
765 items_match_filter = true;
766
767 // See if everyone has these actions.
768 bool show_full_strength = false;
769 if ( (allowed_by_some & (*ra_it)->mPowerBit) == (allowed_by_all & (*ra_it)->mPowerBit) )
770 {
771 show_full_strength = true;
772 }
773
774 LLSD row;
775
776 S32 column_index = 0;
777 row["columns"][column_index]["column"] = "icon";
778 ++column_index;
779
780
781 S32 check_box_index = -1;
782 if (commit_callback)
783 {
784 row["columns"][column_index]["column"] = "checkbox";
785 row["columns"][column_index]["type"] = "checkbox";
786 row["columns"][column_index]["value"] = (*ra_it)->mName;
787 check_box_index = column_index;
788 ++column_index;
789 }
790 else
791 {
792 if (show_full_strength)
793 {
794 icon_map_t::iterator iter = icons.find("full");
795 if (iter != icons.end())
796 {
797 row["columns"][column_index]["column"] = "checkbox";
798 row["columns"][column_index]["type"] = "icon";
799 row["columns"][column_index]["value"] = (*iter).second;
800 ++column_index;
801 }
802 }
803 else
804 {
805 icon_map_t::iterator iter = icons.find("partial");
806 if (iter != icons.end())
807 {
808 row["columns"][column_index]["column"] = "checkbox";
809 row["columns"][column_index]["type"] = "icon";
810 row["columns"][column_index]["value"] = (*iter).second;
811 ++column_index;
812 }
813 row["enabled"] = false;
814 }
815 }
816
817 row["columns"][column_index]["column"] = "action";
818 row["columns"][column_index]["value"] = (*ra_it)->mDescription;
819 row["columns"][column_index]["font"] = "SANSSERIFSMALL";
820
821 LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
822
823 if (-1 != check_box_index)
824 {
825 // Extract the checkbox that was created.
826 LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(check_box_index);
827 LLCheckBoxCtrl* check = check_cell->getCheckBox();
828 check->setEnabled(can_change_actions);
829 check->setCommitCallback(commit_callback);
830 check->setCallbackUserData(ctrl->getCallbackUserData());
831 check->setToolTip( check->getLabel() );
832
833 if (show_all)
834 {
835 check->setTentative(FALSE);
836 if (allowed_by_some & (*ra_it)->mPowerBit)
837 {
838 check->set(TRUE);
839 }
840 else
841 {
842 check->set(FALSE);
843 }
844 }
845 else
846 {
847 check->set(TRUE);
848 if (show_full_strength)
849 {
850 check->setTentative(FALSE);
851 }
852 else
853 {
854 check->setTentative(TRUE);
855 }
856 }
857 }
858 }
859
860 if (!items_match_filter)
861 {
862 S32 title_index = ctrl->getItemIndex(title_row);
863 ctrl->deleteSingleItem(title_index);
864 }
865 }
866}
867
868void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
869{
870 if (mFooter)
871 {
872 mFooter->setAllChildrenEnabled(enable);
873 }
874}
875
876////////////////////////////
877// LLPanelGroupMembersSubTab
878////////////////////////////
879
880// static
881void* LLPanelGroupMembersSubTab::createTab(void* data)
882{
883 LLUUID* group_id = static_cast<LLUUID*>(data);
884 return new LLPanelGroupMembersSubTab("panel group members sub tab", *group_id);
885}
886
887LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab(const std::string& name, const LLUUID& group_id)
888: LLPanelGroupSubTab(name, group_id),
889 mMembersList(NULL),
890 mAssignedRolesList(NULL),
891 mAllowedActionsList(NULL),
892 mChanged(FALSE),
893 mPendingMemberUpdate(FALSE),
894 mHasMatch(FALSE),
895 mNumOwnerAdditions(0)
896{
897}
898
899LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
900{
901}
902
903BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
904{
905 // Upcast parent so we can ask it for sibling controls.
906 LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
907
908 // Look recursively from the parent to find all our widgets.
909 bool recurse = true;
910 mHeader = (LLPanel*) parent->getChildByName("members_header", recurse);
911 mFooter = (LLPanel*) parent->getChildByName("members_footer", recurse);
912
913 mMembersList = (LLNameListCtrl*) parent->getChildByName("member_list", recurse);
914 mAssignedRolesList = (LLScrollListCtrl*) parent->getChildByName("member_assigned_roles", recurse);
915 mAllowedActionsList = (LLScrollListCtrl*) parent->getChildByName("member_allowed_actions", recurse);
916
917 if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE;
918
919 // We want to be notified whenever a member is selected.
920 mMembersList->setCallbackUserData(this);
921 mMembersList->setCommitOnSelectionChange(TRUE);
922 mMembersList->setCommitCallback(onMemberSelect);
923 // Show the member's profile on double click.
924 mMembersList->setDoubleClickCallback(onMemberDoubleClick);
925
926 LLButton* button = (LLButton*) parent->getChildByName("member_invite", recurse);
927 if ( button )
928 {
929 button->setClickedCallback(onInviteMember);
930 button->setCallbackUserData(this);
931 button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
932 }
933
934 mEjectBtn = (LLButton*) parent->getChildByName("member_eject", recurse);
935 if ( mEjectBtn )
936 {
937 mEjectBtn->setClickedCallback(onEjectMembers);
938 mEjectBtn->setCallbackUserData(this);
939 mEjectBtn->setEnabled(FALSE);
940 }
941
942 return TRUE;
943}
944
945
946// static
947void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
948{
949 LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
950 self->handleMemberSelect();
951}
952
953void LLPanelGroupMembersSubTab::handleMemberSelect()
954{
955 lldebugs << "LLPanelGroupMembersSubTab::handleMemberSelect" << llendl;
956
957 mAssignedRolesList->deleteAllItems();
958 mAllowedActionsList->deleteAllItems();
959
960 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
961 if (!gdatap)
962 {
963 llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() "
964 << "-- No group data!" << llendl;
965 return;
966 }
967
968 // Check if there is anything selected.
969 std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
970 if (selection.empty()) return;
971
972 // Build a vector of all selected members, and gather allowed actions.
973 std::vector<LLUUID> selected_members;
974 U64 allowed_by_all = 0xffffffffffffLL;
975 U64 allowed_by_some = 0;
976
977 std::vector<LLScrollListItem*>::iterator itor;
978 for (itor = selection.begin();
979 itor != selection.end(); ++itor)
980 {
981 selected_members.push_back( (*itor)->getUUID() );
982 // Get this member's power mask including any unsaved changes
983
984 U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
985
986 allowed_by_all &= powers;
987 allowed_by_some |= powers;
988 }
989 std::sort(selected_members.begin(), selected_members.end());
990
991 //////////////////////////////////
992 // Build the allowed actions list.
993 //////////////////////////////////
994 buildActionsList(mAllowedActionsList,
995 allowed_by_some,
996 allowed_by_all,
997 mActionIcons,
998 NULL,
999 FALSE,
1000 FALSE,
1001 FALSE);
1002
1003 //////////////////////////////////
1004 // Build the assigned roles list.
1005 //////////////////////////////////
1006 // Add each role to the assigned roles list.
1007 LLGroupMgrGroupData::role_iter iter = gdatap->mRoles.begin();
1008 LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
1009
1010 BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
1011 GP_MEMBER_EJECT);
1012 BOOL member_is_owner = FALSE;
1013
1014 for( ; iter != end; ++iter)
1015 {
1016 // Count how many selected users are in this role.
1017 const LLUUID& role_id = iter->first;
1018 LLGroupRoleData* group_role_data = iter->second;
1019
1020 if (group_role_data)
1021 {
1022 const BOOL needs_sort = FALSE;
1023 S32 count = group_role_data->getMembersInRole(
1024 selected_members, needs_sort);
1025 //check if the user has permissions to assign/remove
1026 //members to/from the role (but the ability to add/remove
1027 //should only be based on the "saved" changes to the role
1028 //not in the temp/meta data. -jwolk
1029 BOOL cb_enable = ( (count > 0) ?
1030 agentCanRemoveFromRole(mGroupID, role_id) :
1031 agentCanAddToRole(mGroupID, role_id) );
1032
1033
1034 // Owner role has special enabling permissions for removal.
1035 if (cb_enable && (count > 0) && role_id == gdatap->mOwnerRole)
1036 {
1037 // Check if any owners besides this agent are selected.
1038 std::vector<LLUUID>::const_iterator member_iter;
1039 std::vector<LLUUID>::const_iterator member_end =
1040 selected_members.end();
1041 for (member_iter = selected_members.begin();
1042 member_iter != member_end;
1043 ++member_iter)
1044 {
1045 // Don't count the agent.
1046 if ((*member_iter) == gAgent.getID()) continue;
1047
1048 // Look up the member data.
1049 LLGroupMgrGroupData::member_iter mi =
1050 gdatap->mMembers.find((*member_iter));
1051 if (mi == gdatap->mMembers.end()) continue;
1052 LLGroupMemberData* member_data = (*mi).second;
1053 // Is the member an owner?
1054 if ( member_data->isInRole(gdatap->mOwnerRole) )
1055 {
1056 // Can't remove other owners.
1057 cb_enable = FALSE;
1058 break;
1059 }
1060 }
1061 }
1062
1063 //now see if there are any role changes for the selected
1064 //members and remember to include them
1065 std::vector<LLUUID>::iterator sel_mem_iter = selected_members.begin();
1066 for (; sel_mem_iter != selected_members.end(); sel_mem_iter++)
1067 {
1068 LLRoleMemberChangeType type;
1069 if ( getRoleChangeType(*sel_mem_iter, role_id, type) )
1070 {
1071 if ( type == RMC_ADD ) count++;
1072 else if ( type == RMC_REMOVE ) count--;
1073 }
1074 }
1075
1076 // If anyone selected is in any role besides 'Everyone' then they can't be ejected.
1077 if (role_id.notNull() && (count > 0))
1078 {
1079 can_eject_members = FALSE;
1080 if (role_id == gdatap->mOwnerRole)
1081 {
1082 member_is_owner = TRUE;
1083 }
1084 }
1085
1086 LLRoleData rd;
1087 if (gdatap->getRoleData(role_id,rd))
1088 {
1089 std::ostringstream label;
1090 label << rd.mRoleName;
1091 // Don't bother showing a count, if there is only 0 or 1.
1092 if (count > 1)
1093 {
1094 label << ": " << count ;
1095 }
1096
1097 LLSD row;
1098 row["id"] = role_id;
1099
1100 row["columns"][0]["column"] = "checkbox";
1101 row["columns"][0]["type"] = "checkbox";
1102
1103 row["columns"][1]["column"] = "role";
1104 row["columns"][1]["value"] = label.str();
1105
1106 if (row["id"].asUUID().isNull())
1107 {
1108 // This is the everyone role, you can't take people out of the everyone role!
1109 row["enabled"] = false;
1110 }
1111
1112 LLScrollListItem* item = mAssignedRolesList->addElement(row);
1113
1114 // Extract the checkbox that was created.
1115 LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(0);
1116 LLCheckBoxCtrl* check = check_cell->getCheckBox();
1117 check->setCommitCallback(onRoleCheck);
1118 check->setCallbackUserData(this);
1119 check->set( count > 0 );
1120 check->setTentative(0 != count && selected_members.size() != count);
1121
1122 //NOTE: as of right now a user can break the group
1123 //by removing himself from a role if he is the
1124 //last owner. We should check for this special case
1125 // -jwolk
1126 check->setEnabled(cb_enable);
1127 }
1128 }
1129 else
1130 {
1131 // This could happen if changes are not synced right on sub-panel change.
1132 llwarns << "No group role data for " << iter->second << llendl;
1133 }
1134 }
1135 mAssignedRolesList->setEnabled(TRUE);
1136
1137 if (!can_eject_members && !member_is_owner)
1138 {
1139 // Maybe we can eject them because we are an owner...
1140 LLGroupMgrGroupData::member_iter mi = gdatap->mMembers.find(gAgent.getID());
1141 if (mi != gdatap->mMembers.end())
1142 {
1143 LLGroupMemberData* member_data = (*mi).second;
1144
1145 if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
1146 {
1147 can_eject_members = TRUE;
1148 }
1149 }
1150 }
1151
1152 mEjectBtn->setEnabled(can_eject_members);
1153}
1154
1155// static
1156void LLPanelGroupMembersSubTab::onMemberDoubleClick(void* user_data)
1157{
1158 LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
1159 self->handleMemberDoubleClick();
1160}
1161
1162//static
1163void LLPanelGroupMembersSubTab::onInviteMember(void *userdata)
1164{
1165 LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
1166
1167 if ( selfp )
1168 {
1169 selfp->handleInviteMember();
1170 }
1171}
1172
1173void LLPanelGroupMembersSubTab::handleInviteMember()
1174{
1175 LLFloaterGroupInvite::showForGroup(mGroupID);
1176}
1177
1178void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
1179{
1180 LLPanelGroupMembersSubTab* selfp = (LLPanelGroupMembersSubTab*) userdata;
1181
1182 if ( selfp )
1183 {
1184 selfp->handleEjectMembers();
1185 }
1186}
1187
1188void LLPanelGroupMembersSubTab::handleEjectMembers()
1189{
1190 //send down an eject message
1191 std::vector<LLUUID> selected_members;
1192
1193 std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
1194 if (selection.empty()) return;
1195
1196 std::vector<LLScrollListItem*>::iterator itor;
1197 for (itor = selection.begin() ;
1198 itor != selection.end(); ++itor)
1199 {
1200 selected_members.push_back((*itor)->getUUID());
1201 }
1202
1203 mMembersList->deleteSelectedItems();
1204
1205 gGroupMgr->sendGroupMemberEjects(mGroupID,
1206 selected_members);
1207}
1208
1209void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
1210 LLRoleMemberChangeType type)
1211{
1212 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1213 if (!gdatap) return;
1214
1215 //add that the user is requesting to change the roles for selected
1216 //members
1217 U64 powers_all_have = 0xffffffffffffLL;
1218 U64 powers_some_have = 0;
1219
1220 BOOL is_owner_role = ( gdatap->mOwnerRole == role_id );
1221 LLUUID member_id;
1222
1223
1224 member_role_change_iter member_end = mMemberRoleChangeData.end();
1225 member_role_change_iter member;
1226 role_change_data_map_t *role_change_datap;
1227 role_change_data_map_t::iterator role_end;
1228 role_change_data_map_t::iterator role;
1229
1230 std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
1231 if (selection.empty()) return;
1232
1233 std::vector<LLScrollListItem*>::iterator itor;
1234 for (itor = selection.begin() ;
1235 itor != selection.end(); ++itor)
1236 {
1237 member_id = (*itor)->getUUID();
1238
1239 //see if we requested a change for this member before
1240 member = mMemberRoleChangeData.find(member_id);
1241 if ( member != member_end )
1242 {
1243 //this member had previously had their role data changed
1244 //so grab it
1245 role_change_datap = (*member).second;
1246 }
1247 else
1248 {
1249 role_change_datap = new role_change_data_map_t;
1250 mMemberRoleChangeData[member_id] = role_change_datap;
1251 }
1252
1253 //now check to see if the selected group member
1254 //had changed his association with the selected role before
1255 role_end = role_change_datap->end();
1256 role = role_change_datap->find(role_id);
1257
1258 if ( role != role_end )
1259 {
1260 //see if the new change type cancels out the previous change
1261 if (role->second != type)
1262 {
1263 role_change_datap->erase(role_id);
1264 if ( is_owner_role ) mNumOwnerAdditions--;
1265 }
1266 //else do nothing
1267
1268 if ( role_change_datap->empty() )
1269 {
1270 //the current member now has no role changes
1271 //so erase the role change and erase the member's entry
1272 delete role_change_datap;
1273 role_change_datap = NULL;
1274
1275 mMemberRoleChangeData.erase(member_id);
1276 }
1277 }
1278 else
1279 {
1280 //a previously unchanged role is being changed
1281 (*role_change_datap)[role_id] = type;
1282 if ( is_owner_role && type == RMC_ADD ) mNumOwnerAdditions++;
1283 }
1284
1285 //we need to calculate what powers the selected members
1286 //have (including the role changes we're making)
1287 //so that we can rebuild the action list
1288 U64 new_powers = getAgentPowersBasedOnRoleChanges(member_id);
1289
1290 powers_all_have &= new_powers;
1291 powers_some_have |= new_powers;
1292 }
1293
1294
1295 mChanged = !mMemberRoleChangeData.empty();
1296 notifyObservers();
1297
1298 //alrighty now we need to update the actions list
1299 //to reflect the changes
1300 mAllowedActionsList->deleteAllItems();
1301 buildActionsList(mAllowedActionsList,
1302 powers_some_have,
1303 powers_all_have,
1304 mActionIcons,
1305 NULL,
1306 FALSE,
1307 FALSE,
1308 FALSE);
1309}
1310
1311
1312// static
1313void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
1314{
1315 LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
1316 LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl);
1317 if (!check_box || !self) return;
1318
1319
1320 LLUUID role_id = self->mAssignedRolesList->getFirstSelected()->getUUID();
1321 LLRoleMemberChangeType change_type = (check_box->get() ?
1322 RMC_ADD :
1323 RMC_REMOVE);
1324
1325 self->handleRoleCheck(role_id, change_type);
1326}
1327
1328void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
1329{
1330 LLScrollListItem* selected = mMembersList->getFirstSelected();
1331 if (selected)
1332 {
1333 LLFloaterAvatarInfo::showFromDirectory( selected->getUUID() );
1334 }
1335}
1336
1337void LLPanelGroupMembersSubTab::activate()
1338{
1339 LLPanelGroupSubTab::activate();
1340
1341 update(GC_ALL);
1342}
1343
1344void LLPanelGroupMembersSubTab::deactivate()
1345{
1346 LLPanelGroupSubTab::deactivate();
1347}
1348
1349bool LLPanelGroupMembersSubTab::needsApply(LLString& mesg)
1350{
1351 return mChanged;
1352}
1353
1354void LLPanelGroupMembersSubTab::cancel()
1355{
1356 if ( mChanged )
1357 {
1358 std::for_each(mMemberRoleChangeData.begin(),
1359 mMemberRoleChangeData.end(),
1360 DeletePairedPointer());
1361 mMemberRoleChangeData.clear();
1362
1363 mChanged = FALSE;
1364 notifyObservers();
1365 }
1366}
1367
1368bool LLPanelGroupMembersSubTab::apply(LLString& mesg)
1369{
1370 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1371 if (!gdatap)
1372 {
1373 llwarns << "Unable to get group data for group " << mGroupID << llendl;
1374
1375 mesg.assign("Unable to save member data. Try again later.");
1376 return false;
1377 }
1378
1379 if (mChanged)
1380 {
1381 //figure out if we are somehow adding an owner or not and alert
1382 //the user...possibly make it ignorable
1383 if ( mNumOwnerAdditions > 0 )
1384 {
1385 LLRoleData rd;
1386 LLStringBase<char>::format_map_t args;
1387
1388 if ( gdatap->getRoleData(gdatap->mOwnerRole, rd) )
1389 {
1390 mHasModal = TRUE;
1391 args["[ROLE_NAME]"] = rd.mRoleName;
1392 gViewerWindow->alertXml("AddGroupOwnerWarning",
1393 args,
1394 addOwnerCB,
1395 this);
1396 }
1397 else
1398 {
1399 llwarns << "Unable to get role information for the owner role in group " << mGroupID << llendl;
1400
1401 mesg.assign("Unable to retried specific group information. Try again later");
1402 return false;
1403 }
1404
1405 }
1406 else
1407 {
1408 applyMemberChanges();
1409 }
1410 }
1411
1412 return true;
1413}
1414
1415//static
1416void LLPanelGroupMembersSubTab::addOwnerCB(S32 option, void* data)
1417{
1418 LLPanelGroupMembersSubTab* self = (LLPanelGroupMembersSubTab*) data;
1419
1420 if (!self) return;
1421
1422 self->mHasModal = FALSE;
1423
1424 if (0 == option)
1425 {
1426 // User clicked "Yes"
1427 self->applyMemberChanges();
1428 }
1429}
1430
1431void LLPanelGroupMembersSubTab::applyMemberChanges()
1432{
1433 //sucks to do a find again here, but it is in constant time, so, could
1434 //be worse
1435 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1436 if (!gdatap)
1437 {
1438 llwarns << "Unable to get group data for group " << mGroupID << llendl;
1439 return;
1440 }
1441
1442 //we need to add all of the changed roles data
1443 //for each member whose role changed
1444 member_role_change_iter member_end = mMemberRoleChangeData.end();
1445 member_role_change_iter member = mMemberRoleChangeData.begin();
1446
1447 for (; member != member_end; member++)
1448 {
1449 role_change_data_map_t::iterator role_end = member->second->end();
1450 role_change_data_map_t::iterator role = member->second->begin();
1451
1452 for (; role != role_end; role++)
1453 {
1454 gdatap->changeRoleMember(role->first, //role_id
1455 member->first, //member_id
1456 role->second); //add/remove
1457 }
1458
1459 member->second->clear();
1460 delete member->second;
1461 }
1462 mMemberRoleChangeData.clear();
1463
1464 gGroupMgr->sendGroupRoleMemberChanges(mGroupID);
1465 //force a UI update
1466 handleMemberSelect();
1467
1468 mChanged = FALSE;
1469 mNumOwnerAdditions = 0;
1470 notifyObservers();
1471}
1472
1473bool LLPanelGroupMembersSubTab::matchesSearchFilter(char* first, char* last)
1474{
1475 // If the search filter is empty, everything passes.
1476 if (mSearchFilter.empty()) return true;
1477
1478 // Create a full name, and compare it to the search filter.
1479 LLString fullname;
1480 fullname.assign(first);
1481 fullname.append(1, ' ');
1482 fullname.append(last);
1483 LLString::toLower(fullname);
1484
1485 std::string::size_type match = fullname.find(mSearchFilter);
1486
1487 if (std::string::npos == match)
1488 {
1489 // not found
1490 return false;
1491 }
1492 else
1493 {
1494 return true;
1495 }
1496}
1497
1498U64 LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges(const LLUUID& agent_id)
1499{
1500 //we loop over all of the changes
1501 //if we are adding a role, then we simply add the role's powers
1502 //if we are removing a role, we store that role id away
1503 //and then we have to build the powers up bases on the roles the agent
1504 //is in
1505 member_role_change_iter member_end = mMemberRoleChangeData.end();
1506 member_role_change_iter member;
1507 role_change_data_map_t *role_change_datap = NULL;
1508 role_change_data_map_t::iterator role_end;
1509 role_change_data_map_t::iterator role;
1510
1511 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1512 if (!gdatap)
1513 {
1514 llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No group data!" << llendl;
1515 return GP_NO_POWERS;
1516 }
1517
1518 LLGroupMemberData* member_data = gdatap->mMembers[agent_id];
1519 if ( !member_data )
1520 {
1521 llwarns << "LLPanelGroupMembersSubTab::getAgentPowersBasedOnRoleChanges() -- No member data for member with UUID " << agent_id << llendl;
1522 return GP_NO_POWERS;
1523 }
1524
1525 //see if there are unsaved role changes for this agent
1526 member = mMemberRoleChangeData.find(agent_id);
1527 if ( member != member_end )
1528 {
1529 //this member has unsaved role changes
1530 //so grab them
1531 role_change_datap = (*member).second;
1532 }
1533
1534 U64 new_powers = GP_NO_POWERS;
1535
1536 if ( role_change_datap )
1537 {
1538 std::vector<LLUUID> roles_to_be_removed;
1539
1540 role_end = role_change_datap->end();
1541 role = role_change_datap->begin();
1542
1543 for (; role != role_end; role++)
1544 {
1545 if ( role->second == RMC_ADD )
1546 new_powers |= gdatap->getRolePowers(role->first);
1547 else
1548 {
1549 roles_to_be_removed.push_back(role->first);
1550 }
1551 }
1552
1553 //loop over the member's current roles, summing up
1554 //the powers (not including the role we are removing)
1555 std::map<LLUUID,LLGroupRoleData*>::iterator current_role =
1556 member_data->roleBegin();
1557 std::map<LLUUID,LLGroupRoleData*>::iterator end_role =
1558 member_data->roleEnd();
1559
1560 for (; current_role != end_role; current_role++)
1561 {
1562 bool role_in_remove_list =
1563 (std::find(roles_to_be_removed.begin(),
1564 roles_to_be_removed.end(),
1565 current_role->second->getID()) !=
1566 roles_to_be_removed.end());
1567
1568 if ( !role_in_remove_list )
1569 {
1570 new_powers |=
1571 current_role->second->getRoleData().mRolePowers;
1572 }
1573 }
1574 }
1575 else
1576 {
1577 //there are no changes for this member
1578 //the member's powers are just the ones stored in the group
1579 //manager
1580 new_powers = member_data->getAgentPowers();
1581 }
1582
1583 return new_powers;
1584}
1585
1586//If there is no change, returns false be sure to verify
1587//that there is a role change before attempting to get it or else
1588//the data will make no sense. Stores the role change type
1589bool LLPanelGroupMembersSubTab::getRoleChangeType(const LLUUID& member_id,
1590 const LLUUID& role_id,
1591 LLRoleMemberChangeType& type)
1592{
1593 member_role_change_iter member_changes_iter;
1594 role_change_data_map_t::iterator role_changes_iter;
1595
1596 member_changes_iter = mMemberRoleChangeData.find(member_id);
1597 if ( member_changes_iter != mMemberRoleChangeData.end() )
1598 {
1599 role_changes_iter = member_changes_iter->second->find(role_id);
1600 if ( role_changes_iter != member_changes_iter->second->end() )
1601 {
1602 type = role_changes_iter->second;
1603 return true;
1604 }
1605 }
1606
1607 return false;
1608}
1609
1610void LLPanelGroupMembersSubTab::draw()
1611{
1612 LLPanelGroupSubTab::draw();
1613
1614 if (mPendingMemberUpdate)
1615 {
1616 updateMembers();
1617 }
1618}
1619
1620void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
1621{
1622 if (mGroupID.isNull()) return;
1623
1624 if ( GC_TITLES == gc || GC_PROPERTIES == gc )
1625 {
1626 // Don't care about title or general group properties updates.
1627 return;
1628 }
1629
1630 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1631 if (!gdatap)
1632 {
1633 llwarns << "LLPanelGroupMembersSubTab::update() -- No group data!" << llendl;
1634 return;
1635 }
1636
1637 // Rebuild the members list.
1638 mMembersList->deleteAllItems();
1639
1640 // Wait for both all data to be retrieved before displaying anything.
1641 if ( gdatap->isMemberDataComplete()
1642 && gdatap->isRoleDataComplete()
1643 && gdatap->isRoleMemberDataComplete())
1644 {
1645 mMemberProgress = gdatap->mMembers.begin();
1646 mPendingMemberUpdate = TRUE;
1647 mHasMatch = FALSE;
1648 }
1649 else
1650 {
1651 // Build a string with info on retrieval progress.
1652 std::ostringstream retrieved;
1653 if ( !gdatap->isMemberDataComplete() )
1654 {
1655 // Still busy retreiving member list.
1656 retrieved << "Retrieving member list (" << gdatap->mMembers.size()
1657 << " / " << gdatap->mMemberCount << ")...";
1658 }
1659 else if( !gdatap->isRoleDataComplete() )
1660 {
1661 // Still busy retreiving role list.
1662 retrieved << "Retrieving role list (" << gdatap->mRoles.size()
1663 << " / " << gdatap->mRoleCount << ")...";
1664 }
1665 else // (!gdatap->isRoleMemberDataComplete())
1666 {
1667 // Still busy retreiving role/member mappings.
1668 retrieved << "Retrieving role member mappings...";
1669 }
1670 mMembersList->setEnabled(FALSE);
1671 mMembersList->addSimpleItem(retrieved.str());
1672 }
1673}
1674
1675void LLPanelGroupMembersSubTab::updateMembers()
1676{
1677 mPendingMemberUpdate = FALSE;
1678
1679 lldebugs << "LLPanelGroupMembersSubTab::updateMembers()" << llendl;
1680
1681 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1682 if (!gdatap)
1683 {
1684 llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
1685 return;
1686 }
1687
1688 // Make sure all data is still complete. Incomplete data
1689 // may occur if we refresh.
1690 if ( !gdatap->isMemberDataComplete()
1691 || !gdatap->isRoleDataComplete()
1692 || !gdatap->isRoleMemberDataComplete())
1693 {
1694 return;
1695 }
1696
1697 LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
1698
1699 char first[DB_FIRST_NAME_BUF_SIZE];
1700 char last[DB_LAST_NAME_BUF_SIZE];
1701 S32 i = 0;
1702 for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
1703 ++mMemberProgress, ++i)
1704 {
1705 if (!mMemberProgress->second)
1706 continue;
1707 // Do filtering on name if it is already in the cache.
1708 bool add_member = true;
1709
1710 if (gCacheName->getName(mMemberProgress->first, first, last))
1711 {
1712 if ( !matchesSearchFilter(first, last) )
1713 {
1714 add_member = false;
1715 }
1716 }
1717
1718 if (add_member)
1719 {
1720 // Build the donated tier string.
1721 std::ostringstream donated;
1722 donated << mMemberProgress->second->getContribution() << " sq. m.";
1723
1724 LLSD row;
1725 row["id"] = (*mMemberProgress).first;
1726
1727 row["columns"][0]["column"] = "name";
1728 // value is filled in by name list control
1729
1730 row["columns"][1]["column"] = "donated";
1731 row["columns"][1]["value"] = donated.str();
1732
1733 row["columns"][2]["column"] = "online";
1734 row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
1735 row["columns"][2]["font"] = "SANSSERIFSMALL";
1736
1737 mMembersList->addElement(row);//, ADD_SORTED);
1738 mHasMatch = TRUE;
1739 }
1740 }
1741
1742 if (mMemberProgress == end)
1743 {
1744 if (mHasMatch)
1745 {
1746 mMembersList->setEnabled(TRUE);
1747 }
1748 else
1749 {
1750 mMembersList->setEnabled(FALSE);
1751 mMembersList->addSimpleItem("No match.");
1752 }
1753 }
1754 else
1755 {
1756 mPendingMemberUpdate = TRUE;
1757 }
1758
1759 // This should clear the other two lists, since nothing is selected.
1760 handleMemberSelect();
1761}
1762
1763
1764
1765////////////////////////////
1766// LLPanelGroupRolesSubTab
1767////////////////////////////
1768
1769// static
1770void* LLPanelGroupRolesSubTab::createTab(void* data)
1771{
1772 LLUUID* group_id = static_cast<LLUUID*>(data);
1773 return new LLPanelGroupRolesSubTab("panel group roles sub tab", *group_id);
1774}
1775
1776LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab(const std::string& name, const LLUUID& group_id)
1777: LLPanelGroupSubTab(name, group_id), mHasRoleChange(FALSE)
1778{
1779}
1780
1781LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab()
1782{
1783}
1784
1785BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
1786{
1787 // Upcast parent so we can ask it for sibling controls.
1788 LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
1789
1790 // Look recursively from the parent to find all our widgets.
1791 bool recurse = true;
1792 mHeader = (LLPanel*) parent->getChildByName("roles_header", recurse);
1793 mFooter = (LLPanel*) parent->getChildByName("roles_footer", recurse);
1794
1795
1796 mRolesList = (LLScrollListCtrl*) parent->getChildByName("role_list", recurse);
1797 mAssignedMembersList = (LLNameListCtrl*) parent->getChildByName("role_assigned_members", recurse);
1798 mAllowedActionsList = (LLScrollListCtrl*) parent->getChildByName("role_allowed_actions", recurse);
1799
1800 mRoleName = (LLLineEditor*) parent->getChildByName("role_name", recurse);
1801 mRoleTitle = (LLLineEditor*) parent->getChildByName("role_title", recurse);
1802 mRoleDescription = (LLTextEditor*) parent->getChildByName("role_description", recurse);
1803
1804 mMemberVisibleCheck = (LLCheckBoxCtrl*) parent->getChildByName("role_visible_in_list", recurse);
1805
1806 if (!mRolesList || !mAssignedMembersList || !mAllowedActionsList
1807 || !mRoleName || !mRoleTitle || !mRoleDescription || !mMemberVisibleCheck)
1808 {
1809 llwarns << "ARG! element not found." << llendl;
1810 return FALSE;
1811 }
1812
1813 LLTextBox* txt = (LLTextBox*) parent->getChildByName("cant_delete_role", FALSE);
1814 if (txt)
1815 {
1816 mRemoveEveryoneTxt = txt->getText();
1817 parent->removeChild(txt);
1818 }
1819
1820 mCreateRoleButton =
1821 (LLButton*) parent->getChildByName("role_create", recurse);
1822 if ( mCreateRoleButton )
1823 {
1824 mCreateRoleButton->setCallbackUserData(this);
1825 mCreateRoleButton->setClickedCallback(onCreateRole);
1826 mCreateRoleButton->setEnabled(FALSE);
1827 }
1828
1829 mDeleteRoleButton =
1830 (LLButton*) parent->getChildByName("role_delete", recurse);
1831 if ( mDeleteRoleButton )
1832 {
1833 mDeleteRoleButton->setCallbackUserData(this);
1834 mDeleteRoleButton->setClickedCallback(onDeleteRole);
1835 mDeleteRoleButton->setEnabled(FALSE);
1836 }
1837
1838 mRolesList->setCommitOnSelectionChange(TRUE);
1839 mRolesList->setCallbackUserData(this);
1840 mRolesList->setCommitCallback(onRoleSelect);
1841
1842 mMemberVisibleCheck->setCallbackUserData(this);
1843 mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange);
1844
1845 mAllowedActionsList->setCommitOnSelectionChange(TRUE);
1846 mAllowedActionsList->setCallbackUserData(this);
1847
1848 mRoleName->setCommitOnFocusLost(TRUE);
1849 mRoleName->setCallbackUserData(this);
1850 mRoleName->setKeystrokeCallback(onPropertiesKey);
1851
1852 mRoleTitle->setCommitOnFocusLost(TRUE);
1853 mRoleTitle->setCallbackUserData(this);
1854 mRoleTitle->setKeystrokeCallback(onPropertiesKey);
1855
1856 mRoleDescription->setCommitOnFocusLost(TRUE);
1857 mRoleDescription->setCallbackUserData(this);
1858 mRoleDescription->setCommitCallback(onDescriptionCommit);
1859 mRoleDescription->setFocusReceivedCallback(onDescriptionCommit);
1860
1861 setFooterEnabled(FALSE);
1862
1863 return TRUE;
1864}
1865
1866void LLPanelGroupRolesSubTab::activate()
1867{
1868 LLPanelGroupSubTab::activate();
1869
1870 mRolesList->deselectAllItems();
1871 mAssignedMembersList->deleteAllItems();
1872 mAllowedActionsList->deleteAllItems();
1873 mRoleName->clear();
1874 mRoleDescription->clear();
1875 mRoleTitle->clear();
1876
1877 setFooterEnabled(FALSE);
1878
1879 mHasRoleChange = FALSE;
1880 update(GC_ALL);
1881}
1882
1883void LLPanelGroupRolesSubTab::deactivate()
1884{
1885 lldebugs << "LLPanelGroupRolesSubTab::deactivate()" << llendl;
1886
1887 LLPanelGroupSubTab::deactivate();
1888}
1889
1890bool LLPanelGroupRolesSubTab::needsApply(LLString& mesg)
1891{
1892 lldebugs << "LLPanelGroupRolesSubTab::needsApply()" << llendl;
1893
1894 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1895
1896 return (mHasRoleChange // Text changed in current role
1897 || (gdatap && gdatap->pendingRoleChanges())); // Pending role changes in the group
1898}
1899
1900bool LLPanelGroupRolesSubTab::apply(LLString& mesg)
1901{
1902 lldebugs << "LLPanelGroupRolesSubTab::apply()" << llendl;
1903
1904 saveRoleChanges();
1905 gGroupMgr->sendGroupRoleChanges(mGroupID);
1906
1907 notifyObservers();
1908
1909 return true;
1910}
1911
1912void LLPanelGroupRolesSubTab::cancel()
1913{
1914 mHasRoleChange = FALSE;
1915 gGroupMgr->cancelGroupRoleChanges(mGroupID);
1916
1917 notifyObservers();
1918}
1919
1920LLSD LLPanelGroupRolesSubTab::createRoleItem(const LLUUID& role_id,
1921 std::string name,
1922 std::string title,
1923 S32 members)
1924{
1925 LLSD row;
1926 row["id"] = role_id;
1927
1928 row["columns"][0]["column"] = "name";
1929 row["columns"][0]["value"] = name;
1930
1931 row["columns"][1]["column"] = "title";
1932 row["columns"][1]["value"] = title;
1933
1934 row["columns"][2]["column"] = "members";
1935 row["columns"][2]["value"] = members;
1936
1937 return row;
1938}
1939
1940bool LLPanelGroupRolesSubTab::matchesSearchFilter(std::string rolename, std::string roletitle)
1941{
1942 // If the search filter is empty, everything passes.
1943 if (mSearchFilter.empty()) return true;
1944
1945 LLString::toLower(rolename);
1946 LLString::toLower(roletitle);
1947 std::string::size_type match_name = rolename.find(mSearchFilter);
1948 std::string::size_type match_title = roletitle.find(mSearchFilter);
1949
1950 if ( (std::string::npos == match_name)
1951 && (std::string::npos == match_title))
1952 {
1953 // not found
1954 return false;
1955 }
1956 else
1957 {
1958 return true;
1959 }
1960}
1961
1962void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
1963{
1964 lldebugs << "LLPanelGroupRolesSubTab::update()" << llendl;
1965
1966 if (mGroupID.isNull()) return;
1967
1968 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
1969
1970 if (!gdatap || !gdatap->isRoleDataComplete())
1971 {
1972 gGroupMgr->sendGroupRoleDataRequest(mGroupID);
1973 }
1974 else
1975 {
1976 bool had_selection = false;
1977 LLUUID last_selected;
1978 if (mRolesList->getFirstSelected())
1979 {
1980 last_selected = mRolesList->getFirstSelected()->getUUID();
1981 had_selection = true;
1982 }
1983 mRolesList->deleteAllItems();
1984
1985 LLScrollListItem* item = NULL;
1986
1987 LLGroupMgrGroupData::role_iter rit = gdatap->mRoles.begin();
1988 LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
1989
1990 for ( ; rit != end; ++rit)
1991 {
1992 LLRoleData rd;
1993 if (gdatap->getRoleData((*rit).first,rd))
1994 {
1995 if (matchesSearchFilter(rd.mRoleName, rd.mRoleTitle))
1996 {
1997 // If this is the everyone role, then EVERYONE is in it.
1998 S32 members_in_role = (*rit).first.isNull() ? gdatap->mMembers.size() : (*rit).second->getTotalMembersInRole();
1999 LLSD row = createRoleItem((*rit).first,rd.mRoleName, rd.mRoleTitle, members_in_role);
2000 item = mRolesList->addElement(row, ((*rit).first.isNull()) ? ADD_TOP : ADD_BOTTOM, this);
2001 if (had_selection && ((*rit).first == last_selected))
2002 {
2003 item->setSelected(TRUE);
2004 }
2005 }
2006 }
2007 else
2008 {
2009 llwarns << "LLPanelGroupRolesSubTab::update() No role data for role " << (*rit).first << llendl;
2010 }
2011 }
2012
2013 mRolesList->sortByColumn("name", TRUE);
2014
2015 if ( (gdatap->mRoles.size() < MAX_ROLES)
2016 && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) )
2017 {
2018 mCreateRoleButton->setEnabled(TRUE);
2019 }
2020 else
2021 {
2022 mCreateRoleButton->setEnabled(FALSE);
2023 }
2024
2025 if (had_selection)
2026 {
2027 handleRoleSelect();
2028 }
2029 else
2030 {
2031 mAssignedMembersList->deleteAllItems();
2032 mAllowedActionsList->deleteAllItems();
2033 mRoleName->clear();
2034 mRoleDescription->clear();
2035 mRoleTitle->clear();
2036 setFooterEnabled(FALSE);
2037 mDeleteRoleButton->setEnabled(FALSE);
2038 }
2039 }
2040
2041 if (!gdatap || !gdatap->isMemberDataComplete())
2042 {
2043 gGroupMgr->sendGroupMembersRequest(mGroupID);
2044 }
2045
2046 if (!gdatap || !gdatap->isRoleMemberDataComplete())
2047 {
2048 gGroupMgr->sendGroupRoleMembersRequest(mGroupID);
2049 }
2050
2051 if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
2052 && gdatap->isMemberDataComplete()
2053 && gdatap->isRoleMemberDataComplete())
2054 {
2055 buildMembersList();
2056 }
2057}
2058
2059// static
2060void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
2061{
2062 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2063 self->handleRoleSelect();
2064}
2065
2066void LLPanelGroupRolesSubTab::handleRoleSelect()
2067{
2068 BOOL can_delete = TRUE;
2069 lldebugs << "LLPanelGroupRolesSubTab::handleRoleSelect()" << llendl;
2070
2071 mAssignedMembersList->deleteAllItems();
2072 mAllowedActionsList->deleteAllItems();
2073
2074 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2075 if (!gdatap)
2076 {
2077 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
2078 << "-- No group data!" << llendl;
2079 return;
2080 }
2081
2082 saveRoleChanges();
2083
2084 // Check if there is anything selected.
2085 LLScrollListItem* item = mRolesList->getFirstSelected();
2086 if (!item)
2087 {
2088 setFooterEnabled(FALSE);
2089 return;
2090 }
2091
2092 setFooterEnabled(TRUE);
2093
2094 LLRoleData rd;
2095 if (gdatap->getRoleData(item->getUUID(),rd))
2096 {
2097 BOOL is_owner_role = ( gdatap->mOwnerRole == item->getUUID() );
2098 mRoleName->setText(rd.mRoleName);
2099 mRoleTitle->setText(rd.mRoleTitle);
2100 mRoleDescription->setText(rd.mRoleDescription);
2101
2102 mAllowedActionsList->setEnabled(gAgent.hasPowerInGroup(mGroupID,
2103 GP_ROLE_CHANGE_ACTIONS));
2104 buildActionsList(mAllowedActionsList,
2105 rd.mRolePowers,
2106 0LL,
2107 mActionIcons,
2108 onActionCheck,
2109 TRUE,
2110 FALSE,
2111 is_owner_role);
2112
2113
2114 mMemberVisibleCheck->set((rd.mRolePowers & GP_MEMBER_VISIBLE_IN_DIR) == GP_MEMBER_VISIBLE_IN_DIR);
2115 mRoleName->setEnabled(!is_owner_role &&
2116 gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
2117 mRoleTitle->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
2118 mRoleDescription->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
2119 mMemberVisibleCheck->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_PROPERTIES));
2120
2121 if (item->getUUID().isNull())
2122 {
2123 // Everyone role, can't edit description or name or delete
2124 mRoleDescription->setEnabled(FALSE);
2125 mRoleName->setEnabled(FALSE);
2126 can_delete = FALSE;
2127 }
2128 //you can't delete the owner role
2129 if ( is_owner_role ) can_delete = FALSE;
2130 }
2131 else
2132 {
2133 mRolesList->deselectAllItems();
2134 mAssignedMembersList->deleteAllItems();
2135 mAllowedActionsList->deleteAllItems();
2136 mRoleName->clear();
2137 mRoleDescription->clear();
2138 mRoleTitle->clear();
2139 setFooterEnabled(FALSE);
2140
2141 can_delete = FALSE;
2142 }
2143 mSelectedRole = item->getUUID();
2144 buildMembersList();
2145
2146 can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
2147 GP_ROLE_DELETE);
2148 mDeleteRoleButton->setEnabled(can_delete);
2149}
2150
2151void LLPanelGroupRolesSubTab::buildMembersList()
2152{
2153 mAssignedMembersList->deleteAllItems();
2154
2155 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2156 if (!gdatap)
2157 {
2158 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
2159 << "-- No group data!" << llendl;
2160 return;
2161 }
2162
2163 // Check if there is anything selected.
2164 LLScrollListItem* item = mRolesList->getFirstSelected();
2165 if (!item) return;
2166
2167 if (item->getUUID().isNull())
2168 {
2169 // Special cased 'Everyone' role
2170 LLGroupMgrGroupData::member_iter mit = gdatap->mMembers.begin();
2171 LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
2172 for ( ; mit != end; ++mit)
2173 {
2174 mAssignedMembersList->addNameItem((*mit).first);
2175 }
2176 }
2177 else
2178 {
2179 LLGroupMgrGroupData::role_iter rit = gdatap->mRoles.find(item->getUUID());
2180 if (rit != gdatap->mRoles.end())
2181 {
2182 LLGroupRoleData* rdatap = (*rit).second;
2183 if (rdatap)
2184 {
2185 std::vector<LLUUID>::const_iterator mit = rdatap->getMembersBegin();
2186 std::vector<LLUUID>::const_iterator end = rdatap->getMembersEnd();
2187 for ( ; mit != end; ++mit)
2188 {
2189 mAssignedMembersList->addNameItem((*mit));
2190 }
2191 }
2192 }
2193 }
2194}
2195
2196// static
2197void LLPanelGroupRolesSubTab::onActionCheck(LLUICtrl* ctrl, void* user_data)
2198{
2199 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2200 LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
2201 if (!check || !self) return;
2202
2203 self->handleActionCheck(check);
2204}
2205
2206struct ActionCBData
2207{
2208 LLPanelGroupRolesSubTab* mSelf;
2209 LLCheckBoxCtrl* mCheck;
2210};
2211
2212void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool force)
2213{
2214 lldebugs << "LLPanelGroupRolesSubTab::handleActionSelect()" << llendl;
2215
2216 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2217 if (!gdatap)
2218 {
2219 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
2220 << "-- No group data!" << llendl;
2221 return;
2222 }
2223
2224 LLScrollListItem* action_item = mAllowedActionsList->getFirstSelected();
2225 if (!action_item)
2226 {
2227 return;
2228 }
2229
2230 LLScrollListItem* role_item = mRolesList->getFirstSelected();
2231 if (!role_item)
2232 {
2233 return;
2234 }
2235 LLUUID role_id = role_item->getUUID();
2236
2237 LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
2238 U64 power = rap->mPowerBit;
2239
2240 if (check->get())
2241 {
2242 if (!force && ( (GP_ROLE_ASSIGN_MEMBER == power)
2243 || (GP_ROLE_CHANGE_ACTIONS == power) ))
2244 {
2245 // Uncheck the item, for now. It will be
2246 // checked if they click 'Yes', below.
2247 check->set(FALSE);
2248
2249 LLRoleData rd;
2250 LLStringBase<char>::format_map_t args;
2251
2252 if ( gdatap->getRoleData(role_id, rd) )
2253 {
2254 args["[ACTION_NAME]"] = rap->mDescription;
2255 args["[ROLE_NAME]"] = rd.mRoleName;
2256 struct ActionCBData* cb_data = new ActionCBData;
2257 cb_data->mSelf = this;
2258 cb_data->mCheck = check;
2259 mHasModal = TRUE;
2260 LLString warning = "AssignDangerousActionWarning";
2261 if (GP_ROLE_CHANGE_ACTIONS == power)
2262 {
2263 warning = "AssignDangerousAbilityWarning";
2264 }
2265 gViewerWindow->alertXml(warning, args, addActionCB, cb_data);
2266 }
2267 else
2268 {
2269 llwarns << "Unable to look up role information for role id: "
2270 << role_id << llendl;
2271 }
2272 }
2273 else
2274 {
2275 gdatap->addRolePower(role_id,power);
2276 }
2277 }
2278 else
2279 {
2280 gdatap->removeRolePower(role_id,power);
2281 }
2282
2283 mHasRoleChange = TRUE;
2284 notifyObservers();
2285}
2286
2287//static
2288void LLPanelGroupRolesSubTab::addActionCB(S32 option, void* data)
2289{
2290 struct ActionCBData* cb_data = (struct ActionCBData*) data;
2291
2292 if (!cb_data || !cb_data->mSelf || !cb_data->mCheck) return;
2293
2294 cb_data->mSelf->mHasModal = FALSE;
2295
2296 if (0 == option)
2297 {
2298 // User clicked "Yes"
2299 cb_data->mCheck->set(TRUE);
2300 const bool force_add = true;
2301 cb_data->mSelf->handleActionCheck(cb_data->mCheck, force_add);
2302 }
2303}
2304
2305
2306// static
2307void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
2308{
2309 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2310 if (!self) return;
2311
2312 self->mHasRoleChange = TRUE;
2313 self->notifyObservers();
2314}
2315
2316// static
2317void LLPanelGroupRolesSubTab::onDescriptionCommit(LLUICtrl* ctrl, void* user_data)
2318{
2319 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2320 if (!self) return;
2321
2322 self->mHasRoleChange = TRUE;
2323 self->notifyObservers();
2324}
2325
2326// static
2327void LLPanelGroupRolesSubTab::onMemberVisibilityChange(LLUICtrl* ctrl, void* user_data)
2328{
2329 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2330 LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
2331 if (!check || !self) return;
2332
2333 self->handleMemberVisibilityChange(check->get());
2334}
2335
2336void LLPanelGroupRolesSubTab::handleMemberVisibilityChange(bool value)
2337{
2338 lldebugs << "LLPanelGroupRolesSubTab::handleMemberVisibilityChange()" << llendl;
2339
2340 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2341 if (!gdatap)
2342 {
2343 llwarns << "LLPanelGroupRolesSubTab::handleRoleSelect() "
2344 << "-- No group data!" << llendl;
2345 return;
2346 }
2347
2348 LLScrollListItem* role_item = mRolesList->getFirstSelected();
2349 if (!role_item)
2350 {
2351 return;
2352 }
2353
2354 if (value)
2355 {
2356 gdatap->addRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
2357 }
2358 else
2359 {
2360 gdatap->removeRolePower(role_item->getUUID(),GP_MEMBER_VISIBLE_IN_DIR);
2361 }
2362}
2363
2364// static
2365void LLPanelGroupRolesSubTab::onCreateRole(void* user_data)
2366{
2367 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2368 if (!self) return;
2369
2370 self->handleCreateRole();
2371}
2372
2373void LLPanelGroupRolesSubTab::handleCreateRole()
2374{
2375 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2376
2377 if (!gdatap) return;
2378
2379 LLUUID new_role_id;
2380 new_role_id.generate();
2381
2382 LLRoleData rd;
2383 rd.mRoleName = "New Role";
2384 gdatap->createRole(new_role_id,rd);
2385
2386 mRolesList->deselectAllItems(TRUE);
2387 LLSD row;
2388 row["id"] = new_role_id;
2389 row["columns"][0]["column"] = "name";
2390 row["columns"][0]["value"] = rd.mRoleName;
2391 mRolesList->addElement(row, ADD_BOTTOM, this);
2392 mRolesList->selectByID(new_role_id);
2393
2394 // put focus on name field and select its contents
2395 if(mRoleName)
2396 {
2397 mRoleName->setFocus(TRUE);
2398 mRoleName->onTabInto();
2399 gFocusMgr.triggerFocusFlash();
2400 }
2401
2402 notifyObservers();
2403}
2404
2405// static
2406void LLPanelGroupRolesSubTab::onDeleteRole(void* user_data)
2407{
2408 LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
2409 if (!self) return;
2410
2411 self->handleDeleteRole();
2412}
2413
2414void LLPanelGroupRolesSubTab::handleDeleteRole()
2415{
2416 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2417
2418 if (!gdatap) return;
2419
2420 LLScrollListItem* role_item = mRolesList->getFirstSelected();
2421 if (!role_item)
2422 {
2423 return;
2424 }
2425
2426 if (role_item->getUUID().isNull() || role_item->getUUID() == gdatap->mOwnerRole)
2427 {
2428 LLString::format_map_t args;
2429 args["[MESSAGE]"] = mRemoveEveryoneTxt;
2430 LLNotifyBox::showXml("GenericNotify", args);
2431 return;
2432 }
2433
2434 gdatap->deleteRole(role_item->getUUID());
2435 mRolesList->deleteSingleItem(mRolesList->getFirstSelectedIndex());
2436 mRolesList->selectFirstItem();
2437
2438 notifyObservers();
2439}
2440
2441void LLPanelGroupRolesSubTab::saveRoleChanges()
2442{
2443 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2444
2445 if (!gdatap) return;
2446
2447 if (mHasRoleChange)
2448 {
2449 LLRoleData rd;
2450 if (!gdatap->getRoleData(mSelectedRole,rd)) return;
2451
2452 rd.mRoleName = mRoleName->getText();
2453 rd.mRoleDescription = mRoleDescription->getText();
2454 rd.mRoleTitle = mRoleTitle->getText();
2455
2456 gdatap->setRoleData(mSelectedRole,rd);
2457
2458 mRolesList->deleteSingleItem(mRolesList->getItemIndex(mSelectedRole));
2459
2460 LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,0);
2461 LLScrollListItem* item = mRolesList->addElement(row, ADD_BOTTOM, this);
2462 item->setSelected(TRUE);
2463
2464 mHasRoleChange = FALSE;
2465 }
2466}
2467////////////////////////////
2468// LLPanelGroupActionsSubTab
2469////////////////////////////
2470
2471// static
2472void* LLPanelGroupActionsSubTab::createTab(void* data)
2473{
2474 LLUUID* group_id = static_cast<LLUUID*>(data);
2475 return new LLPanelGroupActionsSubTab("panel group actions sub tab", *group_id);
2476}
2477
2478LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab(const std::string& name, const LLUUID& group_id)
2479: LLPanelGroupSubTab(name, group_id)
2480{
2481}
2482
2483LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab()
2484{
2485}
2486
2487BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
2488{
2489 // Upcast parent so we can ask it for sibling controls.
2490 LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
2491
2492 // Look recursively from the parent to find all our widgets.
2493 bool recurse = true;
2494 mHeader = (LLPanel*) parent->getChildByName("actions_header", recurse);
2495 mFooter = (LLPanel*) parent->getChildByName("actions_footer", recurse);
2496
2497 mActionDescription = (LLTextEditor*) parent->getChildByName("action_description", recurse);
2498
2499 mActionList = (LLScrollListCtrl*) parent->getChildByName("action_list",recurse);
2500 mActionRoles = (LLScrollListCtrl*) parent->getChildByName("action_roles",recurse);
2501 mActionMembers = (LLNameListCtrl*) parent->getChildByName("action_members",recurse);
2502
2503 if (!mActionList || !mActionDescription || !mActionRoles || !mActionMembers) return FALSE;
2504
2505 mActionList->setCallbackUserData(this);
2506 mActionList->setCommitOnSelectionChange(TRUE);
2507 mActionList->setCommitCallback(onActionSelect);
2508
2509 mActionMembers->setCallbackUserData(this);
2510 mActionRoles->setCallbackUserData(this);
2511
2512 update(GC_ALL);
2513
2514 return TRUE;
2515}
2516
2517void LLPanelGroupActionsSubTab::activate()
2518{
2519 LLPanelGroupSubTab::activate();
2520 lldebugs << "LLPanelGroupActionsSubTab::activate()" << llendl;
2521
2522 mActionList->deselectAllItems();
2523 mActionMembers->deleteAllItems();
2524 mActionRoles->deleteAllItems();
2525 mActionDescription->clear();
2526}
2527
2528void LLPanelGroupActionsSubTab::deactivate()
2529{
2530 lldebugs << "LLPanelGroupActionsSubTab::deactivate()" << llendl;
2531
2532 LLPanelGroupSubTab::deactivate();
2533}
2534
2535bool LLPanelGroupActionsSubTab::needsApply(LLString& mesg)
2536{
2537 lldebugs << "LLPanelGroupActionsSubTab::needsApply()" << llendl;
2538
2539 return false;
2540}
2541
2542bool LLPanelGroupActionsSubTab::apply(LLString& mesg)
2543{
2544 lldebugs << "LLPanelGroupActionsSubTab::apply()" << llendl;
2545 return true;
2546}
2547
2548void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
2549{
2550 lldebugs << "LLPanelGroupActionsSubTab::update()" << llendl;
2551
2552 if (mGroupID.isNull()) return;
2553
2554 mActionList->deselectAllItems();
2555 mActionMembers->deleteAllItems();
2556 mActionRoles->deleteAllItems();
2557 mActionDescription->clear();
2558
2559 mActionList->deleteAllItems();
2560 buildActionsList(mActionList,
2561 GP_ALL_POWERS,
2562 GP_ALL_POWERS,
2563 mActionIcons,
2564 NULL,
2565 FALSE,
2566 TRUE,
2567 FALSE);
2568}
2569
2570// static
2571void LLPanelGroupActionsSubTab::onActionSelect(LLUICtrl* scroll, void* data)
2572{
2573 LLPanelGroupActionsSubTab* self = static_cast<LLPanelGroupActionsSubTab*>(data);
2574 self->handleActionSelect();
2575}
2576
2577void LLPanelGroupActionsSubTab::handleActionSelect()
2578{
2579 mActionMembers->deleteAllItems();
2580 mActionRoles->deleteAllItems();
2581
2582 U64 power_mask = GP_NO_POWERS;
2583 std::vector<LLScrollListItem*> selection =
2584 mActionList->getAllSelected();
2585 if (selection.empty()) return;
2586
2587 LLRoleAction* rap;
2588
2589 std::vector<LLScrollListItem*>::iterator itor;
2590 for (itor = selection.begin() ;
2591 itor != selection.end(); ++itor)
2592 {
2593 rap = (LLRoleAction*)( (*itor)->getUserdata() );
2594 power_mask |= rap->mPowerBit;
2595 }
2596
2597 if (selection.size() == 1)
2598 {
2599 LLScrollListItem* item = selection[0];
2600 rap = (LLRoleAction*)(item->getUserdata());
2601
2602 if (rap->mLongDescription.empty())
2603 {
2604 mActionDescription->setText(rap->mDescription);
2605 }
2606 else
2607 {
2608 mActionDescription->setText(rap->mLongDescription);
2609 }
2610 }
2611 else
2612 {
2613 mActionDescription->clear();
2614 }
2615
2616 LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(mGroupID);
2617
2618 if (!gdatap) return;
2619
2620 if (gdatap->isMemberDataComplete())
2621 {
2622 LLGroupMgrGroupData::member_iter it = gdatap->mMembers.begin();
2623 LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end();
2624 LLGroupMemberData* gmd;
2625
2626 for ( ; it != end; ++it)
2627 {
2628 gmd = (*it).second;
2629 if (!gmd) continue;
2630 if ((gmd->getAgentPowers() & power_mask) == power_mask)
2631 {
2632 mActionMembers->addNameItem(gmd->getID());
2633 }
2634 }
2635 }
2636 else
2637 {
2638 gGroupMgr->sendGroupMembersRequest(mGroupID);
2639 }
2640
2641 if (gdatap->isRoleDataComplete())
2642 {
2643 LLGroupMgrGroupData::role_iter it = gdatap->mRoles.begin();
2644 LLGroupMgrGroupData::role_iter end = gdatap->mRoles.end();
2645 LLGroupRoleData* rmd;
2646
2647 for ( ; it != end; ++it)
2648 {
2649 rmd = (*it).second;
2650 if (!rmd) continue;
2651 if ((rmd->getRoleData().mRolePowers & power_mask) == power_mask)
2652 {
2653 mActionRoles->addSimpleItem(rmd->getRoleData().mRoleName);
2654 }
2655 }
2656 }
2657 else
2658 {
2659 gGroupMgr->sendGroupRoleDataRequest(mGroupID);
2660 }
2661}