/** * @file llfloaterexperienceprofile.cpp * @brief llfloaterexperienceprofile and related class definitions * * $LicenseInfo:firstyear=2013&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2013, 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 "llfloaterexperienceprofile.h" #include "llagent.h" #include "llappviewer.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llcommandhandler.h" #include "llexpandabletextbox.h" #include "llexperiencecache.h" #include "llfloaterreg.h" #include "llhttpclient.h" #include "lllayoutstack.h" #include "lllineeditor.h" #include "llnotificationsutil.h" #include "llsdserialize.h" #include "llslurl.h" #include "lltabcontainer.h" #include "lltextbox.h" #include "lltexturectrl.h" #include "lltrans.h" #include "llviewerregion.h" #include "llevents.h" #include "llfloatergroups.h" #include "llnotifications.h" #include "llfloaterreporter.h" #define XML_PANEL_EXPERIENCE_PROFILE "floater_experienceprofile.xml" #define TF_NAME "experience_title" #define TF_DESC "experience_description" #define TF_SLURL "LocationTextText" #define TF_MRKT "marketplace" #define TF_MATURITY "ContentRatingText" #define TF_OWNER "OwnerText" #define TF_GROUP "GroupText" #define TF_GRID_WIDE "grid_wide" #define TF_PRIVILEGED "privileged" #define EDIT "edit_" #define IMG_LOGO "logo" #define PNL_TOP "top panel" #define PNL_IMAGE "image_panel" #define PNL_DESC "description panel" #define PNL_LOC "location panel" #define PNL_MRKT "marketplace panel" #define PNL_GROUP "group_panel" #define PNL_PERMS "perm panel" #define BTN_ALLOW "allow_btn" #define BTN_BLOCK "block_btn" #define BTN_CANCEL "cancel_btn" #define BTN_CLEAR_LOCATION "clear_btn" #define BTN_EDIT "edit_btn" #define BTN_ENABLE "enable_btn" #define BTN_FORGET "forget_btn" #define BTN_PRIVATE "private_btn" #define BTN_REPORT "report_btn" #define BTN_SAVE "save_btn" #define BTN_SET_GROUP "Group_btn" #define BTN_SET_LOCATION "location_btn" class LLExperienceHandler : public LLCommandHandler { public: LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { if(params.size() != 2 || params[1].asString() != "profile") return false; LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } void experienceCallback(const LLSD& experienceDetails) { if(!experienceDetails.has(LLExperienceCache::MISSING)) { LLFloaterReg::showInstance("experience_profile", experienceDetails[LLExperienceCache::EXPERIENCE_ID].asUUID(), true); } } }; LLExperienceHandler gExperienceHandler; LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data) : LLFloater(data) , mExperienceId(data.asUUID()) , mSaveCompleteAction(NOTHING) , mDirty(false) , mForceClose(false) { } LLFloaterExperienceProfile::~LLFloaterExperienceProfile() { } template class HandleResponder : public LLHTTPClient::Responder { public: HandleResponder(const LLHandle& parent):mParent(parent){} LLHandle mParent; virtual void httpFailure() { LL_WARNS() << "HandleResponder failed with code: " << getStatus() << ", reason: " << getReason() << LL_ENDL; } }; class ExperienceUpdateResponder : public HandleResponder { public: ExperienceUpdateResponder(const LLHandle& parent):HandleResponder(parent) { } virtual void httpSuccess() { LLFloaterExperienceProfile* parent=mParent.get(); if(parent) { parent->onSaveComplete(getContent()); } } }; class ExperiencePreferencesResponder : public LLHTTPClient::Responder { public: ExperiencePreferencesResponder(const LLUUID& single = LLUUID::null):mId(single) { } bool sendSingle(const LLSD& content, const LLSD& permission, const char* name) { if(!content.has(name)) return false; LLEventPump& pump = LLEventPumps::instance().obtain("experience_permission"); const LLSD& list = content[name]; LLSD::array_const_iterator it = list.beginArray(); while(it != list.endArray()) { if(it->asUUID() == mId) { LLSD message; message[it->asString()] = permission; message["experience"] = mId; pump.post(message); return true; } ++it; } return false; } bool hasPermission(const LLSD& content, const char* name) { if(!content.has(name)) return false; const LLSD& list = content[name]; LLSD::array_const_iterator it = list.beginArray(); while(it != list.endArray()) { if(it->asUUID() == mId) { return true; } ++it; } return false; } const char* getPermission(const LLSD& content) { if(hasPermission(content, "experiences")) { return "Allow"; } else if(hasPermission(content, "blocked")) { return "Block"; } return "Forget"; } virtual void httpSuccess() { if(mId.notNull()) { post(getPermission(getContent())); return; } LLEventPumps::instance().obtain("experience_permission").post(getContent()); } void post( const char* perm ) { LLSD experience; LLSD message; experience["permission"]=perm; message["experience"] = mId; message[mId.asString()] = experience; LLEventPumps::instance().obtain("experience_permission").post(message); } private: LLUUID mId; }; class IsAdminResponder : public HandleResponder { public: IsAdminResponder(const LLHandle& parent):HandleResponder(parent) { } virtual void httpSuccess() { LLFloaterExperienceProfile* parent = mParent.get(); if(!parent) return; bool enabled = true; LLViewerRegion* region = gAgent.getRegion(); if (!region) { enabled = false; } else { std::string url=region->getCapability("UpdateExperience"); if(url.empty()) enabled = false; } if(enabled && getContent()["status"].asBoolean()) { parent->getChild(PNL_TOP)->setVisible(TRUE); parent->getChild(BTN_EDIT)->setVisible(TRUE); } } }; BOOL LLFloaterExperienceProfile::postBuild() { if (mExperienceId.notNull()) { LLExperienceCache::getInstance()->fetch(mExperienceId, true); LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); if (region) { std::string lookup_url=region->getCapability("IsExperienceAdmin"); if(!lookup_url.empty()) { LLHTTPClient::get(lookup_url+"?experience_id="+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle())); } } } 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)); childSetAction(BTN_SET_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickLocation, this)); childSetAction(BTN_CLEAR_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickClear, this)); childSetAction(BTN_SET_GROUP, boost::bind(&LLFloaterExperienceProfile::onPickGroup, this)); childSetAction(BTN_REPORT, boost::bind(&LLFloaterExperienceProfile::onReportExperience, this)); getChild(EDIT TF_DESC)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); getChild(EDIT TF_MATURITY)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this)); getChild(EDIT TF_MRKT)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), NULL); getChild(EDIT TF_NAME)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), NULL); childSetCommitCallback(EDIT BTN_ENABLE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), NULL); childSetCommitCallback(EDIT BTN_PRIVATE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), NULL); childSetCommitCallback(EDIT IMG_LOGO, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), NULL); getChild(EDIT TF_DESC)->setCommitOnFocusLost(TRUE); LLEventPumps::instance().obtain("experience_permission").listen(mExperienceId.asString()+"-profile", boost::bind(&LLFloaterExperienceProfile::experiencePermission, getDerivedHandle(this), _1)); return TRUE; } void LLFloaterExperienceProfile::experienceCallback(LLHandle handle, const LLSD& experience ) { LLFloaterExperienceProfile* pllpep = handle.get(); if(pllpep) { pllpep->refreshExperience(experience); } } bool LLFloaterExperienceProfile::experiencePermission( LLHandle handle, const LLSD& permission ) { LLFloaterExperienceProfile* pllpep = handle.get(); if(pllpep) { pllpep->updatePermission(permission); } return false; } void LLFloaterExperienceProfile::onClickEdit() { LLTabContainer* tabs = getChild("tab_container"); tabs->selectTabByName("edit_panel_experience_info"); } void LLFloaterExperienceProfile::onClickCancel() { changeToView(); } void LLFloaterExperienceProfile::onClickSave() { doSave(NOTHING); } void LLFloaterExperienceProfile::onClickPermission(const char* perm) { LLViewerRegion* region = gAgent.getRegion(); if (!region) return; std::string lookup_url=region->getCapability("ExperiencePreferences"); if(lookup_url.empty()) return; LLSD permission; LLSD data; permission["permission"]=perm; data[mExperienceId.asString()]=permission; LLHTTPClient::put(lookup_url, data, new ExperiencePreferencesResponder(mExperienceId)); } void LLFloaterExperienceProfile::onClickForget() { LLViewerRegion* region = gAgent.getRegion(); if (!region) return; std::string lookup_url=region->getCapability("ExperiencePreferences"); if(lookup_url.empty()) return; LLHTTPClient::del(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId)); } bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo ) { LLStyle::Params style; std::string access; if(maturity <= SIM_ACCESS_PG) { 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 { return false; } child->setText(LLStringUtil::null); child->appendImageSegment(style); child->appendText(access, false); return true; } void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience ) { mExperienceDetails = experience; mPackage = experience; LLLayoutPanel* imagePanel = getChild(PNL_IMAGE); LLLayoutPanel* descriptionPanel = getChild(PNL_DESC); LLLayoutPanel* locationPanel = getChild(PNL_LOC); LLLayoutPanel* marketplacePanel = getChild(PNL_MRKT); LLLayoutPanel* topPanel = getChild(PNL_TOP); imagePanel->setVisible(FALSE); descriptionPanel->setVisible(FALSE); locationPanel->setVisible(FALSE); marketplacePanel->setVisible(FALSE); topPanel->setVisible(FALSE); LLTextBox* child = getChild(TF_NAME); //child->setText(experience[LLExperienceCache::NAME].asString()); child->setText(LLSLURL("experience", experience[LLExperienceCache::EXPERIENCE_ID], "profile").getSLURLString()); 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); descriptionPanel->setVisible(value.length()>0); LLTextEditor* edit_child = getChild(EDIT TF_DESC); edit_child->setText(value); mLocationSLURL = experience[LLExperienceCache::SLURL].asString(); child = getChild(TF_SLURL); bool has_slurl = mLocationSLURL.length()>0; locationPanel->setVisible(has_slurl); mLocationSLURL = LLSLURL(mLocationSLURL).getSLURLString(); child->setText(mLocationSLURL); child = getChild(EDIT TF_SLURL); if(has_slurl) { child->setText(mLocationSLURL); } else { child->setText(getString("empty_slurl")); } setMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger()), getChild(TF_MATURITY), getChild(EDIT TF_MATURITY)); LLUUID id = experience[LLExperienceCache::AGENT_ID].asUUID(); child = getChild(TF_OWNER); value = LLSLURL("agent", id, "inspect").getSLURLString(); child->setText(value); id = experience[LLExperienceCache::GROUP_ID].asUUID(); bool id_null = id.isNull(); child = getChild(TF_GROUP); value = LLSLURL("group", id, "inspect").getSLURLString(); child->setText(value); getChild(PNL_GROUP)->setVisible(!id_null); setEditGroup(id); getChild(BTN_SET_GROUP)->setEnabled(experience[LLExperienceCache::AGENT_ID].asUUID() == gAgent.getID()); LLCheckBoxCtrl* enable = getChild(EDIT BTN_ENABLE); S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger(); enable->set(!(properties & LLExperienceCache::PROPERTY_DISABLED)); enable = getChild(EDIT BTN_PRIVATE); enable->set(properties & LLExperienceCache::PROPERTY_PRIVATE); topPanel->setVisible(TRUE); child=getChild(TF_GRID_WIDE); child->setVisible(TRUE); if(properties & LLExperienceCache::PROPERTY_GRID) { child->setText(LLTrans::getString("Grid-Scope")); } else { child->setText(LLTrans::getString("Land-Scope")); } if(getChild(BTN_EDIT)->getVisible()) { topPanel->setVisible(TRUE); } if(properties & LLExperienceCache::PROPERTY_PRIVILEGED) { child = getChild(TF_PRIVILEGED); child->setVisible(TRUE); } else { LLViewerRegion* region = gAgent.getRegion(); if (region) { std::string lookup_url=region->getCapability("ExperiencePreferences"); if(!lookup_url.empty()) { LLHTTPClient::get(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId)); } } } value=experience[LLExperienceCache::METADATA].asString(); if(value.empty()) return; LLPointer parser = new LLSDXMLParser(); LLSD data; 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(); child = getChild(TF_MRKT); child->setText(value); if(value.size()) { marketplacePanel->setVisible(TRUE); } else { marketplacePanel->setVisible(FALSE); } } else { marketplacePanel->setVisible(FALSE); } linechild = getChild(EDIT TF_MRKT); linechild->setText(value); if(data.has(IMG_LOGO)) { LLTextureCtrl* logo = getChild(IMG_LOGO); LLUUID id = data[IMG_LOGO].asUUID(); logo->setImageAssetID(id); imagePanel->setVisible(TRUE); logo = getChild(EDIT IMG_LOGO); logo->setImageAssetID(data[IMG_LOGO].asUUID()); imagePanel->setVisible(id.notNull()); } } else { marketplacePanel->setVisible(FALSE); imagePanel->setVisible(FALSE); } mDirty=false; mForceClose = false; getChild(BTN_SAVE)->setEnabled(mDirty); } void LLFloaterExperienceProfile::setPreferences( const LLSD& content ) { S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger(); if(properties & LLExperienceCache::PROPERTY_PRIVILEGED) { return; } const LLSD& experiences = content["experiences"]; const LLSD& blocked = content["blocked"]; for(LLSD::array_const_iterator it = experiences.beginArray(); it != experiences.endArray() ; ++it) { if(it->asUUID()==mExperienceId) { experienceAllowed(); return; } } for(LLSD::array_const_iterator it = blocked.beginArray(); it != blocked.endArray() ; ++it) { if(it->asUUID()==mExperienceId) { experienceBlocked(); return; } } experienceForgotten(); } void LLFloaterExperienceProfile::onFieldChanged() { updatePackage(); if(!getChild(BTN_EDIT)->getVisible()) { return; } LLSD::map_const_iterator st = mExperienceDetails.beginMap(); LLSD::map_const_iterator dt = mPackage.beginMap(); mDirty = false; while( !mDirty && st != mExperienceDetails.endMap() && dt != mPackage.endMap()) { mDirty = st->first != dt->first || st->second.asString() != dt->second.asString(); ++st;++dt; } if(!mDirty && (st != mExperienceDetails.endMap() || dt != mPackage.endMap())) { mDirty = true; } 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, PostSaveAction 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; mPackage.erase(LLExperienceCache::QUOTA); mPackage.erase(LLExperienceCache::EXPIRES); mPackage.erase(LLExperienceCache::AGENT_ID); LLHTTPClient::post(url, mPackage, new ExperienceUpdateResponder(getDerivedHandle())); } void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) { LLUUID id = getExperienceId(); if(content.has("removed")) { const LLSD& removed = content["removed"]; LLSD::map_const_iterator it = removed.beginMap(); for(/**/; it != removed.endMap(); ++it) { const std::string& field = it->first; if(field == LLExperienceCache::EXPERIENCE_ID) { //this message should be removed by the experience api continue; } const LLSD& data = it->second; std::string error_tag = data["error_tag"].asString()+ "ExperienceProfileMessage"; LLSD fields; if( LLNotifications::instance().getTemplate(error_tag)) { fields["field"] = field; fields["extra_info"] = data["extra_info"]; LLNotificationsUtil::add(error_tag, fields); } else { fields["MESSAGE"]=data["en"]; LLNotificationsUtil::add("GenericAlert", fields); } } } if(!content.has("experience_keys")) { LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with bad content" << LL_ENDL; return; } const LLSD& experiences = content["experience_keys"]; LLSD::array_const_iterator it = experiences.beginArray(); if(it == experiences.endArray()) { LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with empty content" << LL_ENDL; return; } if(!it->has(LLExperienceCache::EXPERIENCE_ID) || ((*it)[LLExperienceCache::EXPERIENCE_ID].asUUID() != id)) { LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with unexpected experience id" << LL_ENDL; return; } refreshExperience(*it); LLExperienceCache::getInstance()->insert(*it); LLExperienceCache::getInstance()->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)); } } void LLFloaterExperienceProfile::onClickLocation() { LLViewerRegion* region = gAgent.getRegion(); if(region) { LLTextBox* child = getChild(EDIT TF_SLURL); mLocationSLURL = LLSLURL(region->getName(), gAgent.getPositionGlobal()).getSLURLString(); child->setText(mLocationSLURL); onFieldChanged(); } } void LLFloaterExperienceProfile::onClickClear() { LLTextBox* child = getChild(EDIT TF_SLURL); mLocationSLURL = ""; child->setText(getString("empty_slurl")); onFieldChanged(); } void LLFloaterExperienceProfile::updatePermission( const LLSD& permission ) { if(permission.has("experience")) { if(permission["experience"].asUUID() != mExperienceId) { return; } std::string str = permission[mExperienceId.asString()]["permission"].asString(); if(str == "Allow") { experienceAllowed(); } else if(str == "Block") { experienceBlocked(); } else if(str == "Forget") { experienceForgotten(); } } else { setPreferences(permission); } } void LLFloaterExperienceProfile::experienceAllowed() { LLButton* button=getChild(BTN_ALLOW); button->setEnabled(FALSE); button=getChild(BTN_FORGET); button->setEnabled(TRUE); button=getChild(BTN_BLOCK); button->setEnabled(TRUE); } void LLFloaterExperienceProfile::experienceForgotten() { LLButton* button=getChild(BTN_ALLOW); button->setEnabled(TRUE); button=getChild(BTN_FORGET); button->setEnabled(FALSE); button=getChild(BTN_BLOCK); button->setEnabled(TRUE); } void LLFloaterExperienceProfile::experienceBlocked() { LLButton* button=getChild(BTN_ALLOW); button->setEnabled(TRUE); button=getChild(BTN_FORGET); button->setEnabled(TRUE); button=getChild(BTN_BLOCK); button->setEnabled(FALSE); } void LLFloaterExperienceProfile::onClose( bool app_quitting ) { LLEventPumps::instance().obtain("experience_permission").stopListening(mExperienceId.asString()+"-profile"); LLFloater::onClose(app_quitting); } void LLFloaterExperienceProfile::updatePackage() { mPackage[LLExperienceCache::NAME] = getChild(EDIT TF_NAME)->getText(); mPackage[LLExperienceCache::DESCRIPTION] = getChild(EDIT TF_DESC)->getText(); if(mLocationSLURL.empty()) { mPackage[LLExperienceCache::SLURL] = LLStringUtil::null; } else { mPackage[LLExperienceCache::SLURL] = mLocationSLURL; } mPackage[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)) { mPackage[LLExperienceCache::METADATA]=os.str(); } int properties = mPackage[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; } mPackage[LLExperienceCache::PROPERTIES] = properties; } void LLFloaterExperienceProfile::onPickGroup() { LLFloater* parent_floater = gFloaterView->getParentFloater(this); LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance("group_picker", LLSD(gAgent.getID())); if (widget) { widget->setSelectGroupCallback(boost::bind(&LLFloaterExperienceProfile::setEditGroup, this, _1)); if (parent_floater) { LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); widget->setOrigin(new_rect.mLeft, new_rect.mBottom); parent_floater->addDependentFloater(widget); } } } void LLFloaterExperienceProfile::setEditGroup( LLUUID group_id ) { LLTextBox* child = getChild(EDIT TF_GROUP); std::string value = LLSLURL("group", group_id, "inspect").getSLURLString(); child->setText(value); mPackage[LLExperienceCache::GROUP_ID] = group_id; onFieldChanged(); } void LLFloaterExperienceProfile::onReportExperience() { LLFloaterReporter::showFromExperience(mExperienceId); }