Files
SingularityViewer/indra/newview/llpanelgroupvoting.cpp
Aleric Inglewood 74dff061ff Support for new LL Responder API.
This adds mStatus, mReason and mContent to ResponderBase
and fills those in instead of passing it to member functions.
The added danger here is that now code can accidently try
to access these variables while they didn't already get a
correct value.

Affected members of ResponderBase (that now have less arguments):
decode_llsd_body, decode_raw_body, completedHeaders,
completed -> httpCompleted, result -> httpSuccess,
errorWithContent and error -> httpFailure.

New API:

ResponderBase::setResult
ResponderBase::getStatus()
ResponderBase::getReason()
ResponderBase::getContent()
ResponderBase::getResponseHeaders() (returns AIHTTPReceivedHeaders though, not LLSD)
ResponderBase::dumpResponse()
ResponderWithCompleted::completeResult
ResponderWithResult::failureResult (previously pubErrorWithContent)
ResponderWithResult::successResult (previously pubResult)

Not implemented:

getHTTPMethod() - use getName() instead which returns the class name of the responder.

completedHeaders() is still called as usual, although you can ignore
it (not implement in a derived responder) and call getResponseHeaders()
instead, provided you implement needsHeaders() and have it return true.

However, classes derived from ResponderHeadersOnly do not have
completedHeaders(), so they still must implement completedHeaders(),
and then call getResponseHeaders() or just access mReceivedHeaders
directly, as usual.
2014-07-12 18:29:44 +02:00

1649 lines
48 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 "llpanelgroupvoting.h"
#include "llbutton.h"
#include "llnotificationsutil.h"
#include "llradiogroup.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llspinctrl.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "llagent.h"
#include "llviewercontrol.h"
#include "llviewerregion.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy startGroupVoteResponder_timeout;
extern AIHTTPTimeoutPolicy groupProposalBallotResponder_timeout;
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::ResponderWithResult
{
public:
LLStartGroupVoteResponder(const LLUUID& group_id)
{
mGroupID = group_id;
}
//If we get back a normal response, handle it here
/*virtual*/ void httpSuccess(void)
{
//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 httpFailure(void)
{
llinfos << "LLPanelGroupVotingResponder::error "
<< mStatus << ": " << mReason << llendl;
LLPanelGroupVoting::handleFailure(mGroupID);
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return startGroupVoteResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLStartGroupVoteResponder"; }
private:
LLUUID mGroupID;
};
class LLGroupProposalBallotResponder : public LLHTTPClient::ResponderWithResult
{
public:
LLGroupProposalBallotResponder(const LLUUID& group_id)
{
mGroupID = group_id;
}
//If we get back a normal response, handle it here
/*virtual*/ void httpSuccess(void)
{
//Ack'd the proposal initialization, now let's finish up.
LLPanelGroupVoting::handleResponse(
mGroupID,
LLPanelGroupVoting::BALLOT,
mContent["voted"].asBoolean());
}
//If we get back an error (not found, etc...), handle it here
/*virtual*/ void httpFailure(void)
{
llinfos << "LLPanelGroupVotingResponder::error "
<< mStatus << ": " << mReason << llendl;
LLPanelGroupVoting::handleFailure(mGroupID);
}
//Return out timeout policy.
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return groupProposalBallotResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLGroupProposalBallotResponder"; }
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));
}
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));
}
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->setCommentText(pending.str());
}
void LLPanelGroupVoting::impl::addNoActiveScrollListItem(EAddPosition pos)
{
// *TODO: translate
mProposals->setCommentText(std::string("There are currently no active proposals"));
}
void LLPanelGroupVoting::impl::addNoHistoryScrollListItem(EAddPosition pos)
{
// *TODO: translate
mVotesHistory->setCommentText(std::string("There are currently no archived proposals"));
}
void LLPanelGroupVoting::impl::addPendingHistoryScrollListItem(unsigned int current,
unsigned int expected,
EAddPosition pos)
{
// *TODO: translate
std::stringstream pending;
pending << "Retrieving archived proposals ("
<< current
<< "\\" << expected << ")";
mVotesHistory->setCommentText(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 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(boost::bind(&LLPanelGroupVoting::impl::onDoubleClickProposal,mImpl));
mImpl->mVotesHistory->setDoubleClickCallback(boost::bind(&LLPanelGroupVoting::impl::onDoubleClickHistoryItem,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);
}