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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloaterpostcard.cpp
  3.  * @brief Postcard send floater, allows setting name, e-mail address, etc.
  4.  *
  5.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2004-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 "llfloaterpostcard.h"
  34. #include "llfontgl.h"
  35. #include "llsys.h"
  36. #include "llgl.h"
  37. #include "v3dmath.h"
  38. #include "lldir.h"
  39. #include "llagent.h"
  40. #include "llui.h"
  41. #include "lllineeditor.h"
  42. #include "llbutton.h"
  43. #include "lltexteditor.h"
  44. #include "llfloaterreg.h"
  45. #include "llnotificationsutil.h"
  46. #include "llviewercontrol.h"
  47. #include "llviewernetwork.h"
  48. #include "lluictrlfactory.h"
  49. #include "lluploaddialog.h"
  50. #include "llviewerstats.h"
  51. #include "llviewerwindow.h"
  52. #include "llstatusbar.h"
  53. #include "llviewerregion.h"
  54. #include "lleconomy.h"
  55. #include "message.h"
  56. #include "llimagejpeg.h"
  57. #include "llimagej2c.h"
  58. #include "llvfile.h"
  59. #include "llvfs.h"
  60. #include "llviewertexture.h"
  61. #include "llassetuploadresponders.h"
  62. #include "llagentui.h"
  63. #include <boost/regex.hpp>  //boost.regex lib
  64. ///----------------------------------------------------------------------------
  65. /// Local function declarations, constants, enums, and typedefs
  66. ///----------------------------------------------------------------------------
  67. ///----------------------------------------------------------------------------
  68. /// Class LLFloaterPostcard
  69. ///----------------------------------------------------------------------------
  70. LLFloaterPostcard::LLFloaterPostcard(const LLSD& key)
  71. : LLFloater(key),
  72. mJPEGImage(NULL),
  73. mViewerImage(NULL),
  74. mHasFirstMsgFocus(false)
  75. {
  76. //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_postcard.xml");
  77. }
  78. // Destroys the object
  79. LLFloaterPostcard::~LLFloaterPostcard()
  80. {
  81. mJPEGImage = NULL; // deletes image
  82. }
  83. BOOL LLFloaterPostcard::postBuild()
  84. {
  85. // pick up the user's up-to-date email address
  86. gAgent.sendAgentUserInfoRequest();
  87. childSetAction("cancel_btn", onClickCancel, this);
  88. childSetAction("send_btn", onClickSend, this);
  89. childDisable("from_form");
  90. std::string name_string;
  91. LLAgentUI::buildFullname(name_string);
  92. childSetValue("name_form", LLSD(name_string));
  93. // For the first time a user focusess to .the msg box, all text will be selected.
  94. getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(onMsgFormFocusRecieved, _1, this));
  95. childSetFocus("to_form", TRUE);
  96.     return TRUE;
  97. }
  98. // static
  99. LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
  100. {
  101. // Take the images from the caller
  102. // It's now our job to clean them up
  103. LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID()));
  104. instance->mJPEGImage = jpeg;
  105. instance->mViewerImage = img;
  106. instance->mImageScale = image_scale;
  107. instance->mPosTakenGlobal = pos_taken_global;
  108. return instance;
  109. }
  110. void LLFloaterPostcard::draw()
  111. {
  112. LLGLSUIDefault gls_ui;
  113. LLFloater::draw();
  114. if(!isMinimized() && mViewerImage.notNull() && mJPEGImage.notNull()) 
  115. {
  116. LLRect rect(getRect());
  117. // first set the max extents of our preview
  118. rect.translate(-rect.mLeft, -rect.mBottom);
  119. rect.mLeft += 280;
  120. rect.mRight -= 10;
  121. rect.mTop -= 20;
  122. rect.mBottom = rect.mTop - 130;
  123. // then fix the aspect ratio
  124. F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight();
  125. if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
  126. {
  127. rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
  128. }
  129. else
  130. {
  131. rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
  132. }
  133. {
  134. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  135. gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
  136. rect.stretch(-1);
  137. }
  138. {
  139. glMatrixMode(GL_TEXTURE);
  140. glPushMatrix();
  141. {
  142. glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
  143. glMatrixMode(GL_MODELVIEW);
  144. gl_draw_scaled_image(rect.mLeft,
  145.  rect.mBottom,
  146.  rect.getWidth(),
  147.  rect.getHeight(),
  148.  mViewerImage.get(), 
  149.  LLColor4::white);
  150. }
  151. glMatrixMode(GL_TEXTURE);
  152. glPopMatrix();
  153. glMatrixMode(GL_MODELVIEW);
  154. }
  155. }
  156. }
  157. // static
  158. void LLFloaterPostcard::onClickCancel(void* data)
  159. {
  160. if (data)
  161. {
  162. LLFloaterPostcard *self = (LLFloaterPostcard *)data;
  163. self->closeFloater(false);
  164. }
  165. }
  166. class LLSendPostcardResponder : public LLAssetUploadResponder
  167. {
  168. public:
  169. LLSendPostcardResponder(const LLSD &post_data,
  170. const LLUUID& vfile_id,
  171. LLAssetType::EType asset_type):
  172.     LLAssetUploadResponder(post_data, vfile_id, asset_type)
  173. {
  174. }
  175. // *TODO define custom uploadFailed here so it's not such a generic message
  176. void uploadComplete(const LLSD& content)
  177. {
  178. // we don't care about what the server returns from this post, just clean up the UI
  179. LLUploadDialog::modalUploadFinished();
  180. }
  181. };
  182. // static
  183. void LLFloaterPostcard::onClickSend(void* data)
  184. {
  185. if (data)
  186. {
  187. LLFloaterPostcard *self = (LLFloaterPostcard *)data;
  188. std::string from(self->childGetValue("from_form").asString());
  189. std::string to(self->childGetValue("to_form").asString());
  190. boost::regex emailFormat("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}(,[ t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})*");
  191. if (to.empty() || !boost::regex_match(to, emailFormat))
  192. {
  193. LLNotificationsUtil::add("PromptRecipientEmail");
  194. return;
  195. }
  196. if (from.empty() || !boost::regex_match(from, emailFormat))
  197. {
  198. LLNotificationsUtil::add("PromptSelfEmail");
  199. return;
  200. }
  201. std::string subject(self->childGetValue("subject_form").asString());
  202. if(subject.empty() || !self->mHasFirstMsgFocus)
  203. {
  204. LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2));
  205. return;
  206. }
  207. if (self->mJPEGImage.notNull())
  208. {
  209. self->sendPostcard();
  210. }
  211. else
  212. {
  213. LLNotificationsUtil::add("ErrorProcessingSnapshot");
  214. }
  215. }
  216. }
  217. // static
  218. void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
  219. {
  220. LLFloaterPostcard *self = (LLFloaterPostcard *)user_data;
  221. LLUploadDialog::modalUploadFinished();
  222. if (result)
  223. {
  224. LLSD args;
  225. args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
  226. LLNotificationsUtil::add("ErrorUploadingPostcard", args);
  227. }
  228. else
  229. {
  230. // only create the postcard once the upload succeeds
  231. // request the postcard
  232. LLMessageSystem* msg = gMessageSystem;
  233. msg->newMessage("SendPostcard");
  234. msg->nextBlock("AgentData");
  235. msg->addUUID("AgentID", gAgent.getID());
  236. msg->addUUID("SessionID", gAgent.getSessionID());
  237. msg->addUUID("AssetID", self->mAssetID);
  238. msg->addVector3d("PosGlobal", self->mPosTakenGlobal);
  239. msg->addString("To", self->childGetValue("to_form").asString());
  240. msg->addString("From", self->childGetValue("from_form").asString());
  241. msg->addString("Name", self->childGetValue("name_form").asString());
  242. msg->addString("Subject", self->childGetValue("subject_form").asString());
  243. msg->addString("Msg", self->childGetValue("msg_form").asString());
  244. msg->addBOOL("AllowPublish", FALSE);
  245. msg->addBOOL("MaturePublish", FALSE);
  246. gAgent.sendReliableMessage();
  247. }
  248. self->closeFloater();
  249. }
  250. // static
  251. void LLFloaterPostcard::updateUserInfo(const std::string& email)
  252. {
  253. LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("postcard");
  254. for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
  255.  iter != inst_list.end(); ++iter)
  256. {
  257. LLFloater* instance = *iter;
  258. const std::string& text = instance->childGetValue("from_form").asString();
  259. if (text.empty())
  260. {
  261. // there's no text in this field yet, pre-populate
  262. instance->childSetValue("from_form", LLSD(email));
  263. }
  264. }
  265. }
  266. void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data)
  267. {
  268. LLFloaterPostcard* self = (LLFloaterPostcard *)data;
  269. if(self) 
  270. {
  271. LLTextEditor* msgForm = self->getChild<LLTextEditor>("msg_form");
  272. if(msgForm && msgForm == receiver && msgForm->hasFocus() && !(self->mHasFirstMsgFocus))
  273. {
  274. self->mHasFirstMsgFocus = true;
  275. msgForm->setText(LLStringUtil::null);
  276. }
  277. }
  278. }
  279. bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response)
  280. {
  281. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  282. if(0 == option)
  283. {
  284. // User clicked OK
  285. if((childGetValue("subject_form").asString()).empty())
  286. {
  287. // Stuff the subject back into the form.
  288. childSetValue("subject_form", getString("default_subject"));
  289. }
  290. if(!mHasFirstMsgFocus)
  291. {
  292. // The user never switched focus to the messagee window. 
  293. // Using the default string.
  294. childSetValue("msg_form", getString("default_message"));
  295. }
  296. sendPostcard();
  297. }
  298. return false;
  299. }
  300. void LLFloaterPostcard::sendPostcard()
  301. {
  302. mTransactionID.generate();
  303. mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
  304. LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG);
  305. // upload the image
  306. std::string url = gAgent.getRegion()->getCapability("SendPostcard");
  307. if(!url.empty())
  308. {
  309. llinfos << "Send Postcard via capability" << llendl;
  310. LLSD body = LLSD::emptyMap();
  311. // the capability already encodes: agent ID, region ID
  312. body["pos-global"] = mPosTakenGlobal.getValue();
  313. body["to"] = childGetValue("to_form").asString();
  314. body["from"] = childGetValue("from_form").asString();
  315. body["name"] = childGetValue("name_form").asString();
  316. body["subject"] = childGetValue("subject_form").asString();
  317. body["msg"] = childGetValue("msg_form").asString();
  318. LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG));
  319. else
  320. {
  321. gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE);
  322. }
  323. // give user feedback of the event
  324. gViewerWindow->playSnapshotAnimAndSound();
  325. LLUploadDialog::modalUploadDialog(getString("upload_message"));
  326. // don't destroy the window until the upload is done
  327. // this way we keep the information in the form
  328. setVisible(FALSE);
  329. // also remove any dependency on another floater
  330. // so that we can be sure to outlive it while we
  331. // need to.
  332. LLFloater* dependee = getDependee();
  333. if (dependee)
  334. dependee->removeDependentFloater(this);
  335. }