1645 lines
47 KiB
C++
1645 lines
47 KiB
C++
/**
|
|
* @file llpanelgroupvoting.cpp
|
|
* @brief LLPanelGroupVoting class definition.
|
|
*
|
|
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2003-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "roles_constants.h"
|
|
|
|
#include "lllineeditor.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "lltextbox.h"
|
|
#include "lltexteditor.h"
|
|
#include "llscrolllistctrl.h"
|
|
#include "llradiogroup.h"
|
|
#include "llspinctrl.h"
|
|
#include "llpanelgroupvoting.h"
|
|
#include "llnamelistctrl.h"
|
|
#include "llbutton.h"
|
|
#include "llnotify.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llfocusmgr.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llviewerregion.h"
|
|
|
|
class LLPanelGroupVoting::impl
|
|
{
|
|
public:
|
|
impl(LLPanelGroupVoting& panel, const LLUUID& group_id);
|
|
~impl();
|
|
|
|
static void onClickCreateProposal(void* userdata);
|
|
static void onClickYes(void *userdata);
|
|
static void onClickNo(void *userdata);
|
|
static void onClickAbstain(void *userdata);
|
|
static void onClickSubmitProposal(void *userdata);
|
|
static void onClickCancelProposal(void *userdata);
|
|
static void onClickViewProposalList(void *userdata);
|
|
static void onClickViewProposalItem(void *userdata);
|
|
static void onDoubleClickProposal(void *userdata);
|
|
|
|
static void onDoubleClickHistoryItem(void *userdata);
|
|
static void onClickViewHistoryItem(void *userdata);
|
|
static void onClickViewHistoryList(void *userdata);
|
|
|
|
void sendGroupProposalsRequest(const LLUUID& group_id);
|
|
void sendStartGroupProposal();
|
|
void sendGroupProposalBallot(const std::string& vote);
|
|
void sendGroupVoteHistoryRequest(const LLUUID& group_id);
|
|
|
|
void setEnableCreateProposal();
|
|
void setEnableVoteProposal();
|
|
void setEnableListProposals();
|
|
void setEnableHistoryItem();
|
|
void setEnableHistoryList();
|
|
|
|
void updateQuorumText();
|
|
void addPendingActiveScrollListItem(unsigned int current,
|
|
unsigned int expected,
|
|
EAddPosition pos);
|
|
void addPendingHistoryScrollListItem(unsigned int current,
|
|
unsigned int expected,
|
|
EAddPosition pos);
|
|
void addNoActiveScrollListItem(EAddPosition pos);
|
|
void addNoHistoryScrollListItem(EAddPosition pos);
|
|
|
|
|
|
static void processGroupActiveProposalItemReply(LLMessageSystem* msg,
|
|
void** data);
|
|
static void processGroupVoteHistoryItemReply(LLMessageSystem* msg,
|
|
void** data);
|
|
|
|
public:
|
|
LLUUID mGroupID;
|
|
LLUUID mProposalID;
|
|
|
|
LLPanelGroupVoting& mPanel;
|
|
|
|
LLSpinCtrl *mQuorum;
|
|
LLTextBox *mQuorumLbl;
|
|
LLSpinCtrl *mDuration;
|
|
LLTextBox *mDurationLbl;
|
|
LLTextBox *mDurationText;
|
|
LLRadioGroup *mMajority;
|
|
LLTextBox *mMajorityLbl;
|
|
LLTextBox *mStartLbl;
|
|
LLTextBox *mEndLbl;
|
|
LLTextBox *mStartDate;
|
|
LLTextBox *mEndDate;
|
|
|
|
LLButton *mBtnYes;
|
|
LLButton *mBtnNo;
|
|
LLButton *mBtnAbstain;
|
|
|
|
LLScrollListCtrl *mProposals;
|
|
LLTextEditor *mProposalText;
|
|
LLButton *mBtnCreateProposal;
|
|
LLButton *mBtnSubmitProposal;
|
|
LLButton *mBtnCancelProposal;
|
|
LLButton *mBtnViewProposalList;
|
|
LLButton *mBtnViewProposalItem;
|
|
|
|
LLScrollListCtrl *mVotesHistory;
|
|
LLTextBox *mVotesHistoryLbl;
|
|
LLTextEditor *mVoteHistoryText;
|
|
LLTextBox *mVoteHistoryTextLbl;
|
|
LLButton *mBtnViewHistoryList;
|
|
LLButton *mBtnViewHistoryItem;
|
|
|
|
int mNumGroupMembers;
|
|
|
|
std::vector<LLSD> mActiveReceived;
|
|
std::vector<LLSD> mHistoryReceived;
|
|
U32 mOtherGroupHistoryItems;
|
|
|
|
int mProposalColumnWidths[10];
|
|
int mHistoryColumnWidths[10];
|
|
|
|
LLUUID mProposalTransID;
|
|
LLUUID mHistoryTransID;
|
|
|
|
static std::map<LLUUID, LLPanelGroupVoting::impl*> sGroupIDs;
|
|
};
|
|
|
|
// ****************************************
|
|
// ** LLPanelGroupVoting::impl Functions **
|
|
// ****************************************
|
|
|
|
LLPanelGroupVoting::impl::impl(LLPanelGroupVoting& panel, const LLUUID& group_id)
|
|
: mPanel(panel),
|
|
mGroupID(group_id)
|
|
{
|
|
|
|
mNumGroupMembers = 0;
|
|
|
|
mProposalTransID = LLUUID::null;
|
|
mHistoryTransID = LLUUID::null;
|
|
|
|
mProposalColumnWidths[0] = -1;
|
|
mProposalColumnWidths[1] = 210;
|
|
mProposalColumnWidths[2] = 120;
|
|
mProposalColumnWidths[3] = -1;
|
|
mProposalColumnWidths[4] = 30;
|
|
for (int index = 5; index < 10; index++)
|
|
{
|
|
mProposalColumnWidths[index] = -1;
|
|
}
|
|
|
|
mHistoryColumnWidths[0] = -1;
|
|
mHistoryColumnWidths[1] = 210; // vote text sans non-printable
|
|
mHistoryColumnWidths[2] = 120;
|
|
mHistoryColumnWidths[3] = -1;
|
|
mHistoryColumnWidths[4] = -1;
|
|
mHistoryColumnWidths[5] = -1; // full vote text
|
|
|
|
//problem what if someone has both the group floater open and the finder
|
|
//open to the same group? Some maps that map group ids to panels
|
|
//will then only be working for the last panel for a given group id :(
|
|
sGroupIDs[group_id] = this;
|
|
|
|
mQuorum = NULL;
|
|
mQuorumLbl = NULL;
|
|
mDuration = NULL;
|
|
mDurationLbl = NULL;
|
|
mDurationText = NULL;
|
|
mMajority = NULL;
|
|
mMajorityLbl = NULL;
|
|
mStartLbl = NULL;
|
|
mEndLbl = NULL;
|
|
mStartDate = NULL;
|
|
mEndDate = NULL;
|
|
|
|
mBtnYes = NULL;
|
|
mBtnNo = NULL;
|
|
mBtnAbstain = NULL;
|
|
|
|
mProposals = NULL;
|
|
mProposalText = NULL;
|
|
mBtnCreateProposal = NULL;
|
|
mBtnSubmitProposal = NULL;
|
|
mBtnCancelProposal = NULL;
|
|
mBtnViewProposalList = NULL;
|
|
mBtnViewProposalItem = NULL;
|
|
|
|
mVotesHistory = NULL;
|
|
mVotesHistoryLbl = NULL;
|
|
mVoteHistoryText = NULL;
|
|
mVoteHistoryTextLbl = NULL;
|
|
mBtnViewHistoryList = NULL;
|
|
mBtnViewHistoryItem = NULL;
|
|
|
|
mOtherGroupHistoryItems = 0;
|
|
}
|
|
|
|
LLPanelGroupVoting::impl::~impl()
|
|
{
|
|
sGroupIDs.erase(mGroupID);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::setEnableListProposals()
|
|
{
|
|
//we make the assumption here that anyone who has the start
|
|
//or vote powers should also have the view powers
|
|
|
|
/* This power was removed to make group roles simpler
|
|
if (!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VIEW) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
*/
|
|
if (!gAgent.isInGroup(mGroupID))
|
|
return;
|
|
|
|
|
|
mPanel.childSetText("proposal_header", mPanel.getString("proposals_header_view_txt"));
|
|
mPanel.childSetText("proposal_instructions", mPanel.getString("proposals_header_view_inst"));
|
|
mPanel.childSetVisible("proposal_lbl", FALSE);
|
|
mPanel.childSetVisible("proposal_voting_lbl", TRUE);
|
|
mProposals->setVisible(TRUE);
|
|
mProposals->setBgSelectedColor(gColors.getColor("ScrollSelectedBGColor"));
|
|
mProposalText->setVisible(FALSE);
|
|
mBtnYes->setEnabled(FALSE);
|
|
mBtnYes->setVisible(FALSE);
|
|
mBtnNo->setEnabled(FALSE);
|
|
mBtnNo->setVisible(FALSE);
|
|
mBtnAbstain->setEnabled(FALSE);
|
|
mBtnAbstain->setVisible(FALSE);
|
|
mBtnSubmitProposal->setEnabled(FALSE);
|
|
mBtnSubmitProposal->setVisible(FALSE);
|
|
mBtnCancelProposal->setEnabled(FALSE);
|
|
mBtnCancelProposal->setVisible(FALSE);
|
|
|
|
mBtnViewProposalItem->setEnabled(TRUE);
|
|
mBtnViewProposalItem->setVisible(TRUE);
|
|
|
|
mBtnViewProposalList->setEnabled(FALSE);
|
|
mBtnViewProposalList->setVisible(FALSE);
|
|
|
|
mQuorumLbl->setVisible(FALSE);
|
|
mQuorum->setEnabled(FALSE);
|
|
mQuorum->setVisible(FALSE);
|
|
mPanel.childSetVisible("quorum_text", FALSE);
|
|
|
|
mDurationLbl->setVisible(FALSE);
|
|
mDuration->setEnabled(FALSE);
|
|
mDuration->setVisible(FALSE);
|
|
mDurationText->setVisible(FALSE);
|
|
|
|
mMajorityLbl->setVisible(FALSE);
|
|
mMajority->setEnabled(FALSE);
|
|
mMajority->setVisible(FALSE);
|
|
mStartLbl->setVisible(FALSE);
|
|
mStartDate->setVisible(FALSE);
|
|
mEndLbl->setVisible(FALSE);
|
|
mEndDate->setVisible(FALSE);
|
|
|
|
//check to see if the agent can create proposals when enabling the
|
|
//create proposal button
|
|
BOOL can_create = gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START);
|
|
|
|
mBtnCreateProposal->setEnabled(can_create);
|
|
mBtnCreateProposal->setVisible(can_create);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::setEnableVoteProposal()
|
|
{
|
|
if (!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE))
|
|
return;
|
|
|
|
LLScrollListItem *item = mProposals->getFirstSelected();
|
|
if (item)
|
|
{
|
|
std::string already_voted;
|
|
std::string vote_cast;
|
|
|
|
mProposalID = item->getUUID();
|
|
|
|
// col 0: index id
|
|
LLScrollListCell * proposal_cell = item->getColumn(1);
|
|
if ( proposal_cell )
|
|
{
|
|
//proposal text
|
|
mProposalText->setText(proposal_cell->getValue().asString());
|
|
}
|
|
else
|
|
{ // Something's wrong... should have some text
|
|
mProposalText->setText(LLStringUtil::null);
|
|
}
|
|
|
|
proposal_cell = item->getColumn(2);
|
|
if (proposal_cell)
|
|
{
|
|
//end date
|
|
mEndDate->setText(proposal_cell->getValue().asString());
|
|
}
|
|
else
|
|
{ // Something's wrong... should have some text
|
|
mEndDate->setText(LLStringUtil::null);
|
|
}
|
|
|
|
// col 3: Vote Type
|
|
proposal_cell = item->getColumn(3);
|
|
if (proposal_cell)
|
|
{
|
|
//already voted
|
|
already_voted = proposal_cell->getValue().asString();
|
|
}
|
|
else
|
|
{ // Something's wrong... should have some text
|
|
already_voted = "";
|
|
}
|
|
|
|
proposal_cell = item->getColumn(5);
|
|
if (proposal_cell)
|
|
{
|
|
//start date
|
|
mStartDate->setText(proposal_cell->getValue().asString());
|
|
}
|
|
else
|
|
{ // Something's wrong... should have some text
|
|
mStartDate->setText(LLStringUtil::null);
|
|
}
|
|
|
|
proposal_cell = item->getColumn(6);
|
|
if (proposal_cell)
|
|
{
|
|
// Vote Cast
|
|
vote_cast = proposal_cell->getValue().asString();
|
|
}
|
|
|
|
// col 8: Vote Initiator
|
|
proposal_cell = item->getColumn(8);
|
|
if (proposal_cell)
|
|
{
|
|
//quorum
|
|
mQuorum->set(
|
|
(F32)atoi(proposal_cell->getValue().asString().c_str()));
|
|
}
|
|
else
|
|
{
|
|
mQuorum->set(0);
|
|
}
|
|
|
|
F32 majority = 0.0f;
|
|
proposal_cell = item->getColumn(9);
|
|
if (proposal_cell)
|
|
{
|
|
//majority
|
|
majority =
|
|
(F32)atof(proposal_cell->getValue().asString().c_str());
|
|
}
|
|
|
|
if(majority == 0.0f)
|
|
{ // Select the Simple Majority
|
|
mMajority->setSelectedIndex(0);
|
|
}
|
|
else if (majority == 1.0f)
|
|
{
|
|
//Select Unanimous
|
|
mMajority->setSelectedIndex(2);
|
|
}
|
|
else
|
|
{
|
|
//Select 2/3 Majority
|
|
mMajority->setSelectedIndex(1);
|
|
}
|
|
|
|
if (already_voted == "Yes")
|
|
{
|
|
LLUIString votestr = mPanel.getString("proposals_header_voted_inst");
|
|
votestr.setArg("[VOTE]", vote_cast);
|
|
mPanel.childSetText("proposal_instructions", votestr.getString());
|
|
|
|
mBtnYes->setEnabled(FALSE);
|
|
mBtnNo->setEnabled(FALSE);
|
|
mBtnAbstain->setEnabled(FALSE);
|
|
}
|
|
else
|
|
{
|
|
mPanel.childSetText("proposal_instructions", mPanel.getString("proposals_header_vote_inst"));
|
|
|
|
mBtnYes->setEnabled(TRUE);
|
|
mBtnNo->setEnabled(TRUE);
|
|
mBtnAbstain->setEnabled(TRUE);
|
|
}
|
|
|
|
mPanel.childSetText("proposal_header", mPanel.getString("proposals_header_vote_txt"));
|
|
mPanel.childSetVisible("proposal_lbl", TRUE);
|
|
mPanel.childSetVisible("proposal_voting_lbl", FALSE);
|
|
mProposals->setVisible(FALSE);
|
|
mProposalText->setEnabled(FALSE);
|
|
mProposalText->setVisible(TRUE);
|
|
mBtnYes->setVisible(TRUE);
|
|
mBtnNo->setVisible(TRUE);
|
|
mBtnAbstain->setVisible(TRUE);
|
|
mBtnSubmitProposal->setEnabled(FALSE);
|
|
mBtnSubmitProposal->setVisible(FALSE);
|
|
mBtnCreateProposal->setEnabled(FALSE);
|
|
mBtnCreateProposal->setVisible(FALSE);
|
|
mBtnCancelProposal->setEnabled(FALSE);
|
|
mBtnCancelProposal->setVisible(FALSE);
|
|
|
|
mBtnViewProposalItem->setEnabled(FALSE);
|
|
mBtnViewProposalItem->setVisible(FALSE);
|
|
|
|
mBtnViewProposalList->setEnabled(TRUE);
|
|
mBtnViewProposalList->setVisible(TRUE);
|
|
|
|
mQuorumLbl->setVisible(TRUE);
|
|
mQuorum->setEnabled(FALSE);
|
|
mQuorum->setVisible(TRUE);
|
|
mPanel.childSetVisible("quorum_text", TRUE);
|
|
|
|
mDurationLbl->setVisible(FALSE);
|
|
mDuration->setEnabled(FALSE);
|
|
mDuration->setVisible(FALSE);
|
|
mDurationText->setVisible(FALSE);
|
|
|
|
mMajorityLbl->setVisible(TRUE);
|
|
mMajority->setEnabled(FALSE);
|
|
mMajority->setVisible(TRUE);
|
|
mStartLbl->setVisible(TRUE);
|
|
mStartDate->setVisible(TRUE);
|
|
mEndLbl->setVisible(TRUE);
|
|
mEndDate->setVisible(TRUE);
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::setEnableCreateProposal()
|
|
{
|
|
if ( !gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
return;
|
|
|
|
mPanel.childSetText("proposal_header", mPanel.getString("proposals_header_create_txt"));
|
|
mPanel.childSetText("proposal_instructions", mPanel.getString("proposals_header_create_inst"));
|
|
mPanel.childSetVisible("proposal_lbl", TRUE);
|
|
mPanel.childSetVisible("proposal_voting_lbl", FALSE);
|
|
mProposals->setVisible(FALSE);
|
|
mProposalText->setEnabled(TRUE);
|
|
mProposalText->setVisible(TRUE);
|
|
mProposalText->setText(LLStringUtil::null);
|
|
mBtnYes->setEnabled(FALSE);
|
|
mBtnYes->setVisible(FALSE);
|
|
mBtnNo->setEnabled(FALSE);
|
|
mBtnNo->setVisible(FALSE);
|
|
mBtnAbstain->setEnabled(FALSE);
|
|
mBtnAbstain->setVisible(FALSE);
|
|
mBtnSubmitProposal->setEnabled(TRUE);
|
|
mBtnSubmitProposal->setVisible(TRUE);
|
|
mBtnCancelProposal->setEnabled(TRUE);
|
|
mBtnCancelProposal->setVisible(TRUE);
|
|
mBtnCreateProposal->setEnabled(FALSE);
|
|
mBtnCreateProposal->setVisible(FALSE);
|
|
|
|
mBtnViewProposalItem->setEnabled(FALSE);
|
|
mBtnViewProposalItem->setVisible(FALSE);
|
|
|
|
mBtnViewProposalList->setEnabled(FALSE);
|
|
mBtnViewProposalList->setVisible(FALSE);
|
|
|
|
mQuorumLbl->setVisible(TRUE);
|
|
mQuorum->setEnabled(TRUE);
|
|
mQuorum->setVisible(TRUE);
|
|
mPanel.childSetVisible("quorum_text", TRUE);
|
|
|
|
mDurationLbl->setVisible(TRUE);
|
|
mDuration->setEnabled(TRUE);
|
|
mDuration->setVisible(TRUE);
|
|
mDurationText->setVisible(TRUE);
|
|
|
|
mMajorityLbl->setVisible(TRUE);
|
|
mMajority->setEnabled(TRUE);
|
|
mMajority->setVisible(TRUE);
|
|
mStartLbl->setVisible(FALSE);
|
|
mStartDate->setVisible(FALSE);
|
|
mEndLbl->setVisible(FALSE);
|
|
mEndDate->setVisible(FALSE);
|
|
|
|
if (mQuorum->get() == 0)
|
|
{
|
|
mQuorum->set((F32)mNumGroupMembers);
|
|
}
|
|
mQuorum->setMaxValue((F32)mNumGroupMembers);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::setEnableHistoryList()
|
|
{
|
|
//we make the assumption here that anyone who has the start
|
|
//or vote powers should also have the view powers
|
|
|
|
/* This power was removed to make group roles simpler
|
|
if (!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VIEW) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
return;
|
|
*/
|
|
if (!gAgent.isInGroup(mGroupID))
|
|
return;
|
|
|
|
mVotesHistoryLbl->setVisible(TRUE);
|
|
mVotesHistory->setVisible(TRUE);
|
|
mVotesHistory->setEnabled(TRUE);
|
|
|
|
mVoteHistoryTextLbl->setVisible(FALSE);
|
|
mVoteHistoryText->setVisible(FALSE);
|
|
mBtnViewHistoryList->setVisible(FALSE);
|
|
|
|
mBtnViewHistoryItem->setVisible(TRUE);
|
|
mBtnViewHistoryItem->setEnabled(TRUE);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::setEnableHistoryItem()
|
|
{
|
|
//we make the assumption here that anyone who has the start
|
|
//or vote powers should also have the view powers
|
|
|
|
/* This power was removed to make group roles simpler
|
|
if (!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VIEW) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
return;
|
|
*/
|
|
|
|
if (!gAgent.isInGroup(mGroupID))
|
|
return;
|
|
|
|
LLScrollListItem *item = mVotesHistory->getFirstSelected();
|
|
// Get full text, not stripped version.
|
|
const LLScrollListCell *cell = item->getColumn(5);
|
|
if (cell)
|
|
{
|
|
mVoteHistoryText->setText(cell->getValue().asString());
|
|
}
|
|
else
|
|
{ // Something's wrong...
|
|
mVoteHistoryText->setText(LLStringUtil::null);
|
|
}
|
|
mVotesHistoryLbl->setVisible(FALSE);
|
|
mVotesHistory->setVisible(FALSE);
|
|
|
|
mVoteHistoryTextLbl->setVisible(TRUE);
|
|
mVoteHistoryText->setVisible(TRUE);
|
|
mVoteHistoryText->setEnabled(FALSE);
|
|
|
|
mBtnViewHistoryList->setVisible(TRUE);
|
|
mBtnViewHistoryList->setEnabled(TRUE);
|
|
mBtnViewHistoryItem->setVisible(FALSE);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::sendGroupProposalsRequest(const LLUUID& group_id)
|
|
{
|
|
//we make the assumption here that anyone who has the start
|
|
//or vote powers should also have the view powers
|
|
|
|
/* This power was removed to make group roles simpler
|
|
if (!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VIEW) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
return;
|
|
*/
|
|
if ( !gAgent.isInGroup(mGroupID) )
|
|
return;
|
|
|
|
mProposalTransID.generate();
|
|
mProposals->deleteAllItems(); //this should delete all the objects
|
|
mActiveReceived.clear();
|
|
mOtherGroupHistoryItems = 0;
|
|
|
|
//fill in some text so the user will at least know that
|
|
//we're pining the server in high latency situations
|
|
addPendingActiveScrollListItem(0, 0, ADD_BOTTOM);
|
|
mProposals->setCanSelect(FALSE);
|
|
mBtnViewProposalItem->setEnabled(FALSE);
|
|
|
|
LLMessageSystem *msg = gMessageSystem;
|
|
msg->newMessageFast(_PREHASH_GroupActiveProposalsRequest);
|
|
msg->nextBlockFast(_PREHASH_AgentData);
|
|
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
|
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
|
msg->nextBlockFast(_PREHASH_GroupData);
|
|
msg->addUUIDFast(_PREHASH_GroupID, group_id );
|
|
msg->nextBlockFast(_PREHASH_TransactionData);
|
|
msg->addUUIDFast(_PREHASH_TransactionID, mProposalTransID);
|
|
gAgent.sendReliableMessage();
|
|
}
|
|
|
|
void LLPanelGroupVoting::handleResponse(
|
|
const LLUUID& group_id,
|
|
ResponseType response,
|
|
bool success)
|
|
{
|
|
impl* self = NULL;
|
|
|
|
//see if the voting ballot for the group is still even open
|
|
std::map<LLUUID, LLPanelGroupVoting::impl*>::const_iterator self_iter =
|
|
LLPanelGroupVoting::impl::sGroupIDs.find(group_id);
|
|
|
|
if ( LLPanelGroupVoting::impl::sGroupIDs.end() != self_iter )
|
|
{
|
|
//cool, we found the panel's implementation
|
|
//(the panel is still open)
|
|
//then we want to do some other stuff :)
|
|
self = self_iter->second;
|
|
}
|
|
|
|
if ( self )
|
|
{
|
|
//refresh the proposals now that we've hit no
|
|
self->sendGroupProposalsRequest(self->mGroupID);
|
|
|
|
if (response == BALLOT)
|
|
{
|
|
LLSD args;
|
|
|
|
if (success)
|
|
{
|
|
args["MESSAGE"] = self->mPanel.getString("vote_recorded");
|
|
}
|
|
else
|
|
{
|
|
args["MESSAGE"] = self->mPanel.getString("vote_previously_recorded");
|
|
}
|
|
|
|
LLNotificationsUtil::add("SystemMessage", args);
|
|
|
|
self->sendGroupVoteHistoryRequest(self->mGroupID);
|
|
}
|
|
self->setEnableListProposals();
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupVoting::handleFailure(
|
|
const LLUUID& group_id)
|
|
{
|
|
impl* self = NULL;
|
|
|
|
//see if the voting ballot for the group is still even open
|
|
std::map<LLUUID, LLPanelGroupVoting::impl*>::const_iterator self_iter =
|
|
LLPanelGroupVoting::impl::sGroupIDs.find(group_id);
|
|
|
|
if ( LLPanelGroupVoting::impl::sGroupIDs.end() != self_iter )
|
|
{
|
|
//cool, we found the panel's implementation
|
|
//(the panel is still open)
|
|
//then we want to do some other stuff :)
|
|
self = self_iter->second;
|
|
}
|
|
|
|
if ( self )
|
|
{
|
|
self->setEnableListProposals();
|
|
}
|
|
}
|
|
|
|
class LLStartGroupVoteResponder : public LLHTTPClient::Responder
|
|
{
|
|
public:
|
|
LLStartGroupVoteResponder(const LLUUID& group_id)
|
|
{
|
|
mGroupID = group_id;
|
|
}
|
|
|
|
//If we get back a normal response, handle it here
|
|
virtual void result(const LLSD& content)
|
|
{
|
|
//Ack'd the proposal initialization, now let's finish up.
|
|
LLPanelGroupVoting::handleResponse(
|
|
mGroupID,
|
|
LLPanelGroupVoting::START_VOTE);
|
|
}
|
|
|
|
//If we get back an error (not found, etc...), handle it here
|
|
virtual void error(U32 status, const std::string& reason)
|
|
{
|
|
llinfos << "LLPanelGroupVotingResponder::error "
|
|
<< status << ": " << reason << llendl;
|
|
|
|
LLPanelGroupVoting::handleFailure(mGroupID);
|
|
}
|
|
private:
|
|
LLUUID mGroupID;
|
|
};
|
|
|
|
class LLGroupProposalBallotResponder : public LLHTTPClient::Responder
|
|
{
|
|
public:
|
|
LLGroupProposalBallotResponder(const LLUUID& group_id)
|
|
{
|
|
mGroupID = group_id;
|
|
}
|
|
|
|
//If we get back a normal response, handle it here
|
|
virtual void result(const LLSD& content)
|
|
{
|
|
//Ack'd the proposal initialization, now let's finish up.
|
|
LLPanelGroupVoting::handleResponse(
|
|
mGroupID,
|
|
LLPanelGroupVoting::BALLOT,
|
|
content["voted"].asBoolean());
|
|
}
|
|
|
|
//If we get back an error (not found, etc...), handle it here
|
|
virtual void error(U32 status, const std::string& reason)
|
|
{
|
|
llinfos << "LLPanelGroupVotingResponder::error "
|
|
<< status << ": " << reason << llendl;
|
|
|
|
LLPanelGroupVoting::handleFailure(mGroupID);
|
|
}
|
|
private:
|
|
LLUUID mGroupID;
|
|
};
|
|
|
|
void LLPanelGroupVoting::impl::sendStartGroupProposal()
|
|
{
|
|
if ( !gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START) )
|
|
return;
|
|
|
|
F32 majority = 0.f;
|
|
S32 duration_seconds = (S32)mDuration->get()*24*60*60; // duration days * 24hours/day * 60min/hr * 60sec/min
|
|
|
|
switch (mMajority->getSelectedIndex())
|
|
{
|
|
case 0: // Simple Majority
|
|
majority = 0.f;
|
|
break;
|
|
case 1: // 2/3 Majority
|
|
majority = 2.f/3.f;
|
|
break;
|
|
case 2: // Unanimous
|
|
majority = 1.0f;
|
|
break;
|
|
}
|
|
|
|
S32 quorum = llfloor(mQuorum->get());
|
|
|
|
// *************************************Conversion to capability
|
|
LLSD body;
|
|
|
|
std::string url = gAgent.getRegion()->getCapability("StartGroupProposal");
|
|
|
|
if (!url.empty())
|
|
{
|
|
body["agent-id"] = gAgent.getID();
|
|
body["session-id"] = gAgent.getSessionID();
|
|
|
|
body["group-id"] = mGroupID;
|
|
body["majority"] = majority;
|
|
body["quorum"] = quorum;
|
|
body["duration"] = duration_seconds;
|
|
body["proposal-text"] = mProposalText->getText();
|
|
|
|
LLHTTPClient::post(
|
|
url,
|
|
body,
|
|
new LLStartGroupVoteResponder(mGroupID),
|
|
300);
|
|
}
|
|
else
|
|
{ //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP!
|
|
LLMessageSystem *msg = gMessageSystem;
|
|
|
|
msg->newMessageFast(_PREHASH_StartGroupProposal);
|
|
msg->nextBlockFast(_PREHASH_AgentData);
|
|
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
|
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
|
|
|
msg->nextBlockFast(_PREHASH_ProposalData);
|
|
msg->addUUIDFast(_PREHASH_GroupID, mGroupID);
|
|
msg->addF32Fast(_PREHASH_Majority, majority );
|
|
msg->addS32Fast(_PREHASH_Quorum, quorum );
|
|
msg->addS32Fast(_PREHASH_Duration, duration_seconds );
|
|
msg->addStringFast(_PREHASH_ProposalText, mProposalText->getText());
|
|
|
|
gAgent.sendReliableMessage();
|
|
|
|
//This code was moved from the callers to here as part of deprecation.
|
|
sendGroupProposalsRequest(mGroupID);
|
|
setEnableListProposals();
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::sendGroupProposalBallot(const std::string& vote)
|
|
{
|
|
if ( !gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) )
|
|
return;
|
|
|
|
LLSD body;
|
|
|
|
std::string url = gAgent.getRegion()->getCapability("GroupProposalBallot");
|
|
|
|
if (!url.empty())
|
|
{
|
|
body["agent-id"] = gAgent.getID();
|
|
body["session-id"] = gAgent.getSessionID();
|
|
body["proposal-id"] = mProposalID;
|
|
body["group-id"] = mGroupID;
|
|
body["vote"] = vote;
|
|
|
|
LLHTTPClient::post(
|
|
url,
|
|
body,
|
|
new LLGroupProposalBallotResponder(mGroupID),
|
|
300);
|
|
}
|
|
else
|
|
{ //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP!
|
|
LLMessageSystem *msg = gMessageSystem;
|
|
|
|
msg->newMessageFast(_PREHASH_GroupProposalBallot);
|
|
msg->nextBlockFast(_PREHASH_AgentData);
|
|
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
|
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
|
|
|
msg->nextBlockFast(_PREHASH_ProposalData);
|
|
msg->addUUIDFast(_PREHASH_ProposalID, mProposalID);
|
|
msg->addUUIDFast(_PREHASH_GroupID, mGroupID);
|
|
msg->addStringFast(_PREHASH_VoteCast, vote);
|
|
|
|
gAgent.sendReliableMessage();
|
|
|
|
//This code was moved from the callers to here as part of deprecation.
|
|
sendGroupProposalsRequest(mGroupID);
|
|
sendGroupVoteHistoryRequest(mGroupID);
|
|
setEnableListProposals();
|
|
}
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::sendGroupVoteHistoryRequest(const LLUUID& group_id)
|
|
{
|
|
//we make the assumption here that anyone who has the start
|
|
//or vote powers should also have the view powers
|
|
|
|
/* This power was removed to make group roles simpler
|
|
if (mAwaitingFirstHistoryItem ||
|
|
(!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VIEW) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_VOTE) &&
|
|
!gAgent.hasPowerInGroup(mGroupID, GP_PROPOSAL_START)) )
|
|
return;
|
|
*/
|
|
|
|
if (!gAgent.isInGroup(mGroupID))
|
|
return;
|
|
|
|
mVotesHistory->deleteAllItems();
|
|
mHistoryTransID.generate();
|
|
mHistoryReceived.clear();
|
|
|
|
//add some text so the user knows we're doing something
|
|
addPendingHistoryScrollListItem(0, 0, ADD_BOTTOM);
|
|
mVotesHistory->setCanSelect(FALSE);
|
|
mBtnViewHistoryItem->setEnabled(FALSE);
|
|
|
|
LLMessageSystem *msg = gMessageSystem;
|
|
msg->newMessageFast(_PREHASH_GroupVoteHistoryRequest);
|
|
msg->nextBlockFast(_PREHASH_AgentData);
|
|
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
|
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
|
msg->nextBlockFast(_PREHASH_GroupData);
|
|
msg->addUUIDFast(_PREHASH_GroupID, group_id );
|
|
msg->nextBlockFast(_PREHASH_TransactionData);
|
|
msg->addUUIDFast(_PREHASH_TransactionID, mHistoryTransID);
|
|
gAgent.sendReliableMessage();
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::updateQuorumText()
|
|
{
|
|
mPanel.childSetTextArg("quorum_text", "[MEMBERS]", llformat("%d", mNumGroupMembers));
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::addPendingActiveScrollListItem(unsigned int current,
|
|
unsigned int expected,
|
|
EAddPosition pos)
|
|
{
|
|
std::stringstream pending;
|
|
// *TODO: translate
|
|
pending << "Retrieving active proposals ("
|
|
<< current
|
|
<< "\\" << expected << ")";
|
|
|
|
mProposals->addCommentText(pending.str());
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::addNoActiveScrollListItem(EAddPosition pos)
|
|
{
|
|
// *TODO: translate
|
|
mProposals->addCommentText(std::string("There are currently no active proposals"), pos);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::addNoHistoryScrollListItem(EAddPosition pos)
|
|
{
|
|
// *TODO: translate
|
|
mVotesHistory->addCommentText(std::string("There are currently no archived proposals"), pos);
|
|
}
|
|
|
|
void LLPanelGroupVoting::impl::addPendingHistoryScrollListItem(unsigned int current,
|
|
unsigned int expected,
|
|
EAddPosition pos)
|
|
{
|
|
// *TODO: translate
|
|
std::stringstream pending;
|
|
pending << "Retrieving archived proposals ("
|
|
<< current
|
|
<< "\\" << expected << ")";
|
|
|
|
mVotesHistory->addCommentText(pending.str());
|
|
}
|
|
|
|
|
|
//static
|
|
std::map<LLUUID, LLPanelGroupVoting::impl*> LLPanelGroupVoting::impl::sGroupIDs;
|
|
|
|
static std::string format_date(std::string date)
|
|
{
|
|
tm t;
|
|
if (sscanf(date.c_str(), "%u/%u/%u %u:%u",
|
|
&t.tm_mon, &t.tm_mday, &t.tm_year, &t.tm_hour, &t.tm_min) == 5
|
|
&& t.tm_year > 1900)
|
|
{
|
|
t.tm_year -= 1900;
|
|
t.tm_mon--;
|
|
t.tm_sec = 0;
|
|
std::string format = gSavedSettings.getString("ShortDateFormat");
|
|
format += " " + gSavedSettings.getString("ShortTimeFormat");
|
|
timeStructToFormattedString(&t, format, date);
|
|
}
|
|
return date;
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSystem *msg, void**)
|
|
{
|
|
LLUUID agent_id;
|
|
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
|
|
if (gAgent.getID() != agent_id)
|
|
{
|
|
llwarns << "Got active group proposals reply for another agent!" << llendl;
|
|
return;
|
|
}
|
|
|
|
LLUUID group_id;
|
|
LLUUID trans_id;
|
|
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
|
|
impl* self = get_if_there(sGroupIDs, group_id, (impl*) NULL);
|
|
if (!self)
|
|
{
|
|
return;
|
|
}
|
|
|
|
msg->getUUIDFast(_PREHASH_TransactionData,
|
|
_PREHASH_TransactionID,
|
|
trans_id);
|
|
|
|
if ( self->mProposalTransID != trans_id ) return;
|
|
|
|
|
|
U32 num_expected;
|
|
std::string item_num_string;
|
|
std::string proposal_text;
|
|
std::string vote_cast;
|
|
std::string start_datetime;
|
|
std::string end_datetime;
|
|
std::string vote_type;
|
|
std::string majority_text;
|
|
std::string quorum_text;
|
|
std::string vote_initiator_string;
|
|
|
|
LLUUID vote_id;
|
|
LLUUID vote_initiator;
|
|
|
|
F32 majority;
|
|
S32 quorum;
|
|
BOOL already_voted;
|
|
S32 num_proposals = msg->getNumberOfBlocksFast(_PREHASH_ProposalData);
|
|
|
|
msg->getU32Fast(_PREHASH_TransactionData,
|
|
_PREHASH_TotalNumItems,
|
|
num_expected);
|
|
|
|
//the first item should be indicative that we
|
|
//are currently receiving information or have it all
|
|
self->mProposals->deleteAllItems();
|
|
// make sure column indices are correct when populating with real data
|
|
self->mProposals->clearColumns();
|
|
|
|
for (int i = 0; i < num_proposals; i++)
|
|
{
|
|
msg->getStringFast(_PREHASH_ProposalData, _PREHASH_TerseDateID, item_num_string, i );
|
|
msg->getUUIDFast(_PREHASH_ProposalData, _PREHASH_VoteID, vote_id, i );
|
|
msg->getStringFast(_PREHASH_ProposalData, _PREHASH_StartDateTime, start_datetime, i );
|
|
msg->getStringFast(_PREHASH_ProposalData, _PREHASH_EndDateTime, end_datetime, i );
|
|
msg->getUUIDFast(_PREHASH_ProposalData, _PREHASH_VoteInitiator, vote_initiator, i );
|
|
msg->getBOOLFast(_PREHASH_ProposalData,_PREHASH_AlreadyVoted, already_voted, i );
|
|
msg->getStringFast(_PREHASH_ProposalData,_PREHASH_VoteCast, vote_cast, i );
|
|
msg->getStringFast(_PREHASH_ProposalData, _PREHASH_ProposalText, proposal_text, i );
|
|
msg->getF32Fast(_PREHASH_ProposalData, _PREHASH_Majority, majority, i );
|
|
msg->getS32Fast(_PREHASH_ProposalData, _PREHASH_Quorum, quorum, i );
|
|
|
|
vote_initiator.toString(vote_initiator_string);
|
|
majority_text = llformat("%f", majority);
|
|
quorum_text = llformat("%i", quorum);
|
|
|
|
LLSD row;
|
|
S32 index = 0;
|
|
row["id"] = vote_id;
|
|
row["columns"][0]["column"] = "item_num";
|
|
row["columns"][0]["value"] = item_num_string;
|
|
row["columns"][0]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][0]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][1]["column"] = "proposal_text";
|
|
row["columns"][1]["value"] = proposal_text;
|
|
row["columns"][1]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][1]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][2]["column"] = "end_datetime";
|
|
row["columns"][2]["value"] = format_date(end_datetime);
|
|
row["columns"][2]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][2]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][3]["column"] = "vote_type";
|
|
row["columns"][3]["value"] = vote_type;
|
|
row["columns"][3]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][3]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][4]["column"] = "already_voted";
|
|
row["columns"][4]["value"] = already_voted ? "Yes" : "No";
|
|
row["columns"][4]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][4]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][5]["column"] = "start_datetime";
|
|
row["columns"][5]["value"] = format_date(start_datetime);
|
|
row["columns"][5]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][5]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][6]["column"] = "vote_cast";
|
|
row["columns"][6]["value"] = vote_cast;
|
|
row["columns"][6]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][6]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][7]["column"] = "vote_initator_string";
|
|
row["columns"][7]["value"] = vote_initiator_string;
|
|
row["columns"][7]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][7]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][8]["column"] = "quorum_text";
|
|
row["columns"][8]["value"] = quorum_text;
|
|
row["columns"][8]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][8]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
row["columns"][9]["column"] = "majority_text";
|
|
row["columns"][9]["value"] = majority_text;
|
|
row["columns"][9]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][9]["width"] = self->mProposalColumnWidths[index++];
|
|
|
|
self->mActiveReceived.push_back(row);
|
|
}
|
|
|
|
int received = self->mActiveReceived.size();
|
|
if ( num_expected == 0 )
|
|
{
|
|
//we are expecting 0 items, put up a message indicating tehre are
|
|
//no active proposals and make the scroll list unselectable
|
|
self->addNoActiveScrollListItem(ADD_BOTTOM);
|
|
self->mProposals->setCanSelect(FALSE);
|
|
self->mBtnViewProposalItem->setEnabled(FALSE);
|
|
}
|
|
else if ( (U32)received != num_expected )
|
|
{
|
|
self->addPendingActiveScrollListItem(received,
|
|
num_expected,
|
|
ADD_BOTTOM);
|
|
self->mProposals->setCanSelect(FALSE);
|
|
self->mBtnViewProposalItem->setEnabled(FALSE);
|
|
}
|
|
else
|
|
{
|
|
//all done display all of the items
|
|
std::vector<LLSD>::iterator it = self->mActiveReceived.begin();
|
|
std::vector<LLSD>::iterator end = self->mActiveReceived.end();
|
|
|
|
for (; it != end; it++)
|
|
{
|
|
self->mProposals->addElement((*it), ADD_SORTED);
|
|
}
|
|
|
|
self->mProposals->setCanSelect(TRUE);
|
|
self->mBtnViewProposalItem->setEnabled(TRUE);
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem *msg, void**)
|
|
{
|
|
LLUUID agent_id;
|
|
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
|
|
if (gAgent.getID() != agent_id)
|
|
{
|
|
llwarns << "Got group voting history reply for another agent!" << llendl;
|
|
return;
|
|
}
|
|
|
|
LLUUID group_id;
|
|
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
|
|
impl* self = sGroupIDs[group_id];
|
|
if (!self)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LLUUID trans_id;
|
|
U32 num_expected;
|
|
|
|
msg->getU32Fast(_PREHASH_TransactionData,
|
|
_PREHASH_TotalNumItems,
|
|
num_expected);
|
|
msg->getUUIDFast(_PREHASH_TransactionData,
|
|
_PREHASH_TransactionID,
|
|
trans_id);
|
|
|
|
if ( self->mHistoryTransID != trans_id ) return;
|
|
|
|
//the first item should be some text
|
|
//explaining that we are attempting to receive information
|
|
//or are currently receiving information, so we should clear out
|
|
//the first line
|
|
self->mVotesHistory->deleteAllItems();
|
|
// make sure column indices are correct when populating with real data
|
|
self->mVotesHistory->clearColumns();
|
|
|
|
if ( num_expected == 0 )
|
|
{
|
|
//we are expecting 0 items, put up a message indicating tehre are
|
|
//no active proposals and make the scroll list unselectable
|
|
self->addNoHistoryScrollListItem(ADD_BOTTOM);
|
|
self->mVotesHistory->setCanSelect(FALSE);
|
|
self->mBtnViewHistoryItem->setEnabled(FALSE);
|
|
return;
|
|
}
|
|
|
|
std::string item_num_string;
|
|
std::string proposal_text;
|
|
std::string vote_result;
|
|
std::string start_datetime;
|
|
std::string end_datetime;
|
|
std::string vote_type;
|
|
|
|
std::string vote_text;
|
|
LLUUID vote_id;
|
|
LLUUID vote_initiator;
|
|
LLUUID winner_id;
|
|
|
|
F32 majority;
|
|
S32 quorum;
|
|
|
|
msg->getStringFast(_PREHASH_HistoryItemData, _PREHASH_TerseDateID, item_num_string );
|
|
msg->getUUIDFast(_PREHASH_HistoryItemData, _PREHASH_VoteID, vote_id );
|
|
msg->getStringFast(_PREHASH_HistoryItemData, _PREHASH_StartDateTime, start_datetime );
|
|
msg->getStringFast(_PREHASH_HistoryItemData, _PREHASH_EndDateTime, end_datetime );
|
|
msg->getUUIDFast(_PREHASH_HistoryItemData, _PREHASH_VoteInitiator, vote_initiator);
|
|
msg->getStringFast(_PREHASH_HistoryItemData, _PREHASH_VoteType, vote_type);
|
|
msg->getStringFast(_PREHASH_HistoryItemData,_PREHASH_VoteResult, vote_result);
|
|
msg->getStringFast(_PREHASH_HistoryItemData, _PREHASH_ProposalText, proposal_text );
|
|
msg->getF32Fast(_PREHASH_HistoryItemData, _PREHASH_Majority, majority);
|
|
msg->getS32Fast(_PREHASH_HistoryItemData, _PREHASH_Quorum, quorum);
|
|
|
|
S32 vote_items = msg->getNumberOfBlocksFast(_PREHASH_VoteItem);
|
|
|
|
if (vote_items > 0)
|
|
{
|
|
if (vote_type == "Proposal")
|
|
{
|
|
LLSD row;
|
|
row["id"] = vote_id;
|
|
|
|
S32 index = 0;
|
|
row["columns"][0]["column"] = "item_num";
|
|
row["columns"][0]["value"] = item_num_string;
|
|
row["columns"][0]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][0]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
vote_text.assign(proposal_text);
|
|
vote_text.append("\n\n--\n");
|
|
if (vote_result == "Success")
|
|
{
|
|
vote_text.append("Proposal PASSED.");
|
|
}
|
|
else
|
|
{
|
|
vote_text.append("Proposal FAILED.");
|
|
}
|
|
vote_text.append(" Votes->\n");
|
|
|
|
std::string vote_result;
|
|
S32 num_votes;
|
|
|
|
for (S32 i = 0; i < vote_items; ++i)
|
|
{
|
|
msg->getStringFast(_PREHASH_VoteItem, _PREHASH_VoteCast, vote_result, i);
|
|
msg->getS32Fast(_PREHASH_VoteItem, _PREHASH_NumVotes, num_votes, i);
|
|
vote_text.append(llformat(" %s: %d\n", vote_result.c_str(), num_votes));
|
|
}
|
|
|
|
vote_text.append("\n");
|
|
|
|
std::string vote_text_stripped = vote_text;
|
|
LLStringUtil::stripNonprintable(vote_text_stripped);
|
|
|
|
row["columns"][1]["column"] = "vote_text_stripped";
|
|
row["columns"][1]["value"] = vote_text_stripped;
|
|
row["columns"][1]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][1]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
row["columns"][2]["column"] = "end_datetime";
|
|
row["columns"][2]["value"] = format_date(end_datetime);
|
|
row["columns"][2]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][2]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
row["columns"][3]["column"] = "vote_type";
|
|
row["columns"][3]["value"] = vote_type;
|
|
row["columns"][3]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][3]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
row["columns"][4]["column"] = "vote_result";
|
|
row["columns"][4]["value"] = vote_result;
|
|
row["columns"][4]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][4]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
row["columns"][5]["column"] = "vote_text";
|
|
row["columns"][5]["value"] = vote_text;
|
|
row["columns"][5]["font"] = "SANSSERIF_SMALL";
|
|
row["columns"][5]["width"] = self->mHistoryColumnWidths[index++];
|
|
|
|
//row->addColumn(vote_text_stripped, font, self->mHistoryColumnWidths[1]);
|
|
//row->addColumn(end_datetime, font, self->mHistoryColumnWidths[2]);
|
|
//row->addColumn(vote_type, font, self->mHistoryColumnWidths[3]);
|
|
//row->addColumn(vote_result, font, self->mHistoryColumnWidths[4]);
|
|
//row->addColumn(vote_text, font, self->mHistoryColumnWidths[5]);
|
|
|
|
self->mHistoryReceived.push_back(row);
|
|
} //end if proposal
|
|
else
|
|
{
|
|
llinfos << "Vote is not a proposal, but a " << vote_type << llendl;
|
|
self->mOtherGroupHistoryItems++;
|
|
}
|
|
} //end if vote_items > 0
|
|
|
|
int received = self->mHistoryReceived.size();
|
|
if ( (U32)received + self->mOtherGroupHistoryItems != num_expected )
|
|
{
|
|
self->addPendingHistoryScrollListItem(received,
|
|
num_expected,
|
|
ADD_BOTTOM);
|
|
self->mVotesHistory->setCanSelect(FALSE);
|
|
self->mBtnViewHistoryItem->setEnabled(FALSE);
|
|
}
|
|
else
|
|
{
|
|
//all done display all of the items
|
|
std::vector<LLSD>::iterator it = self->mHistoryReceived.begin();
|
|
std::vector<LLSD>::iterator end = self->mHistoryReceived.end();
|
|
|
|
for (; it != end; it++)
|
|
{
|
|
self->mVotesHistory->addElement((*it), ADD_SORTED);
|
|
}
|
|
|
|
self->mVotesHistory->setCanSelect(TRUE);
|
|
self->mBtnViewHistoryItem->setEnabled(TRUE);
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickCreateProposal(void* userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
if ( self ) self->setEnableCreateProposal();
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickYes(void *userdata)
|
|
{
|
|
LLPanelGroupVoting::impl* self = (LLPanelGroupVoting::impl*)userdata;
|
|
|
|
if ( self )
|
|
{
|
|
self->mPanel.childSetText("proposal_instructions", self->mPanel.getString("proposals_submit_yes_txt"));
|
|
self->sendGroupProposalBallot("Yes");
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickNo(void *userdata)
|
|
{
|
|
LLPanelGroupVoting::impl* self = (LLPanelGroupVoting::impl*)userdata;
|
|
|
|
if ( self )
|
|
{
|
|
self->mPanel.childSetText("proposal_instructions", self->mPanel.getString("proposals_submit_no_txt"));
|
|
self->sendGroupProposalBallot("No");
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickAbstain(void *userdata)
|
|
{
|
|
impl* self = (LLPanelGroupVoting::impl*) userdata;
|
|
|
|
if ( self )
|
|
{
|
|
self->mPanel.childSetText("proposal_instructions", self->mPanel.getString("proposals_submit_abstain_txt"));
|
|
self->sendGroupProposalBallot("Abstain");
|
|
}
|
|
}
|
|
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickSubmitProposal(void *userdata)
|
|
{
|
|
gFocusMgr.setKeyboardFocus(NULL);
|
|
impl* self = (impl*)userdata;
|
|
|
|
if ( self && self->mProposalText )
|
|
{
|
|
//check to see if the proposal has any text for some form of
|
|
//"validation"
|
|
if ( self->mProposalText->getText().empty() )
|
|
{
|
|
//throw up an error dialog
|
|
LLSD args;
|
|
args["MESSAGE"] = self->mPanel.getString("empty_proposal_txt");
|
|
LLNotificationsUtil::add("GenericAlert", args);
|
|
return;
|
|
}
|
|
|
|
self->mPanel.childSetText("proposal_instructions", self->mPanel.getString("proposals_submit_new_txt"));
|
|
self->sendStartGroupProposal();
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickCancelProposal(void* userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
|
|
if ( self )
|
|
{
|
|
self->setEnableListProposals();
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickViewProposalList(void *userdata)
|
|
{
|
|
impl* self = (LLPanelGroupVoting::impl*)userdata;
|
|
|
|
if ( self ) self->setEnableListProposals();
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickViewProposalItem(void *userdata)
|
|
{
|
|
impl* self = (LLPanelGroupVoting::impl*)userdata;
|
|
|
|
if ( self && self->mProposals )
|
|
{
|
|
LLScrollListItem * proposal = self->mProposals->getFirstSelected();
|
|
// Check if it has anything in column 2. If not, assume it's the "There are currently no active proposals" text
|
|
if (proposal && proposal->getColumn(2))
|
|
{
|
|
self->setEnableVoteProposal();
|
|
}
|
|
else
|
|
{
|
|
LLNotificationsUtil::add("SelectProposalToView");
|
|
}
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onDoubleClickProposal(void *userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
if ( self && self->mProposals->getFirstSelected() != NULL )
|
|
{
|
|
self->setEnableVoteProposal();
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onDoubleClickHistoryItem(void *userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
if ( self && self->mVotesHistory->getFirstSelected() != NULL )
|
|
{
|
|
self->setEnableHistoryItem();
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickViewHistoryItem(void *userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
|
|
if ( self && self->mVotesHistory )
|
|
{
|
|
LLScrollListItem * historic = self->mVotesHistory->getFirstSelected();
|
|
// Check if it has anything in column 2. If not, assume it's the "There are currently no active proposals" text
|
|
if (historic && historic->getColumn(2))
|
|
{
|
|
self->setEnableHistoryItem();
|
|
}
|
|
else
|
|
{
|
|
LLNotificationsUtil::add("SelectHistoryItemToView");
|
|
}
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelGroupVoting::impl::onClickViewHistoryList(void *userdata)
|
|
{
|
|
impl* self = (impl*)userdata;
|
|
|
|
if ( self) self->setEnableHistoryList();
|
|
}
|
|
|
|
// **********************************
|
|
// ** LLPanelGroupVoting Functions **
|
|
// **********************************
|
|
|
|
// static
|
|
void* LLPanelGroupVoting::createTab(void* data)
|
|
{
|
|
LLUUID* group_id = static_cast<LLUUID*>(data);
|
|
return new LLPanelGroupVoting("panel group voting", *group_id);
|
|
}
|
|
|
|
LLPanelGroupVoting::LLPanelGroupVoting(const std::string& name,
|
|
const LLUUID& group_id)
|
|
: LLPanelGroupTab(name, group_id)
|
|
{
|
|
mImpl = new impl(*this, group_id);
|
|
}
|
|
|
|
LLPanelGroupVoting::~LLPanelGroupVoting()
|
|
{
|
|
delete mImpl;
|
|
}
|
|
|
|
BOOL LLPanelGroupVoting::isVisibleByAgent(LLAgent* agentp)
|
|
{
|
|
//if they are in the group, the panel is viewable
|
|
return mAllowEdit && agentp->isInGroup(mGroupID);
|
|
}
|
|
|
|
BOOL LLPanelGroupVoting::postBuild()
|
|
{
|
|
bool recurse = true;
|
|
|
|
mImpl->mDurationText = getChild<LLTextBox>("duration_text",
|
|
recurse);
|
|
mImpl->mQuorum = getChild<LLSpinCtrl>("quorum", recurse);
|
|
mImpl->mQuorumLbl = getChild<LLTextBox>("quorum_lbl", recurse);
|
|
mImpl->mDuration = getChild<LLSpinCtrl>("duration", recurse);
|
|
mImpl->mDurationLbl = getChild<LLTextBox>("duration_lbl", recurse);
|
|
mImpl->mMajority = getChild<LLRadioGroup>("majority", recurse);
|
|
mImpl->mMajorityLbl = getChild<LLTextBox>("majority_lbl", recurse);
|
|
|
|
mImpl->mStartLbl = getChild<LLTextBox>("start_lbl", recurse);
|
|
mImpl->mEndLbl = getChild<LLTextBox>("end_lbl", recurse);
|
|
mImpl->mStartDate = getChild<LLTextBox>("start_date", recurse);
|
|
mImpl->mEndDate = getChild<LLTextBox>("end_date", recurse);
|
|
|
|
mImpl->mBtnYes = getChild<LLButton>("btn_yes", recurse);
|
|
mImpl->mBtnNo = getChild<LLButton>("btn_no", recurse);
|
|
mImpl->mBtnAbstain = getChild<LLButton>("btn_abstain", recurse);
|
|
|
|
mImpl->mProposals =
|
|
getChild<LLScrollListCtrl>("proposals", recurse);
|
|
mImpl->mProposalText =
|
|
getChild<LLTextEditor>("proposal_text", recurse);
|
|
|
|
mImpl->mBtnCreateProposal = getChild<LLButton>("btn_proposal",
|
|
recurse);
|
|
mImpl->mBtnSubmitProposal = getChild<LLButton>("btn_submit",
|
|
recurse);
|
|
mImpl->mBtnCancelProposal = getChild<LLButton>("btn_cancel",
|
|
recurse);
|
|
|
|
mImpl->mBtnViewProposalList =
|
|
getChild<LLButton>("btn_view_proposal_list", recurse);
|
|
mImpl->mBtnViewProposalItem =
|
|
getChild<LLButton>("btn_view_proposal_item", recurse);
|
|
|
|
mImpl->mVotesHistory = getChild<LLScrollListCtrl>("history_list",
|
|
recurse);
|
|
mImpl->mVotesHistoryLbl = getChild<LLTextBox>("history_list_lbl",
|
|
recurse);
|
|
mImpl->mVoteHistoryText = getChild<LLTextEditor>("vote_text",
|
|
recurse);
|
|
mImpl->mVoteHistoryTextLbl = getChild<LLTextBox>("vote_text_lbl",
|
|
recurse);
|
|
|
|
mImpl->mBtnViewHistoryList =
|
|
getChild<LLButton>("btn_view_history_list", recurse);
|
|
mImpl->mBtnViewHistoryItem =
|
|
getChild<LLButton>("btn_view_history_item", recurse);
|
|
|
|
mImpl->updateQuorumText();
|
|
|
|
bool success = (mImpl->mDurationText &&
|
|
mImpl->mQuorum &&
|
|
mImpl->mQuorumLbl &&
|
|
mImpl->mDuration &&
|
|
mImpl->mDurationLbl &&
|
|
mImpl->mMajority &&
|
|
mImpl->mMajorityLbl &&
|
|
mImpl->mStartLbl &&
|
|
mImpl->mEndLbl &&
|
|
mImpl->mStartDate &&
|
|
mImpl->mEndDate &&
|
|
mImpl->mBtnYes &&
|
|
mImpl->mBtnNo &&
|
|
mImpl->mBtnAbstain &&
|
|
mImpl->mProposals &&
|
|
mImpl->mProposalText &&
|
|
mImpl->mBtnCreateProposal &&
|
|
mImpl->mBtnSubmitProposal &&
|
|
mImpl->mBtnCancelProposal &&
|
|
mImpl->mBtnViewProposalList &&
|
|
mImpl->mBtnViewProposalItem &&
|
|
mImpl->mVotesHistory &&
|
|
mImpl->mVotesHistoryLbl &&
|
|
mImpl->mVoteHistoryText &&
|
|
mImpl->mVoteHistoryTextLbl &&
|
|
mImpl->mBtnViewHistoryList &&
|
|
mImpl->mBtnViewHistoryItem );
|
|
|
|
//associate callbacks
|
|
if ( success )
|
|
{
|
|
mImpl->mProposals->setDoubleClickCallback(impl::onDoubleClickProposal);
|
|
mImpl->mProposals->setCallbackUserData(mImpl);
|
|
|
|
mImpl->mVotesHistory->setDoubleClickCallback(impl::onDoubleClickHistoryItem);
|
|
mImpl->mVotesHistory->setCallbackUserData(mImpl);
|
|
|
|
mImpl->mBtnAbstain->setClickedCallback(boost::bind(&impl::onClickAbstain,mImpl));
|
|
|
|
mImpl->mBtnNo->setClickedCallback(boost::bind(&impl::onClickNo,mImpl));
|
|
|
|
mImpl->mBtnYes->setClickedCallback(boost::bind(&impl::onClickYes,mImpl));
|
|
|
|
mImpl->mBtnCreateProposal->setClickedCallback(boost::bind(&impl::onClickCreateProposal,mImpl));
|
|
|
|
mImpl->mBtnSubmitProposal->setClickedCallback(boost::bind(&impl::onClickSubmitProposal,mImpl));
|
|
|
|
mImpl->mBtnCancelProposal->setClickedCallback(boost::bind(&impl::onClickCancelProposal,mImpl));
|
|
|
|
mImpl->mBtnViewProposalList->setClickedCallback(boost::bind(&impl::onClickViewProposalList,mImpl));
|
|
|
|
mImpl->mBtnViewProposalItem->setClickedCallback(boost::bind(&impl::onClickViewProposalItem,mImpl));
|
|
|
|
mImpl->mBtnViewHistoryList->setClickedCallback(boost::bind(&impl::onClickViewHistoryList,mImpl));
|
|
|
|
mImpl->mBtnViewHistoryItem->setClickedCallback(boost::bind(&impl::onClickViewHistoryItem,mImpl));
|
|
|
|
gMessageSystem->setHandlerFuncFast(_PREHASH_GroupActiveProposalItemReply,
|
|
impl::processGroupActiveProposalItemReply);
|
|
gMessageSystem->setHandlerFuncFast(_PREHASH_GroupVoteHistoryItemReply,
|
|
impl::processGroupVoteHistoryItemReply);
|
|
}
|
|
|
|
return success && LLPanelGroupTab::postBuild();
|
|
}
|
|
|
|
|
|
void LLPanelGroupVoting::activate()
|
|
{
|
|
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
|
|
update(GC_ALL);
|
|
|
|
mImpl->setEnableListProposals();
|
|
mImpl->setEnableHistoryList();
|
|
}
|
|
|
|
bool LLPanelGroupVoting::needsApply(std::string& mesg)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool LLPanelGroupVoting::apply(std::string& mesg)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void LLPanelGroupVoting::update(LLGroupChange gc)
|
|
{
|
|
LLGroupMgrGroupData* group_datap = NULL;
|
|
group_datap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
|
|
|
|
if ( group_datap )
|
|
{
|
|
S32 num_group_members = group_datap->mMemberCount;
|
|
mImpl->mNumGroupMembers = num_group_members;
|
|
|
|
mImpl->updateQuorumText();
|
|
}
|
|
|
|
mImpl->sendGroupProposalsRequest(mGroupID);
|
|
mImpl->sendGroupVoteHistoryRequest(mGroupID);
|
|
}
|
|
|
|
|