Skip to content
Snippets Groups Projects
llpanelprofile.cpp 43.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Kadah_Coba's avatar
    Kadah_Coba committed
    /**
    
    * @file llpanelprofile.cpp
    * @brief Profile panel implementation
    *
    
    * $LicenseInfo:firstyear=2009&license=viewerlgpl$
    
    * 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 "llpanelprofile.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    // 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"
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    #include "llavataractions.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    #include "llavatarpropertiesprocessor.h"
    #include "llcallingcard.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    #include "llfloaterreg.h"
    #include "llfirstuse.h"
    #include "llgroupactions.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    #include "llnotificationsutil.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    #include "llpanelprofileclassifieds.h"
    #include "llpanelprofilepicks.h"
    #include "lltrans.h"
    #include "llviewercontrol.h"
    #include "llvoiceclient.h"
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    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
    {
    public:
    	// requires trusted browser to trigger
    	LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { }
    
    	bool handle(const LLSD& params, const LLSD& query_map,
    		LLMediaCtrl* web)
    	{
    		if (params.size() < 1) return false;
    		std::string agent_name = params[0];
    
    		LL_INFOS() << "Profile, agent_name " << agent_name << LL_ENDL;
    
    		std::string url = getProfileURL(agent_name);
    
    		LLWeb::loadURLInternal(url);
    
    
    		return true;
    	}
    };
    LLProfileHandler gProfileHandler;
    
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    
    //////////////////////////////////////////////////////////////////////////
    // LLAgentHandler
    
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    class LLAgentHandler : public LLCommandHandler
    {
    public:
    	// requires trusted browser to trigger
    
    	LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    
    	bool handle(const LLSD& params, const LLSD& query_map,
    
    		LLMediaCtrl* web)
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    	{
    		if (params.size() < 2) return false;
    
    		LLUUID avatar_id;
    		if (!avatar_id.set(params[0], FALSE))
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    		{
    			return false;
    		}
    
    
    		const std::string verb = params[1].asString();
    		if (verb == "about")
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    		{
    
    			LLAvatarActions::showProfile(avatar_id);
    			return true;
    		}
    
    
    			LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id));
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    			return true;
    		}
    
    
    		if (verb == "im")
    		{
    			LLAvatarActions::startIM(avatar_id);
    			return true;
    		}
    
    		if (verb == "pay")
    		{
    
    			if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarPay"))
    			{
    				LLNotificationsUtil::add("NoAvatarPay", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
    				return true;
    			}
    
    
    			LLAvatarActions::pay(avatar_id);
    			return true;
    		}
    
    		if (verb == "offerteleport")
    		{
    			LLAvatarActions::offerTeleport(avatar_id);
    			return true;
    		}
    
    		if (verb == "requestfriend")
    		{
    			LLAvatarActions::requestFriendshipDialog(avatar_id);
    			return true;
    		}
    
    
    		if (verb == "removefriend")
    		{
    			LLAvatarActions::removeFriendDialog(avatar_id);
    			return true;
    		}
    
    
    		if (verb == "mute")
    		{
    			if (! LLAvatarActions::isBlocked(avatar_id))
    			{
    				LLAvatarActions::toggleBlock(avatar_id);
    			}
    			return true;
    		}
    
    		if (verb == "unmute")
    		{
    			if (LLAvatarActions::isBlocked(avatar_id))
    			{
    				LLAvatarActions::toggleBlock(avatar_id);
    			}
    			return true;
    		}
    
    
    				const std::string object_name = LLURI::unescape(params[2].asString());
    
    				LLMute mute(avatar_id, object_name, LLMute::OBJECT);
    				LLMuteList::getInstance()->add(mute);
    				LLPanelBlockedList::showPanelAndSelect(mute.mID);
    			}
    			return true;
    		}
    
    
    		if (verb == "unblock")
    		{
    			if (params.size() > 2)
    			{
    				const std::string object_name = params[2].asString();
    				LLMute mute(avatar_id, object_name, LLMute::OBJECT);
    				LLMuteList::getInstance()->remove(mute);
    			}
    			return true;
    		}
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    		return false;
    	}
    };
    LLAgentHandler gAgentHandler;
    
    
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    
    //////////////////////////////////////////////////////////////////////////
    // LLPanelProfileSecondLife
    
    LLPanelProfileSecondLife::LLPanelProfileSecondLife()
     : LLPanelProfileTab()
     , mStatusText(NULL)
     , mAvatarNameCacheConnection()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    LLPanelProfileSecondLife::~LLPanelProfileSecondLife()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        if (getAvatarId().notNull())
        {
            LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
        }
    
        if (LLVoiceClient::instanceExists())
        {
            LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
        }
    
        if (mAvatarNameCacheConnection.connected())
        {
            mAvatarNameCacheConnection.disconnect();
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    BOOL LLPanelProfileSecondLife::postBuild()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        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;
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onOpen(const LLSD& key)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLPanelProfileTab::onOpen(key);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        resetData();
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        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));
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::apply(LLAvatarData* data)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        if (getIsLoaded() && getSelfProfile())
        {
            data->image_id = mSecondLifePic->getImageAssetID();
            data->about_text = mDescriptionEdit->getValue().asString();
            data->allow_publish = mShowInSearchCheckbox->getValue();
    
    Kadah_Coba's avatar
    Kadah_Coba committed
            LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(data);
        }
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::updateData()
    {
        LLUUID avatar_id = getAvatarId();
        if (!getIsLoading() && avatar_id.notNull() && !(getSelfProfile() && !getEmbedded()))
        {
            setIsLoading();
            LLAvatarPropertiesProcessor::getInstance()->sendAvatarGroupsRequest(avatar_id);
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    
        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);
            }
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::resetData()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        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);
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    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);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::processGroupProperties(const LLAvatarGroups* avatar_groups)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        //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);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::openGroupProfile()
    {
        LLUUID group_id = mGroupList->getSelectedUUID();
        LLGroupActions::show(group_id);
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        mAvatarNameCacheConnection.disconnect();
    
        getChild<LLUICtrl>("complete_name")->setValue( av_name.getCompleteName() );
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        //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;
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        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);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        if (getSelfProfile())
        {
            mShowInSearchCheckbox->setValue((BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLTextBox* partner_text = getChild<LLTextBox>("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"));
        }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLStringUtil::format_map_t args;
        args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data);
        args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        std::string caption_text = getString("CaptionTextAcctInfo", args);
        getChild<LLUICtrl>("acc_status_text")->setValue(caption_text);
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onMapButtonClick()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLAvatarActions::showOnMap(getAvatarId());
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::pay()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLAvatarActions::pay(getAvatarId());
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::toggleBlock()
    {
        LLAvatarActions::toggleBlock(getAvatarId());
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        updateButtons();
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onAddFriendButtonClick()
    {
        LLAvatarActions::requestFriendshipDialog(getAvatarId());
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onIMButtonClick()
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        LLAvatarActions::startIM(getAvatarId());
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onTeleportButtonClick()
    {
        LLAvatarActions::offerTeleport(getAvatarId());
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    void LLPanelProfileSecondLife::onGroupInvite()
    {
        LLAvatarActions::inviteToGroup(getAvatarId());
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    // virtual, called by LLAvatarTracker
    void LLPanelProfileSecondLife::changed(U32 mask)
    {
        updateOnlineStatus();
        updateButtons();
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    // virtual, called by LLVoiceClient
    void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal)
    
    Kadah_Coba's avatar
    Kadah_Coba committed
        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);
    }
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    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"));
    
    Kadah_Coba's avatar
    Kadah_Coba committed
    623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
    
    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())
        {