llfloaterpostcard.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llfloaterpostcard.h"
00035 
00036 #include "llfontgl.h"
00037 #include "llsys.h"
00038 #include "llgl.h"
00039 #include "v3dmath.h"
00040 #include "lldir.h"
00041 
00042 #include "llagent.h"
00043 #include "llui.h"
00044 #include "lllineeditor.h"
00045 #include "llviewertexteditor.h"
00046 #include "llbutton.h"
00047 #include "llviewercontrol.h"
00048 #include "llviewernetwork.h"
00049 #include "lluictrlfactory.h"
00050 #include "lluploaddialog.h"
00051 #include "llviewerstats.h"
00052 #include "llviewerwindow.h"
00053 #include "llstatusbar.h"
00054 #include "llviewerregion.h"
00055 #include "lleconomy.h"
00056 
00057 #include "llgl.h"
00058 #include "llglheaders.h"
00059 #include "llimagejpeg.h"
00060 #include "llimagej2c.h"
00061 #include "llvfile.h"
00062 #include "llvfs.h"
00063 
00064 #include "llassetuploadresponders.h"
00065 
00069 
00070 //static
00071 LLFloaterPostcard::instance_list_t LLFloaterPostcard::sInstances;
00072 
00076 
00077 LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global)
00078 :       LLFloater("Postcard Floater"),
00079         mJPEGImage(jpeg),
00080         mViewerImage(img),
00081         mImageScale(img_scale),
00082         mPosTakenGlobal(pos_taken_global),
00083         mHasFirstMsgFocus(false)
00084 {
00085         init();
00086 }
00087 
00088 void LLFloaterPostcard::init()
00089 {
00090         // pick up the user's up-to-date email address
00091         if(!gAgent.getID().isNull())
00092         {
00093                 // we're logged in, so we can get this info.
00094                 gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest);
00095                 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
00096                 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00097                 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00098                 gAgent.sendReliableMessage();
00099         }
00100 
00101         sInstances.insert(this);
00102 }
00103 
00104 // Destroys the object
00105 LLFloaterPostcard::~LLFloaterPostcard()
00106 {
00107         sInstances.erase(this);
00108         mJPEGImage = NULL; // deletes image
00109 }
00110 
00111 BOOL LLFloaterPostcard::postBuild()
00112 {
00113         childSetAction("cancel_btn", onClickCancel, this);
00114         childSetAction("send_btn", onClickSend, this);
00115 
00116         childDisable("from_form");
00117 
00118         std::string name_string;
00119         gAgent.buildFullname(name_string);
00120         childSetValue("name_form", LLSD(name_string));
00121 
00122         LLTextEditor* MsgField = getChild<LLTextEditor>("msg_form");
00123         if (MsgField)
00124         {
00125                 MsgField->setWordWrap(TRUE);
00126 
00127                 // For the first time a user focusess to .the msg box, all text will be selected.
00128                 MsgField->setFocusChangedCallback(onMsgFormFocusRecieved, this);
00129         }
00130         
00131         childSetFocus("to_form", TRUE);
00132 
00133     return TRUE;
00134 }
00135 
00136 
00137 
00138 // static
00139 LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLImageGL *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
00140 {
00141         // Take the images from the caller
00142         // It's now our job to clean them up
00143         LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global);
00144 
00145         LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml");
00146 
00147         S32 left, top;
00148         gFloaterView->getNewFloaterPosition(&left, &top);
00149         instance->setOrigin(left, top - instance->getRect().getHeight());
00150         
00151         instance->open();               /*Flawfinder: ignore*/
00152 
00153         return instance;
00154 }
00155 
00156 void LLFloaterPostcard::draw()
00157 {
00158         LLGLSUIDefault gls_ui;
00159         LLFloater::draw();
00160 
00161         if(!isMinimized() && mViewerImage.notNull() && mJPEGImage.notNull()) 
00162         {
00163                 LLRect rect(getRect());
00164 
00165                 // first set the max extents of our preview
00166                 rect.translate(-rect.mLeft, -rect.mBottom);
00167                 rect.mLeft += 280;
00168                 rect.mRight -= 10;
00169                 rect.mTop -= 20;
00170                 rect.mBottom = rect.mTop - 130;
00171 
00172                 // then fix the aspect ratio
00173                 F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight();
00174                 if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
00175                 {
00176                         rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
00177                 }
00178                 else
00179                 {
00180                         rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
00181                 }
00182                 {
00183                         LLGLSNoTexture gls_no_texture;
00184                         gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
00185                         rect.stretch(-1);
00186                 }
00187                 {
00188 
00189                 glMatrixMode(GL_TEXTURE);
00190                 glPushMatrix();
00191                 {
00192                         glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
00193                         glMatrixMode(GL_MODELVIEW);
00194                         gl_draw_scaled_image(rect.mLeft,
00195                                                                  rect.mBottom,
00196                                                                  rect.getWidth(),
00197                                                                  rect.getHeight(),
00198                                                                  mViewerImage, 
00199                                                                  LLColor4::white);
00200                 }
00201                 glMatrixMode(GL_TEXTURE);
00202                 glPopMatrix();
00203                 glMatrixMode(GL_MODELVIEW);
00204                 }
00205         }
00206 }
00207 
00208 // static
00209 void LLFloaterPostcard::onClickCancel(void* data)
00210 {
00211         if (data)
00212         {
00213                 LLFloaterPostcard *self = (LLFloaterPostcard *)data;
00214 
00215                 self->close(false);
00216         }
00217 }
00218 
00219 class LLSendPostcardResponder : public LLAssetUploadResponder
00220 {
00221 public:
00222         LLSendPostcardResponder(const LLSD &post_data,
00223                                                         const LLUUID& vfile_id,
00224                                                         LLAssetType::EType asset_type):
00225             LLAssetUploadResponder(post_data, vfile_id, asset_type)
00226         {       
00227         }
00228         // *TODO define custom uploadFailed here so it's not such a generic message
00229         void uploadComplete(const LLSD& content)
00230         {
00231                 // we don't care about what the server returns from this post, just clean up the UI
00232                 LLUploadDialog::modalUploadFinished();
00233         }
00234 };
00235 
00236 // static
00237 void LLFloaterPostcard::onClickSend(void* data)
00238 {
00239         if (data)
00240         {
00241                 LLFloaterPostcard *self = (LLFloaterPostcard *)data;
00242 
00243                 std::string from(self->childGetValue("from_form").asString());
00244                 std::string to(self->childGetValue("to_form").asString());
00245 
00246                 if (to.empty() || to.find('@') == std::string::npos)
00247                 {
00248                         gViewerWindow->alertXml("PromptRecipientEmail");
00249                         return;
00250                 }
00251 
00252                 if (from.empty() || from.find('@') == std::string::npos)
00253                 {
00254                         gViewerWindow->alertXml("PromptSelfEmail");
00255                         return;
00256                 }
00257 
00258                 std::string subject(self->childGetValue("subject_form").asString());
00259                 if(subject.empty() || !self->mHasFirstMsgFocus)
00260                 {
00261                         gViewerWindow->alertXml("PromptMissingSubjMsg", missingSubjMsgAlertCallback, self);
00262                         return;
00263                 }
00264 
00265                 if (self->mJPEGImage.notNull())
00266                 {
00267                         self->sendPostcard();
00268                 }
00269                 else
00270                 {
00271                         gViewerWindow->alertXml("ErrorProcessingSnapshot");
00272                 }
00273         }
00274 }
00275 
00276 // static
00277 void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
00278 {
00279         LLFloaterPostcard *self = (LLFloaterPostcard *)user_data;
00280         
00281         LLUploadDialog::modalUploadFinished();
00282         
00283         if (result)
00284         {
00285                 LLStringBase<char>::format_map_t args;
00286                 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
00287                 gViewerWindow->alertXml("ErrorUploadingPostcard", args);
00288         }
00289         else
00290         {
00291                 // only create the postcard once the upload succeeds
00292 
00293                 // request the postcard
00294                 LLMessageSystem* msg = gMessageSystem;
00295                 msg->newMessage("SendPostcard");
00296                 msg->nextBlock("AgentData");
00297                 msg->addUUID("AgentID", gAgent.getID());
00298                 msg->addUUID("SessionID", gAgent.getSessionID());
00299                 msg->addUUID("AssetID", self->mAssetID);
00300                 msg->addVector3d("PosGlobal", self->mPosTakenGlobal);
00301                 msg->addString("To", self->childGetValue("to_form").asString());
00302                 msg->addString("From", self->childGetValue("from_form").asString());
00303                 msg->addString("Name", self->childGetValue("name_form").asString());
00304                 msg->addString("Subject", self->childGetValue("subject_form").asString());
00305                 msg->addString("Msg", self->childGetValue("msg_form").asString());
00306                 msg->addBOOL("AllowPublish", FALSE);
00307                 msg->addBOOL("MaturePublish", FALSE);
00308                 gAgent.sendReliableMessage();
00309         }
00310 
00311         self->close();
00312 }
00313 
00314 // static
00315 void LLFloaterPostcard::updateUserInfo(const char *email)
00316 {
00317         for (instance_list_t::iterator iter = sInstances.begin();
00318                  iter != sInstances.end(); ++iter)
00319         {
00320                 LLFloaterPostcard *instance = *iter;
00321                 const LLString& text = instance->childGetValue("from_form").asString();
00322                 if (text.empty())
00323                 {
00324                         // there's no text in this field yet, pre-populate
00325                         instance->childSetValue("from_form", LLSD(email));
00326                 }
00327         }
00328 }
00329 
00330 void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data)
00331 {
00332         LLFloaterPostcard* self = (LLFloaterPostcard *)data;
00333         if(self) 
00334         {
00335                 LLTextEditor* msgForm = self->getChild<LLTextEditor>("msg_form");
00336                 if(msgForm && msgForm == receiver && msgForm->hasFocus() && !(self->mHasFirstMsgFocus))
00337                 {
00338                         self->mHasFirstMsgFocus = true;
00339                         msgForm->setText(LLString::null);
00340                 }
00341         }
00342 }
00343 
00344 void LLFloaterPostcard::missingSubjMsgAlertCallback(S32 option, void* data)
00345 {
00346         if(data)
00347         {
00348                 LLFloaterPostcard* self = static_cast<LLFloaterPostcard*>(data);
00349                 if(0 == option)
00350                 {
00351                         // User clicked OK
00352                         if((self->childGetValue("subject_form").asString()).empty())
00353                         {
00354                                 // Stuff the subject back into the form.
00355                                 self->childSetValue("subject_form", self->getString("default_subject"));
00356                         }
00357 
00358                         if(!self->mHasFirstMsgFocus)
00359                         {
00360                                 // The user never switched focus to the messagee window. 
00361                                 // Using the default string.
00362                                 self->childSetValue("msg_form", self->getString("default_message"));
00363                         }
00364 
00365                         self->sendPostcard();
00366                 }
00367         }
00368 }
00369 
00370 void LLFloaterPostcard::sendPostcard()
00371 {
00372         mTransactionID.generate();
00373         mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
00374         LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG);
00375 
00376         // upload the image
00377         std::string url = gAgent.getRegion()->getCapability("SendPostcard");
00378         if(!url.empty())
00379         {
00380                 llinfos << "Send Postcard via capability" << llendl;
00381                 LLSD body = LLSD::emptyMap();
00382                 // the capability already encodes: agent ID, region ID
00383                 body["pos-global"] = mPosTakenGlobal.getValue();
00384                 body["to"] = childGetValue("to_form").asString();
00385                 body["from"] = childGetValue("from_form").asString();
00386                 body["name"] = childGetValue("name_form").asString();
00387                 body["subject"] = childGetValue("subject_form").asString();
00388                 body["msg"] = childGetValue("msg_form").asString();
00389                 LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG));
00390         } 
00391         else
00392         {
00393                 gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE);
00394         }
00395 
00396         LLUploadDialog::modalUploadDialog("Uploading...\n\nPostcard");
00397 
00398         // don't destroy the window until the upload is done
00399         // this way we keep the information in the form
00400         setVisible(FALSE);
00401 
00402         // also remove any dependency on another floater
00403         // so that we can be sure to outlive it while we
00404         // need to.
00405         LLFloater* dependee = getDependee();
00406         if (dependee)
00407                 dependee->removeDependentFloater(this);
00408 }

Generated on Fri May 16 08:33:29 2008 for SecondLife by  doxygen 1.5.5