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 "llvieweruictrlfactory.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 #include "viewer.h"
00064 
00065 #include "llassetuploadresponders.h"
00066 
00070 
00071 LLLinkedList<LLFloaterPostcard> 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.addData(this);
00102 }
00103 
00104 // Destroys the object
00105 LLFloaterPostcard::~LLFloaterPostcard()
00106 {
00107         sInstances.removeData(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         childSetAction("publish_help_btn", onClickPublishHelp, this);
00118 
00119         if (gAgent.isTeen())
00120         {
00121                 // Disable these buttons if they are PG (Teen) users
00122                 childDisable("allow_publish_check");
00123                 childHide("allow_publish_check");
00124                 childDisable("publish_help_btn");
00125                 childHide("publish_help_btn");
00126                 childDisable("mature_check");
00127                 childHide("mature_check");
00128         }
00129         
00130         LLString name_string;
00131         gAgent.buildFullname(name_string);
00132         
00133         childSetValue("name_form", LLSD(name_string));
00134 
00135         LLTextEditor *MsgField = LLUICtrlFactory::getTextEditorByName(this, "msg_form");
00136         if (MsgField)
00137         {
00138                 MsgField->setWordWrap(TRUE);
00139 
00140                 // For the first time a user focusess to .the msg box, all text will be selected.
00141                 MsgField->setFocusChangedCallback(onMsgFormFocusRecieved);
00142                 MsgField->setCallbackUserData(this);
00143         }
00144         
00145         childSetFocus("to_form", TRUE);
00146 
00147     return TRUE;
00148 }
00149 
00150 
00151 
00152 // static
00153 LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLImageGL *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
00154 {
00155         // Take the images from the caller
00156         // It's now our job to clean them up
00157         LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global);
00158 
00159         gUICtrlFactory->buildFloater(instance, "floater_postcard.xml");
00160 
00161         S32 left, top;
00162         gFloaterView->getNewFloaterPosition(&left, &top);
00163         instance->setOrigin(left, top - instance->getRect().getHeight());
00164         
00165         instance->open();               /*Flawfinder: ignore*/
00166 
00167         return instance;
00168 }
00169 
00170 void LLFloaterPostcard::draw()
00171 {
00172         LLGLSUIDefault gls_ui;
00173         LLFloater::draw();
00174 
00175         if(getVisible() && !mMinimized && mViewerImage.notNull() && mJPEGImage.notNull()) 
00176         {
00177                 LLRect rect(mRect);
00178 
00179                 // first set the max extents of our preview
00180                 rect.translate(-rect.mLeft, -rect.mBottom);
00181                 rect.mLeft += 280;
00182                 rect.mRight -= 10;
00183                 rect.mTop -= 20;
00184                 rect.mBottom = rect.mTop - 130;
00185 
00186                 // then fix the aspect ratio
00187                 F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight();
00188                 if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
00189                 {
00190                         rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
00191                 }
00192                 else
00193                 {
00194                         rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
00195                 }
00196                 {
00197                         LLGLSNoTexture gls_no_texture;
00198                         gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
00199                         rect.stretch(-1);
00200                 }
00201                 {
00202 
00203                 glMatrixMode(GL_TEXTURE);
00204                 glPushMatrix();
00205                 {
00206                         glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
00207                         glMatrixMode(GL_MODELVIEW);
00208                         gl_draw_scaled_image(rect.mLeft,
00209                                                                  rect.mBottom,
00210                                                                  rect.getWidth(),
00211                                                                  rect.getHeight(),
00212                                                                  mViewerImage, 
00213                                                                  LLColor4::white);
00214                 }
00215                 glMatrixMode(GL_TEXTURE);
00216                 glPopMatrix();
00217                 glMatrixMode(GL_MODELVIEW);
00218                 }
00219         }
00220 }
00221 
00222 // static
00223 void LLFloaterPostcard::onClickCancel(void* data)
00224 {
00225         if (data)
00226         {
00227                 LLFloaterPostcard *self = (LLFloaterPostcard *)data;
00228 
00229                 self->close(false);
00230         }
00231 }
00232 
00233 class LLSendPostcardResponder : public LLAssetUploadResponder
00234 {
00235 public:
00236         LLSendPostcardResponder(const LLSD &post_data,
00237                                                         const LLUUID& vfile_id,
00238                                                         LLAssetType::EType asset_type):
00239             LLAssetUploadResponder(post_data, vfile_id, asset_type)
00240         {       
00241         }
00242         // *TODO define custom uploadFailed here so it's not such a generic message
00243         void uploadComplete(const LLSD& content)
00244         {
00245                 // we don't care about what the server returns from this post, just clean up the UI
00246                 LLUploadDialog::modalUploadFinished();
00247         }
00248 };
00249 
00250 // static
00251 void LLFloaterPostcard::onClickSend(void* data)
00252 {
00253         if (data)
00254         {
00255                 LLFloaterPostcard *self = (LLFloaterPostcard *)data;
00256 
00257                 LLString from(self->childGetValue("from_form").asString().c_str());
00258                 LLString to(self->childGetValue("to_form").asString().c_str());
00259 
00260                 if (to.empty() || to.find('@') == std::string::npos)
00261                 {
00262                         gViewerWindow->alertXml("PromptRecipientEmail");
00263                         return;
00264                 }
00265 
00266                 if (from.empty() || from.find('@') == std::string::npos)
00267                 {
00268                         gViewerWindow->alertXml("PromptSelfEmail");
00269                         return;
00270                 }
00271 
00272                 LLString subject(self->childGetValue("subject_form").asString().c_str());
00273                 if(subject.empty() || !self->mHasFirstMsgFocus)
00274                 {
00275                         gViewerWindow->alertXml("PromptMissingSubjMsg", missingSubjMsgAlertCallback, self);
00276                         return;
00277                 }
00278 
00279                 if (self->mJPEGImage.notNull())
00280                 {
00281                         self->sendPostcard();
00282                 }
00283                 else
00284                 {
00285                         gViewerWindow->alertXml("ErrorProcessingSnapshot");
00286                 }
00287         }
00288 }
00289 
00290 // static
00291 void LLFloaterPostcard::onClickPublishHelp(void* data)
00292 {
00293         gViewerWindow->alertXml("ClickPublishHelpPostcard");
00294 }
00295 
00296 // static
00297 void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
00298 {
00299         LLFloaterPostcard *self = (LLFloaterPostcard *)user_data;
00300         
00301         LLUploadDialog::modalUploadFinished();
00302         
00303         if (result)
00304         {
00305                 LLStringBase<char>::format_map_t args;
00306                 args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
00307                 gViewerWindow->alertXml("ErrorUploadingPostcard", args);
00308         }
00309         else
00310         {
00311                 // only create the postcard once the upload succeeds
00312 
00313                 // request the postcard
00314                 LLMessageSystem* msg = gMessageSystem;
00315                 msg->newMessage("SendPostcard");
00316                 msg->nextBlock("AgentData");
00317                 msg->addUUID("AgentID", gAgent.getID());
00318                 msg->addUUID("SessionID", gAgent.getSessionID());
00319                 msg->addUUID("AssetID", self->mAssetID);
00320                 msg->addVector3d("PosGlobal", self->mPosTakenGlobal);
00321                 msg->addString("To", self->childGetValue("to_form").asString());
00322                 msg->addString("From", self->childGetValue("from_form").asString());
00323                 msg->addString("Name", self->childGetValue("name_form").asString());
00324                 msg->addString("Subject", self->childGetValue("subject_form").asString());
00325                 msg->addString("Msg", self->childGetValue("msg_form").asString());
00326                 msg->addBOOL("AllowPublish", self->childGetValue("allow_publish_check").asBoolean());
00327                 msg->addBOOL("MaturePublish", self->childGetValue("mature_check").asBoolean());
00328                 gAgent.sendReliableMessage();
00329         }
00330 
00331         self->close();
00332 }
00333 
00334 // static
00335 void LLFloaterPostcard::updateUserInfo(const char *email)
00336 {
00337         LLFloaterPostcard *instance;
00338 
00339         sInstances.resetList();
00340         while ((instance = sInstances.getNextData()))
00341         {
00342                 const LLString& text = instance->childGetValue("from_form").asString();
00343                 if (text.empty())
00344                 {
00345                         // there's no text in this field yet, pre-populate
00346                         instance->childSetValue("from_form", LLSD(email));
00347                 }
00348         }
00349 }
00350 
00351 void LLFloaterPostcard::onMsgFormFocusRecieved(LLUICtrl* receiver, void* data)
00352 {
00353         LLFloaterPostcard* self = (LLFloaterPostcard *)data;
00354         if(self) 
00355         {
00356                 LLTextEditor* msgForm = LLUICtrlFactory::getTextEditorByName(self, "msg_form");
00357                 if(msgForm && msgForm == receiver && msgForm->hasFocus() && !(self->mHasFirstMsgFocus))
00358                 {
00359                         self->mHasFirstMsgFocus = true;
00360                         msgForm->setText(LLString::null);
00361                 }
00362         }
00363 }
00364 
00365 void LLFloaterPostcard::missingSubjMsgAlertCallback(S32 option, void* data)
00366 {
00367         if(data)
00368         {
00369                 LLFloaterPostcard* self = static_cast<LLFloaterPostcard*>(data);
00370                 if(0 == option)
00371                 {
00372                         // User clicked OK
00373                         if((self->childGetValue("subject_form").asString()).empty())
00374                         {
00375                                 // Stuff the subject back into the form.
00376                                 self->childSetValue("subject_form", self->childGetText("default_subject"));
00377                         }
00378 
00379                         if(!self->mHasFirstMsgFocus)
00380                         {
00381                                 // The user never switched focus to the messagee window. 
00382                                 // Using the default string.
00383                                 self->childSetValue("msg_form", self->childGetText("default_message"));
00384                         }
00385 
00386                         self->sendPostcard();
00387                 }
00388         }
00389 }
00390 
00391 void LLFloaterPostcard::sendPostcard()
00392 {
00393         mTransactionID.generate();
00394         mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
00395         LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG);
00396 
00397         // upload the image
00398         std::string url = gAgent.getRegion()->getCapability("SendPostcard");
00399         if(!url.empty())
00400         {
00401                 llinfos << "Send Postcard via capability" << llendl;
00402                 LLSD body = LLSD::emptyMap();
00403                 // the capability already encodes: agent ID, region ID
00404                 body["pos-global"] = mPosTakenGlobal.getValue();
00405                 body["to"] = childGetValue("to_form").asString();
00406                 body["from"] = childGetValue("from_form").asString();
00407                 body["name"] = childGetValue("name_form").asString();
00408                 body["subject"] = childGetValue("subject_form").asString();
00409                 body["msg"] = childGetValue("msg_form").asString();
00410                 body["allow-publish"] = childGetValue("allow_publish_check").asBoolean();
00411                 body["mature-publish"] = childGetValue("mature_check").asBoolean();
00412                 LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG));
00413         } 
00414         else
00415         {
00416                 gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE);
00417         }
00418 
00419         LLUploadDialog::modalUploadDialog("Uploading...\n\nPostcard");
00420 
00421         // don't destroy the window until the upload is done
00422         // this way we keep the information in the form
00423         setVisible(FALSE);
00424 
00425         // also remove any dependency on another floater
00426         // so that we can be sure to outlive it while we
00427         // need to.
00428         LLFloater* dependee = getDependee();
00429         if (dependee)
00430                 dependee->removeDependentFloater(this);
00431 }

Generated on Thu Jul 1 06:08:35 2010 for Second Life Viewer by  doxygen 1.4.7