diff --git a/FIRESTORM-FEATURETABLE.txt b/FIRESTORM-FEATURETABLE.txt index 1b35122546..8daefaeb6c 100644 --- a/FIRESTORM-FEATURETABLE.txt +++ b/FIRESTORM-FEATURETABLE.txt @@ -29,3 +29,4 @@ GUI_IMTabConfig LGPL Small_CamControl LGPL Small_MoveControl LGPL Floating_Topbar LGPL +Profile_Floaters LGPL diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e7962facd2..b6360ff14e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -17,8 +17,7 @@ ChatTabDirection Comment - Toggles the direction of chat tabs between horisontal and vertica -l + Toggles the direction of chat tabs between horisontal and vertical Persist 1 Type @@ -9233,7 +9232,18 @@ l Value 0 - ShowScriptErrors + ShowProfileFloaters + + Comment + Shows resident profiles in a floater rather than the side tray + Persist + 1 + Type + Boolean + Value + 1 + + ShowScriptErrors Comment Show script errors diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 066b4d8bc3..67eb940fa6 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -59,7 +59,9 @@ #include "llrecentpeople.h" #include "llsidetray.h" #include "lltrans.h" -#include "llviewerobjectlist.h" +// [SL:KB] - Patch : UI-ProfileGroupFloater | Checked: 2010-09-08 (Catznip-2.1.2c) | Added: Catznip-2.1.2c +#include "llviewercontrol.h" +// [/SL:KB]#include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" #include "llimfloater.h" @@ -302,20 +304,31 @@ void LLAvatarActions::showProfile(const LLUUID& id) { if (id.notNull()) { - LLSD params; - params["id"] = id; - params["open_tab_name"] = "panel_profile"; +// [SL:KB] - Patch : UI-ProfileGroupFloater | + if ( (!gSavedSettings.getBOOL("ShowProfileFloaters")) || ((gAgent.getID() == id)) ) + { +// [/SL:KB] + LLSD params; + params["id"] = id; + params["open_tab_name"] = "panel_profile"; - //Show own profile - if(gAgent.getID() == id) - { - LLSideTray::getInstance()->showPanel("panel_me", params); - } - //Show other user profile - else - { - LLSideTray::getInstance()->showPanel("panel_profile_view", params); - } + //Show own profile + if(gAgent.getID() == id) + { + LLSideTray::getInstance()->showPanel("panel_me", params); + } + //Show other user profile + else + { + LLSideTray::getInstance()->showPanel("panel_profile_view", params); + } +// [SL:KB] - Patch : UI-ProfileGroupFloater + } + else + { + LLFloaterReg::showInstance("floater_profile_view", LLSD().with("id", id)); + } +// [/SL:KB] } } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 57180f63b5..1a1f4c8dfd 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1,863 +1,875 @@ -/** - * @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$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llpanelavatar.h" - -#include "llagent.h" -#include "llavataractions.h" -#include "llavatarconstants.h" // AVATAR_ONLINE -#include "llcallingcard.h" -#include "llcombobox.h" -#include "lldateutil.h" // ageFromDate() -#include "llimview.h" -#include "llnotificationsutil.h" -#include "lltexteditor.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.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 - { - Optional agent_id; - Params() - : agent_id("agent_id") - { - mouse_opaque(false); - 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() -{} - -void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) -{ - llinfos << "LLDropTarget::doDrop()" << llendl; -} - -BOOL LLDropTarget::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); - - return TRUE; - } - - return FALSE; -} - -static LLDefaultChildRegistry::Register r("drop_target"); - -static LLRegisterPanelClassWrapper t_panel_profile("panel_profile"); -static LLRegisterPanelClassWrapper t_panel_my_profile("panel_my_profile"); -static LLRegisterPanelClassWrapper t_panel_notes("panel_notes"); - -//----------------------------------------------------------------------------- -// LLPanelAvatarNotes() -//----------------------------------------------------------------------------- -LLPanelAvatarNotes::LLPanelAvatarNotes() -: LLPanelProfileTab() -{ - -} - -void LLPanelAvatarNotes::updateData() -{ - LLAvatarPropertiesProcessor::getInstance()-> - sendAvatarNotesRequest(getAvatarId()); -} - -BOOL LLPanelAvatarNotes::postBuild() -{ - childSetCommitCallback("status_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); - childSetCommitCallback("map_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); - childSetCommitCallback("objects_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); - - childSetCommitCallback("add_friend", boost::bind(&LLPanelAvatarNotes::onAddFriendButtonClick, this),NULL); - childSetCommitCallback("im", boost::bind(&LLPanelAvatarNotes::onIMButtonClick, this), NULL); - childSetCommitCallback("call", boost::bind(&LLPanelAvatarNotes::onCallButtonClick, this), NULL); - childSetCommitCallback("teleport", boost::bind(&LLPanelAvatarNotes::onTeleportButtonClick, this), NULL); - childSetCommitCallback("share", boost::bind(&LLPanelAvatarNotes::onShareButtonClick, this), NULL); - childSetCommitCallback("show_on_map_btn", (boost::bind( - &LLPanelAvatarNotes::onMapButtonClick, this)), NULL); - - LLTextEditor* te = getChild("notes_edit"); - te->setCommitCallback(boost::bind(&LLPanelAvatarNotes::onCommitNotes,this)); - te->setCommitOnFocusLost(TRUE); - - resetControls(); - resetData(); - - LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); - - return TRUE; -} - -void LLPanelAvatarNotes::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - fillRightsData(); - - //Disable "Add Friend" button for friends. - getChildView("add_friend")->setEnabled(!LLAvatarActions::isFriend(getAvatarId())); -} - -void LLPanelAvatarNotes::fillRightsData() -{ - getChild("status_check")->setValue(FALSE); - getChild("map_check")->setValue(FALSE); - getChild("objects_check")->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(); - - getChild("status_check")->setValue(LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE); - getChild("map_check")->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); - getChild("objects_check")->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); - - } - - enableCheckboxes(NULL != relation); -} - -void LLPanelAvatarNotes::onCommitNotes() -{ - std::string notes = getChild("notes_edit")->getValue().asString(); - LLAvatarPropertiesProcessor::getInstance()-> sendNotes(getAvatarId(),notes); -} - -void LLPanelAvatarNotes::rightsConfirmationCallback(const LLSD& notification, - const LLSD& response, S32 rights) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - LLAvatarPropertiesProcessor::getInstance()->sendFriendRights( - getAvatarId(), rights); - } - else - { - getChild("objects_check")->setValue( - getChild("objects_check")->getValue().asBoolean() ? FALSE : TRUE); - } -} - -void LLPanelAvatarNotes::confirmModifyRights(bool grant, S32 rights) -{ - LLSD args; - args["NAME"] = LLSLURL("agent", getAvatarId(), "displayname").getSLURLString(); - - if (grant) - { - LLNotificationsUtil::add("GrantModifyRights", args, LLSD(), - boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this, - _1, _2, rights)); - } - else - { - LLNotificationsUtil::add("RevokeModifyRights", args, LLSD(), - boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this, - _1, _2, rights)); - } -} - -void LLPanelAvatarNotes::onCommitRights() -{ - const LLRelationship* buddy_relationship = - LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - - if (NULL == buddy_relationship) - { - // Lets have a warning log message instead of having a crash. EXT-4947. - llwarns << "Trying to modify rights for non-friend avatar. Skipped." << llendl; - return; - } - - - S32 rights = 0; - - if(getChild("status_check")->getValue().asBoolean()) - rights |= LLRelationship::GRANT_ONLINE_STATUS; - if(getChild("map_check")->getValue().asBoolean()) - rights |= LLRelationship::GRANT_MAP_LOCATION; - if(getChild("objects_check")->getValue().asBoolean()) - rights |= LLRelationship::GRANT_MODIFY_OBJECTS; - - bool allow_modify_objects = getChild("objects_check")->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 LLPanelAvatarNotes::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_NOTES == type) - { - LLAvatarNotes* avatar_notes = static_cast(data); - if(avatar_notes && getAvatarId() == avatar_notes->target_id) - { - getChild("notes_edit")->setValue(avatar_notes->notes); - getChildView("notes edit")->setEnabled(true); - - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); - } - } -} - -void LLPanelAvatarNotes::resetData() -{ - getChild("notes_edit")->setValue(LLStringUtil::null); - // Default value is TRUE - getChild("status_check")->setValue(TRUE); -} - -void LLPanelAvatarNotes::resetControls() -{ - //Disable "Add Friend" button for friends. - getChildView("add_friend")->setEnabled(TRUE); - - enableCheckboxes(false); -} - -void LLPanelAvatarNotes::onAddFriendButtonClick() -{ - LLAvatarActions::requestFriendshipDialog(getAvatarId()); -} - -void LLPanelAvatarNotes::onIMButtonClick() -{ - LLAvatarActions::startIM(getAvatarId()); -} - -void LLPanelAvatarNotes::onTeleportButtonClick() -{ - LLAvatarActions::offerTeleport(getAvatarId()); -} - -void LLPanelAvatarNotes::onCallButtonClick() -{ - LLAvatarActions::startCall(getAvatarId()); -} - -void LLPanelAvatarNotes::onShareButtonClick() -{ - //*TODO not implemented. -} - -void LLPanelAvatarNotes::enableCheckboxes(bool enable) -{ - getChildView("status_check")->setEnabled(enable); - getChildView("map_check")->setEnabled(enable); - getChildView("objects_check")->setEnabled(enable); -} - -LLPanelAvatarNotes::~LLPanelAvatarNotes() -{ - if(getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); - } - } -} - -// virtual, called by LLAvatarTracker -void LLPanelAvatarNotes::changed(U32 mask) -{ - getChildView("teleport")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); - - // update rights to avoid have checkboxes enabled when friendship is terminated. EXT-4947. - fillRightsData(); -} - -// virtual -void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) - { - return; - } - - getChildView("call")->setEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()); -} - -void LLPanelAvatarNotes::setAvatarId(const LLUUID& id) -{ - if(id.notNull()) - { - if(getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - } - LLPanelProfileTab::setAvatarId(id); - LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelProfileTab::LLPanelProfileTab() -: LLPanel() -, mAvatarId(LLUUID::null) -{ -} - -LLPanelProfileTab::~LLPanelProfileTab() -{ - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); - } -} - -void LLPanelProfileTab::setAvatarId(const LLUUID& id) -{ - if(id.notNull()) - { - if(getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this); - } - mAvatarId = id; - LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this); - } -} - -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(); -} - -void LLPanelProfileTab::scrollToTop() -{ - LLScrollContainer* scrollContainer = findChild("profile_scroll"); - if (scrollContainer) - scrollContainer->goToTop(); -} - -void LLPanelProfileTab::onMapButtonClick() -{ - LLAvatarActions::showOnMap(getAvatarId()); -} - -void LLPanelProfileTab::updateButtons() -{ - 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); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -bool enable_god() -{ - return gAgent.isGodlike(); -} - -LLPanelAvatarProfile::LLPanelAvatarProfile() -: LLPanelProfileTab() -{ -} - -BOOL LLPanelAvatarProfile::postBuild() -{ - childSetCommitCallback("add_friend",(boost::bind(&LLPanelAvatarProfile::onAddFriendButtonClick,this)),NULL); - childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL); - childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL); - childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL); - childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL); - childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL); - childSetCommitCallback("show_on_map_btn", (boost::bind( - &LLPanelAvatarProfile::onMapButtonClick, this)), NULL); - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("Profile.ShowOnMap", boost::bind(&LLPanelAvatarProfile::onMapButtonClick, this)); - registrar.add("Profile.Pay", boost::bind(&LLPanelAvatarProfile::pay, this)); - registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this)); - registrar.add("Profile.BlockUnblock", boost::bind(&LLPanelAvatarProfile::toggleBlock, this)); - registrar.add("Profile.Kick", boost::bind(&LLPanelAvatarProfile::kick, this)); - registrar.add("Profile.Freeze", boost::bind(&LLPanelAvatarProfile::freeze, this)); - registrar.add("Profile.Unfreeze", boost::bind(&LLPanelAvatarProfile::unfreeze, this)); - registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this)); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; - enable.add("Profile.EnableShowOnMap", boost::bind(&LLPanelAvatarProfile::enableShowOnMap, this)); - enable.add("Profile.EnableGod", boost::bind(&enable_god)); - enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this)); - enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this)); - - mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - - LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); - - resetControls(); - resetData(); - - return TRUE; -} - -void LLPanelAvatarProfile::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - mGroups.clear(); - - //Disable "Add Friend" button for friends. - getChildView("add_friend")->setEnabled(!LLAvatarActions::isFriend(getAvatarId())); -} - -void LLPanelAvatarProfile::updateData() -{ - if (getAvatarId().notNull()) - { - LLAvatarPropertiesProcessor::getInstance()-> - sendAvatarPropertiesRequest(getAvatarId()); - LLAvatarPropertiesProcessor::getInstance()-> - sendAvatarGroupsRequest(getAvatarId()); - } -} - -void LLPanelAvatarProfile::resetControls() -{ - getChildView("status_panel")->setVisible( true); - getChildView("profile_buttons_panel")->setVisible( true); - getChildView("title_groups_text")->setVisible( true); - getChildView("sl_groups")->setVisible( true); - getChildView("add_friend")->setEnabled(true); - - getChildView("status_me_panel")->setVisible( false); - getChildView("profile_me_buttons_panel")->setVisible( false); - getChildView("account_actions_panel")->setVisible( false); -} - -void LLPanelAvatarProfile::resetData() -{ - mGroups.clear(); - getChild("2nd_life_pic")->setValue(LLUUID::null); - getChild("real_world_pic")->setValue(LLUUID::null); - getChild("online_status")->setValue(LLStringUtil::null); - getChild("status_message")->setValue(LLStringUtil::null); - getChild("sl_description_edit")->setValue(LLStringUtil::null); - getChild("fl_description_edit")->setValue(LLStringUtil::null); - getChild("sl_groups")->setValue(LLStringUtil::null); - getChild("homepage_edit")->setValue(LLStringUtil::null); - getChild("register_date")->setValue(LLStringUtil::null); - getChild("acc_status_text")->setValue(LLStringUtil::null); - getChild("partner_text")->setValue(LLStringUtil::null); -} - -void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType type) -{ - if(APT_PROPERTIES == type) - { - const LLAvatarData* avatar_data = static_cast(data); - if(avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProfileProperties(avatar_data); - } - } - else if(APT_GROUPS == type) - { - LLAvatarGroups* avatar_groups = static_cast(data); - if(avatar_groups && getAvatarId() == avatar_groups->avatar_id) - { - processGroupProperties(avatar_groups); - } - } -} - -void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_data) -{ - fillCommonData(avatar_data); - - fillPartnerData(avatar_data); - - fillAccountStatus(avatar_data); -} - -void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_groups) -{ - // *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; - } - - // Creating string, containing group list - std::string groups = ""; - for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) - { - if (it != mGroups.begin()) - groups += ", "; - - std::string group_name = LLURI::escape(it->first); - std::string group_url= it->second.notNull() - ? "[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]" - : getString("no_group_text"); - - groups += group_url; - } - - getChild("sl_groups")->setValue(groups); -} - -void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) -{ - //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; - } - args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now()); - std::string register_date = getString("RegisterDateFormat", args); - getChild("register_date")->setValue(register_date ); - getChild("sl_description_edit")->setValue(avatar_data->about_text); - getChild("fl_description_edit")->setValue(avatar_data->fl_about_text); - getChild("2nd_life_pic")->setValue(avatar_data->image_id); - getChild("real_world_pic")->setValue(avatar_data->fl_image_id); - getChild("homepage_edit")->setValue(avatar_data->profile_url); - - // Hide home page textbox if no page was set to fix "homepage URL appears clickable without URL - EXT-4734" - getChildView("homepage_edit")->setVisible( !avatar_data->profile_url.empty()); -} - -void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data) -{ - LLTextBox* partner_text = getChild("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 LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) -{ - LLStringUtil::format_map_t args; - args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); - args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); - // *NOTE: AVATAR_AGEVERIFIED not currently getting set in - // dataserver/lldataavatar.cpp for privacy considerations - args["[AGEVERIFICATION]"] = ""; - std::string caption_text = getString("CaptionTextAcctInfo", args); - getChild("acc_status_text")->setValue(caption_text); -} - -void LLPanelAvatarProfile::pay() -{ - LLAvatarActions::pay(getAvatarId()); -} - -void LLPanelAvatarProfile::share() -{ - LLAvatarActions::share(getAvatarId()); -} - -void LLPanelAvatarProfile::toggleBlock() -{ - LLAvatarActions::toggleBlock(getAvatarId()); -} - -bool LLPanelAvatarProfile::enableShowOnMap() -{ - bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); - - bool enable_map_btn = (is_buddy_online && is_agent_mappable(getAvatarId())) - || gAgent.isGodlike(); - return enable_map_btn; -} - -bool LLPanelAvatarProfile::enableBlock() -{ - return LLAvatarActions::canBlock(getAvatarId()) && !LLAvatarActions::isBlocked(getAvatarId()); -} - -bool LLPanelAvatarProfile::enableUnblock() -{ - return LLAvatarActions::isBlocked(getAvatarId()); -} - -void LLPanelAvatarProfile::kick() -{ - LLAvatarActions::kick(getAvatarId()); -} - -void LLPanelAvatarProfile::freeze() -{ - LLAvatarActions::freeze(getAvatarId()); -} - -void LLPanelAvatarProfile::unfreeze() -{ - LLAvatarActions::unfreeze(getAvatarId()); -} - -void LLPanelAvatarProfile::csr() -{ - std::string name; - gCacheName->getFullName(getAvatarId(), name); - LLAvatarActions::csr(getAvatarId(), name); -} - -void LLPanelAvatarProfile::onAddFriendButtonClick() -{ - LLAvatarActions::requestFriendshipDialog(getAvatarId()); -} - -void LLPanelAvatarProfile::onIMButtonClick() -{ - LLAvatarActions::startIM(getAvatarId()); -} - -void LLPanelAvatarProfile::onTeleportButtonClick() -{ - LLAvatarActions::offerTeleport(getAvatarId()); -} - -void LLPanelAvatarProfile::onCallButtonClick() -{ - LLAvatarActions::startCall(getAvatarId()); -} - -void LLPanelAvatarProfile::onShareButtonClick() -{ - //*TODO not implemented -} - -void LLPanelAvatarProfile::onOverflowButtonClicked() -{ - if (!mProfileMenu->toggleVisibility()) - return; - - LLView* btn = getChild("overflow_btn"); - - if (mProfileMenu->getButtonRect().isEmpty()) - { - mProfileMenu->setButtonRect(btn); - } - mProfileMenu->updateParent(LLMenuGL::sMenuContainer); - - LLRect rect = btn->getRect(); - LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop); -} - -LLPanelAvatarProfile::~LLPanelAvatarProfile() -{ - if(getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); - } - } -} - -// virtual, called by LLAvatarTracker -void LLPanelAvatarProfile::changed(U32 mask) -{ - getChildView("teleport")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); -} - -// virtual -void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) - { - return; - } - - getChildView("call")->setEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()); -} - -void LLPanelAvatarProfile::setAvatarId(const LLUUID& id) -{ - if(id.notNull()) - { - if(getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - } - LLPanelProfileTab::setAvatarId(id); - LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelMyProfile::LLPanelMyProfile() -: LLPanelAvatarProfile() -{ -} - -BOOL LLPanelMyProfile::postBuild() -{ - LLPanelAvatarProfile::postBuild(); - - childSetCommitCallback("status_me_message_text", boost::bind(&LLPanelMyProfile::onStatusMessageChanged, this), NULL); - - resetControls(); - resetData(); - - return TRUE; -} - -void LLPanelMyProfile::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); -} - -void LLPanelMyProfile::processProfileProperties(const LLAvatarData* avatar_data) -{ - fillCommonData(avatar_data); - - fillPartnerData(avatar_data); - - fillAccountStatus(avatar_data); -} - -void LLPanelMyProfile::resetControls() -{ - getChildView("status_panel")->setVisible( false); - getChildView("profile_buttons_panel")->setVisible( false); - getChildView("title_groups_text")->setVisible( false); - getChildView("sl_groups")->setVisible( false); - getChildView("status_me_panel")->setVisible( true); - getChildView("profile_me_buttons_panel")->setVisible( true); -} - - -void LLPanelMyProfile::onStatusMessageChanged() -{ - updateData(); -} +/** + * @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$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llpanelavatar.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llavatarconstants.h" // AVATAR_ONLINE +#include "llcallingcard.h" +#include "llcombobox.h" +#include "lldateutil.h" // ageFromDate() +#include "llimview.h" +#include "llnotificationsutil.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltoggleablemenu.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 + { + Optional agent_id; + Params() + : agent_id("agent_id") + { + mouse_opaque(false); + 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() +{} + +void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) +{ + llinfos << "LLDropTarget::doDrop()" << llendl; +} + +BOOL LLDropTarget::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); + + return TRUE; + } + + return FALSE; +} + +static LLDefaultChildRegistry::Register r("drop_target"); + +static LLRegisterPanelClassWrapper t_panel_profile("panel_profile"); +static LLRegisterPanelClassWrapper t_panel_my_profile("panel_my_profile"); +static LLRegisterPanelClassWrapper t_panel_notes("panel_notes"); + +//----------------------------------------------------------------------------- +// LLPanelAvatarNotes() +//----------------------------------------------------------------------------- +LLPanelAvatarNotes::LLPanelAvatarNotes() +: LLPanelProfileTab() +{ + +} + +void LLPanelAvatarNotes::updateData() +{ + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarNotesRequest(getAvatarId()); +} + +BOOL LLPanelAvatarNotes::postBuild() +{ + childSetCommitCallback("status_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); + childSetCommitCallback("map_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); + childSetCommitCallback("objects_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL); + + childSetCommitCallback("add_friend", boost::bind(&LLPanelAvatarNotes::onAddFriendButtonClick, this),NULL); + childSetCommitCallback("im", boost::bind(&LLPanelAvatarNotes::onIMButtonClick, this), NULL); + childSetCommitCallback("call", boost::bind(&LLPanelAvatarNotes::onCallButtonClick, this), NULL); + childSetCommitCallback("teleport", boost::bind(&LLPanelAvatarNotes::onTeleportButtonClick, this), NULL); + childSetCommitCallback("share", boost::bind(&LLPanelAvatarNotes::onShareButtonClick, this), NULL); + childSetCommitCallback("show_on_map_btn", (boost::bind( + &LLPanelAvatarNotes::onMapButtonClick, this)), NULL); + + LLTextEditor* te = getChild("notes_edit"); + te->setCommitCallback(boost::bind(&LLPanelAvatarNotes::onCommitNotes,this)); + te->setCommitOnFocusLost(TRUE); + + resetControls(); + resetData(); + + LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); + + return TRUE; +} + +void LLPanelAvatarNotes::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + fillRightsData(); + + //Disable "Add Friend" button for friends. + getChildView("add_friend")->setEnabled(!LLAvatarActions::isFriend(getAvatarId())); +} + +void LLPanelAvatarNotes::fillRightsData() +{ + getChild("status_check")->setValue(FALSE); + getChild("map_check")->setValue(FALSE); + getChild("objects_check")->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(); + + getChild("status_check")->setValue(LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE); + getChild("map_check")->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); + getChild("objects_check")->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); + + } + + enableCheckboxes(NULL != relation); +} + +void LLPanelAvatarNotes::onCommitNotes() +{ + std::string notes = getChild("notes_edit")->getValue().asString(); + LLAvatarPropertiesProcessor::getInstance()-> sendNotes(getAvatarId(),notes); +} + +void LLPanelAvatarNotes::rightsConfirmationCallback(const LLSD& notification, + const LLSD& response, S32 rights) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + LLAvatarPropertiesProcessor::getInstance()->sendFriendRights( + getAvatarId(), rights); + } + else + { + getChild("objects_check")->setValue( + getChild("objects_check")->getValue().asBoolean() ? FALSE : TRUE); + } +} + +void LLPanelAvatarNotes::confirmModifyRights(bool grant, S32 rights) +{ + LLSD args; + args["NAME"] = LLSLURL("agent", getAvatarId(), "displayname").getSLURLString(); + + if (grant) + { + LLNotificationsUtil::add("GrantModifyRights", args, LLSD(), + boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this, + _1, _2, rights)); + } + else + { + LLNotificationsUtil::add("RevokeModifyRights", args, LLSD(), + boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this, + _1, _2, rights)); + } +} + +void LLPanelAvatarNotes::onCommitRights() +{ + const LLRelationship* buddy_relationship = + LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + + if (NULL == buddy_relationship) + { + // Lets have a warning log message instead of having a crash. EXT-4947. + llwarns << "Trying to modify rights for non-friend avatar. Skipped." << llendl; + return; + } + + + S32 rights = 0; + + if(getChild("status_check")->getValue().asBoolean()) + rights |= LLRelationship::GRANT_ONLINE_STATUS; + if(getChild("map_check")->getValue().asBoolean()) + rights |= LLRelationship::GRANT_MAP_LOCATION; + if(getChild("objects_check")->getValue().asBoolean()) + rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + + bool allow_modify_objects = getChild("objects_check")->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 LLPanelAvatarNotes::processProperties(void* data, EAvatarProcessorType type) +{ + if(APT_NOTES == type) + { + LLAvatarNotes* avatar_notes = static_cast(data); + if(avatar_notes && getAvatarId() == avatar_notes->target_id) + { + getChild("notes_edit")->setValue(avatar_notes->notes); + getChildView("notes edit")->setEnabled(true); + + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); + } + } +} + +void LLPanelAvatarNotes::resetData() +{ + getChild("notes_edit")->setValue(LLStringUtil::null); + // Default value is TRUE + getChild("status_check")->setValue(TRUE); +} + +void LLPanelAvatarNotes::resetControls() +{ + //Disable "Add Friend" button for friends. + getChildView("add_friend")->setEnabled(TRUE); + + enableCheckboxes(false); +} + +void LLPanelAvatarNotes::onAddFriendButtonClick() +{ + LLAvatarActions::requestFriendshipDialog(getAvatarId()); +} + +void LLPanelAvatarNotes::onIMButtonClick() +{ + LLAvatarActions::startIM(getAvatarId()); +} + +void LLPanelAvatarNotes::onTeleportButtonClick() +{ + LLAvatarActions::offerTeleport(getAvatarId()); +} + +void LLPanelAvatarNotes::onCallButtonClick() +{ + LLAvatarActions::startCall(getAvatarId()); +} + +void LLPanelAvatarNotes::onShareButtonClick() +{ + //*TODO not implemented. +} + +void LLPanelAvatarNotes::enableCheckboxes(bool enable) +{ + getChildView("status_check")->setEnabled(enable); + getChildView("map_check")->setEnabled(enable); + getChildView("objects_check")->setEnabled(enable); +} + +LLPanelAvatarNotes::~LLPanelAvatarNotes() +{ + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + //if(LLVoiceClient::instanceExists()) + //{ + // LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + //} + } +// [SL:KB] - Patch : UI-ProfileGroupFloater + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + } +// [/SL:KB] +} + +// virtual, called by LLAvatarTracker +void LLPanelAvatarNotes::changed(U32 mask) +{ + getChildView("teleport")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); + + // update rights to avoid have checkboxes enabled when friendship is terminated. EXT-4947. + fillRightsData(); +} + +// virtual +void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + getChildView("call")->setEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()); +} + +void LLPanelAvatarNotes::setAvatarId(const LLUUID& id) +{ + if(id.notNull()) + { + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + LLPanelProfileTab::setAvatarId(id); + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileTab::LLPanelProfileTab() +: LLPanel() +, mAvatarId(LLUUID::null) +{ +} + +LLPanelProfileTab::~LLPanelProfileTab() +{ + if(getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); + } +} + +void LLPanelProfileTab::setAvatarId(const LLUUID& id) +{ + if(id.notNull()) + { + if(getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this); + } + mAvatarId = id; + LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this); + } +} + +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(); +} + +void LLPanelProfileTab::scrollToTop() +{ + LLScrollContainer* scrollContainer = findChild("profile_scroll"); + if (scrollContainer) + scrollContainer->goToTop(); +} + +void LLPanelProfileTab::onMapButtonClick() +{ + LLAvatarActions::showOnMap(getAvatarId()); +} + +void LLPanelProfileTab::updateButtons() +{ + 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); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +bool enable_god() +{ + return gAgent.isGodlike(); +} + +LLPanelAvatarProfile::LLPanelAvatarProfile() +: LLPanelProfileTab() +{ +} + +BOOL LLPanelAvatarProfile::postBuild() +{ + childSetCommitCallback("add_friend",(boost::bind(&LLPanelAvatarProfile::onAddFriendButtonClick,this)),NULL); + childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL); + childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL); + childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL); + childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL); + childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL); + childSetCommitCallback("show_on_map_btn", (boost::bind( + &LLPanelAvatarProfile::onMapButtonClick, this)), NULL); + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Profile.ShowOnMap", boost::bind(&LLPanelAvatarProfile::onMapButtonClick, this)); + registrar.add("Profile.Pay", boost::bind(&LLPanelAvatarProfile::pay, this)); + registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this)); + registrar.add("Profile.BlockUnblock", boost::bind(&LLPanelAvatarProfile::toggleBlock, this)); + registrar.add("Profile.Kick", boost::bind(&LLPanelAvatarProfile::kick, this)); + registrar.add("Profile.Freeze", boost::bind(&LLPanelAvatarProfile::freeze, this)); + registrar.add("Profile.Unfreeze", boost::bind(&LLPanelAvatarProfile::unfreeze, this)); + registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this)); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; + enable.add("Profile.EnableShowOnMap", boost::bind(&LLPanelAvatarProfile::enableShowOnMap, this)); + enable.add("Profile.EnableGod", boost::bind(&enable_god)); + enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this)); + enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this)); + + mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + + LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); + + resetControls(); + resetData(); + + return TRUE; +} + +void LLPanelAvatarProfile::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + mGroups.clear(); + + //Disable "Add Friend" button for friends. + getChildView("add_friend")->setEnabled(!LLAvatarActions::isFriend(getAvatarId())); +} + +void LLPanelAvatarProfile::updateData() +{ + if (getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarPropertiesRequest(getAvatarId()); + LLAvatarPropertiesProcessor::getInstance()-> + sendAvatarGroupsRequest(getAvatarId()); + } +} + +void LLPanelAvatarProfile::resetControls() +{ + getChildView("status_panel")->setVisible( true); + getChildView("profile_buttons_panel")->setVisible( true); + getChildView("title_groups_text")->setVisible( true); + getChildView("sl_groups")->setVisible( true); + getChildView("add_friend")->setEnabled(true); + + getChildView("status_me_panel")->setVisible( false); + getChildView("profile_me_buttons_panel")->setVisible( false); + getChildView("account_actions_panel")->setVisible( false); +} + +void LLPanelAvatarProfile::resetData() +{ + mGroups.clear(); + getChild("2nd_life_pic")->setValue(LLUUID::null); + getChild("real_world_pic")->setValue(LLUUID::null); + getChild("online_status")->setValue(LLStringUtil::null); + getChild("status_message")->setValue(LLStringUtil::null); + getChild("sl_description_edit")->setValue(LLStringUtil::null); + getChild("fl_description_edit")->setValue(LLStringUtil::null); + getChild("sl_groups")->setValue(LLStringUtil::null); + getChild("homepage_edit")->setValue(LLStringUtil::null); + getChild("register_date")->setValue(LLStringUtil::null); + getChild("acc_status_text")->setValue(LLStringUtil::null); + getChild("partner_text")->setValue(LLStringUtil::null); +} + +void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType type) +{ + if(APT_PROPERTIES == type) + { + const LLAvatarData* avatar_data = static_cast(data); + if(avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProfileProperties(avatar_data); + } + } + else if(APT_GROUPS == type) + { + LLAvatarGroups* avatar_groups = static_cast(data); + if(avatar_groups && getAvatarId() == avatar_groups->avatar_id) + { + processGroupProperties(avatar_groups); + } + } +} + +void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_data) +{ + fillCommonData(avatar_data); + + fillPartnerData(avatar_data); + + fillAccountStatus(avatar_data); +} + +void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_groups) +{ + // *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; + } + + // Creating string, containing group list + std::string groups = ""; + for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) + { + if (it != mGroups.begin()) + groups += ", "; + + std::string group_name = LLURI::escape(it->first); + std::string group_url= it->second.notNull() + ? "[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]" + : getString("no_group_text"); + + groups += group_url; + } + + getChild("sl_groups")->setValue(groups); +} + +void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) +{ + //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; + } + args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now()); + std::string register_date = getString("RegisterDateFormat", args); + getChild("register_date")->setValue(register_date ); + getChild("sl_description_edit")->setValue(avatar_data->about_text); + getChild("fl_description_edit")->setValue(avatar_data->fl_about_text); + getChild("2nd_life_pic")->setValue(avatar_data->image_id); + getChild("real_world_pic")->setValue(avatar_data->fl_image_id); + getChild("homepage_edit")->setValue(avatar_data->profile_url); + + // Hide home page textbox if no page was set to fix "homepage URL appears clickable without URL - EXT-4734" + getChildView("homepage_edit")->setVisible( !avatar_data->profile_url.empty()); +} + +void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data) +{ + LLTextBox* partner_text = getChild("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 LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) +{ + LLStringUtil::format_map_t args; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + // *NOTE: AVATAR_AGEVERIFIED not currently getting set in + // dataserver/lldataavatar.cpp for privacy considerations + args["[AGEVERIFICATION]"] = ""; + std::string caption_text = getString("CaptionTextAcctInfo", args); + getChild("acc_status_text")->setValue(caption_text); +} + +void LLPanelAvatarProfile::pay() +{ + LLAvatarActions::pay(getAvatarId()); +} + +void LLPanelAvatarProfile::share() +{ + LLAvatarActions::share(getAvatarId()); +} + +void LLPanelAvatarProfile::toggleBlock() +{ + LLAvatarActions::toggleBlock(getAvatarId()); +} + +bool LLPanelAvatarProfile::enableShowOnMap() +{ + bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); + + bool enable_map_btn = (is_buddy_online && is_agent_mappable(getAvatarId())) + || gAgent.isGodlike(); + return enable_map_btn; +} + +bool LLPanelAvatarProfile::enableBlock() +{ + return LLAvatarActions::canBlock(getAvatarId()) && !LLAvatarActions::isBlocked(getAvatarId()); +} + +bool LLPanelAvatarProfile::enableUnblock() +{ + return LLAvatarActions::isBlocked(getAvatarId()); +} + +void LLPanelAvatarProfile::kick() +{ + LLAvatarActions::kick(getAvatarId()); +} + +void LLPanelAvatarProfile::freeze() +{ + LLAvatarActions::freeze(getAvatarId()); +} + +void LLPanelAvatarProfile::unfreeze() +{ + LLAvatarActions::unfreeze(getAvatarId()); +} + +void LLPanelAvatarProfile::csr() +{ + std::string name; + gCacheName->getFullName(getAvatarId(), name); + LLAvatarActions::csr(getAvatarId(), name); +} + +void LLPanelAvatarProfile::onAddFriendButtonClick() +{ + LLAvatarActions::requestFriendshipDialog(getAvatarId()); +} + +void LLPanelAvatarProfile::onIMButtonClick() +{ + LLAvatarActions::startIM(getAvatarId()); +} + +void LLPanelAvatarProfile::onTeleportButtonClick() +{ + LLAvatarActions::offerTeleport(getAvatarId()); +} + +void LLPanelAvatarProfile::onCallButtonClick() +{ + LLAvatarActions::startCall(getAvatarId()); +} + +void LLPanelAvatarProfile::onShareButtonClick() +{ + //*TODO not implemented +} + +void LLPanelAvatarProfile::onOverflowButtonClicked() +{ + if (!mProfileMenu->toggleVisibility()) + return; + + LLView* btn = getChild("overflow_btn"); + + if (mProfileMenu->getButtonRect().isEmpty()) + { + mProfileMenu->setButtonRect(btn); + } + mProfileMenu->updateParent(LLMenuGL::sMenuContainer); + + LLRect rect = btn->getRect(); + LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop); +} + +LLPanelAvatarProfile::~LLPanelAvatarProfile() +{ + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + //if(LLVoiceClient::instanceExists()) + //{ + // LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + //} + } +// [SL:KB] - Patch : UI-ProfileGroupFloater | Checked: 2010-11-26 (Catznip-2.4.0f) | Added: Catznip-2.4.0f + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + } +// [/SL:KB] +} + +// virtual, called by LLAvatarTracker +void LLPanelAvatarProfile::changed(U32 mask) +{ + getChildView("teleport")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); +} + +// virtual +void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + getChildView("call")->setEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking()); +} + +void LLPanelAvatarProfile::setAvatarId(const LLUUID& id) +{ + if(id.notNull()) + { + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + LLPanelProfileTab::setAvatarId(id); + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelMyProfile::LLPanelMyProfile() +: LLPanelAvatarProfile() +{ +} + +BOOL LLPanelMyProfile::postBuild() +{ + LLPanelAvatarProfile::postBuild(); + + childSetCommitCallback("status_me_message_text", boost::bind(&LLPanelMyProfile::onStatusMessageChanged, this), NULL); + + resetControls(); + resetData(); + + return TRUE; +} + +void LLPanelMyProfile::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); +} + +void LLPanelMyProfile::processProfileProperties(const LLAvatarData* avatar_data) +{ + fillCommonData(avatar_data); + + fillPartnerData(avatar_data); + + fillAccountStatus(avatar_data); +} + +void LLPanelMyProfile::resetControls() +{ + getChildView("status_panel")->setVisible( false); + getChildView("profile_buttons_panel")->setVisible( false); + getChildView("title_groups_text")->setVisible( false); + getChildView("sl_groups")->setVisible( false); + getChildView("status_me_panel")->setVisible( true); + getChildView("profile_me_buttons_panel")->setVisible( true); +} + + +void LLPanelMyProfile::onStatusMessageChanged() +{ + updateData(); +} diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index 7635aedf58..0b7a5695b3 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -35,6 +35,9 @@ #include "llavatarpropertiesprocessor.h" #include "llcallingcard.h" +// [SL:KB] - Patch : UI-ProfileGroupFloater +#include "llfloater.h" +// [/SL:KB] #include "llpanelavatar.h" #include "llpanelpicks.h" #include "llpanelprofile.h" @@ -129,8 +132,37 @@ BOOL LLPanelProfileView::postBuild() mStatusText = getChild("status"); mStatusText->setVisible(false); - childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL); +// childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL); childSetCommitCallback("copy_to_clipboard",boost::bind(&LLPanelProfileView::onCopyToClipboard,this),NULL); +// [SL:KB] - Patch : UI-ProfileGroupFloater + LLFloater* pParentView = dynamic_cast(getParent()); + if (!pParentView) + { + childSetCommitCallback("back", boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL); + } + else + { + pParentView->setTitle(getLabel()); + childSetVisible("back", false); + // -TT - we might want to remove this. Maybe. + // HACK-Catznip: we got rid of the back button so we want to line up the name controls with the rest + LLUICtrl* pCtrls[] = + { + getChild("user_name", FALSE), + getChild("display_name_label", FALSE), + getChild("solo_username_label", FALSE), + getChild("user_name_small", FALSE), + getChild("user_label", FALSE), + getChild("user_slid", FALSE) + }; + int dX = (NULL != pCtrls[0]) ? 10 - pCtrls[0]->getRect().mLeft : 0; + for (int idxCtrl = 0; idxCtrl < sizeof(pCtrls) / sizeof(LLUICtrl*); idxCtrl++) + { + if (pCtrls[idxCtrl]) + pCtrls[idxCtrl]->translate(dX, 0); + } + } +// [/SL:KB] return TRUE; } @@ -242,6 +274,11 @@ void LLPanelProfileView::onAvatarNameCache(const LLUUID& agent_id, getChild("copy_to_clipboard")->setEnabled( false ); getChild("solo_username_label")->setVisible( true ); } +// [SL:KB] - Patch : UI-ProfileGroupFloater + LLFloater* pParentView = dynamic_cast(getParent()); + if (pParentView) + pParentView->setTitle(av_name.getCompleteName() + " - " + getLabel()); +// [/SL:KB] } // EOF diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h index c6d921fdc4..9a7ed73aab 100644 --- a/indra/newview/llpanelprofileview.h +++ b/indra/newview/llpanelprofileview.h @@ -32,6 +32,9 @@ #include "llavatarpropertiesprocessor.h" #include "llagent.h" #include "lltooldraganddrop.h" +// [SL:KB] - Patch : UI-ProfileGroupFloater | Checked: 2010-09-08 (Catznip-2.1.2c) | Added: Catznip-2.1.2c +#include "llfloater.h" +// [/SL:KB] class LLAvatarName; class LLPanelProfile; @@ -64,8 +67,11 @@ public: void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) { - LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), gAgent.getSessionID(), drop, - cargo_type, cargo_data, accept); +// LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), gAgent.getSessionID(), drop, +// cargo_type, cargo_data, accept); +// [SL:KB] - Patch : UI-ProfileGroupFloater + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), LLUUID::null, drop, cargo_type, cargo_data, accept); +// [/SL:KB] return TRUE; } @@ -105,4 +111,20 @@ private: AvatarStatusObserver* mAvatarStatusObserver; }; +// [SL:KB] - Patch : UI-ProfileGroupFloater +class LLFloaterProfileView : public LLFloater +{ +public: + LLFloaterProfileView(const LLSD& seed) : LLFloater(seed) {} + ~LLFloaterProfileView() {} + + void onOpen(const LLSD& key) + { + LLPanel* panel = findChild("panel_profile_view"); + if(panel) + panel->onOpen(key); + } + +}; +// [/SL:KB] #endif //LL_LLPANELPROFILEVIEW_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4b4945176a..a443e6f752 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -112,6 +112,9 @@ #include "llnearbychat.h" #include "llpanelblockedlist.h" #include "llpanelclassified.h" +// [SL:KB] - Patch : UI-ProfileGroupFloater +#include "llpanelprofileview.h" +// [/SL:KB] #include "llpreviewanim.h" #include "llpreviewgesture.h" #include "llpreviewnotecard.h" @@ -158,7 +161,10 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("env_windlight", "floater_windlight_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - + +// [SL:KB] - Patch : UI-ProfileGroupFloater | Checked: 2010-09-08 (Catznip-2.1.2c) | Added: Catznip-2.1.2c + LLFloaterReg::add("floater_profile_view", "floater_profile_view.xml",&LLFloaterReg::build); +// [/SL:KB] LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_profile_view.xml b/indra/newview/skins/default/xui/en/floater_profile_view.xml new file mode 100644 index 0000000000..bb7c10003f --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile_view.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index 97229c413c..d08d560e3b 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -6,6 +6,7 @@ layout="topleft" min_height="350" name="panel_target_profile" + label="Profile View" left="0" width="333">