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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llcurrencyuimanager.cpp
  3.  * @brief LLCurrencyUIManager class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2006-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 "lluictrlfactory.h"
  34. #include "lltextbox.h"
  35. #include "lllineeditor.h"
  36. #include "llviewercontrol.h"
  37. #include "llversioninfo.h"
  38. #include "llcurrencyuimanager.h"
  39. // viewer includes
  40. #include "llagent.h"
  41. #include "llconfirmationmanager.h"
  42. #include "llframetimer.h"
  43. #include "lllineeditor.h"
  44. #include "llviewchildren.h"
  45. #include "llxmlrpctransaction.h"
  46. #include "llviewernetwork.h"
  47. #include "llpanel.h"
  48. const F64 CURRENCY_ESTIMATE_FREQUENCY = 2.0;
  49. // how long of a pause in typing a currency buy amount before an
  50. // esimate is fetched from the server
  51. class LLCurrencyUIManager::Impl
  52. {
  53. public:
  54. Impl(LLPanel& dialog);
  55. virtual ~Impl();
  56. LLPanel& mPanel;
  57. bool mHidden;
  58. bool mError;
  59. std::string mErrorMessage;
  60. std::string mErrorURI;
  61. std::string mZeroMessage;
  62. // user's choices
  63. S32 mUserCurrencyBuy;
  64. bool mUserEnteredCurrencyBuy;
  65. // from website
  66. // pre-viewer 2.0, the server returned estimates as an
  67. // integer US cents value, e.g., "1000" for $10.00
  68. // post-viewer 2.0, the server may also return estimates
  69. // as a string with currency embedded, e.g., "10.00 Euros"
  70. bool mUSDCurrencyEstimated;
  71. S32 mUSDCurrencyEstimatedCost;
  72. bool mLocalCurrencyEstimated;
  73. std::string mLocalCurrencyEstimatedCost;
  74. bool mSupportsInternationalBilling;
  75. std::string mSiteConfirm;
  76. bool mBought;
  77. enum TransactionType
  78. {
  79. TransactionNone,
  80. TransactionCurrency,
  81. TransactionBuy
  82. };
  83. TransactionType  mTransactionType;
  84. LLXMLRPCTransaction* mTransaction;
  85. bool  mCurrencyChanged;
  86. LLFrameTimer mCurrencyKeyTimer;
  87. void updateCurrencyInfo();
  88. void finishCurrencyInfo();
  89. void startCurrencyBuy(const std::string& password);
  90. void finishCurrencyBuy();
  91. void clearEstimate();
  92. bool hasEstimate() const;
  93. std::string getLocalEstimate() const;
  94. void startTransaction(TransactionType type,
  95. const char* method, LLXMLRPCValue params);
  96. bool checkTransaction();
  97. // return true if update needed
  98. void setError(const std::string& message, const std::string& uri);
  99. void clearError();
  100. bool considerUpdateCurrency();
  101. // return true if update needed
  102. void currencyKey(S32);
  103. static void onCurrencyKey(LLLineEditor* caller, void* data);
  104. void prepare();
  105. void updateUI();
  106. };
  107. // is potentially not fully constructed.
  108. LLCurrencyUIManager::Impl::Impl(LLPanel& dialog)
  109. : mPanel(dialog),
  110. mHidden(false),
  111. mError(false),
  112. mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp
  113. mUserEnteredCurrencyBuy(false),
  114. mSupportsInternationalBilling(false),
  115. mBought(false),
  116. mTransactionType(TransactionNone), mTransaction(0),
  117. mCurrencyChanged(false)
  118. {
  119. clearEstimate();
  120. }
  121. LLCurrencyUIManager::Impl::~Impl()
  122. {
  123. delete mTransaction;
  124. }
  125. void LLCurrencyUIManager::Impl::updateCurrencyInfo()
  126. {
  127. clearEstimate();
  128. mBought = false;
  129. mCurrencyChanged = false;
  130. if (mUserCurrencyBuy == 0)
  131. {
  132. mLocalCurrencyEstimated = true;
  133. return;
  134. }
  135. LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
  136. keywordArgs.appendString("agentId", gAgent.getID().asString());
  137. keywordArgs.appendString(
  138. "secureSessionId",
  139. gAgent.getSecureSessionID().asString());
  140. keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
  141. keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
  142. keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
  143. keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
  144. keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
  145. keywordArgs.appendInt("viewerBuildVersion", LLVersionInfo::getBuild());
  146. LLXMLRPCValue params = LLXMLRPCValue::createArray();
  147. params.append(keywordArgs);
  148. startTransaction(TransactionCurrency, "getCurrencyQuote", params);
  149. }
  150. void LLCurrencyUIManager::Impl::finishCurrencyInfo()
  151. {
  152. LLXMLRPCValue result = mTransaction->responseValue();
  153. bool success = result["success"].asBool();
  154. if (!success)
  155. {
  156. setError(
  157. result["errorMessage"].asString(),
  158. result["errorURI"].asString()
  159. );
  160. return;
  161. }
  162. LLXMLRPCValue currency = result["currency"];
  163. // old XML-RPC server: estimatedCost = value in US cents
  164. mUSDCurrencyEstimated = currency["estimatedCost"].isValid();
  165. if (mUSDCurrencyEstimated)
  166. {
  167. mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInt();
  168. }
  169. // newer XML-RPC server: estimatedLocalCost = local currency string
  170. mLocalCurrencyEstimated = currency["estimatedLocalCost"].isValid();
  171. if (mLocalCurrencyEstimated)
  172. {
  173. mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString();
  174. mSupportsInternationalBilling = true;
  175. }
  176. S32 newCurrencyBuy = currency["currencyBuy"].asInt();
  177. if (newCurrencyBuy != mUserCurrencyBuy)
  178. {
  179. mUserCurrencyBuy = newCurrencyBuy;
  180. mUserEnteredCurrencyBuy = false;
  181. }
  182. mSiteConfirm = result["confirm"].asString();
  183. }
  184. void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
  185. {
  186. LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
  187. keywordArgs.appendString("agentId", gAgent.getID().asString());
  188. keywordArgs.appendString(
  189. "secureSessionId",
  190. gAgent.getSecureSessionID().asString());
  191. keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
  192. if (mUSDCurrencyEstimated)
  193. {
  194. keywordArgs.appendInt("estimatedCost", mUSDCurrencyEstimatedCost);
  195. }
  196. if (mLocalCurrencyEstimated)
  197. {
  198. keywordArgs.appendString("estimatedLocalCost", mLocalCurrencyEstimatedCost);
  199. }
  200. keywordArgs.appendString("confirm", mSiteConfirm);
  201. if (!password.empty())
  202. {
  203. keywordArgs.appendString("password", password);
  204. }
  205. keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
  206. keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
  207. keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
  208. keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
  209. keywordArgs.appendInt("viewerBuildVersion", LLVersionInfo::getBuild());
  210. LLXMLRPCValue params = LLXMLRPCValue::createArray();
  211. params.append(keywordArgs);
  212. startTransaction(TransactionBuy, "buyCurrency", params);
  213. clearEstimate();
  214. mCurrencyChanged = false;
  215. }
  216. void LLCurrencyUIManager::Impl::finishCurrencyBuy()
  217. {
  218. LLXMLRPCValue result = mTransaction->responseValue();
  219. bool success = result["success"].asBool();
  220. if (!success)
  221. {
  222. setError(
  223. result["errorMessage"].asString(),
  224. result["errorURI"].asString()
  225. );
  226. }
  227. else
  228. {
  229. mUserCurrencyBuy = 0;
  230. mUserEnteredCurrencyBuy = false;
  231. mBought = true;
  232. }
  233. }
  234. void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
  235. const char* method, LLXMLRPCValue params)
  236. {
  237. static std::string transactionURI;
  238. if (transactionURI.empty())
  239. {
  240. transactionURI = LLViewerLogin::getInstance()->getHelperURI() + "currency.php";
  241. }
  242. delete mTransaction;
  243. mTransactionType = type;
  244. mTransaction = new LLXMLRPCTransaction(
  245. transactionURI,
  246. method,
  247. params,
  248. false /* don't use gzip */
  249. );
  250. clearError();
  251. }
  252. void LLCurrencyUIManager::Impl::clearEstimate()
  253. {
  254. mUSDCurrencyEstimated = false;
  255. mUSDCurrencyEstimatedCost = 0;
  256. mLocalCurrencyEstimated = false;
  257. mLocalCurrencyEstimatedCost = "0";
  258. }
  259. bool LLCurrencyUIManager::Impl::hasEstimate() const
  260. {
  261. return (mUSDCurrencyEstimated || mLocalCurrencyEstimated);
  262. }
  263. std::string LLCurrencyUIManager::Impl::getLocalEstimate() const
  264. {
  265. if (mLocalCurrencyEstimated)
  266. {
  267. // we have the new-style local currency string
  268. return mLocalCurrencyEstimatedCost;
  269. }
  270. if (mUSDCurrencyEstimated)
  271. {
  272. // we have the old-style USD-specific value
  273. return "US$ " + llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0);
  274. }
  275. return "";
  276. }
  277. bool LLCurrencyUIManager::Impl::checkTransaction()
  278. {
  279. if (!mTransaction)
  280. {
  281. return false;
  282. }
  283. if (!mTransaction->process())
  284. {
  285. return false;
  286. }
  287. if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
  288. {
  289. setError(mTransaction->statusMessage(), mTransaction->statusURI());
  290. }
  291. else {
  292. switch (mTransactionType)
  293. {
  294. case TransactionCurrency: finishCurrencyInfo(); break;
  295. case TransactionBuy: finishCurrencyBuy(); break;
  296. default: ;
  297. }
  298. }
  299. delete mTransaction;
  300. mTransaction = NULL;
  301. mTransactionType = TransactionNone;
  302. return true;
  303. }
  304. void LLCurrencyUIManager::Impl::setError(
  305. const std::string& message, const std::string& uri)
  306. {
  307. mError = true;
  308. mErrorMessage = message;
  309. mErrorURI = uri;
  310. }
  311. void LLCurrencyUIManager::Impl::clearError()
  312. {
  313. mError = false;
  314. mErrorMessage.clear();
  315. mErrorURI.clear();
  316. }
  317. bool LLCurrencyUIManager::Impl::considerUpdateCurrency()
  318. {
  319. if (mCurrencyChanged
  320. &&  !mTransaction 
  321. &&  mCurrencyKeyTimer.getElapsedTimeF32() >= CURRENCY_ESTIMATE_FREQUENCY)
  322. {
  323. updateCurrencyInfo();
  324. return true;
  325. }
  326. return false;
  327. }
  328. void LLCurrencyUIManager::Impl::currencyKey(S32 value)
  329. {
  330. mUserEnteredCurrencyBuy = true;
  331. mCurrencyKeyTimer.reset();
  332. if (mUserCurrencyBuy == value)
  333. {
  334. return;
  335. }
  336. mUserCurrencyBuy = value;
  337. if (hasEstimate()) {
  338. clearEstimate();
  339. //cannot just simply refresh the whole UI, as the edit field will
  340. // get reset and the cursor will change...
  341. mPanel.childHide("currency_est");
  342. mPanel.childSetVisible("getting_data",TRUE);
  343. }
  344. mCurrencyChanged = true;
  345. }
  346. // static
  347. void LLCurrencyUIManager::Impl::onCurrencyKey(
  348. LLLineEditor* caller, void* data)
  349. {
  350. S32 value = atoi(caller->getText().c_str());
  351. LLCurrencyUIManager::Impl* self = (LLCurrencyUIManager::Impl*)data;
  352. self->currencyKey(value);
  353. }
  354. void LLCurrencyUIManager::Impl::prepare()
  355. {
  356. LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
  357. if (lindenAmount)
  358. {
  359. lindenAmount->setPrevalidate(LLTextValidate::validateNonNegativeS32);
  360. lindenAmount->setKeystrokeCallback(onCurrencyKey, this);
  361. }
  362. }
  363. void LLCurrencyUIManager::Impl::updateUI()
  364. {
  365. if (mHidden)
  366. {
  367. mPanel.childHide("currency_action");
  368. mPanel.childHide("currency_amt");
  369. mPanel.childHide("currency_est");
  370. return;
  371. }
  372. mPanel.childShow("currency_action");
  373. LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
  374. if (lindenAmount) 
  375. {
  376. lindenAmount->setVisible(true);
  377. lindenAmount->setLabel(mZeroMessage);
  378. if (!mUserEnteredCurrencyBuy)
  379. {
  380. if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
  381. {
  382. lindenAmount->setText(LLStringUtil::null);
  383. }
  384. else
  385. {
  386. lindenAmount->setText(llformat("%d", mUserCurrencyBuy));
  387. }
  388. lindenAmount->selectAll();
  389. }
  390. }
  391. mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", getLocalEstimate());
  392. mPanel.childSetVisible("currency_est", hasEstimate() && mUserCurrencyBuy > 0);
  393. mPanel.childSetVisible("currency_links", mSupportsInternationalBilling);
  394. mPanel.childSetVisible("exchange_rate_note", mSupportsInternationalBilling);
  395. if (mPanel.childIsEnabled("buy_btn")
  396. ||mPanel.childIsVisible("currency_est")
  397. || mPanel.childIsVisible("error_web"))
  398. {
  399. mPanel.childSetVisible("getting_data",FALSE);
  400. }
  401. }
  402. LLCurrencyUIManager::LLCurrencyUIManager(LLPanel& dialog)
  403. : impl(* new Impl(dialog))
  404. {
  405. }
  406. LLCurrencyUIManager::~LLCurrencyUIManager()
  407. {
  408. delete &impl;
  409. }
  410. void LLCurrencyUIManager::setAmount(int amount, bool noEstimate)
  411. {
  412. impl.mUserCurrencyBuy = amount;
  413. impl.mUserEnteredCurrencyBuy = false;
  414. impl.updateUI();
  415. impl.mCurrencyChanged = !noEstimate;
  416. }
  417. int LLCurrencyUIManager::getAmount()
  418. {
  419. return impl.mUserCurrencyBuy;
  420. }
  421. void LLCurrencyUIManager::setZeroMessage(const std::string& message)
  422. {
  423. impl.mZeroMessage = message;
  424. }
  425. void LLCurrencyUIManager::setUSDEstimate(int amount)
  426. {
  427. impl.mUSDCurrencyEstimatedCost = amount;
  428. impl.mUSDCurrencyEstimated = true;
  429. impl.updateUI();
  430. impl.mCurrencyChanged = false;
  431. }
  432. int LLCurrencyUIManager::getUSDEstimate()
  433. {
  434. return impl.mUSDCurrencyEstimated ? impl.mUSDCurrencyEstimatedCost : 0;
  435. }
  436. void LLCurrencyUIManager::setLocalEstimate(const std::string &amount)
  437. {
  438. impl.mLocalCurrencyEstimatedCost = amount;
  439. impl.mLocalCurrencyEstimated = true;
  440. impl.updateUI();
  441. impl.mCurrencyChanged = false;
  442. }
  443. std::string LLCurrencyUIManager::getLocalEstimate() const
  444. {
  445. return impl.getLocalEstimate();
  446. }
  447. void LLCurrencyUIManager::prepare()
  448. {
  449. impl.prepare();
  450. }
  451. void LLCurrencyUIManager::updateUI(bool show)
  452. {
  453. impl.mHidden = !show;
  454. impl.updateUI();
  455. }
  456. bool LLCurrencyUIManager::process()
  457. {
  458. bool changed = false;
  459. changed |= impl.checkTransaction();
  460. changed |= impl.considerUpdateCurrency();
  461. return changed;
  462. }
  463. void LLCurrencyUIManager::buy(const std::string& buy_msg)
  464. {
  465. if (!canBuy())
  466. {
  467. return;
  468. }
  469. LLUIString msg = buy_msg;
  470. msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy));
  471. msg.setArg("[LOCALAMOUNT]", getLocalEstimate());
  472. LLConfirmationManager::confirm(impl.mSiteConfirm,
  473.    msg,
  474.    impl,
  475.    &LLCurrencyUIManager::Impl::startCurrencyBuy);
  476. }
  477. bool LLCurrencyUIManager::inProcess()
  478. {
  479. return impl.mTransactionType != Impl::TransactionNone;
  480. }
  481. bool LLCurrencyUIManager::canCancel()
  482. {
  483. return impl.mTransactionType != Impl::TransactionBuy;
  484. }
  485. bool LLCurrencyUIManager::canBuy()
  486. {
  487. return impl.mTransactionType == Impl::TransactionNone
  488. && impl.hasEstimate()
  489. && impl.mUserCurrencyBuy > 0;
  490. }
  491. bool LLCurrencyUIManager::buying()
  492. {
  493. return impl.mTransactionType == Impl::TransactionBuy;
  494. }
  495. bool LLCurrencyUIManager::bought()
  496. {
  497. return impl.mBought;
  498. }
  499. bool LLCurrencyUIManager::hasError()
  500. {
  501. return impl.mError;
  502. }
  503. std::string LLCurrencyUIManager::errorMessage()
  504. {
  505. return impl.mErrorMessage;
  506. }
  507. std::string LLCurrencyUIManager::errorURI()
  508. {
  509. return impl.mErrorURI;
  510. }