From 91304d3477d433bdf15d19ce08a5b54479634bcd Mon Sep 17 00:00:00 2001
From: Mnikolenko ProductEngine <mnikolenko@productengine.com>
Date: Thu, 7 May 2015 16:22:44 +0300
Subject: MAINT-4812 Restore sending snapshot as email from the viewer.

---
 indra/newview/CMakeLists.txt                       |   1 +
 indra/newview/llfloatersnapshot.cpp                |  30 ++-
 indra/newview/llfloatersnapshot.h                  |   1 +
 indra/newview/llpanelsnapshotoptions.cpp           |   7 +
 indra/newview/llpanelsnapshotpostcard.cpp          | 244 +++++++++++++++++++++
 indra/newview/llsnapshotlivepreview.cpp            |   2 +-
 indra/newview/llsnapshotlivepreview.h              |   2 +-
 indra/newview/llviewermessage.cpp                  |   1 +
 .../default/xui/de/panel_snapshot_postcard.xml     |  21 ++
 .../skins/default/xui/en/floater_snapshot.xml      |   6 +
 .../default/xui/en/panel_snapshot_options.xml      |  17 ++
 .../default/xui/en/panel_snapshot_postcard.xml     | 103 +++++++++
 .../default/xui/es/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/fr/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/it/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/ja/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/pt/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/ru/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/tr/panel_snapshot_postcard.xml     |  18 ++
 .../default/xui/zh/panel_snapshot_postcard.xml     |  18 ++
 20 files changed, 575 insertions(+), 4 deletions(-)
 create mode 100755 indra/newview/llpanelsnapshotpostcard.cpp
 create mode 100755 indra/newview/skins/default/xui/de/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/es/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/fr/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/it/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/ja/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/pt/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/ru/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/tr/panel_snapshot_postcard.xml
 create mode 100755 indra/newview/skins/default/xui/zh/panel_snapshot_postcard.xml

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
@@ -266,6 +266,12 @@
        layout="topleft"
        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"
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>
-- 
cgit v1.2.3