418 lines
14 KiB
C++
418 lines
14 KiB
C++
/**
|
|
* @file llfloaterexperiences.cpp
|
|
* @brief LLFloaterExperiences class implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2012, 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 "llfloaterexperiences.h"
|
|
#include "llfloaterreg.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llevents.h"
|
|
#include "llexperiencecache.h"
|
|
#include "llfloaterregioninfo.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "llpanelexperiencelog.h"
|
|
#include "llpanelexperiencepicker.h"
|
|
#include "llpanelexperiences.h"
|
|
#include "lltabcontainer.h"
|
|
#include "lltrans.h"
|
|
#include "llviewerregion.h"
|
|
|
|
|
|
#define SHOW_RECENT_TAB (0)
|
|
LLFloaterExperiences::LLFloaterExperiences(const LLSD& data)
|
|
:LLFloater(data)
|
|
{
|
|
}
|
|
|
|
LLPanelExperiences* LLFloaterExperiences::addTab(const std::string& name, bool select)
|
|
{
|
|
LLPanelExperiences* newPanel = LLPanelExperiences::create(name);
|
|
getChild<LLTabContainer>("xp_tabs")->addTabPanel(LLTabContainer::TabPanelParams().
|
|
panel(newPanel).
|
|
label(LLTrans::getString(name)).
|
|
select_tab(select));
|
|
|
|
return newPanel;
|
|
}
|
|
|
|
BOOL LLFloaterExperiences::postBuild()
|
|
{
|
|
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperiencePicker());
|
|
addTab("Allowed_Experiences_Tab", true);
|
|
addTab("Blocked_Experiences_Tab", false);
|
|
addTab("Admin_Experiences_Tab", false);
|
|
addTab("Contrib_Experiences_Tab", false);
|
|
LLPanelExperiences* owned = addTab("Owned_Experiences_Tab", false);
|
|
owned->setButtonAction("acquire", boost::bind(&LLFloaterExperiences::sendPurchaseRequest, this));
|
|
owned->enableButton(false);
|
|
#if SHOW_RECENT_TAB
|
|
addTab("Recent_Experiences_Tab", false);
|
|
#endif //SHOW_RECENT_TAB
|
|
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperienceLog());
|
|
resizeToTabs();
|
|
|
|
|
|
LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
|
|
boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void LLFloaterExperiences::clearFromRecent(const LLSD& ids)
|
|
{
|
|
#if SHOW_RECENT_TAB
|
|
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
|
|
|
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
|
if(!tab)
|
|
return;
|
|
|
|
tab->removeExperiences(ids);
|
|
#endif // SHOW_RECENT_TAB
|
|
}
|
|
|
|
void LLFloaterExperiences::setupRecentTabs()
|
|
{
|
|
#if SHOW_RECENT_TAB
|
|
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
|
|
|
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
|
if(!tab)
|
|
return;
|
|
|
|
LLSD recent;
|
|
|
|
const LLExperienceCache::cache_t& experiences = LLExperienceCache::getCached();
|
|
|
|
LLExperienceCache::cache_t::const_iterator it = experiences.begin();
|
|
while( it != experiences.end() )
|
|
{
|
|
if(!it->second.has(LLExperienceCache::MISSING))
|
|
{
|
|
recent.append(it->first);
|
|
}
|
|
++it;
|
|
}
|
|
|
|
tab->setExperienceList(recent);
|
|
#endif // SHOW_RECENT_TAB
|
|
}
|
|
|
|
|
|
void LLFloaterExperiences::resizeToTabs()
|
|
{
|
|
const S32 TAB_WIDTH_PADDING = 16;
|
|
|
|
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
|
LLRect rect = getRect();
|
|
if(rect.getWidth() < tabs->getTotalTabWidth() + TAB_WIDTH_PADDING)
|
|
{
|
|
rect.mRight = rect.mLeft + tabs->getTotalTabWidth() + TAB_WIDTH_PADDING;
|
|
}
|
|
reshape(rect.getWidth(), rect.getHeight(), FALSE);
|
|
}
|
|
|
|
void LLFloaterExperiences::refreshContents()
|
|
{
|
|
setupRecentTabs();
|
|
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
|
|
if (region)
|
|
{
|
|
NameMap_t tabMap;
|
|
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
|
|
|
tabMap["experiences"]="Allowed_Experiences_Tab";
|
|
tabMap["blocked"]="Blocked_Experiences_Tab";
|
|
tabMap["experience_ids"]="Owned_Experiences_Tab";
|
|
|
|
retrieveExperienceList(region->getCapability("GetExperiences"), handle, tabMap);
|
|
|
|
updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
|
updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
|
|
|
retrieveExperienceList(region->getCapability("AgentExperiences"), handle, tabMap,
|
|
"ExperienceAcquireFailed", boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2));
|
|
}
|
|
}
|
|
|
|
void LLFloaterExperiences::onOpen( const LLSD& key )
|
|
{
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
if(region)
|
|
{
|
|
if(region->capabilitiesReceived())
|
|
{
|
|
refreshContents();
|
|
return;
|
|
}
|
|
region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterExperiences::refreshContents, this));
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool LLFloaterExperiences::updatePermissions( const LLSD& permission )
|
|
{
|
|
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
|
LLUUID experience;
|
|
std::string permission_string;
|
|
if(permission.has("experience"))
|
|
{
|
|
experience = permission["experience"].asUUID();
|
|
permission_string = permission[experience.asString()]["permission"].asString();
|
|
|
|
}
|
|
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Allowed_Experiences_Tab");
|
|
if(tab)
|
|
{
|
|
if(permission.has("experiences"))
|
|
{
|
|
tab->setExperienceList(permission["experiences"]);
|
|
}
|
|
else if(experience.notNull())
|
|
{
|
|
if(permission_string != "Allow")
|
|
{
|
|
tab->removeExperience(experience);
|
|
}
|
|
else
|
|
{
|
|
tab->addExperience(experience);
|
|
}
|
|
}
|
|
}
|
|
|
|
tab = (LLPanelExperiences*)tabs->getPanelByName("Blocked_Experiences_Tab");
|
|
if(tab)
|
|
{
|
|
if(permission.has("blocked"))
|
|
{
|
|
tab->setExperienceList(permission["blocked"]);
|
|
}
|
|
else if(experience.notNull())
|
|
{
|
|
if(permission_string != "Block")
|
|
{
|
|
tab->removeExperience(experience);
|
|
}
|
|
else
|
|
{
|
|
tab->addExperience(experience);
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LLFloaterExperiences::onClose( bool app_quitting )
|
|
{
|
|
LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
|
|
LLFloater::onClose(app_quitting);
|
|
}
|
|
|
|
void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content) const
|
|
{
|
|
panel->enableButton(content.has("purchase"));
|
|
|
|
LLFloaterExperiences::findInstance()->updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
|
LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
|
}
|
|
|
|
void LLFloaterExperiences::checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const
|
|
{
|
|
checkPurchaseInfo(panel, content);
|
|
|
|
// determine new item
|
|
const LLSD& response_ids = content["experience_ids"];
|
|
|
|
if (mPrepurchaseIds.size() + 1 == response_ids.size())
|
|
{
|
|
// we have a new element
|
|
for (LLSD::array_const_iterator it = response_ids.beginArray(); it != response_ids.endArray(); ++it)
|
|
{
|
|
LLUUID experience_id = it->asUUID();
|
|
if (std::find(mPrepurchaseIds.begin(), mPrepurchaseIds.end(), experience_id) == mPrepurchaseIds.end())
|
|
{
|
|
// new element found, open it
|
|
LLSD args;
|
|
args["experience_id"] = experience_id;
|
|
args["edit_experience"] = true;
|
|
LLFloaterReg::showInstance("experience_profile", args, true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLFloaterExperiences::updateInfo(std::string experienceCap, std::string tab)
|
|
{
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
if (region)
|
|
{
|
|
NameMap_t tabMap;
|
|
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
|
|
|
tabMap["experience_ids"] = tab;
|
|
|
|
retrieveExperienceList(region->getCapability(experienceCap), handle, tabMap);
|
|
}
|
|
}
|
|
|
|
void LLFloaterExperiences::sendPurchaseRequest()
|
|
{
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
|
|
if (region)
|
|
{
|
|
NameMap_t tabMap;
|
|
const std::string tab_owned_name = "Owned_Experiences_Tab";
|
|
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
|
|
|
tabMap["experience_ids"] = tab_owned_name;
|
|
|
|
// extract ids for experiences that we already have
|
|
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
|
LLPanelExperiences* tab_owned = (LLPanelExperiences*)tabs->getPanelByName(tab_owned_name);
|
|
mPrepurchaseIds.clear();
|
|
if (tab_owned)
|
|
{
|
|
tab_owned->getExperienceIdsList(mPrepurchaseIds);
|
|
}
|
|
|
|
requestNewExperience(region->getCapability("AgentExperiences"), handle, tabMap, "ExperienceAcquireFailed",
|
|
boost::bind(&LLFloaterExperiences::checkAndOpen, this, _1, _2));
|
|
}
|
|
}
|
|
|
|
LLFloaterExperiences* LLFloaterExperiences::findInstance()
|
|
{
|
|
return LLFloaterReg::findTypedInstance<LLFloaterExperiences>("experiences");
|
|
}
|
|
|
|
|
|
void LLFloaterExperiences::retrieveExperienceList(const std::string &url,
|
|
const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
|
|
const std::string &errorNotify, Callback_t cback)
|
|
|
|
{
|
|
invokationFn_t getFn = boost::bind(
|
|
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
|
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
|
//----
|
|
// _1 -> httpAdapter
|
|
// _2 -> httpRequest
|
|
// _3 -> url
|
|
// _4 -> httpOptions
|
|
// _5 -> httpHeaders
|
|
(&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _4, _5);
|
|
|
|
LLCoros::instance().launch("LLFloaterExperiences::retrieveExperienceList",
|
|
boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
|
|
url, hparent, tabMapping, errorNotify, cback, getFn));
|
|
|
|
}
|
|
|
|
void LLFloaterExperiences::requestNewExperience(const std::string &url,
|
|
const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
|
|
const std::string &errorNotify, Callback_t cback)
|
|
{
|
|
invokationFn_t postFn = boost::bind(
|
|
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
|
|
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
|
|
//----
|
|
// _1 -> httpAdapter
|
|
// _2 -> httpRequest
|
|
// _3 -> url
|
|
// _4 -> httpOptions
|
|
// _5 -> httpHeaders
|
|
(&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, LLSD(), _4, _5);
|
|
|
|
LLCoros::instance().launch("LLFloaterExperiences::requestNewExperience",
|
|
boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
|
|
url, hparent, tabMapping, errorNotify, cback, postFn));
|
|
|
|
}
|
|
|
|
|
|
void LLFloaterExperiences::retrieveExperienceListCoro(std::string url,
|
|
LLHandle<LLFloaterExperiences> hparent, NameMap_t tabMapping,
|
|
std::string errorNotify, Callback_t cback, invokationFn_t invoker)
|
|
{
|
|
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
|
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
|
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("retrieveExperienceListCoro", httpPolicy));
|
|
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
|
LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
|
|
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
|
|
|
|
|
|
if (url.empty())
|
|
{
|
|
LL_WARNS() << "retrieveExperienceListCoro called with empty capability!" << LL_ENDL;
|
|
return;
|
|
}
|
|
|
|
LLSD result = invoker(httpAdapter, httpRequest, url, httpOptions, httpHeaders);
|
|
|
|
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
|
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
|
|
|
if (!status)
|
|
{
|
|
LLSD subs;
|
|
subs["ERROR_MESSAGE"] = status.getType();
|
|
LLNotificationsUtil::add(errorNotify, subs);
|
|
|
|
return;
|
|
}
|
|
|
|
if (hparent.isDead())
|
|
return;
|
|
|
|
LLFloaterExperiences* parent = hparent.get();
|
|
LLTabContainer* tabs = parent->getChild<LLTabContainer>("xp_tabs");
|
|
|
|
for (NameMap_t::iterator it = tabMapping.begin(); it != tabMapping.end(); ++it)
|
|
{
|
|
if (result.has(it->first))
|
|
{
|
|
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it->second);
|
|
if (tab)
|
|
{
|
|
const LLSD& ids = result[it->first];
|
|
tab->setExperienceList(ids);
|
|
if (!cback.empty())
|
|
{
|
|
cback(tab, result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|