phoenix-firestorm/indra/newview/kvfloaterflickrupload.cpp

326 lines
10 KiB
C++

/**
* @file kvfloaterflickrupload.cpp
* @brief Flickr upload floater
* @copyright Copyright (c) 2011 Katharine Berry
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
*/
#include "llviewerprecompiledheaders.h"
#include "kvfloaterflickrupload.h"
#include "llagent.h"
#include "llfloaterreg.h"
#include "llfloatersnapshot.h"
#include "llgl.h"
#include "llimage.h"
#include "llnotificationsutil.h"
#include "llslurl.h"
#include "llui.h"
#include "lluploaddialog.h"
#include "llviewercontrol.h"
#include "llviewerregion.h"
#include "llviewertexture.h"
#include "llworld.h"
#include "kvflickr.h"
#include "kvfloaterflickrauth.h"
#include <boost/bind.hpp>
KVFloaterFlickrUpload::KVFloaterFlickrUpload(const LLSD& key) : LLFloater(key),
mCompressedImage(NULL),
mViewerImage(NULL)
{
}
KVFloaterFlickrUpload::~KVFloaterFlickrUpload()
{
mCompressedImage = NULL;
mViewerImage = NULL;
}
// static
KVFloaterFlickrUpload* KVFloaterFlickrUpload::showFromSnapshot(LLImageFormatted *compressed, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global)
{
// Take the images from the caller
// It's now our job to clean them up
KVFloaterFlickrUpload* instance = LLFloaterReg::showTypedInstance<KVFloaterFlickrUpload>("flickr_upload", LLSD(img->getID()));
instance->mCompressedImage = compressed;
instance->mViewerImage = img;
instance->mImageScale = img_scale;
instance->mPosTakenGlobal = pos_taken_global;
return instance;
}
BOOL KVFloaterFlickrUpload::postBuild()
{
// Set the various UI fields to their default values.
childSetValue("rating_combo", gSavedSettings.getLLSD("KittyFlickrLastRating"));
childSetValue("tags_form", gSavedSettings.getLLSD("KittyFlickrLastTags"));
childSetValue("show_position_check", gSavedSettings.getLLSD("KittyFlickrShowPosition"));
// Connect the buttons up
childSetAction("cancel_btn", onClickCancel, this);
childSetAction("upload_btn", onClickUpload, this);
// Check that we actually can do an upload.
LLSD query;
query["auth_token"] = gSavedPerAccountSettings.getLLSD("KittyFlickrToken");
KVFlickrRequest::request("flickr.auth.checkToken", query, boost::bind(&KVFloaterFlickrUpload::confirmToken, this, _1, _2));
return true;
}
void KVFloaterFlickrUpload::confirmToken(bool success, const LLSD &response)
{
if(!success)
{
LLNotificationsUtil::add("KittyFlickrHTTPFail");
closeFloater(false);
return;
}
if(response["stat"].asString() == "ok")
{
// Just in case the username changed. This can happen.
std::string username = response["auth"]["user"]["username"];
gSavedPerAccountSettings.setString("KittyFlickrUsername", username);
childSetValue("account_name", username);
childSetEnabled("upload_btn", true);
}
else
{
// Uh oh.
if(response["code"].asInteger() == 98) // Invalid auth token
{
// Mark the account as invalid
childSetValue("account_name", getString("no_account"));
// Need to authenticate.
gSavedPerAccountSettings.setString("KittyFlickrToken", "");
gSavedPerAccountSettings.setString("KittyFlickrUsername", "");
gSavedPerAccountSettings.setString("KittyFlickrNSID", "");
KVFloaterFlickrAuth *floater = KVFloaterFlickrAuth::showFloater(boost::bind(&KVFloaterFlickrUpload::authCallback, this, _1));
// Link it to us to protect it from freeze frame mode, if need be.
if(floater && getDependee()) // (if we're depending on something, so should it)
{
gFloaterView->removeChild(floater);
gSnapshotFloaterView->addChild(floater);
// Even though we don't really want this to depend on the snapshot view
// being open, if we manipulate it after closing the snapshot view,
// it will crash.
getDependee()->addDependentFloater(floater, false);
}
LLNotificationsUtil::add("KittyFlickrTokenRejected");
}
else
{
LLSD args;
args["CODE"] = response["code"];
args["ERROR"] = response["message"];
LLNotificationsUtil::add("KittyFlickrGenericFail", args);
}
}
}
void KVFloaterFlickrUpload::authCallback(bool authorised)
{
if(authorised)
{
childSetValue("account_name", gSavedPerAccountSettings.getString("KittyFlickrUsername"));
childSetEnabled("upload_btn", true);
}
else
{
LLNotificationsUtil::add("KittyFlickrUploadCancelledAuthRejected");
closeFloater(false);
}
}
void KVFloaterFlickrUpload::saveSettings()
{
gSavedSettings.setS32("KittyFlickrLastRating", childGetValue("rating_combo"));
gSavedSettings.setString("KittyFlickrLastTags", childGetValue("tags_form"));
gSavedSettings.setBOOL("KittyFlickrShowPosition", childGetValue("show_position_check"));
}
void KVFloaterFlickrUpload::uploadSnapshot()
{
mTitle = childGetValue("title_form").asString();
LLSD params;
params["title"] = childGetValue("title_form");
params["safety_level"] = childGetValue("rating_combo");
std::string tags = childGetValue("tags_form");
std::string description = childGetValue("description_form");
if(childGetValue("show_position_check").asBoolean())
{
// Work out where this was taken.
LLVector3d clamped_global = LLWorld::getInstance()->clipToVisibleRegions(gAgent.getPositionGlobal(), mPosTakenGlobal);
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(clamped_global);
if(!region)
{
// Clamping failed? Shouldn't happen.
// Use the agent's position instead; if the region the agent is in doesn't exist we have some serious issues,
// and crashing is an entirely reasonable thing to do.
region = gAgent.getRegion();
clamped_global = gAgent.getPositionGlobal();
}
std::string region_name = region->getName();
LLVector3 region_pos = region->getPosRegionFromGlobal(clamped_global);
std::ostringstream region_tags;
region_tags << " \"secondlife:region=" << region_name << "\"";
region_tags << " secondlife:x=" << llround(region_pos[VX]);
region_tags << " secondlife:y=" << llround(region_pos[VY]);
region_tags << " secondlife:z=" << llround(region_pos[VZ]);
// Now let's give some precise camera values.
region_tags << " secondlife:camera_pos_x=" << (mPosTakenGlobal[VX] - region->getOriginGlobal()[VX]);
region_tags << " secondlife:camera_pos_y=" << (mPosTakenGlobal[VY] - region->getOriginGlobal()[VY]);
region_tags << " secondlife:camera_pos_z=" << mPosTakenGlobal[VZ];
tags += region_tags.str();
// Include an SLurl in the description, too (maybe).
if(gSavedSettings.getBOOL("KittyFlickrIncludeSLURL"))
{
LLSLURL url(region_name, region_pos);
std::ostringstream region_desc;
region_desc << "<em><a href='" << url.getSLURLString() << "'>";
region_desc << "Taken at " << region_name << " (";
region_desc << llround(region_pos[VX]) << ", ";
region_desc << llround(region_pos[VY]) << ", ";
region_desc << llround(region_pos[VZ]) << ")";
region_desc << "</a></em>";
if(description != "")
{
description += "\n\n";
}
description += region_desc.str();
}
}
params["tags"] = tags;
params["description"] = description;
LL_INFOS("FlickrAPI") << "Uploading snapshot with metadata: " << params << LL_ENDL;
params["auth_token"] = gSavedPerAccountSettings.getLLSD("KittyFlickrToken");
LLUploadDialog::modalUploadDialog(getString("uploading"));
KVFlickrRequest::uploadPhoto(params, mCompressedImage, boost::bind(&KVFloaterFlickrUpload::imageUploaded, this, _1, _2));
}
void KVFloaterFlickrUpload::imageUploaded(bool success, const LLSD& response)
{
LLUploadDialog::modalUploadFinished();
LLSD args;
args["TITLE"] = mTitle;
if(success)
{
args["ID"] = response["photoid"];
LLNotificationsUtil::add("KittyFlickrUploadComplete", args);
}
else if(response.has("stat"))
{
args["CODE"] = response["code"];
args["ERROR"] = response["msg"];
LLNotificationsUtil::add("KittyFlickrUploadFailed", args);
}
else
{
LLNotificationsUtil::add("KittyFlickrUploadFailedNoError");
}
// We're pretty much done now.
closeFloater(false);
}
// This function stolen from LLFloaterPostcard
void KVFloaterFlickrUpload::draw()
{
LLGLSUIDefault gls_ui;
LLFloater::draw();
if(!isMinimized() && mViewerImage.notNull() && mCompressedImage.notNull())
{
LLRect rect(getRect());
// first set the max extents of our preview
rect.translate(-rect.mLeft, -rect.mBottom);
rect.mLeft += 280;
rect.mRight -= 10;
rect.mTop -= 27;
rect.mBottom = rect.mTop - 130;
// then fix the aspect ratio
F32 ratio = (F32)mCompressedImage->getWidth() / (F32)mCompressedImage->getHeight();
if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
{
rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
}
else
{
rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
}
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
rect.stretch(-1);
}
{
glMatrixMode(GL_TEXTURE);
glPushMatrix();
{
glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
glMatrixMode(GL_MODELVIEW);
gl_draw_scaled_image(rect.mLeft,
rect.mBottom,
rect.getWidth(),
rect.getHeight(),
mViewerImage.get(),
LLColor4::white);
}
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
}
}
//static
void KVFloaterFlickrUpload::onClickCancel(void* data)
{
if(data)
{
KVFloaterFlickrUpload *self = (KVFloaterFlickrUpload*)data;
self->closeFloater(false);
}
}
//static
void KVFloaterFlickrUpload::onClickUpload(void* data)
{
if(!data)
return;
KVFloaterFlickrUpload *self = (KVFloaterFlickrUpload*)data;
self->uploadSnapshot();
self->saveSettings();
self->setVisible(false);
// Make sure that, if we were attached to anything, that we detach from it.
// Otherwise bad things happen.
LLFloater *dependee = self->getDependee();
if(dependee)
dependee->removeDependentFloater(self);
}