diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfloaterbuyland.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llfloaterbuyland.cpp | 1377 |
1 files changed, 1377 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterbuyland.cpp b/linden/indra/newview/llfloaterbuyland.cpp new file mode 100644 index 0000000..ca5f677 --- /dev/null +++ b/linden/indra/newview/llfloaterbuyland.cpp | |||
@@ -0,0 +1,1377 @@ | |||
1 | /** | ||
2 | * @file llfloaterbuyland.cpp | ||
3 | * @brief LLFloaterBuyLand class implementation | ||
4 | * | ||
5 | * Copyright (c) 2005-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llfloaterbuyland.h" | ||
31 | |||
32 | // viewer includes | ||
33 | #include "llagent.h" | ||
34 | #include "llbutton.h" | ||
35 | #include "llcachename.h" | ||
36 | #include "llcheckboxctrl.h" | ||
37 | #include "llcombobox.h" | ||
38 | #include "llconfirmationmanager.h" | ||
39 | #include "llcurrencyuimanager.h" | ||
40 | #include "llfloater.h" | ||
41 | #include "llfloatertools.h" | ||
42 | #include "llframetimer.h" | ||
43 | #include "lliconctrl.h" | ||
44 | #include "lllineeditor.h" | ||
45 | #include "llnotify.h" | ||
46 | #include "llparcel.h" | ||
47 | #include "llstatusbar.h" | ||
48 | #include "lltextbox.h" | ||
49 | #include "lltexturectrl.h" | ||
50 | #include "llviewchildren.h" | ||
51 | #include "llviewercontrol.h" | ||
52 | #include "llvieweruictrlfactory.h" | ||
53 | #include "llviewerparcelmgr.h" | ||
54 | #include "llviewerregion.h" | ||
55 | #include "llviewertexteditor.h" | ||
56 | #include "llviewerwindow.h" | ||
57 | #include "llweb.h" | ||
58 | #include "llwindow.h" | ||
59 | #include "llworld.h" | ||
60 | #include "llxmlrpctransaction.h" | ||
61 | #include "viewer.h" | ||
62 | #include "roles_constants.h" | ||
63 | |||
64 | // NOTE: This is duplicated in lldatamoney.cpp ... | ||
65 | const F32 GROUP_LAND_BONUS_FACTOR = 1.1f; | ||
66 | const F64 CURRENCY_ESTIMATE_FREQUENCY = 0.5; | ||
67 | // how long of a pause in typing a currency buy amount before an | ||
68 | // esimate is fetched from the server | ||
69 | |||
70 | class LLFloaterBuyLandUI | ||
71 | : public LLFloater | ||
72 | { | ||
73 | private: | ||
74 | LLFloaterBuyLandUI(); | ||
75 | virtual ~LLFloaterBuyLandUI(); | ||
76 | |||
77 | LLViewerRegion* mRegion; | ||
78 | LLParcel* mParcel; | ||
79 | bool mIsClaim; | ||
80 | bool mIsForGroup; | ||
81 | |||
82 | bool mCanBuy; | ||
83 | bool mCannotBuyIsError; | ||
84 | std::string mCannotBuyReason; | ||
85 | std::string mCannotBuyURI; | ||
86 | |||
87 | bool mBought; | ||
88 | |||
89 | // information about the agent | ||
90 | S32 mAgentCommittedTier; | ||
91 | S32 mAgentCashBalance; | ||
92 | bool mAgentHasNeverOwnedLand; | ||
93 | |||
94 | // information about the parcel | ||
95 | bool mParcelValid; | ||
96 | bool mParcelIsForSale; | ||
97 | bool mParcelIsFirstLand; | ||
98 | bool mParcelIsGroupLand; | ||
99 | S32 mParcelGroupContribution; | ||
100 | S32 mParcelPrice; | ||
101 | S32 mParcelActualArea; | ||
102 | S32 mParcelBillableArea; | ||
103 | S32 mParcelSupportedObjects; | ||
104 | bool mParcelSoldWithObjects; | ||
105 | std::string mParcelLocation; | ||
106 | LLUUID mParcelSnapshot; | ||
107 | std::string mParcelSellerName; | ||
108 | |||
109 | // user's choices | ||
110 | S32 mUserPlanChoice; | ||
111 | |||
112 | // from website | ||
113 | bool mSiteValid; | ||
114 | bool mSiteMembershipUpgrade; | ||
115 | std::string mSiteMembershipAction; | ||
116 | std::vector<std::string> | ||
117 | mSiteMembershipPlanIDs; | ||
118 | std::vector<std::string> | ||
119 | mSiteMembershipPlanNames; | ||
120 | bool mSiteLandUseUpgrade; | ||
121 | std::string mSiteLandUseAction; | ||
122 | std::string mSiteConfirm; | ||
123 | |||
124 | // values in current Preflight transaction... used to avoid extra | ||
125 | // preflights when the parcel manager goes update crazy | ||
126 | S32 mPreflightAskBillableArea; | ||
127 | S32 mPreflightAskCurrencyBuy; | ||
128 | |||
129 | LLViewChildren mChildren; | ||
130 | LLCurrencyUIManager mCurrency; | ||
131 | |||
132 | enum TransactionType | ||
133 | { | ||
134 | TransactionPreflight, | ||
135 | TransactionCurrency, | ||
136 | TransactionBuy | ||
137 | }; | ||
138 | LLXMLRPCTransaction* mTransaction; | ||
139 | TransactionType mTransactionType; | ||
140 | |||
141 | LLViewerParcelMgr::ParcelBuyInfo* mParcelBuyInfo; | ||
142 | |||
143 | static LLFloaterBuyLandUI* sInstance; | ||
144 | |||
145 | public: | ||
146 | static LLFloaterBuyLandUI* soleInstance(bool createIfNeeded); | ||
147 | |||
148 | void setForGroup(bool is_for_group); | ||
149 | void setParcel(LLViewerRegion* region, LLParcel* parcel); | ||
150 | |||
151 | void updateAgentInfo(); | ||
152 | void updateParcelInfo(); | ||
153 | void updateCovenantInfo(); | ||
154 | static void onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data); | ||
155 | void updateCovenantText(const std::string& string, const LLUUID &asset_id); | ||
156 | void updateEstateName(const std::string& name); | ||
157 | void updateLastModified(const std::string& text); | ||
158 | void updateEstateOwnerName(const std::string& name); | ||
159 | void updateWebSiteInfo(); | ||
160 | void finishWebSiteInfo(); | ||
161 | |||
162 | void runWebSitePrep(const std::string& password); | ||
163 | void finishWebSitePrep(); | ||
164 | void sendBuyLand(); | ||
165 | |||
166 | void updateNames(); | ||
167 | |||
168 | void refreshUI(); | ||
169 | |||
170 | void startTransaction(TransactionType type, LLXMLRPCValue params); | ||
171 | bool checkTransaction(); | ||
172 | |||
173 | void tellUserError(const std::string& message, const std::string& uri); | ||
174 | |||
175 | virtual BOOL postBuild(); | ||
176 | |||
177 | void startBuyPreConfirm(); | ||
178 | void startBuyPostConfirm(const std::string& password); | ||
179 | |||
180 | static void onClickBuy(void* data); | ||
181 | static void onClickCancel(void* data); | ||
182 | static void onClickErrorWeb(void* data); | ||
183 | |||
184 | virtual void draw(); | ||
185 | virtual BOOL canClose(); | ||
186 | virtual void onClose(bool app_quitting); | ||
187 | |||
188 | private: | ||
189 | class SelectionObserver : public LLParcelObserver | ||
190 | { | ||
191 | public: | ||
192 | virtual void changed(); | ||
193 | }; | ||
194 | }; | ||
195 | |||
196 | static void cacheNameUpdateRefreshesBuyLand(const LLUUID&, | ||
197 | const char*, const char*, BOOL, void* data) | ||
198 | { | ||
199 | LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(false); | ||
200 | if (ui) | ||
201 | { | ||
202 | ui->updateNames(); | ||
203 | } | ||
204 | } | ||
205 | |||
206 | // static | ||
207 | void LLFloaterBuyLand::buyLand( | ||
208 | LLViewerRegion* region, LLParcel* parcel, bool is_for_group) | ||
209 | { | ||
210 | if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED)) | ||
211 | { | ||
212 | gViewerWindow->alertXml("OnlyOfficerCanBuyLand"); | ||
213 | return; | ||
214 | } | ||
215 | |||
216 | LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(true); | ||
217 | ui->setForGroup(is_for_group); | ||
218 | ui->setParcel(region, parcel); | ||
219 | ui->open(); | ||
220 | } | ||
221 | |||
222 | // static | ||
223 | void LLFloaterBuyLand::updateCovenantText(const std::string& string, const LLUUID &asset_id) | ||
224 | { | ||
225 | LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE); | ||
226 | if (floater) | ||
227 | { | ||
228 | floater->updateCovenantText(string, asset_id); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | // static | ||
233 | void LLFloaterBuyLand::updateEstateName(const std::string& name) | ||
234 | { | ||
235 | LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE); | ||
236 | if (floater) | ||
237 | { | ||
238 | floater->updateEstateName(name); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | // static | ||
243 | void LLFloaterBuyLand::updateLastModified(const std::string& text) | ||
244 | { | ||
245 | LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE); | ||
246 | if (floater) | ||
247 | { | ||
248 | floater->updateLastModified(text); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | // static | ||
253 | void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name) | ||
254 | { | ||
255 | LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE); | ||
256 | if (floater) | ||
257 | { | ||
258 | floater->updateEstateOwnerName(name); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | // static | ||
263 | BOOL LLFloaterBuyLand::isOpen() | ||
264 | { | ||
265 | LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE); | ||
266 | if (floater) | ||
267 | { | ||
268 | return floater->getVisible(); | ||
269 | } | ||
270 | return FALSE; | ||
271 | } | ||
272 | |||
273 | // static | ||
274 | LLFloaterBuyLandUI* LLFloaterBuyLandUI::sInstance = NULL; | ||
275 | |||
276 | // static | ||
277 | LLFloaterBuyLandUI* LLFloaterBuyLandUI::soleInstance(bool createIfNeeded) | ||
278 | { | ||
279 | #if !LL_RELEASE_FOR_DOWNLOAD | ||
280 | if (createIfNeeded) | ||
281 | { | ||
282 | delete sInstance; | ||
283 | sInstance = NULL; | ||
284 | } | ||
285 | #endif | ||
286 | if (!sInstance && createIfNeeded) | ||
287 | { | ||
288 | sInstance = new LLFloaterBuyLandUI(); | ||
289 | |||
290 | gUICtrlFactory->buildFloater(sInstance, "floater_buy_land.xml"); | ||
291 | sInstance->center(); | ||
292 | |||
293 | static bool observingCacheName = false; | ||
294 | if (!observingCacheName) | ||
295 | { | ||
296 | gCacheName->addObserver(cacheNameUpdateRefreshesBuyLand); | ||
297 | observingCacheName = true; | ||
298 | } | ||
299 | |||
300 | static SelectionObserver* parcelSelectionObserver = NULL; | ||
301 | if (!parcelSelectionObserver) | ||
302 | { | ||
303 | parcelSelectionObserver = new SelectionObserver; | ||
304 | gParcelMgr->addObserver(parcelSelectionObserver); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | return sInstance; | ||
309 | } | ||
310 | |||
311 | |||
312 | #if LL_WINDOWS | ||
313 | // passing 'this' during construction generates a warning. The callee | ||
314 | // only uses the pointer to hold a reference to 'this' which is | ||
315 | // already valid, so this call does the correct thing. Disable the | ||
316 | // warning so that we can compile without generating a warning. | ||
317 | #pragma warning(disable : 4355) | ||
318 | #endif | ||
319 | LLFloaterBuyLandUI::LLFloaterBuyLandUI() | ||
320 | : LLFloater("Buy Land"), | ||
321 | mParcel(0), | ||
322 | mBought(false), | ||
323 | mParcelValid(false), mSiteValid(false), | ||
324 | mChildren(*this), mCurrency(*this), mTransaction(0), | ||
325 | mParcelBuyInfo(0) | ||
326 | { | ||
327 | } | ||
328 | |||
329 | LLFloaterBuyLandUI::~LLFloaterBuyLandUI() | ||
330 | { | ||
331 | delete mTransaction; | ||
332 | |||
333 | gParcelMgr->deleteParcelBuy(mParcelBuyInfo); | ||
334 | |||
335 | if (sInstance == this) | ||
336 | { | ||
337 | sInstance = NULL; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | void LLFloaterBuyLandUI::SelectionObserver::changed() | ||
342 | { | ||
343 | LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(false); | ||
344 | if (ui) | ||
345 | { | ||
346 | if (gParcelMgr->selectionEmpty()) | ||
347 | { | ||
348 | ui->close(); | ||
349 | } | ||
350 | else { | ||
351 | ui->setParcel( | ||
352 | gParcelMgr->getSelectionRegion(), | ||
353 | gParcelMgr->getSelectedParcel()); | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
358 | |||
359 | void LLFloaterBuyLandUI::updateAgentInfo() | ||
360 | { | ||
361 | mAgentCommittedTier = gStatusBar->getSquareMetersCommitted(); | ||
362 | mAgentCashBalance = gStatusBar->getBalance(); | ||
363 | |||
364 | // *TODO: This is an approximation, we should send this value down | ||
365 | // to the viewer. See SL-10728 for details. | ||
366 | mAgentHasNeverOwnedLand = mAgentCommittedTier == 0; | ||
367 | } | ||
368 | |||
369 | void LLFloaterBuyLandUI::updateParcelInfo() | ||
370 | { | ||
371 | mParcelValid = mParcel && mRegion; | ||
372 | mParcelIsForSale = false; | ||
373 | mParcelIsFirstLand = false; | ||
374 | mParcelIsGroupLand = false; | ||
375 | mParcelGroupContribution = 0; | ||
376 | mParcelPrice = 0; | ||
377 | mParcelActualArea = 0; | ||
378 | mParcelBillableArea = 0; | ||
379 | mParcelSupportedObjects = 0; | ||
380 | mParcelSoldWithObjects = false; | ||
381 | mParcelLocation = ""; | ||
382 | mParcelSnapshot.setNull(); | ||
383 | mParcelSellerName = ""; | ||
384 | |||
385 | mCanBuy = false; | ||
386 | mCannotBuyIsError = false; | ||
387 | |||
388 | if (!mParcelValid) | ||
389 | { | ||
390 | mCannotBuyReason= childGetText("no_land_selected"); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | if (gParcelMgr->getMultipleOwners()) | ||
395 | { | ||
396 | mCannotBuyReason = childGetText("multiple_parcels_selected"); | ||
397 | return; | ||
398 | } | ||
399 | |||
400 | |||
401 | const LLUUID& parcelOwner = mParcel->getOwnerID(); | ||
402 | |||
403 | mIsClaim = mParcel->isPublic(); | ||
404 | if (!mIsClaim) | ||
405 | { | ||
406 | mParcelActualArea = mParcel->getArea(); | ||
407 | mParcelIsForSale = mParcel->getForSale(); | ||
408 | mParcelIsFirstLand = mParcel->getReservedForNewbie(); | ||
409 | mParcelIsGroupLand = mParcel->getIsGroupOwned(); | ||
410 | mParcelPrice = mParcelIsForSale ? mParcel->getSalePrice() : 0; | ||
411 | |||
412 | if (mParcelIsGroupLand) | ||
413 | { | ||
414 | LLUUID group_id = mParcel->getGroupID(); | ||
415 | mParcelGroupContribution = gAgent.getGroupContribution(group_id); | ||
416 | } | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | mParcelActualArea = gParcelMgr->getClaimableArea(); | ||
421 | mParcelIsForSale = true; | ||
422 | mParcelPrice = mParcelActualArea * mParcel->getClaimPricePerMeter(); | ||
423 | } | ||
424 | |||
425 | mParcelBillableArea = | ||
426 | llround(mRegion->getBillableFactor() * mParcelActualArea); | ||
427 | |||
428 | mParcelSupportedObjects = mParcel->getMaxPrimCapacity(); | ||
429 | mParcelSoldWithObjects = mParcel->getSellWithObjects(); | ||
430 | |||
431 | LLVector3 center = mParcel->getCenterpoint(); | ||
432 | mParcelLocation = llformat("%s %d,%d", | ||
433 | mRegion->getName().c_str(), | ||
434 | (int)center[VX], (int)center[VY] | ||
435 | ); | ||
436 | |||
437 | mParcelSnapshot = mParcel->getSnapshotID(); | ||
438 | |||
439 | updateNames(); | ||
440 | |||
441 | bool haveEnoughCash = mParcelPrice <= mAgentCashBalance; | ||
442 | S32 cashBuy = haveEnoughCash ? 0 : (mParcelPrice - mAgentCashBalance); | ||
443 | mCurrency.setAmount(cashBuy, true); | ||
444 | mCurrency.setZeroMessage(haveEnoughCash ? childGetText("none_needed") : ""); | ||
445 | |||
446 | // checks that we can buy the land | ||
447 | |||
448 | if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED)) | ||
449 | { | ||
450 | mCannotBuyReason = childGetText("cant_buy_for_group"); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | if (!mIsClaim) | ||
455 | { | ||
456 | const LLUUID& authorizedBuyer = mParcel->getAuthorizedBuyerID(); | ||
457 | const LLUUID buyer = gAgent.getID(); | ||
458 | const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer; | ||
459 | |||
460 | if (!mParcelIsForSale | ||
461 | || (mParcelPrice == 0 && authorizedBuyer.isNull())) | ||
462 | { | ||
463 | |||
464 | mCannotBuyReason = childGetText("parcel_not_for_sale"); | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | if (parcelOwner == newOwner) | ||
469 | { | ||
470 | if (mIsForGroup) | ||
471 | { | ||
472 | mCannotBuyReason = childGetText("group_already_owns"); | ||
473 | } | ||
474 | else | ||
475 | { | ||
476 | mCannotBuyReason = childGetText("you_already_own"); | ||
477 | } | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) | ||
482 | { | ||
483 | mCannotBuyReason = childGetText("set_to_sell_to_other"); | ||
484 | return; | ||
485 | } | ||
486 | } | ||
487 | else | ||
488 | { | ||
489 | if (mParcelActualArea == 0) | ||
490 | { | ||
491 | mCannotBuyReason = childGetText("no_public_land"); | ||
492 | return; | ||
493 | } | ||
494 | |||
495 | if (gParcelMgr->hasOthersSelected()) | ||
496 | { | ||
497 | // Policy: Must not have someone else's land selected | ||
498 | mCannotBuyReason = childGetText("not_owned_by_you"); | ||
499 | return; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | /* | ||
504 | if ((mRegion->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) | ||
505 | && !gAgent.isGodlike()) | ||
506 | { | ||
507 | mCannotBuyReason = llformat( | ||
508 | "The region %s does not allow transfer of land.", | ||
509 | mRegion->getName().c_str() ); | ||
510 | return; | ||
511 | } | ||
512 | */ | ||
513 | |||
514 | if (mParcel->getReservedForNewbie()) | ||
515 | { | ||
516 | if (mIsForGroup) | ||
517 | { | ||
518 | mCannotBuyReason = childGetText("first_time_group"); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | if (gStatusBar->getSquareMetersCommitted() > 0) | ||
523 | { | ||
524 | mCannotBuyReason == childGetText("first_time"); | ||
525 | return; | ||
526 | } | ||
527 | |||
528 | // *TODO: There should be a check based on the database value | ||
529 | // indra.user.ever_owned_land, only that value never makes it | ||
530 | // to the viewer, see SL-10728 | ||
531 | } | ||
532 | |||
533 | mCanBuy = true; | ||
534 | } | ||
535 | |||
536 | void LLFloaterBuyLandUI::updateCovenantInfo() | ||
537 | { | ||
538 | LLViewerRegion* region = gParcelMgr->getSelectionRegion(); | ||
539 | if(!region) return; | ||
540 | |||
541 | LLTextBox* region_name = (LLTextBox*)getChildByName("region_name_text"); | ||
542 | if (region_name) | ||
543 | { | ||
544 | region_name->setText(region->getName()); | ||
545 | } | ||
546 | |||
547 | LLTextBox* resellable_clause = (LLTextBox*)getChildByName("resellable_clause"); | ||
548 | if (resellable_clause) | ||
549 | { | ||
550 | if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) | ||
551 | { | ||
552 | resellable_clause->setText(childGetText("can_not_resell")); | ||
553 | } | ||
554 | else | ||
555 | { | ||
556 | resellable_clause->setText(childGetText("can_resell")); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | LLTextBox* changeable_clause = (LLTextBox*)getChildByName("changeable_clause"); | ||
561 | if (changeable_clause) | ||
562 | { | ||
563 | if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) | ||
564 | { | ||
565 | changeable_clause->setText(childGetText("can_change")); | ||
566 | } | ||
567 | else | ||
568 | { | ||
569 | changeable_clause->setText(childGetText("can_not_change")); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)getChildByName("agree_covenant"); | ||
574 | if(check) | ||
575 | { | ||
576 | check->set(false); | ||
577 | check->setEnabled(true); | ||
578 | check->setCallbackUserData(this); | ||
579 | check->setCommitCallback(onChangeAgreeCovenant); | ||
580 | } | ||
581 | |||
582 | LLTextBox* box = (LLTextBox*)getChildByName("covenant_text"); | ||
583 | if(box) | ||
584 | { | ||
585 | box->setVisible(FALSE); | ||
586 | } | ||
587 | |||
588 | // send EstateCovenantInfo message | ||
589 | LLMessageSystem *msg = gMessageSystem; | ||
590 | msg->newMessage("EstateCovenantRequest"); | ||
591 | msg->nextBlockFast(_PREHASH_AgentData); | ||
592 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
593 | msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); | ||
594 | msg->sendReliable(region->getHost()); | ||
595 | } | ||
596 | |||
597 | // static | ||
598 | void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data) | ||
599 | { | ||
600 | LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)user_data; | ||
601 | if(self) | ||
602 | { | ||
603 | self->refreshUI(); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | void LLFloaterBuyLandUI::updateCovenantText(const std::string &string, const LLUUID& asset_id) | ||
608 | { | ||
609 | LLViewerTextEditor* editor = (LLViewerTextEditor*)getChildByName("covenant_editor"); | ||
610 | if (editor) | ||
611 | { | ||
612 | editor->setHandleEditKeysDirectly(FALSE); | ||
613 | editor->setText(string); | ||
614 | |||
615 | LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)getChildByName("agree_covenant"); | ||
616 | LLTextBox* box = (LLTextBox*)getChildByName("covenant_text"); | ||
617 | if(check && box) | ||
618 | { | ||
619 | if (asset_id.isNull()) | ||
620 | { | ||
621 | check->set(true); | ||
622 | check->setEnabled(false); | ||
623 | refreshUI(); | ||
624 | |||
625 | // remove the line stating that you must agree | ||
626 | box->setVisible(FALSE); | ||
627 | } | ||
628 | else | ||
629 | { | ||
630 | check->setEnabled(true); | ||
631 | |||
632 | // remove the line stating that you must agree | ||
633 | box->setVisible(TRUE); | ||
634 | } | ||
635 | } | ||
636 | } | ||
637 | } | ||
638 | |||
639 | void LLFloaterBuyLandUI::updateEstateName(const std::string& name) | ||
640 | { | ||
641 | LLTextBox* box = (LLTextBox*)getChildByName("estate_name_text"); | ||
642 | if (box) box->setText(name); | ||
643 | } | ||
644 | |||
645 | void LLFloaterBuyLandUI::updateLastModified(const std::string& text) | ||
646 | { | ||
647 | LLTextBox* editor = (LLTextBox*)getChildByName("covenant_timestamp_text"); | ||
648 | if (editor) editor->setText(text); | ||
649 | } | ||
650 | |||
651 | void LLFloaterBuyLandUI::updateEstateOwnerName(const std::string& name) | ||
652 | { | ||
653 | LLTextBox* box = (LLTextBox*)getChildByName("estate_owner_text"); | ||
654 | if (box) box->setText(name); | ||
655 | } | ||
656 | |||
657 | void LLFloaterBuyLandUI::updateWebSiteInfo() | ||
658 | { | ||
659 | S32 askBillableArea = mIsForGroup ? 0 : mParcelBillableArea; | ||
660 | S32 askCurrencyBuy = mCurrency.getAmount(); | ||
661 | |||
662 | if (mTransaction && mTransactionType == TransactionPreflight | ||
663 | && mPreflightAskBillableArea == askBillableArea | ||
664 | && mPreflightAskCurrencyBuy == askCurrencyBuy) | ||
665 | { | ||
666 | return; | ||
667 | } | ||
668 | |||
669 | mPreflightAskBillableArea = askBillableArea; | ||
670 | mPreflightAskCurrencyBuy = askCurrencyBuy; | ||
671 | |||
672 | #if 0 | ||
673 | // enable this code if you want the details to blank while we're talking | ||
674 | // to the web site... it's kind of jarring | ||
675 | mSiteValid = false; | ||
676 | mSiteMembershipUpgrade = false; | ||
677 | mSiteMembershipAction = "(waiting)"; | ||
678 | mSiteMembershipPlanIDs.clear(); | ||
679 | mSiteMembershipPlanNames.clear(); | ||
680 | mSiteLandUseUpgrade = false; | ||
681 | mSiteLandUseAction = "(waiting)"; | ||
682 | mSiteCurrencyEstimated = false; | ||
683 | mSiteCurrencyEstimatedCost = 0; | ||
684 | #endif | ||
685 | |||
686 | LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); | ||
687 | keywordArgs.appendString("agentId", gAgent.getID().getString()); | ||
688 | keywordArgs.appendString("secureSessionId", | ||
689 | gAgent.getSecureSessionID().getString()); | ||
690 | keywordArgs.appendInt("billableArea", mPreflightAskBillableArea); | ||
691 | keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy); | ||
692 | |||
693 | LLXMLRPCValue params = LLXMLRPCValue::createArray(); | ||
694 | params.append(keywordArgs); | ||
695 | |||
696 | startTransaction(TransactionPreflight, params); | ||
697 | } | ||
698 | |||
699 | void LLFloaterBuyLandUI::finishWebSiteInfo() | ||
700 | { | ||
701 | |||
702 | LLXMLRPCValue result = mTransaction->responseValue(); | ||
703 | |||
704 | mSiteValid = result["success"].asBool(); | ||
705 | if (!mSiteValid) | ||
706 | { | ||
707 | tellUserError( | ||
708 | result["errorMessage"].asString(), | ||
709 | result["errorURI"].asString() | ||
710 | ); | ||
711 | return; | ||
712 | } | ||
713 | |||
714 | LLXMLRPCValue membership = result["membership"]; | ||
715 | mSiteMembershipUpgrade = membership["upgrade"].asBool(); | ||
716 | mSiteMembershipAction = membership["action"].asString(); | ||
717 | mSiteMembershipPlanIDs.clear(); | ||
718 | mSiteMembershipPlanNames.clear(); | ||
719 | LLXMLRPCValue levels = membership["levels"]; | ||
720 | for (LLXMLRPCValue level = levels.rewind(); | ||
721 | level.isValid(); | ||
722 | level = levels.next()) | ||
723 | { | ||
724 | mSiteMembershipPlanIDs.push_back(level["id"].asString()); | ||
725 | mSiteMembershipPlanNames.push_back(level["description"].asString()); | ||
726 | } | ||
727 | mUserPlanChoice = 0; | ||
728 | |||
729 | LLXMLRPCValue landUse = result["landUse"]; | ||
730 | mSiteLandUseUpgrade = landUse["upgrade"].asBool(); | ||
731 | mSiteLandUseAction = landUse["action"].asString(); | ||
732 | |||
733 | LLXMLRPCValue currency = result["currency"]; | ||
734 | mCurrency.setEstimate(currency["estimatedCost"].asInt()); | ||
735 | |||
736 | mSiteConfirm = result["confirm"].asString(); | ||
737 | } | ||
738 | |||
739 | void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password) | ||
740 | { | ||
741 | if (!mCanBuy) | ||
742 | { | ||
743 | return; | ||
744 | } | ||
745 | |||
746 | BOOL remove_contribution = childGetValue("remove_contribution").asBoolean(); | ||
747 | mParcelBuyInfo = gParcelMgr->setupParcelBuy(gAgent.getID(), gAgent.getSessionID(), | ||
748 | gAgent.getGroupID(), mIsForGroup, mIsClaim, remove_contribution); | ||
749 | |||
750 | if (mParcelBuyInfo | ||
751 | && !mSiteMembershipUpgrade | ||
752 | && !mSiteLandUseUpgrade | ||
753 | && mCurrency.getAmount() == 0 | ||
754 | && mSiteConfirm != "password") | ||
755 | { | ||
756 | sendBuyLand(); | ||
757 | return; | ||
758 | } | ||
759 | |||
760 | |||
761 | std::string newLevel = "noChange"; | ||
762 | |||
763 | if (mSiteMembershipUpgrade) | ||
764 | { | ||
765 | LLComboBox* levels = LLUICtrlFactory::getComboBoxByName(this, "account_level"); | ||
766 | if (levels) | ||
767 | { | ||
768 | mUserPlanChoice = levels->getCurrentIndex(); | ||
769 | newLevel = mSiteMembershipPlanIDs[mUserPlanChoice]; | ||
770 | } | ||
771 | } | ||
772 | |||
773 | LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); | ||
774 | keywordArgs.appendString("agentId", gAgent.getID().getString()); | ||
775 | keywordArgs.appendString("secureSessionId", | ||
776 | gAgent.getSecureSessionID().getString()); | ||
777 | keywordArgs.appendString("levelId", newLevel); | ||
778 | keywordArgs.appendInt("billableArea", | ||
779 | mIsForGroup ? 0 : mParcelBillableArea); | ||
780 | keywordArgs.appendInt("currencyBuy", mCurrency.getAmount()); | ||
781 | keywordArgs.appendInt("estimatedCost", mCurrency.getEstimate()); | ||
782 | keywordArgs.appendString("confirm", mSiteConfirm); | ||
783 | if (!password.empty()) | ||
784 | { | ||
785 | keywordArgs.appendString("password", password); | ||
786 | } | ||
787 | |||
788 | LLXMLRPCValue params = LLXMLRPCValue::createArray(); | ||
789 | params.append(keywordArgs); | ||
790 | |||
791 | startTransaction(TransactionBuy, params); | ||
792 | } | ||
793 | |||
794 | void LLFloaterBuyLandUI::finishWebSitePrep() | ||
795 | { | ||
796 | LLXMLRPCValue result = mTransaction->responseValue(); | ||
797 | |||
798 | bool success = result["success"].asBool(); | ||
799 | if (!success) | ||
800 | { | ||
801 | tellUserError( | ||
802 | result["errorMessage"].asString(), | ||
803 | result["errorURI"].asString() | ||
804 | ); | ||
805 | return; | ||
806 | } | ||
807 | |||
808 | sendBuyLand(); | ||
809 | } | ||
810 | |||
811 | void LLFloaterBuyLandUI::sendBuyLand() | ||
812 | { | ||
813 | if (mParcelBuyInfo) | ||
814 | { | ||
815 | gParcelMgr->sendParcelBuy(mParcelBuyInfo); | ||
816 | gParcelMgr->deleteParcelBuy(mParcelBuyInfo); | ||
817 | mBought = true; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | void LLFloaterBuyLandUI::updateNames() | ||
822 | { | ||
823 | if (!mParcelValid) | ||
824 | { | ||
825 | mParcelSellerName = ""; | ||
826 | return; | ||
827 | } | ||
828 | |||
829 | if (mIsClaim) | ||
830 | { | ||
831 | mParcelSellerName = "Linden Lab"; | ||
832 | } | ||
833 | else if (mParcel->getIsGroupOwned()) | ||
834 | { | ||
835 | char groupName[DB_LAST_NAME_BUF_SIZE]; | ||
836 | |||
837 | gCacheName->getGroupName(mParcel->getGroupID(), &groupName[0]); | ||
838 | mParcelSellerName = groupName; | ||
839 | } | ||
840 | else | ||
841 | { | ||
842 | char firstName[DB_LAST_NAME_BUF_SIZE]; | ||
843 | char lastName[DB_LAST_NAME_BUF_SIZE]; | ||
844 | |||
845 | gCacheName->getName(mParcel->getOwnerID(), firstName, lastName); | ||
846 | mParcelSellerName = llformat("%s %s", firstName, lastName); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | |||
851 | void LLFloaterBuyLandUI::startTransaction(TransactionType type, | ||
852 | LLXMLRPCValue params) | ||
853 | { | ||
854 | delete mTransaction; | ||
855 | mTransaction = NULL; | ||
856 | |||
857 | mTransactionType = type; | ||
858 | |||
859 | // Select a URI and method appropriate for the transaction type. | ||
860 | static std::string transaction_uri; | ||
861 | if (transaction_uri.empty()) | ||
862 | { | ||
863 | transaction_uri = getHelperURI() + "landtool.php"; | ||
864 | } | ||
865 | |||
866 | const char* method; | ||
867 | switch (mTransactionType) | ||
868 | { | ||
869 | case TransactionPreflight: | ||
870 | method = "preflightBuyLandPrep"; | ||
871 | break; | ||
872 | case TransactionBuy: | ||
873 | method = "buyLandPrep"; | ||
874 | break; | ||
875 | default: | ||
876 | llwarns << "LLFloaterBuyLandUI: Unknown transaction type!" << llendl; | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | mTransaction = new LLXMLRPCTransaction( | ||
881 | transaction_uri, | ||
882 | method, | ||
883 | params, | ||
884 | false /* don't use gzip */ | ||
885 | ); | ||
886 | } | ||
887 | |||
888 | bool LLFloaterBuyLandUI::checkTransaction() | ||
889 | { | ||
890 | if (!mTransaction) | ||
891 | { | ||
892 | return false; | ||
893 | } | ||
894 | |||
895 | if (!mTransaction->process()) | ||
896 | { | ||
897 | return false; | ||
898 | } | ||
899 | |||
900 | if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete) | ||
901 | { | ||
902 | tellUserError(mTransaction->statusMessage(), mTransaction->statusURI()); | ||
903 | } | ||
904 | else { | ||
905 | switch (mTransactionType) | ||
906 | { | ||
907 | case TransactionPreflight: finishWebSiteInfo(); break; | ||
908 | case TransactionBuy: finishWebSitePrep(); break; | ||
909 | default: ; | ||
910 | } | ||
911 | } | ||
912 | |||
913 | delete mTransaction; | ||
914 | mTransaction = NULL; | ||
915 | |||
916 | return true; | ||
917 | } | ||
918 | |||
919 | void LLFloaterBuyLandUI::tellUserError( | ||
920 | const std::string& message, const std::string& uri) | ||
921 | { | ||
922 | mCanBuy = false; | ||
923 | mCannotBuyIsError = true; | ||
924 | mCannotBuyReason = childGetText("fetching_error"); | ||
925 | mCannotBuyReason += message; | ||
926 | mCannotBuyURI = uri; | ||
927 | } | ||
928 | |||
929 | |||
930 | // virtual | ||
931 | BOOL LLFloaterBuyLandUI::postBuild() | ||
932 | { | ||
933 | mCurrency.prepare(); | ||
934 | |||
935 | childSetAction("buy_btn", onClickBuy, this); | ||
936 | childSetAction("cancel_btn", onClickCancel, this); | ||
937 | childSetAction("error_web", onClickErrorWeb, this); | ||
938 | |||
939 | return TRUE; | ||
940 | } | ||
941 | |||
942 | void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel) | ||
943 | { | ||
944 | if (mTransaction && mTransactionType == TransactionBuy) | ||
945 | { | ||
946 | // the user is buying, don't change the selection | ||
947 | return; | ||
948 | } | ||
949 | |||
950 | mRegion = region; | ||
951 | mParcel = parcel; | ||
952 | |||
953 | updateAgentInfo(); | ||
954 | updateParcelInfo(); | ||
955 | updateCovenantInfo(); | ||
956 | if (mCanBuy) | ||
957 | { | ||
958 | updateWebSiteInfo(); | ||
959 | } | ||
960 | refreshUI(); | ||
961 | } | ||
962 | |||
963 | void LLFloaterBuyLandUI::setForGroup(bool forGroup) | ||
964 | { | ||
965 | mIsForGroup = forGroup; | ||
966 | } | ||
967 | |||
968 | void LLFloaterBuyLandUI::draw() | ||
969 | { | ||
970 | LLFloater::draw(); | ||
971 | |||
972 | bool needsUpdate = false; | ||
973 | needsUpdate |= checkTransaction(); | ||
974 | needsUpdate |= mCurrency.process(); | ||
975 | |||
976 | if (mBought) | ||
977 | { | ||
978 | close(); | ||
979 | } | ||
980 | else if (needsUpdate) | ||
981 | { | ||
982 | if (mCanBuy && mCurrency.hasError()) | ||
983 | { | ||
984 | tellUserError(mCurrency.errorMessage(), mCurrency.errorURI()); | ||
985 | } | ||
986 | |||
987 | refreshUI(); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | BOOL LLFloaterBuyLandUI::canClose() | ||
992 | { | ||
993 | return (mTransaction ? FALSE : TRUE) && mCurrency.canCancel(); | ||
994 | } | ||
995 | |||
996 | void LLFloaterBuyLandUI::onClose(bool app_quitting) | ||
997 | { | ||
998 | LLFloater::onClose(app_quitting); | ||
999 | delete this; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | void LLFloaterBuyLandUI::refreshUI() | ||
1004 | { | ||
1005 | // section zero: title area | ||
1006 | { | ||
1007 | LLTextureCtrl* snapshot = LLViewerUICtrlFactory::getTexturePickerByName(this, "info_image"); | ||
1008 | if (snapshot) | ||
1009 | { | ||
1010 | snapshot->setImageAssetID( | ||
1011 | mParcelValid ? mParcelSnapshot : LLUUID::null); | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | |||
1016 | if (mParcelValid) | ||
1017 | { | ||
1018 | childSetText("info_parcel", mParcelLocation); | ||
1019 | |||
1020 | |||
1021 | childSetTextArg("meters_supports_object", "[AMOUNT]", llformat("%d", mParcelActualArea)); | ||
1022 | childSetTextArg("meters_supports_object", "[AMOUNT2]", llformat("%d", mParcelSupportedObjects)); | ||
1023 | |||
1024 | childSetText("info_size", childGetText("meters_supports_object")); | ||
1025 | |||
1026 | |||
1027 | childSetText("info_price", | ||
1028 | llformat( | ||
1029 | "L$ %d%s", | ||
1030 | mParcelPrice, | ||
1031 | mParcelSoldWithObjects | ||
1032 | ? "\nsold with objects" | ||
1033 | : "")); | ||
1034 | childSetVisible("info_price", mParcelIsForSale); | ||
1035 | } | ||
1036 | else | ||
1037 | { | ||
1038 | childSetText("info_parcel", "(no parcel selected)"); | ||
1039 | childSetText("info_size", ""); | ||
1040 | childSetText("info_price", ""); | ||
1041 | } | ||
1042 | |||
1043 | childSetText("info_action", | ||
1044 | mCanBuy | ||
1045 | ? | ||
1046 | mIsForGroup | ||
1047 | ? childGetText("buying_for_group")//"Buying land for group:" | ||
1048 | : childGetText("buying_will")//"Buying this land will:" | ||
1049 | : | ||
1050 | mCannotBuyIsError | ||
1051 | ? childGetText("cannot_buy_now")//"Cannot buy now:" | ||
1052 | : childGetText("not_for_sale")//"Not for sale:" | ||
1053 | |||
1054 | ); | ||
1055 | } | ||
1056 | |||
1057 | bool showingError = !mCanBuy || !mSiteValid; | ||
1058 | |||
1059 | // error section | ||
1060 | if (showingError) | ||
1061 | { | ||
1062 | mChildren.setBadge("step_error", | ||
1063 | mCannotBuyIsError | ||
1064 | ? LLViewChildren::BADGE_ERROR | ||
1065 | : LLViewChildren::BADGE_WARN); | ||
1066 | |||
1067 | LLTextBox* message = LLUICtrlFactory::getTextBoxByName(this, "error_message"); | ||
1068 | if (message) | ||
1069 | { | ||
1070 | message->setVisible(true); | ||
1071 | message->setWrappedText( | ||
1072 | !mCanBuy ? mCannotBuyReason : "(waiting for data)" | ||
1073 | ); | ||
1074 | } | ||
1075 | |||
1076 | childSetVisible("error_web", | ||
1077 | mCannotBuyIsError && !mCannotBuyURI.empty()); | ||
1078 | } | ||
1079 | else | ||
1080 | { | ||
1081 | childHide("step_error"); | ||
1082 | childHide("error_message"); | ||
1083 | childHide("error_web"); | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | // section one: account | ||
1088 | if (!showingError) | ||
1089 | { | ||
1090 | mChildren.setBadge("step_1", | ||
1091 | mSiteMembershipUpgrade | ||
1092 | ? LLViewChildren::BADGE_NOTE | ||
1093 | : LLViewChildren::BADGE_OK); | ||
1094 | childSetText("account_action", mSiteMembershipAction); | ||
1095 | childSetText("account_reason", | ||
1096 | mSiteMembershipUpgrade | ||
1097 | ? childGetText("must_upgrade") | ||
1098 | : childGetText("cant_own_land") | ||
1099 | ); | ||
1100 | |||
1101 | LLComboBox* levels = LLUICtrlFactory::getComboBoxByName(this, "account_level"); | ||
1102 | if (levels) | ||
1103 | { | ||
1104 | levels->setVisible(mSiteMembershipUpgrade); | ||
1105 | |||
1106 | levels->removeall(); | ||
1107 | for(std::vector<std::string>::const_iterator i | ||
1108 | = mSiteMembershipPlanNames.begin(); | ||
1109 | i != mSiteMembershipPlanNames.end(); | ||
1110 | ++i) | ||
1111 | { | ||
1112 | levels->add(*i); | ||
1113 | } | ||
1114 | |||
1115 | levels->setCurrentByIndex(mUserPlanChoice); | ||
1116 | } | ||
1117 | |||
1118 | childShow("step_1"); | ||
1119 | childShow("account_action"); | ||
1120 | childShow("account_reason"); | ||
1121 | } | ||
1122 | else | ||
1123 | { | ||
1124 | childHide("step_1"); | ||
1125 | childHide("account_action"); | ||
1126 | childHide("account_reason"); | ||
1127 | childHide("account_level"); | ||
1128 | } | ||
1129 | |||
1130 | // section two: land use fees | ||
1131 | if (!showingError) | ||
1132 | { | ||
1133 | mChildren.setBadge("step_2", | ||
1134 | mSiteLandUseUpgrade | ||
1135 | ? LLViewChildren::BADGE_NOTE | ||
1136 | : LLViewChildren::BADGE_OK); | ||
1137 | childSetText("land_use_action", mSiteLandUseAction); | ||
1138 | |||
1139 | std::string message; | ||
1140 | |||
1141 | if (mIsForGroup) | ||
1142 | { | ||
1143 | childSetTextArg("insufficient_land_credits", "[GROUP]", gAgent.mGroupName); | ||
1144 | |||
1145 | |||
1146 | message += childGetText("insufficient_land_credits"); | ||
1147 | |||
1148 | } | ||
1149 | else if (mAgentHasNeverOwnedLand) | ||
1150 | { | ||
1151 | if (mParcelIsFirstLand) | ||
1152 | { | ||
1153 | message += childGetText("first_purchase"); | ||
1154 | } | ||
1155 | else | ||
1156 | { | ||
1157 | message += childGetText("first_time_but_not_first_land"); | ||
1158 | } | ||
1159 | } | ||
1160 | else | ||
1161 | { | ||
1162 | |||
1163 | childSetTextArg("land_holdings", "[BUYER]", llformat("%d", mAgentCommittedTier)); | ||
1164 | message += childGetText("land_holdings"); | ||
1165 | |||
1166 | } | ||
1167 | |||
1168 | if (!mParcelValid) | ||
1169 | { | ||
1170 | message += "(no parcel selected)"; | ||
1171 | } | ||
1172 | else if (mParcelBillableArea == mParcelActualArea) | ||
1173 | { | ||
1174 | childSetTextArg("parcel_meters", "[AMOUNT]", llformat("%d", mParcelActualArea)); | ||
1175 | message += childGetText("parcel_meters"); | ||
1176 | } | ||
1177 | else | ||
1178 | { | ||
1179 | |||
1180 | if (mParcelBillableArea > mParcelActualArea) | ||
1181 | { | ||
1182 | childSetTextArg("premium_land", "[AMOUNT]", llformat("%d", mParcelBillableArea) ); | ||
1183 | message += childGetText("premium_land"); | ||
1184 | } | ||
1185 | else | ||
1186 | { | ||
1187 | childSetTextArg("discounted_land", "[AMOUNT]", llformat("%d", mParcelBillableArea) ); | ||
1188 | message += childGetText("discounted_land"); | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | childSetWrappedText("land_use_reason", message); | ||
1193 | |||
1194 | childShow("step_2"); | ||
1195 | childShow("land_use_action"); | ||
1196 | childShow("land_use_reason"); | ||
1197 | } | ||
1198 | else | ||
1199 | { | ||
1200 | childHide("step_2"); | ||
1201 | childHide("land_use_action"); | ||
1202 | childHide("land_use_reason"); | ||
1203 | } | ||
1204 | |||
1205 | // section three: purchase & currency | ||
1206 | S32 finalBalance = mAgentCashBalance + mCurrency.getAmount() - mParcelPrice; | ||
1207 | bool willHaveEnough = finalBalance >= 0; | ||
1208 | bool haveEnough = mAgentCashBalance >= mParcelPrice; | ||
1209 | S32 minContribution = llceil((F32)mParcelBillableArea / GROUP_LAND_BONUS_FACTOR); | ||
1210 | bool groupContributionEnough = mParcelGroupContribution >= minContribution; | ||
1211 | |||
1212 | mCurrency.updateUI(!showingError && !haveEnough); | ||
1213 | |||
1214 | if (!showingError) | ||
1215 | { | ||
1216 | mChildren.setBadge("step_3", | ||
1217 | !willHaveEnough | ||
1218 | ? LLViewChildren::BADGE_WARN | ||
1219 | : mCurrency.getAmount() > 0 | ||
1220 | ? LLViewChildren::BADGE_NOTE | ||
1221 | : LLViewChildren::BADGE_OK); | ||
1222 | |||
1223 | childSetText("purchase_action", | ||
1224 | llformat( | ||
1225 | "Pay L$ %d to %s for this land", | ||
1226 | mParcelPrice, | ||
1227 | mParcelSellerName.c_str() | ||
1228 | )); | ||
1229 | childSetVisible("purchase_action", mParcelValid); | ||
1230 | |||
1231 | std::string reasonString; | ||
1232 | |||
1233 | if (haveEnough) | ||
1234 | { | ||
1235 | |||
1236 | childSetTextArg("have_enough_lindens", "[AMOUNT]", llformat("%d", mAgentCashBalance)); | ||
1237 | childSetText("currency_reason", childGetText("have_enough_lindens")); | ||
1238 | } | ||
1239 | else | ||
1240 | { | ||
1241 | childSetTextArg("not_enough_lindens", "[AMOUNT]", llformat("%d", mAgentCashBalance)); | ||
1242 | childSetTextArg("not_enough_lindens", "[AMOUNT2]", llformat("%d", mParcelPrice - mAgentCashBalance)); | ||
1243 | |||
1244 | childSetText("currency_reason", childGetText("not_enough_lindens")); | ||
1245 | |||
1246 | childSetTextArg("currency_est", "[AMOUNT2]", llformat("%#.2f", mCurrency.getEstimate() / 100.0)); | ||
1247 | |||
1248 | } | ||
1249 | |||
1250 | if (willHaveEnough) | ||
1251 | { | ||
1252 | |||
1253 | childSetTextArg("balance_left", "[AMOUNT]", llformat("%d", finalBalance)); | ||
1254 | |||
1255 | childSetText("currency_balance", childGetText("balance_left")); | ||
1256 | |||
1257 | } | ||
1258 | else | ||
1259 | { | ||
1260 | |||
1261 | childSetTextArg("balance_needed", "[AMOUNT]", llformat("%d", mParcelPrice - mAgentCashBalance)); | ||
1262 | |||
1263 | childSetText("currency_balance", childGetText("balance_needed")); | ||
1264 | |||
1265 | } | ||
1266 | |||
1267 | //remove_contribution not in XML - ?! | ||
1268 | childSetValue("remove_contribution", LLSD(groupContributionEnough)); | ||
1269 | childSetEnabled("remove_contribution", groupContributionEnough); | ||
1270 | bool showRemoveContribution = mParcelIsGroupLand | ||
1271 | && (mParcelGroupContribution > 0); | ||
1272 | childSetText("remove_contribution", | ||
1273 | llformat("Remove %d square meters of contribution from group", | ||
1274 | minContribution)); | ||
1275 | childSetVisible("remove_contribution", showRemoveContribution); | ||
1276 | |||
1277 | childShow("step_3"); | ||
1278 | childShow("purchase_action"); | ||
1279 | childShow("currency_reason"); | ||
1280 | childShow("currency_balance"); | ||
1281 | } | ||
1282 | else | ||
1283 | { | ||
1284 | childHide("step_3"); | ||
1285 | childHide("purchase_action"); | ||
1286 | childHide("currency_reason"); | ||
1287 | childHide("currency_balance"); | ||
1288 | childHide("remove_group_donation"); | ||
1289 | } | ||
1290 | |||
1291 | |||
1292 | bool agrees_to_covenant = false; | ||
1293 | LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)getChildByName("agree_covenant"); | ||
1294 | if (check) | ||
1295 | { | ||
1296 | agrees_to_covenant = check->get(); | ||
1297 | } | ||
1298 | |||
1299 | childSetEnabled("buy_btn", | ||
1300 | mCanBuy && mSiteValid && willHaveEnough && !mTransaction && agrees_to_covenant); | ||
1301 | } | ||
1302 | |||
1303 | void LLFloaterBuyLandUI::startBuyPreConfirm() | ||
1304 | { | ||
1305 | std::string action; | ||
1306 | |||
1307 | if (mSiteMembershipUpgrade) | ||
1308 | { | ||
1309 | action += mSiteMembershipAction; | ||
1310 | action += "\n"; | ||
1311 | |||
1312 | LLComboBox* levels = LLUICtrlFactory::getComboBoxByName(this, "account_level"); | ||
1313 | if (levels) | ||
1314 | { | ||
1315 | action += " * "; | ||
1316 | action += mSiteMembershipPlanNames[levels->getCurrentIndex()]; | ||
1317 | action += "\n"; | ||
1318 | } | ||
1319 | } | ||
1320 | if (mSiteLandUseUpgrade) | ||
1321 | { | ||
1322 | action += mSiteLandUseAction; | ||
1323 | action += "\n"; | ||
1324 | } | ||
1325 | if (mCurrency.getAmount() > 0) | ||
1326 | { | ||
1327 | |||
1328 | childSetTextArg("buy_for_US", "[AMOUNT]", llformat("%d", mCurrency.getAmount())); | ||
1329 | childSetTextArg("buy_for_US", "[AMOUNT2]", llformat("%#.2f", mCurrency.getEstimate() / 100.0)); | ||
1330 | |||
1331 | action += childGetText("buy_for_US"); | ||
1332 | } | ||
1333 | |||
1334 | childSetTextArg("pay_to_for_land", "[AMOUNT]", llformat("%d", mParcelPrice)); | ||
1335 | childSetTextArg("pay_to_for_land", "[SELLER]", mParcelSellerName.c_str()); | ||
1336 | |||
1337 | action += childGetText("pay_to_for_land"); | ||
1338 | |||
1339 | |||
1340 | LLConfirmationManager::confirm(mSiteConfirm, | ||
1341 | action, | ||
1342 | *this, | ||
1343 | &LLFloaterBuyLandUI::startBuyPostConfirm); | ||
1344 | } | ||
1345 | |||
1346 | void LLFloaterBuyLandUI::startBuyPostConfirm(const std::string& password) | ||
1347 | { | ||
1348 | runWebSitePrep(password); | ||
1349 | |||
1350 | mCanBuy = false; | ||
1351 | mCannotBuyReason = childGetText("processing"); | ||
1352 | refreshUI(); | ||
1353 | } | ||
1354 | |||
1355 | |||
1356 | // static | ||
1357 | void LLFloaterBuyLandUI::onClickBuy(void* data) | ||
1358 | { | ||
1359 | LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data; | ||
1360 | self->startBuyPreConfirm(); | ||
1361 | } | ||
1362 | |||
1363 | // static | ||
1364 | void LLFloaterBuyLandUI::onClickCancel(void* data) | ||
1365 | { | ||
1366 | LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data; | ||
1367 | self->close(); | ||
1368 | } | ||
1369 | |||
1370 | // static | ||
1371 | void LLFloaterBuyLandUI::onClickErrorWeb(void* data) | ||
1372 | { | ||
1373 | LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data; | ||
1374 | LLWeb::loadURLExternal(self->mCannotBuyURI); | ||
1375 | self->close(); | ||
1376 | } | ||
1377 | |||