From ece98188a8e5c76adddf884886f44b6fc9c5ae21 Mon Sep 17 00:00:00 2001 From: dolphin Date: Fri, 6 Sep 2013 17:09:50 -0700 Subject: Added profile editing to the experience profile floater. --- indra/newview/llfloaterexperienceprofile.cpp | 353 ++++++++-- indra/newview/llfloaterexperienceprofile.h | 31 +- indra/newview/llviewerregion.cpp | 4 +- .../default/xui/en/floater_experienceprofile.xml | 757 +++++++++++++-------- 4 files changed, 811 insertions(+), 334 deletions(-) diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 895fd5ee4d..292f6f0952 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -27,19 +27,25 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" #include "llexpandabletextbox.h" #include "llexperiencecache.h" #include "llfloaterexperienceprofile.h" #include "llfloaterreg.h" +#include "llhttpclient.h" #include "lllayoutstack.h" #include "llsdserialize.h" #include "llslurl.h" +#include "lltabcontainer.h" #include "lltextbox.h" #include "lltexturectrl.h" #include "lltrans.h" #include "llviewerregion.h" -#include "llagent.h" -#include "llhttpclient.h" +#include "lllineeditor.h" +#include "llcombobox.h" +#include "llcheckboxctrl.h" +#include "llnotificationsutil.h" +#include "llappviewer.h" #define XML_PANEL_EXPERIENCE_PROFILE "floater_experienceprofile.xml" #define TF_NAME "experience_title" @@ -48,6 +54,7 @@ #define TF_MRKT "marketplace" #define TF_MATURITY "ContentRatingText" #define TF_OWNER "OwnerText" +#define EDIT "edit_" #define IMG_LOGO "logo" @@ -60,6 +67,10 @@ #define BTN_ALLOW "allow_btn" #define BTN_FORGET "forget_btn" #define BTN_BLOCK "block_btn" +#define BTN_CANCEL "cancel_btn" +#define BTN_SAVE "save_btn" +#define BTN_ENABLE "enable_btn" +#define BTN_PRIVATE "private_btn" LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data) @@ -69,78 +80,97 @@ LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data) , mDescriptionPanel(NULL) , mLocationPanel(NULL) , mMarketplacePanel(NULL) + , mSaveCompleteAction(NOTHING) + , mDirty(false) + , mForceClose(false) { } + LLFloaterExperienceProfile::~LLFloaterExperienceProfile() { } -class ExperiencePreferencesResponder : public LLHTTPClient::Responder +template +class HandleResponder : public LLHTTPClient::Responder { public: - ExperiencePreferencesResponder(const LLHandle& parent):mParent(parent) + HandleResponder(const LLHandle& parent):mParent(parent){} + LLHandle mParent; + + virtual void error(U32 status, const std::string& reason) { + llwarns << "HandleResponder failed with code: " << status<< ", reason: " << reason << llendl; } +}; - LLHandle mParent; +class ExperienceUpdateResponder : public HandleResponder +{ +public: + ExperienceUpdateResponder(const LLHandle& parent):HandleResponder(parent) + { + } virtual void result(const LLSD& content) { LLFloaterExperienceProfile* parent=mParent.get(); if(parent) { - parent->setPreferences(content); + parent->onSaveComplete(content); } } - virtual void error(U32 status, const std::string& reason) - { - lldebugs << "ExperiencePreferencesResponder failed with code: " << status<< ", reason: " << reason << llendl; - } }; -class IsAdminResponder : public LLHTTPClient::Responder + +class ExperiencePreferencesResponder : public HandleResponder { public: - IsAdminResponder(const LLHandle& parent):mParent(parent) + ExperiencePreferencesResponder(const LLHandle& parent):HandleResponder(parent) + { + } + + + virtual void result(const LLSD& content) { + LLFloaterExperienceProfile* parent=mParent.get(); + if(parent) + { + parent->setPreferences(content); + } } +}; - LLHandle mParent; +class IsAdminResponder : public HandleResponder +{ +public: + IsAdminResponder(const LLHandle& parent):HandleResponder(parent) + { + } + virtual void result(const LLSD& content) { LLFloaterExperienceProfile* parent = mParent.get(); if(!parent) return; - - LLButton* edit=parent->getChild(BTN_EDIT); - if(content.has("experience_ids")) + bool enabled = true; + LLViewerRegion* region = gAgent.getRegion(); + if (!region) { - LLUUID id=parent->getKey().asUUID(); - const LLSD& xp_ids = content["experience_ids"]; - LLSD::array_const_iterator it = xp_ids.beginArray(); - while(it != xp_ids.endArray()) - { - if(it->asUUID() == id) - { - edit->setVisible(TRUE); - return; - } - ++it; - } + enabled = false; } - edit->setVisible(FALSE); - - //parent->getChild(BTN_EDIT)->setVisible(content["status"].asBoolean()); - } - virtual void error(U32 status, const std::string& reason) - { - lldebugs << "IsAdminResponder failed with code: " << status<< ", reason: " << reason << llendl; + else + { + std::string url=region->getCapability("UpdateExperience"); + if(url.empty()) + enabled = false; + } + + parent->getChild(BTN_EDIT)->setVisible(enabled && content["status"].asBoolean()); } }; @@ -160,16 +190,10 @@ BOOL LLFloaterExperienceProfile::postBuild() LLViewerRegion* region = gAgent.getRegion(); if (region) { - // std::string lookup_url=region->getCapability("IsExperienceAdmin"); - // if(!lookup_url.empty()) - // { - // LLHTTPClient::get(lookup_url+"/"+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle())); - // } - - std::string lookup_url=region->getCapability("GetAdminExperiences"); + std::string lookup_url=region->getCapability("IsExperienceAdmin"); if(!lookup_url.empty()) { - LLHTTPClient::get(lookup_url, new IsAdminResponder(getDerivedHandle())); + LLHTTPClient::get(lookup_url+"?experience_id="+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle())); } lookup_url=region->getCapability("ExperiencePreferences"); @@ -180,14 +204,25 @@ BOOL LLFloaterExperienceProfile::postBuild() } } - - - childSetAction(BTN_EDIT, boost::bind(&LLFloaterExperienceProfile::onClickEdit, this)); childSetAction(BTN_ALLOW, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Allow")); childSetAction(BTN_FORGET, boost::bind(&LLFloaterExperienceProfile::onClickForget, this)); childSetAction(BTN_BLOCK, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Block")); + childSetAction(BTN_CANCEL, boost::bind(&LLFloaterExperienceProfile::onClickCancel, this)); + childSetAction(BTN_SAVE, boost::bind(&LLFloaterExperienceProfile::onClickSave, this)); + + + getChild(EDIT TF_NAME)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_DESC)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_SLURL)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_MATURITY)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_MRKT)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_NAME)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + childSetAction(EDIT BTN_ENABLE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + childSetAction(EDIT BTN_PRIVATE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); + getChild(EDIT TF_DESC)->setCommitOnFocusLost(TRUE); + return TRUE; } @@ -202,7 +237,20 @@ void LLFloaterExperienceProfile::experienceCallback(LLHandle("tab_container"); + + tabs->selectTabByName("edit_panel_experience_info"); +} + + +void LLFloaterExperienceProfile::onClickCancel() +{ + changeToView(); +} +void LLFloaterExperienceProfile::onClickSave() +{ + doSave(NOTHING); } @@ -238,7 +286,7 @@ void LLFloaterExperienceProfile::onClickForget() LLHTTPClient::del(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(getDerivedHandle())); } -bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child ) +bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo ) { LLStyle::Params style; std::string access; @@ -246,16 +294,19 @@ bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* chil { style.image(LLUI::getUIImage(getString("maturity_icon_general"))); access = LLTrans::getString("SIM_ACCESS_PG"); + combo->setCurrentByIndex(2); } else if(maturity <= SIM_ACCESS_MATURE) { style.image(LLUI::getUIImage(getString("maturity_icon_moderate"))); access = LLTrans::getString("SIM_ACCESS_MATURE"); + combo->setCurrentByIndex(1); } else if(maturity <= SIM_ACCESS_ADULT) { style.image(LLUI::getUIImage(getString("maturity_icon_adult"))); access = LLTrans::getString("SIM_ACCESS_ADULT"); + combo->setCurrentByIndex(0); } else { @@ -286,29 +337,38 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience ) LLTextBox* child = getChild(TF_NAME); child->setText(experience[LLExperienceCache::NAME].asString()); - + + LLLineEditor* linechild = getChild(EDIT TF_NAME); + linechild->setText(experience[LLExperienceCache::NAME].asString()); + std::string value = experience[LLExperienceCache::DESCRIPTION].asString(); LLExpandableTextBox* exchild = getChild(TF_DESC); exchild->setText(value); mDescriptionPanel->setVisible(value.length()>0); + + LLTextEditor* edit_child = getChild(EDIT TF_DESC); + edit_child->setText(value); value = experience[LLExperienceCache::SLURL].asString(); child = getChild(TF_SLURL); child->setText(value); mLocationPanel->setVisible(value.length()>0); + + linechild = getChild(EDIT TF_SLURL); + linechild->setText(value); - child = getChild(TF_MATURITY); - setMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger()), child); + setMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger()), getChild(TF_MATURITY), getChild(EDIT TF_MATURITY)); child = getChild(TF_OWNER); - LLUUID id = experience[LLExperienceCache::OWNER_ID].asUUID(); - if(experience[LLExperienceCache::GROUP_ID].asUUID() == id) + LLUUID id = experience[LLExperienceCache::GROUP_ID].asUUID(); + if(id.notNull()) { value = LLSLURL("group", id, "inspect").getSLURLString(); } else { + id = experience[LLExperienceCache::AGENT_ID].asUUID(); value = LLSLURL("agent", id, "inspect").getSLURLString(); } child->setText(value); @@ -324,6 +384,7 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience ) std::istringstream is(value); if(LLSDParser::PARSE_FAILURE != parser->parse(is, data, value.size())) { + value=""; if(data.has(TF_MRKT)) { value=data[TF_MRKT].asString(); @@ -336,21 +397,31 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience ) { mMarketplacePanel->setVisible(FALSE); } + + linechild = getChild(EDIT TF_MRKT); + linechild->setText(value); if(data.has(IMG_LOGO)) { LLTextureCtrl* logo = getChild(IMG_LOGO); logo->setImageAssetID(data[IMG_LOGO].asUUID()); mImagePanel->setVisible(TRUE); + + logo = getChild(EDIT IMG_LOGO); + logo->setImageAssetID(data[IMG_LOGO].asUUID()); } } - - - + LLCheckBoxCtrl* enable = getChild(EDIT BTN_ENABLE); + enable->set( 0 == (mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger() & LLExperienceCache::PROPERTY_DISABLED)); + enable = getChild(EDIT BTN_PRIVATE); + enable->set( 0 != (mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger() & LLExperienceCache::PROPERTY_PRIVATE)); - + mDirty=false; + setCanClose(!mDirty); + + getChild(BTN_SAVE)->setEnabled(mDirty); } void LLFloaterExperienceProfile::setPreferences( const LLSD& content ) @@ -402,3 +473,173 @@ void LLFloaterExperienceProfile::setPreferences( const LLSD& content ) button=getChild(BTN_BLOCK); button->setEnabled(TRUE); } + +void LLFloaterExperienceProfile::onFieldChanged() +{ + mDirty=true; + setCanClose(!mDirty); + getChild(BTN_SAVE)->setEnabled(mDirty); +} + + +BOOL LLFloaterExperienceProfile::canClose() +{ + if(mForceClose || !mDirty) + { + return TRUE; + } + else + { + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, CLOSE)); + return FALSE; + } +} + +bool LLFloaterExperienceProfile::handleSaveChangesDialog( const LLSD& notification, const LLSD& response, int action ) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + // close after saving + doSave( action ); + break; + + case 1: // "No" + if(action != NOTHING) + { + mForceClose = TRUE; + if(action==CLOSE) + { + closeFloater(); + } + else + { + changeToView(); + } + } + break; + + case 2: // "Cancel" + default: + // If we were quitting, we didn't really mean it. + LLAppViewer::instance()->abortQuit(); + break; + } + return false; +} + +void LLFloaterExperienceProfile::doSave( int success_action ) +{ + mSaveCompleteAction=success_action; + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return; + + std::string url=region->getCapability("UpdateExperience"); + if(url.empty()) + return; + + LLSD package=mExperienceDetails; + + package[LLExperienceCache::NAME] = getChild(EDIT TF_NAME)->getText(); + package[LLExperienceCache::DESCRIPTION] = getChild(EDIT TF_DESC)->getText(); + package[LLExperienceCache::SLURL] = getChild(EDIT TF_SLURL)->getText(); + + package[LLExperienceCache::MATURITY] = getChild(EDIT TF_MATURITY)->getSelectedValue().asInteger(); + + LLSD metadata; + + metadata[TF_MRKT] = getChild(EDIT TF_MRKT)->getText(); + metadata[IMG_LOGO] = getChild(EDIT IMG_LOGO)->getImageAssetID(); + + LLPointer formatter = new LLSDXMLFormatter(); + + std::ostringstream os; + if(formatter->format(metadata, os)) + { + package[LLExperienceCache::METADATA]=os.str(); + } + + int properties = package[LLExperienceCache::PROPERTIES].asInteger(); + LLCheckBoxCtrl* enable = getChild(EDIT BTN_ENABLE); + if(enable->get()) + { + properties &= ~LLExperienceCache::PROPERTY_DISABLED; + } + else + { + properties |= LLExperienceCache::PROPERTY_DISABLED; + } + + enable = getChild(EDIT BTN_PRIVATE); + if(enable->get()) + { + properties |= LLExperienceCache::PROPERTY_PRIVATE; + } + else + { + properties &= ~LLExperienceCache::PROPERTY_PRIVATE; + } + + package[LLExperienceCache::PROPERTIES] = properties; + + LLHTTPClient::post(url, package, new ExperienceUpdateResponder(getDerivedHandle())); +} + +void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) +{ + LLUUID id = getExperienceId(); + + if(!content.has("experience_keys")) + { + llwarns << "LLFloaterExperienceProfile::onSaveComplete called with bad content" << llendl; + return; + } + + const LLSD& experiences = content["experience_keys"]; + + LLSD::array_const_iterator it = experiences.beginArray(); + if(it == experiences.endArray()) + { + llwarns << "LLFloaterExperienceProfile::onSaveComplete called with empty content" << llendl; + return; + } + + if(!it->has(LLExperienceCache::EXPERIENCE_ID) || ((*it)[LLExperienceCache::EXPERIENCE_ID].asUUID() != id)) + { + llwarns << "LLFloaterExperienceProfile::onSaveComplete called with unexpected experience id" << llendl; + return; + } + + refreshExperience(*it); + LLExperienceCache::fetch(id, true); + + if(mSaveCompleteAction==VIEW) + { + LLTabContainer* tabs = getChild("tab_container"); + tabs->selectTabByName("panel_experience_info"); + } + else if(mSaveCompleteAction == CLOSE) + { + closeFloater(); + } +} + +void LLFloaterExperienceProfile::changeToView() +{ + if(mForceClose || !mDirty) + { + refreshExperience(mExperienceDetails); + LLTabContainer* tabs = getChild("tab_container"); + + tabs->selectTabByName("panel_experience_info"); + } + else + { + // Bring up view-modal dialog: Save changes? Yes, No, Cancel + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, VIEW)); + } +} diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h index c486ca5f30..c32f274206 100644 --- a/indra/newview/llfloaterexperienceprofile.h +++ b/indra/newview/llfloaterexperienceprofile.h @@ -35,28 +35,47 @@ class LLLayoutPanel; class LLTextBox; +class LLComboBox; class LLFloaterExperienceProfile : public LLFloater { LOG_CLASS(LLFloaterExperienceProfile); public: + enum + { + NOTHING, + CLOSE, + VIEW, + }; + + LLFloaterExperienceProfile(const LLSD& data); virtual ~LLFloaterExperienceProfile(); - void setExperienceId( const LLUUID& experience_id ); + LLUUID getExperienceId() const { return mExperienceId; } void setPreferences( const LLSD& content ); + void refreshExperience(const LLSD& experience); + void onSaveComplete( const LLSD& content ); + virtual BOOL canClose(); protected: void onClickEdit(); void onClickPermission(const char* permission); void onClickForget(); + void onClickCancel(); + + void changeToView(); + void onClickSave(); + + void onFieldChanged(); static void experienceCallback(LLHandle handle, const LLSD& experience); - void refreshExperience(const LLSD& experience); BOOL postBuild(); - bool setMaturityString(U8 maturity, LLTextBox* child); + bool setMaturityString(U8 maturity, LLTextBox* child, LLComboBox* combo); + bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response, int action); + void doSave( int success_action ); LLUUID mExperienceId; LLSD mExperienceDetails; @@ -64,9 +83,9 @@ protected: LLLayoutPanel* mDescriptionPanel; LLLayoutPanel* mLocationPanel; LLLayoutPanel* mMarketplacePanel; - -private: - + int mSaveCompleteAction; + bool mDirty; + bool mForceClose; }; #endif // LL_LLFLOATEREXPERIENCEPROFILE_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index af993943ce..60e0df90a2 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1601,11 +1601,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("GetAdminExperiences"); capabilityNames.append("GetCreatorExperiences"); capabilityNames.append("ExperiencePreferences"); -/* - DMH - Does not work, needs a modified people api to take the experience UUID + capabilityNames.append("UpdateExperience"); capabilityNames.append("IsExperienceAdmin"); capabilityNames.append("IsExperienceContributor"); -*/ capabilityNames.append("GetMesh"); capabilityNames.append("GetMetadata"); capabilityNames.append("GetObjectCost"); diff --git a/indra/newview/skins/default/xui/en/floater_experienceprofile.xml b/indra/newview/skins/default/xui/en/floater_experienceprofile.xml index 58c0ed70ef..f47042ea33 100644 --- a/indra/newview/skins/default/xui/en/floater_experienceprofile.xml +++ b/indra/newview/skins/default/xui/en/floater_experienceprofile.xml @@ -3,15 +3,8 @@ "Parcel_R_Light" - + - - + - + - + - + - + - - - - - - + + + - - - + + - Location: - - + + + - someplace - - - - - Marketplace store: - - + Location: + + + someplace + + + - someplace - - - - - Rating: - - + Marketplace store: + + + someplace + + + - Adult - - - Owner: - - - Kyle - -