llfloaterbuyland.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:34k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloaterbuyland.cpp
  3.  * @brief LLFloaterBuyLand class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2005-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloaterbuyland.h"
  34. // viewer includes
  35. #include "llagent.h"
  36. #include "llbutton.h"
  37. #include "llcachename.h"
  38. #include "llcheckboxctrl.h"
  39. #include "llcombobox.h"
  40. #include "llconfirmationmanager.h"
  41. #include "llcurrencyuimanager.h"
  42. #include "llfloater.h"
  43. #include "llfloaterreg.h"
  44. #include "llfloatertools.h"
  45. #include "llframetimer.h"
  46. #include "lliconctrl.h"
  47. #include "lllineeditor.h"
  48. #include "llnotificationsutil.h"
  49. #include "llparcel.h"
  50. #include "llslurl.h"
  51. #include "llstatusbar.h"
  52. #include "lltextbox.h"
  53. #include "lltexturectrl.h"
  54. #include "llviewchildren.h"
  55. #include "llviewercontrol.h"
  56. #include "lluictrlfactory.h"
  57. #include "llviewerparcelmgr.h"
  58. #include "llviewerregion.h"
  59. #include "llviewertexteditor.h"
  60. #include "llviewerwindow.h"
  61. #include "llweb.h"
  62. #include "llwindow.h"
  63. #include "llworld.h"
  64. #include "llxmlrpctransaction.h"
  65. #include "llviewernetwork.h"
  66. #include "roles_constants.h"
  67. // NOTE: This is duplicated in lldatamoney.cpp ...
  68. const F32 GROUP_LAND_BONUS_FACTOR = 1.1f;
  69. const F64 CURRENCY_ESTIMATE_FREQUENCY = 0.5;
  70. // how long of a pause in typing a currency buy amount before an
  71. // estimate is fetched from the server
  72. class LLFloaterBuyLandUI
  73. : public LLFloater
  74. {
  75. public:
  76. LLFloaterBuyLandUI(const LLSD& key);
  77. virtual ~LLFloaterBuyLandUI();
  78. /*virtual*/ void onClose(bool app_quitting);
  79. // Left padding for maturity rating icon.
  80. static const S32 ICON_PAD = 2;
  81. private:
  82. class SelectionObserver : public LLParcelObserver
  83. {
  84. public:
  85. SelectionObserver(LLFloaterBuyLandUI* floater) : mFloater(floater) {}
  86. virtual void changed();
  87. private:
  88. LLFloaterBuyLandUI* mFloater;
  89. };
  90. private:
  91. SelectionObserver mParcelSelectionObserver;
  92. LLViewerRegion* mRegion;
  93. LLParcelSelectionHandle mParcel;
  94. bool mIsClaim;
  95. bool mIsForGroup;
  96. bool mCanBuy;
  97. bool mCannotBuyIsError;
  98. std::string mCannotBuyReason;
  99. std::string mCannotBuyURI;
  100. bool mBought;
  101. // information about the agent
  102. S32 mAgentCommittedTier;
  103. S32 mAgentCashBalance;
  104. bool mAgentHasNeverOwnedLand;
  105. // information about the parcel
  106. bool mParcelValid;
  107. bool mParcelIsForSale;
  108. bool mParcelIsGroupLand;
  109. S32 mParcelGroupContribution;
  110. S32 mParcelPrice;
  111. S32 mParcelActualArea;
  112. S32 mParcelBillableArea;
  113. S32 mParcelSupportedObjects;
  114. bool mParcelSoldWithObjects;
  115. std::string mParcelLocation;
  116. LLUUID mParcelSnapshot;
  117. std::string mParcelSellerName;
  118. // user's choices
  119. S32 mUserPlanChoice;
  120. // from website
  121. bool mSiteValid;
  122. bool mSiteMembershipUpgrade;
  123. std::string mSiteMembershipAction;
  124. std::vector<std::string>
  125. mSiteMembershipPlanIDs;
  126. std::vector<std::string>
  127. mSiteMembershipPlanNames;
  128. bool mSiteLandUseUpgrade;
  129. std::string mSiteLandUseAction;
  130. std::string mSiteConfirm;
  131. // values in current Preflight transaction... used to avoid extra
  132. // preflights when the parcel manager goes update crazy
  133. S32 mPreflightAskBillableArea;
  134. S32 mPreflightAskCurrencyBuy;
  135. LLViewChildren mChildren;
  136. LLCurrencyUIManager mCurrency;
  137. enum TransactionType
  138. {
  139. TransactionPreflight,
  140. TransactionCurrency,
  141. TransactionBuy
  142. };
  143. LLXMLRPCTransaction* mTransaction;
  144. TransactionType  mTransactionType;
  145. LLViewerParcelMgr::ParcelBuyInfo* mParcelBuyInfo;
  146. public:
  147. void setForGroup(bool is_for_group);
  148. void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
  149. void updateAgentInfo();
  150. void updateParcelInfo();
  151. void updateCovenantInfo();
  152. static void onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data);
  153. void updateFloaterCovenantText(const std::string& string, const LLUUID &asset_id);
  154. void updateFloaterEstateName(const std::string& name);
  155. void updateFloaterLastModified(const std::string& text);
  156. void updateFloaterEstateOwnerName(const std::string& name);
  157. void updateWebSiteInfo();
  158. void finishWebSiteInfo();
  159. void runWebSitePrep(const std::string& password);
  160. void finishWebSitePrep();
  161. void sendBuyLand();
  162. void updateNames();
  163. // Name cache callback
  164. void updateGroupName(const LLUUID& id,
  165.  const std::string& first_name,
  166.  const std::string& last_name,
  167.  BOOL is_group);
  168. void refreshUI();
  169. void startTransaction(TransactionType type, const LLXMLRPCValue& params);
  170. bool checkTransaction();
  171. void tellUserError(const std::string& message, const std::string& uri);
  172. virtual BOOL postBuild();
  173. void startBuyPreConfirm();
  174. void startBuyPostConfirm(const std::string& password);
  175. void onClickBuy();
  176. void onClickCancel();
  177.  void onClickErrorWeb();
  178. virtual void draw();
  179. virtual BOOL canClose();
  180. void onVisibilityChange ( const LLSD& new_visibility );
  181. };
  182. // static
  183. void LLFloaterBuyLand::buyLand(
  184. LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
  185. {
  186. if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
  187. {
  188. LLNotificationsUtil::add("OnlyOfficerCanBuyLand");
  189. return;
  190. }
  191. LLFloaterBuyLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyLandUI>("buy_land");
  192. if (ui)
  193. {
  194. ui->setForGroup(is_for_group);
  195. ui->setParcel(region, parcel);
  196. }
  197. }
  198. // static
  199. void LLFloaterBuyLand::updateCovenantText(const std::string& string, const LLUUID &asset_id)
  200. {
  201. LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
  202. if (floater)
  203. {
  204. floater->updateFloaterCovenantText(string, asset_id);
  205. }
  206. }
  207. // static
  208. void LLFloaterBuyLand::updateEstateName(const std::string& name)
  209. {
  210. LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
  211. if (floater)
  212. {
  213. floater->updateFloaterEstateName(name);
  214. }
  215. }
  216. // static
  217. void LLFloaterBuyLand::updateLastModified(const std::string& text)
  218. {
  219. LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
  220. if (floater)
  221. {
  222. floater->updateFloaterLastModified(text);
  223. }
  224. }
  225. // static
  226. void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name)
  227. {
  228. LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
  229. if (floater)
  230. {
  231. floater->updateFloaterEstateOwnerName(name);
  232. }
  233. }
  234. // static
  235. LLFloater* LLFloaterBuyLand::buildFloater(const LLSD& key)
  236. {
  237. LLFloaterBuyLandUI* floater = new LLFloaterBuyLandUI(key);
  238. return floater;
  239. }
  240. //----------------------------------------------------------------------------
  241. // LLFloaterBuyLandUI
  242. //----------------------------------------------------------------------------
  243. #if LL_WINDOWS
  244. // passing 'this' during construction generates a warning. The callee
  245. // only uses the pointer to hold a reference to 'this' which is
  246. // already valid, so this call does the correct thing. Disable the
  247. // warning so that we can compile without generating a warning.
  248. #pragma warning(disable : 4355)
  249. #endif 
  250. LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
  251. : LLFloater(LLSD()),
  252. mParcelSelectionObserver(this),
  253. mParcel(0),
  254. mBought(false),
  255. mParcelValid(false), mSiteValid(false),
  256. mChildren(*this), mCurrency(*this), mTransaction(0),
  257. mParcelBuyInfo(0)
  258. {
  259. LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
  260. //  LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_buy_land.xml");
  261. }
  262. LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
  263. {
  264. LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
  265. LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
  266. delete mTransaction;
  267. }
  268. // virtual
  269. void LLFloaterBuyLandUI::onClose(bool app_quitting)
  270. {
  271. // This object holds onto observer, transactions, and parcel state.
  272. // Despite being single_instance, destroy it to call destructors and clean
  273. // everything up.
  274. setVisible(FALSE);
  275. destroy();
  276. }
  277. void LLFloaterBuyLandUI::SelectionObserver::changed()
  278. {
  279. if (LLViewerParcelMgr::getInstance()->selectionEmpty())
  280. {
  281. mFloater->closeFloater();
  282. }
  283. else
  284. {
  285. mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
  286. LLViewerParcelMgr::getInstance()->getParcelSelection());
  287. }
  288. }
  289. void LLFloaterBuyLandUI::updateAgentInfo()
  290. {
  291. mAgentCommittedTier = gStatusBar->getSquareMetersCommitted();
  292. mAgentCashBalance = gStatusBar->getBalance();
  293. // *TODO: This is an approximation, we should send this value down
  294. // to the viewer. See SL-10728 for details.
  295. mAgentHasNeverOwnedLand = mAgentCommittedTier == 0;
  296. }
  297. void LLFloaterBuyLandUI::updateParcelInfo()
  298. {
  299. LLParcel* parcel = mParcel->getParcel();
  300. mParcelValid = parcel && mRegion;
  301. mParcelIsForSale = false;
  302. mParcelIsGroupLand = false;
  303. mParcelGroupContribution = 0;
  304. mParcelPrice = 0;
  305. mParcelActualArea = 0;
  306. mParcelBillableArea = 0;
  307. mParcelSupportedObjects = 0;
  308. mParcelSoldWithObjects = false;
  309. mParcelLocation = "";
  310. mParcelSnapshot.setNull();
  311. mParcelSellerName = "";
  312. mCanBuy = false;
  313. mCannotBuyIsError = false;
  314. if (!mParcelValid)
  315. {
  316. mCannotBuyReason = getString("no_land_selected");
  317. return;
  318. }
  319. if (mParcel->getMultipleOwners())
  320. {
  321. mCannotBuyReason = getString("multiple_parcels_selected");
  322. return;
  323. }
  324. const LLUUID& parcelOwner = parcel->getOwnerID();
  325. mIsClaim = parcel->isPublic();
  326. if (!mIsClaim)
  327. {
  328. mParcelActualArea = parcel->getArea();
  329. mParcelIsForSale = parcel->getForSale();
  330. mParcelIsGroupLand = parcel->getIsGroupOwned();
  331. mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0;
  332. if (mParcelIsGroupLand)
  333. {
  334. LLUUID group_id = parcel->getGroupID();
  335. mParcelGroupContribution = gAgent.getGroupContribution(group_id);
  336. }
  337. }
  338. else
  339. {
  340. mParcelActualArea = mParcel->getClaimableArea();
  341. mParcelIsForSale = true;
  342. mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter();
  343. }
  344. mParcelBillableArea =
  345. llround(mRegion->getBillableFactor() * mParcelActualArea);
  346.   mParcelSupportedObjects = llround(
  347. parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()); 
  348.   // Can't have more than region max tasks, regardless of parcel 
  349.   // object bonus factor. 
  350.   LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); 
  351.   if(region) 
  352.   { 
  353. S32 max_tasks_per_region = (S32)region->getMaxTasks(); 
  354. mParcelSupportedObjects = llmin(
  355. mParcelSupportedObjects, max_tasks_per_region); 
  356.   } 
  357. mParcelSoldWithObjects = parcel->getSellWithObjects();
  358. LLVector3 center = parcel->getCenterpoint();
  359. mParcelLocation = llformat("%s %d,%d",
  360. mRegion->getName().c_str(),
  361. (int)center[VX], (int)center[VY]
  362. );
  363. mParcelSnapshot = parcel->getSnapshotID();
  364. updateNames();
  365. bool haveEnoughCash = mParcelPrice <= mAgentCashBalance;
  366. S32 cashBuy = haveEnoughCash ? 0 : (mParcelPrice - mAgentCashBalance);
  367. mCurrency.setAmount(cashBuy, true);
  368. mCurrency.setZeroMessage(haveEnoughCash ? getString("none_needed") : LLStringUtil::null);
  369. // checks that we can buy the land
  370. if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
  371. {
  372. mCannotBuyReason = getString("cant_buy_for_group");
  373. return;
  374. }
  375. if (!mIsClaim)
  376. {
  377. const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID();
  378. const LLUUID buyer = gAgent.getID();
  379. const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer;
  380. if (!mParcelIsForSale
  381. || (mParcelPrice == 0  &&  authorizedBuyer.isNull()))
  382. {
  383. mCannotBuyReason = getString("parcel_not_for_sale");
  384. return;
  385. }
  386. if (parcelOwner == newOwner)
  387. {
  388. if (mIsForGroup)
  389. {
  390. mCannotBuyReason = getString("group_already_owns");
  391. }
  392. else
  393. {
  394. mCannotBuyReason = getString("you_already_own");
  395. }
  396. return;
  397. }
  398. if (!authorizedBuyer.isNull()  &&  buyer != authorizedBuyer)
  399. {
  400. mCannotBuyReason = getString("set_to_sell_to_other");
  401. return;
  402. }
  403. }
  404. else
  405. {
  406. if (mParcelActualArea == 0)
  407. {
  408. mCannotBuyReason = getString("no_public_land");
  409. return;
  410. }
  411. if (mParcel->hasOthersSelected())
  412. {
  413. // Policy: Must not have someone else's land selected
  414. mCannotBuyReason = getString("not_owned_by_you");
  415. return;
  416. }
  417. }
  418. mCanBuy = true;
  419. }
  420. void LLFloaterBuyLandUI::updateCovenantInfo()
  421. {
  422. LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
  423. if(!region) return;
  424. U8 sim_access = region->getSimAccess();
  425. std::string rating = LLViewerRegion::accessToString(sim_access);
  426. LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
  427. if (region_name)
  428. {
  429. std::string region_name_txt = region->getName() + " ("+rating +")";
  430. region_name->setText(region_name_txt);
  431. LLIconCtrl* rating_icon = getChild<LLIconCtrl>("rating_icon");
  432. LLRect rect = rating_icon->getRect();
  433. S32 icon_left_pad = region_name->getRect().mLeft + region_name->getTextBoundingRect().getWidth() + ICON_PAD;
  434. rating_icon->setRect(rect.setOriginAndSize(icon_left_pad, rect.mBottom, rect.getWidth(), rect.getHeight()));
  435. switch(sim_access)
  436. {
  437. case SIM_ACCESS_PG:
  438. rating_icon->setValue(getString("icon_PG"));
  439. break;
  440. case SIM_ACCESS_ADULT:
  441. rating_icon->setValue(getString("icon_R"));
  442. break;
  443. default:
  444. rating_icon->setValue(getString("icon_M"));
  445. }
  446. }
  447. LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
  448. if (region_type)
  449. {
  450. region_type->setText(region->getSimProductName());
  451. }
  452. LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
  453. if (resellable_clause)
  454. {
  455. if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
  456. {
  457. resellable_clause->setText(getString("can_not_resell"));
  458. }
  459. else
  460. {
  461. resellable_clause->setText(getString("can_resell"));
  462. }
  463. }
  464. LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause");
  465. if (changeable_clause)
  466. {
  467. if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES)
  468. {
  469. changeable_clause->setText(getString("can_change"));
  470. }
  471. else
  472. {
  473. changeable_clause->setText(getString("can_not_change"));
  474. }
  475. }
  476. LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
  477. if(check)
  478. {
  479. check->set(false);
  480. check->setEnabled(true);
  481. check->setCommitCallback(onChangeAgreeCovenant, this);
  482. }
  483. LLTextBox* box = getChild<LLTextBox>("covenant_text");
  484. if(box)
  485. {
  486. box->setVisible(FALSE);
  487. }
  488. // send EstateCovenantInfo message
  489. LLMessageSystem *msg = gMessageSystem;
  490. msg->newMessage("EstateCovenantRequest");
  491. msg->nextBlockFast(_PREHASH_AgentData);
  492. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  493. msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
  494. msg->sendReliable(region->getHost());
  495. }
  496. // static
  497. void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data)
  498. {
  499. LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)user_data;
  500. if(self)
  501. {
  502. self->refreshUI();
  503. }
  504. }
  505. void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, const LLUUID& asset_id)
  506. {
  507. LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("covenant_editor");
  508. editor->setText(string);
  509. LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
  510. LLTextBox* box = getChild<LLTextBox>("covenant_text");
  511. if (asset_id.isNull())
  512. {
  513. check->set(true);
  514. check->setEnabled(false);
  515. refreshUI();
  516. // remove the line stating that you must agree
  517. box->setVisible(FALSE);
  518. }
  519. else
  520. {
  521. check->setEnabled(true);
  522. // remove the line stating that you must agree
  523. box->setVisible(TRUE);
  524. }
  525. }
  526. void LLFloaterBuyLandUI::updateFloaterEstateName(const std::string& name)
  527. {
  528. LLTextBox* box = getChild<LLTextBox>("estate_name_text");
  529. if (box) box->setText(name);
  530. }
  531. void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text)
  532. {
  533. LLTextBox* editor = getChild<LLTextBox>("covenant_timestamp_text");
  534. if (editor) editor->setText(text);
  535. }
  536. void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name)
  537. {
  538. LLTextBox* box = getChild<LLTextBox>("estate_owner_text");
  539. if (box) box->setText(name);
  540. }
  541. void LLFloaterBuyLandUI::updateWebSiteInfo()
  542. {
  543. S32 askBillableArea = mIsForGroup ? 0 : mParcelBillableArea;
  544. S32 askCurrencyBuy = mCurrency.getAmount();
  545. if (mTransaction && mTransactionType == TransactionPreflight
  546. &&  mPreflightAskBillableArea == askBillableArea
  547. &&  mPreflightAskCurrencyBuy == askCurrencyBuy)
  548. {
  549. return;
  550. }
  551. mPreflightAskBillableArea = askBillableArea;
  552. mPreflightAskCurrencyBuy = askCurrencyBuy;
  553. #if 0
  554. // enable this code if you want the details to blank while we're talking
  555. // to the web site... it's kind of jarring
  556. mSiteValid = false;
  557. mSiteMembershipUpgrade = false;
  558. mSiteMembershipAction = "(waiting)";
  559. mSiteMembershipPlanIDs.clear();
  560. mSiteMembershipPlanNames.clear();
  561. mSiteLandUseUpgrade = false;
  562. mSiteLandUseAction = "(waiting)";
  563. mSiteCurrencyEstimated = false;
  564. mSiteCurrencyEstimatedCost = 0;
  565. #endif
  566. LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
  567. keywordArgs.appendString("agentId", gAgent.getID().asString());
  568. keywordArgs.appendString(
  569. "secureSessionId",
  570. gAgent.getSecureSessionID().asString());
  571. keywordArgs.appendInt("billableArea", mPreflightAskBillableArea);
  572. keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy);
  573. LLXMLRPCValue params = LLXMLRPCValue::createArray();
  574. params.append(keywordArgs);
  575. startTransaction(TransactionPreflight, params);
  576. }
  577. void LLFloaterBuyLandUI::finishWebSiteInfo()
  578. {
  579. LLXMLRPCValue result = mTransaction->responseValue();
  580. mSiteValid = result["success"].asBool();
  581. if (!mSiteValid)
  582. {
  583. tellUserError(
  584. result["errorMessage"].asString(),
  585. result["errorURI"].asString()
  586. );
  587. return;
  588. }
  589. LLXMLRPCValue membership = result["membership"];
  590. mSiteMembershipUpgrade = membership["upgrade"].asBool();
  591. mSiteMembershipAction = membership["action"].asString();
  592. mSiteMembershipPlanIDs.clear();
  593. mSiteMembershipPlanNames.clear();
  594. LLXMLRPCValue levels = membership["levels"];
  595. for (LLXMLRPCValue level = levels.rewind();
  596. level.isValid();
  597. level = levels.next())
  598. {
  599. mSiteMembershipPlanIDs.push_back(level["id"].asString());
  600. mSiteMembershipPlanNames.push_back(level["description"].asString());
  601. }
  602. mUserPlanChoice = 0;
  603. LLXMLRPCValue landUse = result["landUse"];
  604. mSiteLandUseUpgrade = landUse["upgrade"].asBool();
  605. mSiteLandUseAction = landUse["action"].asString();
  606. LLXMLRPCValue currency = result["currency"];
  607. if (currency["estimatedCost"].isValid())
  608. {
  609. mCurrency.setUSDEstimate(currency["estimatedCost"].asInt());
  610. }
  611. if (currency["estimatedLocalCost"].isValid())
  612. {
  613. mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString());
  614. }
  615. mSiteConfirm = result["confirm"].asString();
  616. }
  617. void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password)
  618. {
  619. if (!mCanBuy)
  620. {
  621. return;
  622. }
  623. BOOL remove_contribution = childGetValue("remove_contribution").asBoolean();
  624. mParcelBuyInfo = LLViewerParcelMgr::getInstance()->setupParcelBuy(gAgent.getID(), gAgent.getSessionID(),
  625. gAgent.getGroupID(), mIsForGroup, mIsClaim, remove_contribution);
  626. if (mParcelBuyInfo
  627. && !mSiteMembershipUpgrade
  628. && !mSiteLandUseUpgrade
  629. && mCurrency.getAmount() == 0
  630. && mSiteConfirm != "password")
  631. {
  632. sendBuyLand();
  633. return;
  634. }
  635. std::string newLevel = "noChange";
  636. if (mSiteMembershipUpgrade)
  637. {
  638. LLComboBox* levels = getChild<LLComboBox>( "account_level");
  639. if (levels)
  640. {
  641. mUserPlanChoice = levels->getCurrentIndex();
  642. newLevel = mSiteMembershipPlanIDs[mUserPlanChoice];
  643. }
  644. }
  645. LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
  646. keywordArgs.appendString("agentId", gAgent.getID().asString());
  647. keywordArgs.appendString(
  648. "secureSessionId",
  649. gAgent.getSecureSessionID().asString());
  650. keywordArgs.appendString("levelId", newLevel);
  651. keywordArgs.appendInt("billableArea",
  652. mIsForGroup ? 0 : mParcelBillableArea);
  653. keywordArgs.appendInt("currencyBuy", mCurrency.getAmount());
  654. keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate());
  655. keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate());
  656. keywordArgs.appendString("confirm", mSiteConfirm);
  657. if (!password.empty())
  658. {
  659. keywordArgs.appendString("password", password);
  660. }
  661. LLXMLRPCValue params = LLXMLRPCValue::createArray();
  662. params.append(keywordArgs);
  663. startTransaction(TransactionBuy, params);
  664. }
  665. void LLFloaterBuyLandUI::finishWebSitePrep()
  666. {
  667. LLXMLRPCValue result = mTransaction->responseValue();
  668. bool success = result["success"].asBool();
  669. if (!success)
  670. {
  671. tellUserError(
  672. result["errorMessage"].asString(),
  673. result["errorURI"].asString()
  674. );
  675. return;
  676. }
  677. sendBuyLand();
  678. }
  679. void LLFloaterBuyLandUI::sendBuyLand()
  680. {
  681. if (mParcelBuyInfo)
  682. {
  683. LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
  684. LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
  685. mBought = true;
  686. }
  687. }
  688. void LLFloaterBuyLandUI::updateNames()
  689. {
  690. LLParcel* parcelp = mParcel->getParcel();
  691. if (!parcelp)
  692. {
  693. mParcelSellerName = LLStringUtil::null;
  694. return;
  695. }
  696. if (mIsClaim)
  697. {
  698. mParcelSellerName = "Linden Lab";
  699. }
  700. else if (parcelp->getIsGroupOwned())
  701. {
  702. gCacheName->get(parcelp->getGroupID(), TRUE,
  703. boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
  704. _1, _2, _3, _4));
  705. }
  706. else
  707. {
  708. mParcelSellerName =
  709. LLSLURL::buildCommand("agent", parcelp->getOwnerID(), "inspect");
  710. }
  711. }
  712. void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
  713.  const std::string& first_name,
  714.  const std::string& last_name,
  715.  BOOL is_group)
  716. {
  717. LLParcel* parcelp = mParcel->getParcel();
  718. if (parcelp
  719. && parcelp->getGroupID() == id)
  720. {
  721. // request is current
  722. mParcelSellerName = first_name;
  723. }
  724. }
  725. void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
  726. {
  727. delete mTransaction;
  728. mTransaction = NULL;
  729. mTransactionType = type;
  730. // Select a URI and method appropriate for the transaction type.
  731. static std::string transaction_uri;
  732. if (transaction_uri.empty())
  733. {
  734. transaction_uri = LLViewerLogin::getInstance()->getHelperURI() + "landtool.php";
  735. }
  736. const char* method;
  737. switch (mTransactionType)
  738. {
  739. case TransactionPreflight:
  740. method = "preflightBuyLandPrep";
  741. break;
  742. case TransactionBuy:
  743. method = "buyLandPrep";
  744. break;
  745. default:
  746. llwarns << "LLFloaterBuyLandUI: Unknown transaction type!" << llendl;
  747. return;
  748. }
  749. mTransaction = new LLXMLRPCTransaction(
  750. transaction_uri,
  751. method,
  752. params,
  753. false /* don't use gzip */
  754. );
  755. }
  756. bool LLFloaterBuyLandUI::checkTransaction()
  757. {
  758. if (!mTransaction)
  759. {
  760. return false;
  761. }
  762. if (!mTransaction->process())
  763. {
  764. return false;
  765. }
  766. if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
  767. {
  768. tellUserError(mTransaction->statusMessage(), mTransaction->statusURI());
  769. }
  770. else {
  771. switch (mTransactionType)
  772. {
  773. case TransactionPreflight: finishWebSiteInfo(); break;
  774. case TransactionBuy: finishWebSitePrep(); break;
  775. default: ;
  776. }
  777. }
  778. delete mTransaction;
  779. mTransaction = NULL;
  780. return true;
  781. }
  782. void LLFloaterBuyLandUI::tellUserError(
  783. const std::string& message, const std::string& uri)
  784. {
  785. mCanBuy = false;
  786. mCannotBuyIsError = true;
  787. mCannotBuyReason = getString("fetching_error");
  788. mCannotBuyReason += message;
  789. mCannotBuyURI = uri;
  790. }
  791. // virtual
  792. BOOL LLFloaterBuyLandUI::postBuild()
  793. {
  794. setVisibleCallback(boost::bind(&LLFloaterBuyLandUI::onVisibilityChange, this, _2));
  795. mCurrency.prepare();
  796. getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this));
  797. getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this));
  798. getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickErrorWeb, this));
  799. center();
  800. return TRUE;
  801. }
  802. void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
  803. {
  804. if (mTransaction &&  mTransactionType == TransactionBuy)
  805. {
  806. // the user is buying, don't change the selection
  807. return;
  808. }
  809. mRegion = region;
  810. mParcel = parcel;
  811. updateAgentInfo();
  812. updateParcelInfo();
  813. updateCovenantInfo();
  814. if (mCanBuy)
  815. {
  816. updateWebSiteInfo();
  817. }
  818. refreshUI();
  819. }
  820. void LLFloaterBuyLandUI::setForGroup(bool forGroup)
  821. {
  822. mIsForGroup = forGroup;
  823. }
  824. void LLFloaterBuyLandUI::draw()
  825. {
  826. LLFloater::draw();
  827. bool needsUpdate = false;
  828. needsUpdate |= checkTransaction();
  829. needsUpdate |= mCurrency.process();
  830. if (mBought)
  831. {
  832. closeFloater();
  833. }
  834. else if (needsUpdate)
  835. {
  836. if (mCanBuy && mCurrency.hasError())
  837. {
  838. tellUserError(mCurrency.errorMessage(), mCurrency.errorURI());
  839. }
  840. refreshUI();
  841. }
  842. }
  843. // virtual
  844. BOOL LLFloaterBuyLandUI::canClose()
  845. {
  846. bool can_close = (mTransaction ? FALSE : TRUE) && mCurrency.canCancel();
  847. if (!can_close)
  848. {
  849. // explain to user why they can't do this, see DEV-9605
  850. LLNotificationsUtil::add("CannotCloseFloaterBuyLand");
  851. }
  852. return can_close;
  853. }
  854. void LLFloaterBuyLandUI::onVisibilityChange ( const LLSD& new_visibility )
  855. {
  856. if (new_visibility.asBoolean())
  857. {
  858. refreshUI();
  859. }
  860. }
  861. void LLFloaterBuyLandUI::refreshUI()
  862. {
  863. // section zero: title area
  864. {
  865. LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
  866. if (snapshot)
  867. {
  868. snapshot->setImageAssetID(
  869. mParcelValid ? mParcelSnapshot : LLUUID::null);
  870. }
  871. if (mParcelValid)
  872. {
  873. childSetText("info_parcel", mParcelLocation);
  874. LLStringUtil::format_map_t string_args;
  875. string_args["[AMOUNT]"] = llformat("%d", mParcelActualArea);
  876. string_args["[AMOUNT2]"] = llformat("%d", mParcelSupportedObjects);
  877. childSetText("info_size", getString("meters_supports_object", string_args));
  878. F32 cost_per_sqm = 0.0f;
  879. if (mParcelActualArea > 0)
  880. {
  881. cost_per_sqm = (F32)mParcelPrice / (F32)mParcelActualArea;
  882. }
  883. LLStringUtil::format_map_t info_price_args;
  884. info_price_args["[PRICE]"] = llformat("%d", mParcelPrice);
  885. info_price_args["[PRICE_PER_SQM]"] = llformat("%.1f", cost_per_sqm);
  886. if (mParcelSoldWithObjects)
  887. {
  888. info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_with_objects");
  889. }
  890. else
  891. {
  892. info_price_args["[SOLD_WITH_OBJECTS]"] = getString("sold_without_objects");
  893. }
  894. childSetText("info_price", getString("info_price_string", info_price_args));
  895. childSetVisible("info_price", mParcelIsForSale);
  896. }
  897. else
  898. {
  899. childSetText("info_parcel", getString("no_parcel_selected"));
  900. childSetText("info_size", LLStringUtil::null);
  901. childSetText("info_price", LLStringUtil::null);
  902. }
  903. childSetText("info_action",
  904. mCanBuy
  905. ?
  906. mIsForGroup
  907. ? getString("buying_for_group")//"Buying land for group:"
  908. : getString("buying_will")//"Buying this land will:"
  909. mCannotBuyIsError
  910. ? getString("cannot_buy_now")//"Cannot buy now:"
  911. : getString("not_for_sale")//"Not for sale:"
  912. );
  913. }
  914. bool showingError = !mCanBuy || !mSiteValid;
  915. // error section
  916. if (showingError)
  917. {
  918. mChildren.setBadge(std::string("step_error"),
  919. mCannotBuyIsError
  920. ? LLViewChildren::BADGE_ERROR
  921. : LLViewChildren::BADGE_WARN);
  922. LLTextBox* message = getChild<LLTextBox>("error_message");
  923. if (message)
  924. {
  925. message->setVisible(true);
  926. message->setValue(LLSD(!mCanBuy ? mCannotBuyReason : "(waiting for data)"));
  927. }
  928. childSetVisible("error_web", 
  929. mCannotBuyIsError && !mCannotBuyURI.empty());
  930. }
  931. else
  932. {
  933. childHide("step_error");
  934. childHide("error_message");
  935. childHide("error_web");
  936. }
  937. // section one: account
  938. if (!showingError)
  939. {
  940. mChildren.setBadge(std::string("step_1"),
  941. mSiteMembershipUpgrade
  942. ? LLViewChildren::BADGE_NOTE
  943. : LLViewChildren::BADGE_OK);
  944. childSetText("account_action", mSiteMembershipAction);
  945. childSetText("account_reason", 
  946. mSiteMembershipUpgrade
  947. ? getString("must_upgrade")
  948. : getString("cant_own_land")
  949. );
  950. LLComboBox* levels = getChild<LLComboBox>( "account_level");
  951. if (levels)
  952. {
  953. levels->setVisible(mSiteMembershipUpgrade);
  954. levels->removeall();
  955. for(std::vector<std::string>::const_iterator i
  956. = mSiteMembershipPlanNames.begin();
  957. i != mSiteMembershipPlanNames.end();
  958. ++i)
  959. {
  960. levels->add(*i);
  961. }
  962. levels->setCurrentByIndex(mUserPlanChoice);
  963. }
  964. childShow("step_1");
  965. childShow("account_action");
  966. childShow("account_reason");
  967. }
  968. else
  969. {
  970. childHide("step_1");
  971. childHide("account_action");
  972. childHide("account_reason");
  973. childHide("account_level");
  974. }
  975. // section two: land use fees
  976. if (!showingError)
  977. {
  978. mChildren.setBadge(std::string("step_2"),
  979. mSiteLandUseUpgrade
  980. ? LLViewChildren::BADGE_NOTE
  981. : LLViewChildren::BADGE_OK);
  982. childSetText("land_use_action", mSiteLandUseAction);
  983. std::string message;
  984. if (mIsForGroup)
  985. {
  986. LLStringUtil::format_map_t string_args;
  987. string_args["[GROUP]"] = std::string(gAgent.getGroupName());
  988. message += getString("insufficient_land_credits", string_args);
  989. }
  990. else
  991. {
  992. LLStringUtil::format_map_t string_args;
  993. string_args["[BUYER]"] = llformat("%d", mAgentCommittedTier);
  994. message += getString("land_holdings", string_args);
  995. }
  996. if (!mParcelValid)
  997. {
  998. message += getString("no_parcel_selected");
  999. }
  1000. else if (mParcelBillableArea == mParcelActualArea)
  1001. {
  1002. LLStringUtil::format_map_t string_args;
  1003. string_args["[AMOUNT]"] = llformat("%d ", mParcelActualArea);
  1004. message += getString("parcel_meters", string_args);
  1005. }
  1006. else
  1007. {
  1008. if (mParcelBillableArea > mParcelActualArea)
  1009. {
  1010. LLStringUtil::format_map_t string_args;
  1011. string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
  1012. message += getString("premium_land", string_args);
  1013. }
  1014. else
  1015. {
  1016. LLStringUtil::format_map_t string_args;
  1017. string_args["[AMOUNT]"] = llformat("%d ", mParcelBillableArea);
  1018. message += getString("discounted_land", string_args);
  1019. }
  1020. }
  1021. childSetValue("land_use_reason", message);
  1022. childShow("step_2");
  1023. childShow("land_use_action");
  1024. childShow("land_use_reason");
  1025. }
  1026. else
  1027. {
  1028. childHide("step_2");
  1029. childHide("land_use_action");
  1030. childHide("land_use_reason");
  1031. }
  1032. // section three: purchase & currency
  1033. S32 finalBalance = mAgentCashBalance + mCurrency.getAmount() - mParcelPrice;
  1034. bool willHaveEnough = finalBalance >= 0;
  1035. bool haveEnough = mAgentCashBalance >= mParcelPrice;
  1036. S32 minContribution = llceil((F32)mParcelBillableArea / GROUP_LAND_BONUS_FACTOR);
  1037. bool groupContributionEnough = mParcelGroupContribution >= minContribution;
  1038. mCurrency.updateUI(!showingError  &&  !haveEnough);
  1039. if (!showingError)
  1040. {
  1041. mChildren.setBadge(std::string("step_3"),
  1042. !willHaveEnough
  1043. ? LLViewChildren::BADGE_WARN
  1044. : mCurrency.getAmount() > 0
  1045. ? LLViewChildren::BADGE_NOTE
  1046. : LLViewChildren::BADGE_OK);
  1047. LLStringUtil::format_map_t string_args;
  1048. string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
  1049. string_args["[SELLER]"] = mParcelSellerName;
  1050. childSetText("purchase_action", getString("pay_to_for_land", string_args));
  1051. childSetVisible("purchase_action", mParcelValid);
  1052. std::string reasonString;
  1053. if (haveEnough)
  1054. {
  1055. LLStringUtil::format_map_t string_args;
  1056. string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
  1057. childSetText("currency_reason", getString("have_enough_lindens", string_args));
  1058. }
  1059. else
  1060. {
  1061. LLStringUtil::format_map_t string_args;
  1062. string_args["[AMOUNT]"] = llformat("%d", mAgentCashBalance);
  1063. string_args["[AMOUNT2]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
  1064. childSetText("currency_reason", getString("not_enough_lindens", string_args));
  1065. childSetTextArg("currency_est", "[LOCAL_AMOUNT]", mCurrency.getLocalEstimate());
  1066. }
  1067. if (willHaveEnough)
  1068. {
  1069. LLStringUtil::format_map_t string_args;
  1070. string_args["[AMOUNT]"] = llformat("%d", finalBalance);
  1071. childSetText("currency_balance", getString("balance_left", string_args));
  1072. }
  1073. else
  1074. {
  1075. LLStringUtil::format_map_t string_args;
  1076. string_args["[AMOUNT]"] = llformat("%d", mParcelPrice - mAgentCashBalance);
  1077. childSetText("currency_balance", getString("balance_needed", string_args));
  1078. }
  1079. childSetValue("remove_contribution", LLSD(groupContributionEnough));
  1080. childSetEnabled("remove_contribution", groupContributionEnough);
  1081. bool showRemoveContribution = mParcelIsGroupLand
  1082. && (mParcelGroupContribution > 0);
  1083. childSetLabelArg("remove_contribution", "[AMOUNT]",
  1084. llformat("%d", minContribution));
  1085. childSetVisible("remove_contribution", showRemoveContribution);
  1086. childShow("step_3");
  1087. childShow("purchase_action");
  1088. childShow("currency_reason");
  1089. childShow("currency_balance");
  1090. }
  1091. else
  1092. {
  1093. childHide("step_3");
  1094. childHide("purchase_action");
  1095. childHide("currency_reason");
  1096. childHide("currency_balance");
  1097. childHide("remove_group_donation");
  1098. }
  1099. bool agrees_to_covenant = false;
  1100. LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
  1101. if (check)
  1102. {
  1103.     agrees_to_covenant = check->get();
  1104. }
  1105. childSetEnabled("buy_btn",
  1106. mCanBuy  &&  mSiteValid  &&  willHaveEnough  &&  !mTransaction && agrees_to_covenant);
  1107. }
  1108. void LLFloaterBuyLandUI::startBuyPreConfirm()
  1109. {
  1110. std::string action;
  1111. if (mSiteMembershipUpgrade)
  1112. {
  1113. action += mSiteMembershipAction;
  1114. action += "n";
  1115. LLComboBox* levels = getChild<LLComboBox>( "account_level");
  1116. if (levels)
  1117. {
  1118. action += " * ";
  1119. action += mSiteMembershipPlanNames[levels->getCurrentIndex()];
  1120. action += "n";
  1121. }
  1122. }
  1123. if (mSiteLandUseUpgrade)
  1124. {
  1125. action += mSiteLandUseAction;
  1126. action += "n";
  1127. }
  1128. if (mCurrency.getAmount() > 0)
  1129. {
  1130. LLStringUtil::format_map_t string_args;
  1131. string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount());
  1132. string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate();
  1133. action += getString("buy_for_US", string_args);
  1134. }
  1135. LLStringUtil::format_map_t string_args;
  1136. string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
  1137. string_args["[SELLER]"] = mParcelSellerName;
  1138. action += getString("pay_to_for_land", string_args);
  1139. LLConfirmationManager::confirm(mSiteConfirm,
  1140. action,
  1141. *this,
  1142. &LLFloaterBuyLandUI::startBuyPostConfirm);
  1143. }
  1144. void LLFloaterBuyLandUI::startBuyPostConfirm(const std::string& password)
  1145. {
  1146. runWebSitePrep(password);
  1147. mCanBuy = false;
  1148. mCannotBuyReason = getString("processing");
  1149. refreshUI();
  1150. }
  1151. void LLFloaterBuyLandUI::onClickBuy()
  1152. {
  1153. startBuyPreConfirm();
  1154. }
  1155. void LLFloaterBuyLandUI::onClickCancel()
  1156. {
  1157. closeFloater();
  1158. }
  1159. void LLFloaterBuyLandUI::onClickErrorWeb()
  1160. {
  1161. LLWeb::loadURLExternal(mCannotBuyURI);
  1162. closeFloater();
  1163. }