diff options
72 files changed, 7641 insertions, 4021 deletions
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 5fdde445ef..3331b8aeee 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -366,6 +366,8 @@ public:  	virtual void	onFocusReceived();  	virtual void	onFocusLost(); +    void        setParseHTML(bool parse_html) { mParseHTML = parse_html; } +  	// LLSpellCheckMenuHandler overrides  	/*virtual*/ bool		getSpellCheck() const; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 99f99834f3..f7b7dd6aa7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -236,6 +236,7 @@ set(viewer_SOURCE_FILES      llfloaterdeleteenvpreset.cpp      llfloaterdeleteprefpreset.cpp      llfloaterdestinations.cpp +    llfloaterdisplayname.cpp      llfloatereditdaycycle.cpp      llfloatereditsky.cpp      llfloatereditwater.cpp @@ -289,6 +290,7 @@ set(viewer_SOURCE_FILES      llfloaterpay.cpp      llfloaterperms.cpp      llfloaterpostprocess.cpp +    llfloaterprofile.cpp      llfloaterpreference.cpp      llfloaterpreviewtrash.cpp      llfloaterproperties.cpp @@ -430,7 +432,6 @@ set(viewer_SOURCE_FILES      llpanelavatar.cpp      llpanelavatartag.cpp      llpanelblockedlist.cpp -    llpanelclassified.cpp      llpanelcontents.cpp      llpaneleditwearable.cpp      llpanelexperiencelisteditor.cpp @@ -462,7 +463,6 @@ set(viewer_SOURCE_FILES      llpanelmediasettingsgeneral.cpp      llpanelmediasettingspermissions.cpp      llpanelmediasettingssecurity.cpp -    llpanelme.cpp      llpanelnearbymedia.cpp      llpanelobject.cpp      llpanelobjectinventory.cpp @@ -473,7 +473,6 @@ set(viewer_SOURCE_FILES      llpanelpeoplemenus.cpp      llpanelpermissions.cpp      llpanelpick.cpp -    llpanelpicks.cpp      llpanelplaceinfo.cpp      llpanelplaceprofile.cpp      llpanelplaces.cpp @@ -481,6 +480,8 @@ set(viewer_SOURCE_FILES      llpanelpresetspulldown.cpp      llpanelprimmediacontrols.cpp      llpanelprofile.cpp +    llpanelprofileclassifieds.cpp +    llpanelprofilepicks.cpp      llpanelsnapshot.cpp      llpanelsnapshotinventory.cpp      llpanelsnapshotlocal.cpp @@ -638,6 +639,7 @@ set(viewer_SOURCE_FILES      llviewercontrol.cpp      llviewercontrollistener.cpp      llviewerdisplay.cpp +    llviewerdisplayname.cpp      llviewerfloaterreg.cpp      llviewerfoldertype.cpp      llviewergenericmessage.cpp @@ -860,6 +862,7 @@ set(viewer_HEADER_FILES      llfloaterdeleteprefpreset.h      llfloaterdeleteenvpreset.h      llfloaterdestinations.h +    llfloaterdisplayname.h      llfloatereditdaycycle.h      llfloatereditsky.h      llfloatereditwater.h @@ -916,6 +919,7 @@ set(viewer_HEADER_FILES      llfloaterpay.h      llfloaterperms.h      llfloaterpostprocess.h +    llfloaterprofile.h      llfloaterpreference.h      llfloaterpreviewtrash.h      llfloaterproperties.h @@ -1047,7 +1051,6 @@ set(viewer_HEADER_FILES      llpanelavatar.h      llpanelavatartag.h      llpanelblockedlist.h -    llpanelclassified.h      llpanelcontents.h      llpaneleditwearable.h      llpanelexperiencelisteditor.h @@ -1080,7 +1083,6 @@ set(viewer_HEADER_FILES      llpanelmediasettingsgeneral.h      llpanelmediasettingspermissions.h      llpanelmediasettingssecurity.h -    llpanelme.h      llpanelnearbymedia.h      llpanelobject.h      llpanelobjectinventory.h @@ -1091,7 +1093,6 @@ set(viewer_HEADER_FILES      llpanelpeoplemenus.h      llpanelpermissions.h      llpanelpick.h -    llpanelpicks.h      llpanelplaceinfo.h      llpanelplaceprofile.h      llpanelplaces.h @@ -1099,6 +1100,8 @@ set(viewer_HEADER_FILES      llpanelpresetspulldown.h      llpanelprimmediacontrols.h      llpanelprofile.h +    llpanelprofileclassifieds.h +    llpanelprofilepicks.h      llpanelsnapshot.h      llpanelteleporthistory.h      llpaneltiptoast.h @@ -1257,6 +1260,7 @@ set(viewer_HEADER_FILES      llviewercontrol.h      llviewercontrollistener.h      llviewerdisplay.h +    llviewerdisplayname.h      llviewerfloaterreg.h      llviewerfoldertype.h      llviewergenericmessage.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index f0b74e7439..ecfb2cd5a8 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -48,6 +48,7 @@  #include "llfloatergroups.h"  #include "llfloaterreg.h"  #include "llfloaterpay.h" +#include "llfloaterprofile.h"  #include "llfloatersidepanelcontainer.h"  #include "llfloaterwebcontent.h"  #include "llfloaterworldmap.h" @@ -67,6 +68,7 @@  #include "llviewercontrol.h"  #include "llviewerobjectlist.h"  #include "llviewermessage.h"	// for handle_lure +#include "llviewernetwork.h" //LLGridManager  #include "llviewerregion.h"  #include "lltrans.h"  #include "llcallingcard.h" @@ -81,6 +83,18 @@ const U32 KICK_FLAGS_FREEZE		= 1 << 0;  const U32 KICK_FLAGS_UNFREEZE	= 1 << 1; +std::string getProfileURL(const std::string& agent_name) +{ +	std::string url = "[WEB_PROFILE_URL][AGENT_NAME]"; +	LLSD subs; +	subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); +	subs["AGENT_NAME"] = agent_name; +	url = LLWeb::expandURLSubstitutions(url, subs); +	LLStringUtil::toLower(url); +	return url; +} + +  // static  void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)  { @@ -319,7 +333,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float  static const char* get_profile_floater_name(const LLUUID& avatar_id)  {  	// Use different floater XML for our profile to be able to save its rect. -	return avatar_id == gAgentID ? "my_profile" : "profile"; +	return avatar_id == gAgentID ? "my_profile_web" : "profile_web";  }  static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) @@ -333,40 +347,101 @@ static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarNa  }  // static -void LLAvatarActions::showProfile(const LLUUID& id) +void LLAvatarActions::showProfile(const LLUUID& avatar_id) +{ +	if (avatar_id.notNull()) +	{ +		LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id)); +	} +} + +// static +void LLAvatarActions::showPicks(const LLUUID& avatar_id)  { -	if (id.notNull()) +	if (avatar_id.notNull())  	{ -		LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_show_profile, _1, _2)); +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showPick(); +        } +	} +} + +// static +void LLAvatarActions::showPick(const LLUUID& avatar_id, const LLUUID& pick_id) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showPick(pick_id); +        } +	} +} + +// static +void LLAvatarActions::showClassifieds(const LLUUID& avatar_id) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showClassified(); +        } +	} +} + +// static +void LLAvatarActions::showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showClassified(classified_id, edit); +        }  	}  }  //static  -bool LLAvatarActions::profileVisible(const LLUUID& id) +bool LLAvatarActions::profileVisible(const LLUUID& avatar_id)  {  	LLSD sd; -	sd["id"] = id; -	LLFloater* browser = getProfileFloater(id); -	return browser && browser->isShown(); +	sd["id"] = avatar_id; +	LLFloater* floater = getProfileFloater(avatar_id); +	return floater && floater->isShown();  }  //static -LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& id) +LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& avatar_id) +{ +    LLFloaterProfile* floater = LLFloaterReg::findTypedInstance<LLFloaterProfile>("profile", LLSD().with("id", avatar_id)); +    return floater; +} + +// static +void LLAvatarActions::showProfileWeb(const LLUUID& avatar_id)  { -	LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> -		(LLFloaterReg::findInstance(get_profile_floater_name(id), LLSD().with("id", id))); -	return browser; +    if (avatar_id.notNull()) +    { +        LLAvatarNameCache::get(avatar_id, boost::bind(&on_avatar_name_show_profile, _1, _2)); +    }  } +  //static  -void LLAvatarActions::hideProfile(const LLUUID& id) +void LLAvatarActions::hideProfile(const LLUUID& avatar_id)  {  	LLSD sd; -	sd["id"] = id; -	LLFloater* browser = getProfileFloater(id); -	if (browser) +	sd["id"] = avatar_id; +	LLFloater* floater = getProfileFloater(avatar_id); +	if (floater)  	{ -		browser->closeFloater(); +		floater->closeFloater();  	}  } diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index b56d5b0fb9..3383b3f5f9 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -38,6 +38,8 @@ class LLInventoryPanel;  class LLFloater;  class LLView; +std::string getProfileURL(const std::string& agent_name); +  /**   * Friend-related actions (add, remove, offer teleport, etc)   */ @@ -91,13 +93,18 @@ public:  	 */  	static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); -	/** -	 * Show avatar profile. -	 */ -	static void showProfile(const LLUUID& id); -	static void hideProfile(const LLUUID& id); -	static bool profileVisible(const LLUUID& id); -	static LLFloater* getProfileFloater(const LLUUID& id); +    /** +     * Show avatar profile. +     */ +    static void showProfile(const LLUUID& avatar_id); +    static void showPicks(const LLUUID& avatar_id); +    static void showPick(const LLUUID& avatar_id, const LLUUID& pick_id); +    static void showClassifieds(const LLUUID& avatar_id); +    static void showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit = false); +    static void hideProfile(const LLUUID& avatar_id); +    static bool profileVisible(const LLUUID& avatar_id); +    static LLFloater* getProfileFloater(const LLUUID& avatar_id); +    static void showProfileWeb(const LLUUID& avatar_id);  	/**  	 * Show avatar on world map. diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 856eb3414e..44ca3c1b5f 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -299,6 +299,21 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m  	That will suppress the warnings and be compatible with old server versions.  	WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply  */ + +    LLInterestsData interests_data; +     +    msg->getUUIDFast(   _PREHASH_AgentData,         _PREHASH_AgentID,       interests_data.agent_id ); +    msg->getUUIDFast(   _PREHASH_AgentData,         _PREHASH_AvatarID,      interests_data.avatar_id ); +    msg->getU32Fast(    _PREHASH_PropertiesData,	_PREHASH_WantToMask,    interests_data.want_to_mask ); +    msg->getStringFast( _PREHASH_PropertiesData,    _PREHASH_WantToText,    interests_data.want_to_text ); +    msg->getU32Fast(    _PREHASH_PropertiesData,	_PREHASH_SkillsMask,    interests_data.skills_mask ); +    msg->getStringFast( _PREHASH_PropertiesData,    _PREHASH_SkillsText,    interests_data.skills_text ); +    msg->getString(     _PREHASH_PropertiesData,    _PREHASH_LanguagesText, interests_data.languages_text ); +     +    LLAvatarPropertiesProcessor* self = getInstance(); +    // Request processed, no longer pending +    self->removePendingRequest(interests_data.avatar_id, APT_INTERESTS_INFO); +    self->notifyObservers(interests_data.avatar_id, &interests_data, APT_INTERESTS_INFO);  }  void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**) @@ -538,6 +553,29 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_  	gAgent.sendReliableMessage();  } +void LLAvatarPropertiesProcessor::sendInterestsInfoUpdate(const LLInterestsData* interests_data) +{ +    if(!interests_data) +    { +        return; +    } + +    LLMessageSystem* msg = gMessageSystem; + +    msg->newMessage(_PREHASH_AvatarInterestsUpdate); +    msg->nextBlockFast( _PREHASH_AgentData); +    msg->addUUIDFast(	_PREHASH_AgentID,       gAgent.getID() ); +    msg->addUUIDFast(   _PREHASH_SessionID,     gAgent.getSessionID() ); +    msg->nextBlockFast( _PREHASH_PropertiesData); +    msg->addU32Fast(	_PREHASH_WantToMask,    interests_data->want_to_mask); +    msg->addStringFast(	_PREHASH_WantToText,    interests_data->want_to_text); +    msg->addU32Fast(	_PREHASH_SkillsMask,    interests_data->skills_mask); +    msg->addStringFast(	_PREHASH_SkillsText,    interests_data->skills_text); +    msg->addString(     _PREHASH_LanguagesText, interests_data->languages_text); +     +    gAgent.sendReliableMessage(); +} +  void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)  {  	if (!new_pick) return; diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index d5c5c75c69..1c981d5b2e 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -56,10 +56,22 @@ enum EAvatarProcessorType  	APT_PICKS,  	APT_PICK_INFO,  	APT_TEXTURES, +    APT_INTERESTS_INFO,  	APT_CLASSIFIEDS,  	APT_CLASSIFIED_INFO  }; +struct LLInterestsData +{ +    LLUUID      agent_id; +    LLUUID      avatar_id; //target id +    U32         want_to_mask; +    std::string want_to_text; +    U32         skills_mask; +    std::string skills_text; +    std::string languages_text; +}; +  struct LLAvatarData  {  	LLUUID 		agent_id; @@ -223,6 +235,8 @@ public:  	void sendClassifiedDelete(const LLUUID& classified_id); +    void sendInterestsInfoUpdate(const LLInterestsData* interests_data); +  	// Returns translated, human readable string for account type, such  	// as "Resident" or "Linden Employee".  Used for profiles, inspectors.  	static std::string accountType(const LLAvatarData* avatar_data); diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp new file mode 100644 index 0000000000..596e8c0dbe --- /dev/null +++ b/indra/newview/llfloaterdisplayname.cpp @@ -0,0 +1,217 @@ +/**  + * @file llfloaterdisplayname.cpp + * @author Leyla Farazha + * @brief Implementation of the LLFloaterDisplayName class. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llfloaterreg.h" +#include "llfloater.h" + +#include "llnotificationsutil.h" +#include "llviewerdisplayname.h" + +#include "llnotifications.h" +#include "llfloaterdisplayname.h" +#include "llavatarnamecache.h" + +#include "llagent.h" + + +class LLFloaterDisplayName : public LLFloater +{ +public: +	LLFloaterDisplayName(const LLSD& key); +	virtual ~LLFloaterDisplayName() { } +	/*virtual*/	BOOL	postBuild(); +	void onSave(); +	void onReset(); +	void onCancel(); +	/*virtual*/ void onOpen(const LLSD& key); +	 +private: +	 +	void onCacheSetName(bool success, +										  const std::string& reason, +										  const LLSD& content); +}; + +LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) : +	LLFloater(key) +{ +} + +void LLFloaterDisplayName::onOpen(const LLSD& key) +{ +	getChild<LLUICtrl>("display_name_editor")->clear(); +	getChild<LLUICtrl>("display_name_confirm")->clear(); + +	LLAvatarName av_name; +	LLAvatarNameCache::get(gAgent.getID(), &av_name); + +	F64 now_secs = LLDate::now().secondsSinceEpoch(); + +	if (now_secs < av_name.mNextUpdate) +	{ +		// ...can't update until some time in the future +		F64 next_update_local_secs = +			av_name.mNextUpdate - LLStringOps::getLocalTimeOffset(); +		LLDate next_update_local(next_update_local_secs); +		// display as "July 18 12:17 PM" +		std::string next_update_string = +		next_update_local.toHTTPDateString("%B %d %I:%M %p"); +		getChild<LLUICtrl>("lockout_text")->setTextArg("[TIME]", next_update_string); +		getChild<LLUICtrl>("lockout_text")->setVisible(true); +		getChild<LLUICtrl>("save_btn")->setEnabled(false); +		getChild<LLUICtrl>("display_name_editor")->setEnabled(false); +		getChild<LLUICtrl>("display_name_confirm")->setEnabled(false); +		getChild<LLUICtrl>("cancel_btn")->setFocus(TRUE); +		 +	} +	else +	{ +		getChild<LLUICtrl>("lockout_text")->setVisible(false); +		getChild<LLUICtrl>("save_btn")->setEnabled(true); +		getChild<LLUICtrl>("display_name_editor")->setEnabled(true); +		getChild<LLUICtrl>("display_name_confirm")->setEnabled(true); + +	} +} + +BOOL LLFloaterDisplayName::postBuild() +{ +	getChild<LLUICtrl>("reset_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onReset, this));	 +	getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onCancel, this));	 +	getChild<LLUICtrl>("save_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onSave, this));	 +	 +	center(); + +	return TRUE; +} + +void LLFloaterDisplayName::onCacheSetName(bool success, +										  const std::string& reason, +										  const LLSD& content) +{ +	if (success) +	{ +		// Inform the user that the change took place, but will take a while +		// to percolate. +		LLSD args; +		args["DISPLAY_NAME"] = content["display_name"]; +		LLNotificationsUtil::add("SetDisplayNameSuccess", args); +		return; +	} + +	// Request failed, notify the user +	std::string error_tag = content["error_tag"].asString(); +	LL_INFOS() << "set name failure error_tag " << error_tag << LL_ENDL; + +	// We might have a localized string for this message +	// error_args will usually be empty from the server. +	if (!error_tag.empty() +		&& LLNotifications::getInstance()->templateExists(error_tag)) +	{ +		LLNotificationsUtil::add(error_tag); +		return; +	} + +	// The server error might have a localized message for us +	std::string lang_code = LLUI::getLanguage(); +	LLSD error_desc = content["error_description"]; +	if (error_desc.has( lang_code )) +	{ +		LLSD args; +		args["MESSAGE"] = error_desc[lang_code].asString(); +		LLNotificationsUtil::add("GenericAlert", args); +		return; +	} + +	// No specific error, throw a generic one +	LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +} + +void LLFloaterDisplayName::onCancel() +{ +	setVisible(false); +} + +void LLFloaterDisplayName::onReset() +{ +	if (LLAvatarNameCache::hasNameLookupURL()) +	{ +		LLViewerDisplayName::set("",boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3)); +	}	 +	else +	{ +		LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +	} +	 +	setVisible(false); +} + + +void LLFloaterDisplayName::onSave() +{ +	std::string display_name_utf8 = getChild<LLUICtrl>("display_name_editor")->getValue().asString(); +	std::string display_name_confirm = getChild<LLUICtrl>("display_name_confirm")->getValue().asString(); + +	if (display_name_utf8.compare(display_name_confirm)) +	{ +		LLNotificationsUtil::add("SetDisplayNameMismatch"); +		return; +	} + +	const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes +	LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8); +	if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH) +	{ +		LLSD args; +		args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH); +		LLNotificationsUtil::add("SetDisplayNameFailedLength", args); +		return; +	} +	 +	if (LLAvatarNameCache::hasNameLookupURL()) +	{ +		LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3));	 +	} +	else +	{ +		LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +	} + +	setVisible(false); +} + + +////////////////////////////////////////////////////////////////////////////// +// LLInspectObjectUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterDisplayNameUtil::registerFloater() +{ +	LLFloaterReg::add("display_name", "floater_display_name.xml", +					  &LLFloaterReg::build<LLFloaterDisplayName>); +} diff --git a/indra/newview/llpanelme.h b/indra/newview/llfloaterdisplayname.h index 60e9d4317d..a00bf56712 100644 --- a/indra/newview/llpanelme.h +++ b/indra/newview/llfloaterdisplayname.h @@ -1,6 +1,5 @@  /**  - * @file llpanelme.h - * @brief Side tray "Me" (My Profile) panel + * @file llfloaterdisplayname.h   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -24,27 +23,16 @@   * $/LicenseInfo$   */ -#ifndef LL_LLPANELMEPROFILE_H -#define LL_LLPANELMEPROFILE_H +#ifndef LLFLOATERDISPLAYNAME_H +#define LLFLOATERDISPLAYNAME_H -#include "llpanel.h" -#include "llpanelprofile.h" -/** -* Panel for displaying Agent's Picks and Classifieds panel. -* LLPanelMe allows user to edit his picks and classifieds. -*/ -class LLPanelMe : public LLPanelProfile +namespace LLFloaterDisplayNameUtil  { -	LOG_CLASS(LLPanelMe); +	// Register with LLFloaterReg +	void registerFloater(); +} -public: -	LLPanelMe(); -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ BOOL postBuild(); -}; - -#endif // LL_LLPANELMEPROFILE_H +#endif diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp index d80793f9e4..4fbb64a1db 100644 --- a/indra/newview/llfloateroutfitsnapshot.cpp +++ b/indra/newview/llfloateroutfitsnapshot.cpp @@ -46,7 +46,6 @@  #include "llviewercontrol.h"  #include "lltoolfocus.h"  #include "lltoolmgr.h" -#include "llwebprofile.h"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llfloaterprofile.cpp b/indra/newview/llfloaterprofile.cpp new file mode 100644 index 0000000000..6b8f881b08 --- /dev/null +++ b/indra/newview/llfloaterprofile.cpp @@ -0,0 +1,107 @@ +/** + * @file llfloaterprofile.cpp + * @brief Avatar profile floater. + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llfloaterprofile.h" + +#include "llpanelavatar.h" +#include "llpanelprofile.h" +#include "llagent.h" //gAgent + +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +LLFloaterProfile::LLFloaterProfile(const LLSD& key) + : LLFloater(key), + mAvatarId(key["id"].asUUID()), + mNameCallbackConnection() +{ +} + +LLFloaterProfile::~LLFloaterProfile() +{ +    if (mNameCallbackConnection.connected()) +    { +        mNameCallbackConnection.disconnect(); +    } +} + +void LLFloaterProfile::onOpen(const LLSD& key) +{ +    mPanelProfile->onOpen(key); + +    if (mAvatarId == gAgentID) +    { +        getChild<LLUICtrl>("ok_btn")->setVisible(TRUE); +        getChild<LLUICtrl>("cancel_btn")->setVisible(TRUE); +    } + +    // Update the avatar name. +    mNameCallbackConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLFloaterProfile::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLFloaterProfile::postBuild() +{ +    mPanelProfile = findChild<LLPanelProfile>(PANEL_PROFILE_VIEW); + +    childSetAction("ok_btn", boost::bind(&LLFloaterProfile::onOKBtn, this)); +    childSetAction("cancel_btn", boost::bind(&LLFloaterProfile::onCancelBtn, this)); + +    return TRUE; +} + +void LLFloaterProfile::showPick(const LLUUID& pick_id) +{ +    mPanelProfile->showPick(pick_id); +} + +void LLFloaterProfile::showClassified(const LLUUID& classified_id, bool edit) +{ +    mPanelProfile->showClassified(classified_id, edit); +} + +void LLFloaterProfile::onOKBtn() +{ +    if (mAvatarId == gAgentID) +    { +        mPanelProfile->apply(); +    } + +    closeFloater(); +} + +void LLFloaterProfile::onCancelBtn() +{ +    closeFloater(); +} + +void LLFloaterProfile::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mNameCallbackConnection.disconnect(); +    setTitle(av_name.getCompleteName()); +} + +// eof diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llfloaterprofile.h index 55e4ffff5e..fa06347cee 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llfloaterprofile.h @@ -1,67 +1,62 @@ -/**  - * @file llpanelme.cpp - * @brief Side tray "Me" (My Profile) panel +/** + * @file llfloaterprofile.h + * @brief Avatar profile floater.   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, 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" +#ifndef LL_LLFLOATERPROFILE_H +#define LL_LLFLOATERPROFILE_H -#include "llpanelme.h" +#include "llavatarnamecache.h" +#include "llfloater.h" -// Viewer includes -#include "llpanelprofile.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llfirstuse.h" -#include "llfloaterreg.h" -#include "llhints.h" -#include "llviewercontrol.h" +class LLPanelProfile; -// Linden libraries -#include "llavatarnamecache.h"		// IDEVO -#include "lliconctrl.h" -#include "llnotifications.h" -#include "llnotificationsutil.h"	// IDEVO -#include "lltabcontainer.h" -#include "lltexturectrl.h" +class LLFloaterProfile : public LLFloater +{ +    LOG_CLASS(LLFloaterProfile); +public: +    LLFloaterProfile(const LLSD& key); +    virtual ~LLFloaterProfile(); -static LLPanelInjector<LLPanelMe> t_panel_me_profile("panel_me"); +    /*virtual*/ void onOpen(const LLSD& key); +    /*virtual*/ BOOL postBuild(); -LLPanelMe::LLPanelMe(void)  - : LLPanelProfile() -{ -	setAvatarId(gAgent.getID()); -} +    void showPick(const LLUUID& pick_id = LLUUID::null); -BOOL LLPanelMe::postBuild() -{ -	LLPanelProfile::postBuild(); +    void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); -	return TRUE; -} +protected: +    void onOKBtn(); +    void onCancelBtn(); -void LLPanelMe::onOpen(const LLSD& key) -{ -	LLPanelProfile::onOpen(key); -} +private: +    LLAvatarNameCache::callback_connection_t mNameCallbackConnection; +    void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +    LLPanelProfile* mPanelProfile; + +    LLUUID mAvatarId; +}; + +#endif // LL_LLFLOATERPROFILE_H diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 62414d3bbb..3a81d1557e 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -65,22 +65,46 @@ public:  	}  }; -static const LLGroupComparator GROUP_COMPARATOR; +static LLGroupComparator GROUP_COMPARATOR; +LLGroupList::Params::Params() +: for_agent("for_agent", true) +{ +}  LLGroupList::LLGroupList(const Params& p)  :	LLFlatListViewEx(p) +    , mForAgent(p.for_agent)  	, mDirty(true) // to force initial update +    , mShowIcons(false) +    , mShowNone(true)  { -	// Listen for agent group changes. -	gAgent.addListener(this, "new group"); - -	mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");  	setCommitOnSelectionChange(true);  	// Set default sort order.  	setComparator(&GROUP_COMPARATOR); +    if (mForAgent) +	{ +        enableForAgent(true); +    } +} + +LLGroupList::~LLGroupList() +{ +    if (mForAgent) gAgent.removeListener(this); +    if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); +} + +void LLGroupList::enableForAgent(bool show_icons) +{ +    mForAgent = true; + +    mShowIcons = mForAgent && gSavedSettings.getBOOL("GroupListShowIcons") && show_icons; + +    // Listen for agent group changes. +    gAgent.addListener(this, "new group"); +  	// Set up context menu.  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; @@ -94,12 +118,6 @@ LLGroupList::LLGroupList(const Params& p)  		mContextMenuHandle = context_menu->getHandle();  } -LLGroupList::~LLGroupList() -{ -	gAgent.removeListener(this); -	if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); -} -  // virtual  void LLGroupList::draw()  { @@ -114,12 +132,15 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); -	LLToggleableMenu* context_menu = mContextMenuHandle.get(); -	if (context_menu && size() > 0) -	{ -		context_menu->buildDrawLabels(); -		context_menu->updateParent(LLMenuGL::sMenuContainer); -		LLMenuGL::showPopup(this, context_menu, x, y); +    if (mForAgent) +    { +        LLToggleableMenu* context_menu = mContextMenuHandle.get(); +        if (context_menu && size() > 0) +        { +            context_menu->buildDrawLabels(); +            context_menu->updateParent(LLMenuGL::sMenuContainer); +            LLMenuGL::showPopup(this, context_menu, x, y); +        }  	}  	return handled; @@ -164,34 +185,49 @@ static bool findInsensitive(std::string haystack, const std::string& needle_uppe  void LLGroupList::refresh()  { -	const LLUUID& 		highlight_id	= gAgent.getGroupID(); -	S32					count			= gAgent.mGroups.size(); -	LLUUID				id; -	bool				have_filter		= !mNameFilter.empty(); - -	clear(); - -	for(S32 i = 0; i < count; ++i) -	{ -		id = gAgent.mGroups.at(i).mID; -		const LLGroupData& group_data = gAgent.mGroups.at(i); -		if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) -			continue; -		addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM); -	} - -	// Sort the list. -	sort(); - -	// Add "none" to list at top if filter not set (what's the point of filtering "none"?). -	// but only if some real groups exists. EXT-4838 -	if (!have_filter && count > 0) -	{ -		std::string loc_none = LLTrans::getString("GroupsNone"); -		addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); -	} - -	selectItemByUUID(highlight_id); +    if (mForAgent) +    { +        const LLUUID& 		highlight_id	= gAgent.getGroupID(); +        S32					count			= gAgent.mGroups.size(); +        LLUUID				id; +        bool				have_filter		= !mNameFilter.empty(); + +        clear(); + +        for(S32 i = 0; i < count; ++i) +        { +            id = gAgent.mGroups.at(i).mID; +            const LLGroupData& group_data = gAgent.mGroups.at(i); +            if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) +                continue; +            addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile); +        } + +        // Sort the list. +        sort(); + +        // Add "none" to list at top if filter not set (what's the point of filtering "none"?). +        // but only if some real groups exists. EXT-4838 +        if (!have_filter && count > 0 && mShowNone) +        { +            std::string loc_none = LLTrans::getString("GroupsNone"); +            addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); +        } + +        selectItemByUUID(highlight_id); +    } +    else +    { +        clear(); + +        for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) +        { +            addNewItem(it->second, it->first, LLUUID::null, ADD_BOTTOM); +        } + +        // Sort the list. +        sort(); +    }  	setDirty(false);  	onCommit(); @@ -212,13 +248,19 @@ void LLGroupList::toggleIcons()  	}  } +void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list) +{ +    mGroups = group_list; +    setDirty(true); +} +  //////////////////////////////////////////////////////////////////////////  // PRIVATE Section  ////////////////////////////////////////////////////////////////////////// -void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos) +void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)  { -	LLGroupListItem* item = new LLGroupListItem(); +	LLGroupListItem* item = new LLGroupListItem(mForAgent && mShowIcons);  	item->setGroupID(id);  	item->setName(name, mNameFilter); @@ -227,7 +269,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL  	item->getChildView("info_btn")->setVisible( false);  	item->getChildView("profile_btn")->setVisible( false);  	item->setGroupIconVisible(mShowIcons); - +    item->setVisibleInProfile(visible_in_profile);  	addItem(item, id, pos);  //	setCommentVisible(false); @@ -243,6 +285,29 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD&  		return true;  	} +    if (event->desc() == "value_changed") +    { +        LLSD data = event->getValue(); +        if (data.has("group_id") && data.has("visible")) +        { +            LLUUID group_id = data["group_id"].asUUID(); +            bool visible = data["visible"].asBoolean(); + +            std::vector<LLPanel*> items; +            getItems(items); +            for (std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) +            { +                LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(*it); +                if (item && item->getGroupID() == group_id) +                { +                    item->setVisibleInProfile(visible); +                    break; +                } +            } +        } +        return true; +    } +  	return false;  } @@ -294,18 +359,25 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)  /*          LLGroupListItem implementation                              */  /************************************************************************/ -LLGroupListItem::LLGroupListItem() +LLGroupListItem::LLGroupListItem(bool for_agent)  :	LLPanel(),  mGroupIcon(NULL),  mGroupNameBox(NULL),  mInfoBtn(NULL),  mGroupID(LLUUID::null)  { -	buildFromFile( "panel_group_list_item.xml"); +    if (for_agent) +    { +        buildFromFile( "panel_group_list_item.xml"); +    } +    else +    { +        buildFromFile( "panel_group_list_item_short.xml"); +    }  	// Remember group icon width including its padding from the name text box,  	// so that we can hide and show the icon again later. -	if (!sIconWidth) +    if (!sIconWidth && mGroupNameBox)  	{  		sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft;  	} @@ -397,6 +469,11 @@ void LLGroupListItem::setGroupIconVisible(bool visible)  	mGroupNameBox->setRect(name_rect);  } +void LLGroupListItem::setVisibleInProfile(bool visible) +{ +    mGroupNameBox->setColor(LLUIColorTable::instance().getColor((visible ? "GroupVisibleInProfile" : "GroupHiddenInProfile"), LLColor4::red).get()); +} +  //////////////////////////////////////////////////////////////////////////  // Private Section  ////////////////////////////////////////////////////////////////////////// @@ -433,8 +510,10 @@ void LLGroupListItem::onProfileBtnClick()  void LLGroupListItem::changed(LLGroupChange gc)  {  	LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); -	if(group_data) -		setGroupIconID(group_data->mInsigniaID); +	if ((gc == GC_ALL || gc == GC_PROPERTIES) && group_data) +    { +        setGroupIconID(group_data->mInsigniaID); +    }  }  //EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 171b77fb00..063b50f5c5 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -50,12 +50,15 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener  public:  	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params>  	{ -		Params(){}; +        Optional<bool> for_agent; +        Params();  	};  	LLGroupList(const Params& p);  	virtual ~LLGroupList(); +    void enableForAgent(bool show_icons); +  	virtual void draw(); // from LLView  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView  	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView @@ -63,13 +66,16 @@ public:  	void setNameFilter(const std::string& filter);  	void toggleIcons();  	bool getIconsVisible() const { return mShowIcons; } +    void setIconsVisible(bool show_icons) { mShowIcons = show_icons; } +    void setShowNone(bool show_none) { mShowNone = show_none; } +    void setGroups(const std::map< std::string,LLUUID> group_list);  	LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); }  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); -	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM); +	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);  	bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes  	bool onContextMenuItemClick(const LLSD& userdata); @@ -80,6 +86,11 @@ private:  	bool mShowIcons;  	bool mDirty;  	std::string mNameFilter; + +    bool mForAgent; +    bool mShowNone; +    typedef std::map< std::string,LLUUID>	group_map_t; +    group_map_t 			mGroups;  };  class LLButton; @@ -90,7 +101,7 @@ class LLGroupListItem : public LLPanel  	, public LLGroupMgrObserver  {  public: -	LLGroupListItem(); +    LLGroupListItem(bool for_agent);  	~LLGroupListItem();  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setValue(const LLSD& value); @@ -106,6 +117,8 @@ public:  	void setGroupIconVisible(bool visible);  	virtual void changed(LLGroupChange gc); + +    void setVisibleInProfile(bool visible);  private:  	void setActive(bool active);  	void onInfoBtnClick(); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 5d1b582d1f..dbda6070fa 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file llpanelavatar.cpp   * @brief LLPanelAvatar and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, 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$   */ @@ -28,172 +28,107 @@  #include "llpanelavatar.h"  #include "llagent.h" -#include "llavataractions.h" -#include "llcallingcard.h" -#include "llcombobox.h" -#include "lldateutil.h"			// ageFromDate() -#include "llimview.h" -#include "llmenubutton.h" -#include "llnotificationsutil.h" -#include "llslurl.h" -#include "lltexteditor.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" +#include "llloadingindicator.h"  #include "lltooldraganddrop.h" -#include "llscrollcontainer.h" -#include "llavatariconctrl.h" -#include "llfloaterreg.h" -#include "llnotificationsutil.h" -#include "llvoiceclient.h" -#include "lltextbox.h" -#include "lltrans.h" - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLDropTarget -// -// This handy class is a simple way to drop something on another -// view. It handles drop events, always setting itself to the size of -// its parent. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLDropTarget : public LLView -{ -public: -	struct Params : public LLInitParam::Block<Params, LLView::Params> -	{ -		Optional<LLUUID> agent_id; -		Params() -		:	agent_id("agent_id") -		{ -			changeDefault(mouse_opaque, false); -			changeDefault(follows.flags, FOLLOWS_ALL); -		} -	}; - -	LLDropTarget(const Params&); -	~LLDropTarget(); - -	void doDrop(EDragAndDropType cargo_type, void* cargo_data); - -	// -	// LLView functionality -	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -								   EDragAndDropType cargo_type, -								   void* cargo_data, -								   EAcceptance* accept, -								   std::string& tooltip_msg); -	void setAgentID(const LLUUID &agent_id)		{ mAgentID = agent_id; } -protected: -	LLUUID mAgentID; -}; - -LLDropTarget::LLDropTarget(const LLDropTarget::Params& p)  -:	LLView(p), -	mAgentID(p.agent_id) -{} -LLDropTarget::~LLDropTarget() +////////////////////////////////////////////////////////////////////////// +// LLProfileDropTarget + +LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p) +:   LLView(p), +    mAgentID(p.agent_id)  {} -void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) +void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)  { -	LL_INFOS() << "LLDropTarget::doDrop()" << LL_ENDL; +    LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL;  } -BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -									 EDragAndDropType cargo_type, -									 void* cargo_data, -									 EAcceptance* accept, -									 std::string& tooltip_msg) +BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +                                     EDragAndDropType cargo_type, +                                     void* cargo_data, +                                     EAcceptance* accept, +                                     std::string& tooltip_msg)  { -	if(getParent()) -	{ -		LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, -												 cargo_type, cargo_data, accept); +    if (getParent()) +    { +        LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, +                                                 cargo_type, cargo_data, accept); -		return TRUE; -	} +        return TRUE; +    } -	return FALSE; +    return FALSE;  } -static LLDefaultChildRegistry::Register<LLDropTarget> r("drop_target"); +static LLDefaultChildRegistry::Register<LLProfileDropTarget> r("profile_drop_target");  ////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// +// LLPanelProfileTab  LLPanelProfileTab::LLPanelProfileTab()  : LLPanel()  , mAvatarId(LLUUID::null) +, mLoading(false) +, mLoaded(false) +, mEmbedded(false) +, mSelfProfile(false)  {  }  LLPanelProfileTab::~LLPanelProfileTab()  { -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); -	} +    if(getAvatarId().notNull()) +    { +        LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); +    }  } -void LLPanelProfileTab::setAvatarId(const LLUUID& id) +void LLPanelProfileTab::setAvatarId(const LLUUID& avatar_id)  { -	if(id.notNull()) -	{ -		if(getAvatarId().notNull()) -		{ -			LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this); -		} -		mAvatarId = id; -		LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this); -	} +    if (avatar_id.notNull()) +    { +        if (getAvatarId().notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this); +        } +        mAvatarId = avatar_id; +        LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); + +        mSelfProfile = (getAvatarId() == gAgentID); +    }  }  void LLPanelProfileTab::onOpen(const LLSD& key)  { -	// Don't reset panel if we are opening it for same avatar. -	if(getAvatarId() != key.asUUID()) -	{ -		resetControls(); -		resetData(); - -		scrollToTop(); -	} - -	// Update data even if we are viewing same avatar profile as some data might been changed. -	setAvatarId(key.asUUID()); -	updateData(); -	updateButtons(); -} +    // Update data even if we are viewing same avatar profile as some data might been changed. +    setAvatarId(key.asUUID()); -void LLPanelProfileTab::scrollToTop() -{ -	LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll"); -	if (scrollContainer) -		scrollContainer->goToTop(); +    setApplyProgress(true);  } -void LLPanelProfileTab::onMapButtonClick() +void LLPanelProfileTab::updateButtons()  { -	LLAvatarActions::showOnMap(getAvatarId()); +    setApplyProgress(false); + +    mLoaded = true;  } -void LLPanelProfileTab::updateButtons() +void LLPanelProfileTab::setApplyProgress(bool started)  { -	bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); -	 -	if(LLAvatarActions::isFriend(getAvatarId())) -	{ -		getChildView("teleport")->setEnabled(is_buddy_online); -	} -	else -	{ -		getChildView("teleport")->setEnabled(true); -	} - -	bool enable_map_btn = (is_buddy_online && -			       is_agent_mappable(getAvatarId())) -		|| gAgent.isGodlike(); -	getChildView("show_on_map_btn")->setEnabled(enable_map_btn); +    LLLoadingIndicator* indicator = findChild<LLLoadingIndicator>("progress_indicator"); + +    if (indicator) +    { +        indicator->setVisible(started); + +        if (started) +        { +            indicator->start(); +        } +        else +        { +            indicator->stop(); +        } +    }  } diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index e33a850cfa..f73ea0643d 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -1,25 +1,25 @@ -/**  +/**   * @file llpanelavatar.h - * @brief LLPanelAvatar and related class definitions + * @brief Legacy profile panel base class   * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2019&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  + * Copyright (C) 2019, 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$   */ @@ -29,80 +29,125 @@  #include "llpanel.h"  #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llvoiceclient.h"  #include "llavatarnamecache.h"  class LLComboBox;  class LLLineEditor; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLProfileDropTarget +// +// This handy class is a simple way to drop something on another +// view. It handles drop events, always setting itself to the size of +// its parent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLProfileDropTarget : public LLView +{ +public: +    struct Params : public LLInitParam::Block<Params, LLView::Params> +    { +        Optional<LLUUID> agent_id; +        Params() +        :   agent_id("agent_id") +        { +            changeDefault(mouse_opaque, false); +            changeDefault(follows.flags, FOLLOWS_ALL); +        } +    }; + +    LLProfileDropTarget(const Params&); +    ~LLProfileDropTarget() {} + +    void doDrop(EDragAndDropType cargo_type, void* cargo_data); + +    // +    // LLView functionality +    virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +                                   EDragAndDropType cargo_type, +                                   void* cargo_data, +                                   EAcceptance* accept, +                                   std::string& tooltip_msg); + +    void setAgentID(const LLUUID &agent_id)     { mAgentID = agent_id; } + +protected: +    LLUUID mAgentID; +}; + +  /**  * Base class for any Profile View.  */  class LLPanelProfileTab -	: public LLPanel -	, public LLAvatarPropertiesObserver +    : public LLPanel +    , public LLAvatarPropertiesObserver  {  public: -	/** -	 * Sets avatar ID, sets panel as observer of avatar related info replies from server. -	 */ -	virtual void setAvatarId(const LLUUID& id); - -	/** -	 * Returns avatar ID. -	 */ -	virtual const LLUUID& getAvatarId() { return mAvatarId; } - -	/** -	 * Sends update data request to server. -	 */ -	virtual void updateData() = 0; - -	/** -	 * Clears panel data if viewing avatar info for first time and sends update data request. -	 */ -	virtual void onOpen(const LLSD& key); - -	/** -	 * Profile tabs should close any opened panels here. -	 * -	 * Called from LLPanelProfile::onOpen() before opening new profile. -	 * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel -	 * before new profile is displayed, otherwise new profile will  -	 * be hidden behind picture info panel. -	 */ -	virtual void onClosePanel() {} - -	/** -	 * Resets controls visibility, state, etc. -	 */ -	virtual void resetControls(){}; - -	/** -	 * Clears all data received from server. -	 */ -	virtual void resetData(){}; - -	/*virtual*/ ~LLPanelProfileTab(); +    /** +     * Sets avatar ID, sets panel as observer of avatar related info replies from server. +     */ +    virtual void setAvatarId(const LLUUID& avatar_id); + +    /** +     * Returns avatar ID. +     */ +    virtual const LLUUID& getAvatarId() { return mAvatarId; } + +    /** +     * Sends update data request to server. +     */ +    virtual void updateData() {}; + +    /** +     * Clears panel data if viewing avatar info for first time and sends update data request. +     */ +    virtual void onOpen(const LLSD& key); + +    /** +     * Processes data received from server. +     */ +    virtual void processProperties(void* data, EAvatarProcessorType type) = 0; + +    /** +     * Clears all data received from server. +     */ +    virtual void resetData(){}; + +    /*virtual*/ ~LLPanelProfileTab(); + +    void setEmbedded(bool embedded) { mEmbedded = embedded; }  protected: -	LLPanelProfileTab(); +    LLPanelProfileTab(); + + +    // mLoading: false: Initial state, can request +    //           true:  Data requested, skip duplicate requests (happens due to LLUI's habit of repeated callbacks) +    // mLoaded:  false: Initial state, show loading indicator +    //           true:  Data recieved, which comes in a single message, hide indicator +    bool getIsLoading() { return mLoading; } +    void setIsLoading() { mLoading = true; } +    bool getIsLoaded() { return mLoaded; } +    void resetLoading() { mLoading = false; mLoaded = false; } + +    const bool getEmbedded() const { return mEmbedded; } -	/** -	 * Scrolls panel to top when viewing avatar info for first time. -	 */ -	void scrollToTop(); +    const bool getSelfProfile() const { return mSelfProfile; } -	virtual void onMapButtonClick(); +    void setApplyProgress(bool started); -	virtual void updateButtons(); +    virtual void updateButtons();  private: -	LLUUID mAvatarId; +    LLUUID  mAvatarId; +    bool    mLoading; +    bool    mLoaded; +    bool    mEmbedded; +    bool    mSelfProfile;  };  #endif // LL_LLPANELAVATAR_H diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp deleted file mode 100644 index b9b97f4cce..0000000000 --- a/indra/newview/llpanelclassified.cpp +++ /dev/null @@ -1,1178 +0,0 @@ -/**  - * @file llpanelclassified.cpp - * @brief LLPanelClassified class implementation - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -// Display of a classified used both for the global view in the -// Find directory, and also for each individual user's classified in their -// profile. - -#include "llviewerprecompiledheaders.h" - -#include "llpanelclassified.h" - -#include "lldispatcher.h" -#include "llfloaterreg.h" -#include "llnotifications.h" -#include "llnotificationsutil.h" -#include "llparcel.h" - -#include "llagent.h" -#include "llclassifiedflags.h" -#include "llcommandhandler.h" // for classified HTML detail page click tracking -#include "lliconctrl.h" -#include "lllineeditor.h" -#include "llcombobox.h" -#include "lltexturectrl.h" -#include "lltexteditor.h" -#include "llviewerparcelmgr.h" -#include "llfloaterworldmap.h" -#include "llviewergenericmessage.h"	// send_generic_message -#include "llviewerregion.h" -#include "llviewertexture.h" -#include "lltrans.h" -#include "llscrollcontainer.h" -#include "llstatusbar.h" -#include "llviewertexture.h" -#include "llcorehttputil.h" - -const S32 MINIMUM_PRICE_FOR_LISTING = 50;	// L$ - -//static -LLPanelClassifiedInfo::panel_list_t LLPanelClassifiedInfo::sAllPanels; - -// "classifiedclickthrough" -// strings[0] = classified_id -// strings[1] = teleport_clicks -// strings[2] = map_clicks -// strings[3] = profile_clicks -class LLDispatchClassifiedClickThrough : public LLDispatchHandler -{ -public: -	virtual bool operator()( -		const LLDispatcher* dispatcher, -		const std::string& key, -		const LLUUID& invoice, -		const sparam_t& strings) -	{ -		if (strings.size() != 4) return false; -		LLUUID classified_id(strings[0]); -		S32 teleport_clicks = atoi(strings[1].c_str()); -		S32 map_clicks = atoi(strings[2].c_str()); -		S32 profile_clicks = atoi(strings[3].c_str()); - -		LLPanelClassifiedInfo::setClickThrough( -			classified_id, teleport_clicks, map_clicks, profile_clicks, false); - -		return true; -	} -}; -static LLDispatchClassifiedClickThrough sClassifiedClickThrough; - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelClassifiedInfo::LLPanelClassifiedInfo() - : LLPanel() - , mInfoLoaded(false) - , mScrollingPanel(NULL) - , mScrollContainer(NULL) - , mScrollingPanelMinHeight(0) - , mScrollingPanelWidth(0) - , mSnapshotStreched(false) - , mTeleportClicksOld(0) - , mMapClicksOld(0) - , mProfileClicksOld(0) - , mTeleportClicksNew(0) - , mMapClicksNew(0) - , mProfileClicksNew(0) - , mSnapshotCtrl(NULL) -{ -	sAllPanels.push_back(this); -} - -LLPanelClassifiedInfo::~LLPanelClassifiedInfo() -{ -	sAllPanels.remove(this); -} - -// static -LLPanelClassifiedInfo* LLPanelClassifiedInfo::create() -{ -	LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo(); -	panel->buildFromFile("panel_classified_info.xml"); -	return panel; -} - -BOOL LLPanelClassifiedInfo::postBuild() -{ -	childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this)); -	childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this)); -	childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this)); - -	mScrollingPanel = getChild<LLPanel>("scroll_content_panel"); -	mScrollContainer = getChild<LLScrollContainer>("profile_scroll"); - -	mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight(); -	mScrollingPanelWidth = mScrollingPanel->getRect().getWidth(); - -	mSnapshotCtrl = getChild<LLTextureCtrl>("classified_snapshot"); -	mSnapshotRect = getDefaultSnapshotRect(); - -	return TRUE; -} - -void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("back_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedInfo::setEditClassifiedCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("edit_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedInfo::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) -{ -	LLPanel::reshape(width, height, called_from_parent); - -	if (!mScrollContainer || !mScrollingPanel) -		return; - -	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - -	S32 scroll_height = mScrollContainer->getRect().getHeight(); -	if (mScrollingPanelMinHeight >= scroll_height) -	{ -		mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight); -	} -	else -	{ -		mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height); -	} - -	mSnapshotRect = getDefaultSnapshotRect(); -	stretchSnapshot(); -} - -void LLPanelClassifiedInfo::onOpen(const LLSD& key) -{ -	LLUUID avatar_id = key["classified_creator_id"]; -	if(avatar_id.isNull()) -	{ -		return; -	} - -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -	} - -	setAvatarId(avatar_id); - -	resetData(); -	resetControls(); -	scrollToTop(); - -	setClassifiedId(key["classified_id"]); -	setClassifiedName(key["classified_name"]); -	setDescription(key["classified_desc"]); -	setSnapshotId(key["classified_snapshot_id"]); -	setFromSearch(key["from_search"]); - -	LL_INFOS() << "Opening classified [" << getClassifiedName() << "] (" << getClassifiedId() << ")" << LL_ENDL; - -	LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); -	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); -	gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); - -	if (gAgent.getRegion()) -	{ -		// While we're at it let's get the stats from the new table if that -		// capability exists. -		std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); -		if (!url.empty()) -		{ -			LL_INFOS() << "Classified stat request via capability" << LL_ENDL; -			LLSD body; -			LLUUID classifiedId = getClassifiedId(); -			body["classified_id"] = classifiedId; -			LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, -				boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1)); -		} -	} -	// Update classified click stats. -	// *TODO: Should we do this when opening not from search? -	sendClickMessage("profile"); - -	setInfoLoaded(false); -} - -/*static*/ -void LLPanelClassifiedInfo::handleSearchStatResponse(LLUUID classifiedId, LLSD result) -{ -    S32 teleport = result["teleport_clicks"].asInteger(); -    S32 map = result["map_clicks"].asInteger(); -    S32 profile = result["profile_clicks"].asInteger(); -    S32 search_teleport = result["search_teleport_clicks"].asInteger(); -    S32 search_map = result["search_map_clicks"].asInteger(); -    S32 search_profile = result["search_profile_clicks"].asInteger(); - -    LLPanelClassifiedInfo::setClickThrough(classifiedId, -        teleport + search_teleport, -        map + search_map, -        profile + search_profile, -        true); -} - -void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_CLASSIFIED_INFO == type) -	{ -		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -		if(c_info && getClassifiedId() == c_info->classified_id) -		{ -			setClassifiedName(c_info->name); -			setDescription(c_info->description); -			setSnapshotId(c_info->snapshot_id); -			setParcelId(c_info->parcel_id); -			setPosGlobal(c_info->pos_global); -			setSimName(c_info->sim_name); - -			setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); -			getChild<LLUICtrl>("category")->setValue(LLClassifiedInfo::sCategories[c_info->category]); - -			static std::string mature_str = getString("type_mature"); -			static std::string pg_str = getString("type_pg"); -			static LLUIString  price_str = getString("l$_price"); -			static std::string date_fmt = getString("date_fmt"); - -			bool mature = is_cf_mature(c_info->flags); -			getChild<LLUICtrl>("content_type")->setValue(mature ? mature_str : pg_str); -			getChild<LLIconCtrl>("content_type_moderate")->setVisible(mature); -			getChild<LLIconCtrl>("content_type_general")->setVisible(!mature); - -			std::string auto_renew_str = is_cf_auto_renew(c_info->flags) ?  -				getString("auto_renew_on") : getString("auto_renew_off"); -			getChild<LLUICtrl>("auto_renew")->setValue(auto_renew_str); - -			price_str.setArg("[PRICE]", llformat("%d", c_info->price_for_listing)); -			getChild<LLUICtrl>("price_for_listing")->setValue(LLSD(price_str)); - -			std::string date_str = date_fmt; -			LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date)); -			getChild<LLUICtrl>("creation_date")->setValue(date_str); - -			setInfoLoaded(true); -		} -	} -} - -void LLPanelClassifiedInfo::resetData() -{ -	setClassifiedName(LLStringUtil::null); -	setDescription(LLStringUtil::null); -	setClassifiedLocation(LLStringUtil::null); -	setClassifiedId(LLUUID::null); -	setSnapshotId(LLUUID::null); -	setPosGlobal(LLVector3d::zero); -	setParcelId(LLUUID::null); -	setSimName(LLStringUtil::null); -	setFromSearch(false); - -	// reset click stats -	mTeleportClicksOld	= 0; -	mMapClicksOld		= 0; -	mProfileClicksOld	= 0; -	mTeleportClicksNew	= 0; -	mMapClicksNew		= 0; -	mProfileClicksNew	= 0; - -	getChild<LLUICtrl>("category")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("content_type")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("price_for_listing")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("auto_renew")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("creation_date")->setValue(LLStringUtil::null); -	getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null); -	getChild<LLIconCtrl>("content_type_moderate")->setVisible(FALSE); -	getChild<LLIconCtrl>("content_type_general")->setVisible(FALSE); -} - -void LLPanelClassifiedInfo::resetControls() -{ -	bool is_self = getAvatarId() == gAgent.getID(); - -	getChildView("edit_btn")->setEnabled(is_self); -	getChildView("edit_btn")->setVisible( is_self); -	getChildView("price_layout_panel")->setVisible( is_self); -	getChildView("clickthrough_layout_panel")->setVisible( is_self); -} - -void LLPanelClassifiedInfo::setClassifiedName(const std::string& name) -{ -	getChild<LLUICtrl>("classified_name")->setValue(name); -} - -std::string LLPanelClassifiedInfo::getClassifiedName() -{ -	return getChild<LLUICtrl>("classified_name")->getValue().asString(); -} - -void LLPanelClassifiedInfo::setDescription(const std::string& desc) -{ -	getChild<LLUICtrl>("classified_desc")->setValue(desc); -} - -std::string LLPanelClassifiedInfo::getDescription() -{ -	return getChild<LLUICtrl>("classified_desc")->getValue().asString(); -} - -void LLPanelClassifiedInfo::setClassifiedLocation(const std::string& location) -{ -	getChild<LLUICtrl>("classified_location")->setValue(location); -} - -std::string LLPanelClassifiedInfo::getClassifiedLocation() -{ -	return getChild<LLUICtrl>("classified_location")->getValue().asString(); -} - -void LLPanelClassifiedInfo::setSnapshotId(const LLUUID& id) -{ -	mSnapshotCtrl->setValue(id); -	mSnapshotStreched = false; -} - -void LLPanelClassifiedInfo::draw() -{ -	LLPanel::draw(); - -	// Stretch in draw because it takes some time to load a texture, -	// going to try to stretch snapshot until texture is loaded -	if(!mSnapshotStreched) -	{ -		stretchSnapshot(); -	} -} - -LLUUID LLPanelClassifiedInfo::getSnapshotId() -{ -	return getChild<LLUICtrl>("classified_snapshot")->getValue().asUUID(); -} - -// static -void LLPanelClassifiedInfo::setClickThrough( -	const LLUUID& classified_id, -	S32 teleport, -	S32 map, -	S32 profile, -	bool from_new_table) -{ -	LL_INFOS() << "Click-through data for classified " << classified_id << " arrived: [" -			<< teleport << ", " << map << ", " << profile << "] (" -			<< (from_new_table ? "new" : "old") << ")" << LL_ENDL; - -	for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) -	{ -		LLPanelClassifiedInfo* self = *iter; -		if (self->getClassifiedId() != classified_id) -		{ -			continue; -		} - -		// *HACK: Skip LLPanelClassifiedEdit instances: they don't display clicks data. -		// Those instances should not be in the list at all. -		if (typeid(*self) != typeid(LLPanelClassifiedInfo)) -		{ -			continue; -		} - -		LL_INFOS() << "Updating classified info panel" << LL_ENDL; - -		// We need to check to see if the data came from the new stat_table  -		// or the old classified table. We also need to cache the data from  -		// the two separate sources so as to display the aggregate totals. - -		if (from_new_table) -		{ -			self->mTeleportClicksNew = teleport; -			self->mMapClicksNew = map; -			self->mProfileClicksNew = profile; -		} -		else -		{ -			self->mTeleportClicksOld = teleport; -			self->mMapClicksOld = map; -			self->mProfileClicksOld = profile; -		} - -		static LLUIString ct_str = self->getString("click_through_text_fmt"); - -		ct_str.setArg("[TELEPORT]",	llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld)); -		ct_str.setArg("[MAP]",		llformat("%d", self->mMapClicksNew + self->mMapClicksOld)); -		ct_str.setArg("[PROFILE]",	llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld)); - -		self->getChild<LLUICtrl>("click_through_text")->setValue(ct_str.getString()); -		// *HACK: remove this when there is enough room for click stats in the info panel -		self->getChildView("click_through_text")->setToolTip(ct_str.getString());   - -		LL_INFOS() << "teleport: " << llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld) -				<< ", map: "    << llformat("%d", self->mMapClicksNew + self->mMapClicksOld) -				<< ", profile: " << llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld) -				<< LL_ENDL; -	} -} - -// static -std::string LLPanelClassifiedInfo::createLocationText( -	const std::string& original_name,  -	const std::string& sim_name,  -	const LLVector3d& pos_global) -{ -	std::string location_text; -	 -	location_text.append(original_name); - -	if (!sim_name.empty()) -	{ -		if (!location_text.empty())  -			location_text.append(", "); -		location_text.append(sim_name); -	} - -	if (!location_text.empty())  -		location_text.append(" "); - -	if (!pos_global.isNull()) -	{ -		S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; -		S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; -		S32 region_z = ll_round((F32)pos_global.mdV[VZ]); -		location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); -	} - -	return location_text; -} - -void LLPanelClassifiedInfo::stretchSnapshot() -{ -	// *NOTE dzaporozhan -	// Could be moved to LLTextureCtrl - -	LLViewerFetchedTexture* texture = mSnapshotCtrl->getTexture(); - -	if(!texture) -	{ -		return; -	} - -	if(0 == texture->getOriginalWidth() || 0 == texture->getOriginalHeight()) -	{ -		// looks like texture is not loaded yet -		return; -	} - -	LLRect rc = mSnapshotRect; -	// *HACK dzaporozhan -	// LLTextureCtrl uses BTN_HEIGHT_SMALL as bottom for texture which causes -	// drawn texture to be smaller than expected. (see LLTextureCtrl::draw()) -	// Lets increase texture height to force texture look as expected. -	rc.mBottom -= BTN_HEIGHT_SMALL; - -	F32 t_width = texture->getFullWidth(); -	F32 t_height = texture->getFullHeight(); - -	F32 ratio = llmin<F32>( (rc.getWidth() / t_width), (rc.getHeight() / t_height) ); - -	t_width *= ratio; -	t_height *= ratio; - -	rc.setCenterAndSize(rc.getCenterX(), rc.getCenterY(), llfloor(t_width), llfloor(t_height)); -	mSnapshotCtrl->setShape(rc); - -	mSnapshotStreched = true; -} - -LLRect LLPanelClassifiedInfo::getDefaultSnapshotRect() -{ -	// Using scroll container makes getting default rect a hard task -	// because rect in postBuild() and in first reshape() is not the same. -	// Using snapshot_panel makes it easier to reshape snapshot. -	return getChild<LLUICtrl>("snapshot_panel")->getLocalRect(); -} - -void LLPanelClassifiedInfo::scrollToTop() -{ -	LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll"); -	if (scrollContainer) -		scrollContainer->goToTop(); -} - -// static -// *TODO: move out of the panel -void LLPanelClassifiedInfo::sendClickMessage( -		const std::string& type, -		bool from_search, -		const LLUUID& classified_id, -		const LLUUID& parcel_id, -		const LLVector3d& global_pos, -		const std::string& sim_name) -{ -	if (gAgent.getRegion()) -	{ -		// You're allowed to click on your own ads to reassure yourself -		// that the system is working. -		LLSD body; -		body["type"]			= type; -		body["from_search"]		= from_search; -		body["classified_id"]	= classified_id; -		body["parcel_id"]		= parcel_id; -		body["dest_pos_global"]	= global_pos.getValue(); -		body["region_name"]		= sim_name; - -		std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); -		LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; -		LL_INFOS() << "body: [" << body << "]" << LL_ENDL; -        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, -            "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); -	} -} - -void LLPanelClassifiedInfo::sendClickMessage(const std::string& type) -{ -	sendClickMessage( -		type, -		fromSearch(), -		getClassifiedId(), -		getParcelId(), -		getPosGlobal(), -		getSimName()); -} - -void LLPanelClassifiedInfo::onMapClick() -{ -	sendClickMessage("map"); -	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); -	LLFloaterReg::showInstance("world_map", "center"); -} - -void LLPanelClassifiedInfo::onTeleportClick() -{ -	if (!getPosGlobal().isExactlyZero()) -	{ -		sendClickMessage("teleport"); -		gAgent.teleportViaLocation(getPosGlobal()); -		LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); -	} -} - -void LLPanelClassifiedInfo::onExit() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -	gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -static const S32 CB_ITEM_MATURE = 0; -static const S32 CB_ITEM_PG	   = 1; - -LLPanelClassifiedEdit::LLPanelClassifiedEdit() - : LLPanelClassifiedInfo() - , mIsNew(false) - , mIsNewWithErrors(false) - , mCanClose(false) - , mPublishFloater(NULL) -{ -} - -LLPanelClassifiedEdit::~LLPanelClassifiedEdit() -{ -} - -//static -LLPanelClassifiedEdit* LLPanelClassifiedEdit::create() -{ -	LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit(); -	panel->buildFromFile("panel_edit_classified.xml"); -	return panel; -} - -BOOL LLPanelClassifiedEdit::postBuild() -{ -	LLPanelClassifiedInfo::postBuild(); - -	LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("classified_snapshot"); -	snapshot->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - -	LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon"); -	snapshot->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon)); -	snapshot->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon)); -	edit_icon->setVisible(false); - -	LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name"); -	line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - -	LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc"); -	text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - -	LLComboBox* combobox = getChild<LLComboBox>( "category"); -	LLClassifiedInfo::cat_map::iterator iter; -	for (iter = LLClassifiedInfo::sCategories.begin(); -		iter != LLClassifiedInfo::sCategories.end(); -		iter++) -	{ -		combobox->add(LLTrans::getString(iter->second)); -	} - -	combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - -	childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); -	childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); -	childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - -	childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this)); -	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this)); - -	mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onTextureSelected, this)); - -	return TRUE; -} - -void LLPanelClassifiedEdit::fillIn(const LLSD& key) -{ -	setAvatarId(gAgent.getID()); - -	if(key.isUndefined()) -	{ -		setPosGlobal(gAgent.getPositionGlobal()); - -		LLUUID snapshot_id = LLUUID::null; -		std::string desc; -		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - -		if(parcel) -		{ -			desc = parcel->getDesc(); -			snapshot_id = parcel->getSnapshotID(); -		} - -		std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); -		LLViewerRegion* region = gAgent.getRegion(); -		if (region) -		{ -			region_name = region->getName(); -		} - -		getChild<LLUICtrl>("classified_name")->setValue(makeClassifiedName()); -		getChild<LLUICtrl>("classified_desc")->setValue(desc); -		setSnapshotId(snapshot_id); -		setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); -		// server will set valid parcel id -		setParcelId(LLUUID::null); -	} -	else -	{ -		setClassifiedId(key["classified_id"]); -		setClassifiedName(key["name"]); -		setDescription(key["desc"]); -		setSnapshotId(key["snapshot_id"]); -		setCategory((U32)key["category"].asInteger()); -		setContentType((U32)key["content_type"].asInteger()); -		setClassifiedLocation(key["location_text"]); -		getChild<LLUICtrl>("auto_renew")->setValue(key["auto_renew"]); -		getChild<LLUICtrl>("price_for_listing")->setValue(key["price_for_listing"].asInteger()); -	} -} - -void LLPanelClassifiedEdit::onOpen(const LLSD& key) -{ -	mIsNew = key.isUndefined(); -	 -	scrollToTop(); - -	// classified is not created yet -	bool is_new = isNew() || isNewWithErrors(); - -	if(is_new) -	{ -		resetData(); -		resetControls(); - -		fillIn(key); - -		if(isNew()) -		{ -			LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); -		} -	} -	else -	{ -		LLPanelClassifiedInfo::onOpen(key); -	} - -	std::string save_btn_label = is_new ? getString("publish_label") : getString("save_label"); -	getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", save_btn_label); - -	enableVerbs(is_new); -	enableEditing(is_new); -	showEditing(!is_new); -	resetDirty(); -	setInfoLoaded(false); -} - -void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_CLASSIFIED_INFO == type) -	{ -		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -		if(c_info && getClassifiedId() == c_info->classified_id) -		{ -			// see LLPanelClassifiedEdit::sendUpdate() for notes -			mIsNewWithErrors = false; -			// for just created classified - panel will probably be closed when we get here. -			if(!getVisible()) -			{ -				return; -			} - -			enableEditing(true); - -			setClassifiedName(c_info->name); -			setDescription(c_info->description); -			setSnapshotId(c_info->snapshot_id); -			setPosGlobal(c_info->pos_global); - -			setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); -			// *HACK see LLPanelClassifiedEdit::sendUpdate() -			setCategory(c_info->category - 1); - -			bool mature = is_cf_mature(c_info->flags); -			bool auto_renew = is_cf_auto_renew(c_info->flags); - -			setContentType(mature ? CB_ITEM_MATURE : CB_ITEM_PG); -			getChild<LLUICtrl>("auto_renew")->setValue(auto_renew); -			getChild<LLUICtrl>("price_for_listing")->setValue(c_info->price_for_listing); -			getChildView("price_for_listing")->setEnabled(isNew()); - -			resetDirty(); -			setInfoLoaded(true); -			enableVerbs(false); - -			// for just created classified - in case user opened edit panel before processProperties() callback  -			getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", getString("save_label")); -		} -	} -} - -BOOL LLPanelClassifiedEdit::isDirty() const -{ -	if(mIsNew)  -	{ -		return TRUE; -	} - -	BOOL dirty = false; - -	dirty |= LLPanelClassifiedInfo::isDirty(); -	dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty(); -	dirty |= getChild<LLUICtrl>("classified_name")->isDirty(); -	dirty |= getChild<LLUICtrl>("classified_desc")->isDirty(); -	dirty |= getChild<LLUICtrl>("category")->isDirty(); -	dirty |= getChild<LLUICtrl>("content_type")->isDirty(); -	dirty |= getChild<LLUICtrl>("auto_renew")->isDirty(); -	dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty(); - -	return dirty; -} - -void LLPanelClassifiedEdit::resetDirty() -{ -	LLPanelClassifiedInfo::resetDirty(); -	getChild<LLUICtrl>("classified_snapshot")->resetDirty(); -	getChild<LLUICtrl>("classified_name")->resetDirty(); - -	LLTextEditor* desc = getChild<LLTextEditor>("classified_desc"); -	// call blockUndo() to really reset dirty(and make isDirty work as intended) -	desc->blockUndo(); -	desc->resetDirty(); - -	getChild<LLUICtrl>("category")->resetDirty(); -	getChild<LLUICtrl>("content_type")->resetDirty(); -	getChild<LLUICtrl>("auto_renew")->resetDirty(); -	getChild<LLUICtrl>("price_for_listing")->resetDirty(); -} - -void LLPanelClassifiedEdit::setSaveCallback(const commit_signal_t::slot_type& cb) -{ -	mSaveButtonClickedSignal.connect(cb); -} - -void LLPanelClassifiedEdit::setCancelCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedEdit::resetControls() -{ -	LLPanelClassifiedInfo::resetControls(); - -	getChild<LLComboBox>("category")->setCurrentByIndex(0); -	getChild<LLComboBox>("content_type")->setCurrentByIndex(0); -	getChild<LLUICtrl>("auto_renew")->setValue(false); -	getChild<LLUICtrl>("price_for_listing")->setValue(MINIMUM_PRICE_FOR_LISTING); -	getChildView("price_for_listing")->setEnabled(TRUE); -} - -bool LLPanelClassifiedEdit::canClose() -{ -	return mCanClose; -} - -void LLPanelClassifiedEdit::draw() -{ -	LLPanel::draw(); - -	// Need to re-stretch on every draw because LLTextureCtrl::onSelectCallback -	// does not trigger callbacks when user navigates through images. -	stretchSnapshot(); -} - -void LLPanelClassifiedEdit::stretchSnapshot() -{ -	LLPanelClassifiedInfo::stretchSnapshot(); - -	getChild<LLUICtrl>("edit_icon")->setShape(mSnapshotCtrl->getRect()); -} - -U32 LLPanelClassifiedEdit::getContentType() -{ -	LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); -	return ct_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setContentType(U32 content_type) -{ -	LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); -	ct_cb->setCurrentByIndex(content_type); -	ct_cb->resetDirty(); -} - -bool LLPanelClassifiedEdit::getAutoRenew() -{ -	return getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); -} - -void LLPanelClassifiedEdit::sendUpdate() -{ -	LLAvatarClassifiedInfo c_data; - -	if(getClassifiedId().isNull()) -	{ -		setClassifiedId(LLUUID::generateNewID()); -	} - -	c_data.agent_id = gAgent.getID(); -	c_data.classified_id = getClassifiedId(); -	// *HACK  -	// Categories on server start with 1 while combo-box index starts with 0 -	c_data.category = getCategory() + 1; -	c_data.name = getClassifiedName(); -	c_data.description = getDescription(); -	c_data.parcel_id = getParcelId(); -	c_data.snapshot_id = getSnapshotId(); -	c_data.pos_global = getPosGlobal(); -	c_data.flags = getFlags(); -	c_data.price_for_listing = getPriceForListing(); - -	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); -	 -	if(isNew()) -	{ -		// Lets assume there will be some error. -		// Successful sendClassifiedInfoUpdate will trigger processProperties and -		// let us know there was no error. -		mIsNewWithErrors = true; -	} -} - -U32 LLPanelClassifiedEdit::getCategory() -{ -	LLComboBox* cat_cb = getChild<LLComboBox>("category"); -	return cat_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setCategory(U32 category) -{ -	LLComboBox* cat_cb = getChild<LLComboBox>("category"); -	cat_cb->setCurrentByIndex(category); -	cat_cb->resetDirty(); -} - -U8 LLPanelClassifiedEdit::getFlags() -{ -	bool auto_renew = getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); - -	LLComboBox* content_cb = getChild<LLComboBox>("content_type"); -	bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE; -	 -	return pack_classified_flags_request(auto_renew, false, mature, false); -} - -void LLPanelClassifiedEdit::enableVerbs(bool enable) -{ -	getChildView("save_changes_btn")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::enableEditing(bool enable) -{ -	getChildView("classified_snapshot")->setEnabled(enable); -	getChildView("classified_name")->setEnabled(enable); -	getChildView("classified_desc")->setEnabled(enable); -	getChildView("set_to_curr_location_btn")->setEnabled(enable); -	getChildView("category")->setEnabled(enable); -	getChildView("content_type")->setEnabled(enable); -	getChildView("price_for_listing")->setEnabled(enable); -	getChildView("auto_renew")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::showEditing(bool show) -{ -	getChildView("price_for_listing_label")->setVisible( show); -	getChildView("price_for_listing")->setVisible( show); -} - -std::string LLPanelClassifiedEdit::makeClassifiedName() -{ -	std::string name; - -	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); -	if(parcel) -	{ -		name = parcel->getName(); -	} - -	if(!name.empty()) -	{ -		return name; -	} - -	LLViewerRegion* region = gAgent.getRegion(); -	if(region) -	{ -		name = region->getName(); -	} - -	return name; -} - -S32 LLPanelClassifiedEdit::getPriceForListing() -{ -	return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPanelClassifiedEdit::setPriceForListing(S32 price) -{ -	getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -void LLPanelClassifiedEdit::onSetLocationClick() -{ -	setPosGlobal(gAgent.getPositionGlobal()); -	setParcelId(LLUUID::null); - -	std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); -	LLViewerRegion* region = gAgent.getRegion(); -	if (region) -	{ -		region_name = region->getName(); -	} - -	setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); - -	// mark classified as dirty -	setValue(LLSD()); - -	onChange(); -} - -void LLPanelClassifiedEdit::onChange() -{ -	enableVerbs(isDirty()); -} - -void LLPanelClassifiedEdit::onSaveClick() -{ -	mCanClose = false; - -	if(!isValidName()) -	{ -		notifyInvalidName(); -		return; -	} -	if(isNew() || isNewWithErrors()) -	{ -		if(gStatusBar->getBalance() < getPriceForListing()) -		{ -			LLNotificationsUtil::add("ClassifiedInsufficientFunds"); -			return; -		} - -		mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( -			"publish_classified", LLSD()); - -		if(!mPublishFloater) -		{ -			mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( -				"publish_classified", LLSD()); - -			mPublishFloater->setPublishClickedCallback(boost::bind -				(&LLPanelClassifiedEdit::onPublishFloaterPublishClicked, this)); -		} - -		// set spinner value before it has focus or value wont be set -		mPublishFloater->setPrice(getPriceForListing()); -		mPublishFloater->openFloater(mPublishFloater->getKey()); -		mPublishFloater->center(); -	} -	else -	{ -		doSave(); -	} -} - -void LLPanelClassifiedEdit::doSave() -{ -	mCanClose = true; -	sendUpdate(); -	resetDirty(); - -	mSaveButtonClickedSignal(this, LLSD()); -} - -void LLPanelClassifiedEdit::onPublishFloaterPublishClicked() -{ -	setPriceForListing(mPublishFloater->getPrice()); - -	doSave(); -} - -std::string LLPanelClassifiedEdit::getLocationNotice() -{ -	static std::string location_notice = getString("location_notice"); -	return location_notice; -} - -bool LLPanelClassifiedEdit::isValidName() -{ -	std::string name = getClassifiedName(); -	if (name.empty()) -	{ -		return false; -	} -	if (!isalnum(name[0])) -	{ -		return false; -	} - -	return true; -} - -void LLPanelClassifiedEdit::notifyInvalidName() -{ -	std::string name = getClassifiedName(); -	if (name.empty()) -	{ -		LLNotificationsUtil::add("BlankClassifiedName"); -	} -	else if (!isalnum(name[0])) -	{ -		LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); -	} -} - -void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) -{ -	ctrl->setVisible(TRUE); -} - -void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) -{ -	ctrl->setVisible(FALSE); -} - -void LLPanelClassifiedEdit::onTextureSelected() -{ -	setSnapshotId(mSnapshotCtrl->getValue().asUUID()); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) - : LLFloater(key) -{ -} - -LLPublishClassifiedFloater::~LLPublishClassifiedFloater() -{ -} - -BOOL LLPublishClassifiedFloater::postBuild() -{ -	LLFloater::postBuild(); - -	childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); -	childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); - -	return TRUE; -} - -void LLPublishClassifiedFloater::setPrice(S32 price) -{ -	getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -S32 LLPublishClassifiedFloater::getPrice() -{ -	return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("publish_btn")->setClickedCallback(cb); -} - -void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -//EOF diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h deleted file mode 100644 index b292782615..0000000000 --- a/indra/newview/llpanelclassified.h +++ /dev/null @@ -1,301 +0,0 @@ -/**  - * @file llpanelclassified.h - * @brief LLPanelClassified class definition - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -// Display of a classified used both for the global view in the -// Find directory, and also for each individual user's classified in their -// profile. -#ifndef LL_LLPANELCLASSIFIED_H -#define LL_LLPANELCLASSIFIED_H - -#include "llavatarpropertiesprocessor.h" -#include "llclassifiedinfo.h" -#include "llfloater.h" -#include "llpanel.h" -#include "llrect.h" -#include "lluuid.h" -#include "v3dmath.h" -#include "llcoros.h" -#include "lleventcoro.h" - -class LLScrollContainer; -class LLTextureCtrl; -class LLUICtrl; - -class LLPublishClassifiedFloater : public LLFloater -{ -public: -	LLPublishClassifiedFloater(const LLSD& key); -	virtual ~LLPublishClassifiedFloater(); - -	/*virtual*/ BOOL postBuild(); - -	void setPrice(S32 price); -	S32 getPrice(); - -	void setPublishClickedCallback(const commit_signal_t::slot_type& cb); -	void setCancelClickedCallback(const commit_signal_t::slot_type& cb); - -private: -}; - -class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver -{ -	LOG_CLASS(LLPanelClassifiedInfo); -public: - -	static LLPanelClassifiedInfo* create(); - -	virtual ~LLPanelClassifiedInfo(); - -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ BOOL postBuild(); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } - -	LLUUID& getAvatarId() { return mAvatarId; } - -	void setSnapshotId(const LLUUID& id); - -	LLUUID getSnapshotId(); - -	void setClassifiedId(const LLUUID& id) { mClassifiedId = id; } - -	LLUUID& getClassifiedId() { return mClassifiedId; } - -	void setClassifiedName(const std::string& name); - -	std::string getClassifiedName(); - -	void setDescription(const std::string& desc); - -	std::string getDescription(); - -	void setClassifiedLocation(const std::string& location); - -	std::string getClassifiedLocation(); - -	void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } - -	LLVector3d& getPosGlobal() { return mPosGlobal; } - -	void setParcelId(const LLUUID& id) { mParcelId = id; } - -	LLUUID getParcelId() { return mParcelId; } - -	void setSimName(const std::string& sim_name) { mSimName = sim_name; } - -	std::string getSimName() { return mSimName; } - -	void setFromSearch(bool val) { mFromSearch = val; } - -	bool fromSearch() { return mFromSearch; } - -	bool getInfoLoaded() { return mInfoLoaded; } - -	void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } - -	static void setClickThrough( -		const LLUUID& classified_id, -		S32 teleport, -		S32 map, -		S32 profile, -		bool from_new_table); - -	static void sendClickMessage( -			const std::string& type, -			bool from_search, -			const LLUUID& classified_id, -			const LLUUID& parcel_id, -			const LLVector3d& global_pos, -			const std::string& sim_name); - -	void setExitCallback(const commit_callback_t& cb); - -	void setEditClassifiedCallback(const commit_callback_t& cb); - -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - -	/*virtual*/ void draw(); - -protected: - -	LLPanelClassifiedInfo(); - -	virtual void resetData(); - -	virtual void resetControls(); - -	static std::string createLocationText( -		const std::string& original_name, -		const std::string& sim_name,  -		const LLVector3d& pos_global); - -	void stretchSnapshot(); -	void sendClickMessage(const std::string& type); - -	LLRect getDefaultSnapshotRect(); - -	void scrollToTop(); - -	void onMapClick(); -	void onTeleportClick(); -	void onExit(); - -	bool mSnapshotStreched; -	LLRect mSnapshotRect; -	LLTextureCtrl* mSnapshotCtrl; - -private: - -	LLUUID mAvatarId; -	LLUUID mClassifiedId; -	LLVector3d mPosGlobal; -	LLUUID mParcelId; -	std::string mSimName; -	bool mFromSearch; -	bool mInfoLoaded; - -	LLScrollContainer*		mScrollContainer; -	LLPanel*				mScrollingPanel; - -	S32 mScrollingPanelMinHeight; -	S32 mScrollingPanelWidth; - -	// Needed for stat tracking -	S32 mTeleportClicksOld; -	S32 mMapClicksOld; -	S32 mProfileClicksOld; -	S32 mTeleportClicksNew; -	S32 mMapClicksNew; -	S32 mProfileClicksNew; - -    static void handleSearchStatResponse(LLUUID classifiedId, LLSD result); - - -	typedef std::list<LLPanelClassifiedInfo*> panel_list_t; -	static panel_list_t sAllPanels; -}; - -class LLPanelClassifiedEdit : public LLPanelClassifiedInfo -{ -	LOG_CLASS(LLPanelClassifiedEdit); -public: - -	static LLPanelClassifiedEdit* create(); - -	virtual ~LLPanelClassifiedEdit(); - -	/*virtual*/ BOOL postBuild(); - -	void fillIn(const LLSD& key); - -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	/*virtual*/ BOOL isDirty() const; - -	/*virtual*/ void resetDirty(); - -	void setSaveCallback(const commit_signal_t::slot_type& cb); - -	void setCancelCallback(const commit_signal_t::slot_type& cb); - -	/*virtual*/ void resetControls(); - -	bool isNew() { return mIsNew; } - -	bool isNewWithErrors() { return mIsNewWithErrors; } - -	bool canClose(); - -	void draw(); - -	void stretchSnapshot(); - -	U32 getCategory(); - -	void setCategory(U32 category); - -	U32 getContentType(); - -	void setContentType(U32 content_type); - -	bool getAutoRenew(); - -	S32 getPriceForListing(); - -protected: - -	LLPanelClassifiedEdit(); - -	void sendUpdate(); - -	void enableVerbs(bool enable); - -	void enableEditing(bool enable); - -	void showEditing(bool show); - -	std::string makeClassifiedName(); - -	void setPriceForListing(S32 price); - -	U8 getFlags(); - -	std::string getLocationNotice(); - -	bool isValidName(); - -	void notifyInvalidName(); - -	void onSetLocationClick(); -	void onChange(); -	void onSaveClick(); - -	void doSave(); - -	void onPublishFloaterPublishClicked(); - -	void onTexturePickerMouseEnter(LLUICtrl* ctrl); -	void onTexturePickerMouseLeave(LLUICtrl* ctrl); - -	void onTextureSelected(); - -private: -	bool mIsNew; -	bool mIsNewWithErrors; -	bool mCanClose; - -	LLPublishClassifiedFloater* mPublishFloater; - -	commit_signal_t mSaveButtonClickedSignal; -}; - -#endif // LL_LLPANELCLASSIFIED_H diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h index f29fdfdecb..0ce48ca118 100644 --- a/indra/newview/llpanelexperiences.h +++ b/indra/newview/llpanelexperiences.h @@ -29,7 +29,6 @@  #include "llaccordionctrltab.h"  #include "llflatlistview.h" -#include "llpanelavatar.h"  class LLExperienceItem;  class LLPanelProfile;  diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 389baa86cd..07a8641a92 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,6 +1,6 @@  /** - * @file llpanelavatar.cpp - * @brief LLPanelAvatar and related class implementations + * @file llpanelimcontrolpanel.cpp + * @brief LLPanelIMControlPanel and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp deleted file mode 100644 index 77bc99da83..0000000000 --- a/indra/newview/llpanelpicks.cpp +++ /dev/null @@ -1,1454 +0,0 @@ -/**  - * @file llpanelpicks.cpp - * @brief LLPanelPicks and related class implementations - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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 "llpanelpicks.h" - -#include "llagent.h" -#include "llagentpicksinfo.h" -#include "llcommandhandler.h" -#include "lldispatcher.h" -#include "llflatlistview.h" -#include "llfloaterreg.h" -#include "llfloatersidepanelcontainer.h" -#include "llfloaterworldmap.h" -#include "llnotificationsutil.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" -#include "lltrans.h" -#include "llviewergenericmessage.h"	// send_generic_message -#include "llmenugl.h" -#include "llviewermenu.h" -#include "llregistry.h" - -#include "llaccordionctrl.h" -#include "llaccordionctrltab.h" -#include "llavatarpropertiesprocessor.h" -#include "llfloatersidepanelcontainer.h" -#include "llpanelavatar.h" -#include "llpanelprofile.h" -#include "llpanelpick.h" -#include "llpanelclassified.h" - -static const std::string XML_BTN_NEW = "new_btn"; -static const std::string XML_BTN_DELETE = "trash_btn"; -static const std::string XML_BTN_INFO = "info_btn"; -static const std::string XML_BTN_TELEPORT = "teleport_btn"; -static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn"; - -static const std::string PICK_ID("pick_id"); -static const std::string PICK_CREATOR_ID("pick_creator_id"); -static const std::string PICK_NAME("pick_name"); - -static const std::string CLASSIFIED_ID("classified_id"); -static const std::string CLASSIFIED_NAME("classified_name"); - - -static LLPanelInjector<LLPanelPicks> t_panel_picks("panel_picks"); - - -class LLPickHandler : public LLCommandHandler, -					  public LLAvatarPropertiesObserver -{ -public: - -	std::set<LLUUID> mPickIds; -	 -	// requires trusted browser to trigger -	LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } - -	bool handle(const LLSD& params, const LLSD& query_map, -		LLMediaCtrl* web) -	{ -		if (!LLUI::sSettingGroups["config"]->getBOOL("EnablePicks")) -		{ -			LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); -			return true; -		} - -		// handle app/classified/create urls first -		if (params.size() == 1 && params[0].asString() == "create") -		{ -			createPick(); -			return true; -		} - -		// then handle the general app/pick/{UUID}/{CMD} urls -		if (params.size() < 2) -		{ -			return false; -		} - -		// get the ID for the pick_id -		LLUUID pick_id; -		if (!pick_id.set(params[0], FALSE)) -		{ -			return false; -		} - -		// edit the pick in the side tray. -		// need to ask the server for more info first though... -		const std::string verb = params[1].asString(); -		if (verb == "edit") -		{		 -			mPickIds.insert(pick_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(gAgent.getID(),pick_id); -			return true; -		} -		else -		{ -			LL_WARNS() << "unknown verb " << verb << LL_ENDL; -			return false; -		} -	} - -	void createPick() -	{ -		// open the new pick panel on the Picks floater -		LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - -		LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); -		if (picks) -		{ -			picks->createNewPick(); -		} -	} - -	void editPick(LLPickData* pick_info) -	{ -		LLSD params; -		params["open_tab_name"] = "panel_picks"; -		params["show_tab_panel"] = "edit_pick"; -		params["pick_id"] = pick_info->pick_id; -		params["avatar_id"] = pick_info->creator_id; -		params["snapshot_id"] = pick_info->snapshot_id; -		params["pick_name"] = pick_info->name; -		params["pick_desc"] = pick_info->desc; -		LLFloaterSidePanelContainer::showPanel("picks", params); -	} -	 -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) -	{ -		if (APT_PICK_INFO != type) -		{ -			return; -		} - -		// is this the pick that we asked for? -		LLPickData* pick_info = static_cast<LLPickData*>(data); -		if (!pick_info || mPickIds.find(pick_info->pick_id) == mPickIds.end()) -		{ -			return; -		} - -		// open the edit side tray for this pick -		if (pick_info->creator_id == gAgent.getID()) -		{ -			editPick(pick_info); -		} -		else -		{ -			LL_WARNS() << "Can't edit a pick you did not create" << LL_ENDL; -		} - -		// remove our observer now that we're done -		mPickIds.erase(pick_info->pick_id); -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); -	} -}; - -LLPickHandler gPickHandler; - -class LLClassifiedHandler : -	public LLCommandHandler, -	public LLAvatarPropertiesObserver -{ -public: -	// throttle calls from untrusted browsers -	LLClassifiedHandler() :	LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} - -	std::set<LLUUID> mClassifiedIds; - -	std::string mRequestVerb; -	 -	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) -	{ -		if (!LLUI::sSettingGroups["config"]->getBOOL("EnableClassifieds")) -		{ -			LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); -			return true; -		} - -		// handle app/classified/create urls first -		if (params.size() == 1 && params[0].asString() == "create") -		{ -			createClassified(); -			return true; -		} - -		// then handle the general app/classified/{UUID}/{CMD} urls -		if (params.size() < 2) -		{ -			return false; -		} - -		// get the ID for the classified -		LLUUID classified_id; -		if (!classified_id.set(params[0], FALSE)) -		{ -			return false; -		} - -		// show the classified in the side tray. -		// need to ask the server for more info first though... -		const std::string verb = params[1].asString(); -		if (verb == "about") -		{ -			mRequestVerb = verb; -			mClassifiedIds.insert(classified_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); -			return true; -		} -		else if (verb == "edit") -		{ -			mRequestVerb = verb; -			mClassifiedIds.insert(classified_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); -			return true; -		} - -		return false; -	} - -	void createClassified() -	{ -		// open the new classified panel on the Picks floater -		LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - -		LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); -		if (picks) -		{ -			picks->createNewClassified(); -		} -	} - -	void openClassified(LLAvatarClassifiedInfo* c_info) -	{ -		if (mRequestVerb == "about") -		{ -			// open the classified info panel on the Me > Picks sidetray -			LLSD params; -			params["id"] = c_info->creator_id; -			params["open_tab_name"] = "panel_picks"; -			params["show_tab_panel"] = "classified_details"; -			params["classified_id"] = c_info->classified_id; -			params["classified_creator_id"] = c_info->creator_id; -			params["classified_snapshot_id"] = c_info->snapshot_id; -			params["classified_name"] = c_info->name; -			params["classified_desc"] = c_info->description; -			params["from_search"] = true; -			LLFloaterSidePanelContainer::showPanel("picks", params); -		} -		else if (mRequestVerb == "edit") -		{ -			if (c_info->creator_id == gAgent.getID()) -			{ -				LL_WARNS() << "edit in progress" << LL_ENDL; -				// open the new classified panel on the Me > Picks sidetray -				LLSD params; -				params["id"] = gAgent.getID(); -				params["open_tab_name"] = "panel_picks"; -				params["show_tab_panel"] = "edit_classified"; -				params["classified_id"] = c_info->classified_id; -				LLFloaterSidePanelContainer::showPanel("my_profile", params); -			} -			else -			{ -				LL_WARNS() << "Can't edit a classified you did not create" << LL_ENDL; -			} -		} -	} - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) -	{ -		if (APT_CLASSIFIED_INFO != type) -		{ -			return; -		} - -		// is this the classified that we asked for? -		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -		if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) -		{ -			return; -		} - -		// open the detail side tray for this classified -		openClassified(c_info); - -		// remove our observer now that we're done -		mClassifiedIds.erase(c_info->classified_id); -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); -	} - -}; -LLClassifiedHandler gClassifiedHandler; - -////////////////////////////////////////////////////////////////////////// - - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPanelPicks::LLPanelPicks() -:	LLPanelProfileTab(), -	mPopupMenu(NULL), -	mProfilePanel(NULL), -	mPickPanel(NULL), -	mPicksList(NULL), -	mClassifiedsList(NULL), -	mPanelPickInfo(NULL), -	mPanelPickEdit(NULL), -	mPlusMenu(NULL), -	mPicksAccTab(NULL), -	mClassifiedsAccTab(NULL), -	mPanelClassifiedInfo(NULL), -	mNoClassifieds(false), -	mNoPicks(false) -{ -} - -LLPanelPicks::~LLPanelPicks() -{ -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); -	} -} - -void* LLPanelPicks::create(void* data /* = NULL */) -{ -	return new LLPanelPicks(); -} - -void LLPanelPicks::updateData() -{ -	// Send Picks request only when we need to, not on every onOpen(during tab switch). -	if(isDirty()) -	{ -		mNoPicks = false; -		mNoClassifieds = false; - -		mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); -		mNoItemsLabel->setVisible(TRUE); - -		mPicksList->clear(); -		LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); - -		mClassifiedsList->clear(); -		LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); -	} -} - -void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_PICKS == type) -	{ -		LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); -		if(avatar_picks && getAvatarId() == avatar_picks->target_id) -		{ -			LLAvatarName av_name; -			LLAvatarNameCache::get(getAvatarId(), &av_name); -			getChild<LLUICtrl>("pick_title")->setTextArg("[NAME]", av_name.getUserName()); -			 -			// Save selection, to be able to edit same item after saving changes. See EXT-3023. -			LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID]; - -			mPicksList->clear(); - -			LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); -			for(; avatar_picks->picks_list.end() != it; ++it) -			{ -				LLUUID pick_id = it->first; -				std::string pick_name = it->second; - -				LLPickItem* picture = LLPickItem::create(); -				picture->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); -				picture->setPickName(pick_name); -				picture->setPickId(pick_id); -				picture->setCreatorId(getAvatarId()); - -				LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture); -				picture->update(); - -				LLSD pick_value = LLSD(); -				pick_value.insert(PICK_ID, pick_id); -				pick_value.insert(PICK_NAME, pick_name); -				pick_value.insert(PICK_CREATOR_ID, getAvatarId()); - -				mPicksList->addItem(picture, pick_value); - -				// Restore selection by item id.  -				if ( pick_id == selected_id ) -					mPicksList->selectItemByValue(pick_value); - -				picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1)); -				picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -				picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -			} - -			showAccordion("tab_picks", mPicksList->size()); - -			resetDirty(); -			updateButtons(); -		} -		 -		mNoPicks = !mPicksList->size(); -	} -	else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) -	{ -		LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); -		if(c_info && getAvatarId() == c_info->target_id) -		{ -			// do not clear classified list in case we will receive two or more data packets. -			// list has been cleared in updateData(). (fix for EXT-6436) - -			LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); -			for(; c_info->classifieds_list.end() != it; ++it) -			{ -				LLAvatarClassifieds::classified_data c_data = *it; - -				LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), c_data.classified_id); -				c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); -				c_item->setClassifiedName(c_data.name); - -				LLSD pick_value = LLSD(); -				pick_value.insert(CLASSIFIED_ID, c_data.classified_id); -				pick_value.insert(CLASSIFIED_NAME, c_data.name); - -				if (!findClassifiedById(c_data.classified_id)) -				{ -					mClassifiedsList->addItem(c_item, pick_value); -				} - -				c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); -				c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -				c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -			} - -			showAccordion("tab_classifieds", mClassifiedsList->size()); - -			resetDirty(); -			updateButtons(); -		} -		 -		mNoClassifieds = !mClassifiedsList->size(); -	} - -	bool no_data = mNoPicks && mNoClassifieds; -	mNoItemsLabel->setVisible(no_data); -	if (no_data) -	{ -		if(getAvatarId() == gAgentID) -		{ -			mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText")); -		} -		else -		{ -			mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText")); -		} -	} -} - -LLPickItem* LLPanelPicks::getSelectedPickItem() -{ -	LLPanel* selected_item = mPicksList->getSelectedItem(); -	if (!selected_item) return NULL; - -	return dynamic_cast<LLPickItem*>(selected_item); -} - -LLClassifiedItem* LLPanelPicks::getSelectedClassifiedItem() -{ -	LLPanel* selected_item = mClassifiedsList->getSelectedItem(); -	if (!selected_item)  -	{ -		return NULL; -	} -	return dynamic_cast<LLClassifiedItem*>(selected_item); -} - -BOOL LLPanelPicks::postBuild() -{ -	mPicksList = getChild<LLFlatListView>("picks_list"); -	mClassifiedsList = getChild<LLFlatListView>("classifieds_list"); - -	mPicksList->setCommitOnSelectionChange(true); -	mClassifiedsList->setCommitOnSelectionChange(true); - -	mPicksList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mPicksList)); -	mClassifiedsList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mClassifiedsList)); - -	mPicksList->setNoItemsCommentText(getString("no_picks")); -	mClassifiedsList->setNoItemsCommentText(getString("no_classifieds")); - -	mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); - -	childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this)); -	childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this)); -	childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this)); -	childSetAction(XML_BTN_SHOW_ON_MAP, boost::bind(&LLPanelPicks::onClickMap, this)); -	childSetAction(XML_BTN_INFO, boost::bind(&LLPanelPicks::onClickInfo, this)); - -	mPicksAccTab = getChild<LLAccordionCtrlTab>("tab_picks"); -	mPicksAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mPicksAccTab)); -	mPicksAccTab->setDisplayChildren(true); - -	mClassifiedsAccTab = getChild<LLAccordionCtrlTab>("tab_classifieds"); -	mClassifiedsAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mClassifiedsAccTab)); -	mClassifiedsAccTab->setDisplayChildren(false); -	 -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; -	registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this)); -	registar.add("Pick.Edit", boost::bind(&LLPanelPicks::onClickMenuEdit, this));  -	registar.add("Pick.Teleport", boost::bind(&LLPanelPicks::onClickTeleport, this)); -	registar.add("Pick.Map", boost::bind(&LLPanelPicks::onClickMap, this)); -	registar.add("Pick.Delete", boost::bind(&LLPanelPicks::onClickDelete, this)); -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registar; -	enable_registar.add("Pick.Enable", boost::bind(&LLPanelPicks::onEnableMenuItem, this, _2)); - -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar; -	plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2)); -	mEnableCallbackRegistrar.add("Picks.Plus.Enable", boost::bind(&LLPanelPicks::isActionEnabled, this, _2)); -	mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	 -	return TRUE; -} - -void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param) -{ -	std::string value = param.asString(); - -	if("new_pick" == value) -	{ -		createNewPick(); -	} -	else if("new_classified" == value) -	{ -		createNewClassified(); -	} -} - -bool LLPanelPicks::isActionEnabled(const LLSD& userdata) const -{ -	std::string command_name = userdata.asString(); - -	if (command_name == "new_pick" && LLAgentPicksInfo::getInstance()->isPickLimitReached()) -	{ -		return false; -	} - -	return true; -} - -bool LLPanelPicks::isClassifiedPublished(LLClassifiedItem* c_item) -{ -	if(c_item) -	{ -		LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; -		if(panel) -		{ -			 return !panel->isNewWithErrors(); -		} - -		// we've got this classified from server - it's published -		return true; -	} -	return false; -} - -void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab) -{ -	if(!mPicksAccTab->getDisplayChildren()) -	{ -		mPicksList->resetSelection(true); -	} -	if(!mClassifiedsAccTab->getDisplayChildren()) -	{ -		mClassifiedsList->resetSelection(true); -	} - -	updateButtons(); -} - -void LLPanelPicks::onOpen(const LLSD& key) -{ -	const LLUUID id(key.asUUID()); -	BOOL self = (gAgent.getID() == id); - -	// only agent can edit her picks  -	getChildView("edit_panel")->setEnabled(self); -	getChildView("edit_panel")->setVisible( self); - -	// Disable buttons when viewing profile for first time -	if(getAvatarId() != id) -	{ -		getChildView(XML_BTN_INFO)->setEnabled(FALSE); -		getChildView(XML_BTN_TELEPORT)->setEnabled(FALSE); -		getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(FALSE); -	} - -	// and see a special title - set as invisible by default in xml file -	if (self) -	{ -		getChildView("pick_title")->setVisible( !self); -		getChildView("pick_title_agent")->setVisible( self); - -		mPopupMenu->setItemVisible("pick_delete", TRUE); -		mPopupMenu->setItemVisible("pick_edit", TRUE); -		mPopupMenu->setItemVisible("pick_separator", TRUE); -	} - -	if(getAvatarId() != id) -	{ -		showAccordion("tab_picks", false); -		showAccordion("tab_classifieds", false); - -		mPicksList->goToTop(); -		// Set dummy value to make panel dirty and make it reload picks -		setValue(LLSD()); -	} - -	LLPanelProfileTab::onOpen(key); -} - -void LLPanelPicks::onClosePanel() -{ -	if (mPanelClassifiedInfo) -	{ -		onPanelClassifiedClose(mPanelClassifiedInfo); -	} -	if (mPanelPickInfo) -	{ -		onPanelPickClose(mPanelPickInfo); -	} -} - -void LLPanelPicks::onListCommit(const LLFlatListView* f_list) -{ -	// Make sure only one of the lists has selection. -	if(f_list == mPicksList) -	{ -		mClassifiedsList->resetSelection(true); -	} -	else if(f_list == mClassifiedsList) -	{ -		mPicksList->resetSelection(true); -	} -	else -	{ -		LL_WARNS() << "Unknown list" << LL_ENDL; -	} - -	updateButtons(); -} - -//static -void LLPanelPicks::onClickDelete() -{ -	LLSD value = mPicksList->getSelectedValue(); -	if (value.isDefined()) -	{ -		LLSD args;  -		args["PICK"] = value[PICK_NAME];  -		LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeletePick, this, _1, _2));  -		return; -	} - -	value = mClassifiedsList->getSelectedValue(); -	if(value.isDefined()) -	{ -		LLSD args;  -		args["NAME"] = value[CLASSIFIED_NAME];  -		LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeleteClassified, this, _1, _2));  -		return; -	} -} - -bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& response)  -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	LLSD pick_value = mPicksList->getSelectedValue(); - -	if (0 == option) -	{ -		LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]); -		mPicksList->removeItemByValue(pick_value); -	} -	updateButtons(); -	return false; -} - -bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response)  -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	LLSD value = mClassifiedsList->getSelectedValue(); - -	if (0 == option) -	{ -		LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]); -		mClassifiedsList->removeItemByValue(value); -	} -	updateButtons(); -	return false; -} - -bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response ) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	if (0 == option) -	{ -		onClickTeleport(); -	} -	return false; -} - -//static -void LLPanelPicks::onClickTeleport() -{ -	LLPickItem* pick_item = getSelectedPickItem(); -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); - -	LLVector3d pos; -	if(pick_item) -		pos = pick_item->getPosGlobal(); -	else if(c_item) -	{ -		pos = c_item->getPosGlobal(); -		LLPanelClassifiedInfo::sendClickMessage("teleport", false, -			c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); -	} - -	if (!pos.isExactlyZero()) -	{ -		gAgent.teleportViaLocation(pos); -		LLFloaterWorldMap::getInstance()->trackLocation(pos); -	} -} - -//static -void LLPanelPicks::onClickMap() -{ -	LLPickItem* pick_item = getSelectedPickItem(); -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); - -	LLVector3d pos; -	if (pick_item) -		pos = pick_item->getPosGlobal(); -	else if(c_item) -	{ -		LLPanelClassifiedInfo::sendClickMessage("map", false, -			c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); -		pos = c_item->getPosGlobal(); -	} - -	LLFloaterWorldMap::getInstance()->trackLocation(pos); -	LLFloaterReg::showInstance("world_map", "center"); -} - - -void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) -{ -	updateButtons(); - -	if (mPopupMenu) -	{ -		mPopupMenu->buildDrawLabels(); -		mPopupMenu->updateParent(LLMenuGL::sMenuContainer); -		((LLContextMenu*)mPopupMenu)->show(x, y); -		LLMenuGL::showPopup(item, mPopupMenu, x, y); -	} -} - -void LLPanelPicks::onDoubleClickPickItem(LLUICtrl* item) -{ -	LLSD pick_value = mPicksList->getSelectedValue(); -	if (pick_value.isUndefined()) return; -	 -	LLSD args;  -	args["PICK"] = pick_value[PICK_NAME];  -	LLNotificationsUtil::add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));  -} - -void LLPanelPicks::onDoubleClickClassifiedItem(LLUICtrl* item) -{ -	LLSD value = mClassifiedsList->getSelectedValue(); -	if (value.isUndefined()) return; - -	LLSD args;  -	args["CLASSIFIED"] = value[CLASSIFIED_NAME];  -	LLNotificationsUtil::add("TeleportToClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));  -} - -void LLPanelPicks::updateButtons() -{ -	bool has_selected = mPicksList->numSelected() > 0 || mClassifiedsList->numSelected() > 0; - -	if (getAvatarId() == gAgentID) -	{ -		getChildView(XML_BTN_DELETE)->setEnabled(has_selected); -	} - -	getChildView(XML_BTN_INFO)->setEnabled(has_selected); -	getChildView(XML_BTN_TELEPORT)->setEnabled(has_selected); -	getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(has_selected); - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	if(c_item) -	{ -		getChildView(XML_BTN_INFO)->setEnabled(isClassifiedPublished(c_item)); -	} -} - -void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel) -{ -	mProfilePanel = profile_panel; -} - - -void LLPanelPicks::buildPickPanel() -{ -// 	if (mPickPanel == NULL) -// 	{ -// 		mPickPanel = new LLPanelPick(); -// 		mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, NULL)); -// 	} -} - -void LLPanelPicks::onClickPlusBtn() -{ -	LLRect rect(getChildView(XML_BTN_NEW)->getRect()); - -	mPlusMenu->updateParent(LLMenuGL::sMenuContainer); -	mPlusMenu->setButtonRect(rect, this); -	LLMenuGL::showPopup(this, mPlusMenu, rect.mLeft, rect.mTop); -} - -void LLPanelPicks::createNewPick() -{ -	createPickEditPanel(); - -	getProfilePanel()->openPanel(mPanelPickEdit, LLSD()); -} - -void LLPanelPicks::createNewClassified() -{ -	LLPanelClassifiedEdit* panel = NULL; -	createClassifiedEditPanel(&panel); - -	getProfilePanel()->openPanel(panel, LLSD()); -} - -void LLPanelPicks::onClickInfo() -{ -	if(mPicksList->numSelected() > 0) -	{ -		openPickInfo(); -	} -	else if(mClassifiedsList->numSelected() > 0) -	{ -		openClassifiedInfo(); -	} -} - -void LLPanelPicks::openPickInfo() -{ -	LLSD selected_value = mPicksList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLPickItem* pick = (LLPickItem*)mPicksList->getSelectedItem(); - -	createPickInfoPanel(); - -	LLSD params; -	params["pick_id"] = pick->getPickId(); -	params["avatar_id"] = pick->getCreatorId(); -	params["snapshot_id"] = pick->getSnapshotId(); -	params["pick_name"] = pick->getPickName(); -	params["pick_desc"] = pick->getPickDesc(); - -	getProfilePanel()->openPanel(mPanelPickInfo, params); -} - -void LLPanelPicks::openClassifiedInfo() -{ -	LLSD selected_value = mClassifiedsList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); -	LLSD params; -	params["classified_id"] = c_item->getClassifiedId(); -	params["classified_creator_id"] = c_item->getAvatarId(); -	params["classified_snapshot_id"] = c_item->getSnapshotId(); -	params["classified_name"] = c_item->getClassifiedName(); -	params["classified_desc"] = c_item->getDescription(); -	params["from_search"] = false; - -	openClassifiedInfo(params); -} - -void LLPanelPicks::openClassifiedInfo(const LLSD ¶ms) -{ -	createClassifiedInfoPanel(); -	getProfilePanel()->openPanel(mPanelClassifiedInfo, params); -} - -void LLPanelPicks::openClassifiedEdit(const LLSD& params) -{ -	LLUUID classified_id = params["classified_id"].asUUID();; -	LL_INFOS() << "opening classified " << classified_id << " for edit" << LL_ENDL; -	editClassified(classified_id); -} - -void LLPanelPicks::showAccordion(const std::string& name, bool show) -{ -	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); -	tab->setVisible(show); -	LLAccordionCtrl* acc = getChild<LLAccordionCtrl>("accordion"); -	acc->arrange(); -} - -void LLPanelPicks::onPanelPickClose(LLPanel* panel) -{ -	getProfilePanel()->closePanel(panel); -} - -void LLPanelPicks::onPanelPickSave(LLPanel* panel) -{ -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel) -{ -	if(!panel->canClose()) -	{ -		return; -	} - -	if(panel->isNew()) -	{ -		mEditClassifiedPanels[panel->getClassifiedId()] = panel; - -		LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); -		c_item->fillIn(panel); - -		LLSD c_value; -		c_value.insert(CLASSIFIED_ID, c_item->getClassifiedId()); -		c_value.insert(CLASSIFIED_NAME, c_item->getClassifiedName()); -		mClassifiedsList->addItem(c_item, c_value, ADD_TOP); - -		c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); -		c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -		c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -		c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); - -		// order does matter, showAccordion will invoke arrange for accordions. -		mClassifiedsAccTab->changeOpenClose(false); -		showAccordion("tab_classifieds", true); -	} -	else if(panel->isNewWithErrors()) -	{ -		LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -		llassert(c_item); -		if (c_item) -		{ -			c_item->fillIn(panel); -		} -	} -	else  -	{ -		onPanelClassifiedClose(panel); -		return; -	} - -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedClose(LLPanelClassifiedInfo* panel) -{ -	if(panel->getInfoLoaded() && !panel->isDirty()) -	{ -		std::vector<LLSD> values; -		mClassifiedsList->getValues(values); -		for(size_t n = 0; n < values.size(); ++n) -		{ -			LLUUID c_id = values[n][CLASSIFIED_ID].asUUID(); -			if(panel->getClassifiedId() == c_id) -			{ -				LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>( -					mClassifiedsList->getItemByValue(values[n])); -				llassert(c_item); -				if (c_item) -				{ -					c_item->setClassifiedName(panel->getClassifiedName()); -					c_item->setDescription(panel->getDescription()); -					c_item->setSnapshotId(panel->getSnapshotId()); -				} -			} -		} -	} - -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::createPickInfoPanel() -{ -	if(!mPanelPickInfo) -	{ -		mPanelPickInfo = LLPanelPickInfo::create(); -		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); -		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); -		mPanelPickInfo->setVisible(FALSE); -	} -} - -void LLPanelPicks::createClassifiedInfoPanel() -{ -	mPanelClassifiedInfo = LLPanelClassifiedInfo::create(); -	mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo)); -	mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this)); -	mPanelClassifiedInfo->setVisible(FALSE); -} - -void LLPanelPicks::createClassifiedEditPanel(LLPanelClassifiedEdit** panel) -{ -	if(panel) -	{ -		LLPanelClassifiedEdit* new_panel = LLPanelClassifiedEdit::create(); -		new_panel->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); -		new_panel->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, new_panel)); -		new_panel->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); -		new_panel->setVisible(FALSE); -		*panel = new_panel; -	} -} - -void LLPanelPicks::createPickEditPanel() -{ -	mPanelPickEdit = LLPanelPickEdit::create(); -	mPanelPickEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); -	mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickSave, this, mPanelPickEdit)); -	mPanelPickEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); -	mPanelPickEdit->setVisible(FALSE); -} - -// void LLPanelPicks::openPickEditPanel(LLPickItem* pick) -// { -// 	if(!pick) -// 	{ -// 		return; -// 	} -// } - -// void LLPanelPicks::openPickInfoPanel(LLPickItem* pick) -// { -// 	if(!mPanelPickInfo) -// 	{ -// 		mPanelPickInfo = LLPanelPickInfo::create(); -// 		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); -// 		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); -// 		mPanelPickInfo->setVisible(FALSE); -// 	} -//  -// 	LLSD params; -// 	params["pick_id"] = pick->getPickId(); -// 	params["avatar_id"] = pick->getCreatorId(); -// 	params["snapshot_id"] = pick->getSnapshotId(); -// 	params["pick_name"] = pick->getPickName(); -// 	params["pick_desc"] = pick->getPickDesc(); -//  -// 	getProfilePanel()->openPanel(mPanelPickInfo, params); -// } - -void LLPanelPicks::openPickEdit(const LLSD& params) -{ -	createPickEditPanel(); -	getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelPickEdit() -{ -	LLSD selected_value = mPicksList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLPickItem* pick = dynamic_cast<LLPickItem*>(mPicksList->getSelectedItem()); -	 -	createPickEditPanel(); - -	LLSD params; -	params["pick_id"] = pick->getPickId(); -	params["avatar_id"] = pick->getCreatorId(); -	params["snapshot_id"] = pick->getSnapshotId(); -	params["pick_name"] = pick->getPickName(); -	params["pick_desc"] = pick->getPickDesc(); - -	getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelClassifiedEdit() -{ -	LLSD selected_value = mClassifiedsList->getSelectedValue(); -	if (selected_value.isUndefined())  -	{ -		return; -	} - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	llassert(c_item); -	if (!c_item) -	{ -		return; -	} -	editClassified(c_item->getClassifiedId()); -} - -LLClassifiedItem *LLPanelPicks::findClassifiedById(const LLUUID& classified_id) -{ -	// HACK - find item by classified id.  Should be a better way. -	std::vector<LLPanel*> items; -	mClassifiedsList->getItems(items); -	LLClassifiedItem* c_item = NULL; -	for(std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) -	{ -		LLClassifiedItem *test_item = dynamic_cast<LLClassifiedItem*>(*it); -		if (test_item && test_item->getClassifiedId() == classified_id) -		{ -			c_item = test_item; -			break; -		} -	} -	return c_item; -} - -void LLPanelPicks::editClassified(const LLUUID&  classified_id) -{ -	LLClassifiedItem* c_item = findClassifiedById(classified_id); -	if (!c_item) -	{ -		LL_WARNS() << "item not found for classified_id " << classified_id << LL_ENDL; -		return; -	} - -	LLSD params; -	params["classified_id"] = c_item->getClassifiedId(); -	params["classified_creator_id"] = c_item->getAvatarId(); -	params["snapshot_id"] = c_item->getSnapshotId(); -	params["name"] = c_item->getClassifiedName(); -	params["desc"] = c_item->getDescription(); -	params["category"] = (S32)c_item->getCategory(); -	params["content_type"] = (S32)c_item->getContentType(); -	params["auto_renew"] = c_item->getAutoRenew(); -	params["price_for_listing"] = c_item->getPriceForListing(); -	params["location_text"] = c_item->getLocationText(); - -	LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; -	if(!panel) -	{ -		createClassifiedEditPanel(&panel); -		mEditClassifiedPanels[c_item->getClassifiedId()] = panel; -	} -	getProfilePanel()->openPanel(panel, params); -	panel->setPosGlobal(c_item->getPosGlobal()); -} - -void LLPanelPicks::onClickMenuEdit() -{ -	if(getSelectedPickItem()) -	{ -		onPanelPickEdit(); -	} -	else if(getSelectedClassifiedItem()) -	{ -		onPanelClassifiedEdit(); -	} -} - -bool LLPanelPicks::onEnableMenuItem(const LLSD& user_data) -{ -	std::string param = user_data.asString(); - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	if(c_item && "info" == param) -	{ -		// dont show Info panel if classified was not created -		return isClassifiedPublished(c_item); -	} - -	return true; -} - -inline LLPanelProfile* LLPanelPicks::getProfilePanel() -{ -	llassert_always(NULL != mProfilePanel); -	return mProfilePanel; -} - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPickItem::LLPickItem() -: LLPanel() -, mPickID(LLUUID::null) -, mCreatorID(LLUUID::null) -, mParcelID(LLUUID::null) -, mSnapshotID(LLUUID::null) -, mNeedData(true) -{ -	buildFromFile("panel_pick_list_item.xml"); -} - -LLPickItem::~LLPickItem() -{ -	if (mCreatorID.notNull()) -	{ -		LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); -	} - -} - -LLPickItem* LLPickItem::create() -{ -	return new LLPickItem(); -} - -void LLPickItem::init(LLPickData* pick_data) -{ -	setPickDesc(pick_data->desc); -	setSnapshotId(pick_data->snapshot_id); -	mPosGlobal = pick_data->pos_global; -	mSimName = pick_data->sim_name; -	mPickDescription = pick_data->desc; -	mUserName = pick_data->user_name; -	mOriginalName = pick_data->original_name; - -	LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture"); -	picture->setImageAssetID(pick_data->snapshot_id); -} - -void LLPickItem::setPickName(const std::string& name) -{ -	mPickName = name; -	getChild<LLUICtrl>("picture_name")->setValue(name); - -} - -const std::string& LLPickItem::getPickName() -{ -	return mPickName; -} - -const LLUUID& LLPickItem::getCreatorId() -{ -	return mCreatorID; -} - -const LLUUID& LLPickItem::getSnapshotId() -{ -	return mSnapshotID; -} - -void LLPickItem::setPickDesc(const std::string& descr) -{ -	getChild<LLUICtrl>("picture_descr")->setValue(descr); -} - -void LLPickItem::setPickId(const LLUUID& id) -{ -	mPickID = id; -} - -const LLUUID& LLPickItem::getPickId() -{ -	return mPickID; -} - -const LLVector3d& LLPickItem::getPosGlobal() -{ -	return mPosGlobal; -} - -const std::string LLPickItem::getDescription() -{ -	return getChild<LLUICtrl>("picture_descr")->getValue().asString(); -} - -void LLPickItem::update() -{ -	setNeedData(true); -	LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID); -} - -void LLPickItem::processProperties(void *data, EAvatarProcessorType type) -{ -	if (APT_PICK_INFO != type)  -	{ -		return; -	} - -	LLPickData* pick_data = static_cast<LLPickData *>(data); -	if (!pick_data || mPickID != pick_data->pick_id)  -	{ -		return; -	} - -	init(pick_data); -	setNeedData(false); -	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); -} - -void set_child_visible(LLView* parent, const std::string& child_name, bool visible) -{ -	parent->getChildView(child_name)->setVisible(visible); -} - -BOOL LLPickItem::postBuild() -{ -	setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); -	setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); -	return TRUE; -} - -void LLPickItem::setValue(const LLSD& value) -{ -	if (!value.isMap()) return;; -	if (!value.has("selected")) return; -	getChildView("selected_icon")->setVisible( value["selected"]); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id) - : LLPanel() - , mAvatarId(avatar_id) - , mClassifiedId(classified_id) -{ -	buildFromFile("panel_classifieds_list_item.xml"); - -	LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); -	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); -} - -LLClassifiedItem::~LLClassifiedItem() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_CLASSIFIED_INFO != type) -	{ -		return; -	} - -	LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -	if( !c_info || c_info->classified_id != getClassifiedId() ) -	{ -		return; -	} - -	setClassifiedName(c_info->name); -	setDescription(c_info->description); -	setSnapshotId(c_info->snapshot_id); -	setPosGlobal(c_info->pos_global); - -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -BOOL LLClassifiedItem::postBuild() -{ -	setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); -	setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); -	return TRUE; -} - -void LLClassifiedItem::setValue(const LLSD& value) -{ -	if (!value.isMap()) return;; -	if (!value.has("selected")) return; -	getChildView("selected_icon")->setVisible( value["selected"]); -} - -void LLClassifiedItem::fillIn(LLPanelClassifiedEdit* panel) -{ -	if(!panel) -	{ -		return; -	} - -	setClassifiedName(panel->getClassifiedName()); -	setDescription(panel->getDescription()); -	setSnapshotId(panel->getSnapshotId()); -	setCategory(panel->getCategory()); -	setContentType(panel->getContentType()); -	setAutoRenew(panel->getAutoRenew()); -	setPriceForListing(panel->getPriceForListing()); -	setPosGlobal(panel->getPosGlobal()); -	setLocationText(panel->getClassifiedLocation()); -} - -void LLClassifiedItem::setClassifiedName(const std::string& name) -{ -	getChild<LLUICtrl>("name")->setValue(name); -} - -void LLClassifiedItem::setDescription(const std::string& desc) -{ -	getChild<LLUICtrl>("description")->setValue(desc); -} - -void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id) -{ -	getChild<LLUICtrl>("picture")->setValue(snapshot_id); -} - -LLUUID LLClassifiedItem::getSnapshotId() -{ -	return getChild<LLUICtrl>("picture")->getValue(); -} - -//EOF diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h deleted file mode 100644 index 3bb7413ac3..0000000000 --- a/indra/newview/llpanelpicks.h +++ /dev/null @@ -1,314 +0,0 @@ -/**  - * @file llpanelpicks.h - * @brief LLPanelPicks and related class definitions - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -#ifndef LL_LLPANELPICKS_H -#define LL_LLPANELPICKS_H - -#include "llpanel.h" -#include "v3dmath.h" -#include "lluuid.h" -#include "llavatarpropertiesprocessor.h" -#include "llpanelavatar.h" -#include "llregistry.h" - -class LLAccordionCtrlTab; -class LLPanelProfile; -class LLMessageSystem; -class LLVector3d; -class LLPanelProfileTab; -class LLAgent; -class LLMenuGL; -class LLPickItem; -class LLClassifiedItem; -class LLFlatListView; -class LLPanelPickInfo; -class LLPanelPickEdit; -class LLToggleableMenu; -class LLPanelClassifiedInfo; -class LLPanelClassifiedEdit; - -// *TODO -// Panel Picks has been consolidated with Classifieds (EXT-2095), give LLPanelPicks -// and corresponding files (cpp, h, xml) a new name. (new name is TBD at the moment) - -class LLPanelPicks  -	: public LLPanelProfileTab -{ -public: -	LLPanelPicks(); -	~LLPanelPicks(); - -	static void* create(void* data); - -	/*virtual*/ BOOL postBuild(void); - -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ void onClosePanel(); - -	void processProperties(void* data, EAvatarProcessorType type); - -	void updateData(); - -	// returns the selected pick item -	LLPickItem* getSelectedPickItem(); -	LLClassifiedItem* getSelectedClassifiedItem(); -	LLClassifiedItem* findClassifiedById(const LLUUID& classified_id); - -	//*NOTE top down approch when panel toggling is done only by  -	// parent panels failed to work (picks related code was in my profile panel) -	void setProfilePanel(LLPanelProfile* profile_panel); - -	void createNewPick(); -	void createNewClassified(); - -protected: -	/*virtual*/void updateButtons(); - -private: -	void onClickDelete(); -	void onClickTeleport(); -	void onClickMap(); - -	void onPlusMenuItemClicked(const LLSD& param); -	bool isActionEnabled(const LLSD& userdata) const; - -	bool isClassifiedPublished(LLClassifiedItem* c_item); - -	void onListCommit(const LLFlatListView* f_list); -	void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); - -	//------------------------------------------------ -	// Callbacks which require panel toggling -	//------------------------------------------------ -	void onClickPlusBtn(); -	void onClickInfo(); -	void onPanelPickClose(LLPanel* panel); -	void onPanelPickSave(LLPanel* panel); -	void onPanelClassifiedSave(LLPanelClassifiedEdit* panel); -	void onPanelClassifiedClose(LLPanelClassifiedInfo* panel); -	void openPickEdit(const LLSD& params); -	void onPanelPickEdit(); -	void onPanelClassifiedEdit(); -	void editClassified(const LLUUID&  classified_id); -	void onClickMenuEdit(); - -	bool onEnableMenuItem(const LLSD& user_data); - -	void openPickInfo(); -	void openClassifiedInfo(); -	void openClassifiedInfo(const LLSD& params); -	void openClassifiedEdit(const LLSD& params); -	friend class LLPanelProfile; - -	void showAccordion(const std::string& name, bool show); - -	void buildPickPanel(); - -	bool callbackDeletePick(const LLSD& notification, const LLSD& response); -	bool callbackDeleteClassified(const LLSD& notification, const LLSD& response); -	bool callbackTeleport(const LLSD& notification, const LLSD& response); - - -	virtual void onDoubleClickPickItem(LLUICtrl* item); -	virtual void onDoubleClickClassifiedItem(LLUICtrl* item); -	virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); - -	LLPanelProfile* getProfilePanel(); - -	void createPickInfoPanel(); -	void createPickEditPanel(); -	void createClassifiedInfoPanel(); -	void createClassifiedEditPanel(LLPanelClassifiedEdit** panel); - -	LLMenuGL* mPopupMenu; -	LLPanelProfile* mProfilePanel; -	LLPanelPickInfo* mPickPanel; -	LLFlatListView* mPicksList; -	LLFlatListView* mClassifiedsList; -	LLPanelPickInfo* mPanelPickInfo; -	LLPanelClassifiedInfo* mPanelClassifiedInfo; -	LLPanelPickEdit* mPanelPickEdit; -	LLToggleableMenu* mPlusMenu; -	LLUICtrl* mNoItemsLabel; - -	// <classified_id, edit_panel> -	typedef std::map<LLUUID, LLPanelClassifiedEdit*> panel_classified_edit_map_t; - -	// This map is needed for newly created classifieds. The purpose of panel is to -	// sit in this map and listen to LLPanelClassifiedEdit::processProperties callback. -	panel_classified_edit_map_t mEditClassifiedPanels; - -	LLAccordionCtrlTab* mPicksAccTab; -	LLAccordionCtrlTab* mClassifiedsAccTab; - -	//true if picks list is empty after processing picks -	bool mNoPicks; -	//true if classifieds list is empty after processing classifieds -	bool mNoClassifieds; -}; - -class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - -	LLPickItem(); - -	static LLPickItem* create(); - -	void init(LLPickData* pick_data); - -	void setPickName(const std::string& name); - -	void setPickDesc(const std::string& descr); - -	void setPickId(const LLUUID& id); - -	void setCreatorId(const LLUUID& id) {mCreatorID = id;}; - -	void setSnapshotId(const LLUUID& id) {mSnapshotID = id;}; - -	void setNeedData(bool need){mNeedData = need;}; - -	const LLUUID& getPickId();  - -	const std::string& getPickName(); - -	const LLUUID& getCreatorId(); - -	const LLUUID& getSnapshotId(); - -	const LLVector3d& getPosGlobal(); - -	const std::string getDescription(); - -	const std::string& getSimName() { return mSimName; } - -	const std::string& getUserName() { return mUserName; } - -	const std::string& getOriginalName() { return mOriginalName; } - -	const std::string& getPickDesc() { return mPickDescription; } - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	void update(); - -	~LLPickItem(); - -	/*virtual*/ BOOL postBuild(); - -	/** setting on/off background icon to indicate selected state */ -	/*virtual*/ void setValue(const LLSD& value); - -protected: - -	LLUUID mPickID; -	LLUUID mCreatorID; -	LLUUID mParcelID; -	LLUUID mSnapshotID; -	LLVector3d mPosGlobal; -	bool mNeedData; - -	std::string mPickName; -	std::string mUserName; -	std::string mOriginalName; -	std::string mPickDescription; -	std::string mSimName; -}; - -class LLClassifiedItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - -	LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id); -	 -	virtual ~LLClassifiedItem(); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	/*virtual*/ BOOL postBuild(); - -	/*virtual*/ void setValue(const LLSD& value); - -	void fillIn(LLPanelClassifiedEdit* panel); - -	LLUUID getAvatarId() {return mAvatarId;} -	 -	void setAvatarId(const LLUUID& avatar_id) {mAvatarId = avatar_id;} - -	LLUUID getClassifiedId() {return mClassifiedId;} - -	void setClassifiedId(const LLUUID& classified_id) {mClassifiedId = classified_id;} - -	void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } - -	const LLVector3d getPosGlobal() { return mPosGlobal; } - -	void setLocationText(const std::string location) { mLocationText = location; } - -	std::string getLocationText() { return mLocationText; } - -	void setClassifiedName (const std::string& name); - -	std::string getClassifiedName() { return getChild<LLUICtrl>("name")->getValue().asString(); } - -	void setDescription(const std::string& desc); - -	std::string getDescription() { return getChild<LLUICtrl>("description")->getValue().asString(); } - -	void setSnapshotId(const LLUUID& snapshot_id); - -	LLUUID getSnapshotId(); - -	void setCategory(U32 cat) { mCategory = cat; } - -	U32 getCategory() { return mCategory; } - -	void setContentType(U32 ct) { mContentType = ct; } - -	U32 getContentType() { return mContentType; } - -	void setAutoRenew(U32 renew) { mAutoRenew = renew; } - -	bool getAutoRenew() { return mAutoRenew; } - -	void setPriceForListing(S32 price) { mPriceForListing = price; } - -	S32 getPriceForListing() { return mPriceForListing; } - -private: -	LLUUID mAvatarId; -	LLUUID mClassifiedId; -	LLVector3d mPosGlobal; -	std::string mLocationText; -	U32 mCategory; -	U32 mContentType; -	bool mAutoRenew; -	S32 mPriceForListing; -}; - -#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 8afa35efa0..fea76f9d04 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1,25 +1,25 @@ -/**  +/**  * @file llpanelprofile.cpp  * @brief Profile panel implementation  *  * $LicenseInfo:firstyear=2009&license=viewerlgpl$  * Second Life Viewer Source Code  * Copyright (C) 2010, 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$  */ @@ -27,31 +27,65 @@  #include "llviewerprecompiledheaders.h"  #include "llpanelprofile.h" -#include "llagent.h" +// Common +#include "llavatarnamecache.h" +#include "llslurl.h" +#include "lldateutil.h" //ageFromDate + +// UI +#include "llavatariconctrl.h" +// #include "llclipboard.h" //gClipboard +#include "llcheckboxctrl.h" +#include "lllineeditor.h" +#include "llloadingindicator.h" +#include "llmenubutton.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltoggleablemenu.h" +#include "llgrouplist.h" + +// Newview +#include "llagent.h" //gAgent +#include "llagentpicksinfo.h"  #include "llavataractions.h" -#include "llfloaterreg.h" +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h"  #include "llcommandhandler.h" -#include "llnotificationsutil.h" -#include "llpanelpicks.h" -#include "lltabcontainer.h" -#include "llviewercontrol.h" -#include "llviewernetwork.h" +#include "llfloaterreg.h" +#include "llfirstuse.h" +#include "llgroupactions.h"  #include "llmutelist.h" +#include "llnotificationsutil.h"  #include "llpanelblockedlist.h" +#include "llpanelprofileclassifieds.h" +#include "llpanelprofilepicks.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llvoiceclient.h"  #include "llweb.h" -static const std::string PANEL_PICKS = "panel_picks"; -std::string getProfileURL(const std::string& agent_name) -{ -	std::string url = "[WEB_PROFILE_URL][AGENT_NAME]"; -	LLSD subs; -	subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); -	subs["AGENT_NAME"] = agent_name; -	url = LLWeb::expandURLSubstitutions(url, subs); -	LLStringUtil::toLower(url); -	return url; -} +static LLPanelInjector<LLPanelProfileSecondLife> t_panel_profile_secondlife("panel_profile_secondlife"); +static LLPanelInjector<LLPanelProfileWeb> t_panel_web("panel_profile_web"); +static LLPanelInjector<LLPanelProfileInterests> t_panel_interests("panel_profile_interests"); +static LLPanelInjector<LLPanelProfilePicks> t_panel_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfileFirstLife> t_panel_firstlife("panel_profile_firstlife"); +static LLPanelInjector<LLPanelProfileNotes> t_panel_notes("panel_profile_notes"); +static LLPanelInjector<LLPanelProfile>          t_panel_profile("panel_profile"); + +static const std::string PANEL_SECONDLIFE   = "panel_profile_secondlife"; +static const std::string PANEL_WEB          = "panel_profile_web"; +static const std::string PANEL_INTERESTS    = "panel_profile_interests"; +static const std::string PANEL_PICKS        = "panel_profile_picks"; +static const std::string PANEL_CLASSIFIEDS  = "panel_profile_classifieds"; +static const std::string PANEL_FIRSTLIFE    = "panel_profile_firstlife"; +static const std::string PANEL_NOTES        = "panel_profile_notes"; + + +////////////////////////////////////////////////////////////////////////// +// LLProfileHandler  class LLProfileHandler : public LLCommandHandler  { @@ -73,6 +107,10 @@ public:  };  LLProfileHandler gProfileHandler; + +////////////////////////////////////////////////////////////////////////// +// LLAgentHandler +  class LLAgentHandler : public LLCommandHandler  {  public: @@ -184,273 +222,1269 @@ public:  LLAgentHandler gAgentHandler; -//-- LLPanelProfile::ChildStack begins ---------------------------------------- -LLPanelProfile::ChildStack::ChildStack() -:	mParent(NULL) + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileSecondLife + +LLPanelProfileSecondLife::LLPanelProfileSecondLife() + : LLPanelProfileTab() + , mStatusText(NULL) + , mAvatarNameCacheConnection()  {  } -LLPanelProfile::ChildStack::~ChildStack() +LLPanelProfileSecondLife::~LLPanelProfileSecondLife()  { -	while (mStack.size() != 0) -	{ -		view_list_t& top = mStack.back(); -		for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) -		{ -			LLView* viewp = *it; -			if (viewp) -			{ -				viewp->die(); -			} -		} -		mStack.pop_back(); -	} +    if (getAvatarId().notNull()) +    { +        LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +    } + +    if (LLVoiceClient::instanceExists()) +    { +        LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); +    } + +    if (mAvatarNameCacheConnection.connected()) +    { +        mAvatarNameCacheConnection.disconnect(); +    }  } -void LLPanelProfile::ChildStack::setParent(LLPanel* parent) +BOOL LLPanelProfileSecondLife::postBuild()  { -	llassert_always(parent != NULL); -	mParent = parent; +    mStatusText             = getChild<LLTextBox>("status"); +    mGroupList              = getChild<LLGroupList>("group_list"); +    mShowInSearchCheckbox   = getChild<LLCheckBoxCtrl>("show_in_search_checkbox"); +    mSecondLifePic          = getChild<LLTextureCtrl>("2nd_life_pic"); +    mDescriptionEdit        = getChild<LLTextBase>("sl_description_edit"); +    mTeleportButton         = getChild<LLButton>("teleport"); +    mShowOnMapButton        = getChild<LLButton>("show_on_map_btn"); +    mBlockButton            = getChild<LLButton>("block"); +    mUnblockButton          = getChild<LLButton>("unblock"); +    mNameLabel              = getChild<LLUICtrl>("name_label"); +    mDisplayNameButton      = getChild<LLButton>("set_name"); +    mAddFriendButton        = getChild<LLButton>("add_friend"); +    mGroupInviteButton      = getChild<LLButton>("group_invite"); +    mPayButton              = getChild<LLButton>("pay"); +    mIMButton               = getChild<LLButton>("im"); + +    mStatusText->setVisible(FALSE); + +    mAddFriendButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onAddFriendButtonClick, this)); +    mIMButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onIMButtonClick, this)); +    mTeleportButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onTeleportButtonClick, this)); +    mShowOnMapButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onMapButtonClick, this)); +    mPayButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::pay, this)); +    mBlockButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::toggleBlock,this)); +    mUnblockButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::toggleBlock,this)); +    mGroupInviteButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onGroupInvite,this)); +    mDisplayNameButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onClickSetName, this)); + +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; +    enable.add("Profile.EnableCall",                [this](LLUICtrl*, const LLSD&) { return mVoiceStatus; }); +    enable.add("Profile.EnableGod",                 [](LLUICtrl*, const LLSD&) { return gAgent.isGodlike(); }); + +    mGroupList->setDoubleClickCallback(boost::bind(&LLPanelProfileSecondLife::openGroupProfile, this)); +    mGroupList->setReturnCallback(boost::bind(&LLPanelProfileSecondLife::openGroupProfile, this)); + +    LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); + +    return TRUE;  } -/// Save current parent's child views and remove them from the child list. -bool LLPanelProfile::ChildStack::push() +void LLPanelProfileSecondLife::onOpen(const LLSD& key)  { -	view_list_t vlist = *mParent->getChildList(); +    LLPanelProfileTab::onOpen(key); -	for (view_list_t::const_iterator it = vlist.begin(); it != vlist.end(); ++it) -	{ -		LLView* viewp = *it; -		mParent->removeChild(viewp); -	} +    resetData(); -	mStack.push_back(vlist); -	dump(); -	return true; +    LLUUID avatar_id = getAvatarId(); +    LLAvatarPropertiesProcessor::getInstance()->addObserver(avatar_id, this); + +    BOOL own_profile = getSelfProfile(); + +    mGroupInviteButton->setVisible(!own_profile); +    mShowOnMapButton->setVisible(!own_profile); +    mPayButton->setVisible(!own_profile); +    mTeleportButton->setVisible(!own_profile); +    mIMButton->setVisible(!own_profile); +    mAddFriendButton->setVisible(!own_profile); +    mBlockButton->setVisible(!own_profile); +    mUnblockButton->setVisible(!own_profile); +    mGroupList->setShowNone(!own_profile); + +    if (own_profile && !getEmbedded()) +    { +        // Group list control cannot toggle ForAgent loading +        // Less than ideal, but viewing own profile via search is edge case +        mGroupList->enableForAgent(false); +    } + +    if (own_profile && !getEmbedded() ) +    { +        mNameLabel->setVisible(FALSE); +        mDisplayNameButton->setVisible(TRUE); +        mDisplayNameButton->setEnabled(TRUE); +    } + +    mDescriptionEdit->setParseHTML(!own_profile && !getEmbedded()); + +    LLProfileDropTarget* drop_target = getChild<LLProfileDropTarget>("drop_target"); +    drop_target->setVisible(!own_profile); +    drop_target->setEnabled(!own_profile); + +    if (!own_profile) +    { +        mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : TRUE); +        drop_target->setAgentID(avatar_id); +        updateOnlineStatus(); +    } + +    updateButtons(); + +    mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2));  } -/// Restore saved children (adding them back to the child list). -bool LLPanelProfile::ChildStack::pop() +void LLPanelProfileSecondLife::apply(LLAvatarData* data)  { -	if (mStack.size() == 0) -	{ -		LL_WARNS() << "Empty stack" << LL_ENDL; -		llassert(mStack.size() == 0); -		return false; -	} +    if (getIsLoaded() && getSelfProfile()) +    { +        data->image_id = mSecondLifePic->getImageAssetID(); +        data->about_text = mDescriptionEdit->getValue().asString(); +        data->allow_publish = mShowInSearchCheckbox->getValue(); -	view_list_t& top = mStack.back(); -	for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) -	{ -		LLView* viewp = *it; -		mParent->addChild(viewp); -	} +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(data); +    } +} -	mStack.pop_back(); -	dump(); -	return true; +void LLPanelProfileSecondLife::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull() && !(getSelfProfile() && !getEmbedded())) +    { +        setIsLoading(); +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarGroupsRequest(avatar_id); +    }  } -/// Temporarily add all saved children back. -void LLPanelProfile::ChildStack::preParentReshape() +void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type)  { -	mSavedStack = mStack; -	while(mStack.size() > 0) -	{ -		pop(); -	} + +    if (APT_PROPERTIES == type) +    { +        const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data); +        if(avatar_data && getAvatarId() == avatar_data->avatar_id) +        { +            processProfileProperties(avatar_data); +            updateButtons(); +        } +    } +    else if (APT_GROUPS == type) +    { +        LLAvatarGroups* avatar_groups = static_cast<LLAvatarGroups*>(data); +        if(avatar_groups && getAvatarId() == avatar_groups->avatar_id) +        { +            processGroupProperties(avatar_groups); +        } +    }  } -/// Add the temporarily saved children back. -void LLPanelProfile::ChildStack::postParentReshape() +void LLPanelProfileSecondLife::resetData()  { -	mStack = mSavedStack; -	mSavedStack = stack_t(); +    resetLoading(); +    getChild<LLUICtrl>("complete_name")->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("register_date")->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("acc_status_text")->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("partner_text")->setValue(LLStringUtil::null); +    mSecondLifePic->setValue(mSecondLifePic->getDefaultImageAssetID()); +    mDescriptionEdit->setValue(LLStringUtil::null); +    mStatusText->setVisible(FALSE); +    mGroups.clear(); +    mGroupList->setGroups(mGroups); +} -	for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it) -	{ -		const view_list_t& vlist = (*stack_it); -		for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) -		{ -			LLView* viewp = *list_it; -			LL_DEBUGS() << "removing " << viewp->getName() << LL_ENDL; -			mParent->removeChild(viewp); -		} -	} +void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) +{ +    LLUUID avatar_id = getAvatarId(); +    if (!LLAvatarActions::isFriend(avatar_id) && !getSelfProfile()) +    { +        // this is non-friend avatar. Status will be updated from LLAvatarPropertiesProcessor. +        // in LLPanelProfileSecondLife::processOnlineStatus() + +        // subscribe observer to get online status. Request will be sent by LLPanelProfileSecondLife itself. +        // do not subscribe for friend avatar because online status can be wrong overridden +        // via LLAvatarData::flags if Preferences: "Only Friends & Groups can see when I am online" is set. +        processOnlineStatus(avatar_data->flags & AVATAR_ONLINE); +    } + +    fillCommonData(avatar_data); + +    fillPartnerData(avatar_data); + +    fillAccountStatus(avatar_data);  } -void LLPanelProfile::ChildStack::dump() +void LLPanelProfileSecondLife::processGroupProperties(const LLAvatarGroups* avatar_groups)  { -	unsigned lvl = 0; -	LL_DEBUGS() << "child stack dump:" << LL_ENDL; -	for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it, ++lvl) -	{ -		std::ostringstream dbg_line; -		dbg_line << "lvl #" << lvl << ":"; -		const view_list_t& vlist = (*stack_it); -		for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) -		{ -			dbg_line << " " << (*list_it)->getName(); -		} -		LL_DEBUGS() << dbg_line.str() << LL_ENDL; -	} +    //KC: the group_list ctrl can handle all this for us on our own profile +    if (getSelfProfile() && !getEmbedded()) +    { +        return; +    } + +    // *NOTE dzaporozhan +    // Group properties may arrive in two callbacks, we need to save them across +    // different calls. We can't do that in textbox as textbox may change the text. + +    LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); +    const LLAvatarGroups::group_list_t::const_iterator it_end = avatar_groups->group_list.end(); + +    for (; it_end != it; ++it) +    { +        LLAvatarGroups::LLGroupData group_data = *it; +        mGroups[group_data.group_name] = group_data.group_id; +    } + +    mGroupList->setGroups(mGroups);  } -//-- LLPanelProfile::ChildStack ends ------------------------------------------ +void LLPanelProfileSecondLife::openGroupProfile() +{ +    LLUUID group_id = mGroupList->getSelectedUUID(); +    LLGroupActions::show(group_id); +} -LLPanelProfile::LLPanelProfile() - : LLPanel() - , mAvatarId(LLUUID::null) +void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)  { -	mChildStack.setParent(this); +    mAvatarNameCacheConnection.disconnect(); + +    getChild<LLUICtrl>("complete_name")->setValue( av_name.getCompleteName() );  } -BOOL LLPanelProfile::postBuild() +void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)  { -	LLPanelPicks* panel_picks = findChild<LLPanelPicks>(PANEL_PICKS); -	panel_picks->setProfilePanel(this); +    //remove avatar id from cache to get fresh info +    LLAvatarIconIDCache::getInstance()->remove(avatar_data->avatar_id); + +    LLStringUtil::format_map_t args; +    { +        std::string birth_date = LLTrans::getString("AvatarBirthDateFormat"); +        LLStringUtil::format(birth_date, LLSD().with("datetime", (S32) avatar_data->born_on.secondsSinceEpoch())); +        args["[REG_DATE]"] = birth_date; +    } -	getTabContainer()[PANEL_PICKS] = panel_picks; +    args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now()); +    std::string register_date = getString("RegisterDateFormat", args); +    getChild<LLUICtrl>("register_date")->setValue(register_date ); +    mDescriptionEdit->setValue(avatar_data->about_text); +    mSecondLifePic->setValue(avatar_data->image_id); -	return TRUE; +    if (getSelfProfile()) +    { +        mShowInSearchCheckbox->setValue((BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH)); +    }  } -// virtual -void LLPanelProfile::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data)  { -	// Temporarily add saved children back and reshape them. -	mChildStack.preParentReshape(); -	LLPanel::reshape(width, height, called_from_parent); -	mChildStack.postParentReshape(); +    LLTextEditor* partner_text = getChild<LLTextEditor>("partner_text"); +    if (avatar_data->partner_id.notNull()) +    { +        partner_text->setText(LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString()); +    } +    else +    { +        partner_text->setText(getString("no_partner_text")); +    }  } -void LLPanelProfile::onOpen(const LLSD& key) +void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data)  { -	getTabContainer()[PANEL_PICKS]->onOpen(getAvatarId()); +    LLStringUtil::format_map_t args; +    args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); +    args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); -	// support commands to open further pieces of UI -	if (key.has("show_tab_panel")) -	{ -		std::string panel = key["show_tab_panel"].asString(); -		if (panel == "create_classified") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				picks->createNewClassified(); -			} -		} -		else if (panel == "classified_details") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openClassifiedInfo(params); -			} -		} -		else if (panel == "edit_classified") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openClassifiedEdit(params); -			} -		} -		else if (panel == "create_pick") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				picks->createNewPick(); -			} -		} -		else if (panel == "edit_pick") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openPickEdit(params); -			} -		} -	} +    std::string caption_text = getString("CaptionTextAcctInfo", args); +    getChild<LLUICtrl>("acc_status_text")->setValue(caption_text);  } -void LLPanelProfile::onTabSelected(const LLSD& param) +void LLPanelProfileSecondLife::onMapButtonClick()  { -	std::string tab_name = param.asString(); -	if (NULL != getTabContainer()[tab_name]) -	{ -		getTabContainer()[tab_name]->onOpen(getAvatarId()); -	} +    LLAvatarActions::showOnMap(getAvatarId());  } -void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params) +void LLPanelProfileSecondLife::pay()  { -	// Hide currently visible panel (STORM-690). -	mChildStack.push(); +    LLAvatarActions::pay(getAvatarId()); +} -	// Add the panel or bring it to front. -	if (panel->getParent() != this) -	{ -		addChild(panel); -	} -	else -	{ -		sendChildToFront(panel); -	} +void LLPanelProfileSecondLife::toggleBlock() +{ +    LLAvatarActions::toggleBlock(getAvatarId()); -	panel->setVisible(TRUE); -	panel->setFocus(TRUE); // prevent losing focus by the floater -	panel->onOpen(params); +    updateButtons(); +} -	LLRect new_rect = getRect(); -	panel->reshape(new_rect.getWidth(), new_rect.getHeight()); -	new_rect.setLeftTopAndSize(0, new_rect.getHeight(), new_rect.getWidth(), new_rect.getHeight()); -	panel->setRect(new_rect); +void LLPanelProfileSecondLife::onAddFriendButtonClick() +{ +    LLAvatarActions::requestFriendshipDialog(getAvatarId());  } -void LLPanelProfile::closePanel(LLPanel* panel) +void LLPanelProfileSecondLife::onIMButtonClick()  { -	panel->setVisible(FALSE); +    LLAvatarActions::startIM(getAvatarId()); +} -	if (panel->getParent() == this)  -	{ -		removeChild(panel); +void LLPanelProfileSecondLife::onTeleportButtonClick() +{ +    LLAvatarActions::offerTeleport(getAvatarId()); +} -		// Make the underlying panel visible. -		mChildStack.pop(); +void LLPanelProfileSecondLife::onGroupInvite() +{ +    LLAvatarActions::inviteToGroup(getAvatarId()); +} -		// Prevent losing focus by the floater -		const child_list_t* child_list = getChildList(); -		if (child_list->size() > 0) -		{ -			child_list->front()->setFocus(TRUE); -		} -		else -		{ -			LL_WARNS() << "No underlying panel to focus." << LL_ENDL; -		} -	} +// virtual, called by LLAvatarTracker +void LLPanelProfileSecondLife::changed(U32 mask) +{ +    updateOnlineStatus(); +    updateButtons();  } -S32 LLPanelProfile::notifyParent(const LLSD& info) +// virtual, called by LLVoiceClient +void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal)  { -	std::string action = info["action"]; -	// lets update Picks list after Pick was saved -	if("save_new_pick" == action) -	{ -		onOpen(info); -		return 1; -	} +    if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +    { +        return; +    } + +    mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : TRUE); +} + +void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.notNull()) +    { +        if (getAvatarId().notNull()) +        { +            LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +        } + +        LLPanelProfileTab::setAvatarId(avatar_id); + +        if (LLAvatarActions::isFriend(getAvatarId())) +        { +            LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); +        } +    } +} + +bool LLPanelProfileSecondLife::isGrantedToSeeOnlineStatus() +{ +    // set text box visible to show online status for non-friends who has not set in Preferences +    // "Only Friends & Groups can see when I am online" +    if (!LLAvatarActions::isFriend(getAvatarId())) +    { +        return true; +    } + +    // *NOTE: GRANT_ONLINE_STATUS is always set to false while changing any other status. +    // When avatar disallow me to see her online status processOfflineNotification Message is received by the viewer +    // see comments for ChangeUserRights template message. EXT-453. +    // If GRANT_ONLINE_STATUS flag is changed it will be applied when viewer restarts. EXT-3880 +    const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); +} + +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 +void LLPanelProfileSecondLife::updateOnlineStatus() +{ +    if (!LLAvatarActions::isFriend(getAvatarId())) return; +    // For friend let check if he allowed me to see his status +    const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    bool online = relationship->isOnline(); +    processOnlineStatus(online); +} -	return LLPanel::notifyParent(info); +void LLPanelProfileSecondLife::processOnlineStatus(bool online) +{ +    mStatusText->setVisible(isGrantedToSeeOnlineStatus()); + +    std::string status = getString(online ? "status_online" : "status_offline"); + +    mStatusText->setValue(status); +    mStatusText->setColor(online ? +    LLUIColorTable::instance().getColor("StatusUserOnline") : +    LLUIColorTable::instance().getColor("StatusUserOffline"));  } + +void LLPanelProfileSecondLife::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mShowInSearchCheckbox->setVisible(TRUE); +        mShowInSearchCheckbox->setEnabled(TRUE); +        mDescriptionEdit->setEnabled(TRUE); +        mSecondLifePic->setEnabled(TRUE); +    } + +    if (!getSelfProfile()) +    { +        LLUUID av_id = getAvatarId(); +        bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); + +        if (LLAvatarActions::isFriend(av_id)) +        { +            mTeleportButton->setEnabled(is_buddy_online); +            //Disable "Add Friend" button for friends. +            mAddFriendButton->setEnabled(false); +        } +        else +        { +            mTeleportButton->setEnabled(true); +            mAddFriendButton->setEnabled(true); +        } + +        bool enable_map_btn = (is_buddy_online && is_agent_mappable(av_id)) || gAgent.isGodlike(); +        mShowOnMapButton->setEnabled(enable_map_btn); + +        bool enable_block_btn = LLAvatarActions::canBlock(av_id) && !LLAvatarActions::isBlocked(av_id); +        mBlockButton->setVisible(enable_block_btn); + +        bool enable_unblock_btn = LLAvatarActions::isBlocked(av_id); +        mUnblockButton->setVisible(enable_unblock_btn); +    } +} + +void LLPanelProfileSecondLife::onClickSetName() +{ +    LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2)); + +    LLFirstUse::setDisplayName(false); +} + +void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    if (av_name.getDisplayName().empty()) +    { +        // something is wrong, tell user to try again later +        LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +        return; +    } + +    LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " +        << LLDate(av_name.mNextUpdate) << LL_ENDL; +    F64 now_secs = LLDate::now().secondsSinceEpoch(); + +    if (now_secs < av_name.mNextUpdate) +    { +        // if the update time is more than a year in the future, it means updates have been blocked +        // show a more general message +        static const S32 YEAR = 60*60*24*365; +        if (now_secs + YEAR < av_name.mNextUpdate) +        { +            LLNotificationsUtil::add("SetDisplayNameBlocked"); +            return; +        } +    } + +    LLFloaterReg::showInstance("display_name"); +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileWeb + +LLPanelProfileWeb::LLPanelProfileWeb() + : LLPanelProfileTab() + , mWebBrowser(NULL) + , mAvatarNameCacheConnection() +{ +} + +LLPanelProfileWeb::~LLPanelProfileWeb() +{ +    if (mAvatarNameCacheConnection.connected()) +    { +        mAvatarNameCacheConnection.disconnect(); +    } +} + +void LLPanelProfileWeb::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLPanelProfileWeb::postBuild() +{ +    mUrlEdit = getChild<LLLineEditor>("url_edit"); +    mLoadButton = getChild<LLUICtrl>("load"); +    mWebProfileButton = getChild<LLButton>("web_profile_popout_btn"); + +    mLoadButton->setCommitCallback(boost::bind(&LLPanelProfileWeb::onCommitLoad, this, _1)); +    mWebProfileButton->setCommitCallback(boost::bind(&LLPanelProfileWeb::onCommitWebProfile, this)); + +    mWebBrowser = getChild<LLMediaCtrl>("profile_html"); +    mWebBrowser->addObserver(this); +    mWebBrowser->setHomePageUrl("about:blank"); + +    mUrlEdit->setEnabled(FALSE); + +    return TRUE; +} + +void LLPanelProfileWeb::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PROPERTIES == type) +    { +        const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data); +        if (avatar_data && getAvatarId() == avatar_data->avatar_id) +        { +            mURLHome = avatar_data->profile_url; +            mUrlEdit->setValue(mURLHome); +            mLoadButton->setEnabled(mURLHome.length() > 0); +            updateButtons(); +        } +    } +} + +void LLPanelProfileWeb::resetData() +{ +    mURLHome = LLStringUtil::null; +    mUrlEdit->setValue(mURLHome); +    mWebBrowser->navigateHome(); +} + +void LLPanelProfileWeb::apply(LLAvatarData* data) +{ +    data->profile_url = mUrlEdit->getValue().asString(); +} + +void LLPanelProfileWeb::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull()) +    { +        setIsLoading(); + +        if (!mURLWebProfile.empty()) +        { +            mWebBrowser->setVisible(TRUE); +            mPerformanceTimer.start(); +            mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); +        } +    } +} + +void LLPanelProfileWeb::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mAvatarNameCacheConnection.disconnect(); + +    std::string username = av_name.getAccountName(); +    if (username.empty()) +    { +        username = LLCacheName::buildUsername(av_name.getDisplayName()); +    } +    else +    { +        LLStringUtil::replaceChar(username, ' ', '.'); +    } + +    mURLWebProfile = getProfileURL(username); +    if (mURLWebProfile.empty()) +    { +        return; +    } + +    //if the tab was opened before name was resolved, load the panel now +    if (getIsLoading()) +    { +        updateData(); +    } +} + +void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) +{ +    if (!mURLHome.empty()) +    { +        LLSD::String valstr = ctrl->getValue().asString(); +        if (valstr.empty()) +        { +            mWebBrowser->setVisible(TRUE); +            mPerformanceTimer.start(); +            mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); +        } +        else if (valstr == "popout") +        { +            // open in viewer's browser, new window +            LLWeb::loadURLInternal(mURLHome); +        } +        else if (valstr == "external") +        { +            // open in external browser +            LLWeb::loadURLExternal(mURLHome); +        } +    } +} + +void LLPanelProfileWeb::onCommitWebProfile() +{ +    // open the web profile floater +    LLAvatarActions::showProfileWeb(getAvatarId()); +} + +void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ +    switch(event) +    { +        case MEDIA_EVENT_STATUS_TEXT_CHANGED: +            childSetValue("status_text", LLSD( self->getStatusText() ) ); +        break; + +        case MEDIA_EVENT_LOCATION_CHANGED: +            // don't set this or user will set there url to profile url +            // when clicking ok on there own profile. +            // childSetText("url_edit", self->getLocation() ); +        break; + +        case MEDIA_EVENT_NAVIGATE_BEGIN: +        { +            if (mFirstNavigate) +            { +                mFirstNavigate = false; +            } +            else +            { +                mPerformanceTimer.start(); +            } +        } +        break; + +        case MEDIA_EVENT_NAVIGATE_COMPLETE: +        { +            LLStringUtil::format_map_t args; +            args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); +            childSetValue("status_text", LLSD( getString("LoadTime", args)) ); +        } +        break; + +        default: +            // Having a default case makes the compiler happy. +        break; +    } +} + +void LLPanelProfileWeb::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mUrlEdit->setEnabled(TRUE); +    } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +static const S32 WANT_CHECKS = 8; +static const S32 SKILL_CHECKS = 6; + +LLPanelProfileInterests::LLPanelProfileInterests() + : LLPanelProfileTab() +{ +} + +LLPanelProfileInterests::~LLPanelProfileInterests() +{ +} + +void LLPanelProfileInterests::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); +} + +BOOL LLPanelProfileInterests::postBuild() +{ +    mWantToEditor = getChild<LLLineEditor>("want_to_edit"); +    mSkillsEditor = getChild<LLLineEditor>("skills_edit"); +    mLanguagesEditor = getChild<LLLineEditor>("languages_edit"); + +    for (S32 i = 0; i < WANT_CHECKS; ++i) +    { +        std::string check_name = llformat("chk%d", i); +        mWantChecks[i] = getChild<LLCheckBoxCtrl>(check_name); +    } + +    for (S32 i = 0; i < SKILL_CHECKS; ++i) +    { +        std::string check_name = llformat("schk%d", i); +        mSkillChecks[i] = getChild<LLCheckBoxCtrl>(check_name); +    } + +    return TRUE; +} + + +void LLPanelProfileInterests::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_INTERESTS_INFO == type) +    { +        const LLInterestsData* interests_data = static_cast<const LLInterestsData*>(data); +        if (interests_data && getAvatarId() == interests_data->avatar_id) +        { +            for (S32 i = 0; i < WANT_CHECKS; ++i) +            { +                if (interests_data->want_to_mask & (1<<i)) +                { +                    mWantChecks[i]->setValue(TRUE); +                } +                else +                { +                    mWantChecks[i]->setValue(FALSE); +                } +            } + +            for (S32 i = 0; i < SKILL_CHECKS; ++i) +            { +                if (interests_data->skills_mask & (1<<i)) +                { +                    mSkillChecks[i]->setValue(TRUE); +                } +                else +                { +                    mSkillChecks[i]->setValue(FALSE); +                } +            } + +            mWantToEditor->setText(interests_data->want_to_text); +            mSkillsEditor->setText(interests_data->skills_text); +            mLanguagesEditor->setText(interests_data->languages_text); + +            updateButtons(); +        } +    } +} + +void LLPanelProfileInterests::resetData() +{ +    mWantToEditor->setValue(LLStringUtil::null); +    mSkillsEditor->setValue(LLStringUtil::null); +    mLanguagesEditor->setValue(LLStringUtil::null); + +    for (S32 i = 0; i < WANT_CHECKS; ++i) +    { +        mWantChecks[i]->setValue(FALSE); +    } + +    for (S32 i = 0; i < SKILL_CHECKS; ++i) +    { +        mSkillChecks[i]->setValue(FALSE); +    } +} + +void LLPanelProfileInterests::apply() +{ +    if (getIsLoaded() && getSelfProfile()) +    { +        LLInterestsData interests_data = LLInterestsData(); + +        interests_data.want_to_mask = 0; +        for (S32 i = 0; i < WANT_CHECKS; ++i) +        { +            if (mWantChecks[i]->getValue().asBoolean()) +            { +                interests_data.want_to_mask |= (1 << i); +            } +        } + +        interests_data.skills_mask = 0; +        for (S32 i = 0; i < SKILL_CHECKS; ++i) +        { +            if (mSkillChecks[i]->getValue().asBoolean()) +            { +                interests_data.skills_mask |= (1 << i); +            } +        } + +        interests_data.want_to_text = mWantToEditor->getText(); +        interests_data.skills_text = mSkillsEditor->getText(); +        interests_data.languages_text = mLanguagesEditor->getText(); + +        LLAvatarPropertiesProcessor::getInstance()->sendInterestsInfoUpdate(&interests_data); +    } + +} + +void LLPanelProfileInterests::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mWantToEditor->setEnabled(TRUE); +        mSkillsEditor->setEnabled(TRUE); +        mLanguagesEditor->setEnabled(TRUE); + +        for (S32 i = 0; i < WANT_CHECKS; ++i) +        { +            mWantChecks[i]->setEnabled(TRUE); +        } + +        for (S32 i = 0; i < SKILL_CHECKS; ++i) +        { +            mSkillChecks[i]->setEnabled(TRUE); +        } +    } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileFirstLife::LLPanelProfileFirstLife() + : LLPanelProfileTab(), + mIsEditing(false) +{ +} + +LLPanelProfileFirstLife::~LLPanelProfileFirstLife() +{ +} + +BOOL LLPanelProfileFirstLife::postBuild() +{ +    mDescriptionEdit = getChild<LLTextEditor>("fl_description_edit"); +    mPicture = getChild<LLTextureCtrl>("real_world_pic"); + +    mDescriptionEdit->setFocusReceivedCallback(boost::bind(&LLPanelProfileFirstLife::onDescriptionFocusReceived, this)); + +    return TRUE; +} + +void LLPanelProfileFirstLife::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); +} + + +void LLPanelProfileFirstLife::onDescriptionFocusReceived() +{ +    if (!mIsEditing && getSelfProfile()) +    { +        mIsEditing = true; +        mDescriptionEdit->setParseHTML(false); +        mDescriptionEdit->setText(mCurrentDescription); +    } +} + +void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PROPERTIES == type) +    { +        const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data); +        if (avatar_data && getAvatarId() == avatar_data->avatar_id) +        { +            mCurrentDescription = avatar_data->fl_about_text; +            mDescriptionEdit->setValue(mCurrentDescription); +            mPicture->setValue(avatar_data->fl_image_id); +            updateButtons(); +        } +    } +} + +void LLPanelProfileFirstLife::resetData() +{ +    mDescriptionEdit->setValue(LLStringUtil::null); +    mPicture->setValue(mPicture->getDefaultImageAssetID()); +} + +void LLPanelProfileFirstLife::apply(LLAvatarData* data) +{ +    data->fl_image_id = mPicture->getImageAssetID(); +    data->fl_about_text = mDescriptionEdit->getValue().asString(); +} + +void LLPanelProfileFirstLife::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mDescriptionEdit->setEnabled(TRUE); +        mPicture->setEnabled(TRUE); +    } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileNotes::LLPanelProfileNotes() +: LLPanelProfileTab() +{ + +} + +void LLPanelProfileNotes::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull()) +    { +        setIsLoading(); +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarNotesRequest(avatar_id); +    } +} + +BOOL LLPanelProfileNotes::postBuild() +{ +    mOnlineStatus = getChild<LLCheckBoxCtrl>("status_check"); +    mMapRights = getChild<LLCheckBoxCtrl>("map_check"); +    mEditObjectRights = getChild<LLCheckBoxCtrl>("objects_check"); +    mNotesEditor = getChild<LLTextEditor>("notes_edit"); + +    mOnlineStatus->setCommitCallback(boost::bind(&LLPanelProfileNotes::onCommitRights, this)); +    mMapRights->setCommitCallback(boost::bind(&LLPanelProfileNotes::onCommitRights, this)); +    mEditObjectRights->setCommitCallback(boost::bind(&LLPanelProfileNotes::onCommitRights, this)); + +    mNotesEditor->setCommitCallback(boost::bind(&LLPanelProfileNotes::onCommitNotes,this)); +    mNotesEditor->setCommitOnFocusLost(TRUE); + +    return TRUE; +} + +void LLPanelProfileNotes::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    fillRightsData(); +} + +void LLPanelProfileNotes::apply() +{ +    onCommitNotes(); +} + +void LLPanelProfileNotes::fillRightsData() +{ +    mOnlineStatus->setValue(FALSE); +    mMapRights->setValue(FALSE); +    mEditObjectRights->setValue(FALSE); + +    const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    // If true - we are viewing friend's profile, enable check boxes and set values. +    if(relation) +    { +        S32 rights = relation->getRightsGrantedTo(); + +        mOnlineStatus->setValue(LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE); +        mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); +        mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); +    } + +    enableCheckboxes(NULL != relation); +} + +void LLPanelProfileNotes::onCommitNotes() +{ +    if (getIsLoaded()) +    { +        std::string notes = mNotesEditor->getValue().asString(); +        LLAvatarPropertiesProcessor::getInstance()->sendNotes(getAvatarId(),notes); +    } +} + +void LLPanelProfileNotes::rightsConfirmationCallback(const LLSD& notification, +        const LLSD& response, S32 rights) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +    if (option == 0) +    { +        LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(getAvatarId(), rights); +    } +    else +    { +        mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? FALSE : TRUE); +    } +} + +void LLPanelProfileNotes::confirmModifyRights(bool grant, S32 rights) +{ +    LLSD args; +    args["NAME"] = LLSLURL("agent", getAvatarId(), "completename").getSLURLString(); + +    if (grant) +    { +        LLNotificationsUtil::add("GrantModifyRights", args, LLSD(), +                boost::bind(&LLPanelProfileNotes::rightsConfirmationCallback, this, +                        _1, _2, rights)); +    } +    else +    { +        LLNotificationsUtil::add("RevokeModifyRights", args, LLSD(), +                boost::bind(&LLPanelProfileNotes::rightsConfirmationCallback, this, +                        _1, _2, rights)); +    } +} + +void LLPanelProfileNotes::onCommitRights() +{ +    const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + +    if (!buddy_relationship) +    { +        // Lets have a warning log message instead of having a crash. EXT-4947. +        LL_WARNS("LegacyProfile") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; +        return; +    } + +    S32 rights = 0; + +    if (mOnlineStatus->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_ONLINE_STATUS; +    } +    if (mMapRights->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_MAP_LOCATION; +    } +    if (mEditObjectRights->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_MODIFY_OBJECTS; +    } + +    bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); + +    // if modify objects checkbox clicked +    if (buddy_relationship->isRightGrantedTo( +            LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) +    { +        confirmModifyRights(allow_modify_objects, rights); +    } +    // only one checkbox can trigger commit, so store the rest of rights +    else +    { +        LLAvatarPropertiesProcessor::getInstance()->sendFriendRights( +                        getAvatarId(), rights); +    } +} + +void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_NOTES == type) +    { +        LLAvatarNotes* avatar_notes = static_cast<LLAvatarNotes*>(data); +        if (avatar_notes && getAvatarId() == avatar_notes->target_id) +        { +            mNotesEditor->setValue(avatar_notes->notes); +            mNotesEditor->setEnabled(TRUE); +            updateButtons(); + +            LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); +        } +    } +} + +void LLPanelProfileNotes::resetData() +{ +    resetLoading(); +    mNotesEditor->setValue(LLStringUtil::null); +    mOnlineStatus->setValue(FALSE); +    mMapRights->setValue(FALSE); +    mEditObjectRights->setValue(FALSE); +} + +void LLPanelProfileNotes::enableCheckboxes(bool enable) +{ +    mOnlineStatus->setEnabled(enable); +    mMapRights->setEnabled(enable); +    mEditObjectRights->setEnabled(enable); +} + +LLPanelProfileNotes::~LLPanelProfileNotes() +{ +    if (getAvatarId().notNull()) +    { +        LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +    } +} + +// virtual, called by LLAvatarTracker +void LLPanelProfileNotes::changed(U32 mask) +{ +    // update rights to avoid have checkboxes enabled when friendship is terminated. EXT-4947. +    fillRightsData(); +} + +void LLPanelProfileNotes::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.notNull()) +    { +        if (getAvatarId().notNull()) +        { +            LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +        } +        LLPanelProfileTab::setAvatarId(avatar_id); +        LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); +    } +} + + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfile + +LLPanelProfile::LLPanelProfile() + : LLPanelProfileTab() +{ +} + +LLPanelProfile::~LLPanelProfile() +{ +} + +BOOL LLPanelProfile::postBuild() +{ +    return TRUE; +} + +void LLPanelProfile::processProperties(void* data, EAvatarProcessorType type) +{ +    //*TODO: figure out what this does +    mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); + +    // Load data on currently opened tab as well +    onTabChange(); +} + +void LLPanelProfile::onTabChange() +{ +    LLPanelProfileTab* active_panel = dynamic_cast<LLPanelProfileTab*>(mTabContainer->getCurrentPanel()); +    if (active_panel) +    { +        active_panel->updateData(); +    } +} + +void LLPanelProfile::onOpen(const LLSD& key) +{ +    LLUUID avatar_id = key["id"].asUUID(); + +    // Don't reload the same profile +    if (getAvatarId() == avatar_id) +    { +        return; +    } + +    LLPanelProfileTab::onOpen(avatar_id); + +    mTabContainer       = getChild<LLTabContainer>("panel_profile_tabs"); +    mPanelSecondlife    = findChild<LLPanelProfileSecondLife>(PANEL_SECONDLIFE); +    mPanelWeb           = findChild<LLPanelProfileWeb>(PANEL_WEB); +    mPanelInterests     = findChild<LLPanelProfileInterests>(PANEL_INTERESTS); +    mPanelPicks         = findChild<LLPanelProfilePicks>(PANEL_PICKS); +    mPanelClassifieds   = findChild<LLPanelProfileClassifieds>(PANEL_CLASSIFIEDS); +    mPanelFirstlife     = findChild<LLPanelProfileFirstLife>(PANEL_FIRSTLIFE); +    mPanelNotes         = findChild<LLPanelProfileNotes>(PANEL_NOTES); + +    mPanelSecondlife->onOpen(avatar_id); +    mPanelWeb->onOpen(avatar_id); +    mPanelInterests->onOpen(avatar_id); +    mPanelPicks->onOpen(avatar_id); +    mPanelClassifieds->onOpen(avatar_id); +    mPanelFirstlife->onOpen(avatar_id); +    mPanelNotes->onOpen(avatar_id); + +    mPanelSecondlife->setEmbedded(getEmbedded()); +    mPanelWeb->setEmbedded(getEmbedded()); +    mPanelInterests->setEmbedded(getEmbedded()); +    mPanelPicks->setEmbedded(getEmbedded()); +    mPanelClassifieds->setEmbedded(getEmbedded()); +    mPanelFirstlife->setEmbedded(getEmbedded()); +    mPanelNotes->setEmbedded(getEmbedded()); + +    // Always request the base profile info +    resetLoading(); +    updateData(); + +    // Only show commit buttons on own profile on floater version +    if (getSelfProfile() && !getEmbedded()) +    { +        getChild<LLUICtrl>("ok_btn")->setVisible(TRUE); +        getChild<LLUICtrl>("cancel_btn")->setVisible(TRUE); +    } + +    // KC - Not handling pick and classified opening thru onOpen +    // because this would make unique profile floaters per slurl +    // and result in multiple profile floaters for the same avatar +} + +void LLPanelProfile::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull()) +    { +        setIsLoading(); +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(avatar_id); +    } +} + +void LLPanelProfile::apply() +{ +    if (getSelfProfile()) +    { +        //KC - AvatarData is spread over 3 different panels +        // collect data from the last 2 and give to the first to save +        LLAvatarData data = LLAvatarData(); +        data.avatar_id = gAgentID; +        mPanelFirstlife->apply(&data); +        mPanelWeb->apply(&data); +        mPanelSecondlife->apply(&data); + +        mPanelInterests->apply(); +        mPanelPicks->apply(); +        mPanelNotes->apply(); + +        //KC - Classifieds handles this itself +    } +} + +void LLPanelProfile::showPick(const LLUUID& pick_id) +{ +    if (pick_id.notNull()) +    { +        mPanelPicks->selectPick(pick_id); +    } +    mTabContainer->selectTabPanel(mPanelPicks); +} + +void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) +{ +    if (classified_id.notNull()) +    { +        mPanelClassifieds->selectClassified(classified_id, edit); +    } +    mTabContainer->selectTabPanel(mPanelClassifieds); +} + + + diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index d97f60ed22..72f913b522 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -1,25 +1,25 @@ -/**  +/**  * @file llpanelprofile.h  * @brief Profile panel  *  * $LicenseInfo:firstyear=2009&license=viewerlgpl$  * Second Life Viewer Source Code  * Copyright (C) 2010, 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$  */ @@ -27,76 +27,386 @@  #ifndef LL_LLPANELPROFILE_H  #define LL_LLPANELPROFILE_H +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" +#include "llfloater.h"  #include "llpanel.h"  #include "llpanelavatar.h" +#include "llmediactrl.h" +#include "llvoiceclient.h" + +// class LLPanelProfileClassifieds; +// class LLTabContainer; +// class LLPanelProfileSecondLife; +// class LLPanelProfileWeb; +// class LLPanelProfileInterests; +// class LLPanelProfilePicks; +// class LLPanelProfileFirstLife; +// class LLPanelProfileNotes; + +class LLAvatarName; +class LLCheckBoxCtrl;  class LLTabContainer; +class LLTextBox; +class LLTextureCtrl; +class LLMediaCtrl; +class LLGroupList; +class LLTextBase; +class LLMenuButton; +class LLLineEditor; +class LLTextEditor; +class LLPanelProfileClassifieds; +class LLPanelProfilePicks; + + +/** +* Panel for displaying Avatar's second life related info. +*/ +class LLPanelProfileSecondLife +	: public LLPanelProfileTab +	, public LLFriendObserver +	, public LLVoiceClientStatusObserver +{ +public: +	LLPanelProfileSecondLife(); +	/*virtual*/ ~LLPanelProfileSecondLife(); + +	/*virtual*/ void onOpen(const LLSD& key); + +	/** +	 * Saves changes. +	 */ +	void apply(LLAvatarData* data); + +	/** +	 * LLFriendObserver trigger +	 */ +	virtual void changed(U32 mask); + +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + +	/*virtual*/ void setAvatarId(const LLUUID& avatar_id); + +	/*virtual*/ BOOL postBuild(); + +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +	void resetData(); + +	/** +	 * Sends update data request to server. +	 */ +	/*virtual*/ void updateData(); + +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +protected: +	/** +	 * Process profile related data received from server. +	 */ +	virtual void processProfileProperties(const LLAvatarData* avatar_data); + +	/** +	 * Processes group related data received from server. +	 */ +	virtual void processGroupProperties(const LLAvatarGroups* avatar_groups); + +	/** +	 * Fills common for Avatar profile and My Profile fields. +	 */ +	virtual void fillCommonData(const LLAvatarData* avatar_data); + +	/** +	 * Fills partner data. +	 */ +	virtual void fillPartnerData(const LLAvatarData* avatar_data); + +	/** +	 * Fills account status. +	 */ +	virtual void fillAccountStatus(const LLAvatarData* avatar_data); + +	void onMapButtonClick(); + +	/** +	 * Opens "Pay Resident" dialog. +	 */ +	void pay(); + +	/** +	 * Add/remove resident to/from your block list. +	 */ +	void toggleBlock(); + +	void onAddFriendButtonClick(); +	void onIMButtonClick(); +	void onTeleportButtonClick(); + +	void onGroupInvite(); + +	bool isGrantedToSeeOnlineStatus(); + +	/** +	 * Displays avatar's online status if possible. +	 * +	 * Requirements from EXT-3880: +	 * For friends: +	 * - Online when online and privacy settings allow to show +	 * - Offline when offline and privacy settings allow to show +	 * - Else: nothing +	 * For other avatars: +	 *	- Online when online and was not set in Preferences/"Only Friends & Groups can see when I am online" +	 *	- Else: Offline +	 */ +	void updateOnlineStatus(); +	void processOnlineStatus(bool online); + +private: +    /*virtual*/ void updateButtons(); +	void onClickSetName(); +	void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name); + +private: +	typedef std::map<std::string, LLUUID> group_map_t; +	group_map_t				mGroups; +	void					openGroupProfile(); + +	LLTextBox*			mStatusText; +	LLGroupList*		mGroupList; +	LLCheckBoxCtrl*		mShowInSearchCheckbox; +	LLTextureCtrl*		mSecondLifePic; +	LLTextBase*			mDescriptionEdit; +	LLButton*			mTeleportButton; +	LLButton*			mShowOnMapButton; +	LLButton*			mBlockButton; +	LLButton*			mUnblockButton; +    LLUICtrl*           mNameLabel; +	LLButton*			mDisplayNameButton; +	LLButton*			mAddFriendButton; +	LLButton*			mGroupInviteButton; +	LLButton*			mPayButton; +	LLButton*			mIMButton; + +	bool				mVoiceStatus; + +	boost::signals2::connection	mAvatarNameCacheConnection; +}; + + +/** +* Panel for displaying Avatar's web profile and home page. +*/ +class LLPanelProfileWeb +	: public LLPanelProfileTab +	, public LLViewerMediaObserver +{ +public: +	LLPanelProfileWeb(); +	/*virtual*/ ~LLPanelProfileWeb(); + +	/*virtual*/ void onOpen(const LLSD& key); + +	/*virtual*/ BOOL postBuild(); + +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +	void resetData(); -std::string getProfileURL(const std::string& agent_name); +	/** +	 * Saves changes. +	 */ +	void apply(LLAvatarData* data); + +	/** +	 * Loads web profile. +	 */ +	/*virtual*/ void updateData(); + +	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +protected: +	/*virtual*/ void updateButtons(); +	void onCommitLoad(LLUICtrl* ctrl); +	void onCommitWebProfile(); + +private: +	std::string			mURLHome; +	std::string			mURLWebProfile; +	LLMediaCtrl*		mWebBrowser; +	LLButton*			mWebProfileButton; +	LLUICtrl*			mLoadButton; +	LLLineEditor*		mUrlEdit; + +	LLFrameTimer		mPerformanceTimer; +	bool				mFirstNavigate; + +	boost::signals2::connection	mAvatarNameCacheConnection; +};  /** -* Base class for Profile View and My Profile. +* Panel for displaying Avatar's interests.  */ -class LLPanelProfile : public LLPanel +class LLPanelProfileInterests +	: public LLPanelProfileTab  { -	LOG_CLASS(LLPanelProfile); +public: +	LLPanelProfileInterests(); +	/*virtual*/ ~LLPanelProfileInterests(); + +	/*virtual*/ void onOpen(const LLSD& key); + +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +	void resetData(); + +	/** +	 * Saves changes. +	 */ +	virtual void apply(); + +protected: +	/*virtual*/ void updateButtons(); + +private: +	LLCheckBoxCtrl*	mWantChecks[8]; +	LLCheckBoxCtrl*	mSkillChecks[6]; +	LLLineEditor*	mWantToEditor; +	LLLineEditor*	mSkillsEditor; +	LLLineEditor*	mLanguagesEditor; +}; + + +/** +* Panel for displaying Avatar's first life related info. +*/ +class LLPanelProfileFirstLife +	: public LLPanelProfileTab +{  public: +	LLPanelProfileFirstLife(); +	/*virtual*/ ~LLPanelProfileFirstLife(); + +	/*virtual*/ void onOpen(const LLSD& key); +  	/*virtual*/ BOOL postBuild(); -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +	void resetData(); + +	/** +	 * Saves changes. +	 */ +	void apply(LLAvatarData* data); + +protected: +	/*virtual*/ void updateButtons(); +	void onDescriptionFocusReceived(); + +	LLTextEditor*	mDescriptionEdit; +    LLTextureCtrl*  mPicture; + +	bool			mIsEditing; +	std::string		mCurrentDescription; +}; + +/** + * Panel for displaying Avatar's notes and modifying friend's rights. + */ +class LLPanelProfileNotes +	: public LLPanelProfileTab +	, public LLFriendObserver +{ +public: +	LLPanelProfileNotes(); +	/*virtual*/ ~LLPanelProfileNotes(); + +	virtual void setAvatarId(const LLUUID& avatar_id); + +	/** +	 * LLFriendObserver trigger +	 */ +	virtual void changed(U32 mask); +  	/*virtual*/ void onOpen(const LLSD& key); -	virtual void openPanel(LLPanel* panel, const LLSD& params); +	/*virtual*/ BOOL postBuild(); + +	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +	void resetData(); -	virtual void closePanel(LLPanel* panel); +	/*virtual*/ void updateData(); -	S32 notifyParent(const LLSD& info); +	/** +	 * Saves changes. +	 */ +	virtual void apply();  protected: +	/** +	 * Fills rights data for friends. +	 */ +	void fillRightsData(); + +	void rightsConfirmationCallback(const LLSD& notification, const LLSD& response, S32 rights); +	void confirmModifyRights(bool grant, S32 rights); +	void onCommitRights(); +	void onCommitNotes(); +	void enableCheckboxes(bool enable); + +    LLCheckBoxCtrl*     mOnlineStatus; +	LLCheckBoxCtrl*     mMapRights; +	LLCheckBoxCtrl*     mEditObjectRights; +	LLTextEditor*       mNotesEditor; +}; + + +/** +* Container panel for the profile tabs +*/ +class LLPanelProfile +    : public LLPanelProfileTab +{ +public: +    LLPanelProfile(); +    /*virtual*/ ~LLPanelProfile(); + +    /*virtual*/ BOOL postBuild(); -	LLPanelProfile(); +    /*virtual*/ void updateData(); -	virtual void onTabSelected(const LLSD& param); +    /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); -	const LLUUID& getAvatarId() { return mAvatarId; } +    /*virtual*/ void onOpen(const LLSD& key); -	void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } +    /** +     * Saves changes. +     */ +    void apply(); -	typedef std::map<std::string, LLPanelProfileTab*> profile_tabs_t; +    void showPick(const LLUUID& pick_id = LLUUID::null); -	profile_tabs_t& getTabContainer() { return mTabContainer; } +    void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false);  private: +    void onTabChange(); -	//-- ChildStack begins ---------------------------------------------------- -	class ChildStack -	{ -		LOG_CLASS(LLPanelProfile::ChildStack); -	public: -		ChildStack(); -		~ChildStack(); -		void setParent(LLPanel* parent); - -		bool push(); -		bool pop(); -		void preParentReshape(); -		void postParentReshape(); - -	private: -		void dump(); - -		typedef LLView::child_list_t view_list_t; -		typedef std::list<view_list_t> stack_t; - -		stack_t		mStack; -		stack_t		mSavedStack; -		LLPanel*	mParent; -	}; -	//-- ChildStack ends ------------------------------------------------------ - -	profile_tabs_t mTabContainer; -	ChildStack		mChildStack; -	LLUUID mAvatarId; +    LLPanelProfileSecondLife*   mPanelSecondlife; +    LLPanelProfileWeb*          mPanelWeb; +    LLPanelProfileInterests*    mPanelInterests; +    LLPanelProfilePicks*        mPanelPicks; +    LLPanelProfileClassifieds*  mPanelClassifieds; +    LLPanelProfileFirstLife*    mPanelFirstlife; +    LLPanelProfileNotes*         mPanelNotes; +    LLTabContainer*             mTabContainer;  };  #endif //LL_LLPANELPROFILE_H diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp new file mode 100644 index 0000000000..49f347dbda --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -0,0 +1,1331 @@ +/** + * @file llpanelprofileclassifieds.cpp + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llpanelprofileclassifieds.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedflags.h" +#include "llcombobox.h" +#include "llcommandhandler.h" // for classified HTML detail page click tracking +#include "llcorehttputil.h" +#include "lldispatcher.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "lliconctrl.h" +#include "lllineeditor.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llparcel.h" +#include "llregistry.h" +#include "llscrollcontainer.h" +#include "llstatusbar.h" +#include "lltabcontainer.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewertexture.h" +#include "llviewertexture.h" + + +//*TODO: verify this limit +const S32 MAX_AVATAR_CLASSIFIEDS = 100; + +const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ + +//static +LLPanelProfileClassified::panel_list_t LLPanelProfileClassified::sAllPanels; + +static LLPanelInjector<LLPanelProfileClassifieds> t_panel_profile_classifieds("panel_profile_classifieds"); +static LLPanelInjector<LLPanelProfileClassified> t_panel_profile_classified("panel_profile_classified"); + +class LLClassifiedHandler : public LLCommandHandler +{ +public: +    // throttle calls from untrusted browsers +    LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} + +    bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +    { +        if (!LLUI::sSettingGroups["config"]->getBOOL("EnableClassifieds")) +        { +            LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); +            return true; +        } + +        // handle app/classified/create urls first +        if (params.size() == 1 && params[0].asString() == "create") +        { +            LLAvatarActions::showClassifieds(gAgent.getID()); +            return true; +        } + +        // then handle the general app/classified/{UUID}/{CMD} urls +        if (params.size() < 2) +        { +            return false; +        } + +        // get the ID for the classified +        LLUUID classified_id; +        if (!classified_id.set(params[0], FALSE)) +        { +            return false; +        } + +        // show the classified in the side tray. +        // need to ask the server for more info first though... +        const std::string verb = params[1].asString(); +        if (verb == "about") +        { +            LLAvatarActions::showClassified(gAgent.getID(), classified_id, false); +            return true; +        } +        else if (verb == "edit") +        { +            LLAvatarActions::showClassified(gAgent.getID(), classified_id, true); +            return true; +        } + +        return false; +    } +}; +LLClassifiedHandler gClassifiedHandler; + +////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassifieds +//----------------------------------------------------------------------------- + +LLPanelProfileClassifieds::LLPanelProfileClassifieds() + : LLPanelProfileTab() + , mClassifiedToSelectOnLoad(LLUUID::null) + , mClassifiedEditOnLoad(false) +{ +} + +LLPanelProfileClassifieds::~LLPanelProfileClassifieds() +{ +} + +void LLPanelProfileClassifieds::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mNewButton->setVisible(TRUE); +        mNewButton->setEnabled(FALSE); + +        mDeleteButton->setVisible(TRUE); +        mDeleteButton->setEnabled(FALSE); +    } +} + +void LLPanelProfileClassifieds::selectClassified(const LLUUID& classified_id, bool edit) +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (classified_panel) +            { +                if (classified_panel->getClassifiedId() == classified_id) +                { +                    mTabContainer->selectTabPanel(classified_panel); +                    if (edit) +                    { +                        classified_panel->setEditMode(TRUE); +                    } +                    break; +                } +            } +        } +    } +    else +    { +        mClassifiedToSelectOnLoad = classified_id; +        mClassifiedEditOnLoad = edit; +    } +} + +BOOL LLPanelProfileClassifieds::postBuild() +{ +    mTabContainer = getChild<LLTabContainer>("tab_classifieds"); +    mNoItemsLabel = getChild<LLUICtrl>("classifieds_panel_text"); +    mNewButton = getChild<LLButton>("new_btn"); +    mDeleteButton = getChild<LLButton>("delete_btn"); + +    mNewButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickNewBtn, this)); +    mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickDelete, this)); + +    return TRUE; +} + +void LLPanelProfileClassifieds::onClickNewBtn() +{ +    mNoItemsLabel->setVisible(FALSE); +    LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); +    classified_panel->onOpen(LLSD()); +    mTabContainer->addTabPanel( +        LLTabContainer::TabPanelParams(). +        panel(classified_panel). +        select_tab(true). +        label(classified_panel->getClassifiedName())); +    updateButtons(); +} + +void LLPanelProfileClassifieds::onClickDelete() +{ +    LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getCurrentPanel()); +    if (classified_panel) +    { +        LLUUID classified_id = classified_panel->getClassifiedId(); +        LLSD args; +        args["PICK"] = classified_panel->getClassifiedName(); +        LLSD payload; +        payload["classified_id"] = classified_id; +        payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); +        LLNotificationsUtil::add("DeleteAvatarPick", args, payload, +            boost::bind(&LLPanelProfileClassifieds::callbackDeleteClassified, this, _1, _2)); +    } +} + +void LLPanelProfileClassifieds::callbackDeleteClassified(const LLSD& notification, const LLSD& response) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + +    if (0 == option) +    { +        LLUUID classified_id = notification["payload"]["classified_id"].asUUID(); +        S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + +        LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (classified_panel && classified_panel->getClassifiedId() == classified_id) +        { +            mTabContainer->removeTabPanel(classified_panel); +        } + +        if (classified_id.notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->sendClassifiedDelete(classified_id); +        } + +        updateButtons(); +    } +} + +void LLPanelProfileClassifieds::processProperties(void* data, EAvatarProcessorType type) +{ +    if ((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) +    { +        LLUUID avatar_id = getAvatarId(); + +        LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); +        if (c_info && getAvatarId() == c_info->target_id) +        { +            // do not clear classified list in case we will receive two or more data packets. +            // list has been cleared in updateData(). (fix for EXT-6436) +            LLUUID selected_id = mClassifiedToSelectOnLoad; + +            LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); +            for (; c_info->classifieds_list.end() != it; ++it) +            { +                LLAvatarClassifieds::classified_data c_data = *it; + +                LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + +                LLSD params; +                params["classified_creator_id"] = avatar_id; +                params["classified_id"] = c_data.classified_id; +                params["classified_name"] = c_data.name; +                params["from_search"] = (selected_id == c_data.classified_id); //SLURL handling and stats tracking +                params["edit"] = (selected_id == c_data.classified_id) && mClassifiedEditOnLoad; +                classified_panel->onOpen(params); + +                mTabContainer->addTabPanel( +                    LLTabContainer::TabPanelParams(). +                    panel(classified_panel). +                    select_tab(selected_id == c_data.classified_id). +                    label(c_data.name)); + +                if (selected_id == c_data.classified_id) +                { +                    mClassifiedToSelectOnLoad = LLUUID::null; +                    mClassifiedEditOnLoad = false; +                } +            } + +            BOOL no_data = !mTabContainer->getTabCount(); +            mNoItemsLabel->setVisible(no_data); +            if (no_data) +            { +                if(getSelfProfile()) +                { +                    mNoItemsLabel->setValue(LLTrans::getString("NoClassifiedsText")); +                } +                else +                { +                    mNoItemsLabel->setValue(LLTrans::getString("NoAvatarClassifiedsText")); +                } +            } +            else if (selected_id.isNull()) +            { +                mTabContainer->selectFirstTab(); +            } + +            updateButtons(); +        } +    } +} + +void LLPanelProfileClassifieds::resetData() +{ +    resetLoading(); +    mTabContainer->deleteAllTabs(); +} + +void LLPanelProfileClassifieds::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mNewButton->setEnabled(canAddNewClassified()); +        mDeleteButton->setEnabled(canDeleteClassified()); +    } +} + +void LLPanelProfileClassifieds::updateData() +{ +    // Send picks request only once +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull()) +    { +        setIsLoading(); +        mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); +        mNoItemsLabel->setVisible(TRUE); + +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(avatar_id); +    } +} + +bool LLPanelProfileClassifieds::canAddNewClassified() +{ +    return (mTabContainer->getTabCount() < MAX_AVATAR_CLASSIFIEDS); +} + +bool LLPanelProfileClassifieds::canDeleteClassified() +{ +    return (mTabContainer->getTabCount() > 0); +} + + +//----------------------------------------------------------------------------- +// LLDispatchClassifiedClickThrough +//----------------------------------------------------------------------------- + +// "classifiedclickthrough" +// strings[0] = classified_id +// strings[1] = teleport_clicks +// strings[2] = map_clicks +// strings[3] = profile_clicks +class LLDispatchClassifiedClickThrough : public LLDispatchHandler +{ +public: +    virtual bool operator()( +        const LLDispatcher* dispatcher, +        const std::string& key, +        const LLUUID& invoice, +        const sparam_t& strings) +    { +        if (strings.size() != 4) return false; +        LLUUID classified_id(strings[0]); +        S32 teleport_clicks = atoi(strings[1].c_str()); +        S32 map_clicks = atoi(strings[2].c_str()); +        S32 profile_clicks = atoi(strings[3].c_str()); + +        LLPanelProfileClassified::setClickThrough( +            classified_id, teleport_clicks, map_clicks, profile_clicks, false); + +        return true; +    } +}; +static LLDispatchClassifiedClickThrough sClassifiedClickThrough; + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassified +//----------------------------------------------------------------------------- + +static const S32 CB_ITEM_MATURE = 0; +static const S32 CB_ITEM_PG    = 1; + +LLPanelProfileClassified::LLPanelProfileClassified() + : LLPanelProfileTab() + , mInfoLoaded(false) + , mTeleportClicksOld(0) + , mMapClicksOld(0) + , mProfileClicksOld(0) + , mTeleportClicksNew(0) + , mMapClicksNew(0) + , mProfileClicksNew(0) + , mSnapshotCtrl(NULL) + , mPublishFloater(NULL) + , mIsNew(false) + , mIsNewWithErrors(false) + , mCanClose(false) + , mEditMode(false) + , mEditOnLoad(false) +{ +    sAllPanels.push_back(this); +} + +LLPanelProfileClassified::~LLPanelProfileClassified() +{ +    sAllPanels.remove(this); +    gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler +} + +//static +LLPanelProfileClassified* LLPanelProfileClassified::create() +{ +    LLPanelProfileClassified* panel = new LLPanelProfileClassified(); +    panel->buildFromFile("panel_profile_classified.xml"); +    return panel; +} + +BOOL LLPanelProfileClassified::postBuild() +{ +    mScrollContainer    = getChild<LLScrollContainer>("profile_scroll"); +    mInfoPanel          = getChild<LLPanel>("info_panel"); +    mEditPanel          = getChild<LLPanel>("edit_panel"); + +    mSnapshotCtrl       = getChild<LLTextureCtrl>("classified_snapshot"); +    mEditIcon           = getChild<LLUICtrl>("edit_icon"); + +    //info +    mClassifiedNameText = getChild<LLUICtrl>("classified_name"); +    mClassifiedDescText = getChild<LLUICtrl>("classified_desc"); +    mLocationText       = getChild<LLUICtrl>("classified_location"); +    mCategoryText       = getChild<LLUICtrl>("category"); +    mContentTypeText    = getChild<LLUICtrl>("content_type"); +    mContentTypeM       = getChild<LLIconCtrl>("content_type_moderate"); +    mContentTypeG       = getChild<LLIconCtrl>("content_type_general"); +    mPriceText          = getChild<LLUICtrl>("price_for_listing"); +    mAutoRenewText      = getChild<LLUICtrl>("auto_renew"); + +    mMapButton          = getChild<LLButton>("show_on_map_btn"); +    mTeleportButton     = getChild<LLButton>("teleport_btn"); +    mEditButton         = getChild<LLButton>("edit_btn"); + +    //edit +    mClassifiedNameEdit = getChild<LLLineEditor>("classified_name_edit"); +    mClassifiedDescEdit = getChild<LLTextEditor>("classified_desc_edit"); +    mLocationEdit       = getChild<LLUICtrl>("classified_location_edit"); +    mCategoryCombo      = getChild<LLComboBox>("category_edit"); +    mContentTypeCombo   = getChild<LLComboBox>("content_type_edit"); +    mPriceEdit          = getChild<LLUICtrl>("price_for_listing_edit"); +    mPricelabel         = getChild<LLUICtrl>("price_for_listing_edit_label"); +    mAutoRenewEdit      = getChild<LLUICtrl>("auto_renew_edit"); + +    mSaveButton         = getChild<LLButton>("save_changes_btn"); +    mSetLocationButton  = getChild<LLButton>("set_to_curr_location_btn"); +    mCancelButton       = getChild<LLButton>("cancel_btn"); + +    mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelProfileClassified::onTextureSelected, this)); +    mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseEnter, this)); +    mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseLeave, this)); +    mEditIcon->setVisible(false); + +    mMapButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onMapClick, this)); +    mTeleportButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onTeleportClick, this)); +    mEditButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onEditClick, this)); +    mSaveButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSaveClick, this)); +    mSetLocationButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSetLocationClick, this)); +    mCancelButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onCancelClick, this)); + +    LLClassifiedInfo::cat_map::iterator iter; +    for (iter = LLClassifiedInfo::sCategories.begin(); +        iter != LLClassifiedInfo::sCategories.end(); +        iter++) +    { +        mCategoryCombo->add(LLTrans::getString(iter->second)); +    } + +    mClassifiedNameEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this), NULL); +    mClassifiedDescEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mCategoryCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mContentTypeCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mPriceEdit->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mAutoRenewEdit->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + +    return TRUE; +} + +void LLPanelProfileClassified::onOpen(const LLSD& key) +{ +    mIsNew = key.isUndefined(); + +    resetData(); +    resetControls(); +    scrollToTop(); + +    // classified is not created yet +    bool is_new = isNew() || isNewWithErrors(); + +    if(is_new) +    { +        LLPanelProfileTab::setAvatarId(gAgent.getID()); + +        setPosGlobal(gAgent.getPositionGlobal()); + +        LLUUID snapshot_id = LLUUID::null; +        std::string desc; +        LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +        if(parcel) +        { +            desc = parcel->getDesc(); +            snapshot_id = parcel->getSnapshotID(); +        } + +        std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); +        LLViewerRegion* region = gAgent.getRegion(); +        if (region) +        { +            region_name = region->getName(); +        } + +        setClassifiedName(makeClassifiedName()); +        setDescription(desc); +        setSnapshotId(snapshot_id); +        setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); +        // server will set valid parcel id +        setParcelId(LLUUID::null); + +        mSaveButton->setLabelArg("[LABEL]", getString("publish_label")); + +        setEditMode(TRUE); +        enableSave(true); +        enableEditing(true); +        resetDirty(); +        setInfoLoaded(false); +    } +    else +    { +        LLUUID avatar_id = key["classified_creator_id"]; +        if(avatar_id.isNull()) +        { +            return; +        } +        LLPanelProfileTab::setAvatarId(avatar_id); + +        setClassifiedId(key["classified_id"]); +        setClassifiedName(key["classified_name"]); +        setFromSearch(key["from_search"]); +        mEditOnLoad = key["edit"]; + +        LL_INFOS() << "Opening classified [" << getClassifiedName() << "] (" << getClassifiedId() << ")" << LL_ENDL; + +        LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + +        gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); + +        if (gAgent.getRegion()) +        { +            // While we're at it let's get the stats from the new table if that +            // capability exists. +            std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); +            if (!url.empty()) +            { +                LL_INFOS() << "Classified stat request via capability" << LL_ENDL; +                LLSD body; +                LLUUID classifiedId = getClassifiedId(); +                body["classified_id"] = classifiedId; +                LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, +                    boost::bind(&LLPanelProfileClassified::handleSearchStatResponse, classifiedId, _1)); +            } +        } +        // Update classified click stats. +        // *TODO: Should we do this when opening not from search? +        if (!fromSearch() ) +        { +            sendClickMessage("profile"); +        } + +        setInfoLoaded(false); +    } + + +    mPricelabel->setVisible(is_new); +    mPriceEdit->setVisible(is_new); + +    bool is_self = getSelfProfile(); +    getChildView("auto_renew_layout_panel")->setVisible(is_self); +    getChildView("clickthrough_layout_panel")->setVisible(is_self); + +    updateButtons(); +} + +void LLPanelProfileClassified::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_CLASSIFIED_INFO != type) +    { +        return; +    } + +    LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); +    if(c_info && getClassifiedId() == c_info->classified_id) +    { +        // see LLPanelProfileClassified::sendUpdate() for notes +        mIsNewWithErrors = false; + +        setClassifiedName(c_info->name); +        setDescription(c_info->description); +        setSnapshotId(c_info->snapshot_id); +        setParcelId(c_info->parcel_id); +        setPosGlobal(c_info->pos_global); +        setSimName(c_info->sim_name); + +        setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); + +        mCategoryText->setValue(LLClassifiedInfo::sCategories[c_info->category]); +        // *HACK see LLPanelProfileClassified::sendUpdate() +        setCategory(c_info->category - 1); + +        bool mature = is_cf_mature(c_info->flags); +        setContentType(mature); + +        bool auto_renew = is_cf_auto_renew(c_info->flags); +        std::string auto_renew_str = auto_renew ? getString("auto_renew_on") : getString("auto_renew_off"); +        mAutoRenewText->setValue(auto_renew_str); +        mAutoRenewEdit->setValue(auto_renew); + +        static LLUIString  price_str = getString("l$_price"); +        price_str.setArg("[PRICE]", llformat("%d", c_info->price_for_listing)); +        mPriceText->setValue(LLSD(price_str)); +        mPriceEdit->setValue(c_info->price_for_listing); +        mPriceEdit->setEnabled(isNew()); + +        static std::string date_fmt = getString("date_fmt"); +        std::string date_str = date_fmt; +        LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date)); +        getChild<LLUICtrl>("creation_date")->setValue(date_str); + +        resetDirty(); +        setInfoLoaded(true); +        enableSave(false); +        enableEditing(true); + +        // for just created classified - in case user opened edit panel before processProperties() callback +        mSaveButton->setLabelArg("[LABEL]", getString("save_label")); + +        updateButtons(); + +        if (mEditOnLoad) +        { +            setEditMode(TRUE); +        } +    } + +} + +void LLPanelProfileClassified::setEditMode(BOOL edit_mode) +{ +    mEditMode = edit_mode; + +    mInfoPanel->setVisible(!edit_mode); +    mEditPanel->setVisible(edit_mode); + +    // snapshot control is common between info and edit, +    // enable it only when in edit mode +    mSnapshotCtrl->setEnabled(edit_mode); + +    scrollToTop(); +    updateButtons(); +} + +void LLPanelProfileClassified::updateButtons() +{ +    bool edit_mode  = getEditMode(); +    mMapButton->setVisible(!edit_mode); +    mTeleportButton->setVisible(!edit_mode); +    mSaveButton->setVisible(edit_mode); +    mCancelButton->setVisible(edit_mode); +    mEditButton->setVisible(!edit_mode && getSelfProfile()); +} + +void LLPanelProfileClassified::enableEditing(bool enable) +{ +    mEditButton->setEnabled(enable); +    mClassifiedNameEdit->setEnabled(enable); +    mClassifiedDescEdit->setEnabled(enable); +    mSetLocationButton->setEnabled(enable); +    mCategoryCombo->setEnabled(enable); +    mContentTypeCombo->setEnabled(enable); +    mPriceEdit->setEnabled(enable); +    mAutoRenewEdit->setEnabled(enable); +} + +void LLPanelProfileClassified::resetControls() +{ +    updateButtons(); + +    mCategoryCombo->setCurrentByIndex(0); +    mContentTypeCombo->setCurrentByIndex(0); +    mAutoRenewEdit->setValue(false); +    mPriceEdit->setValue(MINIMUM_PRICE_FOR_LISTING); +    mPriceEdit->setEnabled(TRUE); +} + +void LLPanelProfileClassified::onEditClick() +{ +    setEditMode(TRUE); +} + +void LLPanelProfileClassified::onCancelClick() +{ +    // Reload data to undo changes to forms +    LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + +    setInfoLoaded(false); + +    setEditMode(FALSE); +} + +void LLPanelProfileClassified::onSaveClick() +{ +    mCanClose = false; + +    if(!isValidName()) +    { +        notifyInvalidName(); +        return; +    } +    if(isNew() || isNewWithErrors()) +    { +        if(gStatusBar->getBalance() < getPriceForListing()) +        { +            LLNotificationsUtil::add("ClassifiedInsufficientFunds"); +            return; +        } + +        mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( +            "publish_classified", LLSD()); + +        if(!mPublishFloater) +        { +            mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( +                "publish_classified", LLSD()); + +            mPublishFloater->setPublishClickedCallback(boost::bind +                (&LLPanelProfileClassified::onPublishFloaterPublishClicked, this)); +        } + +        // set spinner value before it has focus or value wont be set +        mPublishFloater->setPrice(getPriceForListing()); +        mPublishFloater->openFloater(mPublishFloater->getKey()); +        mPublishFloater->center(); +    } +    else +    { +        doSave(); +    } +} + +/*static*/ +void LLPanelProfileClassified::handleSearchStatResponse(LLUUID classifiedId, LLSD result) +{ +    S32 teleport = result["teleport_clicks"].asInteger(); +    S32 map = result["map_clicks"].asInteger(); +    S32 profile = result["profile_clicks"].asInteger(); +    S32 search_teleport = result["search_teleport_clicks"].asInteger(); +    S32 search_map = result["search_map_clicks"].asInteger(); +    S32 search_profile = result["search_profile_clicks"].asInteger(); + +    LLPanelProfileClassified::setClickThrough(classifiedId, +        teleport + search_teleport, +        map + search_map, +        profile + search_profile, +        true); +} + +void LLPanelProfileClassified::resetData() +{ +    setClassifiedName(LLStringUtil::null); +    setDescription(LLStringUtil::null); +    setClassifiedLocation(LLStringUtil::null); +    setClassifiedId(LLUUID::null); +    setSnapshotId(LLUUID::null); +    setPosGlobal(LLVector3d::zero); +    setParcelId(LLUUID::null); +    setSimName(LLStringUtil::null); +    setFromSearch(false); + +    // reset click stats +    mTeleportClicksOld  = 0; +    mMapClicksOld       = 0; +    mProfileClicksOld   = 0; +    mTeleportClicksNew  = 0; +    mMapClicksNew       = 0; +    mProfileClicksNew   = 0; + +    mCategoryText->setValue(LLStringUtil::null); +    mContentTypeText->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null); +    mPriceEdit->setValue(LLStringUtil::null); +    mEditButton->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("creation_date")->setValue(LLStringUtil::null); +    mContentTypeM->setVisible(FALSE); +    mContentTypeG->setVisible(FALSE); +} + +void LLPanelProfileClassified::setClassifiedName(const std::string& name) +{ +    mClassifiedNameText->setValue(name); +    mClassifiedNameEdit->setValue(name); +} + +std::string LLPanelProfileClassified::getClassifiedName() +{ +    return mClassifiedNameEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setDescription(const std::string& desc) +{ +    mClassifiedDescText->setValue(desc); +    mClassifiedDescEdit->setValue(desc); +} + +std::string LLPanelProfileClassified::getDescription() +{ +    return mClassifiedDescEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setClassifiedLocation(const std::string& location) +{ +    mLocationText->setValue(location); +    mLocationEdit->setValue(location); +} + +std::string LLPanelProfileClassified::getClassifiedLocation() +{ +    return mLocationText->getValue().asString(); +} + +void LLPanelProfileClassified::setSnapshotId(const LLUUID& id) +{ +    mSnapshotCtrl->setValue(id); +} + +LLUUID LLPanelProfileClassified::getSnapshotId() +{ +    return mSnapshotCtrl->getValue().asUUID(); +} + +// static +void LLPanelProfileClassified::setClickThrough( +    const LLUUID& classified_id, +    S32 teleport, +    S32 map, +    S32 profile, +    bool from_new_table) +{ +    LL_INFOS() << "Click-through data for classified " << classified_id << " arrived: [" +            << teleport << ", " << map << ", " << profile << "] (" +            << (from_new_table ? "new" : "old") << ")" << LL_ENDL; + +    for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) +    { +        LLPanelProfileClassified* self = *iter; +        if (self->getClassifiedId() != classified_id) +        { +            continue; +        } + +        // *HACK: Skip LLPanelProfileClassified instances: they don't display clicks data. +        // Those instances should not be in the list at all. +        if (typeid(*self) != typeid(LLPanelProfileClassified)) +        { +            continue; +        } + +        LL_INFOS() << "Updating classified info panel" << LL_ENDL; + +        // We need to check to see if the data came from the new stat_table +        // or the old classified table. We also need to cache the data from +        // the two separate sources so as to display the aggregate totals. + +        if (from_new_table) +        { +            self->mTeleportClicksNew = teleport; +            self->mMapClicksNew = map; +            self->mProfileClicksNew = profile; +        } +        else +        { +            self->mTeleportClicksOld = teleport; +            self->mMapClicksOld = map; +            self->mProfileClicksOld = profile; +        } + +        static LLUIString ct_str = self->getString("click_through_text_fmt"); + +        ct_str.setArg("[TELEPORT]", llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld)); +        ct_str.setArg("[MAP]",      llformat("%d", self->mMapClicksNew + self->mMapClicksOld)); +        ct_str.setArg("[PROFILE]",  llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld)); + +        self->getChild<LLUICtrl>("click_through_text")->setValue(ct_str.getString()); +        // *HACK: remove this when there is enough room for click stats in the info panel +        self->getChildView("click_through_text")->setToolTip(ct_str.getString()); + +        LL_INFOS() << "teleport: " << llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld) +                << ", map: "    << llformat("%d", self->mMapClicksNew + self->mMapClicksOld) +                << ", profile: " << llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld) +                << LL_ENDL; +    } +} + +// static +std::string LLPanelProfileClassified::createLocationText( +    const std::string& original_name, +    const std::string& sim_name, +    const LLVector3d& pos_global) +{ +    std::string location_text; + +    location_text.append(original_name); + +    if (!sim_name.empty()) +    { +        if (!location_text.empty()) +            location_text.append(", "); +        location_text.append(sim_name); +    } + +    if (!location_text.empty()) +        location_text.append(" "); + +    if (!pos_global.isNull()) +    { +        S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; +        S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; +        S32 region_z = ll_round((F32)pos_global.mdV[VZ]); +        location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); +    } + +    return location_text; +} + +void LLPanelProfileClassified::scrollToTop() +{ +    if (mScrollContainer) +    { +        mScrollContainer->goToTop(); +    } +} + +//info +// static +// *TODO: move out of the panel +void LLPanelProfileClassified::sendClickMessage( +        const std::string& type, +        bool from_search, +        const LLUUID& classified_id, +        const LLUUID& parcel_id, +        const LLVector3d& global_pos, +        const std::string& sim_name) +{ +    if (gAgent.getRegion()) +    { +        // You're allowed to click on your own ads to reassure yourself +        // that the system is working. +        LLSD body; +        body["type"]            = type; +        body["from_search"]     = from_search; +        body["classified_id"]   = classified_id; +        body["parcel_id"]       = parcel_id; +        body["dest_pos_global"] = global_pos.getValue(); +        body["region_name"]     = sim_name; + +        std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); +        LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; +        LL_INFOS() << "body: [" << body << "]" << LL_ENDL; +        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, +            "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); +    } +} + +void LLPanelProfileClassified::sendClickMessage(const std::string& type) +{ +    sendClickMessage( +        type, +        fromSearch(), +        getClassifiedId(), +        getParcelId(), +        getPosGlobal(), +        getSimName()); +} + +void LLPanelProfileClassified::onMapClick() +{ +    sendClickMessage("map"); +    LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfileClassified::onTeleportClick() +{ +    if (!getPosGlobal().isExactlyZero()) +    { +        sendClickMessage("teleport"); +        gAgent.teleportViaLocation(getPosGlobal()); +        LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    } +} + +BOOL LLPanelProfileClassified::isDirty() const +{ +    if(mIsNew) +    { +        return TRUE; +    } + +    BOOL dirty = false; +    dirty |= mSnapshotCtrl->isDirty(); +    dirty |= mClassifiedNameEdit->isDirty(); +    dirty |= mClassifiedDescEdit->isDirty(); +    dirty |= mCategoryCombo->isDirty(); +    dirty |= mContentTypeCombo->isDirty(); +    dirty |= mAutoRenewEdit->isDirty(); +    dirty |= mPriceEdit->isDirty(); + +    return dirty; +} + +void LLPanelProfileClassified::resetDirty() +{ +    mSnapshotCtrl->resetDirty(); +    mClassifiedNameEdit->resetDirty(); + +    // call blockUndo() to really reset dirty(and make isDirty work as intended) +    mClassifiedDescEdit->blockUndo(); +    mClassifiedDescEdit->resetDirty(); + +    mCategoryCombo->resetDirty(); +    mContentTypeCombo->resetDirty(); +    mAutoRenewEdit->resetDirty(); +    mPriceEdit->resetDirty(); +} + +bool LLPanelProfileClassified::canClose() +{ +    return mCanClose; +} + +U32 LLPanelProfileClassified::getContentType() +{ +    return mContentTypeCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setContentType(bool mature) +{ +    static std::string mature_str = getString("type_mature"); +    static std::string pg_str = getString("type_pg"); +    mContentTypeText->setValue(mature ? mature_str : pg_str); +    mContentTypeM->setVisible(mature); +    mContentTypeG->setVisible(!mature); +    mContentTypeCombo->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG); +    mContentTypeCombo->resetDirty(); +} + +bool LLPanelProfileClassified::getAutoRenew() +{ +    return mAutoRenewEdit->getValue().asBoolean(); +} + +void LLPanelProfileClassified::sendUpdate() +{ +    LLAvatarClassifiedInfo c_data; + +    if(getClassifiedId().isNull()) +    { +        setClassifiedId(LLUUID::generateNewID()); +    } + +    c_data.agent_id = gAgent.getID(); +    c_data.classified_id = getClassifiedId(); +    // *HACK +    // Categories on server start with 1 while combo-box index starts with 0 +    c_data.category = getCategory() + 1; +    c_data.name = getClassifiedName(); +    c_data.description = getDescription(); +    c_data.parcel_id = getParcelId(); +    c_data.snapshot_id = getSnapshotId(); +    c_data.pos_global = getPosGlobal(); +    c_data.flags = getFlags(); +    c_data.price_for_listing = getPriceForListing(); + +    LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); + +    if(isNew()) +    { +        // Lets assume there will be some error. +        // Successful sendClassifiedInfoUpdate will trigger processProperties and +        // let us know there was no error. +        mIsNewWithErrors = true; +    } +} + +U32 LLPanelProfileClassified::getCategory() +{ +    return mCategoryCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setCategory(U32 category) +{ +    mCategoryCombo->setCurrentByIndex(category); +    mCategoryCombo->resetDirty(); +} + +U8 LLPanelProfileClassified::getFlags() +{ +    bool auto_renew = mAutoRenewEdit->getValue().asBoolean(); + +    bool mature = mContentTypeCombo->getCurrentIndex() == CB_ITEM_MATURE; + +    return pack_classified_flags_request(auto_renew, false, mature, false); +} + +void LLPanelProfileClassified::enableSave(bool enable) +{ +    mSaveButton->setEnabled(enable); +} + +std::string LLPanelProfileClassified::makeClassifiedName() +{ +    std::string name; + +    LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +    if(parcel) +    { +        name = parcel->getName(); +    } + +    if(!name.empty()) +    { +        return name; +    } + +    LLViewerRegion* region = gAgent.getRegion(); +    if(region) +    { +        name = region->getName(); +    } + +    return name; +} + +S32 LLPanelProfileClassified::getPriceForListing() +{ +    return mPriceEdit->getValue().asInteger(); +} + +void LLPanelProfileClassified::setPriceForListing(S32 price) +{ +    mPriceEdit->setValue(price); +} + +void LLPanelProfileClassified::onSetLocationClick() +{ +    setPosGlobal(gAgent.getPositionGlobal()); +    setParcelId(LLUUID::null); + +    std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); +    LLViewerRegion* region = gAgent.getRegion(); +    if (region) +    { +        region_name = region->getName(); +    } + +    setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + +    // mark classified as dirty +    setValue(LLSD()); + +    onChange(); +} + +void LLPanelProfileClassified::onChange() +{ +    enableSave(isDirty()); +} + +void LLPanelProfileClassified::doSave() +{ +    //*TODO: Fix all of this + +    mCanClose = true; +    sendUpdate(); +    updateTabLabel(getClassifiedName()); +    resetDirty(); + +    if (!canClose()) +    { +        return; +    } + +    if (!isNew() && !isNewWithErrors()) +    { +        setEditMode(FALSE); +        return; +    } + +    updateButtons(); +} + +void LLPanelProfileClassified::onPublishFloaterPublishClicked() +{ +    setPriceForListing(mPublishFloater->getPrice()); + +    doSave(); +} + +std::string LLPanelProfileClassified::getLocationNotice() +{ +    static std::string location_notice = getString("location_notice"); +    return location_notice; +} + +bool LLPanelProfileClassified::isValidName() +{ +    std::string name = getClassifiedName(); +    if (name.empty()) +    { +        return false; +    } +    if (!isalnum(name[0])) +    { +        return false; +    } + +    return true; +} + +void LLPanelProfileClassified::notifyInvalidName() +{ +    std::string name = getClassifiedName(); +    if (name.empty()) +    { +        LLNotificationsUtil::add("BlankClassifiedName"); +    } +    else if (!isalnum(name[0])) +    { +        LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); +    } +} + +void LLPanelProfileClassified::onTexturePickerMouseEnter() +{ +    mEditIcon->setVisible(TRUE); +} + +void LLPanelProfileClassified::onTexturePickerMouseLeave() +{ +    mEditIcon->setVisible(FALSE); +} + +void LLPanelProfileClassified::onTextureSelected() +{ +    setSnapshotId(mSnapshotCtrl->getValue().asUUID()); +    onChange(); +} + +void LLPanelProfileClassified::updateTabLabel(const std::string& title) +{ +    setLabel(title); +    LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); +    if (parent) +    { +        parent->setCurrentTabName(title); +    } +} + + +//----------------------------------------------------------------------------- +// LLPublishClassifiedFloater +//----------------------------------------------------------------------------- + +LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) + : LLFloater(key) +{ +} + +LLPublishClassifiedFloater::~LLPublishClassifiedFloater() +{ +} + +BOOL LLPublishClassifiedFloater::postBuild() +{ +    LLFloater::postBuild(); + +    childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); +    childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); + +    return TRUE; +} + +void LLPublishClassifiedFloater::setPrice(S32 price) +{ +    getChild<LLUICtrl>("price_for_listing")->setValue(price); +} + +S32 LLPublishClassifiedFloater::getPrice() +{ +    return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); +} + +void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) +{ +    getChild<LLButton>("publish_btn")->setClickedCallback(cb); +} + +void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) +{ +    getChild<LLButton>("cancel_btn")->setClickedCallback(cb); +} diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h new file mode 100644 index 0000000000..592007305b --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.h @@ -0,0 +1,366 @@ +/** + * @file llpanelprofileclassifieds.h + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#ifndef LL_PANELPROFILECLASSIFIEDS_H +#define LL_PANELPROFILECLASSIFIEDS_H + +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedinfo.h" +#include "llfloater.h" +#include "llpanel.h" +#include "llpanelavatar.h" +#include "llrect.h" +#include "lluuid.h" +#include "v3dmath.h" +#include "llcoros.h" +#include "lleventcoro.h" + +class LLCheckBoxCtrl; +class LLLineEditor; +class LLMediaCtrl; +class LLScrollContainer; +class LLTabContainer; +class LLTextEditor; +class LLTextureCtrl; +class LLUICtrl; + + +class LLPublishClassifiedFloater : public LLFloater +{ +public: +    LLPublishClassifiedFloater(const LLSD& key); +    virtual ~LLPublishClassifiedFloater(); + +    /*virtual*/ BOOL postBuild(); + +    void setPrice(S32 price); +    S32 getPrice(); + +    void setPublishClickedCallback(const commit_signal_t::slot_type& cb); +    void setCancelClickedCallback(const commit_signal_t::slot_type& cb); +}; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfileClassifieds +    : public LLPanelProfileTab +{ +public: +    LLPanelProfileClassifieds(); +    /*virtual*/ ~LLPanelProfileClassifieds(); + +    /*virtual*/ BOOL postBuild(); + +    /*virtual*/ void onOpen(const LLSD& key); + +    void selectClassified(const LLUUID& classified_id, bool edit); + +    /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +    /*virtual*/ void resetData(); + +    /*virtual*/ void updateButtons(); + +    /*virtual*/ void updateData(); + +private: +    void onClickNewBtn(); +    void onClickDelete(); +    void callbackDeleteClassified(const LLSD& notification, const LLSD& response); + +    bool canAddNewClassified(); +    bool canDeleteClassified(); + +    LLTabContainer* mTabContainer; +    LLUICtrl*       mNoItemsLabel; +    LLButton*       mNewButton; +    LLButton*       mDeleteButton; + +    LLUUID          mClassifiedToSelectOnLoad; +    bool            mClassifiedEditOnLoad; +}; + + +class LLPanelProfileClassified +    : public LLPanelProfileTab +{ +public: + +    static LLPanelProfileClassified* create(); + +    LLPanelProfileClassified(); + +    /*virtual*/ ~LLPanelProfileClassified(); + +    /*virtual*/ BOOL postBuild(); + +    void onOpen(const LLSD& key); + +    /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +    void setSnapshotId(const LLUUID& id); + +    LLUUID getSnapshotId(); + +    void setClassifiedId(const LLUUID& id) { mClassifiedId = id; } + +    LLUUID& getClassifiedId() { return mClassifiedId; } + +    void setClassifiedName(const std::string& name); + +    std::string getClassifiedName(); + +    void setDescription(const std::string& desc); + +    std::string getDescription(); + +    void setClassifiedLocation(const std::string& location); + +    std::string getClassifiedLocation(); + +    void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + +    LLVector3d& getPosGlobal() { return mPosGlobal; } + +    void setParcelId(const LLUUID& id) { mParcelId = id; } + +    LLUUID getParcelId() { return mParcelId; } + +    void setSimName(const std::string& sim_name) { mSimName = sim_name; } + +    std::string getSimName() { return mSimName; } + +    void setFromSearch(bool val) { mFromSearch = val; } + +    bool fromSearch() { return mFromSearch; } + +    bool getInfoLoaded() { return mInfoLoaded; } + +    void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } + +    /*virtual*/ BOOL isDirty() const; + +    /*virtual*/ void resetDirty(); + +    bool isNew() { return mIsNew; } + +    bool isNewWithErrors() { return mIsNewWithErrors; } + +    bool canClose(); + +    U32 getCategory(); + +    void setCategory(U32 category); + +    U32 getContentType(); + +    void setContentType(bool mature); + +    bool getAutoRenew(); + +    S32 getPriceForListing(); + +    void setEditMode(BOOL edit_mode); +    bool getEditMode() {return mEditMode;} + +    static void setClickThrough( +        const LLUUID& classified_id, +        S32 teleport, +        S32 map, +        S32 profile, +        bool from_new_table); + +    static void sendClickMessage( +            const std::string& type, +            bool from_search, +            const LLUUID& classified_id, +            const LLUUID& parcel_id, +            const LLVector3d& global_pos, +            const std::string& sim_name); + +protected: + +    /*virtual*/ void resetData(); + +    void resetControls(); + +    /*virtual*/ void updateButtons(); + +    static std::string createLocationText( +        const std::string& original_name, +        const std::string& sim_name, +        const LLVector3d& pos_global); + +    void sendClickMessage(const std::string& type); + +    void scrollToTop(); + +    void onEditClick(); +    void onCancelClick(); +    void onSaveClick(); +    void onMapClick(); +    void onTeleportClick(); + +    void sendUpdate(); + +    void enableSave(bool enable); + +    void enableEditing(bool enable); + +    std::string makeClassifiedName(); + +    void setPriceForListing(S32 price); + +    U8 getFlags(); + +    std::string getLocationNotice(); + +    bool isValidName(); + +    void notifyInvalidName(); + +    void onSetLocationClick(); +    void onChange(); + +    void doSave(); + +    void onPublishFloaterPublishClicked(); + +    void onTexturePickerMouseEnter(); +    void onTexturePickerMouseLeave(); + +    void onTextureSelected(); + + + + +    /** +     * Callback for "Map" button, opens Map +     */ +    void onClickMap(); + +    /** +     * Callback for "Teleport" button, teleports user to Pick location. +     */ +    void onClickTeleport(); + +    /** +     * Enables/disables "Save" button +     */ +    void enableSaveButton(BOOL enable); + +    /** +     * Called when snapshot image changes. +     */ +    void onSnapshotChanged(); + +    /** +     * Callback for Pick snapshot, name and description changed event. +     */ +    void onPickChanged(LLUICtrl* ctrl); + +    /** +     * Callback for "Set Location" button click +     */ +    void onClickSetLocation(); + +    /** +     * Callback for "Save" button click +     */ +    void onClickSave(); + +    void onDescriptionFocusReceived(); + +    void updateTabLabel(const std::string& title); + +private: + +    LLTextureCtrl*      mSnapshotCtrl; +    LLUICtrl*           mEditIcon; +    LLUICtrl*           mClassifiedNameText; +    LLUICtrl*           mClassifiedDescText; +    LLLineEditor*       mClassifiedNameEdit; +    LLTextEditor*       mClassifiedDescEdit; +    LLUICtrl*           mLocationText; +    LLUICtrl*           mLocationEdit; +    LLUICtrl*           mCategoryText; +    LLComboBox*         mCategoryCombo; +    LLUICtrl*           mContentTypeText; +    LLIconCtrl*         mContentTypeM; +    LLIconCtrl*         mContentTypeG; +    LLComboBox*         mContentTypeCombo; +    LLUICtrl*           mPriceText; +    LLUICtrl*           mPriceEdit; +    LLUICtrl*           mPricelabel; +    LLUICtrl*           mAutoRenewText; +    LLUICtrl*           mAutoRenewEdit; + +    LLButton*           mMapButton; +    LLButton*           mTeleportButton; +    LLButton*           mEditButton; +    LLButton*           mSaveButton; +    LLButton*           mSetLocationButton; +    LLButton*           mCancelButton; + +    LLScrollContainer*  mScrollContainer; +    LLPanel*            mInfoPanel; +    LLPanel*            mEditPanel; + + +    LLUUID mClassifiedId; +    LLVector3d mPosGlobal; +    LLUUID mParcelId; +    std::string mSimName; +    bool mFromSearch; +    bool mInfoLoaded; +    bool mEditMode; + +    // Needed for stat tracking +    S32 mTeleportClicksOld; +    S32 mMapClicksOld; +    S32 mProfileClicksOld; +    S32 mTeleportClicksNew; +    S32 mMapClicksNew; +    S32 mProfileClicksNew; + + +    static void handleSearchStatResponse(LLUUID classifiedId, LLSD result); + +    typedef std::list<LLPanelProfileClassified*> panel_list_t; +    static panel_list_t sAllPanels; + + +    bool mIsNew; +    bool mIsNewWithErrors; +    bool mCanClose; +    bool mEditOnLoad; + +    LLPublishClassifiedFloater* mPublishFloater; +}; + +#endif // LL_PANELPROFILECLASSIFIEDS_H diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp new file mode 100644 index 0000000000..49d22f5518 --- /dev/null +++ b/indra/newview/llpanelprofilepicks.cpp @@ -0,0 +1,774 @@ +/** + * @file llpanelprofilepicks.cpp + * @brief LLPanelProfilePicks and related class implementations + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llpanelprofilepicks.h" + +#include "llagent.h" +#include "llagentpicksinfo.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llcommandhandler.h" +#include "lldispatcher.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llpanelprofile.h" +#include "llparcel.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" + +static LLPanelInjector<LLPanelProfilePicks> t_panel_profile_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfilePick> t_panel_profile_pick("panel_profile_pick"); + + +class LLPickHandler : public LLCommandHandler +{ +public: + +    // requires trusted browser to trigger +    LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + +    bool handle(const LLSD& params, const LLSD& query_map, +        LLMediaCtrl* web) +    { +        if (!LLUI::sSettingGroups["config"]->getBOOL("EnablePicks")) +        { +            LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); +            return true; +        } + +        // handle app/classified/create urls first +        if (params.size() == 1 && params[0].asString() == "create") +        { +            LLAvatarActions::showPicks(gAgent.getID()); +            return true; +        } + +        // then handle the general app/pick/{UUID}/{CMD} urls +        if (params.size() < 2) +        { +            return false; +        } + +        // get the ID for the pick_id +        LLUUID pick_id; +        if (!pick_id.set(params[0], FALSE)) +        { +            return false; +        } + +        // edit the pick in the side tray. +        // need to ask the server for more info first though... +        const std::string verb = params[1].asString(); +        if (verb == "edit") +        { +            LLAvatarActions::showPick(gAgent.getID(), pick_id); +            return true; +        } +        else +        { +            LL_WARNS() << "unknown verb " << verb << LL_ENDL; +            return false; +        } +    } +}; +LLPickHandler gPickHandler; + + +//----------------------------------------------------------------------------- +// LLPanelProfilePicks +//----------------------------------------------------------------------------- + +LLPanelProfilePicks::LLPanelProfilePicks() + : LLPanelProfileTab() + , mPickToSelectOnLoad(LLUUID::null) +{ +} + +LLPanelProfilePicks::~LLPanelProfilePicks() +{ +} + +void LLPanelProfilePicks::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mNewButton->setVisible(TRUE); +        mNewButton->setEnabled(FALSE); + +        mDeleteButton->setVisible(TRUE); +        mDeleteButton->setEnabled(FALSE); +    } +} + +void LLPanelProfilePicks::selectPick(const LLUUID& pick_id) +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (pick_panel) +            { +                if (pick_panel->getPickId() == pick_id) +                { +                    mTabContainer->selectTabPanel(pick_panel); +                    break; +                } +            } +        } +    } +    else +    { +        mPickToSelectOnLoad = pick_id; +    } +} + +BOOL LLPanelProfilePicks::postBuild() +{ +    mTabContainer = getChild<LLTabContainer>("tab_picks"); +    mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); +    mNewButton = getChild<LLButton>("new_btn"); +    mDeleteButton = getChild<LLButton>("delete_btn"); + +    mNewButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickNewBtn, this)); +    mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickDelete, this)); + +    return TRUE; +} + +void LLPanelProfilePicks::onClickNewBtn() +{ +    mNoItemsLabel->setVisible(FALSE); +    LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); +    pick_panel->setAvatarId(getAvatarId()); +    mTabContainer->addTabPanel( +        LLTabContainer::TabPanelParams(). +        panel(pick_panel). +        select_tab(true). +        label(pick_panel->getPickName())); +    updateButtons(); +} + +void LLPanelProfilePicks::onClickDelete() +{ +    LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); +    if (pick_panel) +    { +        LLUUID pick_id = pick_panel->getPickId(); +        LLSD args; +        args["PICK"] = pick_panel->getPickName(); +        LLSD payload; +        payload["pick_id"] = pick_id; +        payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); +        LLNotificationsUtil::add("DeleteAvatarPick", args, payload, +            boost::bind(&LLPanelProfilePicks::callbackDeletePick, this, _1, _2)); +    } +} + +void LLPanelProfilePicks::callbackDeletePick(const LLSD& notification, const LLSD& response) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + +    if (0 == option) +    { +        LLUUID pick_id = notification["payload"]["pick_id"].asUUID(); +        S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + +        LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (pick_panel && pick_panel->getPickId() == pick_id) +        { +            mTabContainer->removeTabPanel(pick_panel); +        } + +        if (pick_id.notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->sendPickDelete(pick_id); +        } + +        updateButtons(); +    } +} + +void LLPanelProfilePicks::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PICKS == type) +    { +        LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); +        if (avatar_picks && getAvatarId() == avatar_picks->target_id) +        { +            LLUUID selected_id = mPickToSelectOnLoad; +            if (mPickToSelectOnLoad.isNull()) +            { +                if (mTabContainer->getTabCount() > 0) +                { +                    LLPanelProfilePick* active_pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); +                    if (active_pick_panel) +                    { +                        selected_id = active_pick_panel->getPickId(); +                    } +                } +            } + +            mTabContainer->deleteAllTabs(); + +            LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); +            for (; avatar_picks->picks_list.end() != it; ++it) +            { +                LLUUID pick_id = it->first; +                std::string pick_name = it->second; + +                LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + +                pick_panel->setPickId(pick_id); +                pick_panel->setPickName(pick_name); +                pick_panel->setAvatarId(getAvatarId()); + +                mTabContainer->addTabPanel( +                    LLTabContainer::TabPanelParams(). +                    panel(pick_panel). +                    select_tab(selected_id == pick_id). +                    label(pick_name)); + +                if (selected_id == pick_id) +                { +                    mPickToSelectOnLoad = LLUUID::null; +                } +            } + +            BOOL no_data = !mTabContainer->getTabCount(); +            mNoItemsLabel->setVisible(no_data); +            if (no_data) +            { +                if(getSelfProfile()) +                { +                    mNoItemsLabel->setValue(LLTrans::getString("NoPicksText")); +                } +                else +                { +                    mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksText")); +                } +            } +            else if (selected_id.isNull()) +            { +                mTabContainer->selectFirstTab(); +            } + +            updateButtons(); +        } +    } +} + +void LLPanelProfilePicks::resetData() +{ +    resetLoading(); +    mTabContainer->deleteAllTabs(); +} + +void LLPanelProfilePicks::updateButtons() +{ +    LLPanelProfileTab::updateButtons(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mNewButton->setEnabled(canAddNewPick()); +        mDeleteButton->setEnabled(canDeletePick()); +    } +} + +void LLPanelProfilePicks::apply() +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (pick_panel) +            { +                pick_panel->apply(); +            } +        } +    } +} + +void LLPanelProfilePicks::updateData() +{ +    // Send picks request only once +    LLUUID avatar_id = getAvatarId(); +    if (!getIsLoading() && avatar_id.notNull()) +    { +        setIsLoading(); +        mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); +        mNoItemsLabel->setVisible(TRUE); + +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(avatar_id); +    } +} + +bool LLPanelProfilePicks::canAddNewPick() +{ +    return (!LLAgentPicksInfo::getInstance()->isPickLimitReached() && +        mTabContainer->getTabCount() < LLAgentPicksInfo::getInstance()->getMaxNumberOfPicks()); +} + +bool LLPanelProfilePicks::canDeletePick() +{ +    return (mTabContainer->getTabCount() > 0); +} + + +//----------------------------------------------------------------------------- +// LLPanelProfilePick +//----------------------------------------------------------------------------- + +LLPanelProfilePick::LLPanelProfilePick() + : LLPanelProfileTab() + , LLRemoteParcelInfoObserver() + , mSnapshotCtrl(NULL) + , mPickId(LLUUID::null) + , mParcelId(LLUUID::null) + , mRequestedId(LLUUID::null) + , mLocationChanged(false) + , mNewPick(false) + , mCurrentPickDescription("") + , mIsEditing(false) +{ +} + +//static +LLPanelProfilePick* LLPanelProfilePick::create() +{ +    LLPanelProfilePick* panel = new LLPanelProfilePick(); +    panel->buildFromFile("panel_profile_pick.xml"); +    return panel; +} + +LLPanelProfilePick::~LLPanelProfilePick() +{ +    if (mParcelId.notNull()) +    { +        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +    } +} + +void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.isNull()) +    { +        return; +    } +    LLPanelProfileTab::setAvatarId(avatar_id); + +    // creating new Pick +    if (getPickId().isNull() && getSelfProfile()) +    { +        mNewPick = true; + +        setPosGlobal(gAgent.getPositionGlobal()); + +        LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; +        std::string pick_name, pick_desc, region_name; + +        LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +        if (parcel) +        { +            parcel_id = parcel->getID(); +            pick_name = parcel->getName(); +            pick_desc = parcel->getDesc(); +            snapshot_id = parcel->getSnapshotID(); +        } + +        LLViewerRegion* region = gAgent.getRegion(); +        if (region) +        { +            region_name = region->getName(); +        } + +        setParcelID(parcel_id); +        setPickName(pick_name.empty() ? region_name : pick_name); +        setPickDesc(pick_desc); +        setSnapshotId(snapshot_id); +        setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal())); + +        enableSaveButton(TRUE); +    } +    else +    { +        LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(getAvatarId(), getPickId()); + +        enableSaveButton(FALSE); +    } + +    resetDirty(); + +    if (getSelfProfile() && !getEmbedded()) +    { +        mPickName->setEnabled(TRUE); +        mPickDescription->setEnabled(TRUE); +        mSetCurrentLocationButton->setVisible(TRUE); +    } +    else +    { +        mSnapshotCtrl->setEnabled(FALSE); +    } +} + +BOOL LLPanelProfilePick::postBuild() +{ +    mPickName = getChild<LLLineEditor>("pick_name"); +    mPickDescription = getChild<LLTextEditor>("pick_desc"); +    mSaveButton = getChild<LLButton>("save_changes_btn"); +    mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn"); + +    mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot"); +    mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); + +    childSetAction("teleport_btn", boost::bind(&LLPanelProfilePick::onClickTeleport, this)); +    childSetAction("show_on_map_btn", boost::bind(&LLPanelProfilePick::onClickMap, this)); + +    mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); +    mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); + +    mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); +    mPickName->setEnabled(FALSE); + +    mPickDescription->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1)); +    mPickDescription->setFocusReceivedCallback(boost::bind(&LLPanelProfilePick::onDescriptionFocusReceived, this)); + +    getChild<LLUICtrl>("pick_location")->setEnabled(FALSE); + +    return TRUE; +} + +void LLPanelProfilePick::onDescriptionFocusReceived() +{ +    if (!mIsEditing && getSelfProfile()) +    { +        mIsEditing = true; +        mPickDescription->setParseHTML(false); +        setPickDesc(mCurrentPickDescription); +    } +} + +void LLPanelProfilePick::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PICK_INFO != type) +    { +        return; +    } + +    LLPickData* pick_info = static_cast<LLPickData*>(data); +    if (!pick_info +        || pick_info->creator_id != getAvatarId() +        || pick_info->pick_id != getPickId()) +    { +        return; +    } + +    mIsEditing = false; +    mPickDescription->setParseHTML(true); +    mParcelId = pick_info->parcel_id; +    setSnapshotId(pick_info->snapshot_id); +    if (!getSelfProfile() || getEmbedded()) +    { +        mSnapshotCtrl->setEnabled(FALSE); +    } +    setPickName(pick_info->name); +    setPickDesc(pick_info->desc); +    setPosGlobal(pick_info->pos_global); +    mCurrentPickDescription = pick_info->desc; + +    // Send remote parcel info request to get parcel name and sim (region) name. +    sendParcelInfoRequest(); + +    // *NOTE dzaporozhan +    // We want to keep listening to APT_PICK_INFO because user may +    // edit the Pick and we have to update Pick info panel. +    // revomeObserver is called from onClickBack + +    updateButtons(); +} + +void LLPanelProfilePick::apply() +{ +    if ((mNewPick || getIsLoaded()) && isDirty()) +    { +        sendUpdate(); +    } +} + +void LLPanelProfilePick::setSnapshotId(const LLUUID& id) +{ +    mSnapshotCtrl->setImageAssetID(id); +    mSnapshotCtrl->setValid(TRUE); +} + +void LLPanelProfilePick::setPickName(const std::string& name) +{ +    mPickName->setValue(name); +} + +const std::string LLPanelProfilePick::getPickName() +{ +    return mPickName->getValue().asString(); +} + +void LLPanelProfilePick::setPickDesc(const std::string& desc) +{ +    mPickDescription->setValue(desc); +} + +void LLPanelProfilePick::setPickLocation(const std::string& location) +{ +    getChild<LLUICtrl>("pick_location")->setValue(location); +} + +void LLPanelProfilePick::onClickMap() +{ +    LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfilePick::onClickTeleport() +{ +    if (!getPosGlobal().isExactlyZero()) +    { +        gAgent.teleportViaLocation(getPosGlobal()); +        LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    } +} + +void LLPanelProfilePick::enableSaveButton(BOOL enable) +{ +    mSaveButton->setEnabled(enable); +    mSaveButton->setVisible(enable); +} + +void LLPanelProfilePick::onSnapshotChanged() +{ +    enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onPickChanged(LLUICtrl* ctrl) +{ +    if (ctrl && ctrl == mPickName) +    { +        updateTabLabel(mPickName->getText()); +    } + +    enableSaveButton(isDirty()); +} + +void LLPanelProfilePick::resetDirty() +{ +    LLPanel::resetDirty(); + +    mPickName->resetDirty(); +    mPickDescription->resetDirty(); +    mSnapshotCtrl->resetDirty(); +    mLocationChanged = false; +} + +BOOL LLPanelProfilePick::isDirty() const +{ +    if (mNewPick +        || LLPanel::isDirty() +        || mLocationChanged +        || mSnapshotCtrl->isDirty() +        || mPickName->isDirty() +        || mPickDescription->isDirty()) +    { +        return TRUE; +    } +    return FALSE; +} + +void LLPanelProfilePick::onClickSetLocation() +{ +    // Save location for later use. +    setPosGlobal(gAgent.getPositionGlobal()); + +    std::string parcel_name, region_name; + +    LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +    if (parcel) +    { +        mParcelId = parcel->getID(); +        parcel_name = parcel->getName(); +    } + +    LLViewerRegion* region = gAgent.getRegion(); +    if (region) +    { +        region_name = region->getName(); +    } + +    setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); + +    mLocationChanged = true; +    enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onClickSave() +{ +    sendUpdate(); + +    mLocationChanged = false; +} + +std::string LLPanelProfilePick::getLocationNotice() +{ +    static const std::string notice = getString("location_notice"); +    return notice; +} + +void LLPanelProfilePick::sendParcelInfoRequest() +{ +    if (mParcelId != mRequestedId) +    { +        if (mRequestedId.notNull()) +        { +            LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedId, this); +        } +        LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); +        LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); + +        mRequestedId = mParcelId; +    } +} + +void LLPanelProfilePick::processParcelInfo(const LLParcelData& parcel_data) +{ +    setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, parcel_data.sim_name, getPosGlobal())); + +    // We have received parcel info for the requested ID so clear it now. +    mRequestedId.setNull(); + +    if (mParcelId.notNull()) +    { +        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +    } +} + +void LLPanelProfilePick::sendUpdate() +{ +    LLPickData pick_data; + +    // If we don't have a pick id yet, we'll need to generate one, +    // otherwise we'll keep overwriting pick_id 00000 in the database. +    if (getPickId().isNull()) +    { +        getPickId().generate(); +    } + +    pick_data.agent_id = gAgentID; +    pick_data.session_id = gAgent.getSessionID(); +    pick_data.pick_id = getPickId(); +    pick_data.creator_id = gAgentID;; + +    //legacy var  need to be deleted +    pick_data.top_pick = FALSE; +    pick_data.parcel_id = mParcelId; +    pick_data.name = getPickName(); +    pick_data.desc = mPickDescription->getValue().asString(); +    pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); +    pick_data.pos_global = getPosGlobal(); +    pick_data.sort_order = 0; +    pick_data.enabled = TRUE; + +    LLAvatarPropertiesProcessor::getInstance()->sendPickInfoUpdate(&pick_data); + +    if(mNewPick) +    { +        // Assume a successful create pick operation, make new number of picks +        // available immediately. Actual number of picks will be requested in +        // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. +        LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); +    } +} + +// static +std::string LLPanelProfilePick::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global) +{ +    std::string location_text(owner_name); +    if (!original_name.empty()) +    { +        if (!location_text.empty()) +        { +            location_text.append(", "); +        } +        location_text.append(original_name); + +    } + +    if (!sim_name.empty()) +    { +        if (!location_text.empty()) +        { +            location_text.append(", "); +        } +        location_text.append(sim_name); +    } + +    if (!location_text.empty()) +    { +        location_text.append(" "); +    } + +    if (!pos_global.isNull()) +    { +        S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; +        S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; +        S32 region_z = ll_round((F32)pos_global.mdV[VZ]); +        location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); +    } +    return location_text; +} + +void LLPanelProfilePick::updateTabLabel(const std::string& title) +{ +    setLabel(title); +    LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); +    if (parent) +    { +        parent->setCurrentTabName(title); +    } +}
\ No newline at end of file diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h new file mode 100644 index 0000000000..aeaa25bf8b --- /dev/null +++ b/indra/newview/llpanelprofilepicks.h @@ -0,0 +1,234 @@ +/** + * @file llpanelprofilepicks.h + * @brief LLPanelProfilePicks and related class definitions + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#ifndef LL_LLPANELPICKS_H +#define LL_LLPANELPICKS_H + +#include "llpanel.h" +#include "lluuid.h" +#include "llavatarpropertiesprocessor.h" +#include "llpanelavatar.h" +#include "llremoteparcelrequest.h" + +class LLTabContainer; +class LLTextureCtrl; +class LLMediaCtrl; +class LLLineEditor; +class LLTextEditor; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfilePicks +    : public LLPanelProfileTab +{ +public: +    LLPanelProfilePicks(); +    /*virtual*/ ~LLPanelProfilePicks(); + +    /*virtual*/ BOOL postBuild(); + +    /*virtual*/ void onOpen(const LLSD& key); + +    void selectPick(const LLUUID& pick_id); + +    /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +    /*virtual*/ void resetData(); + +    /*virtual*/ void updateButtons(); + +    /** +     * Saves changes. +     */ +    virtual void apply(); + +    /** +     * Sends update data request to server. +     */ +    /*virtual*/ void updateData(); + +private: +    void onClickNewBtn(); +    void onClickDelete(); +    void callbackDeletePick(const LLSD& notification, const LLSD& response); + +    bool canAddNewPick(); +    bool canDeletePick(); + +    LLTabContainer* mTabContainer; +    LLUICtrl*       mNoItemsLabel; +    LLButton*       mNewButton; +    LLButton*       mDeleteButton; + +    LLUUID          mPickToSelectOnLoad; +}; + + +class LLPanelProfilePick +    : public LLPanelProfileTab +    , public LLRemoteParcelInfoObserver +{ +public: + +    // Creates new panel +    static LLPanelProfilePick* create(); + +    LLPanelProfilePick(); + +    /*virtual*/ ~LLPanelProfilePick(); + +    /*virtual*/ BOOL postBuild(); + +    void setAvatarId(const LLUUID& avatar_id); + +    void setPickId(const LLUUID& id) { mPickId = id; } +    virtual LLUUID& getPickId() { return mPickId; } + +    virtual void setPickName(const std::string& name); +    const std::string getPickName(); + +    /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + +    /** +     * Saves changes. +     */ +    virtual void apply(); + +    void updateTabLabel(const std::string& title); + +    //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing +    /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); +    /*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } +    /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {}; + +protected: + +    /** +     * Sends remote parcel info request to resolve parcel name from its ID. +     */ +    void sendParcelInfoRequest(); + +    /** +    * "Location text" is actually the owner name, the original +    * name that owner gave the parcel, and the location. +    */ +    static std::string createLocationText( +        const std::string& owner_name, +        const std::string& original_name, +        const std::string& sim_name, +        const LLVector3d& pos_global); + +    /** +     * Sets snapshot id. +     * +     * Will mark snapshot control as valid if id is not null. +     * Will mark snapshot control as invalid if id is null. If null id is a valid value, +     * you have to manually mark snapshot is valid. +     */ +    virtual void setSnapshotId(const LLUUID& id); +    virtual void setPickDesc(const std::string& desc); +    virtual void setPickLocation(const std::string& location); + +    virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } +    virtual LLVector3d& getPosGlobal() { return mPosGlobal; } + +    /** +     * Callback for "Map" button, opens Map +     */ +    void onClickMap(); + +    /** +     * Callback for "Teleport" button, teleports user to Pick location. +     */ +    void onClickTeleport(); + +    /** +     * Enables/disables "Save" button +     */ +    void enableSaveButton(BOOL enable); + +    /** +     * Called when snapshot image changes. +     */ +    void onSnapshotChanged(); + +    /** +     * Callback for Pick snapshot, name and description changed event. +     */ +    void onPickChanged(LLUICtrl* ctrl); + +    /** +     * Resets panel and all cantrols to unedited state +     */ +    /*virtual*/ void resetDirty(); + +    /** +     * Returns true if any of Pick properties was changed by user. +     */ +    /*virtual*/ BOOL isDirty() const; + +    /** +     * Callback for "Set Location" button click +     */ +    void onClickSetLocation(); + +    /** +     * Callback for "Save" button click +     */ +    void onClickSave(); + +    std::string getLocationNotice(); + +    /** +     * Sends Pick properties to server. +     */ +    void sendUpdate(); + +protected: + +    LLTextureCtrl*      mSnapshotCtrl; +    LLLineEditor*       mPickName; +    LLTextEditor*       mPickDescription; +    LLButton*           mSetCurrentLocationButton; +    LLButton*           mSaveButton; + +    LLVector3d mPosGlobal; +    LLUUID mParcelId; +    LLUUID mPickId; +    LLUUID mRequestedId; + +    bool mLocationChanged; +    bool mNewPick; +    bool                mIsEditing; + +    std::string mCurrentPickDescription; + +    void onDescriptionFocusReceived(); +}; + +#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 243ba00457..7669af579e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -95,6 +95,7 @@  #include "llfloateravatarpicker.h"  #include "llcallbacklist.h"  #include "llcallingcard.h" +#include "llclassifiedinfo.h"  #include "llconsole.h"  #include "llcontainerview.h"  #include "llconversationlog.h" @@ -123,7 +124,6 @@  #include "llpanellogin.h"  #include "llmutelist.h"  #include "llavatarpropertiesprocessor.h" -#include "llpanelclassified.h"  #include "llpanelpick.h"  #include "llpanelgrouplandmoney.h"  #include "llpanelgroupnotices.h" @@ -2516,7 +2516,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)  	msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply);  	msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); -//	msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);  	msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply);  	msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply);  	msg->setHandlerFunc("ScriptDialog", process_script_dialog); diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp new file mode 100644 index 0000000000..24291de6df --- /dev/null +++ b/indra/newview/llviewerdisplayname.cpp @@ -0,0 +1,218 @@ +/**  + * @file llviewerdisplayname.cpp + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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 "llviewerdisplayname.h" + +// viewer includes +#include "llagent.h" +#include "llviewerregion.h" +#include "llvoavatar.h" + +// library includes +#include "llavatarnamecache.h" +#include "llhttpnode.h" +#include "llnotificationsutil.h" +#include "llui.h"					// getLanguage() + +namespace LLViewerDisplayName +{ +	// Fired when viewer receives server response to display name change +	set_name_signal_t sSetDisplayNameSignal; + +	// Fired when there is a change in the agent's name +	name_changed_signal_t sNameChangedSignal; + +	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb)  +	{  +		sNameChangedSignal.connect(cb);  +	} + +	void doNothing() { } +} + +void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot) +{ +	// TODO: simple validation here + +	LLViewerRegion* region = gAgent.getRegion(); +	llassert(region); +	std::string cap_url = region->getCapability("SetDisplayName"); +	if (cap_url.empty()) +	{ +		// this server does not support display names, report error +		slot(false, "unsupported", LLSD()); +		return; +	} + +	// People API requires both the old and new value to change a variable. +	// Our display name will be in cache before the viewer's UI is available +	// to request a change, so we can use direct lookup without callback. +	LLAvatarName av_name; +	if (!LLAvatarNameCache::get( gAgent.getID(), &av_name)) +	{ +		slot(false, "name unavailable", LLSD()); +		return; +	} + +	// People API expects array of [ "old value", "new value" ] +	LLSD change_array = LLSD::emptyArray(); +	change_array.append(av_name.getDisplayName()); +	change_array.append(display_name); +	 +	LL_INFOS() << "Set name POST to " << cap_url << LL_ENDL; + +	// Record our caller for when the server sends back a reply +	sSetDisplayNameSignal.connect(slot); +	 +	// POST the requested change.  The sim will not send a response back to +	// this request directly, rather it will send a separate message after it +	// communicates with the back-end. +	LLSD body; +	body["display_name"] = change_array; +    LLCoros::instance().launch("LLViewerDisplayName::SetDisplayNameCoro", +            boost::bind(&LLViewerDisplayName::setDisplayNameCoro, cap_url, body)); +} + +void LLViewerDisplayName::setDisplayNameCoro(const std::string& cap_url, const LLSD& body) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("SetDisplayNameCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); + +    // People API can return localized error messages.  Indicate our +    // language preference via header. +    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT_LANGUAGE, LLUI::getLanguage()); + +    LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, body, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS() << "Unable to set display name. Status: " << status.toString() << LL_ENDL; +        LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); +        LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); +    } +} + +class LLSetDisplayNameReply : public LLHTTPNode +{ +	LOG_CLASS(LLSetDisplayNameReply); +public: +	/*virtual*/ void post( +		LLHTTPNode::ResponsePtr response, +		const LLSD& context, +		const LLSD& input) const +	{ +		LLSD body = input["body"]; + +		S32 status = body["status"].asInteger(); +		bool success = (status == HTTP_OK); +		std::string reason = body["reason"].asString(); +		LLSD content = body["content"]; + +		LL_INFOS() << "status " << status << " reason " << reason << LL_ENDL; + +		// If viewer's concept of display name is out-of-date, the set request +		// will fail with 409 Conflict.  If that happens, fetch up-to-date +		// name information. +		if (status == HTTP_CONFLICT) +		{ +			LLUUID agent_id = gAgent.getID(); +			// Flush stale data +			LLAvatarNameCache::erase( agent_id ); +			// Queue request for new data: nothing to do on callback though... +			// Note: no need to disconnect the callback as it never gets out of scope +			LLAvatarNameCache::get(agent_id, boost::bind(&LLViewerDisplayName::doNothing)); +			// Kill name tag, as it is wrong +			LLVOAvatar::invalidateNameTag( agent_id ); +		} + +		// inform caller of result +		LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content); +		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); +	} +}; + + +class LLDisplayNameUpdate : public LLHTTPNode +{ +	/*virtual*/ void post( +		LLHTTPNode::ResponsePtr response, +		const LLSD& context, +		const LLSD& input) const +	{ +		LLSD body = input["body"]; +		LLUUID agent_id = body["agent_id"]; +		std::string old_display_name = body["old_display_name"]; +		// By convention this record is called "agent" in the People API +		LLSD name_data = body["agent"]; + +		// Inject the new name data into cache +		LLAvatarName av_name; +		av_name.fromLLSD( name_data ); + +		LL_INFOS() << "name-update now " << LLDate::now() +			<< " next_update " << LLDate(av_name.mNextUpdate) +			<< LL_ENDL; + +		// Name expiration time may be provided in headers, or we may use a +		// default value +		// *TODO: get actual headers out of ResponsePtr +		//LLSD headers = response->mHeaders; +		LLSD headers; +		av_name.mExpires =  +			LLAvatarNameCache::nameExpirationFromHeaders(headers); + +		LLAvatarNameCache::insert(agent_id, av_name); + +		// force name tag to update +		LLVOAvatar::invalidateNameTag(agent_id); + +		LLSD args; +		args["OLD_NAME"] = old_display_name; +		args["SLID"] = av_name.getUserName(); +		args["NEW_NAME"] = av_name.getDisplayName(); +		LLNotificationsUtil::add("DisplayNameUpdate", args); +		if (agent_id == gAgent.getID()) +		{ +			LLViewerDisplayName::sNameChangedSignal(); +		} +	} +}; + +LLHTTPRegistration<LLSetDisplayNameReply> +    gHTTPRegistrationMessageSetDisplayNameReply( +		"/message/SetDisplayNameReply"); + +LLHTTPRegistration<LLDisplayNameUpdate> +    gHTTPRegistrationMessageDisplayNameUpdate( +		"/message/DisplayNameUpdate"); diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h new file mode 100644 index 0000000000..337aaa68b6 --- /dev/null +++ b/indra/newview/llviewerdisplayname.h @@ -0,0 +1,55 @@ +/**  + * @file llviewerdisplayname.h + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#ifndef LLVIEWERDISPLAYNAME_H +#define LLVIEWERDISPLAYNAME_H + +#include <boost/signals2.hpp> + +class LLSD; +class LLUUID; + +namespace LLViewerDisplayName +{ +	typedef boost::signals2::signal< +		void (bool success, const std::string& reason, const LLSD& content)> +			set_name_signal_t; +	typedef set_name_signal_t::slot_type set_name_slot_t; +	 +	typedef boost::signals2::signal<void (void)> name_changed_signal_t; +	typedef name_changed_signal_t::slot_type name_changed_slot_t; + +	// Sends an update to the server to change a display name +	// and call back when done.  May not succeed due to service +	// unavailable or name not available. +	void set(const std::string& display_name, const set_name_slot_t& slot); + +    void setDisplayNameCoro(const std::string& cap_url, const LLSD& body); + +	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb); +} + +#endif // LLVIEWERDISPLAYNAME_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 0ebacddd9b..7e4e9a8b10 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -58,6 +58,7 @@  #include "llfloaterdeleteenvpreset.h"  #include "llfloaterdeleteprefpreset.h"  #include "llfloaterdestinations.h" +#include "llfloaterdisplayname.h"  #include "llfloatereditdaycycle.h"  #include "llfloatereditsky.h"  #include "llfloatereditwater.h" @@ -105,6 +106,7 @@  #include "llfloaterpostprocess.h"  #include "llfloaterpreference.h"  #include "llfloaterpreviewtrash.h" +#include "llfloaterprofile.h"  #include "llfloaterproperties.h"  #include "llfloaterregiondebugconsole.h"  #include "llfloaterregioninfo.h" @@ -149,7 +151,7 @@  #include "llmoveview.h"  #include "llfloaterimnearbychat.h"  #include "llpanelblockedlist.h" -#include "llpanelclassified.h" +#include "llpanelprofileclassifieds.h"  #include "llpreviewanim.h"  #include "llpreviewgesture.h"  #include "llpreviewnotecard.h" @@ -256,6 +258,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLInspectRemoteObjectUtil::registerFloater();  	LLFloaterVoiceVolumeUtil::registerFloater();  	LLNotificationsUI::registerFloater(); +	LLFloaterDisplayNameUtil::registerFloater();  	LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);  	LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); @@ -345,8 +348,9 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);      LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>);      LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); -	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); -	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); +	LLFloaterReg::add("my_profile_web", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); +	LLFloaterReg::add("profile_web", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); +    LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);  	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);  	LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 22a21c9ca3..dd49dcccc2 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -47,7 +47,7 @@  #include "llmutelist.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llpanelprofile.h" +#include "llavataractions.h"  #include "llparcel.h"  #include "llpluginclassmedia.h"  #include "llurldispatcher.h" diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 6c52f118ad..40c9e65823 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6521,6 +6521,15 @@ class LLShowAgentProfile : public view_listener_t  	}  }; +class LLShowAgentProfilePicks : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        LLAvatarActions::showPicks(gAgent.getID()); +        return true; +    } +}; +  class LLToggleAgentProfile : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -9251,6 +9260,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak");  	view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");  	view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); +    view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks");  	view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");  	view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");  	view_listener_t::addMenu(new LLCheckControl(), "CheckControl"); diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 8dcef2c7cd..03ae328416 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -36,7 +36,7 @@  #include "llstring.h"  // newview -#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions +#include "llavataractions.h" // for getProfileURL()  #include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals  #include "llcorehttputil.h" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index e0da7f5d9e..7869eb7267 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -877,6 +877,22 @@        name="PanelNotificationListItem"        value="0.3 0.3 0.3 .3" /> +	<!-- profiles --> +    <color +        name="StatusUserOnline" +        reference="White" /> +    <color +        name="StatusUserOffline" +        reference="LtGray_35" /> +    <!-- Groups visible in own profiles --> +    <color +        name="GroupVisibleInProfile" +        reference="TextBgFocusColor" /> +    <color +        name="GroupHiddenInProfile" +        reference="Gray" /> +     +    <!-- Generic color names (legacy) -->    <color      name="white" diff --git a/indra/newview/skins/default/xui/da/panel_me.xml b/indra/newview/skins/default/xui/da/panel_me.xml deleted file mode 100644 index f98ced5f91..0000000000 --- a/indra/newview/skins/default/xui/da/panel_me.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Min profil" name="panel_me"> -	<tab_container name="tabs"> -		<panel label="MIN PROFIL" name="panel_profile"/> -		<panel label="MINE FAVORITTER" name="panel_picks"/> -	</tab_container> -</panel> diff --git a/indra/newview/skins/default/xui/da/panel_side_tray.xml b/indra/newview/skins/default/xui/da/panel_side_tray.xml deleted file mode 100644 index 66c3e69904..0000000000 --- a/indra/newview/skins/default/xui/da/panel_side_tray.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<!-- Side tray cannot show background because it is always -	partially on screen to hold tab buttons. --> -<side_tray name="sidebar"> -	<sidetray_tab description="Åbn/luk sidebar" name="sidebar_openclose" tab_title="Åbn/luk sidebar"/> -	<sidetray_tab description="Hjem." name="sidebar_home" tab_title="Hjem"> -		<panel label="hjem" name="panel_home"/> -	</sidetray_tab> -	<sidetray_tab description="Redigér din profile og favoritter." name="sidebar_me" tab_title="Min profil"> -		<panel_container name="panel_container"> -			<panel label="Mig" name="panel_me"/> -		</panel_container> -	</sidetray_tab> -	<sidetray_tab description="Find venner, kontakter og personer tæt på." name="sidebar_people" tab_title="Personer"> -		<panel_container name="panel_container"> -			<panel label="Gruppe profil" name="panel_group_info_sidetray"/> -			<panel label="Blokerede beboere og objekter" name="panel_block_list_sidetray"/> -		</panel_container> -	</sidetray_tab> -	<sidetray_tab description="Find steder du vil hen og steder du har været før." label="Steder" name="sidebar_places" tab_title="Steder"> -		<panel label="Steder" name="panel_places"/> -	</sidetray_tab> -	<sidetray_tab description="Browse din beholdning." name="sidebar_inventory" tab_title="Min beholdning"> -		<panel label="Redigér beholdning" name="sidepanel_inventory"/> -	</sidetray_tab> -	<sidetray_tab description="Ændre dit nuværende udseende" name="sidebar_appearance" tab_title="Mit udseende"> -		<panel label="Redigér udseende" name="sidepanel_appearance"/> -	</sidetray_tab> -</side_tray> diff --git a/indra/newview/skins/default/xui/de/floater_picks.xml b/indra/newview/skins/default/xui/de/floater_picks.xml deleted file mode 100644 index 2521920e83..0000000000 --- a/indra/newview/skins/default/xui/de/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Auswahlen"/> diff --git a/indra/newview/skins/default/xui/de/panel_me.xml b/indra/newview/skins/default/xui/de/panel_me.xml deleted file mode 100644 index f49446fbbf..0000000000 --- a/indra/newview/skins/default/xui/de/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mein Profil" name="panel_me"> -	<panel label="MEINE AUSWAHLEN" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/en/floater_picks.xml b/indra/newview/skins/default/xui/en/floater_picks.xml deleted file mode 100644 index 984894b016..0000000000 --- a/indra/newview/skins/default/xui/en/floater_picks.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<floater - positioning="cascading" - can_close="true" - can_resize="true" - height="572" - help_topic="sidebar_me" - min_width="333" - min_height="440" - name="floater_picks" - save_rect="true" - save_visibility="true" - reuse_instance="true" - title="Picks" - width="333" > -   <panel -    class="panel_me" -    name="main_panel" -    filename="panel_me.xml" -    follows="all"/> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile.xml b/indra/newview/skins/default/xui/en/floater_profile.xml new file mode 100644 index 0000000000..af70ba66f0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile.xml @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 +<floater
 + name="avatarinfo"
 + height="510"
 + width="430"
 + layout="topleft"
 + can_close="true"
 + can_resize="true"
 + help_topic="panel_my_profile_tab"
 + min_height="510"
 + min_width="430"
 + positioning="centered"
 + save_rect="true"
 + title="Profile"
 +>
 +    <panel
 +     name="panel_profile_view"
 +     top="0"
 +     left="0"
 +     height="500"
 +     width="420"
 +     follows="all"
 +     class="panel_profile"
 +    >
 +        <tab_container
 +         name="panel_profile_tabs"
 +         top_pad="5"
 +         left="0"
 +         height="500"
 +         width="420"
 +         follows="all"
 +         layout="topleft"
 +         halign="center"
 +         tab_min_width="55"
 +         tab_position="top"
 +        >
 +            <panel
 +             name="panel_profile_secondlife"
 +             label="2nd Life"
 +             layout="topleft"
 +             class="panel_profile_secondlife"
 +             filename="panel_profile_secondlife.xml"
 +             help_topic="profile_secondlife_tab"
 +            />
 +            <panel
 +             name="panel_profile_web"
 +             label="Web"
 +             layout="topleft"
 +             class="panel_profile_web"
 +             filename="panel_profile_web.xml"
 +             help_topic="profile_web_tab"
 +            />
 +            <panel
 +             name="panel_profile_interests"
 +             label="Interests"
 +             layout="topleft"
 +             class="panel_profile_interests"
 +             filename="panel_profile_interests.xml"
 +             help_topic="profile_interests_tab"
 +            />
 +            <panel
 +             name="panel_profile_picks"
 +             label="Picks"
 +             layout="topleft"
 +             class="panel_profile_picks"
 +             filename="panel_profile_picks.xml"
 +             help_topic="profile_picks_tab"
 +            />
 +            <panel
 +             name="panel_profile_classifieds"
 +             label="Classified"
 +             layout="topleft"
 +             class="panel_profile_classifieds"
 +             filename="panel_profile_classifieds.xml"
 +             help_topic="profile_classified_tab"
 +            />
 +            <panel
 +             name="panel_profile_firstlife"
 +             label="1st Life"
 +             layout="topleft"
 +             class="panel_profile_firstlife"
 +             filename="panel_profile_firstlife.xml"
 +             help_topic="profile_firstlife_tab"
 +            />
 +            <panel
 +             name="panel_profile_notes"
 +             label="Notes"
 +             layout="topleft"
 +             class="panel_profile_notes"
 +             filename="panel_profile_notes.xml"
 +             help_topic="profile_notes_tab"
 +            />
 +        </tab_container>
 +        <button
 +         name="ok_btn"
 +         label="OK"
 +         tool_tip="Save changes to profile and close"
 +         bottom_delta="0"
 +         left="10"
 +         height="20"
 +         width="90"
 +         follows="left|bottom"
 +         layout="topleft"
 +         visible="false"
 +        />
 +        <button
 +         name="cancel_btn"
 +         label="Cancel"
 +         bottom_delta="0"
 +         right="-10"
 +         height="20"
 +         width="90"
 +         follows="right|bottom"
 +         layout="topleft"
 +         label_selected="Cancel"
 +         visible="false"
 +        />
 +    </panel>
 +</floater>
 diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 42744b561f..c0ec3c37b7 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -63,8 +63,7 @@         label="Picks..."         name="Picks">          <menu_item_call.on_click -         function="Floater.ToggleOrBringToFront" -         parameter="picks" /> +         function="ShowAgentProfilePicks" />        </menu_item_call>        <menu_item_call          label="Experiences..." diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml new file mode 100644 index 0000000000..d08fdc8c7f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="group_list_item"
 + top="0"
 + left="0"
 + height="16"
 + width="320"
 + follows="top|right|left"
 + layout="topleft"
 +>
 +    <icon
 +     name="hovered_icon"
 +     top="0"
 +     left="0"
 +     height="16"
 +     width="320"
 +     follows="top|right|left"
 +     layout="topleft"
 +     image_name="ListItem_Over"
 +     visible="false"
 +    />
 +    <icon
 +     name="selected_icon"
 +     top="0"
 +     left="0"
 +     height="16"
 +     width="320"
 +     follows="top|right|left"
 +     layout="topleft"
 +     image_name="ListItem_Select"
 +     visible="false"
 +    />
 +    <group_icon
 +     name="group_icon"
 +     top="2"
 +     left="5"
 +     height="14"
 +     width="14"
 +     image_name="Generic_Group"
 +     mouse_opaque="true"
 +     use_draw_context_alpha="false"
 +    />
 +    <text
 +     name="group_name"
 +     value="Unknown"
 +     top="0"
 +     left_pad="5"
 +     right="-2"
 +     height="16"
 +     follows="left|right"
 +     layout="topleft"
 +     parse_urls="false"
 +     text_color="ScrollUnselectedColor"
 +     use_ellipses="true"
 +    />
 +    <button
 +     name="info_btn"
 +     tool_tip="More info"
 +     top_delta="-2"
 +     left_pad="3"
 +     right="-31"
 +     height="16"
 +     width="16"
 +     follows="right"
 +     image_pressed="Info_Press"
 +     image_unselected="Info_Over"
 +     tab_stop="false"
 +    />
 +    <!--*TODO: Should only appear on rollover-->
 +    <button
 +     name="profile_btn"
 +     tool_tip="View profile"
 +     top_delta="-2"
 +     left_pad="5"
 +     right="-3"
 +     height="20"
 +     width="20"
 +     follows="right"
 +     layout="topleft"
 +     image_overlay="Web_Profile_Off"
 +     tab_stop="false"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_me.xml b/indra/newview/skins/default/xui/en/panel_me.xml deleted file mode 100644 index 23e7814cad..0000000000 --- a/indra/newview/skins/default/xui/en/panel_me.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - border="false" - follows="all" - height="570" - label="My Profile" - layout="topleft" - left="0" - name="panel_me" - top="0" - width="333"> -    <panel -        class="panel_picks" -        filename="panel_picks.xml" -        label="MY PICKS" -        help_topic="panel_my_picks_tab" -        name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_classified.xml b/indra/newview/skins/default/xui/en/panel_profile_classified.xml new file mode 100644 index 0000000000..291a67ffba --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classified.xml @@ -0,0 +1,711 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile_classified"
 + top="0"
 + left="0"
 + height="420"
 + width="325"
 + follows="all"
 + layout="topleft"
 + help_topic="panel_profile_classified"
 + min_height="350"
 +>
 +    <panel.string
 +     name="type_mature"
 +    >
 +        Moderate
 +    </panel.string>
 +    <panel.string
 +     name="type_pg"
 +    >
 +        General Content
 +    </panel.string>
 +    <panel.string
 +     name="l$_price"
 +    >
 +        L$[PRICE]
 +    </panel.string>
 +    <panel.string
 +     name="click_through_text_fmt"
 +    >
 +        [TELEPORT] teleport, [MAP] map, [PROFILE] profile
 +    </panel.string>
 +    <panel.string
 +     name="date_fmt"
 +    >
 +        [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]
 +    </panel.string>
 +    <panel.string
 +     name="auto_renew_on"
 +    >
 +        Enabled
 +    </panel.string>
 +    <panel.string
 +     name="auto_renew_off"
 +    >
 +        Disabled
 +    </panel.string>
 +    <panel.string
 +     name="location_notice"
 +    >
 +        (will update after save)
 +    </panel.string>
 +    <string
 +     name="publish_label"
 +    >
 +        Publish
 +    </string>
 +    <string
 +     name="save_label"
 +    >
 +        Save
 +    </string>
 +    <scroll_container
 +     name="profile_scroll"
 +     top="0"
 +     left="0"
 +     bottom="-45"
 +     width="320"
 +     follows="all"
 +     layout="topleft"
 +     color="DkGray2"
 +     opaque="true"
 +     reserve_scroll_corner="false"
 +    >
 +        <panel
 +         name="info_scroll_content_panel"
 +         top="0"
 +         left="0"
 +         height="570"
 +         width="290"
 +         follows="left|top"
 +         layout="topleft"
 +         background_visible="false"
 +         min_height="300"
 +        >
 +            <texture_picker
 +             name="classified_snapshot"
 +             enabled="false"
 +             top="0"
 +             left="10"
 +             height="197"
 +             width="275"
 +             follows="left|top|right"
 +             layout="topleft"
 +             fallback_image="default_land_picture.j2c"
 +            />
 +            <icon
 +             name="edit_icon"
 +             label=""
 +             tool_tip="Click to select an image"
 +             top="0"
 +             left="0"
 +             height="197"
 +             width="272"
 +             layout="topleft"
 +             image_name="spacer24.tga"
 +             visible="false"
 +            />
 +            <panel
 +             name="info_panel"
 +             top="180"
 +             left="0"
 +             height="520"
 +             width="320"
 +             follows="all"
 +             layout="topleft"
 +             visible="true"
 +            >
 +                <text_editor
 +                 name="classified_name"
 +                 top="0"
 +                 left="10"
 +                 height="35"
 +                 width="280"
 +                 follows="left|top|right"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 font="SansSerifBig"
 +                 font.style="BOLD"
 +                 h_pad="0"
 +                 read_only="true"
 +                 text_color="white"
 +                 use_ellipses="true"
 +                 v_pad="0"
 +                >
 +                    [name]
 +                </text_editor>
 +                <text
 +                 name="classified_location_label"
 +                 value="Location:"
 +                 top_pad="-2"
 +                 left="10"
 +                 height="10"
 +                 width="250"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <text_editor
 +                 name="classified_location"
 +                 value="[loading...]"
 +                 top_pad="5"
 +                 left="10"
 +                 height="30"
 +                 width="290"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 h_pad="0"
 +                 read_only="true"
 +                 v_pad="0"
 +                 word_wrap="true"
 +                />
 +                <text
 +                 name="content_type_label"
 +                 value="Content Type:"
 +                 top_pad="10"
 +                 left="10"
 +                 height="10"
 +                 width="140"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <icon
 +                 name="content_type_moderate"
 +                 top_pad="-11"
 +                 left_pad="0"
 +                 height="16"
 +                 width="18"
 +                 follows="top|left"
 +                 layout="topleft"
 +                 image_name="Parcel_M_Light"
 +                />
 +                <icon
 +                 name="content_type_general"
 +                 top_delta="0"
 +                 left_delta="0"
 +                 height="16"
 +                 width="18"
 +                 follows="top|left"
 +                 layout="topleft"
 +                 image_name="Parcel_PG_Light"
 +                />
 +                <text_editor
 +                 name="content_type"
 +                 value="[content type]"
 +                 top_delta="1"
 +                 left_pad="2"
 +                 height="18"
 +                 width="130"
 +                 follows="left|top|right"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 h_pad="0"
 +                 read_only="true"
 +                 v_pad="0"
 +                />
 +                <text
 +                 name="category_label"
 +                 value="Category:"
 +                 top_pad="0"
 +                 left="10"
 +                 height="10"
 +                 width="140"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <text_editor
 +                 name="category"
 +                 value="[category]"
 +                 top_pad="-10"
 +                 left_pad="0"
 +                 height="18"
 +                 width="150"
 +                 follows="left|top|right"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 h_pad="0"
 +                 parse_urls="true"
 +                 read_only="true"
 +                 v_pad="0"
 +                />
 +                <text
 +                 name="creation_date_label"
 +                 value="Creation date:"
 +                 top_pad="0"
 +                 left="10"
 +                 height="10"
 +                 width="140"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <text_editor
 +                 name="creation_date"
 +                 value="[date]"
 +                 tool_tip="Creation date"
 +                 top_pad="-10"
 +                 left_pad="0"
 +                 height="16"
 +                 width="150"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 h_pad="0"
 +                 halign="left"
 +                 read_only="true"
 +                 v_pad="0"
 +                />
 +                <text
 +                 name="price_for_listing_label"
 +                 value="Price for listing:"
 +                 top_pad="5"
 +                 left="10"
 +                 height="10"
 +                 width="140"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <text_editor
 +                 name="price_for_listing"
 +                 tool_tip="Price for listing."
 +                 top_pad="-10"
 +                 left_pad="0"
 +                 height="16"
 +                 width="105"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 allow_scroll="false"
 +                 bg_visible="false"
 +                 h_pad="0"
 +                 halign="left"
 +                 read_only="true"
 +                 v_pad="0"
 +                >
 +                    [PRICE]
 +                </text_editor>
 +                <layout_stack
 +                 name="descr_stack"
 +                 top_pad="5"
 +                 left="10"
 +                 height="215"
 +                 width="290"
 +                 follows="all"
 +                 layout="topleft"
 +                 animate="false"
 +                 orientation="vertical"
 +                >
 +                    <layout_panel
 +                     name="clickthrough_layout_panel"
 +                     top="0"
 +                     left="0"
 +                     height="16"
 +                     width="290"
 +                     follows="all"
 +                     layout="topleft"
 +                     auto_resize="false"
 +                    >
 +                        <text
 +                         name="click_through_label"
 +                         value="Clicks:"
 +                         top_pad="0"
 +                         left="0"
 +                         height="10"
 +                         width="140"
 +                         follows="left|top"
 +                         layout="topleft"
 +                         font.style="BOLD"
 +                         text_color="white"
 +                        />
 +                        <text_editor
 +                         name="click_through_text"
 +                         value="[clicks]"
 +                         tool_tip="Click through data"
 +                         top_pad="-10"
 +                         left_pad="0"
 +                         height="16"
 +                         width="150"
 +                         follows="left|top"
 +                         layout="topleft"
 +                         allow_scroll="false"
 +                         bg_visible="false"
 +                         h_pad="0"
 +                         halign="left"
 +                         read_only="true"
 +                         v_pad="0"
 +                        />
 +                    </layout_panel>
 +                    <layout_panel
 +                     name="auto_renew_layout_panel"
 +                     top="0"
 +                     left="0"
 +                     height="16"
 +                     width="290"
 +                     follows="all"
 +                     layout="topleft"
 +                     auto_resize="false"
 +                    >
 +                        <text
 +                         name="auto_renew_label"
 +                         value="Auto renew:"
 +                         top="0"
 +                         left="0"
 +                         height="10"
 +                         width="140"
 +                         follows="left|top"
 +                         layout="topleft"
 +                         font.style="BOLD"
 +                         text_color="white"
 +                        />
 +                        <text
 +                         name="auto_renew"
 +                         value="Enabled"
 +                         top_pad="-10"
 +                         left_pad="0"
 +                         height="16"
 +                         width="150"
 +                         follows="top|left"
 +                         layout="topleft"
 +                        />
 +                    </layout_panel>
 +                    <layout_panel
 +                     name="descr_layout_panel"
 +                     top="0"
 +                     left="0"
 +                     height="220"
 +                     width="290"
 +                     follows="all"
 +                     layout="topleft"
 +                    >
 +                        <text
 +                         name="classified_desc_label"
 +                         value="Description:"
 +                         top="0"
 +                         left="0"
 +                         height="10"
 +                         width="250"
 +                         follows="left|top"
 +                         layout="topleft"
 +                         font.style="BOLD"
 +                         text_color="white"
 +                        />
 +                        <text_editor
 +                         name="classified_desc"
 +                         value="[description]"
 +                         top_pad="7"
 +                         left="0"
 +                         height="200"
 +                         width="280"
 +                         follows="all"
 +                         layout="topleft"
 +                         allow_scroll="true"
 +                         bg_visible="false"
 +                         h_pad="0"
 +                         max_length="1023"
 +                         parse_urls="true"
 +                         read_only="true"
 +                         v_pad="0"
 +                         word_wrap="true"
 +                        />
 +                    </layout_panel>
 +                </layout_stack>
 +            </panel>
 +            <panel
 +             name="edit_panel"
 +             top="180"
 +             left="0"
 +             height="420"
 +             width="320"
 +             follows="left|top|right"
 +             layout="topleft"
 +             visible="false"
 +            >
 +                <text
 +                 name="Name:"
 +                 top="0"
 +                 left="10"
 +                 height="15"
 +                 width="280"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font="SansSerifSmall"
 +                 font.style="BOLD"
 +                 length="1"
 +                 text_color="white"
 +                 type="string"
 +                >
 +                    Title:
 +                </text>
 +                <line_editor
 +                 name="classified_name_edit"
 +                 top_pad="2"
 +                 left="10"
 +                 height="20"
 +                 width="273"
 +                 follows="left|top|right"
 +                 layout="topleft"
 +                 font="SansSerif"
 +                 max_length_bytes="30"
 +                 prevalidate_callback="ascii"
 +                 text_color="black"
 +                />
 +                <text
 +                 name="description_label"
 +                 top_pad="10"
 +                 left="10"
 +                 height="15"
 +                 width="280"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font="SansSerifSmall"
 +                 font.style="BOLD"
 +                 length="1"
 +                 text_color="white"
 +                 type="string"
 +                >
 +                    Description:
 +                </text>
 +                <text_editor
 +                 name="classified_desc_edit"
 +                 top_pad="2"
 +                 left="10"
 +                 height="100"
 +                 width="273"
 +                 follows="left|top|right"
 +                 layout="topleft"
 +                 max_length="256"
 +                 text_color="black"
 +                 word_wrap="true"
 +                />
 +                <text
 +                 name="location_label"
 +                 top_pad="10"
 +                 left="10"
 +                 height="15"
 +                 width="280"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font="SansSerifSmall"
 +                 font.style="BOLD"
 +                 length="1"
 +                 text_color="white"
 +                 type="string"
 +                >
 +                    Location:
 +                </text>
 +                <text
 +                 name="classified_location_edit"
 +                 top_pad="2"
 +                 left="10"
 +                 right="-10"
 +                 height="30"
 +                 width="280"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 length="1"
 +                 type="string"
 +                 word_wrap="true"
 +                >
 +                    loading...
 +                </text>
 +                <button
 +                 name="set_to_curr_location_btn"
 +                 label="Set to Current Location"
 +                 top_pad="5"
 +                 left="10"
 +                 height="23"
 +                 width="200"
 +                 follows="left|top"
 +                 layout="topleft"
 +                />
 +                <text
 +                 name="category_label"
 +                 value="Category:"
 +                 top_pad="10"
 +                 left="10"
 +                 height="10"
 +                 width="120"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <combo_box
 +                 name="category_edit"
 +                 label=""
 +                 top_delta="-3"
 +                 left_pad="0"
 +                 height="23"
 +                 width="156"
 +                 follows="left|top"
 +                />
 +                <text
 +                 name="content_type_label"
 +                 value="Content type:"
 +                 top_pad="15"
 +                 left="10"
 +                 height="10"
 +                 width="120"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 font.style="BOLD"
 +                 text_color="white"
 +                />
 +                <icons_combo_box
 +                 name="content_type_edit"
 +                 label="General Content"
 +                 top_delta="-3"
 +                 left_pad="0"
 +                 height="23"
 +                 width="156"
 +                 follows="left|top"
 +                 layout="topleft"
 +                >
 +                    <icons_combo_box.drop_down_button
 +                     image_overlay="Parcel_PG_Light"
 +                     image_overlay_alignment="left"
 +                     imgoverlay_label_space="3"
 +                     pad_left="3"
 +                    />
 +                    <icons_combo_box.item
 +                     name="mature_ci"
 +                     label="Moderate Content"
 +                     value="Mature"
 +                    >
 +                        <item.columns
 +                         value="Parcel_M_Light"
 +                         width="20"
 +                         halign="center"
 +                         type="icon"
 +                        />
 +                    </icons_combo_box.item>
 +                    <icons_combo_box.item
 +                     name="pg_ci"
 +                     label="General Content"
 +                     value="PG"
 +                    >
 +                        <item.columns
 +                         value="Parcel_PG_Light"
 +                         width="20"
 +                         halign="center"
 +                         type="icon"
 +                        />
 +                    </icons_combo_box.item>
 +                </icons_combo_box>
 +                <check_box
 +                 name="auto_renew_edit"
 +                 label="Auto renew each week"
 +                 top_pad="10"
 +                 left="10"
 +                 height="16"
 +                 width="250"
 +                 layout="topleft"
 +                />
 +                <text
 +                 name="price_for_listing_edit_label"
 +                 value="Price for listing:"
 +                 top_pad="10"
 +                 left="10"
 +                 height="10"
 +                 width="120"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 text_color="white"
 +                />
 +                <spinner
 +                 name="price_for_listing_edit"
 +                 label="L$"
 +                 value="50"
 +                 tool_tip="Price for listing."
 +                 top_delta="0"
 +                 left_pad="0"
 +                 height="23"
 +                 width="105"
 +                 follows="left|top"
 +                 layout="topleft"
 +                 decimal_digits="0"
 +                 halign="left"
 +                 increment="1"
 +                 label_width="20"
 +                 max_val="99999"
 +                 min_val="50"
 +                />
 +            </panel>
 +        </panel>
 +    </scroll_container>
 +    <panel
 +     name="button_panel"
 +     bottom="-1"
 +     left="9"
 +     height="35"
 +     follows="left|right|bottom"
 +     layout="topleft"
 +    >
 +        <button
 +         name="teleport_btn"
 +         label="Teleport"
 +         top="0"
 +         left="0"
 +         height="23"
 +         width="101"
 +         follows="bottom|left|right"
 +         layout="topleft"
 +        />
 +        <button
 +         name="show_on_map_btn"
 +         label="Map"
 +         top="0"
 +         left_pad="5"
 +         height="23"
 +         width="100"
 +         follows="bottom|left|right"
 +         layout="topleft"
 +        />
 +        <button
 +         name="edit_btn"
 +         label="Edit"
 +         top="0"
 +         left_pad="5"
 +         height="23"
 +         width="101"
 +         follows="bottom|left|right"
 +         layout="topleft"
 +        />
 +        <button
 +         name="save_changes_btn"
 +         label="[LABEL]"
 +         top="0"
 +         left="0"
 +         height="23"
 +         width="155"
 +         follows="bottom|left|right"
 +         layout="topleft"
 +         visible="false"
 +        />
 +        <button
 +         name="cancel_btn"
 +         label="Cancel"
 +         top="0"
 +         left_pad="5"
 +         height="23"
 +         width="156"
 +         follows="bottom|left|right"
 +         layout="topleft"
 +         visible="false"
 +        />
 +    </panel>
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml new file mode 100644 index 0000000000..3c0ff2b10c --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile_classifieds"
 + label="Classified"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <string
 +     name="no_classifieds"
 +     value="No Classifieds"
 +    />
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="20"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <button
 +     name="new_btn"
 +     label="New..."
 +     enabled="false"
 +     top="25"
 +     left="5"
 +     height="20"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     visible="true"
 +    />
 +    <button
 +     name="delete_btn"
 +     label="Delete..."
 +     enabled="false"
 +     left_pad="5"
 +     height="20"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     visible="true"
 +    />
 +    <tab_container
 +     name="tab_classifieds"
 +     top="50"
 +     bottom="-5"
 +     left="4"
 +     right="-4"
 +     follows="all"
 +     layout="topleft"
 +     halign="left"
 +     tab_position="left"
 +     tab_width="85"
 +     use_ellipses="true"
 +    />
 +    <text
 +     name="classifieds_panel_text"
 +     top="300"
 +     left="110"
 +     right="-110"
 +     height="25"
 +     follows="left|top|right"
 +     layout="topleft"
 +     halign="center"
 +     mouse_opaque="false"
 +     wrap="true"
 +    >
 +        Loading...
 +    </text>
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml new file mode 100644 index 0000000000..91675900dc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile_firstlife"
 + label="Profile"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="5"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <texture_picker
 +     name="real_world_pic"
 +     enabled="false"
 +     top="10"
 +     left="6"
 +     height="225"
 +     width="275"
 +     follows="top|left"
 +     layout="topleft"
 +     allow_no_texture="true"
 +     default_image_name="None"
 +     fallback_image="Generic_Person_Large"
 +    />
 +    <text_editor
 +     name="fl_description_edit"
 +     enabled="false"
 +     top="225"
 +     left="6"
 +     right="-7"
 +     height="183"
 +     follows="all"
 +     layout="topleft"
 +     bg_readonly_color="Transparent"
 +     border_visible="true"
 +     max_length="253"
 +     parse_urls="true"
 +     word_wrap="true"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_interests.xml b/indra/newview/skins/default/xui/en/panel_profile_interests.xml new file mode 100644 index 0000000000..5a943ccf4d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_interests.xml @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile_interests"
 + label="Interests"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="5"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <text
 +     name="I Want To:"
 +     top="10"
 +     left="4"
 +     height="16"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    >
 +        I Want To:
 +    </text>
 +    <check_box
 +     name="chk0"
 +     label="Build"
 +     enabled="false"
 +     top_delta="0"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk1"
 +     label="Explore"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk2"
 +     label="Meet"
 +     enabled="false"
 +     top_pad="5"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk6"
 +     label="Be Hired"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk3"
 +     label="Group"
 +     enabled="false"
 +     top_pad="5"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk4"
 +     label="Buy"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk5"
 +     label="Sell"
 +     enabled="false"
 +     top_pad="5"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="chk7"
 +     label="Hire"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <line_editor
 +     name="want_to_edit"
 +     enabled="false"
 +     top_pad="10"
 +     left="76"
 +     height="18"
 +     width="330"
 +     follows="left|top|right"
 +     layout="topleft"
 +     text_pad_left="4"
 +     max_length_bytes="254"
 +    >
 +        (loading...)
 +    </line_editor>
 +
 +    <text
 +     name="Skills:"
 +     top_pad="20"
 +     left="4"
 +     height="16"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    >
 +        Skills:
 +    </text>
 +    <check_box
 +     name="schk0"
 +     label="Textures"
 +     enabled="false"
 +     top_delta="0"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="schk1"
 +     label="Architecture"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <!-- The next two are out of order on purpose due to legacy ordering -->
 +    <check_box
 +     name="schk3"
 +     label="Modeling"
 +     enabled="false"
 +     top_pad="5"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="schk2"
 +     label="Event Planning"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="schk4"
 +     label="Scripting"
 +     enabled="false"
 +     top_pad="5"
 +     left="75"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="schk5"
 +     label="Custom Characters"
 +     enabled="false"
 +     left_pad="80"
 +     height="16"
 +     width="90"
 +     follows="left|top"
 +     layout="topleft"
 +    />
 +    <line_editor
 +     name="skills_edit"
 +     enabled="false"
 +     top_pad="10"
 +     left="76"
 +     height="18"
 +     width="330"
 +     follows="left|top|right"
 +     layout="topleft"
 +     text_pad_left="4"
 +     max_length_bytes="254"
 +    >
 +        (loading...)
 +    </line_editor>
 +
 +    <text
 +     name="Languages:"
 +     top_pad="20"
 +     left="4"
 +     height="16"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    >
 +        Languages:
 +    </text>
 +    <line_editor
 +     name="languages_edit"
 +     enabled="false"
 +     top_delta="-1"
 +     left="76"
 +     height="18"
 +     width="330"
 +     follows="left|top|right"
 +     layout="topleft"
 +     text_pad_left="4"
 +     max_length_bytes="254"
 +    >
 +        (loading...)
 +    </line_editor>
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_notes.xml b/indra/newview/skins/default/xui/en/panel_profile_notes.xml new file mode 100644 index 0000000000..1be7edbcea --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_notes.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_notes"
 + label="Notes & Privacy"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="3"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <text
 +     name="status_message"
 +     value="Private notes on this avatar:"
 +     top="6"
 +     left="6"
 +     right="-6"
 +     height="16"
 +     follows="left|top|right"
 +     layout="topleft"
 +     font.style="BOLD"
 +    />
 +    <text_editor
 +     name="notes_edit"
 +     enabled="false"
 +     top_pad="4"
 +     left="6"
 +     right="-6"
 +     height="335"
 +     follows="all"
 +     layout="topleft"
 +     max_length="1000"
 +     word_wrap="true"
 +    />
 +    <text
 +     name="status_message2"
 +     value="Allow this avatar to:"
 +     top_pad="8"
 +     left="6"
 +     right="-6"
 +     height="16"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +     font.style="BOLD"
 +    />
 +    <check_box
 +     name="status_check"
 +     label="See when I am online"
 +     enabled="false"
 +     left="10"
 +     height="16"
 +     width="293"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="map_check"
 +     label="Find me on the world map"
 +     enabled="false"
 +     left="10"
 +     height="16"
 +     width="293"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +    />
 +    <check_box
 +     name="objects_check"
 +     label="Edit, delete or take my objects"
 +     enabled="false"
 +     left="10"
 +     height="16"
 +     width="293"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_pick.xml b/indra/newview/skins/default/xui/en/panel_profile_pick.xml new file mode 100644 index 0000000000..40f3f83320 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_pick.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_pick_info"
 + top="0"
 + left="0"
 + height="360"
 + width="310"
 + follows="all"
 + layout="topleft"
 + help_topic="profile_pick_info"
 +>
 +    <panel.string
 +     name="location_notice"
 +    >
 +        (will update after save)
 +    </panel.string>
 +    <texture_picker
 +     name="pick_snapshot"
 +     top="10"
 +     left="10"
 +     height="180"
 +     width="290"
 +     follows="left|right|top"
 +     layout="topleft"
 +     fallback_image="default_land_picture.j2c"
 +    />
 +    <line_editor
 +     name="pick_name"
 +     enabled="false"
 +     top_pad="-15"
 +     left="10"
 +     height="20"
 +     width="290"
 +     follows="left|right|top"
 +     layout="topleft"
 +    />
 +    <text_editor
 +     name="pick_desc"
 +     enabled="false"
 +     top_pad="8"
 +     left="10"
 +     height="70"
 +     width="290"
 +     follows="all"
 +     layout="topleft"
 +     allow_html="true"
 +     border_visible="true"
 +     h_pad="4"
 +     max_length="1023"
 +     v_pad="3"
 +     word_wrap="true"
 +    />
 +    <line_editor
 +     name="pick_location"
 +     enabled="false"
 +     left="10"
 +     height="20"
 +     width="290"
 +     follows="left|right|bottom"
 +     layout="topleft"
 +     length="1"
 +     type="string"
 +    >
 +        Loading...
 +    </line_editor>
 +    <button
 +     name="teleport_btn"
 +     label="Teleport"
 +     bottom="-40"
 +     left="10"
 +     height="20"
 +     width="80"
 +     follows="left|bottom"
 +     layout="topleft"
 +    />
 +    <button
 +     name="show_on_map_btn"
 +     label="Show on Map"
 +     bottom_delta="0"
 +     left_pad="5"
 +     height="20"
 +     width="100"
 +     follows="left|bottom"
 +     layout="topleft"
 +    />
 +    <button
 +     name="set_to_curr_location_btn"
 +     label="Set Location"
 +     tool_tip="Set to Current Location"
 +     bottom_delta="0"
 +     left_pad="5"
 +     height="20"
 +     width="100"
 +     follows="left|bottom"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <button
 +     name="save_changes_btn"
 +     label="Save Pick"
 +     bottom="-15"
 +     left="10"
 +     height="20"
 +     width="100"
 +     follows="left|bottom"
 +     layout="topleft"
 +     visible="false"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_picks.xml b/indra/newview/skins/default/xui/en/panel_profile_picks.xml new file mode 100644 index 0000000000..7d0bb16b16 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_picks.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_picks"
 + label="Picks"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <string
 +     name="no_picks"
 +     value="No Picks"
 +    />
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="20"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <text
 +     name="Tell everyone about your favorite places in Second Life."
 +     top="5"
 +     left="5"
 +     right="-5"
 +     height="16"
 +     follows="left|top|right"
 +     layout="topleft"
 +     halign="center"
 +    >
 +        Tell everyone about your favorite places in Second Life.
 +    </text>
 +    <button
 +     name="new_btn"
 +     label="New..."
 +     enabled="false"
 +     top_pad="4"
 +     left="5"
 +     height="20"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <button
 +     name="delete_btn"
 +     label="Delete..."
 +     enabled="false"
 +     left_pad="5"
 +     height="20"
 +     width="70"
 +     follows="left|top"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <tab_container
 +     name="tab_picks"
 +     top="50"
 +     bottom="-5"
 +     left="4"
 +     right="-4"
 +     follows="all"
 +     layout="topleft"
 +     halign="left"
 +     tab_position="left"
 +     use_ellipses="true"
 +    />
 +    <text
 +     name="picks_panel_text"
 +     top="300"
 +     left="110"
 +     right="-110"
 +     height="25"
 +     follows="left|top|right"
 +     layout="topleft"
 +     halign="center"
 +     mouse_opaque="false"
 +     wrap="true"
 +    >
 +        Loading...
 +    </text>
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml new file mode 100644 index 0000000000..73c25a770c --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -0,0 +1,469 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile"
 + label="Profile"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <string
 +     name="status_online"
 +    >
 +        Currently Online
 +    </string>
 +    <string
 +     name="status_offline"
 +    >
 +        Currently Offline
 +    </string>
 +    <string
 +     name="CaptionTextAcctInfo"
 +    >
 +       [ACCTTYPE]
 +[PAYMENTINFO]
 +    </string>
 +    <string
 +     name="payment_update_link_url"
 +    >
 +        http://www.secondlife.com/account/billing.php?lang=en
 +    </string>
 +    <string
 +     name="partner_edit_link_url"
 +    >
 +        http://www.secondlife.com/account/partners.php?lang=en
 +    </string>
 +    <string
 +     name="my_account_link_url"
 +     value="http://secondlife.com/account"
 +    />
 +    <string
 +     name="no_partner_text"
 +     value="None"
 +    />
 +    <string
 +     name="no_group_text"
 +     value="None"
 +    />
 +    <string
 +     name="RegisterDateFormat"
 +    >
 +        [REG_DATE]
 +    </string>
 +    <string
 +     name="name_text_args"
 +    >
 +        [NAME]
 +    </string>
 +    <string
 +     name="display_name_text_args"
 +    >
 +        [DISPLAY_NAME]
 +    </string>
 +    <string
 +     name="FSDev"
 +     value=" Developer"
 +    />
 +    <string
 +     name="FSSupp"
 +     value=" Support"
 +    />
 +    <string
 +     name="FSQualityAssurance"
 +     value=" Bug Hunter"
 +    />
 +    <string
 +     name="FSGW"
 +     value=" Gateway"
 +    />
 +    <loading_indicator
 +     name="progress_indicator"
 +     top="4"
 +     right="-10"
 +     height="23"
 +     width="23"
 +     follows="top|right"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <text
 +     name="name_label"
 +     value="Name:"
 +     top="8"
 +     left="6"
 +     height="20"
 +     width="55"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    />
 +    <button
 +     name="set_name"
 +     label="Name:"
 +     tool_tip="Set Display Name"
 +     enabled="false"
 +     top_delta="0"
 +     left_delta="0"
 +     height="20"
 +     width="55"
 +     follows="top|left"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <text_editor
 +     name="complete_name"
 +     value="(loading...)"
 +     enabled="false"
 +     top_delta="0"
 +     left_pad="4"
 +     right="-6"
 +     height="20"
 +     follows="left|top|right"
 +     layout="topleft"
 +     allow_scroll="false"
 +     bg_visible="false"
 +     border_visible="true"
 +     h_pad="1"
 +     v_pad="2"
 +     max_length="254"
 +    />
 +    <texture_picker
 +     name="2nd_life_pic"
 +     enabled="false"
 +     top_pad="6"
 +     left_delta="0"
 +     height="180"
 +     width="220"
 +     follows="top|left"
 +     layout="topleft"
 +     allow_no_texture="true"
 +     default_image_name="None"
 +     fallback_image="Generic_Person_Large"
 +    />
 +    <text
 +     name="status"
 +     value="Status Unknown"
 +     top_delta="1"
 +     left_pad="4"
 +     right="-6"
 +     height="16"
 +     follows="top|left"
 +     layout="topleft"
 +     halign="center"
 +     text_color="LtGray_50"
 +    />
 +    <text
 +     name="label"
 +     value="Second Life Birthdate:"
 +     top_pad="2"
 +     right="-6"
 +     height="16"
 +     follows="top|left"
 +     layout="topleft"
 +    />
 +    <text_editor
 +     name="register_date"
 +     value="(loading...)"
 +     top_pad="0"
 +     left_delta="2"
 +     right="-6"
 +     height="16"
 +     follows="top|left|right"
 +     layout="topleft"
 +     allow_scroll="false"
 +     bg_visible="false"
 +     border_visible="true"
 +     h_pad="2"
 +     max_length="254"
 +     read_only="true"
 +     translate="false"
 +     v_pad="2"
 +     word_wrap="true"
 +    />
 +    <text
 +     name="label2"
 +     value="Account:"
 +     top_pad="5"
 +     left_delta="-2"
 +     right="-6"
 +     height="16"
 +     follows="top|left"
 +     layout="topleft"
 +    />
 +    <text_editor
 +     name="acc_status_text"
 +     top_pad="0"
 +     left_delta="2"
 +     right="-6"
 +     height="44"
 +     follows="top|left|right"
 +     layout="topleft"
 +     allow_scroll="false"
 +     bg_visible="false"
 +     border_visible="true"
 +     h_pad="2"
 +     read_only="true"
 +     translate="false"
 +     v_pad="2"
 +     word_wrap="true"
 +    />
 +    <text
 +     name="partner_label"
 +     value="Partner:"
 +     top_pad="5"
 +     left_delta="-2"
 +     right="-6"
 +     height="16"
 +     follows="top|left"
 +     layout="topleft"
 +    />
 +    <text_editor
 +     name="partner_text"
 +     top_pad="0"
 +     left_delta="0"
 +     right="-6"
 +     height="20"
 +     follows="top|left|right"
 +     layout="topleft"
 +     allow_scroll="false"
 +     bg_visible="false"
 +     border_visible="true"
 +     parse_urls="true"
 +     h_pad="0"
 +     read_only="true"
 +     translate="false"
 +     v_pad="2"
 +     max_length="254"
 +    />
 +    <text
 +     name="Groups:"
 +     value="Groups:"
 +     top_pad="8"
 +     left="6"
 +     height="16"
 +     width="55"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    />
 +    <button
 +     name="group_invite"
 +     label="+"
 +     tool_tip="Invite to Group"
 +     top_delta="20"
 +     left="40"
 +     height="20"
 +     width="20"
 +     follows="left|top"
 +     layout="topleft"
 +     label_selected="+"
 +    />
 +    <group_list
 +     name="group_list"
 +     top_delta="-20"
 +     left="66"
 +     right="-6"
 +     height="80"
 +     follows="left|top|right"
 +     layout="topleft"
 +     border_visible="true"
 +     color="ScrollBgWriteableColor"
 +     for_agent="false"
 +    />
 +    <text
 +     name="About:"
 +     value="About:"
 +     top_pad="8"
 +     left="6"
 +     height="16"
 +     width="55"
 +     follows="left|top"
 +     layout="topleft"
 +     halign="right"
 +    />
 +    <text_editor
 +     name="sl_description_edit"
 +     enabled="false"
 +     top_delta="0"
 +     left="66"
 +     right="-7"
 +     height="100"
 +     follows="all"
 +     layout="topleft"
 +     bg_readonly_color="Transparent"
 +     border_visible="true"
 +     font="SansSerifSmall"
 +     h_pad="2"
 +     max_length="510"
 +     parse_urls="true"
 +     word_wrap="true"
 +    />
 +    <text
 +     name="Give item:"
 +     value="Give item:"
 +     top_pad="10"
 +     left="6"
 +     height="16"
 +     width="55"
 +     follows="left|bottom"
 +     layout="topleft"
 +     halign="right"
 +    />
 +    <view_border
 +     name="drop_target_rect_vis"
 +     top_delta="0"
 +     left="66"
 +     right="-6"
 +     height="16"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +     bevel_style="in"
 +    />
 +    <text
 +     name="Give inventory"
 +     tool_tip="Drop inventory items here to give them to this person."
 +     top_delta="0"
 +     left="66"
 +     right="-6"
 +     height="16"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +     halign="center"
 +    >
 +        Drop inventory item here.
 +    </text>
 +    <layout_stack
 +     name="buttonstack"
 +     bottom="-3"
 +     left="6"
 +     right="-6"
 +     height="44"
 +     follows="left|bottom|right"
 +     layout="topleft"
 +     orientation="horizontal"
 +    >
 +        <layout_panel
 +         name="left_buttonstack"
 +         left="2"
 +         right="-2"
 +         height="42"
 +         follows="all"
 +         layout="topleft"
 +         user_resize="false"
 +        >
 +            <button
 +             name="show_on_map_btn"
 +             label="Find on Map"
 +             tool_tip="Locate the Resident on the map"
 +             top="2"
 +             left="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +             label_selected="Find on Map"
 +            />
 +            <button
 +             name="pay"
 +             label="Pay"
 +             tool_tip="Pay money to the Resident"
 +             top_pad="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +             label_selected="Pay"
 +            />
 +        </layout_panel>
 +        <layout_panel
 +         name="middle_buttonstack"
 +         left="2"
 +         right="-2"
 +         follows="all"
 +         layout="topleft"
 +         user_resize="false"
 +        >
 +            <button
 +             name="teleport"
 +             label="Offer Teleport"
 +             tool_tip="Offer a teleport to the Resident"
 +             top="2"
 +             left="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +             label_selected="Offer Teleport"
 +            />
 +            <button
 +             name="im"
 +             label="Instant Message"
 +             tool_tip="Open instant message session"
 +             top_pad="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +             label_selected="Instant Message"
 +            />
 +        </layout_panel>
 +        <layout_panel
 +         name="right_buttonstack"
 +         left="2"
 +         right="-2"
 +         follows="all"
 +         layout="topleft"
 +         user_resize="false"
 +        >
 +            <button
 +             name="add_friend"
 +             label="Add Friend"
 +             tool_tip="Offer friendship to the Resident"
 +             top="2"
 +             left="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +             label_selected="Add Friend"
 +            />
 +            <button
 +             name="block"
 +             label="Block"
 +             tool_tip="Block this Resident"
 +             top_pad="2"
 +             height="20"
 +             follows="left|top|right"
 +             layout="topleft"
 +            />
 +            <button
 +             name="unblock"
 +             label="Unblock"
 +             tool_tip="Unblock this Resident"
 +             top_delta="0"
 +             right="-40"
 +             follows="left|top|right"
 +             layout="topleft"
 +            />
 +        </layout_panel>
 +    </layout_stack>
 +    <check_box
 +     name="show_in_search_checkbox"
 +     label="Show in search"
 +     enabled="false"
 +     bottom="-30"
 +     left="60"
 +     height="16"
 +     width="130"
 +     follows="left|bottom"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <profile_drop_target
 +     name="drop_target"
 +     top="0"
 +     bottom="-1"
 +     left="0"
 +     right="-1"
 +     follows="all"
 +     layout="topleft"
 +     mouse_opaque="false"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_profile_web.xml b/indra/newview/skins/default/xui/en/panel_profile_web.xml new file mode 100644 index 0000000000..265de3d1b6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_web.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel
 + name="panel_profile_web"
 + label="Web"
 + top="0"
 + left="0"
 + height="480"
 + width="420"
 + follows="all"
 + layout="topleft"
 +>
 +    <panel.string
 +     name="LoadTime"
 +     value="Load Time: [TIME] seconds"
 +    />
 +    <line_editor
 +     name="url_edit"
 +     enabled="false"
 +     top_pad="5"
 +     left="10"
 +     height="16"
 +     width="400"
 +     follows="left|top"
 +     layout="topleft"
 +     text_pad_left="4"
 +     max_length_bytes="254"
 +    >
 +        (loading..)
 +    </line_editor>
 +    <flyout_button
 +     name="load"
 +     label="Load"
 +     tool_tip="Load this profile page with embedded web browser."
 +     enabled="false"
 +     top_pad="5"
 +     left="10"
 +     height="18"
 +     width="80"
 +     follows="left|top"
 +     layout="topleft"
 +    >
 +        <flyout_button.item
 +         name="open_item"
 +         label="Open in-viewer browser"
 +         value="popout"
 +        />
 +        <flyout_button.item
 +         name="home_item"
 +         label="Open external browser"
 +         value="external"
 +        />
 +    </flyout_button>
 +    <loading_indicator
 +     name="progress_indicator"
 +     left_pad="100"
 +     height="23"
 +     width="23"
 +     follows="top|left"
 +     layout="topleft"
 +     visible="false"
 +    />
 +    <button
 +     name="web_profile_popout_btn"
 +     top_delta="5"
 +     right="-10"
 +     height="16"
 +     width="16"
 +     follows="right|top"
 +     layout="topleft"
 +     image_overlay="tearoffbox.tga"
 +     tool_tip="Popout web profile"
 +    />
 +    <web_browser
 +     name="profile_html"
 +     top="48"
 +     bottom="-18"
 +     left="10"
 +     right="-10"
 +     follows="all"
 +     layout="topleft"
 +     start_url=""
 +    />
 +    <text
 +     name="status_text"
 +     bottom="-4"
 +     left="110"
 +     right="-110"
 +     follows="bottom|left|right"
 +     layout="topleft"
 +     halign="center"
 +    />
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f5f4b4acab..2967fb5103 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2773,10 +2773,14 @@ If you continue to receive this message, please contact Second Life support for  	<string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>  	<string name="ClassifiedUpdateAfterPublish">(will update after publish)</string> -  <!-- panel picks --> -  <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> -  <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> -  <string name="PicksClassifiedsLoadingText">Loading...</string> +    <!-- panel picks --> +    <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> +    <string name="NoPicksText">You haven't created any Picks. Click the New button to create a Pick.</string> +    <string name="NoClassifiedsText">You haven't created any Classifieds. Click the New button to create a Classified.</string> +    <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> +    <string name="NoAvatarPicksText">User has no picks</string> +    <string name="NoAvatarClassifiedsText">User has no classifieds</string> +    <string name="PicksClassifiedsLoadingText">Loading...</string>  	<!-- Multi Preview Floater -->  	<string name="MultiPreviewTitle">Preview</string> diff --git a/indra/newview/skins/default/xui/es/floater_picks.xml b/indra/newview/skins/default/xui/es/floater_picks.xml deleted file mode 100644 index 255aa5dcdc..0000000000 --- a/indra/newview/skins/default/xui/es/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destacados"/> diff --git a/indra/newview/skins/default/xui/es/panel_me.xml b/indra/newview/skins/default/xui/es/panel_me.xml deleted file mode 100644 index 850cd6ec71..0000000000 --- a/indra/newview/skins/default/xui/es/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mi perfil" name="panel_me"> -	<panel label="MIS DESTACADOS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/fr/floater_picks.xml b/indra/newview/skins/default/xui/fr/floater_picks.xml deleted file mode 100644 index f058ff668b..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Favoris"/> diff --git a/indra/newview/skins/default/xui/fr/panel_me.xml b/indra/newview/skins/default/xui/fr/panel_me.xml deleted file mode 100644 index 5676986228..0000000000 --- a/indra/newview/skins/default/xui/fr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mon profil" name="panel_me"> -	<panel label="MES FAVORIS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/it/floater_picks.xml b/indra/newview/skins/default/xui/it/floater_picks.xml deleted file mode 100644 index dfc539da66..0000000000 --- a/indra/newview/skins/default/xui/it/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Preferiti"/> diff --git a/indra/newview/skins/default/xui/it/panel_me.xml b/indra/newview/skins/default/xui/it/panel_me.xml deleted file mode 100644 index a134f6f1de..0000000000 --- a/indra/newview/skins/default/xui/it/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Il mio profilo" name="panel_me"> -	<panel label="I MIEI PREFERITI" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ja/floater_picks.xml b/indra/newview/skins/default/xui/ja/floater_picks.xml deleted file mode 100644 index 359585eb86..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="ピック"/> diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml deleted file mode 100644 index 3df1ae8048..0000000000 --- a/indra/newview/skins/default/xui/ja/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="マイ プロフィール" name="panel_me"> -	<panel label="マイ-ピック" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/pl/floater_picks.xml b/indra/newview/skins/default/xui/pl/floater_picks.xml deleted file mode 100644 index a329e834db..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<floater name="floater_picks" title="Miejsca" /> diff --git a/indra/newview/skins/default/xui/pl/panel_me.xml b/indra/newview/skins/default/xui/pl/panel_me.xml deleted file mode 100644 index 431929420a..0000000000 --- a/indra/newview/skins/default/xui/pl/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel label="Mój Profil" name="panel_me"> -	<panel label="MIEJSCA" name="panel_picks" /> -</panel> diff --git a/indra/newview/skins/default/xui/pt/floater_picks.xml b/indra/newview/skins/default/xui/pt/floater_picks.xml deleted file mode 100644 index 9766196319..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destaques"/> diff --git a/indra/newview/skins/default/xui/pt/panel_me.xml b/indra/newview/skins/default/xui/pt/panel_me.xml deleted file mode 100644 index 281c886bd4..0000000000 --- a/indra/newview/skins/default/xui/pt/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Meu perfil" name="panel_me"> -	<panel label="MEUS DESTAQUES" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ru/floater_picks.xml b/indra/newview/skins/default/xui/ru/floater_picks.xml deleted file mode 100644 index e0ae8d6f03..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Подборка"/> diff --git a/indra/newview/skins/default/xui/ru/panel_me.xml b/indra/newview/skins/default/xui/ru/panel_me.xml deleted file mode 100644 index 21a125af87..0000000000 --- a/indra/newview/skins/default/xui/ru/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Мой профиль" name="panel_me"> -	<panel label="МОЯ ПОДБОРКА" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/tr/floater_picks.xml b/indra/newview/skins/default/xui/tr/floater_picks.xml deleted file mode 100644 index 513a2e319a..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Seçmeler"/> diff --git a/indra/newview/skins/default/xui/tr/panel_me.xml b/indra/newview/skins/default/xui/tr/panel_me.xml deleted file mode 100644 index 4b911c9ce6..0000000000 --- a/indra/newview/skins/default/xui/tr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Profilim" name="panel_me"> -	<panel label="SEÇMELERİM" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/zh/floater_picks.xml b/indra/newview/skins/default/xui/zh/floater_picks.xml deleted file mode 100644 index a8bfcd99e3..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="精選地點"/> diff --git a/indra/newview/skins/default/xui/zh/panel_me.xml b/indra/newview/skins/default/xui/zh/panel_me.xml deleted file mode 100644 index aad1348e46..0000000000 --- a/indra/newview/skins/default/xui/zh/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="我的個人檔案" name="panel_me"> -	<panel label="我的精選地點" name="panel_picks"/> -</panel>  | 
