summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMnikolenko ProductEngine <mnikolenko@productengine.com>2015-05-07 16:22:44 +0300
committerMnikolenko ProductEngine <mnikolenko@productengine.com>2015-05-07 16:22:44 +0300
commit91304d3477d433bdf15d19ce08a5b54479634bcd (patch)
treefc9d5109db236d6606ad21ca4b3ebb650c8b6b3a
parent4769fbbea1f75c4f7bb42da8f29064fe26ff9e01 (diff)
MAINT-4812 Restore sending snapshot as email from the viewer.
-rwxr-xr-xindra/newview/CMakeLists.txt1
-rwxr-xr-xindra/newview/llfloatersnapshot.cpp30
-rwxr-xr-xindra/newview/llfloatersnapshot.h1
-rwxr-xr-xindra/newview/llpanelsnapshotoptions.cpp7
-rwxr-xr-xindra/newview/llpanelsnapshotpostcard.cpp244
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp2
-rw-r--r--indra/newview/llsnapshotlivepreview.h2
-rwxr-xr-xindra/newview/llviewermessage.cpp1
-rwxr-xr-xindra/newview/skins/default/xui/de/panel_snapshot_postcard.xml21
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_snapshot.xml6
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_snapshot_options.xml17
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_snapshot_postcard.xml103
-rwxr-xr-xindra/newview/skins/default/xui/es/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/it/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml18
-rwxr-xr-xindra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml18
20 files changed, 575 insertions, 4 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3d7fd5bc5e..13040ea423 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -464,6 +464,7 @@ set(viewer_SOURCE_FILES
llpanelsnapshotinventory.cpp
llpanelsnapshotlocal.cpp
llpanelsnapshotoptions.cpp
+ llpanelsnapshotpostcard.cpp
llpanelsnapshotprofile.cpp
llpanelteleporthistory.cpp
llpaneltiptoast.cpp
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 185765e390..16fa4684ab 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -56,6 +56,7 @@ LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
@@ -168,7 +169,11 @@ LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotT
name = spanel->getName();
}
- if (name == "panel_snapshot_inventory")
+ if (name == "panel_snapshot_postcard")
+ {
+ type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
+ }
+ else if (name == "panel_snapshot_inventory")
{
type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
}
@@ -419,6 +424,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
}
LLSnapshotLivePreview* previewp = getPreviewView(floater);
+ BOOL got_bytes = previewp && previewp->getDataSize() > 0;
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
// *TODO: Separate maximum size for Web images from postcards
@@ -441,7 +447,10 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
}
floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
- floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor( "LabelTextColor" ));
+ floater->getChild<LLUICtrl>("file_size_label")->setColor(
+ shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
+ && got_bytes
+ && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
// Update the width and height spinners based on the corresponding resolution combos. (?)
switch(shot_type)
@@ -451,6 +460,11 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "profile_size_combo");
break;
+ case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
+ layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
+ setResolution(floater, "postcard_size_combo");
+ break;
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
@@ -1446,6 +1460,18 @@ const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal()
return previewp->getPosTakenGlobal();
}
+// static
+void LLFloaterSnapshot::setAgentEmail(const std::string& email)
+{
+ LLFloaterSnapshot* instance = findInstance();
+ if (instance)
+ {
+ LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container");
+ LLPanel* postcard_panel = panel_container->getPanelByName("panel_snapshot_postcard");
+ postcard_panel->notify(LLSD().with("agent-email", email));
+ }
+}
+
///----------------------------------------------------------------------------
/// Class LLSnapshotFloaterView
///----------------------------------------------------------------------------
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 5bcf1d3099..0bb9474bb5 100755
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -63,6 +63,7 @@ public:
static void postPanelSwitch();
static LLPointer<LLImageFormatted> getImageData();
static const LLVector3d& getPosTakenGlobal();
+ static void setAgentEmail(const std::string& email);
static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); }
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index f41bdd8881..0fc9ceec83 100755
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -56,6 +56,7 @@ private:
void updateUploadCost();
void openPanel(const std::string& panel_name);
void onSaveToProfile();
+ void onSaveToEmail();
void onSaveToInventory();
void onSaveToComputer();
void onSendToFacebook();
@@ -68,6 +69,7 @@ static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptio
LLPanelSnapshotOptions::LLPanelSnapshotOptions()
{
mCommitCallbackRegistrar.add("Snapshot.SaveToProfile", boost::bind(&LLPanelSnapshotOptions::onSaveToProfile, this));
+ mCommitCallbackRegistrar.add("Snapshot.SaveToEmail", boost::bind(&LLPanelSnapshotOptions::onSaveToEmail, this));
mCommitCallbackRegistrar.add("Snapshot.SaveToInventory", boost::bind(&LLPanelSnapshotOptions::onSaveToInventory, this));
mCommitCallbackRegistrar.add("Snapshot.SaveToComputer", boost::bind(&LLPanelSnapshotOptions::onSaveToComputer, this));
mCommitCallbackRegistrar.add("Snapshot.SendToFacebook", boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));
@@ -118,6 +120,11 @@ void LLPanelSnapshotOptions::onSaveToProfile()
openPanel("panel_snapshot_profile");
}
+void LLPanelSnapshotOptions::onSaveToEmail()
+{
+ openPanel("panel_snapshot_postcard");
+}
+
void LLPanelSnapshotOptions::onSaveToInventory()
{
openPanel("panel_snapshot_inventory");
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
new file mode 100755
index 0000000000..8e37b1418c
--- /dev/null
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -0,0 +1,244 @@
+/**
+ * @file llpanelsnapshotpostcard.cpp
+ * @brief Postcard sending panel.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcombobox.h"
+#include "llnotificationsutil.h"
+#include "llsidetraypanelcontainer.h"
+#include "llsliderctrl.h"
+#include "llspinctrl.h"
+#include "lltexteditor.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
+#include "llpanelsnapshot.h"
+#include "llpostcard.h"
+#include "llviewercontrol.h" // gSavedSettings
+#include "llviewerwindow.h"
+
+#include <boost/regex.hpp>
+
+/**
+ * Sends postcard via email.
+ */
+class LLPanelSnapshotPostcard
+: public LLPanelSnapshot
+{
+ LOG_CLASS(LLPanelSnapshotPostcard);
+
+public:
+ LLPanelSnapshotPostcard();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ S32 notify(const LLSD& info);
+
+private:
+ /*virtual*/ std::string getWidthSpinnerName() const { return "postcard_snapshot_width"; }
+ /*virtual*/ std::string getHeightSpinnerName() const { return "postcard_snapshot_height"; }
+ /*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; }
+ /*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; }
+ /*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; }
+ /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; }
+ /*virtual*/ void updateControls(const LLSD& info);
+
+ bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
+ void sendPostcard();
+
+ void onMsgFormFocusRecieved();
+ void onFormatComboCommit(LLUICtrl* ctrl);
+ void onQualitySliderCommit(LLUICtrl* ctrl);
+ void onSend();
+
+ bool mHasFirstMsgFocus;
+ std::string mAgentEmail;
+};
+
+static LLPanelInjector<LLPanelSnapshotPostcard> panel_class("llpanelsnapshotpostcard");
+
+LLPanelSnapshotPostcard::LLPanelSnapshotPostcard()
+: mHasFirstMsgFocus(false)
+{
+ mCommitCallbackRegistrar.add("Postcard.Send", boost::bind(&LLPanelSnapshotPostcard::onSend, this));
+ mCommitCallbackRegistrar.add("Postcard.Cancel", boost::bind(&LLPanelSnapshotPostcard::cancel, this));
+
+}
+
+// virtual
+BOOL LLPanelSnapshotPostcard::postBuild()
+{
+ // pick up the user's up-to-date email address
+ gAgent.sendAgentUserInfoRequest();
+
+ std::string name_string;
+ LLAgentUI::buildFullname(name_string);
+ getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string));
+
+ // For the first time a user focuses to .the msg box, all text will be selected.
+ getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this));
+
+ getChild<LLUICtrl>("to_form")->setFocus(TRUE);
+
+ getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onQualitySliderCommit, this, _1));
+
+ return LLPanelSnapshot::postBuild();
+}
+
+// virtual
+void LLPanelSnapshotPostcard::onOpen(const LLSD& key)
+{
+ LLPanelSnapshot::onOpen(key);
+}
+
+// virtual
+S32 LLPanelSnapshotPostcard::notify(const LLSD& info)
+{
+ if (!info.has("agent-email"))
+ {
+ llassert(info.has("agent-email"));
+ return 0;
+ }
+
+ if (mAgentEmail.empty())
+ {
+ mAgentEmail = info["agent-email"].asString();
+ }
+
+ return 1;
+}
+
+// virtual
+void LLPanelSnapshotPostcard::updateControls(const LLSD& info)
+{
+ getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality"));
+ updateImageQualityLevel();
+
+ const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true;
+ getChild<LLUICtrl>("send_btn")->setEnabled(have_snapshot);
+}
+
+bool LLPanelSnapshotPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if(0 == option)
+ {
+ // User clicked OK
+ if((getChild<LLUICtrl>("subject_form")->getValue().asString()).empty())
+ {
+ // Stuff the subject back into the form.
+ getChild<LLUICtrl>("subject_form")->setValue(getString("default_subject"));
+ }
+
+ if (!mHasFirstMsgFocus)
+ {
+ // The user never switched focus to the message window.
+ // Using the default string.
+ getChild<LLUICtrl>("msg_form")->setValue(getString("default_message"));
+ }
+
+ sendPostcard();
+ }
+ return false;
+}
+
+
+void LLPanelSnapshotPostcard::sendPostcard()
+{
+ std::string to(getChild<LLUICtrl>("to_form")->getValue().asString());
+ std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString());
+
+ LLSD postcard = LLSD::emptyMap();
+ postcard["pos-global"] = LLFloaterSnapshot::getPosTakenGlobal().getValue();
+ postcard["to"] = to;
+ postcard["from"] = mAgentEmail;
+ postcard["name"] = getChild<LLUICtrl>("name_form")->getValue().asString();
+ postcard["subject"] = subject;
+ postcard["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString();
+ LLPostCard::send(LLFloaterSnapshot::getImageData(), postcard);
+
+ // Give user feedback of the event.
+ gViewerWindow->playSnapshotAnimAndSound();
+
+ LLFloaterSnapshot::postSave();
+}
+
+void LLPanelSnapshotPostcard::onMsgFormFocusRecieved()
+{
+ LLTextEditor* msg_form = getChild<LLTextEditor>("msg_form");
+ if (msg_form->hasFocus() && !mHasFirstMsgFocus)
+ {
+ mHasFirstMsgFocus = true;
+ msg_form->setText(LLStringUtil::null);
+ }
+}
+
+void LLPanelSnapshotPostcard::onFormatComboCommit(LLUICtrl* ctrl)
+{
+ // will call updateControls()
+ LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true));
+}
+
+void LLPanelSnapshotPostcard::onQualitySliderCommit(LLUICtrl* ctrl)
+{
+ updateImageQualityLevel();
+
+ LLSliderCtrl* slider = (LLSliderCtrl*)ctrl;
+ S32 quality_val = llfloor((F32)slider->getValue().asReal());
+ LLSD info;
+ info["image-quality-change"] = quality_val;
+ LLFloaterSnapshot::getInstance()->notify(info); // updates the "SnapshotQuality" setting
+}
+
+void LLPanelSnapshotPostcard::onSend()
+{
+ // Validate input.
+ std::string to(getChild<LLUICtrl>("to_form")->getValue().asString());
+
+ boost::regex email_format("[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,})*");
+
+ if (to.empty() || !boost::regex_match(to, email_format))
+ {
+ LLNotificationsUtil::add("PromptRecipientEmail");
+ return;
+ }
+
+ if (mAgentEmail.empty() || !boost::regex_match(mAgentEmail, email_format))
+ {
+ LLNotificationsUtil::add("PromptSelfEmail");
+ return;
+ }
+
+ std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString());
+ if(subject.empty() || !mHasFirstMsgFocus)
+ {
+ LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLPanelSnapshotPostcard::missingSubjMsgAlertCallback, this, _1, _2));
+ return;
+ }
+
+ // Send postcard.
+ sendPostcard();
+}
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 318d1e2861..fbbbead264 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -86,7 +86,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
mNeedsFlash(TRUE),
mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
mDataSize(0),
- mSnapshotType(SNAPSHOT_LOCAL),
+ mSnapshotType(SNAPSHOT_POSTCARD),
mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
mSnapshotUpToDate(FALSE),
mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index f479de59d4..fed33bf37c 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -42,7 +42,7 @@ class LLSnapshotLivePreview : public LLView
public:
enum ESnapshotType
{
- SNAPSHOT_POSTCARD_DEPRECIATED,
+ SNAPSHOT_POSTCARD,
SNAPSHOT_TEXTURE,
SNAPSHOT_LOCAL,
SNAPSHOT_WEB
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 092fa5501d..4e9144ac26 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -7122,6 +7122,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**)
msg->getString( "UserData", "DirectoryVisibility", dir_visibility);
LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email);
+ LLFloaterSnapshot::setAgentEmail(email);
}
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..ead56f2885
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Postkarte aus [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ Sehen Sie mal!
+ </string>
+ <string name="upload_message">
+ Senden...
+ </string>
+ <text name="title">
+ E-Mail
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Nachricht"/>
+ <panel name="panel_postcard_settings" label="Einstellungen"/>
+ </tab_container>
+ <button name="cancel_btn" label="Abbrechen"/>
+ <button name="send_btn" label="Absenden"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 514fb058b9..76adaad57c 100755
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -267,6 +267,12 @@
name="panel_snapshot_profile"
filename="panel_snapshot_profile.xml" />
<panel
+ class="llpanelsnapshotpostcard"
+ follows="all"
+ layout="topleft"
+ name="panel_snapshot_postcard"
+ filename="panel_snapshot_postcard.xml" />
+ <panel
class="llpanelsnapshotinventory"
follows="all"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
index cb29e6a87a..265217ef60 100755
--- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
@@ -107,4 +107,21 @@
<button.commit_callback
function="Snapshot.SendToFlickr"/>
</button>
+ <button
+ follows="left|top"
+ font="SansSerif"
+ halign="left"
+ height="22"
+ image_overlay="Snapshot_Email"
+ image_overlay_alignment="left"
+ image_top_pad="0"
+ imgoverlay_label_space="10"
+ label="Send via E-mail"
+ layout="topleft"
+ left_delta="0"
+ name="save_to_email_btn"
+ top_pad="5">
+ <button.commit_callback
+ function="Snapshot.SaveToEmail" />
+ </button>
</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..975b08be05
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="380"
+ layout="topleft"
+ name="panel_snapshot_postcard"
+ width="490">
+ <string
+ name="default_subject">
+ Postcard from [SECOND_LIFE].
+ </string>
+ <string
+ name="default_message">
+ Check this out!
+ </string>
+ <string
+ name="upload_message">
+ Sending...
+ </string>
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Snapshot_Email"
+ layout="topleft"
+ left="12"
+ mouse_opaque="true"
+ name="title_icon"
+ top="7"
+ width="18" />
+ <text
+ follows="top|left|right"
+ font="SansSerifBold"
+ height="14"
+ layout="topleft"
+ left_pad="12"
+ length="1"
+ name="title"
+ right="-10"
+ text_color="white"
+ type="string"
+ top_delta="2">
+ E-mail
+ </text>
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="9"
+ layout="topleft"
+ name="hr"
+ right="-5"
+ top_pad="5"
+ />
+ <tab_container
+ name="postcard_tabs"
+ tab_group="1"
+ tab_min_width="97"
+ tab_height="21"
+ tab_position="top"
+ top_pad="7"
+ left="5"
+ right="-2"
+ height="319"
+ follows="all"
+ halign="center"
+ use_highlighting_on_hover="true">
+ <panel
+ follows="all"
+ layout="topleft"
+ label="Message"
+ name="panel_postcard_message"
+ filename="panel_postcard_message.xml" />
+ <panel
+ follows="all"
+ layout="topleft"
+ label="Settings"
+ name="panel_postcard_settings"
+ filename="panel_postcard_settings.xml" />
+ </tab_container>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-6"
+ bottom="-20"
+ width="97">
+ <button.commit_callback
+ function="Postcard.Cancel" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Send"
+ layout="topleft"
+ left="10"
+ name="send_btn"
+ top_delta="0"
+ width="97">
+ <button.commit_callback
+ function="Postcard.Send" />
+ </button>
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..81a067a81b
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Postal desde [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ ¡Mira esto!
+ </string>
+ <string name="upload_message">
+ Enviando...
+ </string>
+ <text name="title">
+ Correo-e
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Mensaje"/>
+ <panel name="panel_postcard_settings" label="Ajustes"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..3f5ef04022
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Carte postale de [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ Ouvrez-moi !
+ </string>
+ <string name="upload_message">
+ Envoi en cours...
+ </string>
+ <text name="title">
+ E-mail
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Message"/>
+ <panel name="panel_postcard_settings" label="Paramètres"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..333ce5c12b
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Cartolina da [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ Dai un&apos;occhiata!
+ </string>
+ <string name="upload_message">
+ Invio...
+ </string>
+ <text name="title">
+ E-mail
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Messaggio"/>
+ <panel name="panel_postcard_settings" label="Impostazioni"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..756df9ecc2
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ [SECOND_LIFE] からのポストカードです。
+ </string>
+ <string name="default_message">
+ ぜひご覧ください!
+ </string>
+ <string name="upload_message">
+ 送信中...
+ </string>
+ <text name="title">
+ メール
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="メッセージ"/>
+ <panel name="panel_postcard_settings" label="設定"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..efcbec66ba
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Postal do [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ Confira!
+ </string>
+ <string name="upload_message">
+ Enviando...
+ </string>
+ <text name="title">
+ E-mail
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Mensagem"/>
+ <panel name="panel_postcard_settings" label="Configurações"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..6e1b3a7516
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ Открытка из [SECOND_LIFE].
+ </string>
+ <string name="default_message">
+ Побывай здесь!
+ </string>
+ <string name="upload_message">
+ Отправка...
+ </string>
+ <text name="title">
+ Электронное письмо
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="Сообщение"/>
+ <panel name="panel_postcard_settings" label="Настройки"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..9b9e60d2e0
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ SECOND_LIFE]&apos;dan posta kartı.
+ </string>
+ <string name="default_message">
+ Buna bakın!
+ </string>
+ <string name="upload_message">
+ Gönderiyor...
+ </string>
+ <text name="title">
+ E-posta
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="İleti"/>
+ <panel name="panel_postcard_settings" label="Ayarlar"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml
new file mode 100755
index 0000000000..6dfeaf2505
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_snapshot_postcard">
+ <string name="default_subject">
+ 來自 [SECOND_LIFE] 的明信片。
+ </string>
+ <string name="default_message">
+ 快來看看這個!
+ </string>
+ <string name="upload_message">
+ 傳送中...
+ </string>
+ <text name="title">
+ 電郵
+ </text>
+ <tab_container name="postcard_tabs">
+ <panel name="panel_postcard_message" label="訊息"/>
+ <panel name="panel_postcard_settings" label="設定"/>
+</panel>