summaryrefslogtreecommitdiff
path: root/indra/newview/llfloaterbuyland.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 21:25:21 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-22 22:40:26 +0300
commite2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch)
tree1bb897489ce524986f6196201c10ac0d8861aa5f /indra/newview/llfloaterbuyland.cpp
parent069ea06848f766466f1a281144c82a0f2bd79f3a (diff)
Fix line endlings
Diffstat (limited to 'indra/newview/llfloaterbuyland.cpp')
-rw-r--r--indra/newview/llfloaterbuyland.cpp2758
1 files changed, 1379 insertions, 1379 deletions
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 2287900e5f..570a223908 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -1,1379 +1,1379 @@
-/**
- * @file llfloaterbuyland.cpp
- * @brief LLFloaterBuyLand class implementation
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterbuyland.h"
-
-// viewer includes
-#include "llagent.h"
-#include "llbutton.h"
-#include "llcachename.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
-#include "llconfirmationmanager.h"
-#include "llcurrencyuimanager.h"
-#include "llfloater.h"
-#include "llfloaterreg.h"
-#include "llfloatertools.h"
-#include "llframetimer.h"
-#include "lliconctrl.h"
-#include "lllineeditor.h"
-#include "llnotificationsutil.h"
-#include "llparcel.h"
-#include "llslurl.h"
-#include "llstatusbar.h"
-#include "lltextbox.h"
-#include "lltexturectrl.h"
-#include "lltrans.h"
-#include "llviewchildren.h"
-#include "llviewercontrol.h"
-#include "lluictrlfactory.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h"
-#include "llviewertexteditor.h"
-#include "llviewerwindow.h"
-#include "llweb.h"
-#include "llwindow.h"
-#include "llworld.h"
-#include "llxmlrpctransaction.h"
-#include "llviewernetwork.h"
-#include "roles_constants.h"
-
-// NOTE: This is duplicated in lldatamoney.cpp ...
-const F32 GROUP_LAND_BONUS_FACTOR = 1.1f;
-
-class LLFloaterBuyLandUI
-: public LLFloater
-{
-public:
- LLFloaterBuyLandUI(const LLSD& key);
- virtual ~LLFloaterBuyLandUI();
-
- /*virtual*/ void onClose(bool app_quitting);
-
- // Left padding for maturity rating icon.
- static const S32 ICON_PAD = 2;
-
-private:
- class SelectionObserver : public LLParcelObserver
- {
- public:
- SelectionObserver(LLFloaterBuyLandUI* floater) : mFloater(floater) {}
- virtual void changed();
- private:
- LLFloaterBuyLandUI* mFloater;
- };
-
-private:
- SelectionObserver mParcelSelectionObserver;
- LLViewerRegion* mRegion;
- LLParcelSelectionHandle mParcel;
- bool mIsClaim;
- bool mIsForGroup;
-
- bool mCanBuy;
- bool mCannotBuyIsError;
- std::string mCannotBuyReason;
- std::string mCannotBuyURI;
-
- bool mBought;
-
- // information about the agent
- S32 mAgentCommittedTier;
- S32 mAgentCashBalance;
- bool mAgentHasNeverOwnedLand;
-
- // information about the parcel
- bool mParcelValid;
- bool mParcelIsForSale;
- bool mParcelIsGroupLand;
- S32 mParcelGroupContribution;
- S32 mParcelPrice;
- S32 mParcelActualArea;
- S32 mParcelBillableArea;
- S32 mParcelSupportedObjects;
- bool mParcelSoldWithObjects;
- std::string mParcelLocation;
- LLUUID mParcelSnapshot;
- std::string mParcelSellerName;
-
- // user's choices
- S32 mUserPlanChoice;
-
- // from website
- bool mSiteValid;
- bool mSiteMembershipUpgrade;
- std::string mSiteMembershipAction;
- std::vector<std::string>
- mSiteMembershipPlanIDs;
- std::vector<std::string>
- mSiteMembershipPlanNames;
- bool mSiteLandUseUpgrade;
- std::string mSiteLandUseAction;
- std::string mSiteConfirm;
-
- // values in current Preflight transaction... used to avoid extra
- // preflights when the parcel manager goes update crazy
- S32 mPreflightAskBillableArea;
- S32 mPreflightAskCurrencyBuy;
-
- LLViewChildren mChildren;
- LLCurrencyUIManager mCurrency;
-
- enum TransactionType
- {
- TransactionPreflight,
- TransactionCurrency,
- TransactionBuy
- };
- LLXMLRPCTransaction* mTransaction;
- TransactionType mTransactionType;
-
- LLViewerParcelMgr::ParcelBuyInfo* mParcelBuyInfo;
-
-public:
- void setForGroup(bool is_for_group);
- void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
-
- void updateAgentInfo();
- void updateParcelInfo();
- void updateCovenantInfo();
- static void onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data);
- void updateFloaterCovenantText(const std::string& string, const LLUUID &asset_id);
- void updateFloaterEstateName(const std::string& name);
- void updateFloaterLastModified(const std::string& text);
- void updateFloaterEstateOwnerName(const std::string& name);
- void updateWebSiteInfo();
- void finishWebSiteInfo();
-
- void runWebSitePrep(const std::string& password);
- void finishWebSitePrep();
- void sendBuyLand();
-
- void updateNames();
- // Name cache callback
- void updateGroupName(const LLUUID& id,
- const std::string& name,
- bool is_group);
-
- void refreshUI();
-
- void startTransaction(TransactionType type, const LLXMLRPCValue& params);
- bool checkTransaction();
-
- void tellUserError(const std::string& message, const std::string& uri);
-
- virtual bool postBuild();
-
- void startBuyPreConfirm();
- void startBuyPostConfirm(const std::string& password);
-
- void onClickBuy();
- void onClickCancel();
- void onClickErrorWeb();
-
- virtual void draw();
- virtual bool canClose();
-
- void onVisibilityChanged ( const LLSD& new_visibility );
-
-};
-
-// static
-void LLFloaterBuyLand::buyLand(
- LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
-{
- if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
- {
- LLNotificationsUtil::add("OnlyOfficerCanBuyLand");
- return;
- }
-
- LLFloaterBuyLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (ui)
- {
- ui->setForGroup(is_for_group);
- ui->setParcel(region, parcel);
- }
-}
-
-// static
-void LLFloaterBuyLand::updateCovenantText(const std::string& string, const LLUUID &asset_id)
-{
- LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (floater)
- {
- floater->updateFloaterCovenantText(string, asset_id);
- }
-}
-
-// static
-void LLFloaterBuyLand::updateEstateName(const std::string& name)
-{
- LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (floater)
- {
- floater->updateFloaterEstateName(name);
- }
-}
-
-// static
-void LLFloaterBuyLand::updateLastModified(const std::string& text)
-{
- LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (floater)
- {
- floater->updateFloaterLastModified(text);
- }
-}
-
-// static
-void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name)
-{
- LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
- if (floater)
- {
- floater->updateFloaterEstateOwnerName(name);
- }
-}
-
-// static
-LLFloater* LLFloaterBuyLand::buildFloater(const LLSD& key)
-{
- LLFloaterBuyLandUI* floater = new LLFloaterBuyLandUI(key);
- return floater;
-}
-
-//----------------------------------------------------------------------------
-// LLFloaterBuyLandUI
-//----------------------------------------------------------------------------
-
-#if LL_WINDOWS
-// passing 'this' during construction generates a warning. The callee
-// only uses the pointer to hold a reference to 'this' which is
-// already valid, so this call does the correct thing. Disable the
-// warning so that we can compile without generating a warning.
-#pragma warning(disable : 4355)
-#endif
-LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
-: LLFloater(LLSD()),
- mParcelSelectionObserver(this),
- mParcel(0),
- mBought(false),
- mParcelValid(false), mSiteValid(false),
- mChildren(*this), mCurrency(*this), mTransaction(0),
- mParcelBuyInfo(0)
-{
- LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
-
-}
-
-LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
-{
- LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
-
- delete mTransaction;
-}
-
-// virtual
-void LLFloaterBuyLandUI::onClose(bool app_quitting)
-{
- // This object holds onto observer, transactions, and parcel state.
- // Despite being single_instance, destroy it to call destructors and clean
- // everything up.
- setVisible(false);
- destroy();
-}
-
-void LLFloaterBuyLandUI::SelectionObserver::changed()
-{
- if (LLViewerParcelMgr::getInstance()->selectionEmpty())
- {
- mFloater->closeFloater();
- }
- else
- {
- mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
- LLViewerParcelMgr::getInstance()->getParcelSelection());
- }
-}
-
-
-void LLFloaterBuyLandUI::updateAgentInfo()
-{
- mAgentCommittedTier = gStatusBar->getSquareMetersCommitted();
- mAgentCashBalance = gStatusBar->getBalance();
-
- // *TODO: This is an approximation, we should send this value down
- // to the viewer. See SL-10728 for details.
- mAgentHasNeverOwnedLand = mAgentCommittedTier == 0;
-}
-
-void LLFloaterBuyLandUI::updateParcelInfo()
-{
- LLParcel* parcel = mParcel->getParcel();
- mParcelValid = parcel && mRegion;
- mParcelIsForSale = false;
- mParcelIsGroupLand = false;
- mParcelGroupContribution = 0;
- mParcelPrice = 0;
- mParcelActualArea = 0;
- mParcelBillableArea = 0;
- mParcelSupportedObjects = 0;
- mParcelSoldWithObjects = false;
- mParcelLocation = "";
- mParcelSnapshot.setNull();
- mParcelSellerName = "";
-
- mCanBuy = false;
- mCannotBuyIsError = false;
-
- if (!mParcelValid)
- {
- mCannotBuyReason = getString("no_land_selected");
- return;
- }
-
- if (mParcel->getMultipleOwners())
- {
- mCannotBuyReason = getString("multiple_parcels_selected");
- return;
- }
-
- const LLUUID& parcelOwner = parcel->getOwnerID();
-
- mIsClaim = parcel->isPublic();
- if (!mIsClaim)
- {
- mParcelActualArea = parcel->getArea();
- mParcelIsForSale = parcel->getForSale();
- mParcelIsGroupLand = parcel->getIsGroupOwned();
- mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0;
-
- if (mParcelIsGroupLand)
- {
- LLUUID group_id = parcel->getGroupID();
- mParcelGroupContribution = gAgent.getGroupContribution(group_id);
- }
- }
- else
- {
- mParcelActualArea = mParcel->getClaimableArea();
- mParcelIsForSale = true;
- mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter();
- }
-
- mParcelBillableArea =
- ll_round(mRegion->getBillableFactor() * mParcelActualArea);
-
- mParcelSupportedObjects = ll_round(
- parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus());
- // Can't have more than region max tasks, regardless of parcel
- // object bonus factor.
- LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- if(region)
- {
- S32 max_tasks_per_region = (S32)region->getMaxTasks();
- mParcelSupportedObjects = llmin(
- mParcelSupportedObjects, max_tasks_per_region);
- }
-
- mParcelSoldWithObjects = parcel->getSellWithObjects();
-
-
- LLVector3 center = parcel->getCenterpoint();
- mParcelLocation = llformat("%s %d,%d",
- mRegion->getName().c_str(),
- (int)center[VX], (int)center[VY]
- );
-
- mParcelSnapshot = parcel->getSnapshotID();
-
- updateNames();
-
- bool haveEnoughCash = mParcelPrice <= mAgentCashBalance;
- S32 cashBuy = haveEnoughCash ? 0 : (mParcelPrice - mAgentCashBalance);
- mCurrency.setAmount(cashBuy, true);
- mCurrency.setZeroMessage(haveEnoughCash ? getString("none_needed") : LLStringUtil::null);
-
- // checks that we can buy the land
-
- if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
- {
- mCannotBuyReason = getString("cant_buy_for_group");
- return;
- }
-
- if (!mIsClaim)
- {
- const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID();
- const LLUUID buyer = gAgent.getID();
- const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer;
-
- if (!mParcelIsForSale
- || (mParcelPrice == 0 && authorizedBuyer.isNull()))
- {
-
- mCannotBuyReason = getString("parcel_not_for_sale");
- return;
- }
-
- if (parcelOwner == newOwner)
- {
- if (mIsForGroup)
- {
- mCannotBuyReason = getString("group_already_owns");
- }
- else
- {
- mCannotBuyReason = getString("you_already_own");
- }
- return;
- }
-
- if (!authorizedBuyer.isNull() && buyer != authorizedBuyer)
- {
- // Maybe the parcel is set for sale to a group we are in.
- bool authorized_group =
- gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED)
- && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO);
-
- if (!authorized_group)
- {
- mCannotBuyReason = getString("set_to_sell_to_other");
- return;
- }
- }
- }
- else
- {
- if (mParcelActualArea == 0)
- {
- mCannotBuyReason = getString("no_public_land");
- return;
- }
-
- if (mParcel->hasOthersSelected())
- {
- // Policy: Must not have someone else's land selected
- mCannotBuyReason = getString("not_owned_by_you");
- return;
- }
- }
-
- mCanBuy = true;
-}
-
-void LLFloaterBuyLandUI::updateCovenantInfo()
-{
- LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- if(!region) return;
-
- U8 sim_access = region->getSimAccess();
- std::string rating = LLViewerRegion::accessToString(sim_access);
-
- LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
- if (region_name)
- {
- std::string region_name_txt = region->getName() + " ("+rating +")";
- region_name->setText(region_name_txt);
-
- LLIconCtrl* rating_icon = getChild<LLIconCtrl>("rating_icon");
- LLRect rect = rating_icon->getRect();
- S32 region_name_width = llmin(region_name->getRect().getWidth(), region_name->getTextBoundingRect().getWidth());
- S32 icon_left_pad = region_name->getRect().mLeft + region_name_width + ICON_PAD;
- region_name->setToolTip(region_name->getText());
- rating_icon->setRect(rect.setOriginAndSize(icon_left_pad, rect.mBottom, rect.getWidth(), rect.getHeight()));
-
- switch(sim_access)
- {
- case SIM_ACCESS_PG:
- rating_icon->setValue(getString("icon_PG"));
- break;
-
- case SIM_ACCESS_ADULT:
- rating_icon->setValue(getString("icon_R"));
- break;
-
- default:
- rating_icon->setValue(getString("icon_M"));
- }
- }
-
- LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
- if (region_type)
- {
- region_type->setText(region->getLocalizedSimProductName());
- region_type->setToolTip(region->getLocalizedSimProductName());
- }
-
- LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
- if (resellable_clause)
- {
- if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))
- {
- resellable_clause->setText(getString("can_not_resell"));
- }
- else
- {
- resellable_clause->setText(getString("can_resell"));
- }
- }
-
- LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause");
- if (changeable_clause)
- {
- if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES))
- {
- changeable_clause->setText(getString("can_change"));
- }
- else
- {
- changeable_clause->setText(getString("can_not_change"));
- }
- }
-
- LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
- if(check)
- {
- check->set(false);
- check->setEnabled(true);
- check->setCommitCallback(onChangeAgreeCovenant, this);
- }
-
- LLTextBox* box = getChild<LLTextBox>("covenant_text");
- if(box)
- {
- box->setVisible(false);
- }
-
- // send EstateCovenantInfo message
- LLMessageSystem *msg = gMessageSystem;
- msg->newMessage("EstateCovenantRequest");
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
- msg->sendReliable(region->getHost());
-}
-
-// static
-void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data)
-{
- LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)user_data;
- if(self)
- {
- self->refreshUI();
- }
-}
-
-void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, const LLUUID& asset_id)
-{
- LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("covenant_editor");
- editor->setText(string);
-
- LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
- LLTextBox* box = getChild<LLTextBox>("covenant_text");
- if (asset_id.isNull())
- {
- check->set(true);
- check->setEnabled(false);
- refreshUI();
-
- // remove the line stating that you must agree
- box->setVisible(false);
- }
- else
- {
- check->setEnabled(true);
-
- // remove the line stating that you must agree
- box->setVisible(true);
- }
-}
-
-void LLFloaterBuyLandUI::updateFloaterEstateName(const std::string& name)
-{
- LLTextBox* box = getChild<LLTextBox>("estate_name_text");
- box->setText(name);
- box->setToolTip(name);
-}
-
-void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text)
-{
- LLTextBox* editor = getChild<LLTextBox>("covenant_timestamp_text");
- if (editor) editor->setText(text);
-}
-
-void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name)
-{
- LLTextBox* box = getChild<LLTextBox>("estate_owner_text");
- if (box) box->setText(name);
-}
-
-void LLFloaterBuyLandUI::updateWebSiteInfo()
-{
- S32 askBillableArea = mIsForGroup ? 0 : mParcelBillableArea;
- S32 askCurrencyBuy = mCurrency.getAmount();
-
- if (mTransaction && mTransactionType == TransactionPreflight
- && mPreflightAskBillableArea == askBillableArea
- && mPreflightAskCurrencyBuy == askCurrencyBuy)
- {
- return;
- }
-
- mPreflightAskBillableArea = askBillableArea;
- mPreflightAskCurrencyBuy = askCurrencyBuy;
-
-#if 0
- // enable this code if you want the details to blank while we're talking
- // to the web site... it's kind of jarring
- mSiteValid = false;
- mSiteMembershipUpgrade = false;
- mSiteMembershipAction = "(waiting)";
- mSiteMembershipPlanIDs.clear();
- mSiteMembershipPlanNames.clear();
- mSiteLandUseUpgrade = false;
- mSiteLandUseAction = "(waiting)";
- mSiteCurrencyEstimated = false;
- mSiteCurrencyEstimatedCost = 0;
-#endif
-
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendInt("billableArea", mPreflightAskBillableArea);
- keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy);
-
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
-
- startTransaction(TransactionPreflight, params);
-}
-
-void LLFloaterBuyLandUI::finishWebSiteInfo()
-{
-
- LLXMLRPCValue result = mTransaction->responseValue();
-
- mSiteValid = result["success"].asBool();
- if (!mSiteValid)
- {
- tellUserError(
- result["errorMessage"].asString(),
- result["errorURI"].asString()
- );
- return;
- }
-
- LLXMLRPCValue membership = result["membership"];
- mSiteMembershipUpgrade = membership["upgrade"].asBool();
- mSiteMembershipAction = membership["action"].asString();
- mSiteMembershipPlanIDs.clear();
- mSiteMembershipPlanNames.clear();
- LLXMLRPCValue levels = membership["levels"];
- for (LLXMLRPCValue level = levels.rewind();
- level.isValid();
- level = levels.next())
- {
- mSiteMembershipPlanIDs.push_back(level["id"].asString());
- mSiteMembershipPlanNames.push_back(level["description"].asString());
- }
- mUserPlanChoice = 0;
-
- LLXMLRPCValue landUse = result["landUse"];
- mSiteLandUseUpgrade = landUse["upgrade"].asBool();
- mSiteLandUseAction = landUse["action"].asString();
-
- LLXMLRPCValue currency = result["currency"];
- if (currency["estimatedCost"].isValid())
- {
- mCurrency.setUSDEstimate(currency["estimatedCost"].asInt());
- }
- if (currency["estimatedLocalCost"].isValid())
- {
- mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString());
- }
-
- mSiteConfirm = result["confirm"].asString();
-}
-
-void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password)
-{
- if (!mCanBuy)
- {
- return;
- }
-
- bool remove_contribution = getChild<LLUICtrl>("remove_contribution")->getValue().asBoolean();
- mParcelBuyInfo = LLViewerParcelMgr::getInstance()->setupParcelBuy(gAgent.getID(), gAgent.getSessionID(),
- gAgent.getGroupID(), mIsForGroup, mIsClaim, remove_contribution);
-
- if (mParcelBuyInfo
- && !mSiteMembershipUpgrade
- && !mSiteLandUseUpgrade
- && mCurrency.getAmount() == 0
- && mSiteConfirm != "password")
- {
- sendBuyLand();
- return;
- }
-
-
- std::string newLevel = "noChange";
-
- if (mSiteMembershipUpgrade)
- {
- LLComboBox* levels = getChild<LLComboBox>( "account_level");
- if (levels)
- {
- mUserPlanChoice = levels->getCurrentIndex();
- newLevel = mSiteMembershipPlanIDs[mUserPlanChoice];
- }
- }
-
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendString("levelId", newLevel);
- keywordArgs.appendInt("billableArea",
- mIsForGroup ? 0 : mParcelBillableArea);
- keywordArgs.appendInt("currencyBuy", mCurrency.getAmount());
- keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate());
- keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate());
- keywordArgs.appendString("confirm", mSiteConfirm);
- if (!password.empty())
- {
- keywordArgs.appendString("password", password);
- }
-
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
-
- startTransaction(TransactionBuy, params);
-}
-
-void LLFloaterBuyLandUI::finishWebSitePrep()
-{
- LLXMLRPCValue result = mTransaction->responseValue();
-
- bool success = result["success"].asBool();
- if (!success)
- {
- tellUserError(
- result["errorMessage"].asString(),
- result["errorURI"].asString()
- );
- return;
- }
-
- sendBuyLand();
-}
-
-void LLFloaterBuyLandUI::sendBuyLand()
-{
- if (mParcelBuyInfo)
- {
- LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
- mBought = true;
- }
-}
-
-void LLFloaterBuyLandUI::updateNames()
-{
- LLParcel* parcelp = mParcel->getParcel();
-
- if (!parcelp)
- {
- mParcelSellerName = LLStringUtil::null;
- return;
- }
-
- if (mIsClaim)
- {
- mParcelSellerName = "Linden Lab";
- }
- else if (parcelp->getIsGroupOwned())
- {
- gCacheName->getGroup(parcelp->getGroupID(),
- boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
- _1, _2, _3));
- }
- else
- {
- mParcelSellerName = LLSLURL("agent", parcelp->getOwnerID(), "completename").getSLURLString();
- }
-}
-
-void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
- const std::string& name,
- bool is_group)
-{
- LLParcel* parcelp = mParcel->getParcel();
- if (parcelp
- && parcelp->getGroupID() == id)
- {
- // request is current
- mParcelSellerName = name;
- }
-}
-
-void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
-{
- delete mTransaction;
- mTransaction = NULL;
-
- mTransactionType = type;
-
- // Select a URI and method appropriate for the transaction type.
- static std::string transaction_uri;
- if (transaction_uri.empty())
- {
- transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php";
- }
-
- const char* method;
- switch (mTransactionType)
- {
- case TransactionPreflight:
- method = "preflightBuyLandPrep";
- break;
- case TransactionBuy:
- method = "buyLandPrep";
- break;
- default:
- LL_WARNS() << "LLFloaterBuyLandUI: Unknown transaction type!" << LL_ENDL;
- return;
- }
-
- mTransaction = new LLXMLRPCTransaction(
- transaction_uri,
- method,
- params,
- false /* don't use gzip */
- );
-}
-
-bool LLFloaterBuyLandUI::checkTransaction()
-{
- if (!mTransaction)
- {
- return false;
- }
-
- if (!mTransaction->process())
- {
- return false;
- }
-
- if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
- {
- tellUserError(mTransaction->statusMessage(), mTransaction->statusURI());
- }
- else {
- switch (mTransactionType)
- {
- case TransactionPreflight: finishWebSiteInfo(); break;
- case TransactionBuy: finishWebSitePrep(); break;
- default: ;
- }
- }
-
- delete mTransaction;
- mTransaction = NULL;
-
- return true;
-}
-
-void LLFloaterBuyLandUI::tellUserError(
- const std::string& message, const std::string& uri)
-{
- mCanBuy = false;
- mCannotBuyIsError = true;
- mCannotBuyReason = getString("fetching_error");
- mCannotBuyReason += message;
- mCannotBuyURI = uri;
-}
-
-
-// virtual
-bool LLFloaterBuyLandUI::postBuild()
-{
- setVisibleCallback(boost::bind(&LLFloaterBuyLandUI::onVisibilityChanged, this, _2));
-
- mCurrency.prepare();
-
- getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this));
- getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this));
- getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickErrorWeb, this));
-
- center();
-
- return true;
-}
-
-void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
-{
- if (mTransaction && mTransactionType == TransactionBuy)
- {
- // the user is buying, don't change the selection
- return;
- }
-
- mRegion = region;
- mParcel = parcel;
-
- updateAgentInfo();
- updateParcelInfo();
- updateCovenantInfo();
- if (mCanBuy)
- {
- updateWebSiteInfo();
- }
- refreshUI();
-}
-
-void LLFloaterBuyLandUI::setForGroup(bool forGroup)
-{
- mIsForGroup = forGroup;
-}
-
-void LLFloaterBuyLandUI::draw()
-{
- LLFloater::draw();
-
- bool needsUpdate = false;
- needsUpdate |= checkTransaction();
- needsUpdate |= mCurrency.process();
-
- if (mBought)
- {
- closeFloater();
- }
- else if (needsUpdate)
- {
- if (mCanBuy && mCurrency.hasError())
- {
- tellUserError(mCurrency.errorMessage(), mCurrency.errorURI());
- }
-
- refreshUI();
- }
-}
-
-// virtual
-bool LLFloaterBuyLandUI::canClose()
-{
- // mTransactionType check for pre-buy estimation stage and mCurrency to allow exit after transaction
- bool can_close = !mTransaction && (mTransactionType != TransactionBuy || mCurrency.canCancel());
- if (!can_close)
- {
- // explain to user why they can't do this, see DEV-9605
- LLNotificationsUtil::add("CannotCloseFloaterBuyLand");
- }
- return can_close;
-}
-
-void LLFloaterBuyLandUI::onVisibilityChanged ( const LLSD& new_visibility )
-{
- if (new_visibility.asBoolean())
- {
- refreshUI();
- }
-}
-
-void LLFloaterBuyLandUI::refreshUI()
-{
- // section zero: title area
- {
- LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
- if (snapshot)
- {
- snapshot->setImageAssetID(
- mParcelValid ? mParcelSnapshot : LLUUID::null);
- }
-
- if (mParcelValid)
- {
- getChild<LLUICtrl>("info_parcel")->setValue(mParcelLocation);
-
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mParcelActualArea);
- string_args["[AMOUNT2]"] = llformat("%d", mParcelSupportedObjects);
-
- getChild<LLUICtrl>("info_size")->setValue(getString("meters_supports_object", string_args));
-
- F32 cost_per_sqm = 0.0f;
- if (mParcelActualArea > 0)
- {
- cost_per_sqm = (F32)mParcelPrice / (F32)mParcelActualArea;
- }
-
- LLStringUtil::format_map_t info_price_args;
- info_price_args["[PRICE]"] = llformat("%d", mParcelPrice);
- info_price_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm);
- if (mParcelSoldWithObjects)
- {
- info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects");
- }
- else
- {
- info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects");
- }
- getChild<LLUICtrl>("info_price")->setValue(getString("info_price_string", info_price_args));
- getChildView("info_price")->setVisible( mParcelIsForSale);
- }
- else
- {
- getChild<LLUICtrl>("info_parcel")->setValue(getString("no_parcel_selected"));
- getChild<LLUICtrl>("info_size")->setValue(LLStringUtil::null);
- getChild<LLUICtrl>("info_price")->setValue(LLStringUtil::null);
- }
-
- getChild<LLUICtrl>("info_action")->setValue(
- mCanBuy
- ?
- mIsForGroup
- ? getString("buying_for_group")//"Buying land for group:"
- : getString("buying_will")//"Buying this land will:"
- :
- mCannotBuyIsError
- ? getString("cannot_buy_now")//"Cannot buy now:"
- : getString("not_for_sale")//"Not for sale:"
-
- );
- }
-
- bool showingError = !mCanBuy || !mSiteValid;
-
- // error section
- if (showingError)
- {
- mChildren.setBadge(std::string("step_error"),
- mCannotBuyIsError
- ? LLViewChildren::BADGE_ERROR
- : LLViewChildren::BADGE_WARN);
-
- LLTextBox* message = getChild<LLTextBox>("error_message");
- if (message)
- {
- message->setVisible(true);
- message->setValue(LLSD(!mCanBuy ? mCannotBuyReason : "(waiting for data)"));
- }
-
- getChildView("error_web")->setVisible(mCannotBuyIsError && !mCannotBuyURI.empty());
- }
- else
- {
- getChildView("step_error")->setVisible(false);
- getChildView("error_message")->setVisible(false);
- getChildView("error_web")->setVisible(false);
- }
-
-
- // section one: account
- if (!showingError)
- {
- mChildren.setBadge(std::string("step_1"),
- mSiteMembershipUpgrade
- ? LLViewChildren::BADGE_NOTE
- : LLViewChildren::BADGE_OK);
- getChild<LLUICtrl>("account_action")->setValue(mSiteMembershipAction);
- getChild<LLUICtrl>("account_reason")->setValue(
- mSiteMembershipUpgrade
- ? getString("must_upgrade")
- : getString("cant_own_land")
- );
-
- LLComboBox* levels = getChild<LLComboBox>( "account_level");
- if (levels)
- {
- levels->setVisible(mSiteMembershipUpgrade);
-
- levels->removeall();
- for(std::vector<std::string>::const_iterator i
- = mSiteMembershipPlanNames.begin();
- i != mSiteMembershipPlanNames.end();
- ++i)
- {
- levels->add(*i);
- }
-
- levels->setCurrentByIndex(mUserPlanChoice);
- }
-
- getChildView("step_1")->setVisible(true);
- getChildView("account_action")->setVisible(true);
- getChildView("account_reason")->setVisible(true);
- }
- else
- {
- getChildView("step_1")->setVisible(false);
- getChildView("account_action")->setVisible(false);
- getChildView("account_reason")->setVisible(false);
- getChildView("account_level")->setVisible(false);
- }
-
- // section two: land use fees
- if (!showingError)
- {
- mChildren.setBadge(std::string("step_2"),
- mSiteLandUseUpgrade
- ? LLViewChildren::BADGE_NOTE
- : LLViewChildren::BADGE_OK);
- getChild<LLUICtrl>("land_use_action")->setValue(mSiteLandUseAction);
-
- std::string message;
-
- if (mIsForGroup)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[GROUP]"] = std::string(gAgent.getGroupName());
-
- message += getString("insufficient_land_credits", string_args);
-
- }
- else
- {
- LLStringUtil::format_map_t string_args;
- string_args["[BUYER]"] = llformat("%d", mAgentCommittedTier);
- message += getString("land_holdings", string_args);
- }
-
- if (!mParcelValid)
- {
- message += LLTrans::getString("sentences_separator") + getString("no_parcel_selected");
- }
- else if (mParcelBillableArea == mParcelActualArea)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d ", mParcelActualArea);
- message += LLTrans::getString("sentences_separator") + getString("parcel_meters", string_args);
- }
- else
- {
-
- if (mParcelBillableArea > mParcelActualArea)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
- message += LLTrans::getString("sentences_separator") + getString("premium_land", string_args);
- }
- else
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
- message += LLTrans::getString("sentences_separator") + getString("discounted_land", string_args);
- }
- }
-
- getChild<LLUICtrl>("land_use_reason")->setValue(message);
-
- getChildView("step_2")->setVisible(true);
- getChildView("land_use_action")->setVisible(true);
- getChildView("land_use_reason")->setVisible(true);
- }
- else
- {
- getChildView("step_2")->setVisible(false);
- getChildView("land_use_action")->setVisible(false);
- getChildView("land_use_reason")->setVisible(false);
- }
-
- // section three: purchase & currency
- S32 finalBalance = mAgentCashBalance + mCurrency.getAmount() - mParcelPrice;
- bool willHaveEnough = finalBalance >= 0;
- bool haveEnough = mAgentCashBalance >= mParcelPrice;
- S32 minContribution = llceil((F32)mParcelBillableArea / GROUP_LAND_BONUS_FACTOR);
- bool groupContributionEnough = mParcelGroupContribution >= minContribution;
-
- mCurrency.updateUI(!showingError && !haveEnough);
-
- if (!showingError)
- {
- mChildren.setBadge(std::string("step_3"),
- !willHaveEnough
- ? LLViewChildren::BADGE_WARN
- : mCurrency.getAmount() > 0
- ? LLViewChildren::BADGE_NOTE
- : LLViewChildren::BADGE_OK);
-
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
- string_args["[SELLER]"] = mParcelSellerName;
- getChild<LLUICtrl>("purchase_action")->setValue(getString("pay_to_for_land", string_args));
- getChildView("purchase_action")->setVisible( mParcelValid);
-
- std::string reasonString;
-
- if (haveEnough)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
-
- getChild<LLUICtrl>("currency_reason")->setValue(getString("have_enough_lindens", string_args));
- }
- else
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
- string_args["[AMOUNT2]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
-
- getChild<LLUICtrl>("currency_reason")->setValue(getString("not_enough_lindens", string_args));
-
- getChild<LLUICtrl>("currency_est")->setTextArg("[LOCAL_AMOUNT]", mCurrency.getLocalEstimate());
- }
-
- if (willHaveEnough)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", finalBalance);
-
- getChild<LLUICtrl>("currency_balance")->setValue(getString("balance_left", string_args));
-
- }
- else
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
-
- getChild<LLUICtrl>("currency_balance")->setValue(getString("balance_needed", string_args));
-
- }
-
- getChild<LLUICtrl>("remove_contribution")->setValue(LLSD(groupContributionEnough));
- getChildView("remove_contribution")->setEnabled(groupContributionEnough);
- bool showRemoveContribution = mParcelIsGroupLand
- && (mParcelGroupContribution > 0);
- getChildView("remove_contribution")->setLabelArg("[AMOUNT]",
- llformat("%d", minContribution));
- getChildView("remove_contribution")->setVisible( showRemoveContribution);
-
- getChildView("step_3")->setVisible(true);
- getChildView("purchase_action")->setVisible(true);
- getChildView("currency_reason")->setVisible(true);
- getChildView("currency_balance")->setVisible(true);
- }
- else
- {
- getChildView("step_3")->setVisible(false);
- getChildView("purchase_action")->setVisible(false);
- getChildView("currency_reason")->setVisible(false);
- getChildView("currency_balance")->setVisible(false);
- getChildView("remove_group_donation")->setVisible(false);
- }
-
-
- bool agrees_to_covenant = false;
- LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
- if (check)
- {
- agrees_to_covenant = check->get();
- }
-
- getChildView("buy_btn")->setEnabled(mCanBuy && mSiteValid && willHaveEnough && !mTransaction && agrees_to_covenant);
-}
-
-void LLFloaterBuyLandUI::startBuyPreConfirm()
-{
- std::string action;
-
- if (mSiteMembershipUpgrade)
- {
- action += mSiteMembershipAction;
- action += "\n";
-
- LLComboBox* levels = getChild<LLComboBox>( "account_level");
- if (levels)
- {
- action += " * ";
- action += mSiteMembershipPlanNames[levels->getCurrentIndex()];
- action += "\n";
- }
- }
- if (mSiteLandUseUpgrade)
- {
- action += mSiteLandUseAction;
- action += "\n";
- }
- if (mCurrency.getAmount() > 0)
- {
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount());
- string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate();
-
- action += getString("buy_for_US", string_args);
- }
-
- LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
- string_args["[SELLER]"] = mParcelSellerName;
- action += getString("pay_to_for_land", string_args);
-
-
- LLConfirmationManager::confirm(mSiteConfirm,
- action,
- *this,
- &LLFloaterBuyLandUI::startBuyPostConfirm);
-}
-
-void LLFloaterBuyLandUI::startBuyPostConfirm(const std::string& password)
-{
- runWebSitePrep(password);
-
- mCanBuy = false;
- mCannotBuyReason = getString("processing");
- refreshUI();
-}
-
-
-void LLFloaterBuyLandUI::onClickBuy()
-{
- startBuyPreConfirm();
-}
-
-void LLFloaterBuyLandUI::onClickCancel()
-{
- closeFloater();
-}
-
-void LLFloaterBuyLandUI::onClickErrorWeb()
-{
- LLWeb::loadURLExternal(mCannotBuyURI);
- closeFloater();
-}
-
-
-
+/**
+ * @file llfloaterbuyland.cpp
+ * @brief LLFloaterBuyLand class implementation
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterbuyland.h"
+
+// viewer includes
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcachename.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llconfirmationmanager.h"
+#include "llcurrencyuimanager.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llfloatertools.h"
+#include "llframetimer.h"
+#include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llparcel.h"
+#include "llslurl.h"
+#include "llstatusbar.h"
+#include "lltextbox.h"
+#include "lltexturectrl.h"
+#include "lltrans.h"
+#include "llviewchildren.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewertexteditor.h"
+#include "llviewerwindow.h"
+#include "llweb.h"
+#include "llwindow.h"
+#include "llworld.h"
+#include "llxmlrpctransaction.h"
+#include "llviewernetwork.h"
+#include "roles_constants.h"
+
+// NOTE: This is duplicated in lldatamoney.cpp ...
+const F32 GROUP_LAND_BONUS_FACTOR = 1.1f;
+
+class LLFloaterBuyLandUI
+: public LLFloater
+{
+public:
+ LLFloaterBuyLandUI(const LLSD& key);
+ virtual ~LLFloaterBuyLandUI();
+
+ /*virtual*/ void onClose(bool app_quitting);
+
+ // Left padding for maturity rating icon.
+ static const S32 ICON_PAD = 2;
+
+private:
+ class SelectionObserver : public LLParcelObserver
+ {
+ public:
+ SelectionObserver(LLFloaterBuyLandUI* floater) : mFloater(floater) {}
+ virtual void changed();
+ private:
+ LLFloaterBuyLandUI* mFloater;
+ };
+
+private:
+ SelectionObserver mParcelSelectionObserver;
+ LLViewerRegion* mRegion;
+ LLParcelSelectionHandle mParcel;
+ bool mIsClaim;
+ bool mIsForGroup;
+
+ bool mCanBuy;
+ bool mCannotBuyIsError;
+ std::string mCannotBuyReason;
+ std::string mCannotBuyURI;
+
+ bool mBought;
+
+ // information about the agent
+ S32 mAgentCommittedTier;
+ S32 mAgentCashBalance;
+ bool mAgentHasNeverOwnedLand;
+
+ // information about the parcel
+ bool mParcelValid;
+ bool mParcelIsForSale;
+ bool mParcelIsGroupLand;
+ S32 mParcelGroupContribution;
+ S32 mParcelPrice;
+ S32 mParcelActualArea;
+ S32 mParcelBillableArea;
+ S32 mParcelSupportedObjects;
+ bool mParcelSoldWithObjects;
+ std::string mParcelLocation;
+ LLUUID mParcelSnapshot;
+ std::string mParcelSellerName;
+
+ // user's choices
+ S32 mUserPlanChoice;
+
+ // from website
+ bool mSiteValid;
+ bool mSiteMembershipUpgrade;
+ std::string mSiteMembershipAction;
+ std::vector<std::string>
+ mSiteMembershipPlanIDs;
+ std::vector<std::string>
+ mSiteMembershipPlanNames;
+ bool mSiteLandUseUpgrade;
+ std::string mSiteLandUseAction;
+ std::string mSiteConfirm;
+
+ // values in current Preflight transaction... used to avoid extra
+ // preflights when the parcel manager goes update crazy
+ S32 mPreflightAskBillableArea;
+ S32 mPreflightAskCurrencyBuy;
+
+ LLViewChildren mChildren;
+ LLCurrencyUIManager mCurrency;
+
+ enum TransactionType
+ {
+ TransactionPreflight,
+ TransactionCurrency,
+ TransactionBuy
+ };
+ LLXMLRPCTransaction* mTransaction;
+ TransactionType mTransactionType;
+
+ LLViewerParcelMgr::ParcelBuyInfo* mParcelBuyInfo;
+
+public:
+ void setForGroup(bool is_for_group);
+ void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
+
+ void updateAgentInfo();
+ void updateParcelInfo();
+ void updateCovenantInfo();
+ static void onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data);
+ void updateFloaterCovenantText(const std::string& string, const LLUUID &asset_id);
+ void updateFloaterEstateName(const std::string& name);
+ void updateFloaterLastModified(const std::string& text);
+ void updateFloaterEstateOwnerName(const std::string& name);
+ void updateWebSiteInfo();
+ void finishWebSiteInfo();
+
+ void runWebSitePrep(const std::string& password);
+ void finishWebSitePrep();
+ void sendBuyLand();
+
+ void updateNames();
+ // Name cache callback
+ void updateGroupName(const LLUUID& id,
+ const std::string& name,
+ bool is_group);
+
+ void refreshUI();
+
+ void startTransaction(TransactionType type, const LLXMLRPCValue& params);
+ bool checkTransaction();
+
+ void tellUserError(const std::string& message, const std::string& uri);
+
+ virtual bool postBuild();
+
+ void startBuyPreConfirm();
+ void startBuyPostConfirm(const std::string& password);
+
+ void onClickBuy();
+ void onClickCancel();
+ void onClickErrorWeb();
+
+ virtual void draw();
+ virtual bool canClose();
+
+ void onVisibilityChanged ( const LLSD& new_visibility );
+
+};
+
+// static
+void LLFloaterBuyLand::buyLand(
+ LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
+{
+ if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
+ {
+ LLNotificationsUtil::add("OnlyOfficerCanBuyLand");
+ return;
+ }
+
+ LLFloaterBuyLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (ui)
+ {
+ ui->setForGroup(is_for_group);
+ ui->setParcel(region, parcel);
+ }
+}
+
+// static
+void LLFloaterBuyLand::updateCovenantText(const std::string& string, const LLUUID &asset_id)
+{
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (floater)
+ {
+ floater->updateFloaterCovenantText(string, asset_id);
+ }
+}
+
+// static
+void LLFloaterBuyLand::updateEstateName(const std::string& name)
+{
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (floater)
+ {
+ floater->updateFloaterEstateName(name);
+ }
+}
+
+// static
+void LLFloaterBuyLand::updateLastModified(const std::string& text)
+{
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (floater)
+ {
+ floater->updateFloaterLastModified(text);
+ }
+}
+
+// static
+void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name)
+{
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (floater)
+ {
+ floater->updateFloaterEstateOwnerName(name);
+ }
+}
+
+// static
+LLFloater* LLFloaterBuyLand::buildFloater(const LLSD& key)
+{
+ LLFloaterBuyLandUI* floater = new LLFloaterBuyLandUI(key);
+ return floater;
+}
+
+//----------------------------------------------------------------------------
+// LLFloaterBuyLandUI
+//----------------------------------------------------------------------------
+
+#if LL_WINDOWS
+// passing 'this' during construction generates a warning. The callee
+// only uses the pointer to hold a reference to 'this' which is
+// already valid, so this call does the correct thing. Disable the
+// warning so that we can compile without generating a warning.
+#pragma warning(disable : 4355)
+#endif
+LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
+: LLFloater(LLSD()),
+ mParcelSelectionObserver(this),
+ mParcel(0),
+ mBought(false),
+ mParcelValid(false), mSiteValid(false),
+ mChildren(*this), mCurrency(*this), mTransaction(0),
+ mParcelBuyInfo(0)
+{
+ LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
+
+}
+
+LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
+{
+ LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
+
+ delete mTransaction;
+}
+
+// virtual
+void LLFloaterBuyLandUI::onClose(bool app_quitting)
+{
+ // This object holds onto observer, transactions, and parcel state.
+ // Despite being single_instance, destroy it to call destructors and clean
+ // everything up.
+ setVisible(false);
+ destroy();
+}
+
+void LLFloaterBuyLandUI::SelectionObserver::changed()
+{
+ if (LLViewerParcelMgr::getInstance()->selectionEmpty())
+ {
+ mFloater->closeFloater();
+ }
+ else
+ {
+ mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
+ LLViewerParcelMgr::getInstance()->getParcelSelection());
+ }
+}
+
+
+void LLFloaterBuyLandUI::updateAgentInfo()
+{
+ mAgentCommittedTier = gStatusBar->getSquareMetersCommitted();
+ mAgentCashBalance = gStatusBar->getBalance();
+
+ // *TODO: This is an approximation, we should send this value down
+ // to the viewer. See SL-10728 for details.
+ mAgentHasNeverOwnedLand = mAgentCommittedTier == 0;
+}
+
+void LLFloaterBuyLandUI::updateParcelInfo()
+{
+ LLParcel* parcel = mParcel->getParcel();
+ mParcelValid = parcel && mRegion;
+ mParcelIsForSale = false;
+ mParcelIsGroupLand = false;
+ mParcelGroupContribution = 0;
+ mParcelPrice = 0;
+ mParcelActualArea = 0;
+ mParcelBillableArea = 0;
+ mParcelSupportedObjects = 0;
+ mParcelSoldWithObjects = false;
+ mParcelLocation = "";
+ mParcelSnapshot.setNull();
+ mParcelSellerName = "";
+
+ mCanBuy = false;
+ mCannotBuyIsError = false;
+
+ if (!mParcelValid)
+ {
+ mCannotBuyReason = getString("no_land_selected");
+ return;
+ }
+
+ if (mParcel->getMultipleOwners())
+ {
+ mCannotBuyReason = getString("multiple_parcels_selected");
+ return;
+ }
+
+ const LLUUID& parcelOwner = parcel->getOwnerID();
+
+ mIsClaim = parcel->isPublic();
+ if (!mIsClaim)
+ {
+ mParcelActualArea = parcel->getArea();
+ mParcelIsForSale = parcel->getForSale();
+ mParcelIsGroupLand = parcel->getIsGroupOwned();
+ mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0;
+
+ if (mParcelIsGroupLand)
+ {
+ LLUUID group_id = parcel->getGroupID();
+ mParcelGroupContribution = gAgent.getGroupContribution(group_id);
+ }
+ }
+ else
+ {
+ mParcelActualArea = mParcel->getClaimableArea();
+ mParcelIsForSale = true;
+ mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter();
+ }
+
+ mParcelBillableArea =
+ ll_round(mRegion->getBillableFactor() * mParcelActualArea);
+
+ mParcelSupportedObjects = ll_round(
+ parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus());
+ // Can't have more than region max tasks, regardless of parcel
+ // object bonus factor.
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+ if(region)
+ {
+ S32 max_tasks_per_region = (S32)region->getMaxTasks();
+ mParcelSupportedObjects = llmin(
+ mParcelSupportedObjects, max_tasks_per_region);
+ }
+
+ mParcelSoldWithObjects = parcel->getSellWithObjects();
+
+
+ LLVector3 center = parcel->getCenterpoint();
+ mParcelLocation = llformat("%s %d,%d",
+ mRegion->getName().c_str(),
+ (int)center[VX], (int)center[VY]
+ );
+
+ mParcelSnapshot = parcel->getSnapshotID();
+
+ updateNames();
+
+ bool haveEnoughCash = mParcelPrice <= mAgentCashBalance;
+ S32 cashBuy = haveEnoughCash ? 0 : (mParcelPrice - mAgentCashBalance);
+ mCurrency.setAmount(cashBuy, true);
+ mCurrency.setZeroMessage(haveEnoughCash ? getString("none_needed") : LLStringUtil::null);
+
+ // checks that we can buy the land
+
+ if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
+ {
+ mCannotBuyReason = getString("cant_buy_for_group");
+ return;
+ }
+
+ if (!mIsClaim)
+ {
+ const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID();
+ const LLUUID buyer = gAgent.getID();
+ const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer;
+
+ if (!mParcelIsForSale
+ || (mParcelPrice == 0 && authorizedBuyer.isNull()))
+ {
+
+ mCannotBuyReason = getString("parcel_not_for_sale");
+ return;
+ }
+
+ if (parcelOwner == newOwner)
+ {
+ if (mIsForGroup)
+ {
+ mCannotBuyReason = getString("group_already_owns");
+ }
+ else
+ {
+ mCannotBuyReason = getString("you_already_own");
+ }
+ return;
+ }
+
+ if (!authorizedBuyer.isNull() && buyer != authorizedBuyer)
+ {
+ // Maybe the parcel is set for sale to a group we are in.
+ bool authorized_group =
+ gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED)
+ && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO);
+
+ if (!authorized_group)
+ {
+ mCannotBuyReason = getString("set_to_sell_to_other");
+ return;
+ }
+ }
+ }
+ else
+ {
+ if (mParcelActualArea == 0)
+ {
+ mCannotBuyReason = getString("no_public_land");
+ return;
+ }
+
+ if (mParcel->hasOthersSelected())
+ {
+ // Policy: Must not have someone else's land selected
+ mCannotBuyReason = getString("not_owned_by_you");
+ return;
+ }
+ }
+
+ mCanBuy = true;
+}
+
+void LLFloaterBuyLandUI::updateCovenantInfo()
+{
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+ if(!region) return;
+
+ U8 sim_access = region->getSimAccess();
+ std::string rating = LLViewerRegion::accessToString(sim_access);
+
+ LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
+ if (region_name)
+ {
+ std::string region_name_txt = region->getName() + " ("+rating +")";
+ region_name->setText(region_name_txt);
+
+ LLIconCtrl* rating_icon = getChild<LLIconCtrl>("rating_icon");
+ LLRect rect = rating_icon->getRect();
+ S32 region_name_width = llmin(region_name->getRect().getWidth(), region_name->getTextBoundingRect().getWidth());
+ S32 icon_left_pad = region_name->getRect().mLeft + region_name_width + ICON_PAD;
+ region_name->setToolTip(region_name->getText());
+ rating_icon->setRect(rect.setOriginAndSize(icon_left_pad, rect.mBottom, rect.getWidth(), rect.getHeight()));
+
+ switch(sim_access)
+ {
+ case SIM_ACCESS_PG:
+ rating_icon->setValue(getString("icon_PG"));
+ break;
+
+ case SIM_ACCESS_ADULT:
+ rating_icon->setValue(getString("icon_R"));
+ break;
+
+ default:
+ rating_icon->setValue(getString("icon_M"));
+ }
+ }
+
+ LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
+ if (region_type)
+ {
+ region_type->setText(region->getLocalizedSimProductName());
+ region_type->setToolTip(region->getLocalizedSimProductName());
+ }
+
+ LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
+ if (resellable_clause)
+ {
+ if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))
+ {
+ resellable_clause->setText(getString("can_not_resell"));
+ }
+ else
+ {
+ resellable_clause->setText(getString("can_resell"));
+ }
+ }
+
+ LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause");
+ if (changeable_clause)
+ {
+ if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES))
+ {
+ changeable_clause->setText(getString("can_change"));
+ }
+ else
+ {
+ changeable_clause->setText(getString("can_not_change"));
+ }
+ }
+
+ LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
+ if(check)
+ {
+ check->set(false);
+ check->setEnabled(true);
+ check->setCommitCallback(onChangeAgreeCovenant, this);
+ }
+
+ LLTextBox* box = getChild<LLTextBox>("covenant_text");
+ if(box)
+ {
+ box->setVisible(false);
+ }
+
+ // send EstateCovenantInfo message
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessage("EstateCovenantRequest");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->sendReliable(region->getHost());
+}
+
+// static
+void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data)
+{
+ LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)user_data;
+ if(self)
+ {
+ self->refreshUI();
+ }
+}
+
+void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, const LLUUID& asset_id)
+{
+ LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("covenant_editor");
+ editor->setText(string);
+
+ LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
+ LLTextBox* box = getChild<LLTextBox>("covenant_text");
+ if (asset_id.isNull())
+ {
+ check->set(true);
+ check->setEnabled(false);
+ refreshUI();
+
+ // remove the line stating that you must agree
+ box->setVisible(false);
+ }
+ else
+ {
+ check->setEnabled(true);
+
+ // remove the line stating that you must agree
+ box->setVisible(true);
+ }
+}
+
+void LLFloaterBuyLandUI::updateFloaterEstateName(const std::string& name)
+{
+ LLTextBox* box = getChild<LLTextBox>("estate_name_text");
+ box->setText(name);
+ box->setToolTip(name);
+}
+
+void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text)
+{
+ LLTextBox* editor = getChild<LLTextBox>("covenant_timestamp_text");
+ if (editor) editor->setText(text);
+}
+
+void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name)
+{
+ LLTextBox* box = getChild<LLTextBox>("estate_owner_text");
+ if (box) box->setText(name);
+}
+
+void LLFloaterBuyLandUI::updateWebSiteInfo()
+{
+ S32 askBillableArea = mIsForGroup ? 0 : mParcelBillableArea;
+ S32 askCurrencyBuy = mCurrency.getAmount();
+
+ if (mTransaction && mTransactionType == TransactionPreflight
+ && mPreflightAskBillableArea == askBillableArea
+ && mPreflightAskCurrencyBuy == askCurrencyBuy)
+ {
+ return;
+ }
+
+ mPreflightAskBillableArea = askBillableArea;
+ mPreflightAskCurrencyBuy = askCurrencyBuy;
+
+#if 0
+ // enable this code if you want the details to blank while we're talking
+ // to the web site... it's kind of jarring
+ mSiteValid = false;
+ mSiteMembershipUpgrade = false;
+ mSiteMembershipAction = "(waiting)";
+ mSiteMembershipPlanIDs.clear();
+ mSiteMembershipPlanNames.clear();
+ mSiteLandUseUpgrade = false;
+ mSiteLandUseAction = "(waiting)";
+ mSiteCurrencyEstimated = false;
+ mSiteCurrencyEstimatedCost = 0;
+#endif
+
+ LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
+ keywordArgs.appendString("agentId", gAgent.getID().asString());
+ keywordArgs.appendString(
+ "secureSessionId",
+ gAgent.getSecureSessionID().asString());
+ keywordArgs.appendString("language", LLUI::getLanguage());
+ keywordArgs.appendInt("billableArea", mPreflightAskBillableArea);
+ keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy);
+
+ LLXMLRPCValue params = LLXMLRPCValue::createArray();
+ params.append(keywordArgs);
+
+ startTransaction(TransactionPreflight, params);
+}
+
+void LLFloaterBuyLandUI::finishWebSiteInfo()
+{
+
+ LLXMLRPCValue result = mTransaction->responseValue();
+
+ mSiteValid = result["success"].asBool();
+ if (!mSiteValid)
+ {
+ tellUserError(
+ result["errorMessage"].asString(),
+ result["errorURI"].asString()
+ );
+ return;
+ }
+
+ LLXMLRPCValue membership = result["membership"];
+ mSiteMembershipUpgrade = membership["upgrade"].asBool();
+ mSiteMembershipAction = membership["action"].asString();
+ mSiteMembershipPlanIDs.clear();
+ mSiteMembershipPlanNames.clear();
+ LLXMLRPCValue levels = membership["levels"];
+ for (LLXMLRPCValue level = levels.rewind();
+ level.isValid();
+ level = levels.next())
+ {
+ mSiteMembershipPlanIDs.push_back(level["id"].asString());
+ mSiteMembershipPlanNames.push_back(level["description"].asString());
+ }
+ mUserPlanChoice = 0;
+
+ LLXMLRPCValue landUse = result["landUse"];
+ mSiteLandUseUpgrade = landUse["upgrade"].asBool();
+ mSiteLandUseAction = landUse["action"].asString();
+
+ LLXMLRPCValue currency = result["currency"];
+ if (currency["estimatedCost"].isValid())
+ {
+ mCurrency.setUSDEstimate(currency["estimatedCost"].asInt());
+ }
+ if (currency["estimatedLocalCost"].isValid())
+ {
+ mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString());
+ }
+
+ mSiteConfirm = result["confirm"].asString();
+}
+
+void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password)
+{
+ if (!mCanBuy)
+ {
+ return;
+ }
+
+ bool remove_contribution = getChild<LLUICtrl>("remove_contribution")->getValue().asBoolean();
+ mParcelBuyInfo = LLViewerParcelMgr::getInstance()->setupParcelBuy(gAgent.getID(), gAgent.getSessionID(),
+ gAgent.getGroupID(), mIsForGroup, mIsClaim, remove_contribution);
+
+ if (mParcelBuyInfo
+ && !mSiteMembershipUpgrade
+ && !mSiteLandUseUpgrade
+ && mCurrency.getAmount() == 0
+ && mSiteConfirm != "password")
+ {
+ sendBuyLand();
+ return;
+ }
+
+
+ std::string newLevel = "noChange";
+
+ if (mSiteMembershipUpgrade)
+ {
+ LLComboBox* levels = getChild<LLComboBox>( "account_level");
+ if (levels)
+ {
+ mUserPlanChoice = levels->getCurrentIndex();
+ newLevel = mSiteMembershipPlanIDs[mUserPlanChoice];
+ }
+ }
+
+ LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
+ keywordArgs.appendString("agentId", gAgent.getID().asString());
+ keywordArgs.appendString(
+ "secureSessionId",
+ gAgent.getSecureSessionID().asString());
+ keywordArgs.appendString("language", LLUI::getLanguage());
+ keywordArgs.appendString("levelId", newLevel);
+ keywordArgs.appendInt("billableArea",
+ mIsForGroup ? 0 : mParcelBillableArea);
+ keywordArgs.appendInt("currencyBuy", mCurrency.getAmount());
+ keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate());
+ keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate());
+ keywordArgs.appendString("confirm", mSiteConfirm);
+ if (!password.empty())
+ {
+ keywordArgs.appendString("password", password);
+ }
+
+ LLXMLRPCValue params = LLXMLRPCValue::createArray();
+ params.append(keywordArgs);
+
+ startTransaction(TransactionBuy, params);
+}
+
+void LLFloaterBuyLandUI::finishWebSitePrep()
+{
+ LLXMLRPCValue result = mTransaction->responseValue();
+
+ bool success = result["success"].asBool();
+ if (!success)
+ {
+ tellUserError(
+ result["errorMessage"].asString(),
+ result["errorURI"].asString()
+ );
+ return;
+ }
+
+ sendBuyLand();
+}
+
+void LLFloaterBuyLandUI::sendBuyLand()
+{
+ if (mParcelBuyInfo)
+ {
+ LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
+ mBought = true;
+ }
+}
+
+void LLFloaterBuyLandUI::updateNames()
+{
+ LLParcel* parcelp = mParcel->getParcel();
+
+ if (!parcelp)
+ {
+ mParcelSellerName = LLStringUtil::null;
+ return;
+ }
+
+ if (mIsClaim)
+ {
+ mParcelSellerName = "Linden Lab";
+ }
+ else if (parcelp->getIsGroupOwned())
+ {
+ gCacheName->getGroup(parcelp->getGroupID(),
+ boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
+ _1, _2, _3));
+ }
+ else
+ {
+ mParcelSellerName = LLSLURL("agent", parcelp->getOwnerID(), "completename").getSLURLString();
+ }
+}
+
+void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
+ const std::string& name,
+ bool is_group)
+{
+ LLParcel* parcelp = mParcel->getParcel();
+ if (parcelp
+ && parcelp->getGroupID() == id)
+ {
+ // request is current
+ mParcelSellerName = name;
+ }
+}
+
+void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
+{
+ delete mTransaction;
+ mTransaction = NULL;
+
+ mTransactionType = type;
+
+ // Select a URI and method appropriate for the transaction type.
+ static std::string transaction_uri;
+ if (transaction_uri.empty())
+ {
+ transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php";
+ }
+
+ const char* method;
+ switch (mTransactionType)
+ {
+ case TransactionPreflight:
+ method = "preflightBuyLandPrep";
+ break;
+ case TransactionBuy:
+ method = "buyLandPrep";
+ break;
+ default:
+ LL_WARNS() << "LLFloaterBuyLandUI: Unknown transaction type!" << LL_ENDL;
+ return;
+ }
+
+ mTransaction = new LLXMLRPCTransaction(
+ transaction_uri,
+ method,
+ params,
+ false /* don't use gzip */
+ );
+}
+
+bool LLFloaterBuyLandUI::checkTransaction()
+{
+ if (!mTransaction)
+ {
+ return false;
+ }
+
+ if (!mTransaction->process())
+ {
+ return false;
+ }
+
+ if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
+ {
+ tellUserError(mTransaction->statusMessage(), mTransaction->statusURI());
+ }
+ else {
+ switch (mTransactionType)
+ {
+ case TransactionPreflight: finishWebSiteInfo(); break;
+ case TransactionBuy: finishWebSitePrep(); break;
+ default: ;
+ }
+ }
+
+ delete mTransaction;
+ mTransaction = NULL;
+
+ return true;
+}
+
+void LLFloaterBuyLandUI::tellUserError(
+ const std::string& message, const std::string& uri)
+{
+ mCanBuy = false;
+ mCannotBuyIsError = true;
+ mCannotBuyReason = getString("fetching_error");
+ mCannotBuyReason += message;
+ mCannotBuyURI = uri;
+}
+
+
+// virtual
+bool LLFloaterBuyLandUI::postBuild()
+{
+ setVisibleCallback(boost::bind(&LLFloaterBuyLandUI::onVisibilityChanged, this, _2));
+
+ mCurrency.prepare();
+
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this));
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this));
+ getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickErrorWeb, this));
+
+ center();
+
+ return true;
+}
+
+void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
+{
+ if (mTransaction && mTransactionType == TransactionBuy)
+ {
+ // the user is buying, don't change the selection
+ return;
+ }
+
+ mRegion = region;
+ mParcel = parcel;
+
+ updateAgentInfo();
+ updateParcelInfo();
+ updateCovenantInfo();
+ if (mCanBuy)
+ {
+ updateWebSiteInfo();
+ }
+ refreshUI();
+}
+
+void LLFloaterBuyLandUI::setForGroup(bool forGroup)
+{
+ mIsForGroup = forGroup;
+}
+
+void LLFloaterBuyLandUI::draw()
+{
+ LLFloater::draw();
+
+ bool needsUpdate = false;
+ needsUpdate |= checkTransaction();
+ needsUpdate |= mCurrency.process();
+
+ if (mBought)
+ {
+ closeFloater();
+ }
+ else if (needsUpdate)
+ {
+ if (mCanBuy && mCurrency.hasError())
+ {
+ tellUserError(mCurrency.errorMessage(), mCurrency.errorURI());
+ }
+
+ refreshUI();
+ }
+}
+
+// virtual
+bool LLFloaterBuyLandUI::canClose()
+{
+ // mTransactionType check for pre-buy estimation stage and mCurrency to allow exit after transaction
+ bool can_close = !mTransaction && (mTransactionType != TransactionBuy || mCurrency.canCancel());
+ if (!can_close)
+ {
+ // explain to user why they can't do this, see DEV-9605
+ LLNotificationsUtil::add("CannotCloseFloaterBuyLand");
+ }
+ return can_close;
+}
+
+void LLFloaterBuyLandUI::onVisibilityChanged ( const LLSD& new_visibility )
+{
+ if (new_visibility.asBoolean())
+ {
+ refreshUI();
+ }
+}
+
+void LLFloaterBuyLandUI::refreshUI()
+{
+ // section zero: title area
+ {
+ LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
+ if (snapshot)
+ {
+ snapshot->setImageAssetID(
+ mParcelValid ? mParcelSnapshot : LLUUID::null);
+ }
+
+ if (mParcelValid)
+ {
+ getChild<LLUICtrl>("info_parcel")->setValue(mParcelLocation);
+
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mParcelActualArea);
+ string_args["[AMOUNT2]"] = llformat("%d", mParcelSupportedObjects);
+
+ getChild<LLUICtrl>("info_size")->setValue(getString("meters_supports_object", string_args));
+
+ F32 cost_per_sqm = 0.0f;
+ if (mParcelActualArea > 0)
+ {
+ cost_per_sqm = (F32)mParcelPrice / (F32)mParcelActualArea;
+ }
+
+ LLStringUtil::format_map_t info_price_args;
+ info_price_args["[PRICE]"] = llformat("%d", mParcelPrice);
+ info_price_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm);
+ if (mParcelSoldWithObjects)
+ {
+ info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects");
+ }
+ else
+ {
+ info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects");
+ }
+ getChild<LLUICtrl>("info_price")->setValue(getString("info_price_string", info_price_args));
+ getChildView("info_price")->setVisible( mParcelIsForSale);
+ }
+ else
+ {
+ getChild<LLUICtrl>("info_parcel")->setValue(getString("no_parcel_selected"));
+ getChild<LLUICtrl>("info_size")->setValue(LLStringUtil::null);
+ getChild<LLUICtrl>("info_price")->setValue(LLStringUtil::null);
+ }
+
+ getChild<LLUICtrl>("info_action")->setValue(
+ mCanBuy
+ ?
+ mIsForGroup
+ ? getString("buying_for_group")//"Buying land for group:"
+ : getString("buying_will")//"Buying this land will:"
+ :
+ mCannotBuyIsError
+ ? getString("cannot_buy_now")//"Cannot buy now:"
+ : getString("not_for_sale")//"Not for sale:"
+
+ );
+ }
+
+ bool showingError = !mCanBuy || !mSiteValid;
+
+ // error section
+ if (showingError)
+ {
+ mChildren.setBadge(std::string("step_error"),
+ mCannotBuyIsError
+ ? LLViewChildren::BADGE_ERROR
+ : LLViewChildren::BADGE_WARN);
+
+ LLTextBox* message = getChild<LLTextBox>("error_message");
+ if (message)
+ {
+ message->setVisible(true);
+ message->setValue(LLSD(!mCanBuy ? mCannotBuyReason : "(waiting for data)"));
+ }
+
+ getChildView("error_web")->setVisible(mCannotBuyIsError && !mCannotBuyURI.empty());
+ }
+ else
+ {
+ getChildView("step_error")->setVisible(false);
+ getChildView("error_message")->setVisible(false);
+ getChildView("error_web")->setVisible(false);
+ }
+
+
+ // section one: account
+ if (!showingError)
+ {
+ mChildren.setBadge(std::string("step_1"),
+ mSiteMembershipUpgrade
+ ? LLViewChildren::BADGE_NOTE
+ : LLViewChildren::BADGE_OK);
+ getChild<LLUICtrl>("account_action")->setValue(mSiteMembershipAction);
+ getChild<LLUICtrl>("account_reason")->setValue(
+ mSiteMembershipUpgrade
+ ? getString("must_upgrade")
+ : getString("cant_own_land")
+ );
+
+ LLComboBox* levels = getChild<LLComboBox>( "account_level");
+ if (levels)
+ {
+ levels->setVisible(mSiteMembershipUpgrade);
+
+ levels->removeall();
+ for(std::vector<std::string>::const_iterator i
+ = mSiteMembershipPlanNames.begin();
+ i != mSiteMembershipPlanNames.end();
+ ++i)
+ {
+ levels->add(*i);
+ }
+
+ levels->setCurrentByIndex(mUserPlanChoice);
+ }
+
+ getChildView("step_1")->setVisible(true);
+ getChildView("account_action")->setVisible(true);
+ getChildView("account_reason")->setVisible(true);
+ }
+ else
+ {
+ getChildView("step_1")->setVisible(false);
+ getChildView("account_action")->setVisible(false);
+ getChildView("account_reason")->setVisible(false);
+ getChildView("account_level")->setVisible(false);
+ }
+
+ // section two: land use fees
+ if (!showingError)
+ {
+ mChildren.setBadge(std::string("step_2"),
+ mSiteLandUseUpgrade
+ ? LLViewChildren::BADGE_NOTE
+ : LLViewChildren::BADGE_OK);
+ getChild<LLUICtrl>("land_use_action")->setValue(mSiteLandUseAction);
+
+ std::string message;
+
+ if (mIsForGroup)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[GROUP]"] = std::string(gAgent.getGroupName());
+
+ message += getString("insufficient_land_credits", string_args);
+
+ }
+ else
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[BUYER]"] = llformat("%d", mAgentCommittedTier);
+ message += getString("land_holdings", string_args);
+ }
+
+ if (!mParcelValid)
+ {
+ message += LLTrans::getString("sentences_separator") + getString("no_parcel_selected");
+ }
+ else if (mParcelBillableArea == mParcelActualArea)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d ", mParcelActualArea);
+ message += LLTrans::getString("sentences_separator") + getString("parcel_meters", string_args);
+ }
+ else
+ {
+
+ if (mParcelBillableArea > mParcelActualArea)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
+ message += LLTrans::getString("sentences_separator") + getString("premium_land", string_args);
+ }
+ else
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
+ message += LLTrans::getString("sentences_separator") + getString("discounted_land", string_args);
+ }
+ }
+
+ getChild<LLUICtrl>("land_use_reason")->setValue(message);
+
+ getChildView("step_2")->setVisible(true);
+ getChildView("land_use_action")->setVisible(true);
+ getChildView("land_use_reason")->setVisible(true);
+ }
+ else
+ {
+ getChildView("step_2")->setVisible(false);
+ getChildView("land_use_action")->setVisible(false);
+ getChildView("land_use_reason")->setVisible(false);
+ }
+
+ // section three: purchase & currency
+ S32 finalBalance = mAgentCashBalance + mCurrency.getAmount() - mParcelPrice;
+ bool willHaveEnough = finalBalance >= 0;
+ bool haveEnough = mAgentCashBalance >= mParcelPrice;
+ S32 minContribution = llceil((F32)mParcelBillableArea / GROUP_LAND_BONUS_FACTOR);
+ bool groupContributionEnough = mParcelGroupContribution >= minContribution;
+
+ mCurrency.updateUI(!showingError && !haveEnough);
+
+ if (!showingError)
+ {
+ mChildren.setBadge(std::string("step_3"),
+ !willHaveEnough
+ ? LLViewChildren::BADGE_WARN
+ : mCurrency.getAmount() > 0
+ ? LLViewChildren::BADGE_NOTE
+ : LLViewChildren::BADGE_OK);
+
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
+ string_args["[SELLER]"] = mParcelSellerName;
+ getChild<LLUICtrl>("purchase_action")->setValue(getString("pay_to_for_land", string_args));
+ getChildView("purchase_action")->setVisible( mParcelValid);
+
+ std::string reasonString;
+
+ if (haveEnough)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
+
+ getChild<LLUICtrl>("currency_reason")->setValue(getString("have_enough_lindens", string_args));
+ }
+ else
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
+ string_args["[AMOUNT2]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
+
+ getChild<LLUICtrl>("currency_reason")->setValue(getString("not_enough_lindens", string_args));
+
+ getChild<LLUICtrl>("currency_est")->setTextArg("[LOCAL_AMOUNT]", mCurrency.getLocalEstimate());
+ }
+
+ if (willHaveEnough)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", finalBalance);
+
+ getChild<LLUICtrl>("currency_balance")->setValue(getString("balance_left", string_args));
+
+ }
+ else
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
+
+ getChild<LLUICtrl>("currency_balance")->setValue(getString("balance_needed", string_args));
+
+ }
+
+ getChild<LLUICtrl>("remove_contribution")->setValue(LLSD(groupContributionEnough));
+ getChildView("remove_contribution")->setEnabled(groupContributionEnough);
+ bool showRemoveContribution = mParcelIsGroupLand
+ && (mParcelGroupContribution > 0);
+ getChildView("remove_contribution")->setLabelArg("[AMOUNT]",
+ llformat("%d", minContribution));
+ getChildView("remove_contribution")->setVisible( showRemoveContribution);
+
+ getChildView("step_3")->setVisible(true);
+ getChildView("purchase_action")->setVisible(true);
+ getChildView("currency_reason")->setVisible(true);
+ getChildView("currency_balance")->setVisible(true);
+ }
+ else
+ {
+ getChildView("step_3")->setVisible(false);
+ getChildView("purchase_action")->setVisible(false);
+ getChildView("currency_reason")->setVisible(false);
+ getChildView("currency_balance")->setVisible(false);
+ getChildView("remove_group_donation")->setVisible(false);
+ }
+
+
+ bool agrees_to_covenant = false;
+ LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
+ if (check)
+ {
+ agrees_to_covenant = check->get();
+ }
+
+ getChildView("buy_btn")->setEnabled(mCanBuy && mSiteValid && willHaveEnough && !mTransaction && agrees_to_covenant);
+}
+
+void LLFloaterBuyLandUI::startBuyPreConfirm()
+{
+ std::string action;
+
+ if (mSiteMembershipUpgrade)
+ {
+ action += mSiteMembershipAction;
+ action += "\n";
+
+ LLComboBox* levels = getChild<LLComboBox>( "account_level");
+ if (levels)
+ {
+ action += " * ";
+ action += mSiteMembershipPlanNames[levels->getCurrentIndex()];
+ action += "\n";
+ }
+ }
+ if (mSiteLandUseUpgrade)
+ {
+ action += mSiteLandUseAction;
+ action += "\n";
+ }
+ if (mCurrency.getAmount() > 0)
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount());
+ string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate();
+
+ action += getString("buy_for_US", string_args);
+ }
+
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
+ string_args["[SELLER]"] = mParcelSellerName;
+ action += getString("pay_to_for_land", string_args);
+
+
+ LLConfirmationManager::confirm(mSiteConfirm,
+ action,
+ *this,
+ &LLFloaterBuyLandUI::startBuyPostConfirm);
+}
+
+void LLFloaterBuyLandUI::startBuyPostConfirm(const std::string& password)
+{
+ runWebSitePrep(password);
+
+ mCanBuy = false;
+ mCannotBuyReason = getString("processing");
+ refreshUI();
+}
+
+
+void LLFloaterBuyLandUI::onClickBuy()
+{
+ startBuyPreConfirm();
+}
+
+void LLFloaterBuyLandUI::onClickCancel()
+{
+ closeFloater();
+}
+
+void LLFloaterBuyLandUI::onClickErrorWeb()
+{
+ LLWeb::loadURLExternal(mCannotBuyURI);
+ closeFloater();
+}
+
+
+