From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llfloaterbuyland.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llfloaterbuyland.cpp') diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 464e7ff4a2..62699c5ef3 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -187,7 +187,7 @@ public: void tellUserError(const std::string& message, const std::string& uri); - virtual BOOL postBuild(); + virtual bool postBuild(); void startBuyPreConfirm(); void startBuyPostConfirm(const std::string& password); @@ -197,7 +197,7 @@ public: void onClickErrorWeb(); virtual void draw(); - virtual BOOL canClose(); + virtual bool canClose(); void onVisibilityChanged ( const LLSD& new_visibility ); @@ -929,7 +929,7 @@ void LLFloaterBuyLandUI::tellUserError( // virtual -BOOL LLFloaterBuyLandUI::postBuild() +bool LLFloaterBuyLandUI::postBuild() { setVisibleCallback(boost::bind(&LLFloaterBuyLandUI::onVisibilityChanged, this, _2)); @@ -941,7 +941,7 @@ BOOL LLFloaterBuyLandUI::postBuild() center(); - return TRUE; + return true; } void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel) @@ -994,7 +994,7 @@ void LLFloaterBuyLandUI::draw() } // virtual -BOOL LLFloaterBuyLandUI::canClose() +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()); -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llfloaterbuyland.cpp | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'indra/newview/llfloaterbuyland.cpp') diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 62699c5ef3..63157058b8 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -306,7 +306,7 @@ 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); + setVisible(false); destroy(); } @@ -569,7 +569,7 @@ void LLFloaterBuyLandUI::updateCovenantInfo() LLTextBox* box = getChild("covenant_text"); if(box) { - box->setVisible(FALSE); + box->setVisible(false); } // send EstateCovenantInfo message @@ -605,14 +605,14 @@ void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, co refreshUI(); // remove the line stating that you must agree - box->setVisible(FALSE); + box->setVisible(false); } else { check->setEnabled(true); // remove the line stating that you must agree - box->setVisible(TRUE); + box->setVisible(true); } } @@ -733,7 +733,7 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password) return; } - BOOL remove_contribution = getChild("remove_contribution")->getValue().asBoolean(); + bool remove_contribution = getChild("remove_contribution")->getValue().asBoolean(); mParcelBuyInfo = LLViewerParcelMgr::getInstance()->setupParcelBuy(gAgent.getID(), gAgent.getSessionID(), gAgent.getGroupID(), mIsForGroup, mIsClaim, remove_contribution); @@ -1097,9 +1097,9 @@ void LLFloaterBuyLandUI::refreshUI() } else { - getChildView("step_error")->setVisible(FALSE); - getChildView("error_message")->setVisible(FALSE); - getChildView("error_web")->setVisible(FALSE); + getChildView("step_error")->setVisible(false); + getChildView("error_message")->setVisible(false); + getChildView("error_web")->setVisible(false); } @@ -1134,16 +1134,16 @@ void LLFloaterBuyLandUI::refreshUI() levels->setCurrentByIndex(mUserPlanChoice); } - getChildView("step_1")->setVisible(TRUE); - getChildView("account_action")->setVisible(TRUE); - getChildView("account_reason")->setVisible(TRUE); + 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); + 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 @@ -1201,15 +1201,15 @@ void LLFloaterBuyLandUI::refreshUI() getChild("land_use_reason")->setValue(message); - getChildView("step_2")->setVisible(TRUE); - getChildView("land_use_action")->setVisible(TRUE); - getChildView("land_use_reason")->setVisible(TRUE); + 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); + getChildView("step_2")->setVisible(false); + getChildView("land_use_action")->setVisible(false); + getChildView("land_use_reason")->setVisible(false); } // section three: purchase & currency @@ -1281,18 +1281,18 @@ void LLFloaterBuyLandUI::refreshUI() 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); + 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); + 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); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llfloaterbuyland.cpp | 2758 ++++++++++++++++++------------------ 1 file changed, 1379 insertions(+), 1379 deletions(-) (limited to 'indra/newview/llfloaterbuyland.cpp') 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 - mSiteMembershipPlanIDs; - std::vector - 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("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("buy_land"); - if (floater) - { - floater->updateFloaterCovenantText(string, asset_id); - } -} - -// static -void LLFloaterBuyLand::updateEstateName(const std::string& name) -{ - LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("buy_land"); - if (floater) - { - floater->updateFloaterEstateName(name); - } -} - -// static -void LLFloaterBuyLand::updateLastModified(const std::string& text) -{ - LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("buy_land"); - if (floater) - { - floater->updateFloaterLastModified(text); - } -} - -// static -void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name) -{ - LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("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("region_name_text"); - if (region_name) - { - std::string region_name_txt = region->getName() + " ("+rating +")"; - region_name->setText(region_name_txt); - - LLIconCtrl* rating_icon = getChild("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("region_type_text"); - if (region_type) - { - region_type->setText(region->getLocalizedSimProductName()); - region_type->setToolTip(region->getLocalizedSimProductName()); - } - - LLTextBox* resellable_clause = getChild("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("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("agree_covenant"); - if(check) - { - check->set(false); - check->setEnabled(true); - check->setCommitCallback(onChangeAgreeCovenant, this); - } - - LLTextBox* box = getChild("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("covenant_editor"); - editor->setText(string); - - LLCheckBoxCtrl* check = getChild("agree_covenant"); - LLTextBox* box = getChild("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("estate_name_text"); - box->setText(name); - box->setToolTip(name); -} - -void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text) -{ - LLTextBox* editor = getChild("covenant_timestamp_text"); - if (editor) editor->setText(text); -} - -void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name) -{ - LLTextBox* box = getChild("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("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( "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("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this)); - getChild("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this)); - getChild("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("info_image"); - if (snapshot) - { - snapshot->setImageAssetID( - mParcelValid ? mParcelSnapshot : LLUUID::null); - } - - if (mParcelValid) - { - getChild("info_parcel")->setValue(mParcelLocation); - - LLStringUtil::format_map_t string_args; - string_args["[AMOUNT]"] = llformat("%d", mParcelActualArea); - string_args["[AMOUNT2]"] = llformat("%d", mParcelSupportedObjects); - - getChild("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("info_price")->setValue(getString("info_price_string", info_price_args)); - getChildView("info_price")->setVisible( mParcelIsForSale); - } - else - { - getChild("info_parcel")->setValue(getString("no_parcel_selected")); - getChild("info_size")->setValue(LLStringUtil::null); - getChild("info_price")->setValue(LLStringUtil::null); - } - - getChild("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("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("account_action")->setValue(mSiteMembershipAction); - getChild("account_reason")->setValue( - mSiteMembershipUpgrade - ? getString("must_upgrade") - : getString("cant_own_land") - ); - - LLComboBox* levels = getChild( "account_level"); - if (levels) - { - levels->setVisible(mSiteMembershipUpgrade); - - levels->removeall(); - for(std::vector::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("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("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("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("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("currency_reason")->setValue(getString("not_enough_lindens", string_args)); - - getChild("currency_est")->setTextArg("[LOCAL_AMOUNT]", mCurrency.getLocalEstimate()); - } - - if (willHaveEnough) - { - LLStringUtil::format_map_t string_args; - string_args["[AMOUNT]"] = llformat("%d", finalBalance); - - getChild("currency_balance")->setValue(getString("balance_left", string_args)); - - } - else - { - LLStringUtil::format_map_t string_args; - string_args["[AMOUNT]"] = llformat("%d", mParcelPrice - mAgentCashBalance); - - getChild("currency_balance")->setValue(getString("balance_needed", string_args)); - - } - - getChild("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("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( "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 + mSiteMembershipPlanIDs; + std::vector + 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("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("buy_land"); + if (floater) + { + floater->updateFloaterCovenantText(string, asset_id); + } +} + +// static +void LLFloaterBuyLand::updateEstateName(const std::string& name) +{ + LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("buy_land"); + if (floater) + { + floater->updateFloaterEstateName(name); + } +} + +// static +void LLFloaterBuyLand::updateLastModified(const std::string& text) +{ + LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("buy_land"); + if (floater) + { + floater->updateFloaterLastModified(text); + } +} + +// static +void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name) +{ + LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance("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("region_name_text"); + if (region_name) + { + std::string region_name_txt = region->getName() + " ("+rating +")"; + region_name->setText(region_name_txt); + + LLIconCtrl* rating_icon = getChild("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("region_type_text"); + if (region_type) + { + region_type->setText(region->getLocalizedSimProductName()); + region_type->setToolTip(region->getLocalizedSimProductName()); + } + + LLTextBox* resellable_clause = getChild("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("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("agree_covenant"); + if(check) + { + check->set(false); + check->setEnabled(true); + check->setCommitCallback(onChangeAgreeCovenant, this); + } + + LLTextBox* box = getChild("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("covenant_editor"); + editor->setText(string); + + LLCheckBoxCtrl* check = getChild("agree_covenant"); + LLTextBox* box = getChild("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("estate_name_text"); + box->setText(name); + box->setToolTip(name); +} + +void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text) +{ + LLTextBox* editor = getChild("covenant_timestamp_text"); + if (editor) editor->setText(text); +} + +void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name) +{ + LLTextBox* box = getChild("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("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( "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("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this)); + getChild("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this)); + getChild("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("info_image"); + if (snapshot) + { + snapshot->setImageAssetID( + mParcelValid ? mParcelSnapshot : LLUUID::null); + } + + if (mParcelValid) + { + getChild("info_parcel")->setValue(mParcelLocation); + + LLStringUtil::format_map_t string_args; + string_args["[AMOUNT]"] = llformat("%d", mParcelActualArea); + string_args["[AMOUNT2]"] = llformat("%d", mParcelSupportedObjects); + + getChild("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("info_price")->setValue(getString("info_price_string", info_price_args)); + getChildView("info_price")->setVisible( mParcelIsForSale); + } + else + { + getChild("info_parcel")->setValue(getString("no_parcel_selected")); + getChild("info_size")->setValue(LLStringUtil::null); + getChild("info_price")->setValue(LLStringUtil::null); + } + + getChild("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("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("account_action")->setValue(mSiteMembershipAction); + getChild("account_reason")->setValue( + mSiteMembershipUpgrade + ? getString("must_upgrade") + : getString("cant_own_land") + ); + + LLComboBox* levels = getChild( "account_level"); + if (levels) + { + levels->setVisible(mSiteMembershipUpgrade); + + levels->removeall(); + for(std::vector::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("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("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("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("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("currency_reason")->setValue(getString("not_enough_lindens", string_args)); + + getChild("currency_est")->setTextArg("[LOCAL_AMOUNT]", mCurrency.getLocalEstimate()); + } + + if (willHaveEnough) + { + LLStringUtil::format_map_t string_args; + string_args["[AMOUNT]"] = llformat("%d", finalBalance); + + getChild("currency_balance")->setValue(getString("balance_left", string_args)); + + } + else + { + LLStringUtil::format_map_t string_args; + string_args["[AMOUNT]"] = llformat("%d", mParcelPrice - mAgentCashBalance); + + getChild("currency_balance")->setValue(getString("balance_needed", string_args)); + + } + + getChild("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("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( "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(); +} + + + -- cgit v1.2.3